pi-subagents 0.35.0 → 0.36.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 +59 -0
- package/README.md +132 -24
- package/agents/advisor.md +73 -0
- package/package.json +8 -12
- package/skills/pi-subagents/SKILL.md +22 -9
- package/src/agents/agents.ts +22 -5
- package/src/api/delegation.ts +125 -0
- package/src/extension/config.ts +7 -1
- package/src/extension/index.ts +50 -38
- package/src/extension/rpc.ts +27 -2
- package/src/extension/schemas.ts +22 -2
- package/src/extension/tool-description.ts +2 -2
- package/src/intercom/intercom-bridge.ts +1 -1
- package/src/intercom/native-supervisor-channel.ts +45 -6
- package/src/intercom/result-intercom.ts +7 -0
- package/src/runs/background/async-execution.ts +34 -4
- package/src/runs/background/async-job-tracker.ts +4 -0
- package/src/runs/background/async-resume.ts +27 -5
- package/src/runs/background/async-status.ts +76 -3
- package/src/runs/background/chain-append.ts +2 -0
- package/src/runs/background/completion-batcher.ts +6 -4
- package/src/runs/background/completion-dedupe.ts +2 -11
- package/src/runs/background/fleet-view.ts +9 -4
- package/src/runs/background/notify.ts +132 -120
- package/src/runs/background/result-watcher.ts +138 -78
- package/src/runs/background/run-status.ts +3 -1
- package/src/runs/background/subagent-runner.ts +225 -43
- package/src/runs/background/subagent-wait.ts +130 -4
- package/src/runs/background/wait-tool.ts +2 -2
- package/src/runs/foreground/chain-execution.ts +176 -111
- package/src/runs/foreground/execution.ts +90 -36
- package/src/runs/foreground/foreground-control.ts +90 -0
- package/src/runs/foreground/subagent-executor.ts +394 -163
- package/src/runs/shared/acceptance.ts +55 -13
- package/src/runs/shared/agent-contract.ts +38 -0
- package/src/runs/shared/child-protocol.ts +1 -1
- package/src/runs/shared/completion-guard.ts +36 -5
- package/src/runs/shared/context-mode.ts +44 -0
- package/src/runs/shared/dynamic-fanout.ts +4 -4
- package/src/runs/shared/long-running-guard.ts +4 -0
- package/src/runs/shared/nested-events.ts +27 -2
- package/src/runs/shared/parallel-handoff.ts +154 -0
- package/src/runs/shared/parallel-utils.ts +6 -0
- package/src/runs/shared/pi-args.ts +23 -14
- package/src/runs/shared/run-history.ts +90 -5
- package/src/runs/shared/structured-output.ts +112 -7
- package/src/runs/shared/subagent-control.ts +4 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +17 -18
- package/src/runs/shared/task-intent.ts +10 -5
- package/src/runs/shared/tool-availability.ts +3 -1
- package/src/runs/shared/tool-budget.ts +11 -5
- package/src/runs/shared/turn-budget.ts +2 -1
- package/src/runs/shared/worktree.ts +63 -14
- package/src/shared/accessible-dir.ts +25 -0
- package/src/shared/artifacts.ts +37 -7
- package/src/shared/atomic-json.ts +14 -42
- package/src/shared/child-transcript.ts +52 -0
- package/src/shared/file-system-retry.ts +47 -0
- package/src/shared/settings.ts +9 -1
- package/src/shared/types.ts +211 -22
- package/src/slash/delegation-adapters.ts +152 -5
- package/src/slash/delegation-json.ts +108 -0
- package/src/slash/delegation-request.ts +182 -36
- package/src/slash/prompt-template-bridge.ts +222 -37
- package/src/slash/selector.ts +147 -0
- package/src/slash/slash-commands.ts +14 -5
- package/src/slash/slash-live-state.ts +2 -2
- package/src/slash/subagents-admin.ts +42 -42
- package/src/tui/fleet-status.ts +362 -0
- package/src/tui/fleet-transcript.ts +472 -0
- package/src/tui/fleet.ts +318 -59
- package/src/tui/render.ts +25 -15
- package/src/watchdog/change-signature.ts +105 -12
- package/src/watchdog/review.ts +7 -2
- package/src/watchdog/runtime.ts +5 -3
- package/src/slash/subagents-editor.ts +0 -86
package/src/shared/types.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import * as os from "node:os";
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import type { Message } from "@earendil-works/pi-ai";
|
|
8
|
+
import type { AgentConfig } from "../agents/agents.ts";
|
|
8
9
|
import type { FSWatcher } from "node:fs";
|
|
9
10
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
10
11
|
import type { ModelScopeConfig } from "../runs/shared/model-scope.ts";
|
|
@@ -201,7 +202,7 @@ export interface ControlEvent {
|
|
|
201
202
|
nestedRunId?: string;
|
|
202
203
|
nestingPath?: NestedRunAddress["path"];
|
|
203
204
|
message: string;
|
|
204
|
-
reason?: "idle" | "completion_guard" | "active_long_running" | "tool_failures" | "time_threshold" | "turn_threshold" | "token_threshold";
|
|
205
|
+
reason?: "idle" | "completion_guard" | "active_long_running" | "tool_failures" | "supervisor_request" | "time_threshold" | "turn_threshold" | "token_threshold";
|
|
205
206
|
turns?: number;
|
|
206
207
|
tokens?: number;
|
|
207
208
|
toolCount?: number;
|
|
@@ -214,6 +215,108 @@ export interface ControlEvent {
|
|
|
214
215
|
|
|
215
216
|
export type SubagentResultStatus = "completed" | "failed" | "paused" | "stopped" | "detached";
|
|
216
217
|
export type SubagentRunMode = "single" | "parallel" | "chain";
|
|
218
|
+
|
|
219
|
+
export interface ParallelHandoffPatch {
|
|
220
|
+
path: string;
|
|
221
|
+
branch: string;
|
|
222
|
+
changed: boolean;
|
|
223
|
+
diffStat: string;
|
|
224
|
+
filesChanged: number;
|
|
225
|
+
insertions: number;
|
|
226
|
+
deletions: number;
|
|
227
|
+
error?: string;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface ParallelHandoffChild {
|
|
231
|
+
index: number;
|
|
232
|
+
taskIndex: number;
|
|
233
|
+
agent: string;
|
|
234
|
+
status: SubagentResultStatus;
|
|
235
|
+
summary: string;
|
|
236
|
+
outputPath?: string;
|
|
237
|
+
structuredOutput?: unknown;
|
|
238
|
+
structuredOutputPath?: string;
|
|
239
|
+
sessionPath?: string;
|
|
240
|
+
patch: ParallelHandoffPatch;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export interface ParallelHandoffCleanupTask {
|
|
244
|
+
index: number;
|
|
245
|
+
path: string;
|
|
246
|
+
branch: string;
|
|
247
|
+
worktreeRemoved: boolean;
|
|
248
|
+
branchRemoved: boolean;
|
|
249
|
+
errors?: string[];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export interface ParallelHandoffGroup {
|
|
253
|
+
stepIndex: number;
|
|
254
|
+
baseCommit: string;
|
|
255
|
+
repoRoot: string;
|
|
256
|
+
children: ParallelHandoffChild[];
|
|
257
|
+
cleanup: {
|
|
258
|
+
state: "complete" | "partial";
|
|
259
|
+
tasks: ParallelHandoffCleanupTask[];
|
|
260
|
+
pruned: boolean;
|
|
261
|
+
errors?: string[];
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export interface ParallelHandoffManifest {
|
|
266
|
+
version: 1;
|
|
267
|
+
runId: string;
|
|
268
|
+
mode: "parallel" | "chain";
|
|
269
|
+
source: "foreground" | "async";
|
|
270
|
+
cwd: string;
|
|
271
|
+
createdAt: number;
|
|
272
|
+
updatedAt: number;
|
|
273
|
+
groups: ParallelHandoffGroup[];
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface ParallelHandoffReference {
|
|
277
|
+
version: 1;
|
|
278
|
+
path: string;
|
|
279
|
+
groupCount: number;
|
|
280
|
+
childCount: number;
|
|
281
|
+
changedPatches: number;
|
|
282
|
+
cleanupState: "complete" | "partial";
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface AgentContract {
|
|
286
|
+
version: 1;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export type ChainGateLayer = "execution" | "acceptance";
|
|
290
|
+
|
|
291
|
+
export type ExecutionProjectionStatus = "completed" | "failed" | "paused" | "stopped" | "detached";
|
|
292
|
+
|
|
293
|
+
export interface ExecutionProjection {
|
|
294
|
+
status: ExecutionProjectionStatus;
|
|
295
|
+
success: boolean;
|
|
296
|
+
exitCode: number;
|
|
297
|
+
error?: string;
|
|
298
|
+
interrupted?: boolean;
|
|
299
|
+
timedOut?: boolean;
|
|
300
|
+
stopped?: boolean;
|
|
301
|
+
detached?: boolean;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export interface ReviewProjection {
|
|
305
|
+
status: "not-requested" | "no-blockers" | "blockers" | "needs-parent-decision";
|
|
306
|
+
findings?: AcceptanceReviewResult["findings"];
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
export interface FileMutationEffect {
|
|
310
|
+
status: "not-requested" | "not-applicable" | "observed" | "missing";
|
|
311
|
+
expected: boolean;
|
|
312
|
+
attempted: boolean;
|
|
313
|
+
message?: string;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export interface EffectsProjection {
|
|
317
|
+
fileMutation?: FileMutationEffect;
|
|
318
|
+
}
|
|
319
|
+
|
|
217
320
|
export const SUBAGENT_LIFECYCLE_ARTIFACT_VERSION = 2;
|
|
218
321
|
export type SubagentLifecycleArtifactVersion = typeof SUBAGENT_LIFECYCLE_ARTIFACT_VERSION;
|
|
219
322
|
|
|
@@ -282,6 +385,7 @@ export interface SteeringNotice {
|
|
|
282
385
|
export interface SteeringRecoveryDescriptor {
|
|
283
386
|
version: 1;
|
|
284
387
|
sourceRunId: string;
|
|
388
|
+
agentContract?: AgentContract;
|
|
285
389
|
agent: string;
|
|
286
390
|
sessionFile?: string;
|
|
287
391
|
cwd: string;
|
|
@@ -303,6 +407,7 @@ export interface SteeringRecoveryDescriptor {
|
|
|
303
407
|
memory?: { scope: "project" | "user"; path: string };
|
|
304
408
|
outputPath?: string;
|
|
305
409
|
outputMode: "inline" | "file-only";
|
|
410
|
+
structuredOutputSchema?: JsonSchemaObject;
|
|
306
411
|
acceptance?: AcceptanceInput;
|
|
307
412
|
controlConfig?: ResolvedControlConfig;
|
|
308
413
|
absoluteDeadlineAt?: number;
|
|
@@ -365,6 +470,7 @@ export interface SubagentResultIntercomPayload {
|
|
|
365
470
|
index?: number;
|
|
366
471
|
artifactPath?: string;
|
|
367
472
|
sessionPath?: string;
|
|
473
|
+
parallelHandoff?: ParallelHandoffReference;
|
|
368
474
|
}
|
|
369
475
|
|
|
370
476
|
// ============================================================================
|
|
@@ -585,6 +691,8 @@ export interface ProtocolOutputLimit {
|
|
|
585
691
|
export interface SingleResult {
|
|
586
692
|
agent: string;
|
|
587
693
|
task: string;
|
|
694
|
+
/** Resolved launch context for this child. */
|
|
695
|
+
context?: "fresh" | "fork";
|
|
588
696
|
exitCode: number;
|
|
589
697
|
detached?: boolean;
|
|
590
698
|
detachedReason?: string;
|
|
@@ -599,6 +707,8 @@ export interface SingleResult {
|
|
|
599
707
|
messages?: Message[];
|
|
600
708
|
usage: Usage;
|
|
601
709
|
model?: string;
|
|
710
|
+
/** Effective thinking level used by this foreground child, when known. */
|
|
711
|
+
thinking?: string;
|
|
602
712
|
attemptedModels?: string[];
|
|
603
713
|
modelAttempts?: ModelAttempt[];
|
|
604
714
|
controlEvents?: ControlEvent[];
|
|
@@ -618,9 +728,14 @@ export interface SingleResult {
|
|
|
618
728
|
outputReference?: SavedOutputReference;
|
|
619
729
|
outputSaveError?: string;
|
|
620
730
|
structuredOutput?: unknown;
|
|
731
|
+
structuredOutputFailed?: boolean;
|
|
621
732
|
structuredOutputPath?: string;
|
|
622
733
|
structuredOutputSchemaPath?: string;
|
|
623
734
|
acceptance?: AcceptanceLedger;
|
|
735
|
+
agentContract?: AgentContract;
|
|
736
|
+
execution?: ExecutionProjection;
|
|
737
|
+
review?: ReviewProjection;
|
|
738
|
+
effects?: EffectsProjection;
|
|
624
739
|
transcriptPath?: string;
|
|
625
740
|
transcriptError?: string;
|
|
626
741
|
children?: NestedRunSummary[];
|
|
@@ -648,7 +763,8 @@ export interface SpawnBudgetSnapshot {
|
|
|
648
763
|
export interface Details {
|
|
649
764
|
mode: SubagentRunMode | "management";
|
|
650
765
|
runId?: string;
|
|
651
|
-
context
|
|
766
|
+
/** Run-level context summary. "mixed" when children resolved to different modes. */
|
|
767
|
+
context?: "fresh" | "fork" | "mixed";
|
|
652
768
|
results: SingleResult[];
|
|
653
769
|
controlEvents?: ControlEvent[];
|
|
654
770
|
steering?: SteerActionResult;
|
|
@@ -683,6 +799,7 @@ export interface Details {
|
|
|
683
799
|
// Aggregated cost across all agents in the run
|
|
684
800
|
totalCost?: CostSummary;
|
|
685
801
|
spawnBudget?: SpawnBudgetSnapshot;
|
|
802
|
+
parallelHandoff?: ParallelHandoffReference;
|
|
686
803
|
}
|
|
687
804
|
|
|
688
805
|
// ============================================================================
|
|
@@ -697,8 +814,11 @@ export interface ArtifactPaths {
|
|
|
697
814
|
metadataPath: string;
|
|
698
815
|
}
|
|
699
816
|
|
|
817
|
+
export type ArtifactDirPreference = "project" | "session" | "temp";
|
|
818
|
+
|
|
700
819
|
export interface ArtifactConfig {
|
|
701
820
|
enabled: boolean;
|
|
821
|
+
dir?: ArtifactDirPreference;
|
|
702
822
|
includeInput: boolean;
|
|
703
823
|
includeOutput: boolean;
|
|
704
824
|
includeJsonl: boolean;
|
|
@@ -811,6 +931,8 @@ export interface AsyncStartedEvent {
|
|
|
811
931
|
lifecycleArtifactVersion?: SubagentLifecycleArtifactVersion;
|
|
812
932
|
id?: string;
|
|
813
933
|
asyncDir?: string;
|
|
934
|
+
/** Parent-resolved launch directory, used as a trusted artifact root while this session is live. */
|
|
935
|
+
cwd?: string;
|
|
814
936
|
pid?: number;
|
|
815
937
|
sessionId?: string;
|
|
816
938
|
mode?: SubagentRunMode;
|
|
@@ -867,6 +989,8 @@ export interface AsyncStatus {
|
|
|
867
989
|
workflowGraph?: WorkflowGraphSnapshot;
|
|
868
990
|
steps?: Array<{
|
|
869
991
|
agent: string;
|
|
992
|
+
/** Resolved launch context for this child step. */
|
|
993
|
+
context?: "fresh" | "fork";
|
|
870
994
|
phase?: string;
|
|
871
995
|
label?: string;
|
|
872
996
|
outputName?: string;
|
|
@@ -910,6 +1034,10 @@ export interface AsyncStatus {
|
|
|
910
1034
|
structuredOutputPath?: string;
|
|
911
1035
|
structuredOutputSchemaPath?: string;
|
|
912
1036
|
acceptance?: AcceptanceLedger;
|
|
1037
|
+
agentContract?: AgentContract;
|
|
1038
|
+
execution?: ExecutionProjection;
|
|
1039
|
+
review?: ReviewProjection;
|
|
1040
|
+
effects?: EffectsProjection;
|
|
913
1041
|
watchdog?: ChildWatchdogProgress;
|
|
914
1042
|
}>;
|
|
915
1043
|
sessionDir?: string;
|
|
@@ -918,6 +1046,7 @@ export interface AsyncStatus {
|
|
|
918
1046
|
totalCost?: CostSummary;
|
|
919
1047
|
sessionFile?: string;
|
|
920
1048
|
outputs?: ChainOutputMap;
|
|
1049
|
+
parallelHandoff?: ParallelHandoffReference;
|
|
921
1050
|
}
|
|
922
1051
|
|
|
923
1052
|
export type AsyncJobStep = NonNullable<AsyncStatus["steps"]>[number] & {
|
|
@@ -927,7 +1056,11 @@ export type AsyncJobStep = NonNullable<AsyncStatus["steps"]>[number] & {
|
|
|
927
1056
|
export interface AsyncJobState {
|
|
928
1057
|
asyncId: string;
|
|
929
1058
|
asyncDir: string;
|
|
1059
|
+
/** Parent-resolved launch directory retained for trusted live artifact lookup. */
|
|
1060
|
+
cwd?: string;
|
|
930
1061
|
status: "queued" | "running" | "complete" | "failed" | "paused" | "stopped";
|
|
1062
|
+
/** Short caller-facing task/goal shown in fleet surfaces when available. */
|
|
1063
|
+
description?: string;
|
|
931
1064
|
pid?: number;
|
|
932
1065
|
sessionId?: string;
|
|
933
1066
|
activityState?: ActivityState;
|
|
@@ -939,6 +1072,8 @@ export interface AsyncJobState {
|
|
|
939
1072
|
toolCount?: number;
|
|
940
1073
|
steering?: SteeringStatus;
|
|
941
1074
|
mode?: SubagentRunMode;
|
|
1075
|
+
/** Run-level context summary derived from step contexts. */
|
|
1076
|
+
context?: "fresh" | "fork" | "mixed";
|
|
942
1077
|
agents?: string[];
|
|
943
1078
|
currentStep?: number;
|
|
944
1079
|
chainStepCount?: number;
|
|
@@ -972,8 +1107,17 @@ export interface AsyncJobState {
|
|
|
972
1107
|
export interface ForegroundResumeChild {
|
|
973
1108
|
agent: string;
|
|
974
1109
|
index: number;
|
|
1110
|
+
context?: "fresh" | "fork";
|
|
975
1111
|
sessionFile?: string;
|
|
976
1112
|
status: SubagentResultStatus;
|
|
1113
|
+
activityState?: ActivityState;
|
|
1114
|
+
lastActivityAt?: number;
|
|
1115
|
+
currentTool?: string;
|
|
1116
|
+
currentToolStartedAt?: number;
|
|
1117
|
+
currentPath?: string;
|
|
1118
|
+
turnCount?: number;
|
|
1119
|
+
tokens?: number;
|
|
1120
|
+
toolCount?: number;
|
|
977
1121
|
exitCode?: number;
|
|
978
1122
|
error?: string;
|
|
979
1123
|
finalOutput?: string;
|
|
@@ -985,6 +1129,10 @@ export interface ForegroundResumeChild {
|
|
|
985
1129
|
transcriptError?: string;
|
|
986
1130
|
detachedReason?: string;
|
|
987
1131
|
acceptance?: AcceptanceLedger;
|
|
1132
|
+
agentContract?: AgentContract;
|
|
1133
|
+
execution?: ExecutionProjection;
|
|
1134
|
+
review?: ReviewProjection;
|
|
1135
|
+
effects?: EffectsProjection;
|
|
988
1136
|
updatedAt?: number;
|
|
989
1137
|
}
|
|
990
1138
|
|
|
@@ -998,9 +1146,55 @@ export interface ForegroundResumeRun {
|
|
|
998
1146
|
children: ForegroundResumeChild[];
|
|
999
1147
|
}
|
|
1000
1148
|
|
|
1149
|
+
export interface ForegroundChildControl {
|
|
1150
|
+
index: number;
|
|
1151
|
+
agent: string;
|
|
1152
|
+
description?: string;
|
|
1153
|
+
startedAt: number;
|
|
1154
|
+
updatedAt: number;
|
|
1155
|
+
currentActivityState?: ActivityState;
|
|
1156
|
+
lastActivityAt?: number;
|
|
1157
|
+
currentTool?: string;
|
|
1158
|
+
currentToolStartedAt?: number;
|
|
1159
|
+
currentPath?: string;
|
|
1160
|
+
turnCount?: number;
|
|
1161
|
+
tokens?: number;
|
|
1162
|
+
toolCount?: number;
|
|
1163
|
+
interrupt?: () => boolean;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
export interface ForegroundRunControl {
|
|
1167
|
+
runId: string;
|
|
1168
|
+
mode: SubagentRunMode;
|
|
1169
|
+
startedAt: number;
|
|
1170
|
+
updatedAt: number;
|
|
1171
|
+
/** Effective working directory used to resolve live transcript artifacts. */
|
|
1172
|
+
cwd?: string;
|
|
1173
|
+
currentAgent?: string;
|
|
1174
|
+
currentIndex?: number;
|
|
1175
|
+
/** Short caller-facing task/goal shown in fleet surfaces when available. */
|
|
1176
|
+
description?: string;
|
|
1177
|
+
currentActivityState?: ActivityState;
|
|
1178
|
+
lastActivityAt?: number;
|
|
1179
|
+
currentTool?: string;
|
|
1180
|
+
currentToolStartedAt?: number;
|
|
1181
|
+
currentPath?: string;
|
|
1182
|
+
turnCount?: number;
|
|
1183
|
+
tokens?: number;
|
|
1184
|
+
toolCount?: number;
|
|
1185
|
+
/** Independently tracked children for foreground parallel work and fleet inspection. */
|
|
1186
|
+
activeChildren?: Map<number, ForegroundChildControl>;
|
|
1187
|
+
nestedRoute?: NestedRouteInfo;
|
|
1188
|
+
nestedChildren?: NestedRunSummary[];
|
|
1189
|
+
interrupt?: () => boolean;
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1001
1192
|
export interface SubagentState {
|
|
1002
1193
|
baseCwd: string;
|
|
1003
1194
|
currentSessionId: string | null;
|
|
1195
|
+
/** Runtime-owned artifact resolution inputs used by Fleet transcript targeting. */
|
|
1196
|
+
artifactDirPreference?: ArtifactDirPreference;
|
|
1197
|
+
parentSessionFile?: string | null;
|
|
1004
1198
|
subagentInProgress?: boolean;
|
|
1005
1199
|
subagentSpawns?: {
|
|
1006
1200
|
sessionId: string | null;
|
|
@@ -1012,26 +1206,10 @@ export interface SubagentState {
|
|
|
1012
1206
|
asyncJobs: Map<string, AsyncJobState>;
|
|
1013
1207
|
/** Current-session active and recent async runs for the native fleet inspector. */
|
|
1014
1208
|
fleetJobs?: Map<string, AsyncJobState>;
|
|
1209
|
+
/** Suppress dynamic status widgets while the fleet overlay owns the viewport. */
|
|
1210
|
+
fleetInspectorOpen?: boolean;
|
|
1015
1211
|
foregroundRuns?: Map<string, ForegroundResumeRun>;
|
|
1016
|
-
foregroundControls: Map<string,
|
|
1017
|
-
runId: string;
|
|
1018
|
-
mode: SubagentRunMode;
|
|
1019
|
-
startedAt: number;
|
|
1020
|
-
updatedAt: number;
|
|
1021
|
-
currentAgent?: string;
|
|
1022
|
-
currentIndex?: number;
|
|
1023
|
-
currentActivityState?: ActivityState;
|
|
1024
|
-
lastActivityAt?: number;
|
|
1025
|
-
currentTool?: string;
|
|
1026
|
-
currentToolStartedAt?: number;
|
|
1027
|
-
currentPath?: string;
|
|
1028
|
-
turnCount?: number;
|
|
1029
|
-
tokens?: number;
|
|
1030
|
-
toolCount?: number;
|
|
1031
|
-
nestedRoute?: NestedRouteInfo;
|
|
1032
|
-
nestedChildren?: NestedRunSummary[];
|
|
1033
|
-
interrupt?: () => boolean;
|
|
1034
|
-
}>;
|
|
1212
|
+
foregroundControls: Map<string, ForegroundRunControl>;
|
|
1035
1213
|
lastForegroundControlId: string | null;
|
|
1036
1214
|
pendingForegroundControlNotices?: Map<string, ReturnType<typeof setTimeout>>;
|
|
1037
1215
|
cleanupTimers: Map<string, ReturnType<typeof setTimeout>>;
|
|
@@ -1088,13 +1266,18 @@ export const SUBAGENT_RESULT_INTERCOM_DELIVERY_EVENT = "subagent:result-intercom
|
|
|
1088
1266
|
export interface RunSyncOptions {
|
|
1089
1267
|
/** Session id of the direct parent session for permission-system ask forwarding. */
|
|
1090
1268
|
parentSessionId?: string;
|
|
1269
|
+
/** Resolved launch context for this child. */
|
|
1270
|
+
context?: "fresh" | "fork";
|
|
1091
1271
|
cwd?: string;
|
|
1092
1272
|
signal?: AbortSignal;
|
|
1093
1273
|
interruptSignal?: AbortSignal;
|
|
1094
1274
|
timeoutMs?: number;
|
|
1095
1275
|
deadlineAt?: number;
|
|
1096
1276
|
turnBudget?: ResolvedTurnBudget;
|
|
1277
|
+
/** Enforce maxTurns + graceTurns as a hard model-turn boundary. */
|
|
1278
|
+
enforceHardTurnLimit?: boolean;
|
|
1097
1279
|
toolBudget?: ResolvedToolBudget;
|
|
1280
|
+
allowZeroToolBudget?: boolean;
|
|
1098
1281
|
allowIntercomDetach?: boolean;
|
|
1099
1282
|
intercomEvents?: IntercomEventBus;
|
|
1100
1283
|
onUpdate?: (r: import("@earendil-works/pi-agent-core").AgentToolResult<Details>) => void;
|
|
@@ -1134,6 +1317,7 @@ export interface RunSyncOptions {
|
|
|
1134
1317
|
schemaPath: string;
|
|
1135
1318
|
outputPath: string;
|
|
1136
1319
|
};
|
|
1320
|
+
agentContract?: AgentContract;
|
|
1137
1321
|
acceptance?: AcceptanceInput;
|
|
1138
1322
|
acceptanceContext?: {
|
|
1139
1323
|
mode?: SubagentRunMode;
|
|
@@ -1178,7 +1362,9 @@ export interface ScheduledRunsConfig {
|
|
|
1178
1362
|
|
|
1179
1363
|
export interface ExtensionConfig {
|
|
1180
1364
|
asyncByDefault?: boolean;
|
|
1181
|
-
/** Show the
|
|
1365
|
+
/** Show the Claude Code-style navigable fleet below the editor. Defaults to true. */
|
|
1366
|
+
fleetView?: boolean;
|
|
1367
|
+
/** Show the legacy above-editor async runs widget. Defaults to true only when fleetView is disabled. */
|
|
1182
1368
|
asyncWidget?: boolean;
|
|
1183
1369
|
/** Tool description variant registered for the parent-facing subagent tool. Defaults to full. */
|
|
1184
1370
|
toolDescriptionMode?: ToolDescriptionMode;
|
|
@@ -1200,6 +1386,8 @@ export interface ExtensionConfig {
|
|
|
1200
1386
|
worktreeSetupHook?: string;
|
|
1201
1387
|
worktreeSetupHookTimeoutMs?: number;
|
|
1202
1388
|
worktreeBaseDir?: string;
|
|
1389
|
+
/** Where to store subagent artifact files. Defaults to "project" (cwd/.pi-subagents). Set to "session" for pi session dir, or "temp" for OS temp. */
|
|
1390
|
+
artifactDir?: ArtifactDirPreference;
|
|
1203
1391
|
intercomBridge?: IntercomBridgeConfig;
|
|
1204
1392
|
proactiveSkillSubagents?: ProactiveSkillSubagentsConfig | false;
|
|
1205
1393
|
scheduledRuns?: ScheduledRunsConfig;
|
|
@@ -1216,6 +1404,7 @@ export const DEFAULT_MAX_OUTPUT: Required<MaxOutputConfig> = {
|
|
|
1216
1404
|
|
|
1217
1405
|
export const DEFAULT_ARTIFACT_CONFIG: ArtifactConfig = {
|
|
1218
1406
|
enabled: true,
|
|
1407
|
+
dir: "project",
|
|
1219
1408
|
includeInput: true,
|
|
1220
1409
|
includeOutput: true,
|
|
1221
1410
|
includeJsonl: false,
|
|
@@ -1,12 +1,23 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SUBAGENT_DELEGATION_PROTOCOL_VERSION,
|
|
3
|
+
SUBAGENT_DELEGATION_V2_PROTOCOL_VERSION,
|
|
3
4
|
type SubagentDelegationAcceptanceResult,
|
|
5
|
+
type SubagentDelegationEffectsResult,
|
|
6
|
+
type SubagentDelegationExecutionResult,
|
|
4
7
|
type SubagentDelegationRequest,
|
|
5
8
|
type SubagentDelegationResponse,
|
|
9
|
+
type SubagentDelegationReviewResult,
|
|
6
10
|
type SubagentDelegationStatus,
|
|
7
11
|
type SubagentDelegationUpdate,
|
|
12
|
+
type SubagentDelegationV2Request,
|
|
13
|
+
type SubagentDelegationV2Response,
|
|
14
|
+
type SubagentDelegationV2Thinking,
|
|
15
|
+
type SubagentDelegationV2Value,
|
|
16
|
+
type SubagentDelegationV2Update,
|
|
8
17
|
} from "../api/delegation.ts";
|
|
9
|
-
import type { AcceptanceInput, ToolBudgetConfig, TurnBudgetConfig } from "../shared/types.ts";
|
|
18
|
+
import type { AcceptanceInput, AgentContract, EffectsProjection, ExecutionProjection, JsonSchemaObject, ReviewProjection, ToolBudgetConfig, TurnBudgetConfig, Usage } from "../shared/types.ts";
|
|
19
|
+
import { isAgentContractV1 } from "../runs/shared/agent-contract.ts";
|
|
20
|
+
import { cloneJsonWithinByteLimit } from "./delegation-json.ts";
|
|
10
21
|
|
|
11
22
|
export interface PromptTemplateDelegationTask {
|
|
12
23
|
agent: string;
|
|
@@ -86,15 +97,22 @@ export interface PromptTemplateBridgeResult {
|
|
|
86
97
|
exitCode?: number;
|
|
87
98
|
error?: string;
|
|
88
99
|
model?: string;
|
|
100
|
+
thinking?: string;
|
|
101
|
+
structuredOutput?: unknown;
|
|
89
102
|
interrupted?: boolean;
|
|
90
103
|
timedOut?: boolean;
|
|
91
104
|
stopped?: boolean;
|
|
92
105
|
turnBudgetExceeded?: boolean;
|
|
93
106
|
toolBudgetBlocked?: boolean;
|
|
107
|
+
structuredOutputFailed?: boolean;
|
|
94
108
|
savedOutputPath?: string;
|
|
95
109
|
sessionFile?: string;
|
|
110
|
+
agentContract?: AgentContract;
|
|
111
|
+
execution?: ExecutionProjection;
|
|
96
112
|
acceptance?: SubagentDelegationAcceptanceResult;
|
|
97
|
-
|
|
113
|
+
review?: ReviewProjection;
|
|
114
|
+
effects?: EffectsProjection;
|
|
115
|
+
usage?: Usage;
|
|
98
116
|
progressSummary?: { toolCount?: number; durationMs?: number; tokens?: number };
|
|
99
117
|
skillsWarning?: string;
|
|
100
118
|
outputSaveError?: string;
|
|
@@ -125,12 +143,20 @@ export interface DelegatedSubagentExecutionParams {
|
|
|
125
143
|
worktree?: boolean;
|
|
126
144
|
timeoutMs?: number;
|
|
127
145
|
turnBudget?: TurnBudgetConfig;
|
|
146
|
+
/** Internal-only strict turn-boundary enforcement for versioned foreground delegation. */
|
|
147
|
+
enforceHardTurnLimit?: boolean;
|
|
128
148
|
toolBudget?: ToolBudgetConfig;
|
|
129
149
|
skill?: string | string[] | boolean;
|
|
130
150
|
output?: string | boolean;
|
|
131
151
|
outputMode?: "inline" | "file-only";
|
|
152
|
+
outputSchema?: JsonSchemaObject;
|
|
153
|
+
agentContract?: AgentContract;
|
|
132
154
|
acceptance?: AcceptanceInput;
|
|
133
155
|
artifacts?: boolean;
|
|
156
|
+
/** Internal-only thinking override accepted by executeDelegated. */
|
|
157
|
+
delegatedThinkingOverride?: SubagentDelegationV2Thinking;
|
|
158
|
+
/** Internal-only V2 capability accepted and stripped by executeDelegated. */
|
|
159
|
+
delegatedAllowZeroToolBudget?: true;
|
|
134
160
|
async: false;
|
|
135
161
|
foregroundOnly: true;
|
|
136
162
|
clarify: false;
|
|
@@ -175,8 +201,8 @@ export function parsePromptTemplateRequest(data: unknown): PromptTemplateDelegat
|
|
|
175
201
|
const fallbackTask = tasks[0];
|
|
176
202
|
return {
|
|
177
203
|
requestId: value.requestId,
|
|
178
|
-
agent: hasSingle ? value.agent : fallbackTask!.agent,
|
|
179
|
-
task: hasSingle ? value.task : fallbackTask!.task,
|
|
204
|
+
agent: hasSingle ? value.agent! : fallbackTask!.agent,
|
|
205
|
+
task: hasSingle ? value.task! : fallbackTask!.task,
|
|
180
206
|
...(tasks.length > 0 ? { tasks } : {}),
|
|
181
207
|
context: value.context,
|
|
182
208
|
model: value.model,
|
|
@@ -343,10 +369,13 @@ export function toSubagentDelegationExecutionParams(request: SubagentDelegationR
|
|
|
343
369
|
model: request.model,
|
|
344
370
|
timeoutMs: request.timeoutMs,
|
|
345
371
|
turnBudget: request.turnBudget,
|
|
372
|
+
enforceHardTurnLimit: true,
|
|
346
373
|
toolBudget: request.toolBudget,
|
|
347
374
|
skill: request.skill,
|
|
348
375
|
output: request.output,
|
|
349
376
|
outputMode: request.outputMode,
|
|
377
|
+
outputSchema: request.outputSchema,
|
|
378
|
+
agentContract: request.agentContract,
|
|
350
379
|
acceptance: request.acceptance,
|
|
351
380
|
artifacts: request.artifacts,
|
|
352
381
|
async: false,
|
|
@@ -355,6 +384,30 @@ export function toSubagentDelegationExecutionParams(request: SubagentDelegationR
|
|
|
355
384
|
};
|
|
356
385
|
}
|
|
357
386
|
|
|
387
|
+
export function toSubagentDelegationV2ExecutionParams(request: SubagentDelegationV2Request): DelegatedSubagentExecutionParams {
|
|
388
|
+
return {
|
|
389
|
+
agent: request.agent,
|
|
390
|
+
task: request.task,
|
|
391
|
+
context: request.context,
|
|
392
|
+
cwd: request.cwd,
|
|
393
|
+
model: request.model,
|
|
394
|
+
timeoutMs: request.timeoutMs,
|
|
395
|
+
turnBudget: request.turnBudget,
|
|
396
|
+
enforceHardTurnLimit: true,
|
|
397
|
+
toolBudget: request.toolBudget,
|
|
398
|
+
skill: request.skill,
|
|
399
|
+
output: false,
|
|
400
|
+
...(request.result.kind === "structured" ? { outputSchema: request.result.schema } : {}),
|
|
401
|
+
acceptance: false,
|
|
402
|
+
artifacts: request.artifacts,
|
|
403
|
+
delegatedThinkingOverride: request.thinking,
|
|
404
|
+
delegatedAllowZeroToolBudget: true,
|
|
405
|
+
async: false,
|
|
406
|
+
foregroundOnly: true,
|
|
407
|
+
clarify: false,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
358
411
|
export function toSubagentDelegationUpdate(requestId: string, result: PromptTemplateBridgeResult): SubagentDelegationUpdate | undefined {
|
|
359
412
|
const legacy = toDelegationUpdate(requestId, result);
|
|
360
413
|
if (!legacy) return undefined;
|
|
@@ -373,6 +426,29 @@ export function toSubagentDelegationUpdate(requestId: string, result: PromptTemp
|
|
|
373
426
|
};
|
|
374
427
|
}
|
|
375
428
|
|
|
429
|
+
export function toSubagentDelegationV2Update(
|
|
430
|
+
request: SubagentDelegationV2Request,
|
|
431
|
+
result: PromptTemplateBridgeResult,
|
|
432
|
+
): SubagentDelegationV2Update | undefined {
|
|
433
|
+
const legacy = toDelegationUpdate(request.requestId, result);
|
|
434
|
+
if (!legacy) return undefined;
|
|
435
|
+
return {
|
|
436
|
+
version: SUBAGENT_DELEGATION_V2_PROTOCOL_VERSION,
|
|
437
|
+
requestId: request.requestId,
|
|
438
|
+
ownerRunId: request.ownerRunId,
|
|
439
|
+
nodeId: request.nodeId,
|
|
440
|
+
...(legacy.currentTool ? { currentTool: legacy.currentTool } : {}),
|
|
441
|
+
...(legacy.currentToolArgs ? { currentToolArgs: legacy.currentToolArgs } : {}),
|
|
442
|
+
...(legacy.recentOutput ? { recentOutput: legacy.recentOutput } : {}),
|
|
443
|
+
...(legacy.recentOutputLines ? { recentOutputLines: legacy.recentOutputLines } : {}),
|
|
444
|
+
...(legacy.recentTools ? { recentTools: legacy.recentTools } : {}),
|
|
445
|
+
...(legacy.model ? { model: legacy.model } : {}),
|
|
446
|
+
...(typeof legacy.toolCount === "number" ? { toolCount: legacy.toolCount } : {}),
|
|
447
|
+
...(typeof legacy.durationMs === "number" ? { durationMs: legacy.durationMs } : {}),
|
|
448
|
+
...(typeof legacy.tokens === "number" ? { tokens: legacy.tokens } : {}),
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
376
452
|
function resolveSubagentDelegationStatus(
|
|
377
453
|
result: PromptTemplateBridgeResult,
|
|
378
454
|
aborted: boolean,
|
|
@@ -381,9 +457,10 @@ function resolveSubagentDelegationStatus(
|
|
|
381
457
|
const child = result.details?.results?.[0];
|
|
382
458
|
if (!child) return "failed";
|
|
383
459
|
if (result.details?.timedOut || child.timedOut) return "timed_out";
|
|
460
|
+
if (child?.structuredOutputFailed) return "structured_output_failed";
|
|
384
461
|
if (child?.turnBudgetExceeded) return "turn_budget_exhausted";
|
|
385
462
|
if (child?.toolBudgetBlocked) return "tool_budget_exhausted";
|
|
386
|
-
if (child?.acceptance?.status === "rejected" && child.acceptance.explicit) return "acceptance_failed";
|
|
463
|
+
if (!isAgentContractV1(child.agentContract) && child?.acceptance?.status === "rejected" && child.acceptance.explicit) return "acceptance_failed";
|
|
387
464
|
if (result.details?.stopped || child?.stopped || child?.interrupted) return "interrupted";
|
|
388
465
|
if (result.isError || child?.error || (typeof child?.exitCode === "number" && child.exitCode !== 0)) return "failed";
|
|
389
466
|
return "completed";
|
|
@@ -410,10 +487,13 @@ export function toSubagentDelegationResponse(
|
|
|
410
487
|
...(child?.agent ? { agent: child.agent } : {}),
|
|
411
488
|
...(child?.model ? { model: child.model } : {}),
|
|
412
489
|
...(typeof child?.exitCode === "number" ? { exitCode: child.exitCode } : {}),
|
|
490
|
+
...(child?.execution ? { execution: child.execution as SubagentDelegationExecutionResult } : {}),
|
|
413
491
|
...(child?.finalOutput ? { output: child.finalOutput } : {}),
|
|
414
492
|
...(child?.savedOutputPath ? { outputPath: child.savedOutputPath } : {}),
|
|
415
493
|
...(child?.sessionFile ? { sessionFile: child.sessionFile } : {}),
|
|
416
494
|
...(child?.acceptance ? { acceptance: { status: child.acceptance.status, explicit: child.acceptance.explicit } } : {}),
|
|
495
|
+
...(child?.review ? { review: child.review as SubagentDelegationReviewResult } : {}),
|
|
496
|
+
...(child?.effects ? { effects: child.effects as SubagentDelegationEffectsResult } : {}),
|
|
417
497
|
...(typeof child?.usage?.turns === "number" ? { turns: child.usage.turns } : {}),
|
|
418
498
|
...(typeof progress?.toolCount === "number" ? { toolCount: progress.toolCount } : {}),
|
|
419
499
|
...(typeof progress?.durationMs === "number" ? { durationMs: progress.durationMs } : {}),
|
|
@@ -422,6 +502,73 @@ export function toSubagentDelegationResponse(
|
|
|
422
502
|
};
|
|
423
503
|
}
|
|
424
504
|
|
|
505
|
+
const MAX_V2_RESULT_BYTES = 1024 * 1024;
|
|
506
|
+
|
|
507
|
+
export function toSubagentDelegationV2Response(
|
|
508
|
+
request: SubagentDelegationV2Request,
|
|
509
|
+
result: PromptTemplateBridgeResult,
|
|
510
|
+
aborted: boolean,
|
|
511
|
+
): SubagentDelegationV2Response {
|
|
512
|
+
const child = result.details?.results?.[0];
|
|
513
|
+
const progress = child?.progressSummary ?? result.details?.progress?.[0];
|
|
514
|
+
let status = resolveSubagentDelegationStatus(result, aborted);
|
|
515
|
+
let error = child?.error ?? (status === "failed" ? firstTextContent(result.content) : undefined);
|
|
516
|
+
let projectedResult: SubagentDelegationV2Value | undefined;
|
|
517
|
+
if (status === "completed") {
|
|
518
|
+
if (request.result.kind === "text") {
|
|
519
|
+
if (typeof child?.finalOutput !== "string") {
|
|
520
|
+
status = "failed";
|
|
521
|
+
error = "Delegated subagent did not capture a text result.";
|
|
522
|
+
} else if (Buffer.byteLength(child.finalOutput, "utf8") > MAX_V2_RESULT_BYTES) {
|
|
523
|
+
status = "failed";
|
|
524
|
+
error = "Delegated text result exceeds 1 MiB when UTF-8 encoded.";
|
|
525
|
+
} else {
|
|
526
|
+
projectedResult = { kind: "text", text: child.finalOutput };
|
|
527
|
+
}
|
|
528
|
+
} else if (child?.structuredOutput === undefined) {
|
|
529
|
+
status = "failed";
|
|
530
|
+
error = "Delegated subagent did not capture the requested structured result.";
|
|
531
|
+
} else {
|
|
532
|
+
const inspected = cloneJsonWithinByteLimit(child.structuredOutput, MAX_V2_RESULT_BYTES);
|
|
533
|
+
if (!inspected.ok) {
|
|
534
|
+
status = "failed";
|
|
535
|
+
error = inspected.reason === "too_large"
|
|
536
|
+
? "Delegated structured result exceeds 1 MiB when encoded."
|
|
537
|
+
: "Delegated structured result is not plain JSON data.";
|
|
538
|
+
} else {
|
|
539
|
+
projectedResult = { kind: "structured", value: inspected.value };
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const usage = child?.usage;
|
|
544
|
+
return {
|
|
545
|
+
version: SUBAGENT_DELEGATION_V2_PROTOCOL_VERSION,
|
|
546
|
+
requestId: request.requestId,
|
|
547
|
+
ownerRunId: request.ownerRunId,
|
|
548
|
+
nodeId: request.nodeId,
|
|
549
|
+
status,
|
|
550
|
+
...(error ? { error } : {}),
|
|
551
|
+
...(result.details?.runId ? { runId: result.details.runId } : {}),
|
|
552
|
+
...(child?.agent ? { agent: child.agent } : {}),
|
|
553
|
+
...(child?.model ? { model: child.model } : {}),
|
|
554
|
+
...(child?.thinking ? { thinking: child.thinking } : {}),
|
|
555
|
+
...(typeof child?.exitCode === "number" ? { exitCode: child.exitCode } : {}),
|
|
556
|
+
...(projectedResult ? { result: projectedResult } : {}),
|
|
557
|
+
...(usage ? {
|
|
558
|
+
usage: {
|
|
559
|
+
input: usage.input,
|
|
560
|
+
output: usage.output,
|
|
561
|
+
cacheRead: usage.cacheRead,
|
|
562
|
+
cacheWrite: usage.cacheWrite,
|
|
563
|
+
cost: usage.cost,
|
|
564
|
+
turns: usage.turns,
|
|
565
|
+
toolCalls: progress?.toolCount ?? 0,
|
|
566
|
+
durationMs: progress?.durationMs ?? 0,
|
|
567
|
+
},
|
|
568
|
+
} : {}),
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
425
572
|
export function toPromptTemplateResponse(
|
|
426
573
|
request: PromptTemplateDelegationRequest,
|
|
427
574
|
result: PromptTemplateBridgeResult,
|