ProcessOutput returns an AgentTool that retrieves the output of a tracked process by its ID.
(options ProcessToolOptions)
| 395 | // ProcessOutput returns an AgentTool that retrieves the output |
| 396 | // of a tracked process by its ID. |
| 397 | func ProcessOutput(options ProcessToolOptions) fantasy.AgentTool { |
| 398 | return fantasy.NewAgentTool( |
| 399 | "process_output", |
| 400 | "Retrieve output from a tracked process by ID. "+ |
| 401 | "Use the process_id returned by execute with "+ |
| 402 | "run_in_background=true or from a timed-out "+ |
| 403 | "execute's background_process_id. Blocks up to "+ |
| 404 | "10s for the process to exit, then returns the "+ |
| 405 | "output and exit_code. If still running after "+ |
| 406 | "the timeout, returns the output so far. Use "+ |
| 407 | "wait_timeout to override the default 10s wait "+ |
| 408 | "(e.g. '30s', or '0s' for an immediate snapshot "+ |
| 409 | "without waiting).", |
| 410 | func(ctx context.Context, args ProcessOutputArgs, _ fantasy.ToolCall) (fantasy.ToolResponse, error) { |
| 411 | if options.GetWorkspaceConn == nil { |
| 412 | return fantasy.NewTextErrorResponse("workspace connection resolver is not configured"), nil |
| 413 | } |
| 414 | if args.ProcessID == "" { |
| 415 | return fantasy.NewTextErrorResponse("process_id is required"), nil |
| 416 | } |
| 417 | conn, err := options.GetWorkspaceConn(ctx) |
| 418 | if err != nil { |
| 419 | return fantasy.NewTextErrorResponse(err.Error()), nil |
| 420 | } |
| 421 | |
| 422 | timeout := defaultProcessOutputTimeout |
| 423 | if args.WaitTimeout != nil { |
| 424 | parsed, err := time.ParseDuration(*args.WaitTimeout) |
| 425 | if err != nil { |
| 426 | return fantasy.NewTextErrorResponse( |
| 427 | fmt.Sprintf("invalid wait_timeout %q: %v", *args.WaitTimeout, err), |
| 428 | ), nil |
| 429 | } |
| 430 | timeout = parsed |
| 431 | } |
| 432 | var opts *workspacesdk.ProcessOutputOptions |
| 433 | // Save parent context before applying timeout. |
| 434 | parentCtx := ctx |
| 435 | if timeout > 0 { |
| 436 | opts = &workspacesdk.ProcessOutputOptions{ |
| 437 | Wait: true, |
| 438 | } |
| 439 | var cancel context.CancelFunc |
| 440 | ctx, cancel = context.WithTimeout(ctx, timeout) |
| 441 | defer cancel() |
| 442 | } |
| 443 | resp, err := conn.ProcessOutput(ctx, args.ProcessID, opts) |
| 444 | if err != nil { |
| 445 | // The blocking request may have failed due to a |
| 446 | // context timeout or a transport error (e.g. |
| 447 | // server WriteTimeout). Try a non-blocking |
| 448 | // snapshot if the parent context is still alive. |
| 449 | if parentCtx.Err() != nil { |
| 450 | return errorResult(fmt.Sprintf("get process output: %v", err)), nil |
| 451 | } |
| 452 | bgCtx, bgCancel := context.WithTimeout(parentCtx, snapshotTimeout) |
| 453 | defer bgCancel() |
| 454 | resp, err = conn.ProcessOutput(bgCtx, args.ProcessID, nil) |
no test coverage detected