code

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 3, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package toolcode provides the code-mode orchestration layer for executing constrained code snippets with access to metatool helper functions.

toolcode sits on top of toolindex, tooldocs, and toolrun to provide a unified interface for discovering, documenting, and executing tools from within code snippets. It maintains MCP protocol alignment (version 2025-11-25).

Architecture

The package defines three main interfaces:

  • Tools: The metatool environment exposed to code snippets, providing SearchTools, ListNamespaces, DescribeTool, ListToolExamples, RunTool, RunChain, and Println functions.

  • Engine: The pluggable code execution engine that runs snippets with access to the Tools environment.

  • Executor: The main entry point that orchestrates execution, applying defaults, enforcing limits, and collecting results.

Execution Limits

The executor enforces two types of limits:

Tool Call Tracing

Every tool invocation is recorded in a ToolCallRecord containing:

  • ToolID: The canonical tool identifier
  • Args: The arguments passed to the tool
  • Structured: The structured result from successful execution
  • BackendKind: The backend that executed the tool (mcp, provider, local)
  • Error/ErrorOp: Error information if the call failed
  • DurationMs: Execution time in milliseconds

Result Convention

Code snippets should assign their final result to the `__out` variable. The Engine is responsible for extracting this value and returning it in ExecuteResult.Value.

Example (Errors)
package main

import (
	"fmt"

	"github.com/jonwraymond/toolexec/code"
)

func main() {
	// code.ErrConfiguration is returned when Config is invalid
	fmt.Printf("ErrConfiguration: %v\n", code.ErrConfiguration)
	// code.ErrLimitExceeded is returned when limits are hit
	fmt.Printf("ErrLimitExceeded: %v\n", code.ErrLimitExceeded)
}
Output:

ErrConfiguration: configuration error
ErrLimitExceeded: limit exceeded
Example (ExecuteParams)
package main

import (
	"fmt"
	"time"

	"github.com/jonwraymond/toolexec/code"
)

func main() {
	params := code.ExecuteParams{
		Language:     "go",
		Code:         `tools.RunTool(ctx, "math:add", map[string]any{"a": 1, "b": 2})`,
		Timeout:      10 * time.Second,
		MaxToolCalls: 5,
	}

	fmt.Printf("Language: %s\n", params.Language)
	fmt.Printf("Timeout: %v\n", params.Timeout)
	fmt.Printf("MaxToolCalls: %d\n", params.MaxToolCalls)
}
Output:

Language: go
Timeout: 10s
MaxToolCalls: 5
Example (ExecuteResult)
package main

import (
	"fmt"

	"github.com/jonwraymond/toolexec/code"
)

func main() {
	result := code.ExecuteResult{
		Value:      42,
		DurationMs: 150,
		ToolCalls: []code.ToolCallRecord{
			{
				ToolID:      "math:add",
				Args:        map[string]any{"a": 1, "b": 2},
				Structured:  3,
				DurationMs:  5,
				BackendKind: "local",
			},
		},
		Stdout: "Debug output\n",
	}

	fmt.Printf("Value: %v\n", result.Value)
	fmt.Printf("Duration: %dms\n", result.DurationMs)
	fmt.Printf("Tool calls: %d\n", len(result.ToolCalls))
	fmt.Printf("First tool: %s\n", result.ToolCalls[0].ToolID)
}
Output:

Value: 42
Duration: 150ms
Tool calls: 1
First tool: math:add
Example (ToolCallRecord)
package main

import (
	"fmt"

	"github.com/jonwraymond/toolexec/code"
)

func main() {
	record := code.ToolCallRecord{
		ToolID:      "text:format",
		Args:        map[string]any{"text": "hello", "style": "upper"},
		Structured:  "HELLO",
		DurationMs:  3,
		BackendKind: "local",
	}

	fmt.Printf("Tool: %s\n", record.ToolID)
	fmt.Printf("Duration: %dms\n", record.DurationMs)
	fmt.Printf("Result: %v\n", record.Structured)
	fmt.Printf("Backend: %s\n", record.BackendKind)
}
Output:

Tool: text:format
Duration: 3ms
Result: HELLO
Backend: local

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrCodeExecution indicates an error during code snippet execution,
	// such as syntax errors or runtime exceptions in the snippet.
	ErrCodeExecution = errors.New("code execution error")

	// ErrConfiguration indicates an invalid or incomplete configuration.
	ErrConfiguration = errors.New("configuration error")

	// ErrLimitExceeded indicates that an execution limit was reached,
	// such as timeout or maximum tool calls.
	ErrLimitExceeded = errors.New("limit exceeded")
)

