107 lines
2.3 KiB
Ruby
107 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "mini_racer"
|
|
require "json"
|
|
|
|
module DiscourseAi
|
|
module AiBot
|
|
module Tools
|
|
class JavascriptEvaluator < Tool
|
|
TIMEOUT = 500
|
|
MAX_MEMORY = 10_000_000
|
|
MARSHAL_STACK_DEPTH = 20
|
|
|
|
def self.signature
|
|
{
|
|
name: name,
|
|
description: "Evaluates JavaScript code using MiniRacer",
|
|
parameters: [
|
|
{
|
|
name: "script",
|
|
description: "The JavaScript code to evaluate",
|
|
type: "string",
|
|
required: true,
|
|
},
|
|
],
|
|
}
|
|
end
|
|
|
|
def self.name
|
|
"javascript_evaluator"
|
|
end
|
|
|
|
def script
|
|
parameters[:script].to_s
|
|
end
|
|
|
|
def timeout
|
|
@timeout || TIMEOUT
|
|
end
|
|
|
|
def timeout=(value)
|
|
@timeout = value
|
|
end
|
|
|
|
def max_memory
|
|
@max_memory || MAX_MEMORY
|
|
end
|
|
|
|
def max_memory=(value)
|
|
@max_memory = value
|
|
end
|
|
|
|
def invoke
|
|
context =
|
|
MiniRacer::Context.new(
|
|
timeout: timeout,
|
|
max_memory: MAX_MEMORY,
|
|
marshal_stack_depth: MARSHAL_STACK_DEPTH,
|
|
)
|
|
|
|
# works around llms like anthropic loving console.log
|
|
eval_script = <<~JS
|
|
let console = {};
|
|
console.log = function(val) {
|
|
return val;
|
|
};
|
|
|
|
#{script}
|
|
JS
|
|
|
|
result = context.eval(eval_script)
|
|
|
|
# only do special handling and truncating for long strings
|
|
if result.to_s.length > 1000
|
|
result = truncate(result.to_s, max_length: 10_000, percent_length: 0.3, llm: llm)
|
|
end
|
|
|
|
{ result: result }
|
|
rescue MiniRacer::ScriptTerminatedError => e
|
|
{ error: "JavaScript execution timed out: #{e.message}" }
|
|
rescue MiniRacer::V8OutOfMemoryError => e
|
|
{ error: "JavaScript execution exceeded memory limit: #{e.message}" }
|
|
rescue MiniRacer::Error => e
|
|
{ error: "JavaScript execution error: #{e.message}" }
|
|
end
|
|
|
|
def details
|
|
<<~MD
|
|
|
|
|
|
```
|
|
#{script}
|
|
```
|
|
|
|
MD
|
|
end
|
|
|
|
private
|
|
|
|
def description_args
|
|
{ script: script }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|