pi-subagents 0.58.0 → 0.59.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 +65 -0
- package/docs/agents.md +5 -3
- package/docs/configuration.md +4 -4
- package/docs/extension-api.md +1 -1
- package/docs/models.md +24 -1
- package/docs/observability.md +1 -1
- package/docs/tool-reference.md +89 -4
- package/docs/workflows.md +93 -2
- package/package.json +3 -1
- package/prompts/review-loop.md +2 -2
- package/skills/council-mode/SKILL.md +1 -1
- package/skills/pi-subagents/SKILL.md +1 -1
- package/skills/pi-subagents/references/execution-controls.md +5 -1
- package/skills/pi-subagents/references/management-authoring-rpc.md +1 -2
- package/skills/pi-subagents/references/prompting-and-roles.md +24 -3
- package/src/agents/agent-management.ts +5 -17
- package/src/agents/agent-serializer.ts +4 -2
- package/src/agents/agents.ts +67 -26
- package/src/agents/runtime-agent-registry.ts +9 -16
- package/src/api/background-work.ts +5 -1
- package/src/api/delegation.ts +0 -7
- package/src/api/preflight.ts +6 -9
- package/src/extension/fanout-child.ts +5 -3
- package/src/extension/index.ts +51 -23
- package/src/extension/public-execution.ts +15 -2
- package/src/extension/schemas.ts +35 -10
- package/src/extension/tool-description.ts +18 -3
- package/src/intercom/result-intercom.ts +2 -0
- package/src/profiles/profiles.ts +5 -6
- package/src/runs/background/active-async-capacity.ts +2 -2
- package/src/runs/background/async-execution.ts +50 -35
- package/src/runs/background/async-job-tracker.ts +14 -12
- package/src/runs/background/async-resume.ts +23 -25
- package/src/runs/background/async-status-snapshot.ts +23 -261
- package/src/runs/background/async-status.ts +66 -7
- package/src/runs/background/chain-append.ts +6 -3
- package/src/runs/background/chain-root-attachment.ts +60 -8
- package/src/runs/background/fleet-view.ts +21 -11
- package/src/runs/background/notify.ts +158 -6
- package/src/runs/background/result-files.ts +2 -1
- package/src/runs/background/result-watcher.ts +2 -0
- package/src/runs/background/resume-guidance.ts +1 -1
- package/src/runs/background/retained-children.ts +1 -1
- package/src/runs/background/run-status.ts +18 -8
- package/src/runs/background/scheduled-runs.ts +86 -7
- package/src/runs/background/stale-run-reconciler.ts +10 -4
- package/src/runs/background/steering.ts +4 -14
- package/src/runs/background/subagent-runner.ts +346 -357
- package/src/runs/background/subagent-wait.ts +58 -10
- package/src/runs/background/terminal-run-index.ts +1 -1
- package/src/runs/background/wait-completions.ts +22 -1
- package/src/runs/background/wait-config.ts +23 -9
- package/src/runs/background/wait-tool.ts +9 -2
- package/src/runs/foreground/async-steering-action.ts +2 -2
- package/src/runs/foreground/execution.ts +114 -120
- package/src/runs/foreground/foreground-control.ts +3 -0
- package/src/runs/foreground/foreground-history.ts +1 -0
- package/src/runs/foreground/subagent-executor.ts +478 -239
- package/src/runs/foreground/workflow-detach-reconcile.ts +99 -200
- package/src/runs/shared/abort-recovery.ts +119 -0
- package/src/runs/shared/async-status-projection.ts +463 -0
- package/src/runs/shared/child-identity.ts +19 -4
- package/src/runs/shared/child-launch-plan.ts +151 -0
- package/src/runs/shared/completion-evidence.ts +89 -0
- package/src/runs/shared/completion-guard.ts +1 -1
- package/src/runs/shared/dynamic-fanout.ts +2 -2
- package/src/runs/shared/host-step-status.ts +230 -0
- package/src/runs/shared/lane-metadata.ts +105 -0
- package/src/runs/shared/mcp-config-sources.ts +42 -6
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +93 -143
- package/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
- package/src/runs/shared/model-fallback.ts +9 -2
- package/src/runs/shared/nested-events.ts +6 -2
- package/src/runs/shared/nested-render.ts +7 -3
- package/src/runs/shared/parallel-handoff.ts +419 -7
- package/src/runs/shared/parallel-utils.ts +7 -0
- package/src/runs/shared/pi-args.ts +20 -2
- package/src/runs/shared/single-output.ts +27 -4
- package/src/runs/shared/subagent-prompt-runtime.ts +13 -4
- package/src/runs/shared/worktree-cleanup-plan.ts +847 -0
- package/src/runs/shared/worktree.ts +18 -0
- package/src/shared/child-session-name.ts +46 -0
- package/src/shared/extension-context.ts +24 -0
- package/src/shared/formatters.ts +5 -2
- package/src/shared/launch-contract.ts +1 -1
- package/src/shared/settings.ts +9 -103
- package/src/shared/types.ts +198 -29
- package/src/shared/utils.ts +35 -55
- package/src/slash/delegation-adapters.ts +1 -8
- package/src/slash/delegation-request.ts +0 -4
- package/src/slash/slash-bridge.ts +1 -2
- package/src/slash/slash-commands.ts +369 -90
- package/src/slash/slash-live-state.ts +22 -11
- package/src/tui/fleet-status.ts +125 -74
- package/src/tui/fleet.ts +11 -5
- package/src/tui/render.ts +316 -27
- package/src/watchdog/turn-delta.ts +1 -1
- package/src/workflows/chat-progress.ts +6 -3
- package/src/workflows/host-command.ts +230 -0
- package/src/workflows/scripted-workflow.ts +452 -38
- package/src/workflows/workflow-child-summary.ts +9 -5
- package/src/workflows/workflow-preflight.ts +270 -0
- package/src/workflows/workflow-receipt.ts +43 -4
- package/src/workflows/workflow-settlement.ts +246 -0
- package/src/runs/shared/turn-budget.ts +0 -98
|
@@ -46,6 +46,7 @@ import {
|
|
|
46
46
|
findLatestSessionFile,
|
|
47
47
|
detectSubagentError,
|
|
48
48
|
hasEmptyTerminalAssistantResponse,
|
|
49
|
+
formatEmptyTerminalAssistantResponseError,
|
|
49
50
|
extractToolArgsPreview,
|
|
50
51
|
extractTextFromContent,
|
|
51
52
|
boundStreamedRecentTools,
|
|
@@ -55,7 +56,9 @@ import {
|
|
|
55
56
|
import { buildSkillInjection, resolveSkillsWithFallback } from "../../agents/skills.ts";
|
|
56
57
|
import { buildAgentMemoryInjection } from "../../agents/agent-memory.ts";
|
|
57
58
|
import { effectiveToolTimeoutMs, formatToolTimeoutMessage, resolveToolTimeoutMs, toolTimeoutCallKey, toolTimeoutFromEnv } from "../shared/tool-timeout.ts";
|
|
58
|
-
import { evaluateCompletionMutationGuard, validateImplementationToolContract } from "../shared/completion-guard.ts";
|
|
59
|
+
import { evaluateCompletionMutationGuard, expectsImplementationMutation, hasMutationToolCapability, validateImplementationToolContract } from "../shared/completion-guard.ts";
|
|
60
|
+
import { planCompletionEvidence } from "../shared/completion-evidence.ts";
|
|
61
|
+
import { planAbortRecovery } from "../shared/abort-recovery.ts";
|
|
59
62
|
import { arbitrateCompletionGuardRescue } from "../shared/llm-intent-arbiter.ts";
|
|
60
63
|
import { getPiSpawnCommand } from "../shared/pi-spawn.ts";
|
|
61
64
|
import { preflightLaunchCwd } from "../shared/launch-cwd.ts";
|
|
@@ -64,6 +67,7 @@ import { createOrcaProgressTab, type OrcaProgressTab } from "../shared/orca-prog
|
|
|
64
67
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
65
68
|
import { resolvePermissionRules } from "../shared/permissions.ts";
|
|
66
69
|
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan, type SubagentTaskDelivery } from "../shared/pi-args.ts";
|
|
70
|
+
import { deriveChildSessionName } from "../../shared/child-session-name.ts";
|
|
67
71
|
import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.ts";
|
|
68
72
|
import { assertAgentAllowedByCapabilityCeiling, decodeSubagentCapabilityCeiling, intersectSubagentCapabilityCeilings, resolveCurrentSubagentCapabilityCeiling, SUBAGENT_CAPABILITY_CEILING_ENV } from "../shared/capability-ceiling.ts";
|
|
69
73
|
import { resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
@@ -103,7 +107,6 @@ import {
|
|
|
103
107
|
import { acceptanceFailureMessage, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport, validateAcceptanceInput } from "../shared/acceptance.ts";
|
|
104
108
|
import { PROMPT_REDACTED } from "../../shared/utils.ts";
|
|
105
109
|
import { attachContractProjections, isAgentContractV1 } from "../shared/agent-contract.ts";
|
|
106
|
-
import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, turnBudgetDecision, turnBudgetDeferredNote, turnBudgetDeferredState, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
|
|
107
110
|
import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
|
|
108
111
|
import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
|
|
109
112
|
import { agentDefinitionDigest, launchBindingDigest } from "../../shared/launch-contract.ts";
|
|
@@ -294,6 +297,9 @@ function snapshotStreamResult(result: SingleResult, progress: AgentProgress): Si
|
|
|
294
297
|
return snapshot;
|
|
295
298
|
}
|
|
296
299
|
|
|
300
|
+
const AFTER_COMPACTION_SETTLEMENT = Symbol("afterCompactionSettlement");
|
|
301
|
+
type AbortRecoverySingleResult = SingleResult & { [AFTER_COMPACTION_SETTLEMENT]?: true };
|
|
302
|
+
|
|
297
303
|
async function runSingleAttempt(
|
|
298
304
|
runtimeCwd: string,
|
|
299
305
|
agent: AgentConfig,
|
|
@@ -323,6 +329,10 @@ async function runSingleAttempt(
|
|
|
323
329
|
assertThinkingWithinCeiling({ model: modelArg, configThinking: effectiveThinking, ceiling: options.thinkingCeiling, agent: agent.name, runId: options.runId });
|
|
324
330
|
const expectedModelForVerification = shared.verifyModel ? modelArg : undefined;
|
|
325
331
|
const resolvedThinking = resolveEffectiveThinking(modelArg, effectiveThinking);
|
|
332
|
+
// Display name for the child session: applied inside the child via
|
|
333
|
+
// PI_SUBAGENT_SESSION_NAME and echoed back on the result payload so hosts
|
|
334
|
+
// can label this run without reading the child's session file.
|
|
335
|
+
const childSessionName = deriveChildSessionName({ agent: agent.name, task: shared.originalTask ?? task });
|
|
326
336
|
const watchdogConfig = resolveWatchdogConfig(options.cwd ?? runtimeCwd);
|
|
327
337
|
const childWatchdog = watchdogConfig.ok
|
|
328
338
|
? resolveChildWatchdogConfig({
|
|
@@ -351,13 +361,15 @@ async function runSingleAttempt(
|
|
|
351
361
|
inheritSkills: agent.inheritSkills,
|
|
352
362
|
requireReadTool: Boolean(shared.resolvedSkillNames?.length),
|
|
353
363
|
tools: agent.tools,
|
|
364
|
+
allowNestedSubagents: agent.allowNestedSubagents,
|
|
354
365
|
extensions: agent.extensions,
|
|
355
366
|
subagentOnlyExtensions: agent.subagentOnlyExtensions,
|
|
356
|
-
systemPrompt:
|
|
367
|
+
systemPrompt: shared.systemPrompt,
|
|
357
368
|
mcpDirectTools: agent.mcpDirectTools,
|
|
358
369
|
cwd: options.cwd ?? runtimeCwd,
|
|
359
370
|
promptFileStem: agent.name,
|
|
360
371
|
intercomSessionName: options.intercomSessionName,
|
|
372
|
+
sessionName: childSessionName,
|
|
361
373
|
orchestratorIntercomTarget: options.orchestratorIntercomTarget,
|
|
362
374
|
runId: options.runId,
|
|
363
375
|
childAgentName: agent.name,
|
|
@@ -380,6 +392,7 @@ async function runSingleAttempt(
|
|
|
380
392
|
permissionAuditPath,
|
|
381
393
|
childWatchdog,
|
|
382
394
|
waitToolEnabled: options.waitToolEnabled,
|
|
395
|
+
waitToolDefaultTimeoutMs: options.waitToolDefaultTimeoutMs,
|
|
383
396
|
capabilityCeiling: options.capabilityCeiling,
|
|
384
397
|
thinkingCeiling: options.thinkingCeiling,
|
|
385
398
|
extensionBindings: options.extensionBindings,
|
|
@@ -390,9 +403,10 @@ async function runSingleAttempt(
|
|
|
390
403
|
shared.launchWarnings.emitted = true;
|
|
391
404
|
}
|
|
392
405
|
|
|
393
|
-
const effectiveSystemPrompt =
|
|
406
|
+
const effectiveSystemPrompt = shared.systemPrompt;
|
|
394
407
|
const toolPlan = resolvePiLaunchToolPlan({
|
|
395
408
|
tools: agent.tools,
|
|
409
|
+
allowNestedSubagents: agent.allowNestedSubagents,
|
|
396
410
|
extensions: agent.extensions,
|
|
397
411
|
subagentOnlyExtensions: agent.subagentOnlyExtensions,
|
|
398
412
|
mcpDirectTools: agent.mcpDirectTools,
|
|
@@ -425,6 +439,7 @@ async function runSingleAttempt(
|
|
|
425
439
|
index: options.index ?? 0,
|
|
426
440
|
agent: agent.name,
|
|
427
441
|
task,
|
|
442
|
+
...(childSessionName ? { sessionName: childSessionName } : {}),
|
|
428
443
|
messages: [],
|
|
429
444
|
finalOutput: "",
|
|
430
445
|
exitCode: 1,
|
|
@@ -465,6 +480,7 @@ async function runSingleAttempt(
|
|
|
465
480
|
index: options.index ?? 0,
|
|
466
481
|
agent: agent.name,
|
|
467
482
|
task: shared.originalTask ?? task,
|
|
483
|
+
...(childSessionName ? { sessionName: childSessionName } : {}),
|
|
468
484
|
...(options.agentContract ? { agentContract: options.agentContract } : {}),
|
|
469
485
|
launchContractDigest,
|
|
470
486
|
launchResolvedExtensions,
|
|
@@ -478,7 +494,6 @@ async function runSingleAttempt(
|
|
|
478
494
|
transcriptPath: shared.transcriptWriter ? shared.artifactPaths?.transcriptPath : undefined,
|
|
479
495
|
skills: shared.resolvedSkillNames,
|
|
480
496
|
skillsWarning: shared.skillsWarning,
|
|
481
|
-
...(options.turnBudget ? { turnBudget: initialTurnBudgetState(options.turnBudget) } : {}),
|
|
482
497
|
...(options.toolBudget ? { toolBudget: initialToolBudgetState(options.toolBudget) } : {}),
|
|
483
498
|
...(options.capabilityCeiling ? { capabilityCeiling: options.capabilityCeiling } : {}),
|
|
484
499
|
...(capabilityAudit ? { capabilityAudit } : {}),
|
|
@@ -507,6 +522,7 @@ async function runSingleAttempt(
|
|
|
507
522
|
const progress: AgentProgress = {
|
|
508
523
|
index: options.index ?? 0,
|
|
509
524
|
agent: agent.name,
|
|
525
|
+
...(childSessionName ? { sessionName: childSessionName } : {}),
|
|
510
526
|
status: "running",
|
|
511
527
|
task,
|
|
512
528
|
skills: shared.resolvedSkillNames,
|
|
@@ -566,6 +582,7 @@ async function runSingleAttempt(
|
|
|
566
582
|
return result;
|
|
567
583
|
}
|
|
568
584
|
}
|
|
585
|
+
let afterCompactionSettlement = false;
|
|
569
586
|
const exitCode = await new Promise<number>((resolve) => {
|
|
570
587
|
const proc = spawn(spawnSpec.command, spawnSpec.args, {
|
|
571
588
|
cwd: options.cwd ?? runtimeCwd,
|
|
@@ -585,20 +602,7 @@ async function runSingleAttempt(
|
|
|
585
602
|
let timeoutTimer: NodeJS.Timeout | undefined;
|
|
586
603
|
let timeoutTerminationTimer: NodeJS.Timeout | undefined;
|
|
587
604
|
let timeoutHardKillTimer: NodeJS.Timeout | undefined;
|
|
588
|
-
let turnBudgetSoftReached = false;
|
|
589
|
-
let turnBudgetTerminationTimer: NodeJS.Timeout | undefined;
|
|
590
|
-
let turnBudgetHardKillTimer: NodeJS.Timeout | undefined;
|
|
591
605
|
let protocolHardKillTimer: NodeJS.Timeout | undefined;
|
|
592
|
-
const clearTurnBudgetTimers = () => {
|
|
593
|
-
if (turnBudgetTerminationTimer) {
|
|
594
|
-
clearTimeout(turnBudgetTerminationTimer);
|
|
595
|
-
turnBudgetTerminationTimer = undefined;
|
|
596
|
-
}
|
|
597
|
-
if (turnBudgetHardKillTimer) {
|
|
598
|
-
clearTimeout(turnBudgetHardKillTimer);
|
|
599
|
-
turnBudgetHardKillTimer = undefined;
|
|
600
|
-
}
|
|
601
|
-
};
|
|
602
606
|
const clearTimeoutTimers = () => {
|
|
603
607
|
if (timeoutTimer) {
|
|
604
608
|
clearTimeout(timeoutTimer);
|
|
@@ -661,6 +665,7 @@ async function runSingleAttempt(
|
|
|
661
665
|
let forcedTerminationSignal = false;
|
|
662
666
|
let cleanTerminalAssistantStopReceived = false;
|
|
663
667
|
let agentSettledReceived = false;
|
|
668
|
+
let compactionStartedReceived = false;
|
|
664
669
|
let finalDrainTimer: NodeJS.Timeout | undefined;
|
|
665
670
|
let finalHardKillTimer: NodeJS.Timeout | undefined;
|
|
666
671
|
let watchdogTailTimer: NodeJS.Timeout | undefined;
|
|
@@ -759,7 +764,6 @@ async function runSingleAttempt(
|
|
|
759
764
|
clearStdioGuard();
|
|
760
765
|
clearTimeoutTimers();
|
|
761
766
|
clearAllToolTimeouts();
|
|
762
|
-
clearTurnBudgetTimers();
|
|
763
767
|
if (protocolHardKillTimer) {
|
|
764
768
|
clearTimeout(protocolHardKillTimer);
|
|
765
769
|
protocolHardKillTimer = undefined;
|
|
@@ -897,57 +901,6 @@ async function runSingleAttempt(
|
|
|
897
901
|
}));
|
|
898
902
|
return true;
|
|
899
903
|
};
|
|
900
|
-
const requestTurnBudgetAbort = (turnCount: number) => {
|
|
901
|
-
const budget = options.turnBudget;
|
|
902
|
-
if (!budget || result.timedOut || result.turnBudgetExceeded || interruptedByControl || processClosed || lifecycleFinished) return;
|
|
903
|
-
const message = turnBudgetExceededMessage(budget, turnCount);
|
|
904
|
-
result.turnBudgetExceeded = true;
|
|
905
|
-
result.wrapUpRequested = true;
|
|
906
|
-
result.turnBudget = turnBudgetState(budget, turnCount, true);
|
|
907
|
-
result.error = message;
|
|
908
|
-
result.finalOutput = message;
|
|
909
|
-
progress.status = "failed";
|
|
910
|
-
progress.error = message;
|
|
911
|
-
progress.durationMs = Date.now() - startTime;
|
|
912
|
-
fireUpdate();
|
|
913
|
-
trySignalChild(proc, "SIGINT");
|
|
914
|
-
turnBudgetTerminationTimer = setTimeout(() => {
|
|
915
|
-
if (processClosed || lifecycleFinished || result.timedOut) return;
|
|
916
|
-
trySignalChild(proc, "SIGTERM");
|
|
917
|
-
}, 1000);
|
|
918
|
-
turnBudgetTerminationTimer.unref?.();
|
|
919
|
-
turnBudgetHardKillTimer = setTimeout(() => {
|
|
920
|
-
if (processClosed || lifecycleFinished || result.timedOut) return;
|
|
921
|
-
trySignalChild(proc, "SIGKILL");
|
|
922
|
-
}, 4000);
|
|
923
|
-
turnBudgetHardKillTimer.unref?.();
|
|
924
|
-
};
|
|
925
|
-
|
|
926
|
-
const updateTurnBudget = (turnCount: number, terminalAssistantStop: boolean, toolWorkActiveOrStarting: boolean) => {
|
|
927
|
-
const budget = options.turnBudget;
|
|
928
|
-
if (!budget || result.timedOut || result.turnBudgetExceeded) return;
|
|
929
|
-
if (turnCount < budget.maxTurns) {
|
|
930
|
-
result.turnBudget = { ...budget, outcome: "within-budget", turnCount };
|
|
931
|
-
return;
|
|
932
|
-
}
|
|
933
|
-
if (!turnBudgetSoftReached) {
|
|
934
|
-
turnBudgetSoftReached = true;
|
|
935
|
-
result.wrapUpRequested = true;
|
|
936
|
-
appendRecentOutput(progress, [turnBudgetSoftNote(budget, turnCount)]);
|
|
937
|
-
}
|
|
938
|
-
const decision = turnBudgetDecision(budget, turnCount, terminalAssistantStop, toolWorkActiveOrStarting, options.enforceHardTurnLimit);
|
|
939
|
-
if (decision === "defer") {
|
|
940
|
-
result.turnBudget = turnBudgetDeferredState(
|
|
941
|
-
budget,
|
|
942
|
-
turnCount,
|
|
943
|
-
result.turnBudget?.terminationDeferredAtTurn,
|
|
944
|
-
);
|
|
945
|
-
return;
|
|
946
|
-
}
|
|
947
|
-
result.turnBudget = turnBudgetState(budget, turnCount, false);
|
|
948
|
-
if (decision === "abort") requestTurnBudgetAbort(turnCount);
|
|
949
|
-
};
|
|
950
|
-
|
|
951
904
|
const updateActivityState = (now: number): boolean => {
|
|
952
905
|
if (!controlConfig.enabled) return false;
|
|
953
906
|
const idleState = deriveActivityState({
|
|
@@ -1001,7 +954,7 @@ async function runSingleAttempt(
|
|
|
1001
954
|
const fireUpdate = () => {
|
|
1002
955
|
if (!options.onUpdate || processClosed) return;
|
|
1003
956
|
progress.durationMs = Date.now() - startTime;
|
|
1004
|
-
const output =
|
|
957
|
+
const output = result.timedOut && result.finalOutput ? result.finalOutput : getFinalOutput(result.messages ?? []);
|
|
1005
958
|
emitUpdateSnapshot(output || "(running...)");
|
|
1006
959
|
};
|
|
1007
960
|
|
|
@@ -1021,8 +974,20 @@ async function runSingleAttempt(
|
|
|
1021
974
|
}
|
|
1022
975
|
shared.transcriptWriter?.writeChildEvent(evt);
|
|
1023
976
|
shared.orcaProgressTab?.event(evt);
|
|
977
|
+
if (evt.type === "compaction_start") compactionStartedReceived = true;
|
|
978
|
+
if (evt.type === "compaction_end" && evt.willRetry === true) {
|
|
979
|
+
compactionStartedReceived = false;
|
|
980
|
+
afterCompactionSettlement = false;
|
|
981
|
+
}
|
|
982
|
+
if (evt.type === "agent_start" || evt.type === "auto_retry_start") {
|
|
983
|
+
compactionStartedReceived = false;
|
|
984
|
+
afterCompactionSettlement = false;
|
|
985
|
+
}
|
|
1024
986
|
const lifecycleAction = projectChildLifecycle(evt, false, childLifecycleState);
|
|
1025
|
-
if (evt.type === "agent_settled" && lifecycleAction === "start-drain")
|
|
987
|
+
if (evt.type === "agent_settled" && lifecycleAction === "start-drain") {
|
|
988
|
+
agentSettledReceived = true;
|
|
989
|
+
afterCompactionSettlement = compactionStartedReceived;
|
|
990
|
+
}
|
|
1026
991
|
applyChildLifecycle(lifecycleAction);
|
|
1027
992
|
|
|
1028
993
|
if (isChildWatchdogStatusEvent(evt)) {
|
|
@@ -1094,16 +1059,11 @@ async function runSingleAttempt(
|
|
|
1094
1059
|
if (evt.message.role === "assistant") {
|
|
1095
1060
|
result.usage.turns++;
|
|
1096
1061
|
progress.turnCount = result.usage.turns;
|
|
1097
|
-
const stopReason = (evt.message as { stopReason?: string }).stopReason;
|
|
1098
1062
|
const toolCalls = Array.isArray(evt.message.content)
|
|
1099
1063
|
? evt.message.content.filter((part) => (part as { type?: string }).type === "toolCall")
|
|
1100
1064
|
: [];
|
|
1101
1065
|
const hasToolCall = toolCalls.length > 0;
|
|
1102
|
-
const terminalAssistantStop = stopReason === "stop" && !hasToolCall;
|
|
1103
|
-
const terminalStructuredOutputCall = Boolean(options.structuredOutput)
|
|
1104
|
-
&& toolCalls.length === 1
|
|
1105
|
-
&& (toolCalls[0] as { name?: string }).name === "structured_output";
|
|
1106
|
-
updateTurnBudget(result.usage.turns, terminalAssistantStop || terminalStructuredOutputCall, hasToolCall || Boolean(progress.currentTool));
|
|
1066
|
+
const terminalAssistantStop = (evt.message as { stopReason?: string }).stopReason === "stop" && !hasToolCall;
|
|
1107
1067
|
const u = evt.message.usage;
|
|
1108
1068
|
if (u) {
|
|
1109
1069
|
const window = (u.input || 0) + (u.cacheRead || 0);
|
|
@@ -1363,14 +1323,17 @@ async function runSingleAttempt(
|
|
|
1363
1323
|
const rawStdout = rawStdoutTail.text();
|
|
1364
1324
|
let closeError = result.error ?? toolDiagnosticError ?? assistantError;
|
|
1365
1325
|
const forcedDrainAfterFinalSuccess = Boolean(forcedTerminationSignal || signal) && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !closeError;
|
|
1326
|
+
const forcedDrainAfterEmptyTerminal = forcedDrainAfterFinalSuccess && hasEmptyTerminalAssistantResponse(result.messages ?? []);
|
|
1366
1327
|
if (signal) result.processSignal = signal;
|
|
1328
|
+
if (!closeError && forcedDrainAfterEmptyTerminal && stderr.trim()) {
|
|
1329
|
+
closeError = stderr.trim();
|
|
1330
|
+
}
|
|
1367
1331
|
if (!closeError && isUnexplainedProcessSignal({
|
|
1368
1332
|
processSignal: signal,
|
|
1369
1333
|
interrupted: result.interrupted,
|
|
1370
1334
|
timedOut: result.timedOut,
|
|
1371
1335
|
stopped: result.stopped,
|
|
1372
|
-
|
|
1373
|
-
forcedDrainAfterFinalSuccess,
|
|
1336
|
+
forcedDrainAfterFinalSuccess: forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal,
|
|
1374
1337
|
})) {
|
|
1375
1338
|
closeError = formatProcessSignalError(signal!);
|
|
1376
1339
|
}
|
|
@@ -1380,7 +1343,7 @@ async function runSingleAttempt(
|
|
|
1380
1343
|
if (code !== 0 && stderr.trim() && !closeError && !forcedDrainAfterFinalSuccess) {
|
|
1381
1344
|
closeError = stderr.trim();
|
|
1382
1345
|
}
|
|
1383
|
-
const finalCode = forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? (code ?? 1) : (code ?? 0);
|
|
1346
|
+
const finalCode = forcedDrainAfterFinalSuccess && !forcedDrainAfterEmptyTerminal ? 0 : forcedTerminationSignal || signal ? (code ?? 1) : (code ?? 0);
|
|
1384
1347
|
if (!result.error && closeError) result.error = closeError;
|
|
1385
1348
|
finish(finalCode);
|
|
1386
1349
|
});
|
|
@@ -1452,6 +1415,9 @@ async function runSingleAttempt(
|
|
|
1452
1415
|
}
|
|
1453
1416
|
});
|
|
1454
1417
|
result.exitCode = exitCode;
|
|
1418
|
+
if (afterCompactionSettlement) {
|
|
1419
|
+
(result as AbortRecoverySingleResult)[AFTER_COMPACTION_SETTLEMENT] = true;
|
|
1420
|
+
}
|
|
1455
1421
|
if (interruptedByControl) {
|
|
1456
1422
|
result.exitCode = 0;
|
|
1457
1423
|
result.interrupted = true;
|
|
@@ -1472,7 +1438,6 @@ async function runSingleAttempt(
|
|
|
1472
1438
|
&& !abortedBySignal
|
|
1473
1439
|
&& !result.timedOut
|
|
1474
1440
|
&& !result.stopped
|
|
1475
|
-
&& !result.turnBudgetExceeded
|
|
1476
1441
|
&& !result.protocolError
|
|
1477
1442
|
&& !toolAvailabilityError) {
|
|
1478
1443
|
const processExitCode = result.exitCode;
|
|
@@ -1525,9 +1490,12 @@ async function runSingleAttempt(
|
|
|
1525
1490
|
: messages;
|
|
1526
1491
|
const errInfo = detectSubagentError(errorMessages);
|
|
1527
1492
|
const missingOutput = !finalText?.trim() && !validatedStructuredOutput;
|
|
1528
|
-
|
|
1493
|
+
const terminalEmptyAfterUsefulWork = !validatedStructuredOutput
|
|
1494
|
+
&& hasEmptyTerminalAssistantResponse(messages)
|
|
1495
|
+
&& (progress.toolCount > 0 || Boolean(finalText?.trim()));
|
|
1496
|
+
if ((missingOutput || terminalEmptyAfterUsefulWork) && (!errInfo.hasError || hasEmptyTerminalAssistantResponse(messages))) {
|
|
1529
1497
|
result.exitCode = 1;
|
|
1530
|
-
result.error =
|
|
1498
|
+
result.error = formatEmptyTerminalAssistantResponseError(messages);
|
|
1531
1499
|
} else if (errInfo.hasError) {
|
|
1532
1500
|
result.exitCode = errInfo.exitCode ?? 1;
|
|
1533
1501
|
result.error = errInfo.details
|
|
@@ -1546,6 +1514,7 @@ async function runSingleAttempt(
|
|
|
1546
1514
|
}
|
|
1547
1515
|
|
|
1548
1516
|
result.progressSummary = {
|
|
1517
|
+
...(childSessionName ? { sessionName: childSessionName } : {}),
|
|
1549
1518
|
toolCount: progress.toolCount,
|
|
1550
1519
|
tokens: progress.tokens,
|
|
1551
1520
|
durationMs: progress.durationMs,
|
|
@@ -1571,14 +1540,6 @@ async function runSingleAttempt(
|
|
|
1571
1540
|
fullOutput = fullOutput.trim()
|
|
1572
1541
|
? `${timeoutMessage}\n\n${result.timeoutRecovery.message}\n\nPartial output before timeout:\n${fullOutput}`
|
|
1573
1542
|
: `${timeoutMessage}\n\n${result.timeoutRecovery.message}`;
|
|
1574
|
-
} else if (result.turnBudgetExceeded && result.turnBudget) {
|
|
1575
|
-
fullOutput = formatTurnBudgetOutput(turnBudgetExceededMessage(result.turnBudget, result.turnBudget.turnCount), fullOutput);
|
|
1576
|
-
} else if (result.turnBudget?.outcome === "termination-deferred") {
|
|
1577
|
-
const note = turnBudgetDeferredNote(result.turnBudget, result.turnBudget.terminationDeferredAtTurn ?? result.turnBudget.turnCount);
|
|
1578
|
-
fullOutput = fullOutput.trim() ? `${note}\n\n${fullOutput}` : note;
|
|
1579
|
-
} else if (result.wrapUpRequested && result.turnBudget?.outcome === "wrap-up-requested") {
|
|
1580
|
-
const note = turnBudgetSoftNote(result.turnBudget, result.turnBudget.wrapUpRequestedAtTurn ?? result.turnBudget.turnCount);
|
|
1581
|
-
fullOutput = fullOutput.trim() ? `${note}\n\n${fullOutput}` : note;
|
|
1582
1543
|
}
|
|
1583
1544
|
const completionGuardEnabled = isAgentContractV1(options.agentContract) ? agent.completionGuard === true : agent.completionGuard !== false;
|
|
1584
1545
|
const completionGuard = ((result.exitCode === 0 && !result.error) || toolAvailabilityError) && completionGuardEnabled
|
|
@@ -1595,7 +1556,6 @@ async function runSingleAttempt(
|
|
|
1595
1556
|
: undefined;
|
|
1596
1557
|
const mutationAttemptObserved = observedMutationAttempt || mutationEvidence.attemptedMutation;
|
|
1597
1558
|
let completionGuardTriggered = completionGuard?.triggered === true && !mutationAttemptObserved;
|
|
1598
|
-
const completionGuardBlocked = completionGuard?.blocked === true;
|
|
1599
1559
|
// The classifier is deliberately narrow, so a read-only review task can
|
|
1600
1560
|
// still be misread as implementation. Arbitrate BEFORE any failure side
|
|
1601
1561
|
// effect is published (effects, exit code, progress, notifications,
|
|
@@ -1612,31 +1572,26 @@ async function runSingleAttempt(
|
|
|
1612
1572
|
completionGuardTriggered = arbitration.triggered;
|
|
1613
1573
|
arbiterRescued = arbitration.rescued;
|
|
1614
1574
|
}
|
|
1615
|
-
|
|
1575
|
+
const completionEvidence = planCompletionEvidence({
|
|
1576
|
+
guard: completionGuard,
|
|
1577
|
+
guardTriggered: completionGuardTriggered,
|
|
1578
|
+
completionGuardEnabled,
|
|
1579
|
+
mutationCapable: hasMutationToolCapability(contractTools, toolPlan.effectiveMcpTools),
|
|
1580
|
+
implementationMutationExpected: expectsImplementationMutation(agent.name, shared.originalTask ?? task),
|
|
1581
|
+
mutationAttemptObserved,
|
|
1582
|
+
mutationEvidence,
|
|
1583
|
+
arbiterRescued,
|
|
1584
|
+
agentContractV1: isAgentContractV1(options.agentContract),
|
|
1585
|
+
});
|
|
1586
|
+
if (completionEvidence.fileMutation) {
|
|
1616
1587
|
result.effects = {
|
|
1617
1588
|
...(result.effects ?? {}),
|
|
1618
|
-
fileMutation:
|
|
1619
|
-
status: completionGuardBlocked
|
|
1620
|
-
? "blocked"
|
|
1621
|
-
: completionGuard.expectedMutation
|
|
1622
|
-
? completionGuardTriggered
|
|
1623
|
-
? "missing"
|
|
1624
|
-
: arbiterRescued
|
|
1625
|
-
? "not-applicable"
|
|
1626
|
-
: "observed"
|
|
1627
|
-
: "not-applicable",
|
|
1628
|
-
expected: completionGuard.expectedMutation,
|
|
1629
|
-
attempted: completionGuardBlocked ? false : completionGuard.attemptedMutation || mutationAttemptObserved,
|
|
1630
|
-
evidence: mutationEvidence,
|
|
1631
|
-
...(completionGuardBlocked && completionGuard.message ? { message: completionGuard.message } : {}),
|
|
1632
|
-
...(completionGuardTriggered ? { message: "Subagent completed without making edits for an implementation task." } : {}),
|
|
1633
|
-
...(arbiterRescued ? { resolvedBy: "llm-intent-arbiter" } : {}),
|
|
1634
|
-
},
|
|
1589
|
+
fileMutation: completionEvidence.fileMutation,
|
|
1635
1590
|
};
|
|
1636
1591
|
}
|
|
1637
|
-
if (
|
|
1592
|
+
if (completionEvidence.legacyFailureError) {
|
|
1638
1593
|
result.exitCode = 1;
|
|
1639
|
-
result.error =
|
|
1594
|
+
result.error = completionEvidence.legacyFailureError;
|
|
1640
1595
|
progress.status = "failed";
|
|
1641
1596
|
progress.error = result.error;
|
|
1642
1597
|
emitControlEvent(buildControlEvent({
|
|
@@ -1651,10 +1606,14 @@ async function runSingleAttempt(
|
|
|
1651
1606
|
}));
|
|
1652
1607
|
}
|
|
1653
1608
|
if (options.outputPath && result.exitCode === 0) {
|
|
1654
|
-
const resolvedOutput = resolveSingleOutput(options.outputPath, fullOutput, shared.outputSnapshot);
|
|
1609
|
+
const resolvedOutput = resolveSingleOutput(options.outputPath, fullOutput, shared.outputSnapshot, options.outputClaimPath);
|
|
1655
1610
|
fullOutput = stripAcceptanceReport(resolvedOutput.fullOutput);
|
|
1656
1611
|
result.savedOutputPath = resolvedOutput.savedPath;
|
|
1657
1612
|
result.outputSaveError = resolvedOutput.saveError;
|
|
1613
|
+
if (resolvedOutput.fatalError) {
|
|
1614
|
+
result.exitCode = 1;
|
|
1615
|
+
result.error = result.error ? `${result.error}\n${resolvedOutput.saveError}` : resolvedOutput.saveError;
|
|
1616
|
+
}
|
|
1658
1617
|
if (resolvedOutput.savedPath) {
|
|
1659
1618
|
result.outputReference = formatSavedOutputReference(resolvedOutput.savedPath, fullOutput);
|
|
1660
1619
|
if (result.outputState === "absent") result.outputState = "unknown";
|
|
@@ -1711,6 +1670,7 @@ async function runSyncCompletionInner(
|
|
|
1711
1670
|
...options,
|
|
1712
1671
|
capabilityCeiling: intersectSubagentCapabilityCeilings(options.capabilityCeiling ?? resolveCurrentSubagentCapabilityCeiling(options.parentSessionId), decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV])),
|
|
1713
1672
|
};
|
|
1673
|
+
const childSessionName = deriveChildSessionName({ agent: agentName, task });
|
|
1714
1674
|
const agent = agents.find((a) => a.name === agentName);
|
|
1715
1675
|
if (!agent) {
|
|
1716
1676
|
const diagnosticContext = options.unknownAgentDiagnosticContext
|
|
@@ -1953,12 +1913,16 @@ async function runSyncCompletionInner(
|
|
|
1953
1913
|
// Escalated to "file" after an unexplained zero-activity startup failure so
|
|
1954
1914
|
// retries keep the task text out of argv (endpoint pre-exec scans may deny it).
|
|
1955
1915
|
let taskDeliveryOverride: SubagentTaskDelivery | undefined;
|
|
1916
|
+
let abortRecoveryAttempted = false;
|
|
1917
|
+
let nextAttemptTask = taskWithAcceptance;
|
|
1956
1918
|
modelAttemptsLoop: for (let modelIndex = 0; modelIndex < modelsToTry.length; modelIndex++) {
|
|
1957
1919
|
const candidate = modelsToTry[modelIndex];
|
|
1958
1920
|
for (let startupAttemptIndex = 0; ; startupAttemptIndex++) {
|
|
1921
|
+
const recoveringAbort = abortRecoveryAttempted;
|
|
1922
|
+
const attemptTask = nextAttemptTask;
|
|
1959
1923
|
const verifyModel = Boolean(candidate) && !(options.modelOverrideFromParent && modelIndex === 0);
|
|
1960
1924
|
const outputSnapshot = captureSingleOutputSnapshot(options.outputPath);
|
|
1961
|
-
const result = await runSingleAttempt(runtimeCwd, agent,
|
|
1925
|
+
const result = await runSingleAttempt(runtimeCwd, agent, attemptTask, candidate, attemptOptions, {
|
|
1962
1926
|
sessionEnabled,
|
|
1963
1927
|
systemPrompt,
|
|
1964
1928
|
resolvedSkillNames: resolvedSkills.length > 0 ? resolvedSkills.map((skill) => skill.name) : undefined,
|
|
@@ -1978,7 +1942,7 @@ async function runSyncCompletionInner(
|
|
|
1978
1942
|
verifyModel,
|
|
1979
1943
|
});
|
|
1980
1944
|
lastResult = result;
|
|
1981
|
-
if (startupAttemptIndex === 0) {
|
|
1945
|
+
if (!recoveringAbort && startupAttemptIndex === 0) {
|
|
1982
1946
|
if (result.model) attemptedModels.push(result.model);
|
|
1983
1947
|
else if (candidate) attemptedModels.push(candidate);
|
|
1984
1948
|
}
|
|
@@ -1994,11 +1958,42 @@ async function runSyncCompletionInner(
|
|
|
1994
1958
|
usage: { ...result.usage },
|
|
1995
1959
|
};
|
|
1996
1960
|
modelAttempts.push(attempt);
|
|
1961
|
+
if (!attemptSucceeded) {
|
|
1962
|
+
const afterCompactionSettlement = (result as AbortRecoverySingleResult)[AFTER_COMPACTION_SETTLEMENT];
|
|
1963
|
+
const abortRecovery = planAbortRecovery({
|
|
1964
|
+
messages: result.messages ?? [],
|
|
1965
|
+
error: result.error,
|
|
1966
|
+
processSignal: result.processSignal,
|
|
1967
|
+
sessionAvailable: Boolean(options.sessionFile && existsSync(options.sessionFile)),
|
|
1968
|
+
alreadyResumed: abortRecoveryAttempted,
|
|
1969
|
+
stopped: result.stopped || result.detached || options.signal?.aborted,
|
|
1970
|
+
interrupted: result.interrupted || intercomDetached || options.interruptSignal?.aborted,
|
|
1971
|
+
timedOut: result.timedOut,
|
|
1972
|
+
toolBudgetExhausted: result.toolBudgetBlocked,
|
|
1973
|
+
usageBudgetExhausted: false,
|
|
1974
|
+
structuredOutputFailed: result.structuredOutputFailed,
|
|
1975
|
+
acceptanceFailed: false,
|
|
1976
|
+
currentTool: result.progress?.currentTool,
|
|
1977
|
+
afterCompactionSettlement,
|
|
1978
|
+
});
|
|
1979
|
+
if (abortRecovery.action === "resume") {
|
|
1980
|
+
abortRecoveryAttempted = true;
|
|
1981
|
+
nextAttemptTask = abortRecovery.prompt;
|
|
1982
|
+
attemptNotes.push("[abort-recovery] provider/transport abort after useful progress; resuming the retained child session once.");
|
|
1983
|
+
continue;
|
|
1984
|
+
}
|
|
1985
|
+
if (abortRecovery.diagnostic) {
|
|
1986
|
+
result.error = result.error ? `${result.error}\n${abortRecovery.diagnostic}` : abortRecovery.diagnostic;
|
|
1987
|
+
attempt.error = result.error;
|
|
1988
|
+
break modelAttemptsLoop;
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
if (recoveringAbort && !attemptSucceeded) break modelAttemptsLoop;
|
|
1997
1992
|
if (options.workflowChildPermitLaunch && !attemptSucceeded) break modelAttemptsLoop;
|
|
1998
1993
|
// Preserve the legacy intercom handoff contract: once this logical run has
|
|
1999
1994
|
// been handed to a supervisor, terminating that attempt must not launch a
|
|
2000
1995
|
// startup retry or model fallback. Explicit user detach retains fallback.
|
|
2001
|
-
if (intercomDetached || result.timedOut
|
|
1996
|
+
if (intercomDetached || result.timedOut) break modelAttemptsLoop;
|
|
2002
1997
|
if (attemptSucceeded) break modelAttemptsLoop;
|
|
2003
1998
|
|
|
2004
1999
|
const startupFailure = isRetryableSubagentStartupFailure({
|
|
@@ -2015,7 +2010,6 @@ async function runSyncCompletionInner(
|
|
|
2015
2010
|
interrupted: result.interrupted,
|
|
2016
2011
|
timedOut: result.timedOut,
|
|
2017
2012
|
stopped: result.stopped,
|
|
2018
|
-
turnBudgetExceeded: result.turnBudgetExceeded,
|
|
2019
2013
|
});
|
|
2020
2014
|
const retryDelayMs = SUBAGENT_STARTUP_RETRY_DELAYS_MS[startupAttemptIndex];
|
|
2021
2015
|
if (startupFailure && retryDelayMs !== undefined) {
|
|
@@ -2089,11 +2083,13 @@ async function runSyncCompletionInner(
|
|
|
2089
2083
|
usage: emptyUsage(),
|
|
2090
2084
|
error: "Subagent did not produce a result.",
|
|
2091
2085
|
} satisfies SingleResult, options.context);
|
|
2086
|
+
result.task = task;
|
|
2092
2087
|
|
|
2093
2088
|
result.usage = aggregateUsage;
|
|
2094
2089
|
result.attemptedModels = attemptedModels.length > 0 ? attemptedModels : undefined;
|
|
2095
2090
|
result.modelAttempts = modelAttempts.length > 0 ? modelAttempts : undefined;
|
|
2096
2091
|
result.progressSummary = {
|
|
2092
|
+
...(childSessionName ? { sessionName: childSessionName } : {}),
|
|
2097
2093
|
toolCount: totalToolCount,
|
|
2098
2094
|
tokens: aggregateUsage.input + aggregateUsage.output,
|
|
2099
2095
|
durationMs: totalDurationMs,
|
|
@@ -2147,8 +2143,6 @@ async function runSyncCompletionInner(
|
|
|
2147
2143
|
result.acceptance = buildSkippedAcceptanceLedger(effectiveAcceptance, { id: "stopped", message: "Acceptance was not evaluated because the subagent was stopped." });
|
|
2148
2144
|
} else if (result.timedOut) {
|
|
2149
2145
|
result.acceptance = buildSkippedAcceptanceLedger(effectiveAcceptance, { id: "timeout", message: "Acceptance was not evaluated because the subagent timed out." });
|
|
2150
|
-
} else if (result.turnBudgetExceeded) {
|
|
2151
|
-
result.acceptance = buildSkippedAcceptanceLedger(effectiveAcceptance, { id: "turn-budget", message: "Acceptance was not evaluated because the subagent exceeded its turn budget." });
|
|
2152
2146
|
} else {
|
|
2153
2147
|
result.acceptance = await evaluateAcceptance({
|
|
2154
2148
|
acceptance: effectiveAcceptance,
|
|
@@ -18,6 +18,7 @@ interface BeginForegroundChildInput {
|
|
|
18
18
|
|
|
19
19
|
function copyProgress(target: ForegroundChildControl, progress: AgentProgress | undefined): void {
|
|
20
20
|
if (!progress) return;
|
|
21
|
+
target.sessionName = progress.sessionName;
|
|
21
22
|
target.currentActivityState = progress.activityState;
|
|
22
23
|
target.lastActivityAt = progress.lastActivityAt;
|
|
23
24
|
target.currentTool = progress.currentTool;
|
|
@@ -36,6 +37,7 @@ function copyProgress(target: ForegroundChildControl, progress: AgentProgress |
|
|
|
36
37
|
|
|
37
38
|
function syncCurrentChild(control: ForegroundRunControl, child: ForegroundChildControl): void {
|
|
38
39
|
control.currentAgent = child.agent;
|
|
40
|
+
control.sessionName = child.sessionName;
|
|
39
41
|
control.currentIndex = child.index;
|
|
40
42
|
control.description = child.description;
|
|
41
43
|
control.currentActivityState = child.currentActivityState;
|
|
@@ -59,6 +61,7 @@ function syncCurrentChild(control: ForegroundRunControl, child: ForegroundChildC
|
|
|
59
61
|
|
|
60
62
|
function clearCurrentChild(control: ForegroundRunControl): void {
|
|
61
63
|
control.currentAgent = undefined;
|
|
64
|
+
control.sessionName = undefined;
|
|
62
65
|
control.currentIndex = undefined;
|
|
63
66
|
control.currentActivityState = undefined;
|
|
64
67
|
control.lastActivityAt = undefined;
|
|
@@ -29,6 +29,7 @@ function compactChild(child: ForegroundResumeChild): ForegroundResumeChild {
|
|
|
29
29
|
return {
|
|
30
30
|
agent: child.agent,
|
|
31
31
|
index: child.index,
|
|
32
|
+
...(child.sessionName ? { sessionName: child.sessionName } : {}),
|
|
32
33
|
...(child.context ? { context: child.context } : {}),
|
|
33
34
|
...(child.sessionFile ? { sessionFile: child.sessionFile } : {}),
|
|
34
35
|
...(child.model ? { model: child.model } : {}),
|