Sentinel errors for error classification.

Functions

This section is empty.

Types

type CodeError

type CodeError struct {
	// Message describes the error.
	Message string

	// Line is the 1-based line number where the error occurred.
	// Zero indicates the line is unknown.
	Line int

	// Column is the 1-based column number where the error occurred.
	// Zero indicates the column is unknown.
	Column int

	// Err is the underlying error, if any.
	Err error
}

CodeError represents an error that occurred during code snippet execution. It includes optional source location information for debugging.

func (*CodeError) Error

func (e *CodeError) Error() string

Error returns the error message, including line and column if available.

func (*CodeError) Is

func (e *CodeError) Is(target error) bool

Is reports whether this error matches the target. CodeError matches ErrCodeExecution to allow sentinel-style error checking.

func (*CodeError) Unwrap

func (e *CodeError) Unwrap() error

Unwrap returns the underlying error for use with errors.Is and errors.As.

type Config

type Config struct {
	// Index provides tool discovery and lookup capabilities.
	// Required.
	Index index.Index

	// Docs provides tool documentation.
	// Required.
	Docs tooldoc.Store

	// Run provides tool execution capabilities.
	// Required.
	Run run.Runner

	// Engine is the pluggable code execution engine.
	// Required.
	Engine Engine

	// DefaultTimeout is the default execution timeout when not specified
	// in ExecuteParams. If zero, no default timeout is applied.
	DefaultTimeout time.Duration

	// DefaultLanguage is the default language when not specified in
	// ExecuteParams. Defaults to "go" if empty.
	DefaultLanguage string

	// MaxToolCalls limits the maximum number of tool invocations per
	// execution. Zero means unlimited.
	MaxToolCalls int

	// MaxChainSteps limits the maximum number of steps allowed in a single
	// RunChain call. Zero means unlimited.
	MaxChainSteps int

	// Logger is an optional logger for observability.
	Logger Logger
}

Config holds the configuration for a code executor.

func (*Config) Validate

func (c *Config) Validate() error

Validate checks that all required fields are set. Returns ErrConfiguration if any required field is missing.

type DefaultExecutor

type DefaultExecutor struct {
	// contains filtered or unexported fields
}

DefaultExecutor is the standard implementation of Executor.

func NewDefaultExecutor

func NewDefaultExecutor(cfg Config) (*DefaultExecutor, error)

NewDefaultExecutor creates a new DefaultExecutor with the given configuration. Returns ErrConfiguration if any required field is missing.

func (*DefaultExecutor) ExecuteCode

func (e *DefaultExecutor) ExecuteCode(ctx context.Context, params ExecuteParams) (ExecuteResult, error)

ExecuteCode runs a code snippet with the given parameters.

type Engine

type Engine interface {
	// Execute runs a code snippet with access to the tools environment.
	// It returns the execution result including the final value, output,
	// and any errors encountered.
	Execute(ctx context.Context, params ExecuteParams, tools Tools) (ExecuteResult, error)
}

Engine is the pluggable code execution engine that runs code snippets with access to the Tools environment. Implementations are responsible for parsing and executing the code in the specified language.

The Engine should:

  • Execute the code with access to the provided Tools
  • Capture the final result (typically via __out variable convention)
  • Return any stdout/stderr captured during execution
  • Wrap execution errors in CodeError with line/column info when available

Contract: - Concurrency: implementations must be safe for concurrent use. - Context: must honor cancellation/deadlines and return ctx.Err() when canceled. - Errors: execution failures should return CodeError where possible; callers use errors.Is. - Ownership: params and Tools are read-only; returned ExecuteResult is caller-owned.

type ExecuteParams

type ExecuteParams struct {
	// Language specifies the programming language of the code snippet.
	// If empty, the executor's default language is used.
	Language string `json:"language"`

	// Code is the source code to execute.
	Code string `json:"code"`

	// Timeout specifies the maximum duration for execution.
	// If zero, the executor's default timeout is used.
	Timeout time.Duration `json:"timeout"`

	// MaxToolCalls limits the number of tool invocations allowed.
	// If zero, the executor's configured limit applies (or unlimited if none).
	MaxToolCalls int `json:"maxToolCalls,omitempty"`
}

