@gajae-code/coding-agent 0.14.2 → 0.15.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 +120 -1
- package/dist/types/async/job-manager.d.ts +4 -1
- package/dist/types/autoresearch/dashboard.d.ts +29 -4
- package/dist/types/autoresearch/data-context.d.ts +25 -0
- package/dist/types/autoresearch/git.d.ts +65 -7
- package/dist/types/autoresearch/harness.d.ts +58 -0
- package/dist/types/autoresearch/prompts.d.ts +51 -0
- package/dist/types/autoresearch/runs.d.ts +173 -0
- package/dist/types/autoresearch/types.d.ts +9 -139
- package/dist/types/capability/types.d.ts +20 -0
- package/dist/types/cli/accounts-cli.d.ts +1 -0
- package/dist/types/commands/{rlm.d.ts → autoresearch.d.ts} +2 -4
- package/dist/types/config/autorouting-contract.d.ts +146 -0
- package/dist/types/config/autorouting-generator.d.ts +40 -0
- package/dist/types/config/autorouting-tier-map.d.ts +16844 -0
- package/dist/types/config/autorouting.d.ts +35 -0
- package/dist/types/config/model-discovery-manager.d.ts +8 -1
- package/dist/types/config/model-registry.d.ts +30 -1
- package/dist/types/config/provider-selection-policy.d.ts +23 -0
- package/dist/types/config/settings-schema.d.ts +61 -3
- package/dist/types/config/settings.d.ts +3 -0
- package/dist/types/coordinator/contract.d.ts +1 -1
- package/dist/types/coordinator-mcp/durability.d.ts +29 -0
- package/dist/types/coordinator-mcp/event-webhook.d.ts +50 -0
- package/dist/types/coordinator-mcp/question-state.d.ts +1 -1
- package/dist/types/coordinator-mcp/server.d.ts +14 -0
- package/dist/types/crash/index-store.d.ts +3 -0
- package/dist/types/crash/record-loader.d.ts +2 -0
- package/dist/types/crash/upstream/relay.d.ts +5 -3
- package/dist/types/cursor.d.ts +12 -0
- package/dist/types/defaults/gjc-defaults.d.ts +35 -1
- package/dist/types/defaults/gjc-skills.generated.d.ts +1 -1
- package/dist/types/discovery/helpers.d.ts +1 -1
- package/dist/types/edit/index.d.ts +2 -1
- package/dist/types/eval/py/executor.d.ts +2 -0
- package/dist/types/extensibility/extensions/loader.d.ts +32 -0
- package/dist/types/extensibility/gjc-plugins/types.d.ts +1 -1
- package/dist/types/extensibility/skills.d.ts +2 -0
- package/dist/types/gjc-runtime/autoresearch-runtime.d.ts +194 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +1 -1
- package/dist/types/gjc-runtime/psmux-detect.d.ts +1 -1
- package/dist/types/gjc-runtime/python-transcript.d.ts +19 -0
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +2 -8
- package/dist/types/gjc-runtime/session-layout.d.ts +6 -3
- package/dist/types/gjc-runtime/state-renderer.d.ts +0 -22
- package/dist/types/gjc-runtime/state-schema.d.ts +7 -7
- package/dist/types/gjc-runtime/tmux-common.d.ts +2 -2
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +38 -1
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +2 -24
- package/dist/types/gjc-runtime/ultragoal-validation-policy.d.ts +73 -0
- package/dist/types/gjc-runtime/workflow-recovery-projection.d.ts +100 -0
- package/dist/types/hooks/skill-keywords.d.ts +1 -1
- package/dist/types/main.d.ts +0 -10
- package/dist/types/modes/acp/acp-agent.d.ts +13 -6
- package/dist/types/modes/components/model-selector.d.ts +14 -0
- package/dist/types/modes/components/skill-hud/render.d.ts +6 -1
- package/dist/types/modes/components/smart-routing-panel.d.ts +82 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +14 -0
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/types.d.ts +9 -0
- package/dist/types/rlm/artifacts.d.ts +4 -4
- package/dist/types/runtime/optional-runtime-services.d.ts +2 -1
- package/dist/types/runtime/workspace-tree-service.d.ts +5 -1
- package/dist/types/runtime-mcp/config.d.ts +6 -0
- package/dist/types/runtime-mcp/manager.d.ts +10 -0
- package/dist/types/sdk/acp/adapter.d.ts +0 -4
- package/dist/types/sdk/broker/broker.d.ts +1 -1
- package/dist/types/sdk/broker/lifecycle.d.ts +57 -2
- package/dist/types/sdk/broker/session-index.d.ts +15 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +6 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -0
- package/dist/types/sdk/bus/index.d.ts +8 -0
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +2 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +12 -2
- package/dist/types/sdk/client/client.d.ts +39 -4
- package/dist/types/sdk/host/host.d.ts +1 -0
- package/dist/types/sdk/host/internal-autorouting-state.d.ts +3 -0
- package/dist/types/sdk/host/model-pin.d.ts +29 -0
- package/dist/types/sdk/host/session-runtime.d.ts +2 -1
- package/dist/types/sdk/lifecycle-session.d.ts +13 -0
- package/dist/types/sdk/router/session-router.d.ts +27 -1
- package/dist/types/sdk/session.d.ts +11 -1
- package/dist/types/session/agent-session.d.ts +36 -6
- package/dist/types/session/artifacts.d.ts +16 -1
- package/dist/types/session/internal/managed-session-storage.d.ts +7 -0
- package/dist/types/session/session-manager.d.ts +84 -2
- package/dist/types/session/session-staging-paths.d.ts +3 -0
- package/dist/types/skill-state/canonical-skills.d.ts +1 -1
- package/dist/types/skill-state/workflow-hud.d.ts +12 -21
- package/dist/types/skill-state/workflow-mutation-guard.d.ts +1 -0
- package/dist/types/slash-commands/helpers/autorouting-status.d.ts +8 -0
- package/dist/types/system-prompt.d.ts +23 -0
- package/dist/types/task/executor.d.ts +35 -4
- package/dist/types/task/index.d.ts +17 -3
- package/dist/types/task/receipt.d.ts +3 -1
- package/dist/types/task/types.d.ts +144 -0
- package/dist/types/tools/atomic-file-write.d.ts +72 -0
- package/dist/types/tools/descriptors.d.ts +1 -0
- package/dist/types/tools/index.d.ts +36 -1
- package/dist/types/tools/move-session.d.ts +40 -0
- package/dist/types/tools/python.d.ts +12 -0
- package/dist/types/tools/resource-gc.d.ts +0 -3
- package/dist/types/tools/search.d.ts +8 -1
- package/dist/types/tools/skill.d.ts +9 -4
- package/dist/types/tools/subagent.d.ts +33 -3
- package/dist/types/utils/xml-escape.d.ts +2 -0
- package/dist/types/workflow/workflow-intent-diff.d.ts +2 -2
- package/dist/types/workflow/workflow-intent-report-consumer.d.ts +1 -1
- package/package.json +11 -12
- package/scripts/build-sdk-package-smoke.ts +7 -5
- package/scripts/check-autorouting-tier-map.ts +183 -0
- package/scripts/generate-sdk-operation-inventory.ts +12 -0
- package/scripts/generate-tool-catalog.ts +40 -5
- package/src/async/job-manager.ts +5 -2
- package/src/autoresearch/dashboard.ts +134 -314
- package/src/autoresearch/data-context.ts +35 -0
- package/src/autoresearch/git.ts +186 -26
- package/src/autoresearch/{helpers.ts → harness.ts} +65 -40
- package/src/autoresearch/{prompt-setup.md → prompts/prompt-setup.md} +7 -7
- package/src/autoresearch/prompts/prompt.md +103 -0
- package/src/autoresearch/prompts.ts +126 -0
- package/src/autoresearch/runs.ts +708 -0
- package/src/autoresearch/types.ts +9 -150
- package/src/capability/index.ts +4 -4
- package/src/capability/types.ts +20 -0
- package/src/cli/accounts-cli.ts +21 -5
- package/src/cli/config-cli.ts +25 -1
- package/src/cli/fast-help.ts +1 -2
- package/src/cli/list-models.ts +5 -8
- package/src/cli/setup-cli.ts +8 -0
- package/src/cli.ts +2 -21
- package/src/commands/autoresearch.ts +33 -0
- package/src/commands/coordinator.ts +15 -0
- package/src/commands/launch.ts +2 -4
- package/src/commands/quick-lane.ts +1 -1
- package/src/commands/sdk.ts +24 -0
- package/src/commands/state.ts +1 -1
- package/src/config/autorouting-contract.ts +474 -0
- package/src/config/autorouting-generator.ts +238 -0
- package/src/config/autorouting-tier-map.ts +6108 -0
- package/src/config/autorouting.ts +120 -0
- package/src/config/model-discovery-manager.ts +42 -11
- package/src/config/model-registry.ts +348 -68
- package/src/config/provider-selection-policy.ts +60 -9
- package/src/config/settings-schema.ts +195 -6
- package/src/config/settings.ts +62 -1
- package/src/config.ts +2 -3
- package/src/coordinator/contract.ts +0 -1
- package/src/coordinator-mcp/codex-handoff.ts +68 -42
- package/src/coordinator-mcp/durability.ts +200 -0
- package/src/coordinator-mcp/event-webhook.ts +278 -0
- package/src/coordinator-mcp/question-state.ts +109 -46
- package/src/coordinator-mcp/server.ts +932 -504
- package/src/crash/index-store.ts +126 -22
- package/src/crash/record-loader.ts +7 -0
- package/src/crash/upstream/relay.ts +82 -34
- package/src/cursor.ts +84 -1
- package/src/debug/index.ts +26 -0
- package/src/defaults/gjc/skills/autoresearch/SKILL.md +116 -0
- package/src/defaults/gjc/skills/autoresearch/auto-critic.md +46 -0
- package/src/defaults/gjc/skills/autoresearch/auto-iterate.md +42 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +17 -37
- package/src/defaults/gjc/skills/ralplan/SKILL.md +21 -18
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +6 -17
- package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +2 -2
- package/src/defaults/gjc-defaults.ts +89 -2
- package/src/defaults/gjc-skills.generated.ts +24 -17
- package/src/discovery/builtin.ts +18 -5
- package/src/discovery/helpers.ts +6 -6
- package/src/edit/index.ts +5 -2
- package/src/eval/py/executor.ts +8 -0
- package/src/extensibility/extensions/loader.ts +135 -13
- package/src/extensibility/extensions/wrapper.ts +1 -2
- package/src/extensibility/gjc-plugins/schema.ts +1 -1
- package/src/extensibility/runtime-skill-discovery.ts +2 -2
- package/src/extensibility/skill-management.ts +2 -3
- package/src/extensibility/skills.ts +16 -8
- package/src/gjc-runtime/autoresearch-runtime.ts +1509 -0
- package/src/gjc-runtime/gc-render.ts +0 -1
- package/src/gjc-runtime/gc-runtime.ts +1 -11
- package/src/gjc-runtime/launch-tmux.ts +3 -3
- package/src/gjc-runtime/psmux-detect.ts +2 -2
- package/src/gjc-runtime/python-transcript.ts +58 -0
- package/src/gjc-runtime/ralplan-runtime.ts +6 -18
- package/src/gjc-runtime/session-layout.ts +18 -7
- package/src/gjc-runtime/session-state-sidecar.ts +58 -9
- package/src/gjc-runtime/state-renderer.ts +0 -38
- package/src/gjc-runtime/state-runtime.ts +43 -22
- package/src/gjc-runtime/state-schema.ts +1 -1
- package/src/gjc-runtime/tmux-common.ts +7 -7
- package/src/gjc-runtime/ultragoal-change-set.ts +232 -11
- package/src/gjc-runtime/ultragoal-runtime.ts +309 -114
- package/src/gjc-runtime/ultragoal-validation-policy.ts +247 -0
- package/src/gjc-runtime/workflow-command-ref.ts +15 -11
- package/src/gjc-runtime/workflow-manifest.generated.json +413 -532
- package/src/gjc-runtime/workflow-manifest.ts +43 -83
- package/src/gjc-runtime/workflow-recovery-projection.ts +616 -0
- package/src/hooks/skill-keywords.ts +3 -3
- package/src/hooks/skill-state.ts +2 -2
- package/src/internal-urls/docs-index.generated.ts +26 -24
- package/src/lsp/index.ts +25 -5
- package/src/main.ts +2 -27
- package/src/modes/acp/acp-agent.ts +200 -75
- package/src/modes/components/model-selector.ts +216 -13
- package/src/modes/components/oauth-selector.ts +5 -5
- package/src/modes/components/skill-hud/render.ts +173 -35
- package/src/modes/components/smart-routing-panel.ts +531 -0
- package/src/modes/components/tool-status-header.ts +6 -3
- package/src/modes/controllers/command-controller.ts +17 -7
- package/src/modes/controllers/input-controller.ts +44 -9
- package/src/modes/controllers/runtime-mcp-command-controller.ts +4 -0
- package/src/modes/controllers/selector-controller.ts +298 -65
- package/src/modes/interactive-mode.ts +8 -1
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +1 -1
- package/src/modes/types.ts +9 -1
- package/src/prompts/agents/planner.md +1 -1
- package/src/prompts/system/system-prompt.md +1 -1
- package/src/prompts/system/volatile-project-context.md +2 -1
- package/src/prompts/tools/move-session.md +15 -0
- package/src/prompts/tools/python.md +12 -0
- package/src/prompts/tools/skill-discovery.md +1 -1
- package/src/prompts/tools/skill.md +2 -2
- package/src/prompts/tools/task-summary.md +1 -0
- package/src/prompts/tools/task.md +6 -0
- package/src/rlm/artifacts.ts +12 -10
- package/src/runtime/optional-runtime-services.ts +3 -2
- package/src/runtime/workspace-tree-service.ts +11 -3
- package/src/runtime-mcp/config.ts +8 -1
- package/src/runtime-mcp/manager.ts +33 -0
- package/src/sdk/acp/adapter.ts +48 -1
- package/src/sdk/broker/broker.ts +30 -2
- package/src/sdk/broker/discovery.ts +217 -2
- package/src/sdk/broker/lifecycle.ts +385 -59
- package/src/sdk/broker/session-index.ts +243 -48
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/bus/chat-daemon-control.ts +8 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +5 -0
- package/src/sdk/bus/index.ts +208 -11
- package/src/sdk/bus/kind-aware-reconciliation.ts +16 -0
- package/src/sdk/bus/reconciliation-store.ts +27 -5
- package/src/sdk/bus/telegram-daemon-contract.ts +12 -2
- package/src/sdk/client/client.ts +204 -22
- package/src/sdk/host/host.ts +16 -0
- package/src/sdk/host/internal-autorouting-state.ts +13 -0
- package/src/sdk/host/model-pin.ts +101 -0
- package/src/sdk/host/reverse-leases.ts +2 -1
- package/src/sdk/host/session-runtime.test.ts +224 -1
- package/src/sdk/host/session-runtime.ts +125 -37
- package/src/sdk/lifecycle/service.ts +3 -1
- package/src/sdk/lifecycle-session.ts +42 -1
- package/src/sdk/protocol/operation-inventory.generated.json +66 -0
- package/src/sdk/router/session-router.ts +375 -36
- package/src/sdk/session.ts +547 -47
- package/src/session/account-inventory.ts +1 -1
- package/src/session/agent-session.ts +765 -189
- package/src/session/artifacts.ts +234 -4
- package/src/session/internal/managed-session-storage.ts +91 -4
- package/src/session/provider-safety-stop-hint.ts +3 -2
- package/src/session/session-manager.ts +775 -16
- package/src/session/session-staging-paths.ts +8 -0
- package/src/setup/hermes/templates/operator-instructions.v1.md +0 -1
- package/src/setup/host-plugin-setup.ts +2 -2
- package/src/skill-state/active-state.ts +2 -2
- package/src/skill-state/canonical-skills.ts +1 -1
- package/src/skill-state/initial-phase.ts +1 -1
- package/src/skill-state/workflow-hud.ts +41 -41
- package/src/skill-state/workflow-mutation-guard.ts +26 -7
- package/src/slash-commands/builtin-registry.ts +77 -0
- package/src/slash-commands/helpers/autorouting-status.ts +55 -0
- package/src/system-prompt.ts +102 -5
- package/src/task/discovery.ts +2 -3
- package/src/task/executor.ts +617 -43
- package/src/task/index.ts +262 -15
- package/src/task/receipt.ts +30 -0
- package/src/task/render.ts +11 -1
- package/src/task/types.ts +316 -0
- package/src/tools/atomic-file-write.ts +594 -0
- package/src/tools/bisect.ts +3 -2
- package/src/tools/descriptors.test.ts +3 -0
- package/src/tools/descriptors.ts +24 -0
- package/src/tools/image-gen.ts +5 -1
- package/src/tools/index.ts +62 -5
- package/src/tools/move-session.ts +107 -0
- package/src/tools/python.ts +205 -0
- package/src/tools/read.ts +88 -15
- package/src/tools/renderers.ts +2 -0
- package/src/tools/resource-gc.ts +8 -177
- package/src/tools/search.ts +30 -6
- package/src/tools/skill-discovery.ts +1 -0
- package/src/tools/skill.ts +37 -7
- package/src/tools/subagent-render.ts +119 -13
- package/src/tools/subagent.ts +91 -74
- package/src/tools/tool-catalog.generated.ts +64 -2
- package/src/tools/write.ts +16 -12
- package/src/utils/xml-escape.ts +14 -0
- package/src/web/search/providers/codex.ts +2 -2
- package/src/workflow/workflow-intent-diff.ts +13 -12
- package/src/workflow/workflow-intent-report-consumer.ts +6 -6
- package/dist/types/autoresearch/helpers.d.ts +0 -24
- package/dist/types/autoresearch/index.d.ts +0 -2
- package/dist/types/autoresearch/state.d.ts +0 -17
- package/dist/types/autoresearch/storage.d.ts +0 -142
- package/dist/types/autoresearch/tools/init-experiment.d.ts +0 -31
- package/dist/types/autoresearch/tools/log-experiment.d.ts +0 -23
- package/dist/types/autoresearch/tools/run-experiment.d.ts +0 -8
- package/dist/types/autoresearch/tools/update-notes.d.ts +0 -12
- package/dist/types/commands/team.d.ts +0 -24
- package/dist/types/gjc-runtime/team-gc.d.ts +0 -7
- package/dist/types/gjc-runtime/team-launch.d.ts +0 -61
- package/dist/types/gjc-runtime/team-notify.d.ts +0 -45
- package/dist/types/gjc-runtime/team-runtime.d.ts +0 -336
- package/dist/types/gjc-runtime/team-store.d.ts +0 -168
- package/dist/types/gjc-runtime/team-worker-heartbeat.d.ts +0 -43
- package/dist/types/gjc-runtime/team-worker-memory-guard.d.ts +0 -92
- package/dist/types/gjc-runtime/team-workers.d.ts +0 -83
- package/dist/types/rlm/index.d.ts +0 -47
- package/dist/types/rlm/preset.d.ts +0 -23
- package/dist/types/rlm/python-tool.d.ts +0 -16
- package/src/autoresearch/command-resume.md +0 -14
- package/src/autoresearch/index.ts +0 -536
- package/src/autoresearch/prompt.md +0 -103
- package/src/autoresearch/resume-message.md +0 -10
- package/src/autoresearch/state.ts +0 -273
- package/src/autoresearch/storage.ts +0 -699
- package/src/autoresearch/tools/init-experiment.ts +0 -272
- package/src/autoresearch/tools/log-experiment.ts +0 -524
- package/src/autoresearch/tools/run-experiment.ts +0 -475
- package/src/autoresearch/tools/update-notes.ts +0 -109
- package/src/commands/rlm.ts +0 -19
- package/src/commands/team.ts +0 -238
- package/src/defaults/gjc/skills/deep-interview/auto-research-greenfield.md +0 -42
- package/src/defaults/gjc/skills/team/SKILL.md +0 -467
- package/src/gjc-runtime/team-gc.ts +0 -49
- package/src/gjc-runtime/team-launch.ts +0 -404
- package/src/gjc-runtime/team-notify.ts +0 -326
- package/src/gjc-runtime/team-runtime.ts +0 -5923
- package/src/gjc-runtime/team-store.ts +0 -878
- package/src/gjc-runtime/team-worker-heartbeat.ts +0 -149
- package/src/gjc-runtime/team-worker-memory-guard.ts +0 -363
- package/src/gjc-runtime/team-workers.ts +0 -1123
- package/src/prompts/system/rlm-report-command.md +0 -1
- package/src/prompts/system/rlm-research.md +0 -23
- package/src/rlm/index.ts +0 -365
- package/src/rlm/preset.ts +0 -76
- package/src/rlm/python-tool.ts +0 -68
package/src/task/index.ts
CHANGED
|
@@ -26,6 +26,8 @@ import {
|
|
|
26
26
|
} from "@gajae-code/coding-agent/async";
|
|
27
27
|
import { $pickenv, prompt, Snowflake } from "@gajae-code/utils";
|
|
28
28
|
import type { ToolSession } from "..";
|
|
29
|
+
import { normalizeTierSelector, type RoutingOutcome, resolveTaskRouting } from "../config/autorouting";
|
|
30
|
+
import { AUTOROUTING_SELECTOR_MAX_LENGTH, type AutoroutingReasonCode } from "../config/autorouting-contract";
|
|
29
31
|
import { resolveProfileBindings } from "../config/model-profiles";
|
|
30
32
|
import { resolveAgentModelPatterns } from "../config/model-resolver";
|
|
31
33
|
import type { Theme } from "../modes/theme/theme";
|
|
@@ -33,7 +35,9 @@ import planModeSubagentPrompt from "../prompts/system/plan-mode-subagent.md" wit
|
|
|
33
35
|
import taskDescriptionTemplate from "../prompts/tools/task.md" with { type: "text" };
|
|
34
36
|
import taskSummaryTemplate from "../prompts/tools/task-summary.md" with { type: "text" };
|
|
35
37
|
import type { ForkContextSeed } from "../session/agent-session";
|
|
38
|
+
import { splitSelectorThinkingSuffix } from "../thinking";
|
|
36
39
|
import { formatBytes, formatDuration } from "../tools/render-utils";
|
|
40
|
+
import { escapeXmlAttribute } from "../utils/xml-escape";
|
|
37
41
|
import {
|
|
38
42
|
type AgentDefinition,
|
|
39
43
|
type AgentProgress,
|
|
@@ -44,6 +48,7 @@ import {
|
|
|
44
48
|
type SingleResult,
|
|
45
49
|
type TaskItem,
|
|
46
50
|
type TaskParams,
|
|
51
|
+
type TaskRoutingEvidence,
|
|
47
52
|
type TaskToolDetails,
|
|
48
53
|
type TaskToolSchemaInstance,
|
|
49
54
|
} from "./types";
|
|
@@ -66,7 +71,13 @@ import { generateCommitMessage } from "../utils/commit-message-generator";
|
|
|
66
71
|
import * as git from "../utils/git";
|
|
67
72
|
import { loadBundledAgents } from "./agents";
|
|
68
73
|
import { discoverAgents, filterVisibleAgents, getAgent } from "./discovery";
|
|
69
|
-
import {
|
|
74
|
+
import {
|
|
75
|
+
buildBoundedRoutingSkips,
|
|
76
|
+
createManagedTaskPersistence,
|
|
77
|
+
renderSubagentUserPrompt,
|
|
78
|
+
runSubprocess,
|
|
79
|
+
} from "./executor";
|
|
80
|
+
|
|
70
81
|
import { adviseForkContextMode } from "./fork-context-advisory";
|
|
71
82
|
import { FORK_CONTEXT_TOKEN_BUDGET_BY_MODE } from "./fork-context-budget";
|
|
72
83
|
import { getTaskIdValidationError, validateAllocatedTaskId } from "./id";
|
|
@@ -132,7 +143,7 @@ function renderTaskAssignment(assignment: string, simpleMode: TaskSimpleMode): s
|
|
|
132
143
|
export function subagentRunOutcomeFromSingleResult(
|
|
133
144
|
finalText: string,
|
|
134
145
|
singleResult:
|
|
135
|
-
| (Pick<SingleResult, "aborted" | "exitCode" | "paused" | "setupFailure"> &
|
|
146
|
+
| (Pick<SingleResult, "aborted" | "exitCode" | "paused" | "setupFailure" | "localErrorSummary"> &
|
|
136
147
|
Partial<Pick<TaskResultReceipt, "status">>)
|
|
137
148
|
| undefined,
|
|
138
149
|
): string | SubagentRunOutcome {
|
|
@@ -145,6 +156,9 @@ export function subagentRunOutcomeFromSingleResult(
|
|
|
145
156
|
...(singleResult.setupFailure && !singleResult.aborted
|
|
146
157
|
? { setupFailureSummary: singleResult.setupFailure.summary }
|
|
147
158
|
: {}),
|
|
159
|
+
...(singleResult.localErrorSummary && !singleResult.aborted
|
|
160
|
+
? { localErrorSummary: singleResult.localErrorSummary }
|
|
161
|
+
: {}),
|
|
148
162
|
};
|
|
149
163
|
}
|
|
150
164
|
if (singleResult && ((singleResult.aborted ?? false) || singleResult.exitCode !== 0)) {
|
|
@@ -154,6 +168,9 @@ export function subagentRunOutcomeFromSingleResult(
|
|
|
154
168
|
...(singleResult.setupFailure && !singleResult.aborted
|
|
155
169
|
? { setupFailureSummary: singleResult.setupFailure.summary }
|
|
156
170
|
: {}),
|
|
171
|
+
...(singleResult.localErrorSummary && !singleResult.aborted
|
|
172
|
+
? { localErrorSummary: singleResult.localErrorSummary }
|
|
173
|
+
: {}),
|
|
157
174
|
};
|
|
158
175
|
}
|
|
159
176
|
return finalText;
|
|
@@ -316,6 +333,7 @@ function renderDescription(
|
|
|
316
333
|
simpleMode: TaskSimpleMode,
|
|
317
334
|
ircEnabled: boolean,
|
|
318
335
|
parentSpawns: string,
|
|
336
|
+
autoroutingActive: boolean,
|
|
319
337
|
): string {
|
|
320
338
|
const spawningDisabled = parentSpawns === "";
|
|
321
339
|
let filteredAgents = filterVisibleAgents(agents);
|
|
@@ -333,7 +351,7 @@ function renderDescription(
|
|
|
333
351
|
filteredAgents = filteredAgents.filter(a => allowed.has(a.name));
|
|
334
352
|
}
|
|
335
353
|
const { contextEnabled, customSchemaEnabled } = getTaskSimpleModeCapabilities(simpleMode);
|
|
336
|
-
|
|
354
|
+
const description = prompt.render(taskDescriptionTemplate, {
|
|
337
355
|
agents: filteredAgents,
|
|
338
356
|
spawningDisabled,
|
|
339
357
|
MAX_CONCURRENCY: maxConcurrency,
|
|
@@ -345,7 +363,9 @@ function renderDescription(
|
|
|
345
363
|
defaultMode: simpleMode === "default",
|
|
346
364
|
schemaFreeMode: simpleMode === "schema-free",
|
|
347
365
|
independentMode: simpleMode === "independent",
|
|
366
|
+
autoroutingActive,
|
|
348
367
|
});
|
|
368
|
+
return description;
|
|
349
369
|
}
|
|
350
370
|
|
|
351
371
|
function createTaskModeError(text: string): AgentToolResult<TaskToolDetails> {
|
|
@@ -479,6 +499,47 @@ export function resolveForkContextMaxTokens(configured: number, model: Model | u
|
|
|
479
499
|
return normalizeForkContextCap(configured, fallback, Number.MAX_SAFE_INTEGER);
|
|
480
500
|
}
|
|
481
501
|
|
|
502
|
+
const ROUTING_SUMMARY_UNSAFE_RE = /[\u0000-\u001f\u007f-\u009f\u2028\u2029]/gu;
|
|
503
|
+
|
|
504
|
+
function sanitizeRoutingSummaryValue(value: string): string {
|
|
505
|
+
return value.normalize("NFKC").replace(ROUTING_SUMMARY_UNSAFE_RE, " ").slice(0, AUTOROUTING_SELECTOR_MAX_LENGTH);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
export function findRoutingSnapshotModel(selector: string, routingSnapshot: readonly Model[]): Model | undefined {
|
|
509
|
+
const slash = selector.indexOf("/");
|
|
510
|
+
if (slash <= 0) return undefined;
|
|
511
|
+
const provider = selector.slice(0, slash).toLowerCase();
|
|
512
|
+
const modelId = selector.slice(slash + 1);
|
|
513
|
+
const providerMatches = routingSnapshot.filter(candidate => candidate.provider.toLowerCase() === provider);
|
|
514
|
+
return (
|
|
515
|
+
providerMatches.find(candidate => candidate.id === modelId) ??
|
|
516
|
+
providerMatches.find(candidate => {
|
|
517
|
+
const suffix = splitSelectorThinkingSuffix(modelId);
|
|
518
|
+
return (
|
|
519
|
+
suffix.invalidSuffix === undefined && suffix.thinkingLevel !== undefined && candidate.id === suffix.selector
|
|
520
|
+
);
|
|
521
|
+
})
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Project routing evidence into the XML-attribute-safe display view consumed by
|
|
527
|
+
* the task-summary template. The template runtime uses noEscape, so every
|
|
528
|
+
* interpolated attribute value must be escaped here.
|
|
529
|
+
*/
|
|
530
|
+
export function projectRoutingForSummary(
|
|
531
|
+
routing: TaskRoutingEvidence | undefined,
|
|
532
|
+
): { tier: string; effectiveModel: string; note: string } | undefined {
|
|
533
|
+
if (!routing) return undefined;
|
|
534
|
+
return {
|
|
535
|
+
tier: escapeXmlAttribute(sanitizeRoutingSummaryValue(routing.tier)),
|
|
536
|
+
effectiveModel: escapeXmlAttribute(
|
|
537
|
+
sanitizeRoutingSummaryValue(routing.effectiveModel ?? routing.requestedSelector),
|
|
538
|
+
),
|
|
539
|
+
note: escapeXmlAttribute(sanitizeRoutingSummaryValue(routing.note ?? "")),
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
|
|
482
543
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
483
544
|
// Tool Class
|
|
484
545
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -559,9 +620,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
559
620
|
this.#getTaskSimpleMode(),
|
|
560
621
|
hasAvailableIrcTool(this.session),
|
|
561
622
|
this.session.getSessionSpawns() ?? "*",
|
|
623
|
+
this.session.settings.getEffectiveAutorouting().active,
|
|
562
624
|
);
|
|
563
625
|
}
|
|
564
626
|
readonly #sessionRepositoryBinding: RepositoryBinding;
|
|
627
|
+
#testRunSubprocess: typeof runSubprocess | undefined;
|
|
565
628
|
|
|
566
629
|
private constructor(
|
|
567
630
|
private readonly session: ToolSession,
|
|
@@ -573,6 +636,10 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
573
636
|
this.#sessionRepositoryBinding = sessionRepositoryBinding;
|
|
574
637
|
}
|
|
575
638
|
|
|
639
|
+
#runSubprocess(options: Parameters<typeof runSubprocess>[0]): Promise<SingleResult> {
|
|
640
|
+
return (this.#testRunSubprocess ?? runSubprocess)(options);
|
|
641
|
+
}
|
|
642
|
+
|
|
576
643
|
#getTaskSimpleMode(): TaskSimpleMode {
|
|
577
644
|
return this.session.settings.get("task.simple");
|
|
578
645
|
}
|
|
@@ -794,12 +861,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
794
861
|
* Repository authority is captured from session cwd *before* agent discovery so
|
|
795
862
|
* multi-repo workspaces fail closed prior to context/discovery (#2901).
|
|
796
863
|
*/
|
|
797
|
-
static async create(session: ToolSession): Promise<TaskTool> {
|
|
864
|
+
static async create(session: ToolSession, options?: { runSubprocess?: typeof runSubprocess }): Promise<TaskTool> {
|
|
798
865
|
const sessionRepositoryBinding = await captureRepositoryBinding(session.cwd, { displayPath: session.cwd });
|
|
799
|
-
// Authority check before discovery: session cwd must resolve to a stable binding.
|
|
800
866
|
await assertExecutionRootMatchesRepositoryBinding(session.cwd, sessionRepositoryBinding);
|
|
801
867
|
const { agents } = await discoverAgents(session.cwd);
|
|
802
|
-
|
|
868
|
+
const tool = new TaskTool(session, agents, publicRepositoryBinding(sessionRepositoryBinding));
|
|
869
|
+
tool.#testRunSubprocess = options?.runSubprocess;
|
|
870
|
+
return tool;
|
|
803
871
|
}
|
|
804
872
|
|
|
805
873
|
/** Create catalog metadata from bundled agents only, without ambient filesystem discovery. */
|
|
@@ -1941,6 +2009,123 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1941
2009
|
}
|
|
1942
2010
|
const tasksWithUniqueIds = tasks.map((t, i) => ({ ...t, id: validateAllocatedTaskId(uniqueIds[i] ?? "") }));
|
|
1943
2011
|
|
|
2012
|
+
const effectiveAutorouting = this.session.settings.getEffectiveAutorouting();
|
|
2013
|
+
const registry = this.session.modelRegistry as
|
|
2014
|
+
| {
|
|
2015
|
+
getAvailable?: () => Model[];
|
|
2016
|
+
getAll?: () => Model[];
|
|
2017
|
+
getApiKey?: (model: Model, credentialSessionId?: string) => Promise<string | undefined>;
|
|
2018
|
+
}
|
|
2019
|
+
| undefined;
|
|
2020
|
+
const routingSnapshot = registry?.getAll?.() ?? registry?.getAvailable?.();
|
|
2021
|
+
const routingByIndex = new Map<number, RoutingOutcome>();
|
|
2022
|
+
const routingCandidatesByIndex = new Map<number, string[]>();
|
|
2023
|
+
const routingSkipsByIndex = new Map<number, Array<{ selector: string; code: AutoroutingReasonCode }>>();
|
|
2024
|
+
for (let i = 0; i < tasksWithUniqueIds.length; i++) {
|
|
2025
|
+
const task = tasksWithUniqueIds[i];
|
|
2026
|
+
const outcome = routingSnapshot
|
|
2027
|
+
? resolveTaskRouting({
|
|
2028
|
+
effectiveAutorouting,
|
|
2029
|
+
requestedTier: task.tier,
|
|
2030
|
+
availableModels: routingSnapshot,
|
|
2031
|
+
})
|
|
2032
|
+
: effectiveAutorouting.active
|
|
2033
|
+
? {
|
|
2034
|
+
kind: "manual-fallback" as const,
|
|
2035
|
+
tier: task.tier ?? "balanced",
|
|
2036
|
+
requestedTier: task.tier,
|
|
2037
|
+
...(task.tier === undefined ? { defaultTierApplied: true as const } : {}),
|
|
2038
|
+
attemptedSelectorCount: 0,
|
|
2039
|
+
reason: "tier_unmatched" as const,
|
|
2040
|
+
}
|
|
2041
|
+
: { kind: "disabled" as const };
|
|
2042
|
+
|
|
2043
|
+
routingByIndex.set(i, outcome);
|
|
2044
|
+
if (outcome.kind === "disabled" || !routingSnapshot || !effectiveAutorouting.active) continue;
|
|
2045
|
+
|
|
2046
|
+
// Enumerate every configured selector before choosing a routed or manual
|
|
2047
|
+
// outcome. This keeps AC12 evidence complete even when every selector is
|
|
2048
|
+
// missing, malformed, or disabled.
|
|
2049
|
+
const configured = effectiveAutorouting.map[outcome.tier] ?? [];
|
|
2050
|
+
const candidates: string[] = [];
|
|
2051
|
+
const skips: Array<{ selector: string; code: AutoroutingReasonCode }> = [];
|
|
2052
|
+
const disabledProviders = new Set(
|
|
2053
|
+
this.session.settings.get("disabledProviders").map(provider => provider.toLowerCase()),
|
|
2054
|
+
);
|
|
2055
|
+
for (const selector of configured) {
|
|
2056
|
+
const slash = selector.indexOf("/");
|
|
2057
|
+
const provider = slash > 0 ? selector.slice(0, slash).toLowerCase() : "";
|
|
2058
|
+
// Disabled takes precedence over snapshot presence: a disabled provider
|
|
2059
|
+
// that is also absent must remain truthfully classified as disabled.
|
|
2060
|
+
if (disabledProviders.has(provider)) {
|
|
2061
|
+
skips.push({ selector, code: "provider_disabled" });
|
|
2062
|
+
continue;
|
|
2063
|
+
}
|
|
2064
|
+
const normalized = normalizeTierSelector(selector, routingSnapshot);
|
|
2065
|
+
if (!("pinned" in normalized)) {
|
|
2066
|
+
skips.push({
|
|
2067
|
+
selector,
|
|
2068
|
+
code: "rejected" in normalized ? "selector_not_provider_qualified" : "snapshot_missing",
|
|
2069
|
+
});
|
|
2070
|
+
continue;
|
|
2071
|
+
}
|
|
2072
|
+
candidates.push(normalized.pinned);
|
|
2073
|
+
}
|
|
2074
|
+
routingCandidatesByIndex.set(i, candidates);
|
|
2075
|
+
routingSkipsByIndex.set(i, skips);
|
|
2076
|
+
}
|
|
2077
|
+
const resolveAutoroutingCandidates = async (
|
|
2078
|
+
index: number,
|
|
2079
|
+
): Promise<{
|
|
2080
|
+
candidates: string[];
|
|
2081
|
+
skips: Array<{ selector: string; code: AutoroutingReasonCode }>;
|
|
2082
|
+
preflightErrors: Map<string, unknown>;
|
|
2083
|
+
}> => {
|
|
2084
|
+
const candidates = [...(routingCandidatesByIndex.get(index) ?? [])];
|
|
2085
|
+
const skips = [...(routingSkipsByIndex.get(index) ?? [])];
|
|
2086
|
+
const preflightErrors = new Map<string, unknown>();
|
|
2087
|
+
if (!registry?.getApiKey || !routingSnapshot) return { candidates, skips, preflightErrors };
|
|
2088
|
+
const authenticated: string[] = [];
|
|
2089
|
+
for (const selector of candidates) {
|
|
2090
|
+
const model = findRoutingSnapshotModel(selector, routingSnapshot);
|
|
2091
|
+
if (!model) {
|
|
2092
|
+
skips.push({ selector, code: "snapshot_missing" });
|
|
2093
|
+
continue;
|
|
2094
|
+
}
|
|
2095
|
+
try {
|
|
2096
|
+
const key = await registry.getApiKey(
|
|
2097
|
+
model,
|
|
2098
|
+
this.session.getCredentialSessionId?.() ?? this.session.getSessionId?.() ?? undefined,
|
|
2099
|
+
);
|
|
2100
|
+
if (key) authenticated.push(selector);
|
|
2101
|
+
else skips.push({ selector, code: "credential_unavailable" });
|
|
2102
|
+
} catch (error) {
|
|
2103
|
+
// Preserve the candidate for executor preflight, which records the
|
|
2104
|
+
// terminal lookup failure in the routing ledger.
|
|
2105
|
+
preflightErrors.set(selector, error);
|
|
2106
|
+
authenticated.push(selector);
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
return { candidates: authenticated, skips, preflightErrors };
|
|
2110
|
+
};
|
|
2111
|
+
const effectivePatterns = (index: number): string | string[] => {
|
|
2112
|
+
const outcome = routingByIndex.get(index);
|
|
2113
|
+
return outcome?.kind === "routed" ? [outcome.pinnedSelector] : modelOverride;
|
|
2114
|
+
};
|
|
2115
|
+
const routeEvidenceForSynthetic = (outcome: RoutingOutcome | undefined): TaskRoutingEvidence | undefined => {
|
|
2116
|
+
if (!outcome || outcome.kind === "disabled") return undefined;
|
|
2117
|
+
return {
|
|
2118
|
+
tier: outcome.tier,
|
|
2119
|
+
requestedTier: outcome.requestedTier,
|
|
2120
|
+
defaultTierApplied: outcome.defaultTierApplied,
|
|
2121
|
+
requestedSelector: outcome.kind === "routed" ? outcome.pinnedSelector : "manual-model-chain",
|
|
2122
|
+
notExecuted: true,
|
|
2123
|
+
substitutions: [],
|
|
2124
|
+
manualFallbackReason: outcome.kind === "manual-fallback" ? outcome.reason : undefined,
|
|
2125
|
+
note: `${outcome.tier}; ${outcome.kind === "manual-fallback" ? outcome.reason : "not-executed"}`,
|
|
2126
|
+
};
|
|
2127
|
+
};
|
|
2128
|
+
|
|
1944
2129
|
const availableSkills = [...(this.session.skills ?? [])];
|
|
1945
2130
|
// Resolve autoload skills from agent definition against available skills
|
|
1946
2131
|
const resolvedAutoloadSkills =
|
|
@@ -1975,7 +2160,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1975
2160
|
tokens: 0,
|
|
1976
2161
|
cost: 0,
|
|
1977
2162
|
durationMs: 0,
|
|
1978
|
-
modelOverride,
|
|
2163
|
+
modelOverride: effectivePatterns(i),
|
|
1979
2164
|
description: taskItem.description,
|
|
1980
2165
|
});
|
|
1981
2166
|
}
|
|
@@ -2034,6 +2219,51 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2034
2219
|
const managedPersistence = parentArtifactManager?.getManagedStore()
|
|
2035
2220
|
? createManagedTaskPersistence(parentArtifactManager, task.id)
|
|
2036
2221
|
: undefined;
|
|
2222
|
+
|
|
2223
|
+
const routingOutcome = routingByIndex.get(index);
|
|
2224
|
+
|
|
2225
|
+
const routeEvidence = (
|
|
2226
|
+
outcome: RoutingOutcome | undefined,
|
|
2227
|
+
freshOnResume = false,
|
|
2228
|
+
): TaskRoutingEvidence | undefined => {
|
|
2229
|
+
if (!outcome || outcome.kind === "disabled") return undefined;
|
|
2230
|
+
const noteParts = [
|
|
2231
|
+
`${outcome.tier}${outcome.defaultTierApplied ? " (default)" : ""}`,
|
|
2232
|
+
outcome.kind === "manual-fallback" ? outcome.reason : undefined,
|
|
2233
|
+
freshOnResume ? "freshOnResume" : undefined,
|
|
2234
|
+
].filter((part): part is string => part !== undefined);
|
|
2235
|
+
return {
|
|
2236
|
+
tier: outcome.tier,
|
|
2237
|
+
requestedTier: outcome.requestedTier,
|
|
2238
|
+
defaultTierApplied: outcome.defaultTierApplied,
|
|
2239
|
+
requestedSelector: outcome.kind === "routed" ? outcome.pinnedSelector : "manual-model-chain",
|
|
2240
|
+
effectiveModel: outcome.kind === "routed" ? outcome.pinnedSelector : "manual-model-chain",
|
|
2241
|
+
substitutions: [],
|
|
2242
|
+
manualFallbackReason: outcome.kind === "manual-fallback" ? outcome.reason : undefined,
|
|
2243
|
+
freshOnResume: freshOnResume ? true : undefined,
|
|
2244
|
+
note: noteParts.join("; "),
|
|
2245
|
+
};
|
|
2246
|
+
};
|
|
2247
|
+
|
|
2248
|
+
const effectiveRunMode = overrides?.runMode ?? executionOverrides?.runMode;
|
|
2249
|
+
const autoroutingInitial =
|
|
2250
|
+
routingOutcome?.kind === "routed" && (effectiveRunMode ?? "initial") === "initial";
|
|
2251
|
+
const autoroutingData =
|
|
2252
|
+
(effectiveRunMode ?? "initial") === "initial" && routingOutcome && routingOutcome.kind !== "disabled"
|
|
2253
|
+
? routingOutcome.kind === "routed"
|
|
2254
|
+
? await resolveAutoroutingCandidates(index)
|
|
2255
|
+
: {
|
|
2256
|
+
candidates: undefined,
|
|
2257
|
+
skips: [...(routingSkipsByIndex.get(index) ?? [])],
|
|
2258
|
+
preflightErrors: new Map(),
|
|
2259
|
+
}
|
|
2260
|
+
: { candidates: undefined, skips: undefined, preflightErrors: new Map() };
|
|
2261
|
+
const routingForRun = routeEvidence(
|
|
2262
|
+
routingOutcome,
|
|
2263
|
+
effectiveRunMode === "resume" || effectiveRunMode === "message",
|
|
2264
|
+
);
|
|
2265
|
+
if (routingForRun && autoroutingData.skips)
|
|
2266
|
+
Object.assign(routingForRun, buildBoundedRoutingSkips(autoroutingData.skips));
|
|
2037
2267
|
const taskSessionFile = managedPersistence
|
|
2038
2268
|
? null
|
|
2039
2269
|
: (overrides?.sessionFile ?? executionOverrides?.sessionFiles?.get(task.id) ?? null);
|
|
@@ -2044,7 +2274,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2044
2274
|
}
|
|
2045
2275
|
if (!isIsolated) {
|
|
2046
2276
|
await assertExecutionRootMatchesRepositoryBinding(this.session.cwd, taskRepositoryBinding);
|
|
2047
|
-
const result = await runSubprocess({
|
|
2277
|
+
const result = await this.#runSubprocess({
|
|
2048
2278
|
cwd: this.session.cwd,
|
|
2049
2279
|
agent: effectiveAgent,
|
|
2050
2280
|
task: renderTaskAssignment(task.assignment, simpleMode),
|
|
@@ -2054,12 +2284,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2054
2284
|
description: task.description,
|
|
2055
2285
|
index,
|
|
2056
2286
|
id: task.id,
|
|
2057
|
-
runMode:
|
|
2287
|
+
runMode: effectiveRunMode,
|
|
2288
|
+
|
|
2058
2289
|
resumeMessage: overrides?.resumeMessage ?? executionOverrides?.resumeMessage,
|
|
2059
2290
|
subagentId: task.id,
|
|
2060
2291
|
asyncJobManager: manager,
|
|
2061
2292
|
taskDepth,
|
|
2062
|
-
modelOverride,
|
|
2293
|
+
modelOverride: effectivePatterns(index),
|
|
2063
2294
|
parentActiveModelPattern,
|
|
2064
2295
|
parentActiveModelProfile: parentOwnedModelProfile,
|
|
2065
2296
|
parentSessionId: this.session.getSessionId?.() ?? undefined,
|
|
@@ -2076,6 +2307,12 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2076
2307
|
enableLsp: subagentLspEnabled,
|
|
2077
2308
|
signal,
|
|
2078
2309
|
eventBus: this.session.eventBus,
|
|
2310
|
+
routing: routingForRun,
|
|
2311
|
+
autoroutingCandidates: autoroutingInitial ? autoroutingData.candidates : undefined,
|
|
2312
|
+
autoroutingSkips: autoroutingInitial ? autoroutingData.skips : undefined,
|
|
2313
|
+
autoroutingPreflightErrors: autoroutingInitial ? autoroutingData.preflightErrors : undefined,
|
|
2314
|
+
autoroutingPreflight: autoroutingInitial,
|
|
2315
|
+
|
|
2079
2316
|
onProgress: progress => {
|
|
2080
2317
|
progressMap.set(index, {
|
|
2081
2318
|
...structuredClone(progress),
|
|
@@ -2121,7 +2358,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2121
2358
|
// Isolated worktrees must preserve the source repository identity (#2901).
|
|
2122
2359
|
await assertExecutionRootMatchesRepositoryBinding(isolationDir, taskRepositoryBinding);
|
|
2123
2360
|
|
|
2124
|
-
const result = await runSubprocess({
|
|
2361
|
+
const result = await this.#runSubprocess({
|
|
2125
2362
|
cwd: this.session.cwd,
|
|
2126
2363
|
worktree: isolationDir,
|
|
2127
2364
|
agent: effectiveAgent,
|
|
@@ -2132,12 +2369,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2132
2369
|
description: task.description,
|
|
2133
2370
|
index,
|
|
2134
2371
|
id: task.id,
|
|
2135
|
-
runMode:
|
|
2372
|
+
runMode: effectiveRunMode,
|
|
2373
|
+
|
|
2136
2374
|
resumeMessage: overrides?.resumeMessage ?? executionOverrides?.resumeMessage,
|
|
2137
2375
|
subagentId: task.id,
|
|
2138
2376
|
asyncJobManager: manager,
|
|
2139
2377
|
taskDepth,
|
|
2140
|
-
modelOverride,
|
|
2378
|
+
modelOverride: effectivePatterns(index),
|
|
2141
2379
|
parentActiveModelPattern,
|
|
2142
2380
|
parentActiveModelProfile: parentOwnedModelProfile,
|
|
2143
2381
|
parentSessionId: this.session.getSessionId?.() ?? undefined,
|
|
@@ -2154,6 +2392,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2154
2392
|
enableLsp: subagentLspEnabled,
|
|
2155
2393
|
signal,
|
|
2156
2394
|
eventBus: this.session.eventBus,
|
|
2395
|
+
routing: routingForRun,
|
|
2396
|
+
autoroutingCandidates: autoroutingInitial ? autoroutingData.candidates : undefined,
|
|
2397
|
+
autoroutingSkips: autoroutingInitial ? autoroutingData.skips : undefined,
|
|
2398
|
+
autoroutingPreflightErrors: autoroutingInitial ? autoroutingData.preflightErrors : undefined,
|
|
2399
|
+
autoroutingPreflight: autoroutingInitial,
|
|
2157
2400
|
onProgress: progress => {
|
|
2158
2401
|
progressMap.set(index, {
|
|
2159
2402
|
...structuredClone(progress),
|
|
@@ -2285,7 +2528,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2285
2528
|
truncated: false,
|
|
2286
2529
|
durationMs: Date.now() - taskStart,
|
|
2287
2530
|
tokens: 0,
|
|
2288
|
-
modelOverride,
|
|
2531
|
+
modelOverride: effectivePatterns(index),
|
|
2532
|
+
routing: routeEvidenceForSynthetic(routingByIndex.get(index)),
|
|
2533
|
+
|
|
2289
2534
|
forkContext,
|
|
2290
2535
|
error: message,
|
|
2291
2536
|
};
|
|
@@ -2325,7 +2570,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2325
2570
|
truncated: false,
|
|
2326
2571
|
durationMs: 0,
|
|
2327
2572
|
tokens: 0,
|
|
2328
|
-
modelOverride,
|
|
2573
|
+
modelOverride: effectivePatterns(index),
|
|
2574
|
+
routing: routeEvidenceForSynthetic(routingByIndex.get(index)),
|
|
2329
2575
|
error: "Cancelled before start",
|
|
2330
2576
|
aborted: true,
|
|
2331
2577
|
abortReason: "Cancelled before start",
|
|
@@ -2647,6 +2893,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
2647
2893
|
charSize: formatBytes(r.outputRef.sizeBytes),
|
|
2648
2894
|
}
|
|
2649
2895
|
: undefined,
|
|
2896
|
+
routing: projectRoutingForSummary(r.routing),
|
|
2650
2897
|
};
|
|
2651
2898
|
});
|
|
2652
2899
|
|
package/src/task/receipt.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { AUTOROUTING_SELECTOR_MAX_LENGTH } from "../config/autorouting-contract";
|
|
1
2
|
import {
|
|
3
|
+
assertRoutingEvidenceInvariant,
|
|
2
4
|
hasCompleteUsageCostBreakdown,
|
|
3
5
|
type ReviewFindingsArtifactRef,
|
|
4
6
|
type SingleResult,
|
|
7
|
+
type TaskRoutingEvidence,
|
|
5
8
|
type TaskToolDetails,
|
|
6
9
|
} from "./types";
|
|
7
10
|
export interface TaskRoi {
|
|
@@ -33,6 +36,7 @@ export interface TaskResultReceipt {
|
|
|
33
36
|
contextTokens?: number;
|
|
34
37
|
contextWindow?: number;
|
|
35
38
|
modelOverride?: string | string[];
|
|
39
|
+
routing?: TaskRoutingEvidence;
|
|
36
40
|
modelSubstitutionWarning?: SingleResult["modelSubstitutionWarning"];
|
|
37
41
|
fastMode?: boolean;
|
|
38
42
|
usage?: SingleResult["usage"];
|
|
@@ -42,6 +46,7 @@ export interface TaskResultReceipt {
|
|
|
42
46
|
persistence?: SingleResult["persistence"];
|
|
43
47
|
retryFailure?: { attempt: number; errorSummary: string };
|
|
44
48
|
setupFailure?: { summary: string };
|
|
49
|
+
localErrorSummary?: SingleResult["localErrorSummary"];
|
|
45
50
|
errorSummary?: string;
|
|
46
51
|
duplicateDisposition?: SingleResult["duplicateDisposition"];
|
|
47
52
|
abortSummary?: string;
|
|
@@ -145,6 +150,9 @@ function buildSafeSynopsis(raw: SingleResult, outputRef: TaskResultReceipt["outp
|
|
|
145
150
|
if (raw.abortReason) {
|
|
146
151
|
return `Task ${status}; abort reason recorded.`;
|
|
147
152
|
}
|
|
153
|
+
if (raw.localErrorSummary) {
|
|
154
|
+
return `Task ${status}; local failure (${raw.localErrorSummary.kind}): ${raw.localErrorSummary.summary}`;
|
|
155
|
+
}
|
|
148
156
|
if (raw.error) {
|
|
149
157
|
return `Task ${status}; error recorded.`;
|
|
150
158
|
}
|
|
@@ -243,6 +251,25 @@ export function buildTaskRoiSummary(receipts: readonly TaskResultReceipt[]): Tas
|
|
|
243
251
|
lowRoiChildIds: receipts.filter(receipt => receipt.roi?.lowRoi).map(receipt => receipt.id),
|
|
244
252
|
};
|
|
245
253
|
}
|
|
254
|
+
function validatedRoutingEvidence(value: TaskRoutingEvidence | undefined): TaskRoutingEvidence | undefined {
|
|
255
|
+
if (!value) return undefined;
|
|
256
|
+
try {
|
|
257
|
+
const bounded: TaskRoutingEvidence = {
|
|
258
|
+
...value,
|
|
259
|
+
requestedSelector: value.requestedSelector.slice(0, AUTOROUTING_SELECTOR_MAX_LENGTH),
|
|
260
|
+
skips: value.skips
|
|
261
|
+
?.slice(0, 16)
|
|
262
|
+
.map(skip => ({ ...skip, selector: skip.selector.slice(0, AUTOROUTING_SELECTOR_MAX_LENGTH) })),
|
|
263
|
+
attempts: value.attempts
|
|
264
|
+
?.slice(0, 6)
|
|
265
|
+
.map(attempt => ({ ...attempt, selector: attempt.selector.slice(0, AUTOROUTING_SELECTOR_MAX_LENGTH) })),
|
|
266
|
+
};
|
|
267
|
+
assertRoutingEvidenceInvariant(bounded);
|
|
268
|
+
return bounded;
|
|
269
|
+
} catch {
|
|
270
|
+
return undefined;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
246
273
|
|
|
247
274
|
export function buildTaskReceipt(raw: SingleResult): TaskResultReceipt {
|
|
248
275
|
// Receipts only include outputRef when production code kept outputMeta after a
|
|
@@ -284,6 +311,7 @@ export function buildTaskReceipt(raw: SingleResult): TaskResultReceipt {
|
|
|
284
311
|
contextWindow: raw.contextWindow,
|
|
285
312
|
modelOverride: raw.modelOverride,
|
|
286
313
|
modelSubstitutionWarning: raw.modelSubstitutionWarning,
|
|
314
|
+
routing: validatedRoutingEvidence(raw.routing),
|
|
287
315
|
usage: raw.usage,
|
|
288
316
|
cost: raw.usage?.cost.total,
|
|
289
317
|
usageCostBreakdownComplete:
|
|
@@ -295,8 +323,10 @@ export function buildTaskReceipt(raw: SingleResult): TaskResultReceipt {
|
|
|
295
323
|
? { attempt: raw.retryFailure.attempt, errorSummary: "Retry failure recorded." }
|
|
296
324
|
: undefined,
|
|
297
325
|
duplicateDisposition: raw.duplicateDisposition,
|
|
326
|
+
localErrorSummary: raw.localErrorSummary,
|
|
298
327
|
errorSummary:
|
|
299
328
|
raw.setupFailure?.summary ??
|
|
329
|
+
raw.localErrorSummary?.summary ??
|
|
300
330
|
(raw.error
|
|
301
331
|
? "Error recorded."
|
|
302
332
|
: raw.persistence?.outcome === "recovery_available"
|
package/src/task/render.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import type { Component } from "@gajae-code/tui";
|
|
9
9
|
import { Text } from "@gajae-code/tui";
|
|
10
|
-
import { formatNumber, sanitizeText } from "@gajae-code/utils";
|
|
10
|
+
import { formatNumber, sanitizeDisplayLine, sanitizeText } from "@gajae-code/utils";
|
|
11
11
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
12
12
|
import type { Theme } from "../modes/theme/theme";
|
|
13
13
|
import {
|
|
@@ -913,6 +913,16 @@ function renderAgentResult(result: TaskResultReceipt, isLast: boolean, expanded:
|
|
|
913
913
|
)}`,
|
|
914
914
|
);
|
|
915
915
|
}
|
|
916
|
+
if (result.routing) {
|
|
917
|
+
const model = result.routing.effectiveModel ?? "not-executed";
|
|
918
|
+
const note = result.routing.note ? ` ${result.routing.note}` : "";
|
|
919
|
+
// effectiveModel is provider-reported and note is free-form diagnostic text;
|
|
920
|
+
// receipt validation bounds neither, and an embedded newline would inject a
|
|
921
|
+
// row past the width cap, so flatten to a single sanitized line.
|
|
922
|
+
lines.push(
|
|
923
|
+
`${continuePrefix}${theme.fg("dim", truncateToWidth(replaceTabs(sanitizeDisplayLine(`Routing: ${model}${note}`)), 90))}`,
|
|
924
|
+
);
|
|
925
|
+
}
|
|
916
926
|
if (result.roi?.lowRoi) {
|
|
917
927
|
lines.push(`${continuePrefix}${theme.fg("warning", "low ROI: produced no material contribution")}`);
|
|
918
928
|
}
|