From fddd137806d3522a2f3fe3521586f472fcf794ce Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 15 Mar 2026 17:22:44 +0800 Subject: [PATCH] fix(sandbox): update token generation and improve ClaudeRunner file handling - Changed token generation from "sandbox:mcp" to "grpc:mcp" for both access and refresh tokens, aligning with updated service requirements. - Enhanced ClaudeRunner to copy skills from the specified directory to the ".claude/skills" path, improving skill management. - Updated MCP configuration file path to ".claude/mcp.json" for better organization and consistency in file handling. - Added error logging for skill copying and exit code handling in stream execution, enhancing debugging capabilities. Made-with: Cursor --- agent/sandbox/v2/claude/runner.go | 26 +++++++++++++++----------- agent/sandbox/v2/token.go | 4 ++-- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/agent/sandbox/v2/claude/runner.go b/agent/sandbox/v2/claude/runner.go index 465414e2..51a38c24 100644 --- a/agent/sandbox/v2/claude/runner.go +++ b/agent/sandbox/v2/claude/runner.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "os" "path" "strings" "time" @@ -41,17 +42,17 @@ func (r *ClaudeRunner) Prepare(ctx context.Context, req *types.PrepareRequest) e r.mode = "cli" } - env := resolveOSEnv(req.Computer, req.Config) - steps := append([]types.PrepareStep{}, req.Config.Prepare...) if req.SkillsDir != "" { - claudeDir := env.pathJoin(env.WorkDir, ".claude") - steps = append(steps, types.PrepareStep{ - Action: "exec", - Cmd: env.mkdirCmd(claudeDir), - Once: true, - }) + ws := req.Computer.Workplace() + if ws != nil { + src := "local:///" + req.SkillsDir + dst := ".claude/skills" + if _, err := ws.Copy(src, dst); err != nil { + fmt.Fprintf(os.Stderr, "[claude] warn: copy skills %s -> %s: %v\n", src, dst, err) + } + } } if len(req.MCPServers) > 0 { @@ -60,7 +61,7 @@ func (r *ClaudeRunner) Prepare(ctx context.Context, req *types.PrepareRequest) e mcpJSON := buildMCPConfig(req.MCPServers) steps = append(steps, types.PrepareStep{ Action: "file", - Path: env.pathJoin(env.WorkDir, ".mcp.json"), + Path: ".claude/mcp.json", Content: mcpJSON, }) } @@ -103,6 +104,8 @@ func (r *ClaudeRunner) Stream(ctx context.Context, req *types.StreamRequest, han streamOpts = append(streamOpts, infra.WithStdin(stdin)) } + fmt.Fprintf(os.Stderr, "[claude] Stream cmd=%v hasMCP=%v isContinuation=%v stdinLen=%d\n", cmd, r.hasMCP, isContinuation, len(stdin)) + execStream, err := computer.Stream(ctx, cmd, streamOpts...) if err != nil { return fmt.Errorf("computer.Stream: %w", err) @@ -157,6 +160,7 @@ func (r *ClaudeRunner) Stream(ctx context.Context, req *types.StreamRequest, han return waitErr } if exitCode != 0 { + fmt.Fprintf(os.Stderr, "[claude] exit code=%d parseErr=%v waitErr=%v stderr=%q\n", exitCode, parseErr, waitErr, stderrStr) if stderrStr != "" { return fmt.Errorf("claude CLI exited with code %d: %s", exitCode, stderrStr) } @@ -302,7 +306,7 @@ func (r *ClaudeRunner) buildCLICommand(req *types.StreamRequest, oe *osEnv, isCo } if r.hasMCP { - mcpPath := oe.pathJoin(oe.WorkDir, ".mcp.json") + mcpPath := oe.pathJoin(oe.WorkDir, ".claude", "mcp.json") args = append(args, "--mcp-config", mcpPath) if r.mcpToolPattern != "" { args = append(args, "--allowedTools", r.mcpToolPattern) @@ -327,7 +331,7 @@ func buildMCPConfig(servers []types.MCPServer) []byte { } mcpServers[name] = map[string]any{ "command": "tai", - "args": []string{"mcp"}, + "args": []string{"mcp", name}, } } if len(mcpServers) == 0 { diff --git a/agent/sandbox/v2/token.go b/agent/sandbox/v2/token.go index dc47f9d0..956c39cd 100644 --- a/agent/sandbox/v2/token.go +++ b/agent/sandbox/v2/token.go @@ -70,7 +70,7 @@ func IssueSandboxToken(teamID, userID string) (*types.SandboxToken, error) { extraClaims["team_id"] = teamID } - tokenStr, err := svc.MakeAccessToken("__yao.sandbox", "sandbox:mcp", subject, + tokenStr, err := svc.MakeAccessToken("__yao.sandbox", "grpc:mcp", subject, int(accessTokenTTL.Seconds()), extraClaims) if err != nil { return nil, fmt.Errorf("sandbox token: issue access token: %w", err) @@ -78,7 +78,7 @@ func IssueSandboxToken(teamID, userID string) (*types.SandboxToken, error) { tok := &types.SandboxToken{Token: tokenStr} - refreshStr, err := svc.MakeRefreshToken("__yao.sandbox", "sandbox:mcp", subject, + refreshStr, err := svc.MakeRefreshToken("__yao.sandbox", "grpc:mcp", subject, int(refreshTokenTTL.Seconds()), extraClaims) if err != nil { return nil, fmt.Errorf("sandbox token: issue refresh token: %w", err)