ExecuteParams specifies the parameters for executing a code snippet.

type ExecuteResult

type ExecuteResult struct {
	// Value is the final result of the code execution, typically from the
	// __out variable convention.
	Value any `json:"value,omitempty"`

	// Stdout contains any output written via Println or similar.
	Stdout string `json:"stdout,omitempty"`

	// Stderr contains any error output from the execution.
	Stderr string `json:"stderr,omitempty"`

	// ToolCalls records all tool invocations made during execution.
	ToolCalls []ToolCallRecord `json:"toolCalls,omitempty"`

	// DurationMs is the total execution time in milliseconds.
	DurationMs int64 `json:"durationMs"`
}

ExecuteResult contains the outcome of executing a code snippet.

type Executor

type Executor interface {
	// ExecuteCode runs a code snippet with the given parameters.
	// It applies configuration defaults, enforces limits, and collects
	// tool call traces and output.
	ExecuteCode(ctx context.Context, params ExecuteParams) (ExecuteResult, error)
}

Executor is the main entry point for executing code snippets. It orchestrates configuration, limits, and result collection.

Contract: - Concurrency: implementations must be safe for concurrent use. - Context: must honor cancellation/deadlines; deadline exceeded is wrapped with ErrLimitExceeded. - Errors: configuration failures return ErrConfiguration; execution failures propagate. - Ownership: params are read-only; returned ExecuteResult is caller-owned.

type Logger

type Logger interface {
	// Logf logs a formatted message.
	Logf(format string, args ...any)
}

Logger is an optional interface for observability during code execution. Implementations can log tool calls, timing information, and other events.

Contract: - Concurrency: implementations must be safe for concurrent use. - Errors: logging must be best-effort; Logf should not panic. - Ownership: format/args are read-only.

type ToolCallRecord

type ToolCallRecord struct {
	// ToolID is the canonical identifier of the tool that was called.
	ToolID string `json:"toolId"`

	// Args contains the arguments passed to the tool.
	Args map[string]any `json:"args,omitempty"`

	// Structured contains the structured result from a successful tool execution.
	Structured any `json:"structured,omitempty"`

	// BackendKind indicates which backend executed the tool (mcp, provider, local).
	BackendKind string `json:"backendKind,omitempty"`

	// Error contains the error message if the tool call failed.
	Error string `json:"error,omitempty"`

	// ErrorOp indicates the operation that failed (e.g., "run", "chain").
	ErrorOp string `json:"errorOp,omitempty"`

	// DurationMs is the execution time in milliseconds.
	DurationMs int64 `json:"durationMs"`
}

ToolCallRecord captures information about a single tool invocation during code execution. It records the tool identifier, arguments, result, and timing information for observability and debugging.

type Tools

type Tools interface {
	// SearchTools searches for tools matching the query, returning up to limit results.
	SearchTools(ctx context.Context, query string, limit int) ([]index.Summary, error)

	// ListNamespaces returns all available tool namespaces.
	ListNamespaces(ctx context.Context) ([]string, error)

	// DescribeTool returns documentation for a tool at the specified detail level.
	DescribeTool(ctx context.Context, id string, level tooldoc.DetailLevel) (tooldoc.ToolDoc, error)

	// ListToolExamples returns up to maxExamples usage examples for a tool.
	ListToolExamples(ctx context.Context, id string, maxExamples int) ([]tooldoc.ToolExample, error)

	// RunTool executes a single tool and returns the result.
	// Each call is recorded in the tool call trace.
	RunTool(ctx context.Context, id string, args map[string]any) (run.RunResult, error)

	// RunChain executes a sequence of tool calls, where each step can
	// optionally use the previous step's result via UsePrevious.
	// Each step is recorded in the tool call trace.
	RunChain(ctx context.Context, steps []run.ChainStep) (run.RunResult, []run.StepResult, error)

	// Println writes output to the captured stdout buffer.
	Println(args ...any)
}

Tools is the metatool environment exposed to code snippets during execution. It provides functions for discovering, documenting, and executing tools.

Contract: - Concurrency: implementations must be safe for concurrent use. - Context: methods must honor cancellation/deadlines and return ctx.Err() when canceled. - Errors: execution failures propagate underlying errors (e.g., ErrLimitExceeded). - Ownership: args are read-only; returned slices/results are caller-owned snapshots. - Nil/zero: empty IDs return ErrNotFound/ErrInvalidToolID downstream; nil args treated as empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL