feat(agent): add real-time streaming updates to exec tool
Utilize the onUpdate callback from pi-agent-core's AgentTool interface to stream output updates in real-time while commands are executing. - Accept onUpdate as 4th parameter in execute function - Emit tailBuffer updates on each stdout/stderr data event - Stop emitting updates once command is backgrounded (yielded) This enables UI to show live command output progress via the tool_execution_update agent event. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
cbb13b26d1
commit
14bcebee2a
1 changed files with 24 additions and 1 deletions
|
|
@ -47,7 +47,7 @@ export function createExecTool(defaultCwd?: string): AgentTool<typeof ExecSchema
|
|||
description:
|
||||
"Execute a shell command. If the command doesn't complete within yieldMs (default 10s), it automatically runs in background and returns a process ID with any output collected so far. Use 'process output <id>' to check output, 'process status <id>' to check status, 'process stop <id>' to terminate.",
|
||||
parameters: ExecSchema,
|
||||
execute: async (_toolCallId, args, signal) => {
|
||||
execute: async (_toolCallId, args, signal, onUpdate) => {
|
||||
const { command, cwd, timeoutMs, yieldMs = DEFAULT_YIELD_MS } = args as ExecArgs;
|
||||
const effectiveCwd = cwd || defaultCwd;
|
||||
|
||||
|
|
@ -67,6 +67,29 @@ export function createExecTool(defaultCwd?: string): AgentTool<typeof ExecSchema
|
|||
// This ensures output is captured even before yield timeout
|
||||
const processId = registerProcess(child, command, effectiveCwd, "exec");
|
||||
|
||||
// Stream output updates via onUpdate callback
|
||||
// Note: appendOutput is already called by registerProcess, we just emit updates here
|
||||
const emitUpdate = () => {
|
||||
if (!onUpdate || yielded) return;
|
||||
const entry = PROCESS_REGISTRY.get(processId);
|
||||
if (!entry) return;
|
||||
onUpdate({
|
||||
content: [{ type: "text", text: entry.tailBuffer || "(running...)" }],
|
||||
details: {
|
||||
output: entry.tailBuffer,
|
||||
exitCode: null,
|
||||
truncated: false,
|
||||
processId,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Listen to stdout/stderr to trigger onUpdate (data collection is handled by registerProcess)
|
||||
if (onUpdate) {
|
||||
child.stdout?.on("data", emitUpdate);
|
||||
child.stderr?.on("data", emitUpdate);
|
||||
}
|
||||
|
||||
// Timeout handling (hard kill)
|
||||
if (timeoutMs && timeoutMs > 0) {
|
||||
timeout = setTimeout(() => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue