executeSandboxCodeStream executes code in sandbox with streaming output
(ctx context.Context, language string, code string, handler SandboxStreamHandler)
| 1958 | |
| 1959 | // executeSandboxCodeStream executes code in sandbox with streaming output |
| 1960 | func executeSandboxCodeStream(ctx context.Context, language string, code string, handler SandboxStreamHandler) (*ToolResult, error) { |
| 1961 | reqPayload := buildSandboxRequest(ctx, language, code) |
| 1962 | |
| 1963 | jsonData, err := json.Marshal(reqPayload) |
| 1964 | if err != nil { |
| 1965 | return nil, fmt.Errorf("failed to marshal sandbox request: %v", err) |
| 1966 | } |
| 1967 | |
| 1968 | url := fmt.Sprintf("%s/execute/stream", strings.TrimRight(config.SandboxServiceURL, "/")) |
| 1969 | logSandboxRequestDebug(ctx, "stream", url, reqPayload, jsonData) |
| 1970 | |
| 1971 | var resp *http.Response |
| 1972 | retryErr := common.Retry(ctx, func() error { |
| 1973 | streamResp, reqErr := getSandboxClient().ExecuteCodeStream(ctx, convertToSandboxClientExecuteRequest(reqPayload)) |
| 1974 | if reqErr != nil { |
| 1975 | logger.Warnf(ctx, "Sandbox streaming request failed: %v", reqErr) |
| 1976 | return reqErr |
| 1977 | } |
| 1978 | resp = streamResp |
| 1979 | return nil |
| 1980 | }, |
| 1981 | common.WithMaxRetries(3), |
| 1982 | common.WithInitialDelay(500*time.Millisecond), |
| 1983 | common.WithRetryableFunc(common.IsRetryableError), |
| 1984 | ) |
| 1985 | if retryErr != nil { |
| 1986 | logger.Errorf(ctx, "Sandbox streaming unavailable after retries: %v", retryErr) |
| 1987 | return nil, fmt.Errorf("工具服务暂时不可用,请稍后重试") |
| 1988 | } |
| 1989 | defer resp.Body.Close() |
| 1990 | |
| 1991 | // Parse SSE stream |
| 1992 | result, parseErr := parseSSEStream(ctx, resp.Body, handler) |
| 1993 | if parseErr != nil { |
| 1994 | logger.Debugf(ctx, "【沙盒】stream解析失败: err=%v", parseErr) |
| 1995 | return nil, parseErr |
| 1996 | } |
| 1997 | outputFiles, snapshot := filterSandboxOutputFilesBySnapshot(loadSandboxOutputSnapshot(ctx), result.OutputFiles) |
| 1998 | rememberSandboxOutputSnapshot(ctx, snapshot) |
| 1999 | result.OutputFiles = outputFiles |
| 2000 | logger.Debugf(ctx, "【沙盒】stream最终结果: output_chars=%d, output_files=%d, output_file_names=%v", |
| 2001 | len(result.Output), len(result.OutputFiles), collectOutputFileNames(result.OutputFiles)) |
| 2002 | return result, nil |
| 2003 | } |
| 2004 | |
| 2005 | func executeSyncToolStream(ctx context.Context, toolName string, executor func() (*ToolResult, error), handler SandboxStreamHandler) (*ToolResult, error) { |
| 2006 | start := time.Now() |
no test coverage detected