executeSandboxCode handles the HTTP communication with the Sandbox Service with retry logic for transient failures
(ctx context.Context, language string, code string)
| 218 | // executeSandboxCode handles the HTTP communication with the Sandbox Service |
| 219 | // with retry logic for transient failures |
| 220 | func executeSandboxCode(ctx context.Context, language string, code string) (string, error) { |
| 221 | reqPayload := buildSandboxRequest(ctx, language, code) |
| 222 | if err := ensureSandboxSessionSeeded(ctx, reqPayload.SessionID, reqPayload.Cwd); err != nil { |
| 223 | return "", err |
| 224 | } |
| 225 | if err := preflightSandboxClientCode(ctx, reqPayload.SessionID, reqPayload.Cwd, language, code); err != nil { |
| 226 | return "", err |
| 227 | } |
| 228 | |
| 229 | jsonData, err := json.Marshal(reqPayload) |
| 230 | if err != nil { |
| 231 | return "", fmt.Errorf("failed to marshal sandbox request: %v", err) |
| 232 | } |
| 233 | |
| 234 | url := fmt.Sprintf("%s/execute", strings.TrimRight(config.SandboxServiceURL, "/")) |
| 235 | logSandboxRequestDebug(ctx, "execute_legacy", url, reqPayload, jsonData) |
| 236 | |
| 237 | var result *sandboxclient.ExecuteCodeResponse |
| 238 | |
| 239 | // Execute with retry logic for transient failures |
| 240 | retryErr := common.Retry(ctx, func() error { |
| 241 | resp, httpErr := getSandboxClient().ExecuteCode(ctx, convertToSandboxClientExecuteRequest(reqPayload)) |
| 242 | if httpErr != nil { |
| 243 | logger.Warnf(ctx, "Sandbox service request failed: %v", httpErr) |
| 244 | return httpErr |
| 245 | } |
| 246 | result = resp |
| 247 | return nil |
| 248 | }, |
| 249 | common.WithMaxRetries(3), |
| 250 | common.WithInitialDelay(500*time.Millisecond), |
| 251 | common.WithRetryableFunc(common.IsRetryableError), |
| 252 | ) |
| 253 | |
| 254 | if retryErr != nil { |
| 255 | logger.Errorf(ctx, "Sandbox service unavailable after retries: %v", retryErr) |
| 256 | return "", fmt.Errorf("工具服务暂时不可用,请稍后重试") |
| 257 | } |
| 258 | logSandboxResponseDebug(ctx, "execute_legacy", convertFromSandboxClientExecuteResponse(result)) |
| 259 | return formatCommandResult(result.Stdout, result.Stderr, result.ExitCode), nil |
| 260 | } |
| 261 | |
| 262 | // DetectToolCallsFromContent parses the content string for code blocks or patterns that imply a tool call |
| 263 | func DetectToolCallsFromContent(content string) []relay_model.Tool { |
nothing calls this directly
no test coverage detected