@gajae-code/coding-agent 0.18.11 → 0.18.12
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 +293 -0
- package/dist/types/async/job-manager.d.ts +7 -3
- package/dist/types/async/result-formatting.d.ts +2 -0
- package/dist/types/autoresearch/git.d.ts +1 -1
- package/dist/types/capability/fs.d.ts +2 -2
- package/dist/types/cli/accounts-cli.d.ts +2 -2
- package/dist/types/cli/doctor/install-repairs.d.ts +4 -1
- package/dist/types/cli/install-activation.d.ts +10 -4
- package/dist/types/cli/public-command-errors.d.ts +1 -0
- package/dist/types/cli/update-cli.d.ts +14 -1
- package/dist/types/cli-ordinary.d.ts +2 -2
- package/dist/types/commands/accounts.d.ts +2 -1
- package/dist/types/commands/migrate.d.ts +1 -1
- package/dist/types/commands/sdk.d.ts +5 -0
- package/dist/types/commit/changelog/index.d.ts +1 -0
- package/dist/types/config/autorouting-tier-map.d.ts +30 -0
- package/dist/types/config/config-hot-reload-trust.d.ts +12 -0
- package/dist/types/config/config-hot-reload.d.ts +39 -0
- package/dist/types/config/file-lock.d.ts +8 -1
- package/dist/types/config/model-discovery-manager.d.ts +2 -0
- package/dist/types/config/model-profile-activation.d.ts +62 -6
- package/dist/types/config/model-registry.d.ts +56 -5
- package/dist/types/config/model-resolver.d.ts +2 -0
- package/dist/types/config/models-config-schema.d.ts +10 -0
- package/dist/types/config/settings-schema.d.ts +46 -3
- package/dist/types/config/settings.d.ts +33 -1
- package/dist/types/dap/config.d.ts +8 -4
- package/dist/types/debug/system-info.d.ts +6 -1
- package/dist/types/discovery/mcp-compat.d.ts +3 -1
- package/dist/types/edit/modes/patch.d.ts +5 -0
- package/dist/types/edit/modes/replace.d.ts +3 -0
- package/dist/types/exec/bash-executor.d.ts +12 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +3 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +2 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +0 -2
- package/dist/types/migrate/adapters/codex.d.ts +2 -1
- package/dist/types/migrate/adapters/index.d.ts +10 -1
- package/dist/types/migrate/executor.d.ts +3 -1
- package/dist/types/migrate/types.d.ts +15 -3
- package/dist/types/modes/components/settings-selector.d.ts +6 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +2 -0
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/runtime-mcp/content-limits.d.ts +4 -0
- package/dist/types/runtime-mcp/manager.d.ts +7 -0
- package/dist/types/runtime-mcp/plugin-mcp-name-filter.d.ts +22 -0
- package/dist/types/runtime-mcp/tool-bridge.d.ts +4 -0
- package/dist/types/sdk/broker/broker-exit.d.ts +2 -2
- package/dist/types/sdk/broker/broker.d.ts +7 -1
- package/dist/types/sdk/broker/daemon-entry.d.ts +11 -1
- package/dist/types/sdk/broker/doctor-restart.d.ts +1 -1
- package/dist/types/sdk/broker/ensure.d.ts +136 -7
- package/dist/types/sdk/broker/hop.d.ts +36 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +18 -10
- package/dist/types/sdk/broker/lock-host-identity.d.ts +5 -0
- package/dist/types/sdk/broker/session-index.d.ts +4 -1
- package/dist/types/sdk/bus/chat-command-policy.d.ts +2 -1
- package/dist/types/sdk/bus/index.d.ts +23 -0
- package/dist/types/sdk/bus/reconciliation-store.d.ts +10 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -1
- package/dist/types/sdk/cli/session-cli.d.ts +0 -1
- package/dist/types/sdk/host/session-runtime.d.ts +32 -0
- package/dist/types/sdk/prompt-deadline-flush.d.ts +42 -4
- package/dist/types/sdk/prompt-deadline-manager.d.ts +2 -0
- package/dist/types/sdk/protocol/adapter-validation.d.ts +10 -4
- package/dist/types/sdk/reconciliation-extensions.d.ts +1 -1
- package/dist/types/sdk/session-list.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +58 -2
- package/dist/types/session/internal/managed-session-scope.d.ts +2 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +1 -1
- package/dist/types/session/internal/native-publish-outcome.d.ts +1 -1
- package/dist/types/session/messages.d.ts +5 -1
- package/dist/types/session/session-manager.d.ts +13 -3
- package/dist/types/session/startup-auth-config.d.ts +24 -2
- package/dist/types/session/streaming-output.d.ts +11 -0
- package/dist/types/session/terminal-abort.d.ts +3 -1
- package/dist/types/session-import/service.d.ts +1 -1
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +7 -3
- package/dist/types/slash-commands/helpers/provider-auth-status.d.ts +8 -0
- package/dist/types/task/executor.d.ts +19 -2
- package/dist/types/tools/ast-edit-write-path.d.ts +10 -0
- package/dist/types/tools/atomic-file-write.d.ts +9 -7
- package/dist/types/tools/bash-allowed-prefixes.d.ts +11 -0
- package/dist/types/tools/descriptors.d.ts +2 -0
- package/dist/types/tools/fetch.d.ts +1 -1
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/python.d.ts +1 -1
- package/dist/types/tools/report-issue.d.ts +41 -0
- package/dist/types/tools/subagent.d.ts +23 -0
- package/dist/types/web/scrapers/types.d.ts +8 -1
- package/dist/types/web/search/providers/insane.d.ts +7 -1
- package/dist/types/web/search/providers/searxng.d.ts +5 -0
- package/package.json +8 -8
- package/scripts/build-binary.ts +2 -1
- package/scripts/capture-subagent-compact-panel-showcase.ts +105 -0
- package/scripts/generate-docs-index.ts +8 -1
- package/scripts/generate-sdk-operation-inventory.ts +22 -4
- package/src/async/job-manager.ts +356 -56
- package/src/async/result-formatting.ts +40 -0
- package/src/autoresearch/git.ts +9 -2
- package/src/autoresearch/prompts/prompt-setup.md +1 -1
- package/src/capability/fs.ts +27 -19
- package/src/capability/index.ts +2 -2
- package/src/cli/accounts-cli.ts +176 -8
- package/src/cli/auth-broker-cli.ts +21 -11
- package/src/cli/doctor/install-repairs.ts +35 -5
- package/src/cli/fast-help.ts +1 -1
- package/src/cli/install-activation.ts +47 -4
- package/src/cli/migrate-cli.ts +7 -5
- package/src/cli/public-command-errors.ts +4 -0
- package/src/cli/root-flags.ts +2 -2
- package/src/cli/stats-cli.ts +9 -5
- package/src/cli/update-cli.ts +224 -7
- package/src/cli-ordinary.ts +7 -2
- package/src/commands/accounts.ts +10 -5
- package/src/commands/migrate.ts +3 -3
- package/src/commands/sdk.ts +199 -42
- package/src/commands/ultragoal.ts +16 -8
- package/src/commit/changelog/index.ts +39 -1
- package/src/commit/message.ts +10 -3
- package/src/config/autorouting-tier-map.ts +30 -0
- package/src/config/config-hot-reload-trust.ts +148 -0
- package/src/config/config-hot-reload.ts +734 -0
- package/src/config/file-lock.ts +216 -56
- package/src/config/model-bindings-applier.ts +85 -47
- package/src/config/model-discovery-manager.ts +10 -0
- package/src/config/model-profile-activation.ts +716 -113
- package/src/config/model-registry.ts +1334 -158
- package/src/config/model-resolver.ts +3 -1
- package/src/config/models-config-schema.ts +6 -0
- package/src/config/settings-schema.ts +60 -3
- package/src/config/settings.ts +458 -24
- package/src/coordinator-mcp/policy.ts +26 -1
- package/src/crash/sanitize.ts +4 -0
- package/src/customization/import.ts +3 -1
- package/src/dap/config.ts +31 -11
- package/src/dap/defaults.json +1 -1
- package/src/debug/crash-diagnostics.ts +2 -1
- package/src/debug/report-bundle.ts +19 -0
- package/src/debug/system-info.ts +8 -3
- package/src/defaults/gjc/extensions/grok-cli-vendor/src/shared/base-url.ts +21 -7
- package/src/discovery/agents-md.ts +1 -1
- package/src/discovery/helpers.ts +1 -2
- package/src/discovery/mcp-compat.ts +120 -17
- package/src/edit/apply-patch/index.ts +12 -1
- package/src/edit/index.ts +13 -17
- package/src/edit/modes/patch.ts +187 -8
- package/src/edit/modes/replace.ts +136 -0
- package/src/eval/js/context-manager.ts +29 -3
- package/src/eval/js/worker-entry.ts +51 -18
- package/src/eval/py/executor.ts +14 -4
- package/src/eval/py/runner.py +144 -5
- package/src/exec/bash-executor.ts +81 -4
- package/src/exec/bash-shell-guardian.ts +4 -1
- package/src/exec/bash-shell-supervisor.ts +8 -4
- package/src/exec/isolated-shell.ts +5 -1
- package/src/export/html/index.ts +46 -6
- package/src/extensibility/custom-tools/wrapper.ts +3 -1
- package/src/extensibility/extensions/loader.ts +8 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -2
- package/src/gjc-runtime/gc-runtime.ts +33 -6
- package/src/gjc-runtime/launch-tmux.ts +7 -2
- package/src/gjc-runtime/launch-worktree.test.ts +148 -0
- package/src/gjc-runtime/launch-worktree.ts +101 -14
- package/src/gjc-runtime/managed-owner-admission.ts +46 -2
- package/src/gjc-runtime/session-resolution.ts +38 -6
- package/src/gjc-runtime/session-state-lock.ts +59 -14
- package/src/gjc-runtime/state-runtime.ts +23 -19
- package/src/hooks/native-skill-hook.ts +14 -11
- package/src/internal-urls/docs-index.generated.ts +14 -13
- package/src/internal-urls/local-protocol.ts +142 -8
- package/src/lsp/index.ts +29 -0
- package/src/lsp/workspace-path.ts +23 -0
- package/src/migrate/action-planner.ts +57 -0
- package/src/migrate/adapters/claude-code.ts +23 -4
- package/src/migrate/adapters/codex.ts +22 -4
- package/src/migrate/adapters/index.ts +22 -4
- package/src/migrate/adapters/opencode.ts +6 -1
- package/src/migrate/executor.ts +84 -7
- package/src/migrate/report.ts +19 -2
- package/src/migrate/types.ts +14 -4
- package/src/modes/DESIGN.md +51 -0
- package/src/modes/acp/permission-mode.ts +18 -1
- package/src/modes/components/assistant-message.ts +55 -1
- package/src/modes/components/settings-selector.ts +103 -37
- package/src/modes/controllers/command-controller.ts +38 -2
- package/src/modes/controllers/plan-mode-controller.ts +17 -7
- package/src/modes/controllers/selector-controller.ts +62 -6
- package/src/modes/interactive-mode.ts +68 -0
- package/src/modes/theme/theme.ts +15 -0
- package/src/prompts/tools/debug.md +1 -1
- package/src/prompts/tools/read.md +1 -1
- package/src/prompts/tools/report-issue.md +13 -0
- package/src/prompts/tools/task.md +1 -1
- package/src/runtime-credential-selector.ts +2 -2
- package/src/runtime-mcp/content-limits.ts +7 -0
- package/src/runtime-mcp/manager-pool.test.ts +5 -4
- package/src/runtime-mcp/manager.ts +32 -0
- package/src/runtime-mcp/oauth-flow.ts +32 -6
- package/src/runtime-mcp/plugin-mcp-name-filter.ts +62 -0
- package/src/runtime-mcp/render.ts +16 -1
- package/src/runtime-mcp/tool-bridge.ts +126 -17
- package/src/sdk/broker/broker-exit.ts +8 -5
- package/src/sdk/broker/broker.ts +342 -82
- package/src/sdk/broker/daemon-entry.ts +338 -116
- package/src/sdk/broker/doctor-restart.ts +2 -1
- package/src/sdk/broker/ensure.ts +1143 -265
- package/src/sdk/broker/hop.ts +274 -0
- package/src/sdk/broker/lifecycle-ledger.ts +35 -11
- package/src/sdk/broker/lock-host-identity.ts +29 -0
- package/src/sdk/broker/session-index.ts +62 -12
- package/src/sdk/bus/chat-command-policy.ts +16 -3
- package/src/sdk/bus/index.ts +52 -21
- package/src/sdk/bus/reconciliation-store.ts +201 -8
- package/src/sdk/bus/telegram-daemon-contract.ts +3 -1
- package/src/sdk/cli/session-cli.ts +21 -6
- package/src/sdk/host/session-runtime.test.ts +118 -23
- package/src/sdk/host/session-runtime.ts +352 -47
- package/src/sdk/lifecycle/service.ts +1 -0
- package/src/sdk/prompt-deadline-flush.ts +78 -5
- package/src/sdk/prompt-deadline-manager.ts +68 -14
- package/src/sdk/protocol/adapter-validation.ts +53 -11
- package/src/sdk/protocol/operation-inventory.generated.json +101 -2
- package/src/sdk/reconciliation-extensions.ts +1 -0
- package/src/sdk/session-list.ts +1 -0
- package/src/sdk/session.ts +114 -61
- package/src/session/agent-session.ts +1043 -81
- package/src/session/internal/managed-session-scope.ts +126 -39
- package/src/session/internal/managed-session-storage.ts +14 -11
- package/src/session/internal/native-publish-outcome.ts +5 -1
- package/src/session/messages.ts +47 -6
- package/src/session/session-manager.ts +236 -14
- package/src/session/startup-auth-config.ts +116 -8
- package/src/session/streaming-output.ts +262 -4
- package/src/session/terminal-abort.ts +14 -2
- package/src/session-import/service.ts +1 -0
- package/src/skill-state/workflow-mutation-guard.ts +491 -32
- package/src/slash-commands/builtin-registry.ts +15 -3
- package/src/slash-commands/helpers/credential-switch.ts +10 -5
- package/src/slash-commands/helpers/provider-auth-status.ts +456 -0
- package/src/task/executor.ts +103 -12
- package/src/task/index.ts +389 -175
- package/src/tools/ast-edit-write-path.ts +64 -0
- package/src/tools/ast-edit.ts +18 -1
- package/src/tools/atomic-file-write.ts +46 -15
- package/src/tools/auto-generated-guard.ts +3 -0
- package/src/tools/bash-allowed-prefixes.ts +153 -5
- package/src/tools/bash-interactive.ts +14 -2
- package/src/tools/bash.ts +14 -0
- package/src/tools/debug.ts +7 -6
- package/src/tools/descriptors.test.ts +44 -0
- package/src/tools/descriptors.ts +34 -2
- package/src/tools/fetch.ts +3 -2
- package/src/tools/index.ts +2 -0
- package/src/tools/output-meta.ts +23 -2
- package/src/tools/python.ts +1 -1
- package/src/tools/read.ts +17 -35
- package/src/tools/report-issue.ts +184 -0
- package/src/tools/subagent-render.ts +114 -12
- package/src/tools/subagent.ts +108 -1
- package/src/tools/todo-write.ts +41 -3
- package/src/tools/tool-catalog.generated.ts +31 -3
- package/src/tools/write.ts +35 -3
- package/src/utils/commit-message-generator.ts +9 -2
- package/src/utils/file-mentions.ts +29 -1
- package/src/utils/title-generator.ts +7 -2
- package/src/web/scrapers/index.ts +3 -1
- package/src/web/scrapers/types.ts +8 -0
- package/src/web/scrapers/youtube.ts +3 -2
- package/src/web/search/providers/insane.ts +91 -28
- package/src/web/search/providers/searxng.ts +62 -10
package/src/task/index.ts
CHANGED
|
@@ -31,6 +31,7 @@ import { AUTOROUTING_SELECTOR_MAX_LENGTH, type AutoroutingReasonCode } from "../
|
|
|
31
31
|
import { resolveProfileBindings } from "../config/model-profiles";
|
|
32
32
|
import { resolveAgentModelPatterns } from "../config/model-resolver";
|
|
33
33
|
import type { Theme } from "../modes/theme/theme";
|
|
34
|
+
import type { PlanModeState } from "../plan-mode/state";
|
|
34
35
|
import planModeSubagentPrompt from "../prompts/system/plan-mode-subagent.md" with { type: "text" };
|
|
35
36
|
import taskSummaryTemplate from "../prompts/tools/task-summary.md" with { type: "text" };
|
|
36
37
|
import type { ForkContextSeed } from "../session/agent-session";
|
|
@@ -118,11 +119,17 @@ interface DuplicateDisposition {
|
|
|
118
119
|
predecessorIds: string[];
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
interface TaskArtifactPersistence {
|
|
123
|
+
effectiveArtifactsDir: string | undefined;
|
|
124
|
+
parentArtifactManager: ArtifactManager | undefined;
|
|
125
|
+
}
|
|
126
|
+
|
|
121
127
|
interface TaskResumeDescriptor {
|
|
122
128
|
toolCallId: string;
|
|
123
129
|
params: TaskParams;
|
|
124
130
|
task: TaskItem & { id: string };
|
|
125
131
|
sessionFile: string | null;
|
|
132
|
+
artifactPersistence: TaskArtifactPersistence;
|
|
126
133
|
durableOutputAllowed?: boolean;
|
|
127
134
|
forkContextSeed?: ForkContextSeed;
|
|
128
135
|
agentSource: AgentDefinition["source"];
|
|
@@ -136,6 +143,96 @@ interface TaskResumeDescriptor {
|
|
|
136
143
|
function isTaskResumeDescriptor(value: unknown): value is TaskResumeDescriptor {
|
|
137
144
|
return typeof value === "object" && value !== null && "task" in value && "params" in value;
|
|
138
145
|
}
|
|
146
|
+
|
|
147
|
+
/** Retain the caller-visible execution inputs for detached and resumed runs. */
|
|
148
|
+
function captureTaskExecutionScope(session: ToolSession): ToolSession {
|
|
149
|
+
const snapshot = new Map<PropertyKey, unknown>([
|
|
150
|
+
["cwd", session.cwd],
|
|
151
|
+
["hasUI", session.hasUI],
|
|
152
|
+
["contextFiles", session.contextFiles ? [...session.contextFiles] : undefined],
|
|
153
|
+
["workspaceTree", session.workspaceTree],
|
|
154
|
+
["home", session.home],
|
|
155
|
+
["profileAuthority", session.profileAuthority],
|
|
156
|
+
["skills", session.skills ? [...session.skills] : undefined],
|
|
157
|
+
["promptTemplates", session.promptTemplates ? [...session.promptTemplates] : undefined],
|
|
158
|
+
["enableLsp", session.enableLsp],
|
|
159
|
+
["hasEditTool", session.hasEditTool],
|
|
160
|
+
["eventBus", session.eventBus],
|
|
161
|
+
["outputSchema", session.outputSchema],
|
|
162
|
+
["requireYieldTool", session.requireYieldTool],
|
|
163
|
+
["taskDepth", session.taskDepth],
|
|
164
|
+
["currentAgentType", session.currentAgentType],
|
|
165
|
+
["model", session.model],
|
|
166
|
+
["settings", session.settings.snapshot()],
|
|
167
|
+
["serviceTier", session.serviceTier],
|
|
168
|
+
["authStorage", session.authStorage],
|
|
169
|
+
["modelRegistry", session.modelRegistry],
|
|
170
|
+
["agentRegistry", session.agentRegistry],
|
|
171
|
+
]);
|
|
172
|
+
for (const key of [
|
|
173
|
+
"getSessionFile",
|
|
174
|
+
"getSessionSpawns",
|
|
175
|
+
"getSessionId",
|
|
176
|
+
"getAsyncEndpointId",
|
|
177
|
+
"getAsyncJobManager",
|
|
178
|
+
"getCredentialSessionId",
|
|
179
|
+
"getAgentId",
|
|
180
|
+
"getSessionAgentDir",
|
|
181
|
+
"getActiveModelString",
|
|
182
|
+
"getModelString",
|
|
183
|
+
"getActiveModelProfile",
|
|
184
|
+
"getCompactContext",
|
|
185
|
+
"getMcpManager",
|
|
186
|
+
"getHindsightSessionState",
|
|
187
|
+
"isManagedSessionDestination",
|
|
188
|
+
] as const) {
|
|
189
|
+
const accessor: unknown = Reflect.get(session, key, session);
|
|
190
|
+
if (typeof accessor === "function") {
|
|
191
|
+
const value: unknown = Reflect.apply(accessor, session, []);
|
|
192
|
+
snapshot.set(key, () => value);
|
|
193
|
+
} else {
|
|
194
|
+
snapshot.set(key, accessor);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const boundMethods = new Map<PropertyKey, { source: unknown; bound: unknown }>();
|
|
199
|
+
return new Proxy(session, {
|
|
200
|
+
get(target, property) {
|
|
201
|
+
if (snapshot.has(property)) return snapshot.get(property);
|
|
202
|
+
const value: unknown = Reflect.get(target, property, target);
|
|
203
|
+
if (typeof value !== "function") return value;
|
|
204
|
+
const cached = boundMethods.get(property);
|
|
205
|
+
if (cached?.source === value) return cached.bound;
|
|
206
|
+
const bound = value.bind(target);
|
|
207
|
+
boundMethods.set(property, { source: value, bound });
|
|
208
|
+
return bound;
|
|
209
|
+
},
|
|
210
|
+
}) as ToolSession;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Approval policy copied into a task child. A missing mode stays `allow`, the child default. */
|
|
214
|
+
function inheritedSubagentApproval(session: ToolSession) {
|
|
215
|
+
const mode = session.getSdkPermissionMode?.();
|
|
216
|
+
return {
|
|
217
|
+
sdkPermissionMode: mode === "deny" || mode === "prompt" ? mode : ("allow" as const),
|
|
218
|
+
clientBridge: session.getClientBridge?.(),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Enabled plan mode only. A missing or disabled state leaves the child writable. */
|
|
223
|
+
function inheritedPlanMode(session: ToolSession): { planModeState?: PlanModeState } {
|
|
224
|
+
const state = session.getPlanModeState?.();
|
|
225
|
+
if (!state?.enabled || !state.planFilePath) return {};
|
|
226
|
+
return {
|
|
227
|
+
planModeState: {
|
|
228
|
+
enabled: true,
|
|
229
|
+
planFilePath: state.planFilePath,
|
|
230
|
+
...(state.workflow ? { workflow: state.workflow } : {}),
|
|
231
|
+
...(state.reentry !== undefined ? { reentry: state.reentry } : {}),
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
139
236
|
function renderTaskAssignment(assignment: string, simpleMode: TaskSimpleMode): string {
|
|
140
237
|
return renderSubagentUserPrompt(assignment, simpleMode === "independent");
|
|
141
238
|
}
|
|
@@ -587,22 +684,43 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
587
684
|
return renderTaskDescription(this.session);
|
|
588
685
|
}
|
|
589
686
|
readonly #sessionRepositoryBinding: RepositoryBinding;
|
|
687
|
+
readonly #ownerSession: ToolSession;
|
|
688
|
+
readonly #parentModelProfileOwnershipMarker: unknown;
|
|
590
689
|
#testRunSubprocess: typeof runSubprocess | undefined;
|
|
591
690
|
|
|
592
691
|
private constructor(
|
|
593
692
|
private readonly session: ToolSession,
|
|
594
693
|
discoveredAgents: AgentDefinition[],
|
|
595
694
|
sessionRepositoryBinding: RepositoryBinding,
|
|
695
|
+
ownerSession?: ToolSession,
|
|
696
|
+
parentModelProfileOwnershipMarker?: unknown,
|
|
596
697
|
) {
|
|
597
698
|
this.#blockedAgent = $pickenv("GJC_BLOCKED_AGENT", "PI_BLOCKED_AGENT");
|
|
598
699
|
this.#discoveredAgents = discoveredAgents;
|
|
599
700
|
this.#sessionRepositoryBinding = sessionRepositoryBinding;
|
|
701
|
+
this.#ownerSession = ownerSession ?? session;
|
|
702
|
+
this.#parentModelProfileOwnershipMarker = parentModelProfileOwnershipMarker;
|
|
600
703
|
}
|
|
601
704
|
|
|
602
705
|
#runSubprocess(options: Parameters<typeof runSubprocess>[0]): Promise<SingleResult> {
|
|
603
706
|
return (this.#testRunSubprocess ?? runSubprocess)(options);
|
|
604
707
|
}
|
|
605
708
|
|
|
709
|
+
#createExecutionFacade(): TaskTool {
|
|
710
|
+
const parentModelProfileOwnershipMarker = (
|
|
711
|
+
this.#ownerSession as { sessionManager?: { getModelProfileOwnershipMarker?: () => unknown } }
|
|
712
|
+
).sessionManager?.getModelProfileOwnershipMarker?.();
|
|
713
|
+
const invocation = new TaskTool(
|
|
714
|
+
captureTaskExecutionScope(this.#ownerSession),
|
|
715
|
+
this.#discoveredAgents,
|
|
716
|
+
this.#sessionRepositoryBinding,
|
|
717
|
+
this.#ownerSession,
|
|
718
|
+
parentModelProfileOwnershipMarker,
|
|
719
|
+
);
|
|
720
|
+
invocation.#testRunSubprocess = this.#testRunSubprocess;
|
|
721
|
+
return invocation;
|
|
722
|
+
}
|
|
723
|
+
|
|
606
724
|
#getTaskSimpleMode(): TaskSimpleMode {
|
|
607
725
|
return this.session.settings.get("task.simple");
|
|
608
726
|
}
|
|
@@ -624,7 +742,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
624
742
|
* advertise agent:// URIs without a successful allocation.
|
|
625
743
|
*/
|
|
626
744
|
async #ensureSessionLifetimeArtifacts(): Promise<{ dir: string; manager: ArtifactManager } | null> {
|
|
627
|
-
const state = sessionLifetimeArtifactsState(this
|
|
745
|
+
const state = sessionLifetimeArtifactsState(this.#ownerSession);
|
|
628
746
|
if (state.authorized && state.dir && state.manager) return { dir: state.dir, manager: state.manager };
|
|
629
747
|
if (this.session.ensureArtifactManager) {
|
|
630
748
|
const manager = await this.session.ensureArtifactManager();
|
|
@@ -685,13 +803,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
685
803
|
adoptIntoSessionOwner: boolean,
|
|
686
804
|
): Promise<boolean> {
|
|
687
805
|
if (state.authorized) return true;
|
|
688
|
-
state.originalGetArtifactsDir = this.
|
|
689
|
-
state.originalGetAuthorizedArtifactsDirs = this.
|
|
690
|
-
state.originalGetArtifactManager = this.
|
|
691
|
-
state.originalIsArtifactManagerAuthorized = this.
|
|
692
|
-
state.originalAgentOutputManager = this.
|
|
806
|
+
state.originalGetArtifactsDir = this.#ownerSession.getArtifactsDir;
|
|
807
|
+
state.originalGetAuthorizedArtifactsDirs = this.#ownerSession.getAuthorizedArtifactsDirs;
|
|
808
|
+
state.originalGetArtifactManager = this.#ownerSession.getArtifactManager;
|
|
809
|
+
state.originalIsArtifactManagerAuthorized = this.#ownerSession.isArtifactManagerAuthorized;
|
|
810
|
+
state.originalAgentOutputManager = this.#ownerSession.agentOutputManager;
|
|
693
811
|
|
|
694
|
-
state.installedGetArtifactsDir = () => state.originalGetArtifactsDir?.() ?? dir;
|
|
812
|
+
state.installedGetArtifactsDir = () => state.originalGetArtifactsDir?.call(this.#ownerSession) ?? dir;
|
|
695
813
|
state.installedGetAuthorizedArtifactsDirs = () => {
|
|
696
814
|
const dirs: string[] = [];
|
|
697
815
|
const add = (candidate: string | null | undefined) => {
|
|
@@ -699,68 +817,73 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
699
817
|
const normalized = path.resolve(candidate);
|
|
700
818
|
if (!dirs.includes(normalized)) dirs.push(normalized);
|
|
701
819
|
};
|
|
702
|
-
for (const authorized of state.originalGetAuthorizedArtifactsDirs?.() ?? [])
|
|
820
|
+
for (const authorized of state.originalGetAuthorizedArtifactsDirs?.call(this.#ownerSession) ?? [])
|
|
821
|
+
add(authorized);
|
|
703
822
|
add(dir);
|
|
704
823
|
return dirs;
|
|
705
824
|
};
|
|
706
825
|
state.installedGetArtifactManager = () => manager;
|
|
707
826
|
state.installedIsArtifactManagerAuthorized = candidate =>
|
|
708
|
-
candidate === manager ||
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
827
|
+
candidate === manager ||
|
|
828
|
+
state.originalIsArtifactManagerAuthorized?.call(this.#ownerSession, candidate) === true;
|
|
829
|
+
if (owned || !this.#ownerSession.agentOutputManager) {
|
|
830
|
+
state.installedAgentOutputManager = new AgentOutputManager(
|
|
831
|
+
() => this.#ownerSession.getArtifactsDir?.() ?? null,
|
|
832
|
+
{
|
|
833
|
+
parentPrefix: owned ? state.outputPrefix : undefined,
|
|
834
|
+
getAuthorizedArtifactsDirs: () => this.#ownerSession.getAuthorizedArtifactsDirs?.() ?? [],
|
|
835
|
+
},
|
|
836
|
+
);
|
|
714
837
|
}
|
|
715
838
|
|
|
716
839
|
let cleanupRan = false;
|
|
717
840
|
const cleanup = async () => {
|
|
718
841
|
cleanupRan = true;
|
|
719
|
-
this.
|
|
720
|
-
if (this.
|
|
721
|
-
this.
|
|
722
|
-
if (this.
|
|
723
|
-
this.
|
|
724
|
-
if (this.
|
|
725
|
-
this.
|
|
726
|
-
if (this.
|
|
727
|
-
this.
|
|
728
|
-
if (this.
|
|
729
|
-
this.
|
|
730
|
-
sessionLifetimeArtifacts.delete(this
|
|
842
|
+
this.#ownerSession.releaseArtifactManager?.(manager);
|
|
843
|
+
if (this.#ownerSession.getArtifactsDir === state.installedGetArtifactsDir)
|
|
844
|
+
this.#ownerSession.getArtifactsDir = state.originalGetArtifactsDir;
|
|
845
|
+
if (this.#ownerSession.getAuthorizedArtifactsDirs === state.installedGetAuthorizedArtifactsDirs)
|
|
846
|
+
this.#ownerSession.getAuthorizedArtifactsDirs = state.originalGetAuthorizedArtifactsDirs;
|
|
847
|
+
if (this.#ownerSession.getArtifactManager === state.installedGetArtifactManager)
|
|
848
|
+
this.#ownerSession.getArtifactManager = state.originalGetArtifactManager;
|
|
849
|
+
if (this.#ownerSession.isArtifactManagerAuthorized === state.installedIsArtifactManagerAuthorized)
|
|
850
|
+
this.#ownerSession.isArtifactManagerAuthorized = state.originalIsArtifactManagerAuthorized;
|
|
851
|
+
if (this.#ownerSession.agentOutputManager === state.installedAgentOutputManager)
|
|
852
|
+
this.#ownerSession.agentOutputManager = state.originalAgentOutputManager;
|
|
853
|
+
sessionLifetimeArtifacts.delete(this.#ownerSession);
|
|
731
854
|
if (owned) await fs.rm(dir, { recursive: true, force: true });
|
|
732
855
|
};
|
|
733
|
-
const registerCleanup = this.
|
|
856
|
+
const registerCleanup = this.#ownerSession.registerSessionCleanup;
|
|
734
857
|
if (!registerCleanup) {
|
|
735
858
|
state.dir = undefined;
|
|
736
859
|
state.manager = undefined;
|
|
737
860
|
state.ensurePromise = undefined;
|
|
738
|
-
sessionLifetimeArtifacts.delete(this
|
|
861
|
+
sessionLifetimeArtifacts.delete(this.#ownerSession);
|
|
739
862
|
if (owned) await fs.rm(dir, { recursive: true, force: true }).catch(() => {});
|
|
740
863
|
return false;
|
|
741
864
|
}
|
|
742
865
|
try {
|
|
743
|
-
registerCleanup(cleanup);
|
|
866
|
+
registerCleanup.call(this.#ownerSession, cleanup);
|
|
744
867
|
} catch {
|
|
745
868
|
state.dir = undefined;
|
|
746
869
|
state.manager = undefined;
|
|
747
870
|
state.ensurePromise = undefined;
|
|
748
|
-
sessionLifetimeArtifacts.delete(this
|
|
871
|
+
sessionLifetimeArtifacts.delete(this.#ownerSession);
|
|
749
872
|
if (owned) await fs.rm(dir, { recursive: true, force: true }).catch(() => {});
|
|
750
873
|
return false;
|
|
751
874
|
}
|
|
752
875
|
if (cleanupRan) return false;
|
|
753
876
|
state.cleanupRegistered = true;
|
|
754
|
-
if (adoptIntoSessionOwner && this.
|
|
877
|
+
if (adoptIntoSessionOwner && this.#ownerSession.adoptArtifactManager) {
|
|
755
878
|
try {
|
|
756
|
-
this.
|
|
879
|
+
this.#ownerSession.adoptArtifactManager(manager);
|
|
757
880
|
} catch {
|
|
758
881
|
await cleanup();
|
|
759
882
|
return false;
|
|
760
883
|
}
|
|
761
884
|
if (
|
|
762
|
-
this.
|
|
763
|
-
this.
|
|
885
|
+
this.#ownerSession.getArtifactManager?.() !== manager ||
|
|
886
|
+
this.#ownerSession.isArtifactManagerAuthorized?.(manager) !== true
|
|
764
887
|
) {
|
|
765
888
|
await cleanup();
|
|
766
889
|
return false;
|
|
@@ -768,11 +891,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
768
891
|
}
|
|
769
892
|
|
|
770
893
|
state.authorized = true;
|
|
771
|
-
this.
|
|
772
|
-
this.
|
|
773
|
-
this.
|
|
774
|
-
this.
|
|
775
|
-
if (state.installedAgentOutputManager) this.
|
|
894
|
+
this.#ownerSession.getArtifactsDir = state.installedGetArtifactsDir;
|
|
895
|
+
this.#ownerSession.getAuthorizedArtifactsDirs = state.installedGetAuthorizedArtifactsDirs;
|
|
896
|
+
this.#ownerSession.getArtifactManager = state.installedGetArtifactManager;
|
|
897
|
+
this.#ownerSession.isArtifactManagerAuthorized = state.installedIsArtifactManagerAuthorized;
|
|
898
|
+
if (state.installedAgentOutputManager) this.#ownerSession.agentOutputManager = state.installedAgentOutputManager;
|
|
776
899
|
return true;
|
|
777
900
|
}
|
|
778
901
|
|
|
@@ -819,6 +942,26 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
819
942
|
};
|
|
820
943
|
}
|
|
821
944
|
|
|
945
|
+
#resolveAdmittedArtifactPersistence(admitted: TaskArtifactPersistence): TaskArtifactPersistence {
|
|
946
|
+
if (!admitted.parentArtifactManager?.getManagedStore()) return admitted;
|
|
947
|
+
const admittedOwnerId = this.session.getSessionId?.();
|
|
948
|
+
const currentOwnerId = this.#ownerSession.getSessionId?.();
|
|
949
|
+
const admittedFile = this.session.getSessionFile();
|
|
950
|
+
const currentFile = this.#ownerSession.getSessionFile();
|
|
951
|
+
if (
|
|
952
|
+
!admittedOwnerId ||
|
|
953
|
+
admittedOwnerId !== currentOwnerId ||
|
|
954
|
+
!admittedFile ||
|
|
955
|
+
!currentFile ||
|
|
956
|
+
path.basename(admittedFile) !== path.basename(currentFile)
|
|
957
|
+
)
|
|
958
|
+
return admitted;
|
|
959
|
+
const current = this.#sharedArtifactStore();
|
|
960
|
+
if (!current?.manager.getManagedStore()) return admitted;
|
|
961
|
+
current.manager.assertManagedBinding();
|
|
962
|
+
return { effectiveArtifactsDir: current.dir, parentArtifactManager: current.manager };
|
|
963
|
+
}
|
|
964
|
+
|
|
822
965
|
/**
|
|
823
966
|
* Create a TaskTool instance.
|
|
824
967
|
* Repository authority is captured from session cwd *before* agent discovery so
|
|
@@ -863,8 +1006,18 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
863
1006
|
signal?: AbortSignal,
|
|
864
1007
|
onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
|
|
865
1008
|
): Promise<AgentToolResult<TaskToolDetails>> {
|
|
1009
|
+
return this.#createExecutionFacade().#executeCaptured(_toolCallId, rawParams, signal, onUpdate);
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
async #executeCaptured(
|
|
1013
|
+
_toolCallId: string,
|
|
1014
|
+
rawParams: unknown,
|
|
1015
|
+
signal?: AbortSignal,
|
|
1016
|
+
onUpdate?: AgentToolUpdateCallback<TaskToolDetails>,
|
|
1017
|
+
): Promise<AgentToolResult<TaskToolDetails>> {
|
|
1018
|
+
const session = this.session;
|
|
866
1019
|
const params = normalizeTaskAdmissionParams(rawParams as TaskParams);
|
|
867
|
-
const simpleMode =
|
|
1020
|
+
const simpleMode = session.settings.get("task.simple");
|
|
868
1021
|
const validationError = validateTaskModeParams(simpleMode, params);
|
|
869
1022
|
if (validationError) {
|
|
870
1023
|
return createTaskModeError(validationError);
|
|
@@ -872,7 +1025,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
872
1025
|
|
|
873
1026
|
// Re-verify session authority before using any discovered agents or scheduling work.
|
|
874
1027
|
try {
|
|
875
|
-
await assertExecutionRootMatchesRepositoryBinding(
|
|
1028
|
+
await assertExecutionRootMatchesRepositoryBinding(session.cwd, this.#sessionRepositoryBinding);
|
|
876
1029
|
} catch (error) {
|
|
877
1030
|
const message =
|
|
878
1031
|
error instanceof RepositoryBindingError
|
|
@@ -888,7 +1041,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
888
1041
|
if (taskIdValidationError) {
|
|
889
1042
|
return createTaskModeError(taskIdValidationError);
|
|
890
1043
|
}
|
|
891
|
-
const bindingResolution = await resolveTaskItemsWithRepositoryBindings(
|
|
1044
|
+
const bindingResolution = await resolveTaskItemsWithRepositoryBindings(session.cwd, rawTaskItems);
|
|
892
1045
|
if (bindingResolution.error) {
|
|
893
1046
|
return createTaskModeError(bindingResolution.error);
|
|
894
1047
|
}
|
|
@@ -900,7 +1053,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
900
1053
|
const agent = getAgent(this.#discoveredAgents, params.agent);
|
|
901
1054
|
if (!agent) {
|
|
902
1055
|
const available =
|
|
903
|
-
callableAgents(this.#discoveredAgents,
|
|
1056
|
+
callableAgents(this.#discoveredAgents, session)
|
|
904
1057
|
.map(agent => agent.name)
|
|
905
1058
|
.join(", ") || "none";
|
|
906
1059
|
return {
|
|
@@ -909,7 +1062,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
909
1062
|
};
|
|
910
1063
|
}
|
|
911
1064
|
|
|
912
|
-
const disabledAgents =
|
|
1065
|
+
const disabledAgents = session.settings.get("task.disabledAgents") as string[];
|
|
913
1066
|
if (disabledAgents.length > 0 && disabledAgents.includes(params.agent)) {
|
|
914
1067
|
const enabled = filterVisibleAgents(this.#discoveredAgents)
|
|
915
1068
|
.filter(a => !disabledAgents.includes(a.name))
|
|
@@ -928,7 +1081,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
928
1081
|
const forkContextValidationError = validateForkContextRequests(
|
|
929
1082
|
taskItems,
|
|
930
1083
|
agent,
|
|
931
|
-
|
|
1084
|
+
session.settings.get("task.forkContext.enabled"),
|
|
932
1085
|
);
|
|
933
1086
|
if (forkContextValidationError) {
|
|
934
1087
|
return createTaskModeError(forkContextValidationError);
|
|
@@ -972,9 +1125,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
972
1125
|
// Durable allocation failed: keep child session jsonl under local:// only.
|
|
973
1126
|
// Do not advertise agent:// URIs without durable output backing.
|
|
974
1127
|
const asyncLocalOptions: LocalProtocolOptions = {
|
|
975
|
-
getArtifactsDir: this.session.getArtifactsDir
|
|
976
|
-
isManagedDestination:
|
|
977
|
-
getSessionId:
|
|
1128
|
+
getArtifactsDir: () => this.session.getArtifactsDir?.() ?? null,
|
|
1129
|
+
isManagedDestination: session.isManagedSessionDestination,
|
|
1130
|
+
getSessionId: session.getSessionId ?? (() => null),
|
|
978
1131
|
};
|
|
979
1132
|
await initializeLocalRoot(asyncLocalOptions);
|
|
980
1133
|
externalTaskSessionsDir = resolveLocalUrlToPath("local://subagents/sessions", asyncLocalOptions);
|
|
@@ -982,7 +1135,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
982
1135
|
}
|
|
983
1136
|
|
|
984
1137
|
const outputManager =
|
|
985
|
-
this.session.agentOutputManager ?? new AgentOutputManager(this.session.getArtifactsDir
|
|
1138
|
+
this.session.agentOutputManager ?? new AgentOutputManager(() => this.session.getArtifactsDir?.() ?? null);
|
|
986
1139
|
const uniqueIds = await outputManager.allocateBatch(taskItems.map(t => t.id));
|
|
987
1140
|
const fallbackAgentSource =
|
|
988
1141
|
this.#discoveredAgents.find(agent => agent.name === params.agent)?.source ?? "bundled";
|
|
@@ -1041,9 +1194,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1041
1194
|
});
|
|
1042
1195
|
};
|
|
1043
1196
|
|
|
1044
|
-
const maxConcurrency =
|
|
1045
|
-
const ownerId =
|
|
1046
|
-
const parentSession =
|
|
1197
|
+
const maxConcurrency = session.settings.get("task.maxConcurrency");
|
|
1198
|
+
const ownerId = session.getAgentId?.() ?? undefined;
|
|
1199
|
+
const parentSession = session.getSessionFile();
|
|
1047
1200
|
const admitDuplicateLaunch = (
|
|
1048
1201
|
subagentId: string,
|
|
1049
1202
|
task: TaskItem,
|
|
@@ -1083,7 +1236,14 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1083
1236
|
};
|
|
1084
1237
|
let resumeRunner: ResumeRunner | undefined;
|
|
1085
1238
|
if (typeof manager.setResumeRunner === "function") {
|
|
1086
|
-
resumeRunner = (
|
|
1239
|
+
resumeRunner = (
|
|
1240
|
+
_subagentId,
|
|
1241
|
+
message,
|
|
1242
|
+
resumeDescriptor,
|
|
1243
|
+
resumeToolCallId,
|
|
1244
|
+
admissionEndpointId,
|
|
1245
|
+
ownedRegistrationEndpointId,
|
|
1246
|
+
) => {
|
|
1087
1247
|
const descriptor = isTaskResumeDescriptor(resumeDescriptor?.data) ? resumeDescriptor.data : undefined;
|
|
1088
1248
|
if (!descriptor) return undefined;
|
|
1089
1249
|
const admission = (() => {
|
|
@@ -1148,10 +1308,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1148
1308
|
{
|
|
1149
1309
|
runMode: message ? "message" : "resume",
|
|
1150
1310
|
resumeMessage: message,
|
|
1311
|
+
asyncJobManager: manager,
|
|
1151
1312
|
sessionFiles: new Map([[descriptor.task.id, descriptor.sessionFile]]),
|
|
1152
1313
|
suppressRoiReconciliation: true,
|
|
1153
1314
|
...(descriptor.durableOutputAllowed === true
|
|
1154
|
-
? {}
|
|
1315
|
+
? { persistence: descriptor.artifactPersistence }
|
|
1155
1316
|
: {
|
|
1156
1317
|
persistence: {
|
|
1157
1318
|
effectiveArtifactsDir: undefined,
|
|
@@ -1181,7 +1342,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1181
1342
|
},
|
|
1182
1343
|
{
|
|
1183
1344
|
id: `${descriptor.task.id}-resume-${Snowflake.next()}`,
|
|
1184
|
-
ownerId:
|
|
1345
|
+
ownerId: session.getAgentId?.() ?? undefined,
|
|
1185
1346
|
metadata: {
|
|
1186
1347
|
subagent: {
|
|
1187
1348
|
id: descriptor.task.id,
|
|
@@ -1208,7 +1369,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1208
1369
|
manager,
|
|
1209
1370
|
resumeToolCallId ?? descriptor.toolCallId,
|
|
1210
1371
|
resumeJobId,
|
|
1211
|
-
|
|
1372
|
+
admissionEndpointId ?? session.getAsyncEndpointId?.() ?? session.getSessionId?.() ?? undefined,
|
|
1373
|
+
ownedRegistrationEndpointId ?? AsyncJobManager.endpointIdOf(manager),
|
|
1212
1374
|
);
|
|
1213
1375
|
return resumeJobId;
|
|
1214
1376
|
};
|
|
@@ -1217,21 +1379,21 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1217
1379
|
const semaphore = new Semaphore(maxConcurrency);
|
|
1218
1380
|
const buildForkContextSeedForTask = async (task: TaskItem): Promise<ForkContextSeed | undefined> => {
|
|
1219
1381
|
if (!requestsForkContext(task)) return undefined;
|
|
1220
|
-
if (!
|
|
1382
|
+
if (!session.buildForkContextSeed) {
|
|
1221
1383
|
throw new Error("Current session cannot build fork-context seeds.");
|
|
1222
1384
|
}
|
|
1223
|
-
const configuredMaxMessages =
|
|
1224
|
-
?
|
|
1385
|
+
const configuredMaxMessages = session.settings.has("task.forkContext.maxMessages")
|
|
1386
|
+
? session.settings.get("task.forkContext.maxMessages")
|
|
1225
1387
|
: undefined;
|
|
1226
|
-
const configuredMaxTokens =
|
|
1388
|
+
const configuredMaxTokens = session.settings.get("task.forkContext.maxTokens");
|
|
1227
1389
|
const params = resolveForkSeedParamsForMode(
|
|
1228
1390
|
task.inheritContext,
|
|
1229
1391
|
configuredMaxMessages,
|
|
1230
1392
|
configuredMaxTokens,
|
|
1231
|
-
|
|
1393
|
+
session.model,
|
|
1232
1394
|
);
|
|
1233
1395
|
if (!params) return undefined;
|
|
1234
|
-
return await
|
|
1396
|
+
return await session.buildForkContextSeed({
|
|
1235
1397
|
...params,
|
|
1236
1398
|
signal,
|
|
1237
1399
|
});
|
|
@@ -1328,6 +1490,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1328
1490
|
[uniqueId],
|
|
1329
1491
|
frozenForkSeeds,
|
|
1330
1492
|
{
|
|
1493
|
+
asyncJobManager: manager,
|
|
1331
1494
|
sessionFiles: new Map([[uniqueId, subtaskSessionFile]]),
|
|
1332
1495
|
suppressRoiReconciliation: true,
|
|
1333
1496
|
persistence: {
|
|
@@ -1420,7 +1583,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1420
1583
|
},
|
|
1421
1584
|
{
|
|
1422
1585
|
id: label,
|
|
1423
|
-
ownerId:
|
|
1586
|
+
ownerId: session.getAgentId?.() ?? undefined,
|
|
1424
1587
|
metadata: {
|
|
1425
1588
|
subagent: {
|
|
1426
1589
|
id: uniqueId,
|
|
@@ -1444,19 +1607,23 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1444
1607
|
manager,
|
|
1445
1608
|
_toolCallId,
|
|
1446
1609
|
jobId,
|
|
1447
|
-
|
|
1610
|
+
session.getAsyncEndpointId?.() ?? session.getSessionId?.() ?? undefined,
|
|
1448
1611
|
);
|
|
1449
1612
|
startedJobs.push({ jobId, taskId: taskItem.id });
|
|
1450
1613
|
if (typeof manager.registerResumeDescriptor === "function") {
|
|
1451
1614
|
manager.registerResumeDescriptor(
|
|
1452
1615
|
{
|
|
1453
1616
|
subagentId: uniqueId,
|
|
1454
|
-
ownerId:
|
|
1617
|
+
ownerId: session.getAgentId?.() ?? undefined,
|
|
1455
1618
|
data: {
|
|
1456
1619
|
toolCallId: _toolCallId,
|
|
1457
1620
|
params,
|
|
1458
1621
|
task: { ...taskItem, id: uniqueId },
|
|
1459
1622
|
sessionFile: subtaskSessionFile,
|
|
1623
|
+
artifactPersistence: {
|
|
1624
|
+
effectiveArtifactsDir: batchArtifactsDir,
|
|
1625
|
+
parentArtifactManager: asyncParentArtifactManager,
|
|
1626
|
+
},
|
|
1460
1627
|
durableOutputAllowed: Boolean(batchArtifactsDir),
|
|
1461
1628
|
forkContextSeed: frozenForkSeed,
|
|
1462
1629
|
agentSource: fallbackAgentSource,
|
|
@@ -1472,7 +1639,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1472
1639
|
if (typeof manager.registerSubagentRecord === "function") {
|
|
1473
1640
|
manager.registerSubagentRecord({
|
|
1474
1641
|
subagentId: uniqueId,
|
|
1475
|
-
ownerId:
|
|
1642
|
+
ownerId: session.getAgentId?.() ?? undefined,
|
|
1476
1643
|
currentJobId: jobId,
|
|
1477
1644
|
currentJobGeneration: manager.getJob(jobId)?.generation,
|
|
1478
1645
|
historicalJobIds: [],
|
|
@@ -1556,7 +1723,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1556
1723
|
? ` Failed to schedule ${failedSchedules.length} task${failedSchedules.length === 1 ? "" : "s"}.`
|
|
1557
1724
|
: "";
|
|
1558
1725
|
|
|
1559
|
-
const ircEnabled = hasAvailableIrcTool(
|
|
1726
|
+
const ircEnabled = hasAvailableIrcTool(session);
|
|
1560
1727
|
const taskIdByItemId = new Map<string, string>();
|
|
1561
1728
|
for (let i = 0; i < taskItems.length; i++) {
|
|
1562
1729
|
taskIdByItemId.set(taskItems[i].id, uniqueIds[i]);
|
|
@@ -1603,11 +1770,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1603
1770
|
executionOverrides?: {
|
|
1604
1771
|
runMode?: "initial" | "resume" | "message";
|
|
1605
1772
|
resumeMessage?: string;
|
|
1773
|
+
asyncJobManager?: AsyncJobManager;
|
|
1606
1774
|
sessionFiles?: ReadonlyMap<string, string | null>;
|
|
1607
|
-
persistence?:
|
|
1608
|
-
effectiveArtifactsDir: string | undefined;
|
|
1609
|
-
parentArtifactManager: ArtifactManager | undefined;
|
|
1610
|
-
};
|
|
1775
|
+
persistence?: TaskArtifactPersistence;
|
|
1611
1776
|
/**
|
|
1612
1777
|
* Set for per-child async runs: the spawnPlan is carried for gate
|
|
1613
1778
|
* consistency, but batch-level ROI reconciliation must not be computed
|
|
@@ -1616,10 +1781,12 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1616
1781
|
suppressRoiReconciliation?: boolean;
|
|
1617
1782
|
},
|
|
1618
1783
|
): Promise<AgentToolResult<TaskToolDetails>> {
|
|
1784
|
+
const session = this.session;
|
|
1785
|
+
const ownedJobManager = executionOverrides?.asyncJobManager ?? this.#resolveOwnedJobManager();
|
|
1619
1786
|
const startTime = Date.now();
|
|
1620
1787
|
// Pre-discovery authority: session cwd must still match the capture from create().
|
|
1621
1788
|
try {
|
|
1622
|
-
await assertExecutionRootMatchesRepositoryBinding(
|
|
1789
|
+
await assertExecutionRootMatchesRepositoryBinding(session.cwd, this.#sessionRepositoryBinding);
|
|
1623
1790
|
} catch (error) {
|
|
1624
1791
|
const message =
|
|
1625
1792
|
error instanceof RepositoryBindingError
|
|
@@ -1629,25 +1796,25 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1629
1796
|
: String(error);
|
|
1630
1797
|
return createTaskModeError(`Session repository binding rejected before task discovery: ${message}`);
|
|
1631
1798
|
}
|
|
1632
|
-
const bindingResolution = await resolveTaskItemsWithRepositoryBindings(
|
|
1799
|
+
const bindingResolution = await resolveTaskItemsWithRepositoryBindings(session.cwd, params.tasks ?? []);
|
|
1633
1800
|
if (bindingResolution.error) {
|
|
1634
1801
|
return createTaskModeError(bindingResolution.error);
|
|
1635
1802
|
}
|
|
1636
1803
|
const boundParams: TaskParams = { ...params, tasks: bindingResolution.tasks };
|
|
1637
1804
|
|
|
1638
|
-
const { agents, projectAgentsDir } = await discoverAgents(
|
|
1805
|
+
const { agents, projectAgentsDir } = await discoverAgents(session.cwd);
|
|
1639
1806
|
const { agent: agentName, context, schema: outputSchema } = boundParams;
|
|
1640
|
-
const simpleMode =
|
|
1807
|
+
const simpleMode = session.settings.get("task.simple");
|
|
1641
1808
|
const { contextEnabled, customSchemaEnabled } = getTaskSimpleModeCapabilities(simpleMode);
|
|
1642
1809
|
const sharedContext = contextEnabled ? context?.trim() : undefined;
|
|
1643
|
-
const isolationMode =
|
|
1810
|
+
const isolationMode = session.settings.get("task.isolation.mode");
|
|
1644
1811
|
const isolationRequested = "isolated" in boundParams ? boundParams.isolated === true : false;
|
|
1645
1812
|
const isIsolated = isolationMode !== "none" && isolationRequested;
|
|
1646
|
-
const mergeMode =
|
|
1647
|
-
const commitStyle =
|
|
1648
|
-
const maxConcurrency =
|
|
1649
|
-
const taskDepth =
|
|
1650
|
-
const subagentLspEnabled = (
|
|
1813
|
+
const mergeMode = session.settings.get("task.isolation.merge");
|
|
1814
|
+
const commitStyle = session.settings.get("task.isolation.commits");
|
|
1815
|
+
const maxConcurrency = session.settings.get("task.maxConcurrency");
|
|
1816
|
+
const taskDepth = session.taskDepth ?? 0;
|
|
1817
|
+
const subagentLspEnabled = (session.enableLsp ?? true) && session.settings.get("task.enableLsp");
|
|
1651
1818
|
|
|
1652
1819
|
if (isolationMode === "none" && "isolated" in boundParams) {
|
|
1653
1820
|
return {
|
|
@@ -1669,7 +1836,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1669
1836
|
const agent = getAgent(agents, agentName);
|
|
1670
1837
|
if (!agent) {
|
|
1671
1838
|
const available =
|
|
1672
|
-
callableAgents(agents,
|
|
1839
|
+
callableAgents(agents, session)
|
|
1673
1840
|
.map(agent => agent.name)
|
|
1674
1841
|
.join(", ") || "none";
|
|
1675
1842
|
return {
|
|
@@ -1688,7 +1855,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1688
1855
|
}
|
|
1689
1856
|
|
|
1690
1857
|
// Check if agent is disabled in settings
|
|
1691
|
-
const disabledAgents =
|
|
1858
|
+
const disabledAgents = session.settings.get("task.disabledAgents") as string[];
|
|
1692
1859
|
if (disabledAgents.length > 0 && disabledAgents.includes(agentName)) {
|
|
1693
1860
|
const enabled = filterVisibleAgents(agents)
|
|
1694
1861
|
.filter(a => !disabledAgents.includes(a.name))
|
|
@@ -1711,13 +1878,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1711
1878
|
const forkContextValidationError = validateForkContextRequests(
|
|
1712
1879
|
boundParams.tasks ?? [],
|
|
1713
1880
|
agent,
|
|
1714
|
-
|
|
1881
|
+
session.settings.get("task.forkContext.enabled"),
|
|
1715
1882
|
);
|
|
1716
1883
|
if (forkContextValidationError) {
|
|
1717
1884
|
return createTaskModeError(forkContextValidationError);
|
|
1718
1885
|
}
|
|
1719
1886
|
|
|
1720
|
-
const planModeState =
|
|
1887
|
+
const planModeState = session.getPlanModeState?.();
|
|
1721
1888
|
const planModeTools = ["read", "search", "find", "lsp", "web_search"];
|
|
1722
1889
|
const effectiveAgent: typeof agent = planModeState?.enabled
|
|
1723
1890
|
? {
|
|
@@ -1729,21 +1896,19 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1729
1896
|
: agent;
|
|
1730
1897
|
|
|
1731
1898
|
// Apply per-agent model override from settings (highest priority)
|
|
1732
|
-
const agentModelOverrides =
|
|
1899
|
+
const agentModelOverrides = session.settings.get("task.agentModelOverrides");
|
|
1733
1900
|
const settingsModelOverride = agentModelOverrides[agentName];
|
|
1734
|
-
const parentActiveModelPattern =
|
|
1901
|
+
const parentActiveModelPattern = session.getActiveModelString?.();
|
|
1735
1902
|
// A live active model profile claims persisted agent overrides: bare
|
|
1736
1903
|
// profile aliases may re-resolve to an equivalent provider variant at
|
|
1737
1904
|
// dispatch. Manual/direct sessions (no active profile) stay exact.
|
|
1738
1905
|
const parentActiveModelProfile = (
|
|
1739
|
-
|
|
1906
|
+
session as { getActiveModelProfile?: () => string | undefined }
|
|
1740
1907
|
).getActiveModelProfile?.();
|
|
1741
1908
|
// Propagate the parent session's ownership marker when a session-local profile is active.
|
|
1742
|
-
const parentModelProfileOwnershipMarker =
|
|
1743
|
-
this.session as { sessionManager?: { getModelProfileOwnershipMarker?: () => unknown } }
|
|
1744
|
-
).sessionManager?.getModelProfileOwnershipMarker?.();
|
|
1909
|
+
const parentModelProfileOwnershipMarker = this.#parentModelProfileOwnershipMarker;
|
|
1745
1910
|
const parentProfileDefinition = parentActiveModelProfile
|
|
1746
|
-
?
|
|
1911
|
+
? session.modelRegistry?.getModelProfile?.(parentActiveModelProfile)
|
|
1747
1912
|
: undefined;
|
|
1748
1913
|
const parentProfileBindings = parentProfileDefinition
|
|
1749
1914
|
? resolveProfileBindings(parentProfileDefinition)
|
|
@@ -1765,17 +1930,17 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1765
1930
|
// profile's role binding before falling back to the parent model.
|
|
1766
1931
|
settingsOverride: settingsModelOverride ?? parentProfileBinding,
|
|
1767
1932
|
agentModel: effectiveAgent.model,
|
|
1768
|
-
settings:
|
|
1933
|
+
settings: session.settings,
|
|
1769
1934
|
activeModelPattern: parentActiveModelPattern,
|
|
1770
|
-
fallbackModelPattern:
|
|
1935
|
+
fallbackModelPattern: session.getModelString?.(),
|
|
1771
1936
|
});
|
|
1772
1937
|
const thinkingLevelOverride = effectiveAgent.thinkingLevel;
|
|
1773
1938
|
|
|
1774
1939
|
// Output schema priority: task call > agent frontmatter > inherited parent session.
|
|
1775
1940
|
// task.simple can disable the task-call override while leaving agent/session schemas intact.
|
|
1776
1941
|
const effectiveOutputSchema = customSchemaEnabled
|
|
1777
|
-
? (outputSchema ?? effectiveAgent.output ??
|
|
1778
|
-
: (effectiveAgent.output ??
|
|
1942
|
+
? (outputSchema ?? effectiveAgent.output ?? session.outputSchema)
|
|
1943
|
+
: (effectiveAgent.output ?? session.outputSchema);
|
|
1779
1944
|
|
|
1780
1945
|
// Handle empty or missing tasks
|
|
1781
1946
|
if (!boundParams.tasks || boundParams.tasks.length === 0) {
|
|
@@ -1865,7 +2030,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1865
2030
|
let baseline: WorktreeBaseline | null = null;
|
|
1866
2031
|
if (isIsolated) {
|
|
1867
2032
|
try {
|
|
1868
|
-
repoRoot = await getRepoRoot(
|
|
2033
|
+
repoRoot = await getRepoRoot(session.cwd);
|
|
1869
2034
|
baseline = await captureBaseline(repoRoot);
|
|
1870
2035
|
} catch (err) {
|
|
1871
2036
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -1890,15 +2055,16 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1890
2055
|
// File-backed session artifacts, or a session-lifetime durable temp root for
|
|
1891
2056
|
// in-memory parents. Never use a per-task temp dir that is deleted on return —
|
|
1892
2057
|
// advertised agent:// URIs must remain readable for the parent session lifetime.
|
|
1893
|
-
const { effectiveArtifactsDir, parentArtifactManager } =
|
|
1894
|
-
|
|
2058
|
+
const { effectiveArtifactsDir, parentArtifactManager } = executionOverrides?.persistence
|
|
2059
|
+
? this.#resolveAdmittedArtifactPersistence(executionOverrides.persistence)
|
|
2060
|
+
: await this.#resolveEffectiveArtifactsDir();
|
|
1895
2061
|
const hasDurableOutputBacking = Boolean(effectiveArtifactsDir);
|
|
1896
2062
|
|
|
1897
2063
|
// Share the parent session's local:// root with subagents so they read/write the same scratch space
|
|
1898
2064
|
const localProtocolOptions: LocalProtocolOptions = {
|
|
1899
|
-
getArtifactsDir: this.session.getArtifactsDir
|
|
1900
|
-
isManagedDestination:
|
|
1901
|
-
getSessionId:
|
|
2065
|
+
getArtifactsDir: () => this.session.getArtifactsDir?.() ?? null,
|
|
2066
|
+
isManagedDestination: session.isManagedSessionDestination,
|
|
2067
|
+
getSessionId: session.getSessionId ?? (() => null),
|
|
1902
2068
|
};
|
|
1903
2069
|
|
|
1904
2070
|
// Subagents adopt the parent's ArtifactManager (including session-lifetime
|
|
@@ -1942,7 +2108,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1942
2108
|
}
|
|
1943
2109
|
|
|
1944
2110
|
// Check spawn restrictions from parent
|
|
1945
|
-
const parentSpawns =
|
|
2111
|
+
const parentSpawns = session.getSessionSpawns() ?? "*";
|
|
1946
2112
|
const allowedSpawns = parentSpawns.split(",").map(s => s.trim());
|
|
1947
2113
|
const isSpawnAllowed = (): boolean => {
|
|
1948
2114
|
if (parentSpawns === "") return false; // Empty = deny all
|
|
@@ -1971,8 +2137,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1971
2137
|
// Place fork-context handoff material in the session-scoped external local
|
|
1972
2138
|
// root. Subagent prompts may expose this path to subprocesses, so it must
|
|
1973
2139
|
// never carry managed transcript/artifact authority.
|
|
1974
|
-
const shouldWriteConversationContext = !hasAvailableIrcTool(
|
|
1975
|
-
const compactContext = shouldWriteConversationContext ?
|
|
2140
|
+
const shouldWriteConversationContext = !hasAvailableIrcTool(session);
|
|
2141
|
+
const compactContext = shouldWriteConversationContext ? session.getCompactContext?.() : undefined;
|
|
1976
2142
|
let contextFilePath: string | undefined;
|
|
1977
2143
|
if (compactContext) {
|
|
1978
2144
|
await initializeLocalRoot(localProtocolOptions);
|
|
@@ -1988,13 +2154,19 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1988
2154
|
uniqueIds = preAllocatedIds;
|
|
1989
2155
|
} else {
|
|
1990
2156
|
const outputManager =
|
|
1991
|
-
this.session.agentOutputManager ??
|
|
2157
|
+
this.session.agentOutputManager ??
|
|
2158
|
+
new AgentOutputManager(() => this.session.getArtifactsDir?.() ?? null);
|
|
1992
2159
|
uniqueIds = await outputManager.allocateBatch(tasks.map(t => t.id));
|
|
1993
2160
|
}
|
|
1994
2161
|
const tasksWithUniqueIds = tasks.map((t, i) => ({ ...t, id: validateAllocatedTaskId(uniqueIds[i] ?? "") }));
|
|
1995
2162
|
|
|
1996
|
-
const
|
|
1997
|
-
const
|
|
2163
|
+
const isResumedRun = executionOverrides?.runMode === "resume" || executionOverrides?.runMode === "message";
|
|
2164
|
+
const routingSettings = isResumedRun ? this.#ownerSession.settings : session.settings;
|
|
2165
|
+
const effectiveAutorouting = routingSettings.getEffectiveAutorouting();
|
|
2166
|
+
const disabledProviders = new Set(
|
|
2167
|
+
routingSettings.get("disabledProviders").map(provider => provider.toLowerCase()),
|
|
2168
|
+
);
|
|
2169
|
+
const registry = session.modelRegistry as
|
|
1998
2170
|
| {
|
|
1999
2171
|
getAvailable?: () => Model[];
|
|
2000
2172
|
getAll?: () => Model[];
|
|
@@ -2002,16 +2174,20 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2002
2174
|
}
|
|
2003
2175
|
| undefined;
|
|
2004
2176
|
const routingSnapshot = registry?.getAll?.() ?? registry?.getAvailable?.();
|
|
2177
|
+
const availableRoutingSnapshot = routingSnapshot?.filter(
|
|
2178
|
+
model => !disabledProviders.has(model.provider.toLowerCase()),
|
|
2179
|
+
);
|
|
2005
2180
|
const routingByIndex = new Map<number, RoutingOutcome>();
|
|
2006
2181
|
const routingCandidatesByIndex = new Map<number, string[]>();
|
|
2007
2182
|
const routingSkipsByIndex = new Map<number, Array<{ selector: string; code: AutoroutingReasonCode }>>();
|
|
2183
|
+
const routingPreflightErrorsByIndex = new Map<number, Map<string, unknown>>();
|
|
2008
2184
|
for (let i = 0; i < tasksWithUniqueIds.length; i++) {
|
|
2009
2185
|
const task = tasksWithUniqueIds[i];
|
|
2010
2186
|
const outcome = routingSnapshot
|
|
2011
2187
|
? resolveTaskRouting({
|
|
2012
2188
|
effectiveAutorouting,
|
|
2013
2189
|
requestedTier: task.tier,
|
|
2014
|
-
availableModels:
|
|
2190
|
+
availableModels: availableRoutingSnapshot,
|
|
2015
2191
|
})
|
|
2016
2192
|
: effectiveAutorouting.active
|
|
2017
2193
|
? {
|
|
@@ -2033,9 +2209,6 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2033
2209
|
const configured = effectiveAutorouting.map[outcome.tier] ?? [];
|
|
2034
2210
|
const candidates: string[] = [];
|
|
2035
2211
|
const skips: Array<{ selector: string; code: AutoroutingReasonCode }> = [];
|
|
2036
|
-
const disabledProviders = new Set(
|
|
2037
|
-
this.session.settings.get("disabledProviders").map(provider => provider.toLowerCase()),
|
|
2038
|
-
);
|
|
2039
2212
|
for (const selector of configured) {
|
|
2040
2213
|
const slash = selector.indexOf("/");
|
|
2041
2214
|
const provider = slash > 0 ? selector.slice(0, slash).toLowerCase() : "";
|
|
@@ -2060,6 +2233,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2060
2233
|
}
|
|
2061
2234
|
const resolveAutoroutingCandidates = async (
|
|
2062
2235
|
index: number,
|
|
2236
|
+
stopAfterFirstAuthenticatedCandidate = false,
|
|
2063
2237
|
): Promise<{
|
|
2064
2238
|
candidates: string[];
|
|
2065
2239
|
skips: Array<{ selector: string; code: AutoroutingReasonCode }>;
|
|
@@ -2079,19 +2253,38 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2079
2253
|
try {
|
|
2080
2254
|
const key = await registry.getApiKey(
|
|
2081
2255
|
model,
|
|
2082
|
-
|
|
2256
|
+
session.getCredentialSessionId?.() ?? session.getSessionId?.() ?? undefined,
|
|
2083
2257
|
);
|
|
2084
|
-
if (key)
|
|
2085
|
-
|
|
2258
|
+
if (key) {
|
|
2259
|
+
authenticated.push(selector);
|
|
2260
|
+
if (stopAfterFirstAuthenticatedCandidate) break;
|
|
2261
|
+
} else skips.push({ selector, code: "credential_unavailable" });
|
|
2086
2262
|
} catch (error) {
|
|
2087
|
-
// Preserve
|
|
2088
|
-
//
|
|
2263
|
+
// Preserve lookup errors for executor terminalization; only a returned
|
|
2264
|
+
// undefined value means this candidate may be skipped.
|
|
2089
2265
|
preflightErrors.set(selector, error);
|
|
2090
2266
|
authenticated.push(selector);
|
|
2267
|
+
if (stopAfterFirstAuthenticatedCandidate) break;
|
|
2091
2268
|
}
|
|
2092
2269
|
}
|
|
2093
2270
|
return { candidates: authenticated, skips, preflightErrors };
|
|
2094
2271
|
};
|
|
2272
|
+
if (isResumedRun) {
|
|
2273
|
+
for (const [index, outcome] of routingByIndex) {
|
|
2274
|
+
if (outcome.kind !== "routed") continue;
|
|
2275
|
+
const { candidates, skips, preflightErrors } = await resolveAutoroutingCandidates(index, true);
|
|
2276
|
+
routingSkipsByIndex.set(index, skips);
|
|
2277
|
+
const pinnedSelector = candidates[0];
|
|
2278
|
+
if (pinnedSelector) {
|
|
2279
|
+
routingCandidatesByIndex.set(index, [pinnedSelector]);
|
|
2280
|
+
if (preflightErrors.size > 0) routingPreflightErrorsByIndex.set(index, preflightErrors);
|
|
2281
|
+
routingByIndex.set(index, { ...outcome, pinnedSelector });
|
|
2282
|
+
continue;
|
|
2283
|
+
}
|
|
2284
|
+
routingPreflightErrorsByIndex.delete(index);
|
|
2285
|
+
routingCandidatesByIndex.set(index, []);
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2095
2288
|
const effectivePatterns = (index: number): string | string[] => {
|
|
2096
2289
|
const outcome = routingByIndex.get(index);
|
|
2097
2290
|
return outcome?.kind === "routed" ? [outcome.pinnedSelector] : modelOverride;
|
|
@@ -2110,7 +2303,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2110
2303
|
};
|
|
2111
2304
|
};
|
|
2112
2305
|
|
|
2113
|
-
const availableSkills = [...(
|
|
2306
|
+
const availableSkills = [...(session.skills ?? [])];
|
|
2114
2307
|
// Resolve autoload skills from agent definition against available skills
|
|
2115
2308
|
const resolvedAutoloadSkills =
|
|
2116
2309
|
agent.autoloadSkills?.length && availableSkills.length > 0
|
|
@@ -2118,11 +2311,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2118
2311
|
.map(name => availableSkills.find(s => s.name === name))
|
|
2119
2312
|
.filter((s): s is NonNullable<typeof s> => s !== undefined)
|
|
2120
2313
|
: [];
|
|
2121
|
-
const contextFiles =
|
|
2314
|
+
const contextFiles = session.contextFiles?.filter(
|
|
2122
2315
|
file => path.basename(file.path).toLowerCase() !== "agents.md",
|
|
2123
2316
|
);
|
|
2124
|
-
const promptTemplates =
|
|
2125
|
-
const parentMcpManager =
|
|
2317
|
+
const promptTemplates = session.promptTemplates;
|
|
2318
|
+
const parentMcpManager = session.getMcpManager?.();
|
|
2126
2319
|
// Exact-config tools-only managers belong to the top-level ACP session and cannot be reused by sub-sessions.
|
|
2127
2320
|
const reusableParentMcpManager = parentMcpManager?.isToolsOnly() ? undefined : parentMcpManager;
|
|
2128
2321
|
|
|
@@ -2152,21 +2345,21 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2152
2345
|
|
|
2153
2346
|
const buildForkContextSeed = async (task: (typeof tasksWithUniqueIds)[number]) => {
|
|
2154
2347
|
if (!requestsForkContext(task)) return undefined;
|
|
2155
|
-
if (!
|
|
2348
|
+
if (!session.buildForkContextSeed) {
|
|
2156
2349
|
throw new Error("Current session cannot build fork-context seeds.");
|
|
2157
2350
|
}
|
|
2158
|
-
const configuredMaxMessages =
|
|
2159
|
-
?
|
|
2351
|
+
const configuredMaxMessages = session.settings.has("task.forkContext.maxMessages")
|
|
2352
|
+
? session.settings.get("task.forkContext.maxMessages")
|
|
2160
2353
|
: undefined;
|
|
2161
|
-
const configuredMaxTokens =
|
|
2354
|
+
const configuredMaxTokens = session.settings.get("task.forkContext.maxTokens");
|
|
2162
2355
|
const params = resolveForkSeedParamsForMode(
|
|
2163
2356
|
task.inheritContext,
|
|
2164
2357
|
configuredMaxMessages,
|
|
2165
2358
|
configuredMaxTokens,
|
|
2166
|
-
|
|
2359
|
+
session.model,
|
|
2167
2360
|
);
|
|
2168
2361
|
if (!params) return undefined;
|
|
2169
|
-
return await
|
|
2362
|
+
return await session.buildForkContextSeed({
|
|
2170
2363
|
...params,
|
|
2171
2364
|
signal,
|
|
2172
2365
|
});
|
|
@@ -2185,7 +2378,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2185
2378
|
// The session's ENDPOINT-owned manager (resolved once per task so
|
|
2186
2379
|
// model metadata and live handles land in the SAME manager the
|
|
2187
2380
|
// job runs in — review thread P1).
|
|
2188
|
-
const manager =
|
|
2381
|
+
const manager = ownedJobManager;
|
|
2189
2382
|
const forkContext = requestsForkContext(task)
|
|
2190
2383
|
? { mode: task.inheritContext, clonedTokens: forkContextSeed?.metadata.approximateTokens ?? 0 }
|
|
2191
2384
|
: undefined;
|
|
@@ -2200,8 +2393,14 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2200
2393
|
recommendedMode: advisory.recommendedMode,
|
|
2201
2394
|
reasons: advisory.reasons,
|
|
2202
2395
|
};
|
|
2396
|
+
let retainedPersistence: TaskArtifactPersistence = { effectiveArtifactsDir, parentArtifactManager };
|
|
2203
2397
|
const managedPersistence = parentArtifactManager?.getManagedStore()
|
|
2204
|
-
? createManagedTaskPersistence(parentArtifactManager, task.id)
|
|
2398
|
+
? createManagedTaskPersistence(parentArtifactManager, task.id, () => {
|
|
2399
|
+
retainedPersistence = this.#resolveAdmittedArtifactPersistence(retainedPersistence);
|
|
2400
|
+
if (!retainedPersistence.parentArtifactManager)
|
|
2401
|
+
throw new Error("Managed Task storage authority is unavailable");
|
|
2402
|
+
return retainedPersistence.parentArtifactManager;
|
|
2403
|
+
})
|
|
2205
2404
|
: undefined;
|
|
2206
2405
|
|
|
2207
2406
|
const routingOutcome = routingByIndex.get(index);
|
|
@@ -2232,6 +2431,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2232
2431
|
const effectiveRunMode = overrides?.runMode ?? executionOverrides?.runMode;
|
|
2233
2432
|
const autoroutingInitial =
|
|
2234
2433
|
routingOutcome?.kind === "routed" && (effectiveRunMode ?? "initial") === "initial";
|
|
2434
|
+
const includeAutoroutingResolution =
|
|
2435
|
+
autoroutingInitial || effectiveRunMode === "resume" || effectiveRunMode === "message";
|
|
2235
2436
|
const autoroutingData =
|
|
2236
2437
|
(effectiveRunMode ?? "initial") === "initial" && routingOutcome && routingOutcome.kind !== "disabled"
|
|
2237
2438
|
? routingOutcome.kind === "routed"
|
|
@@ -2241,7 +2442,14 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2241
2442
|
skips: [...(routingSkipsByIndex.get(index) ?? [])],
|
|
2242
2443
|
preflightErrors: new Map(),
|
|
2243
2444
|
}
|
|
2244
|
-
: {
|
|
2445
|
+
: {
|
|
2446
|
+
candidates:
|
|
2447
|
+
includeAutoroutingResolution && routingOutcome?.kind === "routed"
|
|
2448
|
+
? [...(routingCandidatesByIndex.get(index) ?? [])]
|
|
2449
|
+
: undefined,
|
|
2450
|
+
skips: [...(routingSkipsByIndex.get(index) ?? [])],
|
|
2451
|
+
preflightErrors: routingPreflightErrorsByIndex.get(index) ?? new Map(),
|
|
2452
|
+
};
|
|
2245
2453
|
const routingForRun = routeEvidence(
|
|
2246
2454
|
routingOutcome,
|
|
2247
2455
|
effectiveRunMode === "resume" || effectiveRunMode === "message",
|
|
@@ -2257,9 +2465,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2257
2465
|
assertPathUnderRepositoryBinding(taskRepositoryBinding, ".");
|
|
2258
2466
|
}
|
|
2259
2467
|
if (!isIsolated) {
|
|
2260
|
-
await assertExecutionRootMatchesRepositoryBinding(
|
|
2468
|
+
await assertExecutionRootMatchesRepositoryBinding(session.cwd, taskRepositoryBinding);
|
|
2261
2469
|
const result = await this.#runSubprocess({
|
|
2262
|
-
cwd:
|
|
2470
|
+
cwd: session.cwd,
|
|
2263
2471
|
agent: effectiveAgent,
|
|
2264
2472
|
task: renderTaskAssignment(task.assignment, simpleMode),
|
|
2265
2473
|
assignment: task.assignment.trim(),
|
|
@@ -2278,9 +2486,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2278
2486
|
parentActiveModelPattern,
|
|
2279
2487
|
parentActiveModelProfile: parentOwnedModelProfile,
|
|
2280
2488
|
parentModelProfileOwnershipMarker: parentModelProfileOwnershipMarker as any,
|
|
2281
|
-
parentSessionId:
|
|
2489
|
+
parentSessionId: session.getSessionId?.() ?? undefined,
|
|
2282
2490
|
parentCredentialSessionId:
|
|
2283
|
-
|
|
2491
|
+
session.getCredentialSessionId?.() ?? session.getSessionId?.() ?? undefined,
|
|
2284
2492
|
thinkingLevel: thinkingLevelOverride,
|
|
2285
2493
|
outputSchema: effectiveOutputSchema,
|
|
2286
2494
|
sessionFile: taskSessionFile,
|
|
@@ -2288,39 +2496,43 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2288
2496
|
artifactsDir: effectiveArtifactsDir,
|
|
2289
2497
|
managedPersistence,
|
|
2290
2498
|
contextFile: contextFilePath,
|
|
2291
|
-
ircAvailable: hasAvailableIrcTool(
|
|
2499
|
+
ircAvailable: hasAvailableIrcTool(session),
|
|
2292
2500
|
enableLsp: subagentLspEnabled,
|
|
2293
2501
|
signal,
|
|
2294
|
-
eventBus:
|
|
2502
|
+
eventBus: session.eventBus,
|
|
2295
2503
|
routing: routingForRun,
|
|
2296
|
-
autoroutingCandidates:
|
|
2297
|
-
autoroutingSkips:
|
|
2298
|
-
autoroutingPreflightErrors:
|
|
2504
|
+
autoroutingCandidates: includeAutoroutingResolution ? autoroutingData.candidates : undefined,
|
|
2505
|
+
autoroutingSkips: includeAutoroutingResolution ? autoroutingData.skips : undefined,
|
|
2506
|
+
autoroutingPreflightErrors: includeAutoroutingResolution
|
|
2507
|
+
? autoroutingData.preflightErrors
|
|
2508
|
+
: undefined,
|
|
2299
2509
|
autoroutingPreflight: autoroutingInitial,
|
|
2300
2510
|
|
|
2301
2511
|
onProgress: progress => {
|
|
2302
2512
|
progressMap.set(index, {
|
|
2303
2513
|
...structuredClone(progress),
|
|
2304
2514
|
});
|
|
2305
|
-
|
|
2515
|
+
ownedJobManager?.recordSubagentProgress(task.id, progress);
|
|
2306
2516
|
emitProgress();
|
|
2307
2517
|
},
|
|
2308
|
-
authStorage:
|
|
2309
|
-
modelRegistry:
|
|
2310
|
-
agentRegistry:
|
|
2311
|
-
settings:
|
|
2312
|
-
agentDir:
|
|
2313
|
-
profileAuthority:
|
|
2314
|
-
inheritedServiceTier:
|
|
2518
|
+
authStorage: session.authStorage,
|
|
2519
|
+
modelRegistry: session.modelRegistry,
|
|
2520
|
+
agentRegistry: session.agentRegistry,
|
|
2521
|
+
settings: session.settings,
|
|
2522
|
+
agentDir: session.getSessionAgentDir?.() ?? session.settings.getAgentDir(),
|
|
2523
|
+
profileAuthority: session.profileAuthority,
|
|
2524
|
+
inheritedServiceTier: session.serviceTier,
|
|
2525
|
+
...inheritedSubagentApproval(session),
|
|
2526
|
+
...inheritedPlanMode(session),
|
|
2315
2527
|
contextFiles,
|
|
2316
2528
|
skills: availableSkills,
|
|
2317
2529
|
autoloadSkills: resolvedAutoloadSkills,
|
|
2318
|
-
workspaceTree:
|
|
2530
|
+
workspaceTree: session.workspaceTree,
|
|
2319
2531
|
promptTemplates,
|
|
2320
2532
|
localProtocolOptions,
|
|
2321
2533
|
parentArtifactManager,
|
|
2322
|
-
parentHindsightSessionState:
|
|
2323
|
-
parentTelemetry:
|
|
2534
|
+
parentHindsightSessionState: session.getHindsightSessionState?.(),
|
|
2535
|
+
parentTelemetry: session.getTelemetry?.(),
|
|
2324
2536
|
parentMcpManager: reusableParentMcpManager,
|
|
2325
2537
|
forkContextSeed,
|
|
2326
2538
|
});
|
|
@@ -2346,7 +2558,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2346
2558
|
await assertExecutionRootMatchesRepositoryBinding(isolationDir, taskRepositoryBinding);
|
|
2347
2559
|
|
|
2348
2560
|
const result = await this.#runSubprocess({
|
|
2349
|
-
cwd:
|
|
2561
|
+
cwd: session.cwd,
|
|
2350
2562
|
worktree: isolationDir,
|
|
2351
2563
|
agent: effectiveAgent,
|
|
2352
2564
|
task: renderTaskAssignment(task.assignment, simpleMode),
|
|
@@ -2366,9 +2578,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2366
2578
|
parentActiveModelPattern,
|
|
2367
2579
|
parentActiveModelProfile: parentOwnedModelProfile,
|
|
2368
2580
|
parentModelProfileOwnershipMarker: parentModelProfileOwnershipMarker as any,
|
|
2369
|
-
parentSessionId:
|
|
2581
|
+
parentSessionId: session.getSessionId?.() ?? undefined,
|
|
2370
2582
|
parentCredentialSessionId:
|
|
2371
|
-
|
|
2583
|
+
session.getCredentialSessionId?.() ?? session.getSessionId?.() ?? undefined,
|
|
2372
2584
|
thinkingLevel: thinkingLevelOverride,
|
|
2373
2585
|
outputSchema: effectiveOutputSchema,
|
|
2374
2586
|
sessionFile: taskSessionFile,
|
|
@@ -2376,38 +2588,42 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2376
2588
|
artifactsDir: effectiveArtifactsDir,
|
|
2377
2589
|
managedPersistence,
|
|
2378
2590
|
contextFile: contextFilePath,
|
|
2379
|
-
ircAvailable: hasAvailableIrcTool(
|
|
2591
|
+
ircAvailable: hasAvailableIrcTool(session),
|
|
2380
2592
|
enableLsp: subagentLspEnabled,
|
|
2381
2593
|
signal,
|
|
2382
|
-
eventBus:
|
|
2594
|
+
eventBus: session.eventBus,
|
|
2383
2595
|
routing: routingForRun,
|
|
2384
|
-
autoroutingCandidates:
|
|
2385
|
-
autoroutingSkips:
|
|
2386
|
-
autoroutingPreflightErrors:
|
|
2596
|
+
autoroutingCandidates: includeAutoroutingResolution ? autoroutingData.candidates : undefined,
|
|
2597
|
+
autoroutingSkips: includeAutoroutingResolution ? autoroutingData.skips : undefined,
|
|
2598
|
+
autoroutingPreflightErrors: includeAutoroutingResolution
|
|
2599
|
+
? autoroutingData.preflightErrors
|
|
2600
|
+
: undefined,
|
|
2387
2601
|
autoroutingPreflight: autoroutingInitial,
|
|
2388
2602
|
onProgress: progress => {
|
|
2389
2603
|
progressMap.set(index, {
|
|
2390
2604
|
...structuredClone(progress),
|
|
2391
2605
|
});
|
|
2392
|
-
|
|
2606
|
+
ownedJobManager?.recordSubagentProgress(task.id, progress);
|
|
2393
2607
|
emitProgress();
|
|
2394
2608
|
},
|
|
2395
|
-
authStorage:
|
|
2396
|
-
modelRegistry:
|
|
2397
|
-
agentRegistry:
|
|
2398
|
-
settings:
|
|
2399
|
-
agentDir:
|
|
2400
|
-
profileAuthority:
|
|
2401
|
-
inheritedServiceTier:
|
|
2609
|
+
authStorage: session.authStorage,
|
|
2610
|
+
modelRegistry: session.modelRegistry,
|
|
2611
|
+
agentRegistry: session.agentRegistry,
|
|
2612
|
+
settings: session.settings,
|
|
2613
|
+
agentDir: session.getSessionAgentDir?.() ?? session.settings.getAgentDir(),
|
|
2614
|
+
profileAuthority: session.profileAuthority,
|
|
2615
|
+
inheritedServiceTier: session.serviceTier,
|
|
2616
|
+
...inheritedSubagentApproval(session),
|
|
2617
|
+
...inheritedPlanMode(session),
|
|
2402
2618
|
contextFiles,
|
|
2403
2619
|
skills: availableSkills,
|
|
2404
2620
|
autoloadSkills: resolvedAutoloadSkills,
|
|
2405
|
-
workspaceTree:
|
|
2621
|
+
workspaceTree: session.workspaceTree,
|
|
2406
2622
|
promptTemplates,
|
|
2407
2623
|
localProtocolOptions,
|
|
2408
2624
|
parentArtifactManager,
|
|
2409
|
-
parentHindsightSessionState:
|
|
2410
|
-
parentTelemetry:
|
|
2625
|
+
parentHindsightSessionState: session.getHindsightSessionState?.(),
|
|
2626
|
+
parentTelemetry: session.getTelemetry?.(),
|
|
2411
2627
|
parentMcpManager: reusableParentMcpManager,
|
|
2412
2628
|
forkContextSeed,
|
|
2413
2629
|
});
|
|
@@ -2425,15 +2641,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2425
2641
|
if (mergeMode === "branch" && taskSucceeded) {
|
|
2426
2642
|
try {
|
|
2427
2643
|
const commitMsg =
|
|
2428
|
-
commitStyle === "ai" &&
|
|
2644
|
+
commitStyle === "ai" && session.modelRegistry
|
|
2429
2645
|
? async (diff: string) => {
|
|
2430
2646
|
return generateCommitMessage(
|
|
2431
2647
|
diff,
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
this.session.getSessionId?.() ??
|
|
2436
|
-
undefined,
|
|
2648
|
+
session.modelRegistry!,
|
|
2649
|
+
session.settings,
|
|
2650
|
+
session.getCredentialSessionId?.() ?? session.getSessionId?.() ?? undefined,
|
|
2437
2651
|
);
|
|
2438
2652
|
}
|
|
2439
2653
|
: undefined;
|