pi-subagents 0.49.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +97 -0
- package/agents/gpt-pro.md +17 -0
- package/agents/oracle.md +7 -5
- package/agents/researcher.md +1 -1
- package/agents/reviewer.md +2 -2
- package/agents/scout.md +1 -1
- package/agents/worker.md +1 -1
- package/async-retention-discovery-worker.mjs +180 -0
- package/docs/agents.md +37 -2
- package/docs/configuration.md +76 -14
- package/docs/extension-api.md +78 -1
- package/docs/missions.md +1 -1
- package/docs/observability.md +20 -4
- package/docs/tool-reference.md +55 -39
- package/docs/workflows.md +171 -5
- package/package.json +4 -2
- package/skills/pi-subagents/SKILL.md +5 -4
- package/skills/pi-subagents/references/constraints-and-recipes.md +9 -6
- package/skills/pi-subagents/references/execution-controls.md +22 -18
- package/skills/pi-subagents/references/management-authoring-rpc.md +5 -5
- package/skills/pi-subagents/references/prompting-and-roles.md +33 -17
- package/src/agents/agent-management.ts +100 -345
- package/src/agents/agent-serializer.ts +2 -0
- package/src/agents/agents.ts +135 -25
- package/src/api/external-job-provider.ts +185 -0
- package/src/api/external-runs.ts +174 -84
- package/src/api/preflight.ts +42 -11
- package/src/api/shared-types.ts +2 -0
- package/src/extension/config.ts +36 -3
- package/src/extension/doctor.ts +3 -6
- package/src/extension/fanout-child.ts +2 -2
- package/src/extension/index.ts +210 -90
- package/src/extension/public-execution.ts +31 -2
- package/src/extension/rpc.ts +5 -1
- package/src/extension/schemas.ts +14 -36
- package/src/extension/tool-description.ts +37 -24
- package/src/inspectors/herdr/actions.ts +5 -9
- package/src/inspectors/herdr/inspector-runner.ts +2 -1
- package/src/inspectors/herdr/project-panes.ts +4 -8
- package/src/inspectors/herdr/shell-command.ts +16 -0
- package/src/intercom/intercom-bridge.ts +2 -3
- package/src/intercom/native-supervisor-channel.ts +49 -51
- package/src/missions/goal-driver.ts +3 -1
- package/src/missions/lifecycle.ts +6 -1
- package/src/missions/store.ts +4 -9
- package/src/profiles/profiles.ts +3 -1
- package/src/runs/background/active-run-index.ts +94 -1
- package/src/runs/background/async-execution.ts +98 -38
- package/src/runs/background/async-job-tracker.ts +21 -4
- package/src/runs/background/async-resume.ts +30 -17
- package/src/runs/background/async-retention.ts +888 -0
- package/src/runs/background/async-status-snapshot.ts +277 -0
- package/src/runs/background/async-status.ts +47 -56
- package/src/runs/background/chain-append.ts +3 -33
- package/src/runs/background/chain-root-attachment.ts +2 -2
- package/src/runs/background/completion-replay.ts +11 -1
- package/src/runs/background/control-channel.ts +14 -68
- package/src/runs/background/fleet-view.ts +3 -1
- package/src/runs/background/index-segment.ts +59 -0
- package/src/runs/background/notify.ts +3 -1
- package/src/runs/background/result-files.ts +505 -0
- package/src/runs/background/result-watcher.ts +250 -51
- package/src/runs/background/retained-children.ts +79 -20
- package/src/runs/background/run-id-query.ts +7 -0
- package/src/runs/background/run-id-resolver.ts +37 -29
- package/src/runs/background/run-status.ts +34 -20
- package/src/runs/background/scheduled-runs.ts +71 -27
- package/src/runs/background/stale-run-reconciler.ts +33 -16
- package/src/runs/background/steering.ts +11 -1
- package/src/runs/background/subagent-runner.ts +535 -161
- package/src/runs/background/subagent-wait.ts +9 -7
- package/src/runs/background/terminal-run-index.ts +129 -0
- package/src/runs/background/wait-completions.ts +22 -2
- package/src/runs/background/wait-subscriptions.ts +80 -1
- package/src/runs/foreground/async-dismiss-action.ts +2 -1
- package/src/runs/foreground/async-steering-action.ts +21 -14
- package/src/runs/foreground/execution.ts +221 -15
- package/src/runs/foreground/subagent-executor.ts +529 -1519
- package/src/runs/foreground/workflow-foreground-steering.ts +6 -5
- package/src/runs/shared/chain-outputs.ts +1 -3
- package/src/runs/shared/completion-guard.ts +96 -6
- package/src/runs/shared/external-cli-runner.ts +4 -0
- package/src/runs/shared/external-job-bridge.ts +450 -0
- package/src/runs/shared/external-job-runner.ts +286 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +14 -0
- package/src/runs/shared/model-fallback.ts +34 -3
- package/src/runs/shared/nested-events.ts +66 -62
- package/src/runs/shared/orca-progress-tabs.ts +437 -0
- package/src/runs/shared/parallel-handoff.ts +46 -4
- package/src/runs/shared/parallel-utils.ts +6 -15
- package/src/runs/shared/permissions.ts +5 -1
- package/src/runs/shared/pi-args.ts +8 -1
- package/src/runs/shared/subagent-control.ts +41 -4
- package/src/runs/shared/subagent-prompt-runtime.ts +13 -15
- package/src/runs/shared/subagent-startup-retry.ts +12 -0
- package/src/runs/shared/tool-timeout.ts +93 -0
- package/src/runs/shared/workflow-graph.ts +1 -23
- package/src/runs/shared/worktree.ts +12 -1
- package/src/shared/atomic-json.ts +22 -2
- package/src/shared/capacity-resilient-json.ts +102 -0
- package/src/shared/completion-owner.ts +14 -0
- package/src/shared/file-system-retry.ts +49 -1
- package/src/shared/fork-context.ts +42 -0
- package/src/shared/prompt-resources.ts +0 -40
- package/src/shared/settings.ts +3 -27
- package/src/shared/types.ts +88 -27
- package/src/shared/utils.ts +8 -0
- package/src/shared/watch-strategy.ts +10 -0
- package/src/slash/slash-commands.ts +45 -28
- package/src/slash/slash-live-state.ts +3 -0
- package/src/tui/fleet-status.ts +160 -45
- package/src/tui/fleet.ts +186 -28
- package/src/tui/render.ts +41 -10
- package/src/workflows/chat-progress.ts +7 -5
- package/src/workflows/scripted-workflow.ts +424 -125
- package/src/runs/foreground/chain-clarify.ts +0 -1354
- package/src/runs/foreground/chain-execution.ts +0 -1565
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
buildControlEvent,
|
|
39
39
|
claimControlNotification,
|
|
40
40
|
deriveActivityState,
|
|
41
|
+
shouldEmitOpenToolAttention,
|
|
41
42
|
shouldNotifyControlEvent,
|
|
42
43
|
} from "../shared/subagent-control.ts";
|
|
43
44
|
import {
|
|
@@ -53,10 +54,12 @@ import {
|
|
|
53
54
|
} from "../../shared/utils.ts";
|
|
54
55
|
import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
|
|
55
56
|
import { buildAgentMemoryInjection } from "../../agents/agent-memory.ts";
|
|
57
|
+
import { effectiveToolTimeoutMs, formatToolTimeoutMessage, resolveToolTimeoutMs, toolTimeoutCallKey, toolTimeoutFromEnv } from "../shared/tool-timeout.ts";
|
|
56
58
|
import { evaluateCompletionMutationGuard } from "../shared/completion-guard.ts";
|
|
57
59
|
import { arbitrateCompletionGuardRescue } from "../shared/llm-intent-arbiter.ts";
|
|
58
60
|
import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
|
|
59
61
|
import { createJsonlWriter } from "../../shared/jsonl-writer.ts";
|
|
62
|
+
import { createOrcaProgressTab, type OrcaProgressTab } from "../shared/orca-progress-tabs.ts";
|
|
60
63
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
61
64
|
import { resolvePermissionRules } from "../shared/permissions.ts";
|
|
62
65
|
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan, type SubagentTaskDelivery } from "../shared/pi-args.ts";
|
|
@@ -74,6 +77,7 @@ import {
|
|
|
74
77
|
} from "../shared/model-fallback.ts";
|
|
75
78
|
import {
|
|
76
79
|
SUBAGENT_STARTUP_RETRY_DELAYS_MS,
|
|
80
|
+
formatSubagentExtensionConflictError,
|
|
77
81
|
formatSubagentStartupRetryExhaustedError,
|
|
78
82
|
formatSubagentStartupRetryNote,
|
|
79
83
|
isRetryableSubagentStartupFailure,
|
|
@@ -302,6 +306,7 @@ async function runSingleAttempt(
|
|
|
302
306
|
outputSnapshot?: SingleOutputSnapshot;
|
|
303
307
|
originalTask?: string;
|
|
304
308
|
taskDelivery?: SubagentTaskDelivery;
|
|
309
|
+
orcaProgressTab?: OrcaProgressTab;
|
|
305
310
|
},
|
|
306
311
|
): Promise<SingleResult> {
|
|
307
312
|
const effectiveThinking = options.thinkingOverride ?? agent.thinking;
|
|
@@ -670,6 +675,7 @@ async function runSingleAttempt(
|
|
|
670
675
|
clearWatchdogTailTimer();
|
|
671
676
|
clearStdioGuard();
|
|
672
677
|
clearTimeoutTimers();
|
|
678
|
+
clearAllToolTimeouts();
|
|
673
679
|
clearTurnBudgetTimers();
|
|
674
680
|
if (protocolHardKillTimer) {
|
|
675
681
|
clearTimeout(protocolHardKillTimer);
|
|
@@ -694,6 +700,64 @@ async function runSingleAttempt(
|
|
|
694
700
|
|
|
695
701
|
let activeLongRunningNotified = false;
|
|
696
702
|
let pendingToolResult: { tool: string; path?: string; mutates: boolean; startedAt?: number } | undefined;
|
|
703
|
+
type ActiveToolCall = { key: string; tool: string; args: string; startedAt: number; path?: string };
|
|
704
|
+
let activeToolSequence = 0;
|
|
705
|
+
const activeToolCalls = new Map<string, ActiveToolCall>();
|
|
706
|
+
const activeToolKeysByName = new Map<string, string[]>();
|
|
707
|
+
const latestActiveToolCall = (): ActiveToolCall | undefined => [...activeToolCalls.values()].sort((left, right) => right.startedAt - left.startedAt)[0];
|
|
708
|
+
const refreshCurrentTool = (): void => {
|
|
709
|
+
const active = latestActiveToolCall();
|
|
710
|
+
if (!active) {
|
|
711
|
+
progress.currentTool = undefined;
|
|
712
|
+
progress.currentToolArgs = undefined;
|
|
713
|
+
progress.currentToolStartedAt = undefined;
|
|
714
|
+
progress.currentPath = undefined;
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
progress.currentTool = active.tool;
|
|
718
|
+
progress.currentToolArgs = active.args;
|
|
719
|
+
progress.currentToolStartedAt = active.startedAt;
|
|
720
|
+
progress.currentPath = active.path;
|
|
721
|
+
};
|
|
722
|
+
const recordActiveToolCall = (event: { toolCallId?: unknown; toolName: string }, args: Record<string, unknown>, now: number): ActiveToolCall => {
|
|
723
|
+
const key = toolTimeoutCallKey(event, ++activeToolSequence);
|
|
724
|
+
const path = resolveCurrentPath(event.toolName, args);
|
|
725
|
+
const active: ActiveToolCall = {
|
|
726
|
+
key,
|
|
727
|
+
tool: event.toolName,
|
|
728
|
+
args: extractToolArgsPreview(args),
|
|
729
|
+
startedAt: now,
|
|
730
|
+
...(path !== undefined ? { path } : {}),
|
|
731
|
+
};
|
|
732
|
+
activeToolCalls.set(key, active);
|
|
733
|
+
const keys = activeToolKeysByName.get(active.tool) ?? [];
|
|
734
|
+
keys.push(key);
|
|
735
|
+
activeToolKeysByName.set(active.tool, keys);
|
|
736
|
+
refreshCurrentTool();
|
|
737
|
+
return active;
|
|
738
|
+
};
|
|
739
|
+
const removeActiveToolCallKey = (key: string): ActiveToolCall | undefined => {
|
|
740
|
+
const active = activeToolCalls.get(key);
|
|
741
|
+
if (!active) return undefined;
|
|
742
|
+
activeToolCalls.delete(key);
|
|
743
|
+
const keys = activeToolKeysByName.get(active.tool)?.filter((candidate) => candidate !== key) ?? [];
|
|
744
|
+
if (keys.length > 0) activeToolKeysByName.set(active.tool, keys);
|
|
745
|
+
else activeToolKeysByName.delete(active.tool);
|
|
746
|
+
return active;
|
|
747
|
+
};
|
|
748
|
+
const removeActiveToolCall = (event: { toolCallId?: unknown; toolName?: unknown }): ActiveToolCall | undefined => {
|
|
749
|
+
const key = typeof event.toolCallId === "string" && event.toolCallId.length > 0
|
|
750
|
+
? `id:${event.toolCallId}`
|
|
751
|
+
: typeof event.toolName === "string"
|
|
752
|
+
? activeToolKeysByName.get(event.toolName)?.[0]
|
|
753
|
+
: activeToolCalls.size === 1
|
|
754
|
+
? [...activeToolCalls.keys()][0]
|
|
755
|
+
: undefined;
|
|
756
|
+
return key ? removeActiveToolCallKey(key) : undefined;
|
|
757
|
+
};
|
|
758
|
+
const openToolAttentionTarget = (now: number): ActiveToolCall | undefined => [...activeToolCalls.values()]
|
|
759
|
+
.filter((active) => shouldEmitOpenToolAttention({ config: controlConfig, currentTool: active.tool, currentToolStartedAt: active.startedAt, now }))
|
|
760
|
+
.sort((left, right) => left.startedAt - right.startedAt)[0];
|
|
697
761
|
const mutatingFailures = createMutatingFailureState();
|
|
698
762
|
const mutatingFailureWindowMs = 5 * 60_000;
|
|
699
763
|
const currentToolDurationMs = (now: number) => progress.currentToolStartedAt ? Math.max(0, now - progress.currentToolStartedAt) : undefined;
|
|
@@ -719,6 +783,7 @@ async function runSingleAttempt(
|
|
|
719
783
|
currentToolDurationMs: input.currentToolDurationMs ?? currentToolDurationMs(now),
|
|
720
784
|
currentPath: input.currentPath ?? progress.currentPath,
|
|
721
785
|
recentFailureSummary: input.recentFailureSummary,
|
|
786
|
+
taskPreview: task,
|
|
722
787
|
});
|
|
723
788
|
emitControlEvent(event);
|
|
724
789
|
return previous !== "needs_attention";
|
|
@@ -745,6 +810,7 @@ async function runSingleAttempt(
|
|
|
745
810
|
currentToolDurationMs: currentToolDurationMs(now),
|
|
746
811
|
currentPath: progress.currentPath,
|
|
747
812
|
elapsedMs: now - startTime,
|
|
813
|
+
taskPreview: task,
|
|
748
814
|
}));
|
|
749
815
|
return true;
|
|
750
816
|
};
|
|
@@ -811,6 +877,17 @@ async function runSingleAttempt(
|
|
|
811
877
|
if (idleState === "needs_attention") {
|
|
812
878
|
return progress.activityState === "needs_attention" ? false : emitNeedsAttention(now);
|
|
813
879
|
}
|
|
880
|
+
const toolAttentionTarget = progress.activityState !== "needs_attention" ? openToolAttentionTarget(now) : undefined;
|
|
881
|
+
if (toolAttentionTarget) {
|
|
882
|
+
const durationMs = Math.max(0, now - toolAttentionTarget.startedAt);
|
|
883
|
+
return emitNeedsAttention(now, {
|
|
884
|
+
message: `${agent.name} has had tool '${toolAttentionTarget.tool}' open for ${Math.floor(durationMs / 1000)}s`,
|
|
885
|
+
reason: "tool_open_threshold",
|
|
886
|
+
currentTool: toolAttentionTarget.tool,
|
|
887
|
+
currentPath: toolAttentionTarget.path,
|
|
888
|
+
currentToolDurationMs: durationMs,
|
|
889
|
+
});
|
|
890
|
+
}
|
|
814
891
|
const activeReason = nextLongRunningTrigger(controlConfig, {
|
|
815
892
|
startedAt: startTime,
|
|
816
893
|
now,
|
|
@@ -848,16 +925,18 @@ async function runSingleAttempt(
|
|
|
848
925
|
const processLine = (line: string) => {
|
|
849
926
|
if (!line.trim()) return;
|
|
850
927
|
jsonlWriter.writeLine(line);
|
|
851
|
-
let evt: { type?: string; message?: Message; toolName?: string; args?: unknown; willRetry?: unknown };
|
|
928
|
+
let evt: { type?: string; message?: Message; toolName?: string; toolCallId?: string; args?: unknown; willRetry?: unknown };
|
|
852
929
|
try {
|
|
853
|
-
evt = JSON.parse(line) as { type?: string; message?: Message; toolName?: string; args?: unknown; willRetry?: unknown };
|
|
930
|
+
evt = JSON.parse(line) as { type?: string; message?: Message; toolName?: string; toolCallId?: string; args?: unknown; willRetry?: unknown };
|
|
854
931
|
} catch {
|
|
855
932
|
rawStdoutTail.push(`${line}\n`);
|
|
856
933
|
shared.transcriptWriter?.writeStdoutLine(line);
|
|
934
|
+
shared.orcaProgressTab?.append(`${line}\n`);
|
|
857
935
|
// Non-JSON stdout lines are expected; only structured events are parsed.
|
|
858
936
|
return;
|
|
859
937
|
}
|
|
860
938
|
shared.transcriptWriter?.writeChildEvent(evt);
|
|
939
|
+
shared.orcaProgressTab?.event(evt);
|
|
861
940
|
if (evt.type === "agent_settled") agentSettledReceived = true;
|
|
862
941
|
applyChildLifecycle(projectChildLifecycle(evt));
|
|
863
942
|
|
|
@@ -892,6 +971,8 @@ async function runSingleAttempt(
|
|
|
892
971
|
const toolArgs = evt.args && typeof evt.args === "object" && !Array.isArray(evt.args)
|
|
893
972
|
? evt.args as Record<string, unknown>
|
|
894
973
|
: {};
|
|
974
|
+
const activeTool = evt.toolName !== undefined ? recordActiveToolCall(evt as { toolCallId?: unknown; toolName: string }, toolArgs, now) : undefined;
|
|
975
|
+
if (evt.toolName !== undefined) armToolTimeout(evt as { toolCallId?: unknown; toolName: string });
|
|
895
976
|
if (options.structuredOutput && evt.toolName === "structured_output") {
|
|
896
977
|
structuredOutputToolInvoked = true;
|
|
897
978
|
structuredOutputMessageStartIndex = result.messages?.length ?? 0;
|
|
@@ -903,28 +984,23 @@ async function runSingleAttempt(
|
|
|
903
984
|
if (options.toolBudget) {
|
|
904
985
|
result.toolBudget = toolBudgetState(options.toolBudget, progress.toolCount);
|
|
905
986
|
}
|
|
906
|
-
progress.currentTool = evt.toolName;
|
|
907
|
-
progress.currentToolArgs = extractToolArgsPreview(toolArgs);
|
|
908
|
-
progress.currentToolStartedAt = now;
|
|
909
|
-
progress.currentPath = resolveCurrentPath(evt.toolName, toolArgs);
|
|
910
987
|
const mutates = isMutatingTool(evt.toolName, toolArgs);
|
|
911
988
|
observedMutationAttempt = observedMutationAttempt || mutates;
|
|
912
|
-
pendingToolResult = { tool: evt.toolName ?? "tool", path:
|
|
989
|
+
pendingToolResult = { tool: evt.toolName ?? "tool", path: activeTool?.path, mutates, startedAt: now };
|
|
913
990
|
fireUpdate();
|
|
914
991
|
}
|
|
915
992
|
|
|
916
993
|
if (evt.type === "tool_execution_end") {
|
|
917
|
-
|
|
994
|
+
clearActiveToolTimeout(evt);
|
|
995
|
+
const endedTool = removeActiveToolCall(evt);
|
|
996
|
+
if (endedTool) {
|
|
918
997
|
progress.recentTools.push({
|
|
919
|
-
tool:
|
|
920
|
-
args:
|
|
998
|
+
tool: endedTool.tool,
|
|
999
|
+
args: endedTool.args,
|
|
921
1000
|
endMs: now,
|
|
922
1001
|
});
|
|
923
1002
|
}
|
|
924
|
-
|
|
925
|
-
progress.currentToolArgs = undefined;
|
|
926
|
-
progress.currentToolStartedAt = undefined;
|
|
927
|
-
progress.currentPath = undefined;
|
|
1003
|
+
refreshCurrentTool();
|
|
928
1004
|
fireUpdate();
|
|
929
1005
|
}
|
|
930
1006
|
|
|
@@ -1022,6 +1098,7 @@ async function runSingleAttempt(
|
|
|
1022
1098
|
timeoutTimer = setTimeout(() => {
|
|
1023
1099
|
if (processClosed || lifecycleFinished || interruptedByControl) return;
|
|
1024
1100
|
result.timedOut = true;
|
|
1101
|
+
clearAllToolTimeouts();
|
|
1025
1102
|
result.error = attemptTimeout.message;
|
|
1026
1103
|
result.finalOutput = attemptTimeout.message;
|
|
1027
1104
|
progress.status = "failed";
|
|
@@ -1043,6 +1120,81 @@ async function runSingleAttempt(
|
|
|
1043
1120
|
timeoutTimer.unref?.();
|
|
1044
1121
|
}
|
|
1045
1122
|
|
|
1123
|
+
let toolTimeoutSequence = 0;
|
|
1124
|
+
const activeToolTimeouts = new Map<string, { toolName: string; timer: ReturnType<typeof setTimeout> }>();
|
|
1125
|
+
const activeToolTimeoutKeysByName = new Map<string, string[]>();
|
|
1126
|
+
let toolTimeoutTerminationTimer: ReturnType<typeof setTimeout> | undefined;
|
|
1127
|
+
let toolTimeoutHardKillTimer: ReturnType<typeof setTimeout> | undefined;
|
|
1128
|
+
const removeToolTimeoutKey = (key: string): void => {
|
|
1129
|
+
const active = activeToolTimeouts.get(key);
|
|
1130
|
+
if (!active) return;
|
|
1131
|
+
clearTimeout(active.timer);
|
|
1132
|
+
activeToolTimeouts.delete(key);
|
|
1133
|
+
const keys = activeToolTimeoutKeysByName.get(active.toolName)?.filter((candidate) => candidate !== key) ?? [];
|
|
1134
|
+
if (keys.length > 0) activeToolTimeoutKeysByName.set(active.toolName, keys);
|
|
1135
|
+
else activeToolTimeoutKeysByName.delete(active.toolName);
|
|
1136
|
+
};
|
|
1137
|
+
const clearActiveToolTimeout = (event: { toolCallId?: unknown; toolName?: unknown }): void => {
|
|
1138
|
+
const key = typeof event.toolCallId === "string" && event.toolCallId.length > 0
|
|
1139
|
+
? `id:${event.toolCallId}`
|
|
1140
|
+
: typeof event.toolName === "string"
|
|
1141
|
+
? activeToolTimeoutKeysByName.get(event.toolName)?.[0]
|
|
1142
|
+
: activeToolTimeouts.size === 1
|
|
1143
|
+
? [...activeToolTimeouts.keys()][0]
|
|
1144
|
+
: undefined;
|
|
1145
|
+
if (key) removeToolTimeoutKey(key);
|
|
1146
|
+
};
|
|
1147
|
+
const clearAllToolTimeouts = (): void => {
|
|
1148
|
+
for (const key of [...activeToolTimeouts.keys()]) removeToolTimeoutKey(key);
|
|
1149
|
+
if (toolTimeoutTerminationTimer) {
|
|
1150
|
+
clearTimeout(toolTimeoutTerminationTimer);
|
|
1151
|
+
toolTimeoutTerminationTimer = undefined;
|
|
1152
|
+
}
|
|
1153
|
+
if (toolTimeoutHardKillTimer) {
|
|
1154
|
+
clearTimeout(toolTimeoutHardKillTimer);
|
|
1155
|
+
toolTimeoutHardKillTimer = undefined;
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
const terminateForToolTimeout = (message: string): void => {
|
|
1159
|
+
if (processClosed || lifecycleFinished || interruptedByControl) return;
|
|
1160
|
+
result.timedOut = true;
|
|
1161
|
+
result.error = message;
|
|
1162
|
+
result.finalOutput = message;
|
|
1163
|
+
progress.status = "failed";
|
|
1164
|
+
progress.error = message;
|
|
1165
|
+
progress.durationMs = Date.now() - startTime;
|
|
1166
|
+
fireUpdate();
|
|
1167
|
+
trySignalChild(proc, "SIGINT");
|
|
1168
|
+
toolTimeoutTerminationTimer = setTimeout(() => {
|
|
1169
|
+
if (processClosed || lifecycleFinished) return;
|
|
1170
|
+
trySignalChild(proc, "SIGTERM");
|
|
1171
|
+
}, 1000);
|
|
1172
|
+
toolTimeoutTerminationTimer.unref?.();
|
|
1173
|
+
toolTimeoutHardKillTimer = setTimeout(() => {
|
|
1174
|
+
if (processClosed || lifecycleFinished) return;
|
|
1175
|
+
trySignalChild(proc, "SIGKILL");
|
|
1176
|
+
}, 4000);
|
|
1177
|
+
toolTimeoutHardKillTimer.unref?.();
|
|
1178
|
+
};
|
|
1179
|
+
const armToolTimeout = (event: { toolCallId?: unknown; toolName: string }): void => {
|
|
1180
|
+
const timeoutForTool = effectiveToolTimeoutMs(event.toolName, options.toolTimeoutMs);
|
|
1181
|
+
if (timeoutForTool === undefined) return;
|
|
1182
|
+
const elapsed = Date.now() - startTime;
|
|
1183
|
+
const runRemaining = attemptTimeout ? Math.max(0, attemptTimeout.remainingMs - elapsed) : undefined;
|
|
1184
|
+
if (runRemaining !== undefined && timeoutForTool >= runRemaining) return;
|
|
1185
|
+
const key = toolTimeoutCallKey(event, ++toolTimeoutSequence);
|
|
1186
|
+
const toolName = event.toolName;
|
|
1187
|
+
const timer = setTimeout(() => {
|
|
1188
|
+
removeToolTimeoutKey(key);
|
|
1189
|
+
terminateForToolTimeout(formatToolTimeoutMessage(toolName, timeoutForTool));
|
|
1190
|
+
}, timeoutForTool);
|
|
1191
|
+
timer.unref?.();
|
|
1192
|
+
activeToolTimeouts.set(key, { toolName, timer });
|
|
1193
|
+
const keys = activeToolTimeoutKeysByName.get(toolName) ?? [];
|
|
1194
|
+
keys.push(key);
|
|
1195
|
+
activeToolTimeoutKeysByName.set(toolName, keys);
|
|
1196
|
+
};
|
|
1197
|
+
|
|
1046
1198
|
const stderrTail = createBoundedByteTail();
|
|
1047
1199
|
const failProtocol = (limit: ProtocolOutputLimit): void => {
|
|
1048
1200
|
if (result.protocolError) return;
|
|
@@ -1077,6 +1229,7 @@ async function runSingleAttempt(
|
|
|
1077
1229
|
proc.stderr.on("data", (chunk: Buffer) => {
|
|
1078
1230
|
stderrTail.push(chunk);
|
|
1079
1231
|
stderrReader.push(chunk);
|
|
1232
|
+
shared.orcaProgressTab?.append(chunk.toString("utf-8"));
|
|
1080
1233
|
});
|
|
1081
1234
|
proc.on("exit", () => {
|
|
1082
1235
|
childExited = true;
|
|
@@ -1156,6 +1309,7 @@ async function runSingleAttempt(
|
|
|
1156
1309
|
if (result.timedOut) return;
|
|
1157
1310
|
interruptedByControl = true;
|
|
1158
1311
|
clearTimeoutTimers();
|
|
1312
|
+
clearAllToolTimeouts();
|
|
1159
1313
|
progress.status = "running";
|
|
1160
1314
|
progress.durationMs = Date.now() - startTime;
|
|
1161
1315
|
result.interrupted = true;
|
|
@@ -1201,6 +1355,10 @@ async function runSingleAttempt(
|
|
|
1201
1355
|
};
|
|
1202
1356
|
return result;
|
|
1203
1357
|
}
|
|
1358
|
+
result.error = formatSubagentExtensionConflictError(result.error, {
|
|
1359
|
+
agent: agent.name,
|
|
1360
|
+
ambientExtensionsEnabled: !launchResolvedExtensions.disableAmbientExtensions,
|
|
1361
|
+
});
|
|
1204
1362
|
if (result.error && result.exitCode === 0) {
|
|
1205
1363
|
result.exitCode = 1;
|
|
1206
1364
|
}
|
|
@@ -1378,7 +1536,7 @@ async function runSingleAttempt(
|
|
|
1378
1536
|
/**
|
|
1379
1537
|
* Run a subagent synchronously (blocking until complete)
|
|
1380
1538
|
*/
|
|
1381
|
-
async function
|
|
1539
|
+
async function runSyncCompletionInner(
|
|
1382
1540
|
runtimeCwd: string,
|
|
1383
1541
|
agents: AgentConfig[],
|
|
1384
1542
|
agentName: string,
|
|
@@ -1427,6 +1585,24 @@ async function runSyncCompletion(
|
|
|
1427
1585
|
error: acceptanceErrors.join(" "),
|
|
1428
1586
|
}, options.context));
|
|
1429
1587
|
}
|
|
1588
|
+
const toolTimeout = resolveToolTimeoutMs({
|
|
1589
|
+
callValue: options.toolTimeoutMs,
|
|
1590
|
+
agentValue: agent.defaultToolTimeoutMs,
|
|
1591
|
+
configValue: options.configToolTimeoutMs,
|
|
1592
|
+
envValue: toolTimeoutFromEnv(),
|
|
1593
|
+
});
|
|
1594
|
+
if (toolTimeout.error) {
|
|
1595
|
+
return redactResultPrompt(withRunContext({
|
|
1596
|
+
index: options.index ?? 0,
|
|
1597
|
+
agent: agentName,
|
|
1598
|
+
task,
|
|
1599
|
+
exitCode: 1,
|
|
1600
|
+
messages: [],
|
|
1601
|
+
usage: emptyUsage(),
|
|
1602
|
+
error: toolTimeout.error,
|
|
1603
|
+
}, options.context));
|
|
1604
|
+
}
|
|
1605
|
+
options = { ...options, toolTimeoutMs: toolTimeout.toolTimeoutMs };
|
|
1430
1606
|
const outputModeValidationError = validateFileOnlyOutputMode(options.outputMode, options.outputPath, `Single run (${agentName})`);
|
|
1431
1607
|
if (outputModeValidationError) {
|
|
1432
1608
|
return redactResultPrompt(withRunContext({
|
|
@@ -1531,6 +1707,14 @@ async function runSyncCompletion(
|
|
|
1531
1707
|
}
|
|
1532
1708
|
}
|
|
1533
1709
|
|
|
1710
|
+
const orcaProgressTab = createOrcaProgressTab({
|
|
1711
|
+
cwd: options.cwd ?? runtimeCwd,
|
|
1712
|
+
runId: options.runId,
|
|
1713
|
+
agent: agentName,
|
|
1714
|
+
index: options.index ?? 0,
|
|
1715
|
+
});
|
|
1716
|
+
if (orcaProgressTab) options.onOrcaProgressTabCreated?.(orcaProgressTab);
|
|
1717
|
+
|
|
1534
1718
|
const persistResultMetadata = (target: SingleResult): void => {
|
|
1535
1719
|
persistSingleResultMetadata({
|
|
1536
1720
|
metadataPath: artifactPathsResult?.metadataPath,
|
|
@@ -1585,6 +1769,7 @@ async function runSyncCompletion(
|
|
|
1585
1769
|
outputSnapshot,
|
|
1586
1770
|
originalTask: task,
|
|
1587
1771
|
taskDelivery: taskDeliveryOverride,
|
|
1772
|
+
orcaProgressTab,
|
|
1588
1773
|
});
|
|
1589
1774
|
lastResult = result;
|
|
1590
1775
|
if (startupAttemptIndex === 0) {
|
|
@@ -1813,6 +1998,27 @@ async function runSyncCompletion(
|
|
|
1813
1998
|
return result;
|
|
1814
1999
|
}
|
|
1815
2000
|
|
|
2001
|
+
async function runSyncCompletion(
|
|
2002
|
+
runtimeCwd: string,
|
|
2003
|
+
agents: AgentConfig[],
|
|
2004
|
+
agentName: string,
|
|
2005
|
+
task: string,
|
|
2006
|
+
options: RunSyncOptions,
|
|
2007
|
+
): Promise<SingleResult> {
|
|
2008
|
+
let orcaProgressTab: OrcaProgressTab | undefined;
|
|
2009
|
+
try {
|
|
2010
|
+
const result = await runSyncCompletionInner(runtimeCwd, agents, agentName, task, {
|
|
2011
|
+
...options,
|
|
2012
|
+
onOrcaProgressTabCreated: (tab) => { orcaProgressTab = tab; },
|
|
2013
|
+
});
|
|
2014
|
+
orcaProgressTab?.finish(result.stopped ? "stopped" : result.exitCode === 0 && !result.error ? "completed" : "failed", result.sessionFile);
|
|
2015
|
+
return result;
|
|
2016
|
+
} catch (error) {
|
|
2017
|
+
orcaProgressTab?.finish("failed");
|
|
2018
|
+
throw error;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
2021
|
+
|
|
1816
2022
|
/**
|
|
1817
2023
|
* Runs the authoritative completion pipeline independently from the foreground
|
|
1818
2024
|
* receipt. Detachment is same-runtime only: it does not adopt or daemonize work.
|