pi-subagents 0.50.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 +62 -0
- package/agents/gpt-pro.md +17 -0
- package/async-retention-discovery-worker.mjs +180 -0
- package/docs/agents.md +35 -2
- package/docs/configuration.md +30 -12
- package/docs/extension-api.md +42 -1
- package/docs/observability.md +4 -4
- package/docs/tool-reference.md +38 -39
- package/docs/workflows.md +169 -3
- package/package.json +4 -2
- package/skills/pi-subagents/SKILL.md +5 -4
- package/skills/pi-subagents/references/constraints-and-recipes.md +6 -4
- package/skills/pi-subagents/references/execution-controls.md +18 -15
- package/skills/pi-subagents/references/management-authoring-rpc.md +3 -3
- package/skills/pi-subagents/references/prompting-and-roles.md +2 -2
- package/src/agents/agent-management.ts +100 -345
- package/src/agents/agents.ts +125 -25
- package/src/api/external-job-provider.ts +185 -0
- package/src/api/preflight.ts +31 -6
- package/src/api/shared-types.ts +2 -0
- package/src/extension/config.ts +3 -3
- package/src/extension/doctor.ts +3 -6
- package/src/extension/fanout-child.ts +2 -2
- package/src/extension/index.ts +165 -88
- package/src/extension/public-execution.ts +28 -1
- package/src/extension/schemas.ts +12 -35
- package/src/extension/tool-description.ts +35 -24
- package/src/inspectors/herdr/actions.ts +2 -2
- package/src/inspectors/herdr/inspector-runner.ts +2 -1
- package/src/inspectors/herdr/project-panes.ts +2 -2
- package/src/intercom/native-supervisor-channel.ts +30 -9
- 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 +31 -8
- package/src/runs/background/async-execution.ts +49 -31
- package/src/runs/background/async-job-tracker.ts +20 -4
- package/src/runs/background/async-resume.ts +28 -13
- package/src/runs/background/async-retention.ts +888 -0
- package/src/runs/background/async-status.ts +39 -53
- package/src/runs/background/chain-append.ts +3 -33
- package/src/runs/background/control-channel.ts +14 -68
- package/src/runs/background/index-segment.ts +59 -0
- package/src/runs/background/notify.ts +3 -1
- package/src/runs/background/result-files.ts +158 -90
- package/src/runs/background/result-watcher.ts +72 -20
- package/src/runs/background/retained-children.ts +13 -3
- package/src/runs/background/run-id-query.ts +7 -0
- package/src/runs/background/run-id-resolver.ts +11 -9
- package/src/runs/background/run-status.ts +27 -18
- package/src/runs/background/scheduled-runs.ts +22 -4
- package/src/runs/background/stale-run-reconciler.ts +6 -3
- package/src/runs/background/steering.ts +11 -1
- package/src/runs/background/subagent-runner.ts +250 -138
- package/src/runs/background/subagent-wait.ts +7 -7
- package/src/runs/background/terminal-run-index.ts +129 -0
- package/src/runs/background/wait-completions.ts +21 -4
- package/src/runs/background/wait-subscriptions.ts +80 -1
- package/src/runs/foreground/async-steering-action.ts +21 -14
- package/src/runs/foreground/execution.ts +2 -0
- package/src/runs/foreground/subagent-executor.ts +460 -1536
- package/src/runs/foreground/workflow-foreground-steering.ts +6 -5
- package/src/runs/shared/chain-outputs.ts +1 -3
- 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 +22 -5
- package/src/runs/shared/orca-progress-tabs.ts +84 -22
- package/src/runs/shared/parallel-handoff.ts +46 -4
- package/src/runs/shared/parallel-utils.ts +4 -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 +26 -4
- package/src/runs/shared/subagent-prompt-runtime.ts +12 -6
- 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 +60 -26
- package/src/shared/utils.ts +8 -0
- package/src/shared/watch-strategy.ts +10 -0
- package/src/slash/slash-commands.ts +11 -3
- package/src/tui/fleet.ts +63 -15
- package/src/workflows/chat-progress.ts +1 -1
- package/src/workflows/scripted-workflow.ts +207 -65
- package/src/runs/foreground/chain-clarify.ts +0 -1354
- package/src/runs/foreground/chain-execution.ts +0 -1581
package/src/extension/index.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Toggle: async parameter (default: true; set asyncByDefault:false in config.json to opt out)
|
|
10
10
|
*
|
|
11
11
|
* Config file: ~/.pi/agent/extensions/subagent/config.json
|
|
12
|
-
* { "asyncByDefault": true, "forceTopLevelAsync": true, "maxSubagentDepth": 1, "intercomBridge": { "mode": "always", "instructionFile": "./intercom-bridge.md" }, "worktreeSetupHook": "./scripts/setup-worktree.mjs" }
|
|
12
|
+
* { "asyncByDefault": true, "defaultSubagentContext": "fork", "forceTopLevelAsync": true, "maxSubagentDepth": 1, "intercomBridge": { "mode": "always", "instructionFile": "./intercom-bridge.md" }, "worktreeSetupHook": "./scripts/setup-worktree.mjs" }
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import { randomUUID } from "node:crypto";
|
|
@@ -23,6 +23,7 @@ import { discoverAgents } from "../agents/agents.ts";
|
|
|
23
23
|
import { ensureAccessibleDir } from "../shared/accessible-dir.ts";
|
|
24
24
|
import { cleanupAllArtifactDirs, cleanupOldArtifacts, getArtifactsDir } from "../shared/artifacts.ts";
|
|
25
25
|
import { resolveCurrentSessionId } from "../shared/session-identity.ts";
|
|
26
|
+
import { currentCompletionOwnerId } from "../shared/completion-owner.ts";
|
|
26
27
|
import { cleanupOldChainDirs } from "../shared/settings.ts";
|
|
27
28
|
import { clearLegacyResultAnimationTimer, renderSubagentResult, renderSubagentSummary } from "../tui/render.ts";
|
|
28
29
|
import { openSubagentFleet } from "../tui/fleet.ts";
|
|
@@ -31,7 +32,8 @@ import { createSubagentParamsSchema } from "./schemas.ts";
|
|
|
31
32
|
import { createSubagentExecutor, type SubagentParamsLike } from "../runs/foreground/subagent-executor.ts";
|
|
32
33
|
import { createAsyncJobTracker } from "../runs/background/async-job-tracker.ts";
|
|
33
34
|
import { getActiveAsyncCapacitySnapshot, resolveMaxActiveAsyncRunsPerSession } from "../runs/background/active-async-capacity.ts";
|
|
34
|
-
import { cleanupResultIndexes } from "../runs/background/result-files.ts";
|
|
35
|
+
import { cleanupResultIndexes, missionObserverResultCandidateFiles } from "../runs/background/result-files.ts";
|
|
36
|
+
import { ASYNC_RETENTION_DELAY_MS, cleanupAsyncRetention } from "../runs/background/async-retention.ts";
|
|
35
37
|
import { createResultWatcher } from "../runs/background/result-watcher.ts";
|
|
36
38
|
import { createScheduledRunManager } from "../runs/background/scheduled-runs.ts";
|
|
37
39
|
import { registerSlashCommands } from "../slash/slash-commands.ts";
|
|
@@ -53,7 +55,7 @@ import { SUBAGENT_CHILD_ENV, SUBAGENT_PARENT_SESSION_ENV } from "../runs/shared/
|
|
|
53
55
|
import { resolveCurrentSubagentCapabilityCeiling } from "../runs/shared/capability-ceiling.ts";
|
|
54
56
|
import { formatDuration, shortenPath } from "../shared/formatters.ts";
|
|
55
57
|
import { loadConfig, resolveAsyncByDefault, resolveScheduledStoreRoot } from "./config.ts";
|
|
56
|
-
import { buildSubagentToolDescription } from "./tool-description.ts";
|
|
58
|
+
import { buildSubagentToolDescription, buildSubagentToolPromptMetadata } from "./tool-description.ts";
|
|
57
59
|
import { collectGoalContinuationNotices } from "../missions/goal-driver.ts";
|
|
58
60
|
import { restoreForegroundRunHistory } from "../runs/foreground/foreground-history.ts";
|
|
59
61
|
import { resolveMissionStoreLocation } from "../missions/store.ts";
|
|
@@ -84,6 +86,37 @@ import {
|
|
|
84
86
|
export { loadConfig, resolveAsyncByDefault } from "./config.ts";
|
|
85
87
|
|
|
86
88
|
const SLOW_RELOAD_PHASE_MS = 250;
|
|
89
|
+
const RUNTIME_REGISTRY_STORE_KEY = "__piSubagentRuntimeRegistry";
|
|
90
|
+
|
|
91
|
+
interface SubagentRuntimeEntry {
|
|
92
|
+
cleanup(): void;
|
|
93
|
+
sessionManager: object | null;
|
|
94
|
+
visibleControlNotices: Set<string>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface SubagentRuntimeRegistry {
|
|
98
|
+
bySessionManager: WeakMap<object, SubagentRuntimeEntry>;
|
|
99
|
+
visibleControlNoticesBySessionManager: WeakMap<object, Set<string>>;
|
|
100
|
+
activeEntries: Set<SubagentRuntimeEntry>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function getRuntimeRegistry(): SubagentRuntimeRegistry {
|
|
104
|
+
const globalStore = globalThis as Record<string, unknown>;
|
|
105
|
+
const existing = globalStore[RUNTIME_REGISTRY_STORE_KEY] as Partial<SubagentRuntimeRegistry> | undefined;
|
|
106
|
+
if (existing?.bySessionManager instanceof WeakMap && existing.activeEntries instanceof Set) {
|
|
107
|
+
if (!(existing.visibleControlNoticesBySessionManager instanceof WeakMap)) {
|
|
108
|
+
existing.visibleControlNoticesBySessionManager = new WeakMap();
|
|
109
|
+
}
|
|
110
|
+
return existing as SubagentRuntimeRegistry;
|
|
111
|
+
}
|
|
112
|
+
const registry: SubagentRuntimeRegistry = {
|
|
113
|
+
bySessionManager: new WeakMap(),
|
|
114
|
+
visibleControlNoticesBySessionManager: new WeakMap(),
|
|
115
|
+
activeEntries: new Set(),
|
|
116
|
+
};
|
|
117
|
+
globalStore[RUNTIME_REGISTRY_STORE_KEY] = registry;
|
|
118
|
+
return registry;
|
|
119
|
+
}
|
|
87
120
|
|
|
88
121
|
function logSlowPhase(label: string, startedAt: number): void {
|
|
89
122
|
const elapsed = Date.now() - startedAt;
|
|
@@ -358,16 +391,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
358
391
|
if (process.env[SUBAGENT_CHILD_ENV] === "1") {
|
|
359
392
|
return;
|
|
360
393
|
}
|
|
361
|
-
const
|
|
362
|
-
const runtimeCleanupStoreKey = "__piSubagentRuntimeCleanup";
|
|
363
|
-
const previousRuntimeCleanup = globalStore[runtimeCleanupStoreKey];
|
|
364
|
-
if (typeof previousRuntimeCleanup === "function") {
|
|
365
|
-
try {
|
|
366
|
-
previousRuntimeCleanup();
|
|
367
|
-
} catch {
|
|
368
|
-
// Best effort cleanup for stale timers from an older reload.
|
|
369
|
-
}
|
|
370
|
-
}
|
|
394
|
+
const runtimeRegistry = getRuntimeRegistry();
|
|
371
395
|
|
|
372
396
|
DIRS.results = ensureAccessibleDir(DIRS.results);
|
|
373
397
|
DIRS.async = ensureAccessibleDir(DIRS.async);
|
|
@@ -395,6 +419,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
395
419
|
const state: SubagentState = {
|
|
396
420
|
baseCwd: "",
|
|
397
421
|
currentSessionId: null,
|
|
422
|
+
completionOwnerId: currentCompletionOwnerId(),
|
|
398
423
|
artifactDirPreference: config.artifactDir ?? DEFAULT_ARTIFACT_CONFIG.dir,
|
|
399
424
|
...(config.authorityPolicy ? { authorityPolicy: config.authorityPolicy } : {}),
|
|
400
425
|
...(config.missions ? { missionStoreConfig: config.missions } : {}),
|
|
@@ -440,6 +465,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
440
465
|
: undefined;
|
|
441
466
|
let executorScheduled: ((id: string, params: SubagentParamsLike, signal: AbortSignal, ctx: ExtensionContext) => Promise<AgentToolResult<Details>>) | undefined;
|
|
442
467
|
let goalTurnId = 0;
|
|
468
|
+
let parentSessionEnvValue: string | null = null;
|
|
443
469
|
const scheduledStoreRoot = config.scheduledRuns?.storeRoot === undefined ? undefined : resolveScheduledStoreRoot(config.scheduledRuns.storeRoot);
|
|
444
470
|
const scheduledRunManager = createScheduledRunManager({
|
|
445
471
|
config,
|
|
@@ -456,10 +482,18 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
456
482
|
},
|
|
457
483
|
resolveCapabilityCeiling: (sessionId) => resolveCurrentSubagentCapabilityCeiling(sessionId),
|
|
458
484
|
});
|
|
485
|
+
let refreshResultDelivery = () => {};
|
|
486
|
+
const hasResultDeliveryDemand = () => {
|
|
487
|
+
if ([...state.asyncJobs.values()].some((job) => job.status === "queued" || job.status === "running")) return true;
|
|
488
|
+
if (state.foregroundControls.size > 0) return true;
|
|
489
|
+
if (scheduledRunManager.observedCompletionRunIds().size > 0) return true;
|
|
490
|
+
return missionObserverResultCandidateFiles(DIRS.results).length > 0;
|
|
491
|
+
};
|
|
459
492
|
const { ensurePoller, refreshWidget, handleStarted, handleComplete, resetJobs, restoreActiveJobs, dispose: disposeAsyncJobTracker } = createAsyncJobTracker(pi, state, DIRS.async, {
|
|
460
493
|
widgetEnabled: asyncWidgetEnabled,
|
|
494
|
+
onJobTerminal: () => refreshResultDelivery(),
|
|
461
495
|
});
|
|
462
|
-
const
|
|
496
|
+
const resultWatcher = createResultWatcher(
|
|
463
497
|
pi,
|
|
464
498
|
state,
|
|
465
499
|
DIRS.results,
|
|
@@ -468,23 +502,30 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
468
502
|
notifier: completionNotifier,
|
|
469
503
|
observeCompletion: (result) => scheduledRunManager.handleAsyncCompletion(result),
|
|
470
504
|
observedCompletionRunIds: () => scheduledRunManager.observedCompletionRunIds(),
|
|
505
|
+
hasDeliveryDemand: hasResultDeliveryDemand,
|
|
471
506
|
deliverIntercomResults: config.intercomBridge?.resultDelivery === true,
|
|
472
507
|
},
|
|
473
508
|
);
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
509
|
+
const { startResultWatcher, primeExistingResults, stopResultWatcher } = resultWatcher;
|
|
510
|
+
refreshResultDelivery = resultWatcher.refreshResultDelivery;
|
|
511
|
+
const asyncRetentionAbort = new AbortController();
|
|
512
|
+
const asyncRetentionTimer = setTimeout(async () => {
|
|
513
|
+
try {
|
|
514
|
+
await cleanupAsyncRetention({
|
|
515
|
+
asyncDirRoot: DIRS.async,
|
|
516
|
+
resultsDir: DIRS.results,
|
|
517
|
+
signal: asyncRetentionAbort.signal,
|
|
518
|
+
protectedRunIds: new Set([
|
|
519
|
+
...state.asyncJobs.keys(),
|
|
520
|
+
...(state.workflowControllers?.keys() ?? []),
|
|
521
|
+
...scheduledRunManager.referencedAsyncRunIds(),
|
|
522
|
+
]),
|
|
523
|
+
});
|
|
524
|
+
} catch (error) {
|
|
525
|
+
console.error("Failed to clean retained async subagent state:", error);
|
|
526
|
+
}
|
|
527
|
+
}, ASYNC_RETENTION_DELAY_MS);
|
|
528
|
+
asyncRetentionTimer.unref?.();
|
|
488
529
|
|
|
489
530
|
const executor = createSubagentExecutor({
|
|
490
531
|
pi,
|
|
@@ -498,6 +539,8 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
498
539
|
getSubagentSessionRoot,
|
|
499
540
|
expandTilde,
|
|
500
541
|
discoverAgents,
|
|
542
|
+
activateSupervisorTransport: () => supervisorChannel.activateTransport(),
|
|
543
|
+
refreshResultDelivery: () => refreshResultDelivery(),
|
|
501
544
|
});
|
|
502
545
|
executorScheduled = executor.executeScheduled;
|
|
503
546
|
|
|
@@ -592,11 +635,12 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
592
635
|
});
|
|
593
636
|
|
|
594
637
|
|
|
595
|
-
const parameters = createSubagentParamsSchema(
|
|
638
|
+
const parameters = createSubagentParamsSchema();
|
|
596
639
|
const tool: ToolDefinition<typeof parameters, Details> = {
|
|
597
640
|
name: "subagent",
|
|
598
641
|
label: "Subagent",
|
|
599
642
|
description: buildSubagentToolDescription(config),
|
|
643
|
+
...buildSubagentToolPromptMetadata(config),
|
|
600
644
|
parameters,
|
|
601
645
|
|
|
602
646
|
execute(id, params, signal, onUpdate, ctx) {
|
|
@@ -607,7 +651,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
607
651
|
const gap = " ".repeat(config.mainWindowRenderer?.horizontalSpacing ?? 1);
|
|
608
652
|
const title = theme.fg("toolTitle", theme.bold("subagent"));
|
|
609
653
|
if (args.action) {
|
|
610
|
-
const target = args.agent ||
|
|
654
|
+
const target = args.agent || "";
|
|
611
655
|
return new Text(
|
|
612
656
|
`${title}${gap}${args.action}${target ? `${gap}${theme.fg("accent", target)}` : ""}`,
|
|
613
657
|
0, 0,
|
|
@@ -667,22 +711,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
667
711
|
foregroundDetachShortcut: config.foregroundDetachShortcut,
|
|
668
712
|
});
|
|
669
713
|
|
|
670
|
-
|
|
671
|
-
const controlNoticeSeenStoreKey = "__piSubagentVisibleControlNotices";
|
|
672
|
-
const previousEventUnsubscribes = globalStore[eventUnsubscribeStoreKey];
|
|
673
|
-
if (Array.isArray(previousEventUnsubscribes)) {
|
|
674
|
-
for (const unsubscribe of previousEventUnsubscribes) {
|
|
675
|
-
if (typeof unsubscribe !== "function") continue;
|
|
676
|
-
try {
|
|
677
|
-
unsubscribe();
|
|
678
|
-
} catch {
|
|
679
|
-
// Best effort cleanup for stale handlers from an older reload.
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
const existingVisibleControlNotices = globalStore[controlNoticeSeenStoreKey];
|
|
684
|
-
const visibleControlNotices = existingVisibleControlNotices instanceof Set ? existingVisibleControlNotices as Set<string> : new Set<string>();
|
|
685
|
-
globalStore[controlNoticeSeenStoreKey] = visibleControlNotices;
|
|
714
|
+
let visibleControlNotices = new Set<string>();
|
|
686
715
|
const activeHerdrRuns = () => projectActiveHerdrRuns(state);
|
|
687
716
|
const herdrStatusBridge = registerHerdrStatusBridge({
|
|
688
717
|
events: pi.events,
|
|
@@ -704,10 +733,13 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
704
733
|
};
|
|
705
734
|
const asyncStartedHandler = (payload: unknown) => {
|
|
706
735
|
handleStarted(payload);
|
|
736
|
+
supervisorChannel.activateTransport();
|
|
737
|
+
refreshResultDelivery();
|
|
707
738
|
fleetStatus?.refresh();
|
|
708
739
|
};
|
|
709
740
|
const asyncCompleteHandler = (payload: unknown) => {
|
|
710
741
|
handleComplete(payload);
|
|
742
|
+
refreshResultDelivery();
|
|
711
743
|
refreshActiveAsyncCapacity();
|
|
712
744
|
scheduledRunManager.handleAsyncCompletion(payload);
|
|
713
745
|
fleetStatus?.refresh();
|
|
@@ -724,7 +756,6 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
724
756
|
herdrStatusBridge.dispose,
|
|
725
757
|
rpcBridge.dispose,
|
|
726
758
|
];
|
|
727
|
-
globalStore[eventUnsubscribeStoreKey] = eventUnsubscribes;
|
|
728
759
|
|
|
729
760
|
pi.on("tool_result", (event, ctx) => {
|
|
730
761
|
if (event.toolName !== "subagent") return;
|
|
@@ -802,6 +833,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
802
833
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
803
834
|
if (sessionId) {
|
|
804
835
|
process.env[SUBAGENT_PARENT_SESSION_ENV] = sessionId;
|
|
836
|
+
parentSessionEnvValue = sessionId;
|
|
805
837
|
}
|
|
806
838
|
}
|
|
807
839
|
state.lastUiContext = ctx;
|
|
@@ -840,6 +872,89 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
840
872
|
fleetStatus?.setContext(ctx);
|
|
841
873
|
};
|
|
842
874
|
|
|
875
|
+
let runtimeCleaned = false;
|
|
876
|
+
const runtimeEntry: SubagentRuntimeEntry = {
|
|
877
|
+
sessionManager: null,
|
|
878
|
+
visibleControlNotices,
|
|
879
|
+
cleanup() {
|
|
880
|
+
if (runtimeCleaned) return;
|
|
881
|
+
runtimeCleaned = true;
|
|
882
|
+
const shuttingDownParentSession = parentSessionEnvValue;
|
|
883
|
+
clearTimeout(resultIndexCleanupTimer);
|
|
884
|
+
clearTimeout(asyncRetentionTimer);
|
|
885
|
+
asyncRetentionAbort.abort();
|
|
886
|
+
stopResultWatcher();
|
|
887
|
+
completionNotifier.dispose();
|
|
888
|
+
mainWatchdog.dispose();
|
|
889
|
+
scheduledRunManager.stop();
|
|
890
|
+
supervisorChannel.dispose();
|
|
891
|
+
waitSubscriptionManager.dispose();
|
|
892
|
+
fleetStatus?.dispose();
|
|
893
|
+
disposeAsyncJobTracker();
|
|
894
|
+
for (const timer of state.cleanupTimers.values()) clearTimeout(timer);
|
|
895
|
+
state.cleanupTimers.clear();
|
|
896
|
+
state.asyncJobs.clear();
|
|
897
|
+
for (const unsubscribe of eventUnsubscribes) {
|
|
898
|
+
try {
|
|
899
|
+
unsubscribe();
|
|
900
|
+
} catch {
|
|
901
|
+
// Best effort cleanup during shutdown or reload.
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
slashBridge.cancelAll();
|
|
905
|
+
slashBridge.dispose();
|
|
906
|
+
promptTemplateBridge.cancelAll();
|
|
907
|
+
promptTemplateBridge.dispose();
|
|
908
|
+
state.widgetsSuspended = false;
|
|
909
|
+
state.currentSessionId = null;
|
|
910
|
+
state.parentSessionFile = null;
|
|
911
|
+
parentSessionEnvValue = null;
|
|
912
|
+
if (shuttingDownParentSession && process.env[SUBAGENT_PARENT_SESSION_ENV] === shuttingDownParentSession) {
|
|
913
|
+
delete process.env[SUBAGENT_PARENT_SESSION_ENV];
|
|
914
|
+
}
|
|
915
|
+
if (runtimeEntry.sessionManager && runtimeRegistry.bySessionManager.get(runtimeEntry.sessionManager) === runtimeEntry) {
|
|
916
|
+
runtimeRegistry.bySessionManager.delete(runtimeEntry.sessionManager);
|
|
917
|
+
}
|
|
918
|
+
runtimeRegistry.activeEntries.delete(runtimeEntry);
|
|
919
|
+
if (runtimeRegistry.activeEntries.size === 0) clearSlashSnapshots();
|
|
920
|
+
try {
|
|
921
|
+
if (state.lastUiContext?.hasUI) state.lastUiContext.ui.setWidget(WIDGET_KEY, undefined);
|
|
922
|
+
} catch (error) {
|
|
923
|
+
if (!isStaleExtensionContextError(error)) throw error;
|
|
924
|
+
}
|
|
925
|
+
state.lastUiContext = null;
|
|
926
|
+
},
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
const installRuntime = (ctx: ExtensionContext) => {
|
|
930
|
+
if (runtimeCleaned) {
|
|
931
|
+
throw new Error("Cannot restart a cleaned pi-subagents extension runtime; register a new extension instance.");
|
|
932
|
+
}
|
|
933
|
+
const sessionManager = ctx.sessionManager as object;
|
|
934
|
+
const previousRuntime = runtimeRegistry.bySessionManager.get(sessionManager);
|
|
935
|
+
const existingVisibleControlNotices = runtimeRegistry.visibleControlNoticesBySessionManager.get(sessionManager);
|
|
936
|
+
if (existingVisibleControlNotices) {
|
|
937
|
+
visibleControlNotices = existingVisibleControlNotices;
|
|
938
|
+
} else {
|
|
939
|
+
runtimeRegistry.visibleControlNoticesBySessionManager.set(sessionManager, visibleControlNotices);
|
|
940
|
+
}
|
|
941
|
+
runtimeEntry.visibleControlNotices = visibleControlNotices;
|
|
942
|
+
if (runtimeEntry.sessionManager && runtimeEntry.sessionManager !== sessionManager
|
|
943
|
+
&& runtimeRegistry.bySessionManager.get(runtimeEntry.sessionManager) === runtimeEntry) {
|
|
944
|
+
runtimeRegistry.bySessionManager.delete(runtimeEntry.sessionManager);
|
|
945
|
+
}
|
|
946
|
+
runtimeEntry.sessionManager = sessionManager;
|
|
947
|
+
runtimeRegistry.bySessionManager.set(sessionManager, runtimeEntry);
|
|
948
|
+
runtimeRegistry.activeEntries.add(runtimeEntry);
|
|
949
|
+
if (previousRuntime && previousRuntime !== runtimeEntry) {
|
|
950
|
+
try {
|
|
951
|
+
previousRuntime.cleanup();
|
|
952
|
+
} catch {
|
|
953
|
+
// Best effort cleanup for stale resources from the replaced runtime.
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
|
|
843
958
|
pi.on("agent_start", () => {
|
|
844
959
|
resumeWidgetsAfterCompaction();
|
|
845
960
|
herdrStatusBridge.agentStarted();
|
|
@@ -867,6 +982,7 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
867
982
|
});
|
|
868
983
|
|
|
869
984
|
pi.on("session_start", (event, ctx) => {
|
|
985
|
+
installRuntime(ctx);
|
|
870
986
|
const recovering = event.reason === "startup" || event.reason === "reload" || event.reason === "resume";
|
|
871
987
|
resetSessionState(ctx, recovering);
|
|
872
988
|
herdrStatusBridge.sessionStarted({
|
|
@@ -875,50 +991,11 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
875
991
|
});
|
|
876
992
|
rpcBridge.emitReady(ctx);
|
|
877
993
|
supervisorChannel.start();
|
|
994
|
+
supervisorChannel.activateTransport();
|
|
878
995
|
});
|
|
879
996
|
|
|
880
997
|
pi.on("session_shutdown", async () => {
|
|
881
|
-
|
|
882
|
-
clearTimeout(resultIndexCleanupTimer);
|
|
883
|
-
stopResultWatcher();
|
|
884
|
-
state.currentSessionId = null;
|
|
885
|
-
state.parentSessionFile = null;
|
|
886
|
-
completionNotifier.dispose();
|
|
887
|
-
delete process.env[SUBAGENT_PARENT_SESSION_ENV];
|
|
888
|
-
for (const unsubscribe of eventUnsubscribes) {
|
|
889
|
-
try {
|
|
890
|
-
unsubscribe();
|
|
891
|
-
} catch {
|
|
892
|
-
// Best effort cleanup during shutdown.
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
if (globalStore[eventUnsubscribeStoreKey] === eventUnsubscribes) {
|
|
896
|
-
delete globalStore[eventUnsubscribeStoreKey];
|
|
897
|
-
}
|
|
898
|
-
scheduledRunManager.stop();
|
|
899
|
-
disposeAsyncJobTracker();
|
|
900
|
-
for (const timer of state.cleanupTimers.values()) {
|
|
901
|
-
clearTimeout(timer);
|
|
902
|
-
}
|
|
903
|
-
state.cleanupTimers.clear();
|
|
904
|
-
state.asyncJobs.clear();
|
|
905
|
-
clearSlashSnapshots();
|
|
906
|
-
slashBridge.cancelAll();
|
|
907
|
-
slashBridge.dispose();
|
|
908
|
-
promptTemplateBridge.cancelAll();
|
|
909
|
-
promptTemplateBridge.dispose();
|
|
910
|
-
supervisorChannel.dispose();
|
|
911
|
-
fleetStatus?.dispose();
|
|
912
|
-
if (globalStore[runtimeCleanupStoreKey] === runtimeCleanup) {
|
|
913
|
-
delete globalStore[runtimeCleanupStoreKey];
|
|
914
|
-
}
|
|
915
|
-
try {
|
|
916
|
-
if (state.lastUiContext?.hasUI) {
|
|
917
|
-
state.lastUiContext.ui.setWidget(WIDGET_KEY, undefined);
|
|
918
|
-
}
|
|
919
|
-
} catch (error) {
|
|
920
|
-
if (!isStaleExtensionContextError(error)) throw error;
|
|
921
|
-
}
|
|
998
|
+
runtimeEntry.cleanup();
|
|
922
999
|
await herdrStatusBridge.flush();
|
|
923
1000
|
});
|
|
924
1001
|
}
|
|
@@ -8,7 +8,11 @@ export interface PublicSubagentExecutionParams {
|
|
|
8
8
|
parallel?: unknown;
|
|
9
9
|
concurrency?: unknown;
|
|
10
10
|
chainDir?: unknown;
|
|
11
|
+
chainName?: unknown;
|
|
12
|
+
config?: unknown;
|
|
11
13
|
workflowScript?: unknown;
|
|
14
|
+
isolation?: unknown;
|
|
15
|
+
worktree?: unknown;
|
|
12
16
|
output?: unknown;
|
|
13
17
|
resume?: unknown;
|
|
14
18
|
clarify?: unknown;
|
|
@@ -27,6 +31,17 @@ export type PublicSubagentExecutionNormalization<T> =
|
|
|
27
31
|
* Internal runs.run children and structured owned delegation bypass this boundary.
|
|
28
32
|
*/
|
|
29
33
|
export function normalizePublicSubagentExecution<T extends PublicSubagentExecutionParams>(params: T): PublicSubagentExecutionNormalization<T> {
|
|
34
|
+
if (params.isolation !== undefined) {
|
|
35
|
+
if (params.isolation !== "none" && params.isolation !== "worktree") {
|
|
36
|
+
return { ok: false, error: "isolation must be 'none' or 'worktree'.", mode: params.workflowScript !== undefined ? "workflow" : "management" };
|
|
37
|
+
}
|
|
38
|
+
const isolationWorktree = params.isolation === "worktree";
|
|
39
|
+
if (params.worktree !== undefined && params.worktree !== isolationWorktree) {
|
|
40
|
+
return { ok: false, error: `isolation '${params.isolation}' conflicts with worktree: ${String(params.worktree)}.`, mode: params.workflowScript !== undefined ? "workflow" : "management" };
|
|
41
|
+
}
|
|
42
|
+
const { isolation: _isolation, ...normalizedParams } = params;
|
|
43
|
+
params = { ...normalizedParams, worktree: isolationWorktree } as T;
|
|
44
|
+
}
|
|
30
45
|
if (params.runFanoutBudget !== undefined || params.runFanoutAdmitted !== undefined) {
|
|
31
46
|
return { ok: false, error: "Public execution does not accept internal run fan-out fields.", mode: params.workflowScript !== undefined ? "workflow" : "management" };
|
|
32
47
|
}
|
|
@@ -38,6 +53,12 @@ export function normalizePublicSubagentExecution<T extends PublicSubagentExecuti
|
|
|
38
53
|
if (params.clarify !== undefined) {
|
|
39
54
|
return { ok: false, error: "Public workflowScript execution does not support clarify UI.", mode: "workflow" };
|
|
40
55
|
}
|
|
56
|
+
if (params.chainName !== undefined) {
|
|
57
|
+
return { ok: false, error: "Durable chain management was removed; use workflowScript or /prompt-workflow for repeatable workflows.", mode: "management" };
|
|
58
|
+
}
|
|
59
|
+
if (params.config && typeof params.config === "object" && !Array.isArray(params.config) && Object.prototype.hasOwnProperty.call(params.config, "steps")) {
|
|
60
|
+
return { ok: false, error: "Durable chain definitions were removed; use workflowScript or /prompt-workflow for repeatable workflows.", mode: "management" };
|
|
61
|
+
}
|
|
41
62
|
if (params.resume !== undefined) {
|
|
42
63
|
return { ok: false, error: "Top-level resume execution is not available. Put resume on a workflowScript runs.run/runs.all item.", mode: "workflow" };
|
|
43
64
|
}
|
|
@@ -47,6 +68,12 @@ export function normalizePublicSubagentExecution<T extends PublicSubagentExecuti
|
|
|
47
68
|
}
|
|
48
69
|
if (normalizedAction !== undefined) {
|
|
49
70
|
const legacyAction = normalizedAction.toLowerCase();
|
|
71
|
+
if (legacyAction === "append-step") {
|
|
72
|
+
return { ok: false, error: "Legacy append-step control was removed from the public subagent tool; use current workflowScript orchestration.", mode: "management" };
|
|
73
|
+
}
|
|
74
|
+
if (legacyAction === "approve-checkpoint" || legacyAction === "reject-checkpoint") {
|
|
75
|
+
return { ok: false, error: "Legacy checkpoint approval controls were removed from the public subagent tool; use current workflowScript orchestration.", mode: "management" };
|
|
76
|
+
}
|
|
50
77
|
if (legacyAction === "single") {
|
|
51
78
|
return { ok: false, error: "action='single' is not supported. Omit action and pass { agent, task } for one child.", mode: "workflow" };
|
|
52
79
|
}
|
|
@@ -71,7 +98,7 @@ export function normalizePublicSubagentExecution<T extends PublicSubagentExecuti
|
|
|
71
98
|
return { ok: true, params: { ...params, action: normalizedAction } };
|
|
72
99
|
}
|
|
73
100
|
if (params.step !== undefined) {
|
|
74
|
-
return { ok: false, error: "step is
|
|
101
|
+
return { ok: false, error: "step is not a public execution field; use workflowScript for orchestration.", mode: "workflow" };
|
|
75
102
|
}
|
|
76
103
|
if (params.workflowScript !== undefined && (params.agent !== undefined || params.task !== undefined)) {
|
|
77
104
|
return { ok: false, error: "Structured single-child execution cannot be combined with workflowScript.", mode: "workflow" };
|
package/src/extension/schemas.ts
CHANGED
|
@@ -188,8 +188,6 @@ export const DynamicCollectSchema = Type.Object({
|
|
|
188
188
|
|
|
189
189
|
// Flattened so chain steps do not need an object-shape anyOf/oneOf union.
|
|
190
190
|
export const ChainItem = Type.Object({
|
|
191
|
-
checkpoint: Type.Optional(Type.String({ description: "Approval checkpoint name. Pauses the chain without launching a child until approve-checkpoint or reject-checkpoint is called." })),
|
|
192
|
-
message: Type.Optional(Type.String({ description: "Optional approval message shown while the checkpoint is paused." })),
|
|
193
191
|
agent: Type.Optional(Type.String({ description: "Sequential step agent name" })),
|
|
194
192
|
task: Type.Optional(Type.String({
|
|
195
193
|
description: "Task template with variables: {task}=original request, {previous}=prior step's text response, {chain_dir}=shared folder, {outputs.name}=prior named output. Required for first step, defaults to '{previous}' for subsequent steps."
|
|
@@ -224,7 +222,7 @@ export const ChainItem = Type.Object({
|
|
|
224
222
|
description: "Create isolated git worktrees for each parallel task."
|
|
225
223
|
})),
|
|
226
224
|
}, {
|
|
227
|
-
description: "Chain step: use {agent, task?, ...} for sequential, {parallel: [...]} for static concurrent execution, {expand, parallel: {...}, collect} for dynamic fanout
|
|
225
|
+
description: "Chain step: use {agent, task?, ...} for sequential, {parallel: [...]} for static concurrent execution, or {expand, parallel: {...}, collect} for dynamic fanout.",
|
|
228
226
|
additionalProperties: false,
|
|
229
227
|
});
|
|
230
228
|
|
|
@@ -257,17 +255,16 @@ const ControlOverrides = Type.Object({
|
|
|
257
255
|
const SubagentParamProperties = {
|
|
258
256
|
agent: Type.Optional(Type.String({ description: "Agent for one-child execution, or target for agent management actions." })),
|
|
259
257
|
task: Type.Optional(Type.String({ description: "Optional one-child task. Requires agent; cannot combine with action or workflowScript." })),
|
|
260
|
-
resume: Type.Optional(Type.String({ description: "Retained child run id for a workflowScript runs.run/runs.all item. Mutually exclusive with agent; task supplies the follow-up." })),
|
|
261
258
|
// Management action (when present, tool operates in management mode)
|
|
262
259
|
action: Type.Optional(Type.String({ minLength: 1,
|
|
263
260
|
description: "Optional management/control action. Omit this field for structured single-child or workflowScript execution; use it only for management/control actions."
|
|
264
261
|
})),
|
|
265
262
|
name: Type.Optional(Type.String({ description: "Human-readable name for action='schedule.create'." })),
|
|
266
263
|
id: Type.Optional(Type.String({
|
|
267
|
-
description: "Run id/prefix for status/debug.run, interrupt, steer,
|
|
264
|
+
description: "Run id/prefix for status/debug.run, interrupt, steer, or mission.attach-run."
|
|
268
265
|
})),
|
|
269
266
|
runId: Type.Optional(Type.String({
|
|
270
|
-
description: "Target run ID for debug.run, interrupt, steer,
|
|
267
|
+
description: "Target run ID for debug.run, interrupt, steer, or mission.attach-run. Prefer id."
|
|
271
268
|
})),
|
|
272
269
|
dir: Type.Optional(Type.String({
|
|
273
270
|
description: "Async run directory for status/debug.run, stop, resume, or steer."
|
|
@@ -288,8 +285,6 @@ const SubagentParamProperties = {
|
|
|
288
285
|
target: Type.Optional(Type.String({ enum: ["main", "children", "child"], description: "Target for watchdog actions." })),
|
|
289
286
|
focus: Type.Optional(Type.Boolean({ description: "Focus the new Herdr pane for inspector.open or project.open." })),
|
|
290
287
|
thinking: Type.Optional(Type.Unsafe({ anyOf: [{ type: "string" }, { type: "boolean", enum: [false] }], description: "Thinking level for action='watchdog.configure' (off/minimal/low/medium/high/xhigh/max, inherit, or false for off)." })),
|
|
291
|
-
schedule: Type.Optional(Type.String({ deprecated: true, description: "Removed one-shot schedule field. Use action='schedule.create' with at." })),
|
|
292
|
-
scheduleName: Type.Optional(Type.String({ deprecated: true, description: "Removed schedule display field. Use name." })),
|
|
293
288
|
at: Type.Optional(Type.String({ description: "One-shot trigger for action='schedule.create': a relative delay such as '+10m' or an ISO timestamp with timezone." })),
|
|
294
289
|
every: Type.Optional(Type.String({ description: "Fixed recurring interval for action='schedule.create', such as '30m', '6h', '2d', or '2w'." })),
|
|
295
290
|
on: Type.Optional(Type.Unsafe({ anyOf: [{ type: "string" }, { type: "integer" }], description: "Calendar selector reserved for a later schedule slice." })),
|
|
@@ -304,27 +299,23 @@ const SubagentParamProperties = {
|
|
|
304
299
|
runMode: Type.Optional(Type.String({ description: "Attached run mode." })),
|
|
305
300
|
runStatus: Type.Optional(Type.String({ description: "Attached run status." })),
|
|
306
301
|
summary: Type.Optional(Type.String({ description: "Mission close summary." })),
|
|
307
|
-
//
|
|
308
|
-
chainName: Type.Optional(Type.String({
|
|
309
|
-
description: "Chain name for get/update/delete management actions"
|
|
310
|
-
})),
|
|
311
|
-
// Agent/chain configuration for create/update (nested to avoid conflicts with execution fields)
|
|
302
|
+
// Agent configuration for create/update (nested to avoid conflicts with execution fields)
|
|
312
303
|
config: Type.Optional(Type.Unsafe({
|
|
313
304
|
anyOf: [
|
|
314
305
|
{ type: "object", additionalProperties: true },
|
|
315
306
|
{ type: "string" },
|
|
316
307
|
],
|
|
317
|
-
description: "Agent
|
|
308
|
+
description: "Agent config for create/update. Object or JSON string."
|
|
318
309
|
})),
|
|
319
|
-
workflowScript: Type.Optional(Type.String({ minLength: 1, description: "Trusted inline JavaScript statement body.
|
|
320
|
-
chatProgress: Type.Optional(Type.String({ enum: ["auto", "off", "live-card"], description: "WorkflowScript chat progress projection. auto shows a live in-chat card only for watched foreground workflows in the same Git repository; it is off otherwise." })),
|
|
310
|
+
workflowScript: Type.Optional(Type.String({ minLength: 1, description: "Trusted inline JavaScript statement body. Normally async unless asyncByDefault:false; set async:true when async matters. Use async:false only when the parent must block until completion, never for reviews or gates. Use explicit return for output. Use top-level await, plain helper functions, or explicit Promise chains; nested async function, arrow, and method helpers are rejected. Use await runs.run(key, {agent, task, worktree?, gate?}) or runs.run(key, {resume, task}), runs.all([...]), await runs.steer(key, message, {mode?, index?, ackTimeoutMs?}), runs.status(id), runs.ref(s), emit(value), console, and return. For ordinary parallel fanout, use await runs.all([{key, agent, task}, ...]); do not read .output from unawaited runs.run launches. Stored runs.run promises are only for advanced rolling fanout, and each must later be observed with direct await, Promise.race, or Promise.all. runs.steer targets a prior stable child key, never a raw run id, and must be awaited or returned. Mission workflows also have async state.get(key) and state.set(key, JSONValue). Compose sequential and parallel phases dynamically. Set worktree:true at workflow or child level for a separate managed worktree; child fields override workflow defaults. gate is one host-run command and cannot be combined with acceptance. runs.run accepts one child only. No filesystem, shell, Pi tools, or host globals." })),
|
|
311
|
+
chatProgress: Type.Optional(Type.String({ enum: ["auto", "off", "live-card"], description: "WorkflowScript chat progress projection. auto shows a live in-chat card only for watched foreground workflows in the same Git repository; it is off otherwise. Explicit live-card requires same-repository async:false; async workflows should omit chatProgress or use auto/off." })),
|
|
312
|
+
isolation: Type.Optional(Type.String({ enum: ["none", "worktree"], description: "Workflow child isolation. none runs in the shared cwd; worktree requires managed git worktree isolation." })),
|
|
321
313
|
worktree: Type.Optional(Type.Boolean({ description: "Managed child isolation. true gives each workflow child a separate git worktree; an individual runs.run/runs.all item can override a workflow default with worktree:false." })),
|
|
322
|
-
step: Type.Optional(Type.Unsafe({ ...ChainItem, description: "One chain step for action='append-step' only. Not an execution mode." })),
|
|
323
314
|
context: Type.Optional(Type.String({
|
|
324
315
|
enum: ["fresh", "fork"],
|
|
325
|
-
description: "'fresh' or 'fork' to branch from parent session. Explicit context overrides every child
|
|
316
|
+
description: "'fresh' or 'fork' to branch from parent session. Explicit context overrides every child. If omitted, config defaultSubagentContext wins over each agent defaultContext; implicit fork needs a persisted parent session and leaf, else fresh.",
|
|
326
317
|
})),
|
|
327
|
-
async: Type.Optional(Type.Boolean({ description: "Run in background
|
|
318
|
+
async: Type.Optional(Type.Boolean({ description: "Run in background unless asyncByDefault:false. Set false only when the parent must block until completion." })),
|
|
328
319
|
timeoutMs: Type.Optional(Type.Integer({ minimum: 1, description: "Timeout. Foreground and single async runs use config timeoutMs, else 30m; async composites have no default parent deadline. Alias maxRuntimeMs." })),
|
|
329
320
|
maxRuntimeMs: Type.Optional(Type.Integer({ minimum: 1, description: "Alias timeoutMs. Foreground and single async runs use config timeoutMs, else 30m; async composites have no default parent deadline." })),
|
|
330
321
|
toolTimeoutMs: Type.Optional(Type.Integer({ minimum: 1, description: "Optional hard per-tool-call timeout in milliseconds; known-fast built-in tools have a five-minute default." })),
|
|
@@ -357,26 +348,12 @@ const SubagentParamProperties = {
|
|
|
357
348
|
gate: Type.Optional(Type.String({ minLength: 1, description: "Host gate command. Cannot be combined with acceptance." })),
|
|
358
349
|
};
|
|
359
350
|
|
|
360
|
-
const { step: _legacyChainStep, ...subagentParamPropertiesWithoutStep } = SubagentParamProperties;
|
|
361
|
-
const trimmedSubagentParamProperties = {
|
|
362
|
-
...subagentParamPropertiesWithoutStep,
|
|
363
|
-
id: Type.Optional(Type.String({
|
|
364
|
-
description: "Run id/prefix for status/debug.run, interrupt, steer, or mission.attach-run."
|
|
365
|
-
})),
|
|
366
|
-
runId: Type.Optional(Type.String({
|
|
367
|
-
description: "Target run ID for debug.run, interrupt, steer, or mission.attach-run. Prefer id."
|
|
368
|
-
})),
|
|
369
|
-
};
|
|
370
351
|
const SubagentParamsSchema = Type.Object(SubagentParamProperties);
|
|
371
|
-
const TrimmedSubagentParamsSchema = Type.Object(trimmedSubagentParamProperties);
|
|
372
352
|
|
|
373
353
|
export const SubagentParams = keepTopLevelParameterDescriptions(SubagentParamsSchema);
|
|
374
|
-
export const SubagentParamsWithoutLegacyChainControls = keepTopLevelParameterDescriptions(TrimmedSubagentParamsSchema);
|
|
375
354
|
|
|
376
|
-
export function createSubagentParamsSchema(
|
|
377
|
-
return
|
|
378
|
-
? SubagentParams
|
|
379
|
-
: SubagentParamsWithoutLegacyChainControls;
|
|
355
|
+
export function createSubagentParamsSchema(): typeof SubagentParams {
|
|
356
|
+
return SubagentParams;
|
|
380
357
|
}
|
|
381
358
|
|
|
382
359
|
const SubagentWaitParamsSchema = Type.Object({
|