yao/agent/sandbox/executor.go
Max bec8d9d426 Fix SystemPrompt passing and Claude CLI stream-json parsing
- Fix missing SystemPrompt field in sandbox executor options conversion
  (was causing Claude CLI to be skipped even when prompts were configured)
- Rewrite parseStream to handle Claude CLI stream-json output format:
  - system: initialization message
  - assistant: message with content array (text, tool_use)
  - result: final result with verification string
- Add comprehensive E2E tests via caller for sandbox integration:
  - TestSandboxE2E_ClaudeCLIExecution: verify command execution
  - TestSandboxE2E_FileCreation: verify file operations
  - TestSandboxE2E_HookOnlyMode: verify Claude CLI skip logic
  - TestSandboxE2E_StreamingResponse: verify streaming works
- Add real_e2e_test.go for direct Claude CLI execution testing

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-01-31 15:07:40 +08:00

51 lines
1.4 KiB
Go

package sandbox
import (
"fmt"
"github.com/yaoapp/yao/agent/sandbox/claude"
infraSandbox "github.com/yaoapp/yao/sandbox"
)
// New creates a new Executor based on the command type
func New(manager *infraSandbox.Manager, opts *Options) (Executor, error) {
if opts == nil {
return nil, fmt.Errorf("options is required")
}
if !IsValidCommand(opts.Command) {
return nil, fmt.Errorf("unsupported command type: %s, supported: %v", opts.Command, CommandTypes)
}
// Set default image if not specified
if opts.Image == "" {
opts.Image = DefaultImage(opts.Command)
}
switch opts.Command {
case "claude":
// Convert to claude.Options
claudeOpts := &claude.Options{
Command: opts.Command,
Image: opts.Image,
MaxMemory: opts.MaxMemory,
MaxCPU: opts.MaxCPU,
Timeout: opts.Timeout,
Arguments: opts.Arguments,
UserID: opts.UserID,
ChatID: opts.ChatID,
MCPConfig: opts.MCPConfig,
MCPTools: opts.MCPTools,
SkillsDir: opts.SkillsDir,
SystemPrompt: opts.SystemPrompt, // Required for Claude CLI execution
ConnectorHost: opts.ConnectorHost,
ConnectorKey: opts.ConnectorKey,
Model: opts.Model,
}
return claude.NewExecutor(manager, claudeOpts)
case "cursor":
return nil, fmt.Errorf("cursor executor not implemented yet")
default:
return nil, fmt.Errorf("unsupported command type: %s", opts.Command)
}
}