Pure Go JavaScript/TypeScript execution engine using goja + esbuild. Provides sandboxed code execution with a call() bridge for agent actions, automatic TypeScript detection and transpilation, timeout enforcement, max-calls limits, and a concurrent execution pool. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
68 lines
1.9 KiB
Go
68 lines
1.9 KiB
Go
package jsruntime
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// ToolCaller is implemented by the action registry to bridge call() invocations
|
|
// from JavaScript code to the host application.
|
|
type ToolCaller interface {
|
|
Call(ctx context.Context, actionName string, args map[string]any) (any, error)
|
|
}
|
|
|
|
// ExecuteOptions configures a single code execution.
|
|
type ExecuteOptions struct {
|
|
Timeout time.Duration // Maximum execution time. Default 120s.
|
|
MaxCalls int // Maximum number of call() invocations. Default 50.
|
|
MaxMemoryMB int // Memory limit hint in MB. Default 128.
|
|
}
|
|
|
|
// defaults fills in zero-value fields with sensible defaults.
|
|
func (o ExecuteOptions) defaults() ExecuteOptions {
|
|
if o.Timeout <= 0 {
|
|
o.Timeout = 120 * time.Second
|
|
}
|
|
if o.MaxCalls <= 0 {
|
|
o.MaxCalls = 50
|
|
}
|
|
if o.MaxMemoryMB <= 0 {
|
|
o.MaxMemoryMB = 128
|
|
}
|
|
return o
|
|
}
|
|
|
|
// ExecuteResult holds the output of a successful execution.
|
|
type ExecuteResult struct {
|
|
Value any // Final expression value (JSON-serializable)
|
|
CallCount int // Number of call() invocations made
|
|
Duration time.Duration // Wall-clock execution time
|
|
}
|
|
|
|
// ExecError wraps execution errors with structured context.
|
|
type ExecError struct {
|
|
Code string // SYNTAX_ERROR, RUNTIME_ERROR, TIMEOUT, MAX_CALLS_EXCEEDED, TRANSPILE_ERROR
|
|
Message string // Human-readable error description
|
|
Stack string // JS stack trace if available
|
|
Line int // Source line if available
|
|
Column int // Source column if available
|
|
}
|
|
|
|
// Error implements the error interface.
|
|
func (e *ExecError) Error() string {
|
|
if e.Stack != "" {
|
|
return fmt.Sprintf("%s: %s\n%s", e.Code, e.Message, e.Stack)
|
|
}
|
|
return fmt.Sprintf("%s: %s", e.Code, e.Message)
|
|
}
|
|
|
|
// Error code constants.
|
|
const (
|
|
CodeSyntaxError = "SYNTAX_ERROR"
|
|
CodeRuntimeError = "RUNTIME_ERROR"
|
|
CodeTimeout = "TIMEOUT"
|
|
CodeMaxCallsExceeded = "MAX_CALLS_EXCEEDED"
|
|
CodeTranspileError = "TRANSPILE_ERROR"
|
|
)
|