Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5675c48
chore(go.mod): run go mod tidy
spachava753 Nov 27, 2025
73f836a
doc(specs): add Code Mode specification
spachava753 Nov 28, 2025
aa0cce6
docs(specs): refine code mode spec with execution details and error h…
spachava753 Nov 28, 2025
3995900
docs(specs): fix typos and syntax errors in code_mode.md
spachava753 Nov 28, 2025
d759bbd
doc(specs): restructure code mode spec and add multimedia content han…
spachava753 Nov 28, 2025
08a0ff6
doc(specs): change code mode to use separate file instead of inlining
spachava753 Nov 28, 2025
5e69b24
doc(spec): add advanced example to code mode spec
spachava753 Nov 28, 2025
13c8a3a
docs(specs): add execution timeout to code mode and improve tool call…
spachava753 Nov 28, 2025
6704b50
docs(specs): refine code mode spec with implementation clarity
spachava753 Nov 28, 2025
5251182
docs(specs): clarify code mode config uses override behavior instead …
spachava753 Nov 28, 2025
752ac2d
docs(specs): add implementation task breakdown for code mode
spachava753 Nov 28, 2025
fc037f6
feat(config): add code mode configuration types and resolution
spachava753 Nov 28, 2025
59f2ab3
feat(codemode): implement JSON Schema to Go type converter
spachava753 Nov 29, 2025
1bd5b21
feat(codemode): implement tool name collision detection
spachava753 Nov 29, 2025
470fc2d
feat(codemode): generate Go function signatures and type definitions …
spachava753 Nov 29, 2025
f492725
docs(specs): mark Task 4 complete
spachava753 Nov 29, 2025
f0377d4
feat(codemode): generate main.go template with MCP client setup
spachava753 Nov 29, 2025
32c81ff
feat(codemode): generate execute_go_code tool description
spachava753 Nov 29, 2025
bf6006d
feat(codemode): implement code execution sandbox
spachava753 Nov 29, 2025
089f48b
feat(codemode): implement execution timeout and signal handling
spachava753 Nov 29, 2025
c4b7e24
feat(codemode): implement error classification and handling
spachava753 Nov 29, 2025
56c6368
docs(specs): add timeout/kill error handling and fix typo
spachava753 Nov 29, 2025
ed131cc
feat(codemode): implement execute_go_code tool callback
spachava753 Nov 29, 2025
a572df2
feat(codemode): integrate code mode into CreateToolCapableGenerator
spachava753 Nov 30, 2025
c52d0e7
feat(codemode): render execute_go_code tool calls as Go code blocks
spachava753 Nov 30, 2025
6cec409
fix(codemode): use string type for tools without output schemas
spachava753 Nov 30, 2025
cb99861
fix(codemode): use pointers for optional struct fields to distinguish…
spachava753 Nov 30, 2025
2424b97
docs(specs): update code mode spec to reflect pointer-based optional …
spachava753 Nov 30, 2025
1c5d1ef
fix(codemode): register execute_go_code tool even without MCP servers
spachava753 Nov 30, 2025
b4fe61d
chore(schema): add CodeModeConfig to JSON schema
spachava753 Nov 30, 2025
51ce06f
docs: add code mode documentation to AGENTS.md and README.md
spachava753 Nov 30, 2025
980f9f6
docs(agent): rewrite system prompt with expanded guidance for code mo…
spachava753 Nov 30, 2025
7f89665
test(codemode): add token usage comparison tests demonstrating code m…
spachava753 Dec 1, 2025
dc644d6
docs(agent): refine code mode instructions for standard library prefe…
spachava753 Dec 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
!/.gitignore

!*.go
!*.go.tmpl
!go.sum
!go.mod
!go.work
Expand Down
34 changes: 34 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Key capabilities:
- `internal/`: Hosts all of the actual business logic and utilities
-
`agent/`: Package that hosts generator adapters, streaming/printing, thinking filter, system prompt generation, and agent creation to execute a user query
- `codemode/`: Package that hosts code mode implementation - schema to Go type conversion, tool collision detection, code execution sandbox, and execute_go_code tool
- `config/`: Package that hosts configuration loading, validation, parameter merging, and config specific types
- `mcp/`: Package that hosts MCP config validation and client, as well as code for connecting to MPC servers
- `storage/`: Package that hosts SQLite-backed conversation storage (.cpeconvo) and related persistence code
Expand Down Expand Up @@ -52,6 +53,12 @@ Run (typical dev):
# New conversation or continue specific one
./cpe --config ./examples/cpe.yaml -m sonnet -n "Start fresh"
./cpe --config ./examples/cpe.yaml -m sonnet -c <message_id> "Continue"

# Enable code mode (composes MCP tools as Go functions)
./cpe --config ./examples/cpe.yaml -m sonnet "Your prompt" # If codeMode.enabled=true in config

# Disable code mode for a specific invocation (if enabled by default)
# Note: currently requires config change, no CLI flag exists
```

Model utilities:
Expand Down Expand Up @@ -103,6 +110,7 @@ go generate ./internal/config/
- Preference: Use table-driven tests
- Share common setup/validation logic through helper functions or validation callbacks
- Name test cases descriptively in the `name` field
- **Use exact matching for test assertions**: Always compare expected vs actual output exactly. Do not use `strings.Contains` or partial matching for output verification; use full expected strings in `want` fields
- Prefer httptest for HTTP; avoid real network calls
- Keep tests deterministic; use short timeouts; avoid sleeping where possible
- Isolate filesystem effects; clean up temp files; do not depend on developer-local state
Expand All @@ -113,6 +121,32 @@ go generate ./internal/config/

CPE is a CLI tool and MCP client where execution time is dominated by network calls to AI model APIs. Performance optimizations are typically not a concern unless specifically requested by the user. Focus on correctness, maintainability, and user experience over micro-optimizations.

## Code Mode

Code mode allows LLMs to execute Go code to interact with MCP tools, providing:
- **Composability**: Chain multiple tool calls in a single execution
- **Control flow**: Use loops, conditionals, and error handling
- **Efficiency**: Reduce round-trips between LLM and tools
- **Standard library access**: File I/O, HTTP requests, data processing

Configuration:
```yaml
defaults:
codeMode:
enabled: true
excludedTools:
- some_tool # Expose as regular tool instead
```

The LLM generates complete Go programs implementing a `Run(ctx context.Context) error` function. CPE compiles and executes them in a temporary sandbox with access to MCP tools as strongly-typed Go functions.

Implementation notes:
- Tool schemas are converted to Go structs using `internal/codemode/schema.go`
- Generated programs run with `go run` in `/tmp/cpe-tmp-*` directories
- Execution timeout enforced via SIGINT→SIGKILL with 5s grace period
- Exit codes: 0=success, 1=recoverable error, 2=panic (recoverable), 3=fatal error
- Non-streaming printer renders generated code as syntax-highlighted Go blocks

## Documentation for Go Symbols

When gathering context about symbols like types, global variables, constants, functions and methods, prefer to use
Expand Down
90 changes: 90 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ conversations.
- OpenAI models (GPT-4o, GPT-4o Mini, etc.)
- Anthropic Claude models (Claude 3.5 Sonnet, Claude 3 Opus, etc.)
- Google Gemini models (Gemini 1.5 Pro, Gemini 1.5 Flash, etc.)
- **Code Mode**: Enable LLMs to generate and execute Go code for complex tool compositions, control flow, and multi-step operations in a single turn
- **Conversation management**: Save, list, view, and continue previous conversations
- **Model Context Protocol (MCP)**: Connect to external MCP servers for enhanced functionality

Expand Down Expand Up @@ -386,6 +387,10 @@ defaults:
model: "sonnet"
systemPromptPath: "./custom-prompt.txt"
timeout: "5m"
codeMode:
enabled: true
excludedTools:
- multimedia_tool
generationParams:
temperature: 0.7
maxTokens: 4096
Expand Down Expand Up @@ -561,6 +566,91 @@ This allows you to create contextual system prompts that adapt to the current en

Model Context Protocol (MCP) servers are configured in the unified configuration file under the `mcpServers` section. See the [Configuration](#configuration) section above for details on configuring MCP servers in your `cpe.yaml` file.

### Code Mode

Code Mode is an advanced feature that allows LLMs to generate and execute Go code to interact with MCP tools. Instead of making discrete tool calls, the LLM writes complete Go programs that can:

- **Compose multiple tools** in a single execution without round-trips
- **Use control flow** like loops and conditionals for complex logic
- **Process data** using Go's standard library (file I/O, JSON, strings, etc.)
- **Handle errors** with proper Go error handling patterns

#### Enabling Code Mode

Add code mode configuration to your `cpe.yaml`:

```yaml
defaults:
codeMode:
enabled: true
excludedTools:
- multimedia_tool # Exclude tools returning images/videos
- stateful_tool # Exclude tools that maintain state

models:
- ref: sonnet
# Inherits defaults.codeMode

- ref: small-model
# Override for this model only
codeMode:
enabled: true
excludedTools:
- expensive_tool
```

#### How It Works

When code mode is enabled, CPE exposes a special `execute_go_code` tool that:
1. Accepts complete Go source code from the LLM
2. Compiles it with MCP tools exposed as strongly-typed functions
3. Executes it in a temporary sandbox with configurable timeout
4. Returns the output (stdout/stderr) to the LLM

Example LLM-generated code:
```go
package main

import (
"context"
"fmt"
)

func Run(ctx context.Context) error {
weather, err := GetWeather(ctx, GetWeatherInput{
City: "Seattle",
Unit: "fahrenheit",
})
if err != nil {
return err
}

fmt.Printf("Temperature in Seattle: %.0f°F\n", weather.Temperature)
return nil
}
```

#### When to Use Code Mode

**Enable code mode when:**
- You have multiple related tools that need to be composed
- Your tasks involve loops, conditionals, or complex data processing
- You want to reduce latency from multiple LLM round-trips
- You need file I/O or standard library functionality

**Exclude tools from code mode when:**
- They return multimedia content (images, video, audio)
- They maintain state across calls (session-based tools)
- They're built-in tools that models are specifically trained to use

#### Security Considerations

Generated code runs with the same permissions as the CPE process. For production use, consider:
- Running CPE in a containerized or sandboxed environment
- Using restricted file permissions
- Setting conservative execution timeouts
- Carefully configuring which tools are exposed

## Examples

### Code Creation
Expand Down
2 changes: 1 addition & 1 deletion cmd/mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ var mcpCallToolCmd = &cobra.Command{
return err
}

toolArgs := make(map[string]interface{})
toolArgs := make(map[string]any)
if mcpToolArgs != "" {
if err := json.Unmarshal([]byte(mcpToolArgs), &toolArgs); err != nil {
return fmt.Errorf("invalid tool arguments JSON: %w", err)
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ func executeRootCommand(ctx context.Context, args []string) error {
customURL,
effectiveConfig.NoStream,
effectiveConfig.MCPServers,
effectiveConfig.CodeMode,
)
if err != nil {
return fmt.Errorf("failed to create tool capable generator: %w", err)
Expand Down
Loading