Skip to content
Merged
9 changes: 5 additions & 4 deletions packages/core/src/services/backgroundShellRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

/**
* Tracks background shell processes spawned via the `shell` tool with
* `is_background: true`. Each entry holds the metadata the agent and the
* `/tasks` slash command need to query, observe, or terminate a running
* background shell.
* `is_background: true`. Each entry holds the metadata that the agent,
* the `/tasks` slash command, and the interactive Background tasks
* dialog use to query, observe, or terminate a running background
* shell.
*
* State machine: register → running → { completed | failed | cancelled }.
* Transitions out of running are one-shot: complete/fail/cancel become
Expand All @@ -28,7 +29,7 @@ export type BackgroundShellStatus =
| 'cancelled';

export interface BackgroundShellEntry {
/** Stable id used by the model and the `/tasks` UI. */
/** Stable id used by the model, the `/tasks` slash command, and the Background tasks dialog. */
shellId: string;
/** The user-supplied command, after any pre-processing the tool applies. */
command: string;
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/services/monitorRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ export class MonitorRegistry {
);
// Persist the reason so the dialog's detail view can surface it
// after the monitor terminates (the chat-history notification is
// separate and not visible from /tasks dialog reopens).
// separate and not visible in later Background tasks dialog
Comment thread
wenshao marked this conversation as resolved.
Resolved
// reopens or `/tasks` listings).
entry.error = 'Max events reached';
this.settle(entry, 'completed');
entry.abortController.abort();
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/tools/monitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@ class MonitorToolInvocation extends BaseToolInvocation<
`max_events: ${maxEvents}\n` +
`idle_timeout: ${idleTimeoutMs}ms\n` +
`Events will be delivered as notifications. ` +
`The monitor auto-stops after ${maxEvents} events or ${idleTimeoutMs}ms of silence.`,
`The monitor auto-stops after ${maxEvents} events or ${idleTimeoutMs}ms of silence.\n` +
`To inspect: /tasks (text) or the interactive Background tasks dialog (focus the footer Background tasks pill, then Enter — detail view + live updates).`,
returnDisplay: `Monitor started: ${displayDescription} (${monitorId})`,
Comment thread
wenshao marked this conversation as resolved.
Resolved
};
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/tools/shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -862,7 +862,7 @@ export class ShellToolInvocation extends BaseToolInvocation<
`id: ${shellId}\n` +
pidLine +
`output file: ${outputPath}\n` +
`Use the /tasks command to list and inspect background shells, or Read the output file directly.`,
`To inspect: /tasks (text) or the interactive Background tasks dialog (focus the footer Background tasks pill, then Enter — detail view + live updates). Read the output file directly to view the captured output.`,
returnDisplay: `Background shell ${shellId} started${pid !== undefined ? ` (pid ${pid})` : ''}.`,
};
}
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/tools/task-stop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ class TaskStopInvocation extends BaseToolInvocation<
// Background shell registry (Phase B). Settles asynchronously when the
// child process exits in response to the AbortController; the registry
// entry's terminal state (`cancelled`) and final exit code/output stay
// observable via `/tasks` and the on-disk output file.
// observable via `/tasks` (text), the interactive Background tasks
// dialog (focus the footer Background tasks pill, then Enter), and
// the on-disk output file.
const shellRegistry = this.config.getBackgroundShellRegistry();
const shellEntry = shellRegistry.get(taskId);
if (shellEntry) {
Expand All @@ -107,7 +109,7 @@ class TaskStopInvocation extends BaseToolInvocation<
return {
llmContent:
`Cancellation requested for background shell "${taskId}". ` +
`Final status will be visible via /tasks once the process drains; ` +
`Final status will be visible via /tasks (text) or the interactive Background tasks dialog (focus the footer Background tasks pill, then Enter) once the process drains; ` +
`captured output remains at ${shellEntry.outputPath}.\n` +
`Command: ${shellEntry.command}`,
returnDisplay: `Cancelled shell: ${shellEntry.command}`,
Expand All @@ -123,7 +125,8 @@ class TaskStopInvocation extends BaseToolInvocation<
monitorRegistry.cancel(taskId);
return {
llmContent:
`Cancellation requested for monitor "${taskId}".\n` +
`Cancellation requested for monitor "${taskId}". ` +
`Final status will be visible via /tasks (text) or the interactive Background tasks dialog (focus the footer Background tasks pill, then Enter) once the process drains.\n` +
Comment thread
wenshao marked this conversation as resolved.
Resolved
Comment thread
wenshao marked this conversation as resolved.
Resolved
`Command: ${monitorEntry.command}`,
returnDisplay: `Cancelled monitor: ${monitorEntry.description}`,
};
Expand Down
Loading