mixdog 0.9.87 → 0.9.89
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/package.json +13 -7
- package/scripts/tool-failures.mjs +60 -24
- package/src/agents/heavy-worker/AGENT.md +3 -4
- package/src/agents/worker/AGENT.md +1 -2
- package/src/cli.mjs +8 -0
- package/src/defaults/cycle3-review-prompt.md +4 -4
- package/src/rules/agent/00-core.md +3 -0
- package/src/rules/agent/42-cycle3-agent.md +5 -6
- package/src/rules/lead/01-general.md +2 -0
- package/src/rules/shared/01-tool.md +29 -35
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +3 -51
- package/src/runtime/agent/orchestrator/agent-runtime/maintenance-route.mjs +59 -0
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +2 -2
- package/src/runtime/agent/orchestrator/agent-runtime/title-completion.mjs +67 -0
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +57 -4
- package/src/runtime/agent/orchestrator/agent-trace-io.mjs +2 -3
- package/src/runtime/agent/orchestrator/config.mjs +29 -11
- package/src/runtime/agent/orchestrator/context/collect.mjs +1 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +1 -1
- package/src/runtime/agent/orchestrator/mcp/client.mjs +0 -24
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +3 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +25 -17
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +321 -22
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +35 -22
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +28 -23
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +10 -2
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth-tokens.mjs +0 -1
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +2 -5
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-native-blocks.mjs +27 -0
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +23 -0
- package/src/runtime/agent/orchestrator/providers/lib/stream-outcome.mjs +329 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +23 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +107 -20
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +4 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +124 -12
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +19 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-responses-payload.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +110 -75
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +96 -113
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +160 -11
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +18 -1
- package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +147 -117
- package/src/runtime/agent/orchestrator/session/loop/stop-hooks.mjs +88 -0
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +50 -8
- package/src/runtime/agent/orchestrator/session/loop/termination.mjs +25 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +47 -6
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +485 -24
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +100 -2
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +28 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +80 -14
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint.mjs +142 -2
- package/src/runtime/agent/orchestrator/session/manager/usage-metrics.mjs +128 -32
- package/src/runtime/agent/orchestrator/session/manager.mjs +5 -1
- package/src/runtime/agent/orchestrator/session/save-session-worker.mjs +77 -4
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +70 -39
- package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +91 -0
- package/src/runtime/agent/orchestrator/session/store/listing.mjs +141 -64
- package/src/runtime/agent/orchestrator/session/store/live-state.mjs +253 -0
- package/src/runtime/agent/orchestrator/session/store/load-cache.mjs +211 -28
- package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +313 -0
- package/src/runtime/agent/orchestrator/session/store/save-worker.mjs +622 -53
- package/src/runtime/agent/orchestrator/session/store/serialize.mjs +43 -10
- package/src/runtime/agent/orchestrator/session/store/summary-cache.mjs +53 -8
- package/src/runtime/agent/orchestrator/session/store/summary-rebuild-worker.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/store/write-guards.mjs +113 -9
- package/src/runtime/agent/orchestrator/session/store-summary-index.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +476 -52
- package/src/runtime/agent/orchestrator/session/store.mjs +721 -196
- package/src/runtime/agent/orchestrator/session/token-native.mjs +2 -4
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +19 -0
- package/src/runtime/agent/orchestrator/tools/bash-session.mjs +4 -6
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +146 -90
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +93 -17
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +5 -0
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +7 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-spawn.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +85 -5
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-store.mjs +52 -0
- package/src/runtime/agent/orchestrator/tools/code-graph/disk-cache.mjs +54 -51
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +14 -15
- package/src/runtime/agent/orchestrator/tools/patch/dispatch.mjs +132 -8
- package/src/runtime/agent/orchestrator/tools/patch/matcher.mjs +86 -3
- package/src/runtime/agent/orchestrator/tools/patch/native-server.mjs +6 -1
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +210 -38
- package/src/runtime/agent/orchestrator/tools/patch/paths.mjs +23 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +87 -19
- package/src/runtime/agent/orchestrator/tools/patch-manifest.json +11 -11
- package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +33 -8
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +12 -2
- package/src/runtime/media/lanes.mjs +2 -2
- package/src/runtime/media/renditions.mjs +101 -17
- package/src/runtime/media/renditions.test.mjs +54 -0
- package/src/runtime/media/store.mjs +111 -43
- package/src/runtime/media/store.test.mjs +53 -11
- package/src/runtime/memory/index.mjs +26 -50
- package/src/runtime/memory/lib/core-memory-candidates.mjs +2 -7
- package/src/runtime/memory/lib/core-memory-store.mjs +2 -9
- package/src/runtime/memory/lib/cycle-scheduler.mjs +10 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +3 -3
- package/src/runtime/memory/lib/embedding-worker.mjs +60 -15
- package/src/runtime/memory/lib/http-router.mjs +4 -0
- package/src/runtime/memory/lib/ko-morph.mjs +49 -6
- package/src/runtime/memory/lib/memory-action-handlers.mjs +21 -18
- package/src/runtime/memory/lib/memory-cycle2.mjs +3 -3
- package/src/runtime/memory/lib/memory-cycle3.mjs +1 -3
- package/src/runtime/memory/lib/memory-recall-store.mjs +24 -0
- package/src/runtime/memory/lib/query-handlers.mjs +26 -28
- package/src/runtime/memory/tool-defs.mjs +3 -3
- package/src/runtime/shared/atomic-file.mjs +5 -1
- package/src/runtime/shared/child-guardian.mjs +73 -2
- package/src/runtime/shared/provider-api-key.mjs +22 -5
- package/src/runtime/shared/tool-execution-contract.mjs +53 -0
- package/src/session-runtime/config-helpers.mjs +6 -5
- package/src/session-runtime/lifecycle-api.mjs +16 -4
- package/src/session-runtime/media-api.mjs +31 -16
- package/src/session-runtime/prewarm.mjs +2 -24
- package/src/session-runtime/runtime-core.mjs +33 -15
- package/src/session-runtime/runtime-tunables.mjs +0 -3
- package/src/session-runtime/session-lifecycle.mjs +0 -6
- package/src/session-runtime/session-title.mjs +228 -0
- package/src/session-runtime/session-turn-api.mjs +11 -7
- package/src/session-runtime/workflow-agents-api.mjs +16 -0
- package/src/session-runtime/workflow.mjs +7 -5
- package/src/standalone/agent-tool/job-views.mjs +90 -36
- package/src/standalone/agent-tool/spawn-flow.mjs +25 -216
- package/src/standalone/agent-tool/worker-index.mjs +8 -0
- package/src/standalone/agent-tool/worker-rows.mjs +2 -1
- package/src/standalone/agent-tool.mjs +17 -17
- package/src/standalone/agent-watchdog-registry.mjs +19 -2
- package/src/standalone/channel-daemon.mjs +8 -0
- package/src/standalone/explore-tool.mjs +1 -1
- package/src/standalone/memory-runtime-proxy.mjs +4 -7
- package/src/standalone/projects.mjs +4 -1
- package/src/standalone/usage-dashboard.mjs +25 -3
- package/src/tui/App.jsx +5 -3
- package/src/tui/app/resume-picker.mjs +7 -2
- package/src/tui/app/route-pickers.mjs +11 -117
- package/src/tui/app/slash-dispatch.mjs +13 -3
- package/src/tui/app/transcript-row-estimate.mjs +1 -1
- package/src/tui/app/transcript-window.mjs +17 -93
- package/src/tui/app/use-transcript-scroll.mjs +32 -2
- package/src/tui/app/use-transcript-window.mjs +64 -114
- package/src/tui/components/Markdown.jsx +19 -2
- package/src/tui/components/Message.jsx +8 -3
- package/src/tui/components/ToolExecution.jsx +7 -3
- package/src/tui/dist/index.mjs +243 -223
- package/src/tui/engine/live-share.mjs +15 -5
- package/src/tui/engine/render-timing.mjs +2 -2
- package/src/tui/engine/session-api-ext.mjs +74 -4
- package/src/tui/engine/session-flow.mjs +3 -1
- package/src/tui/engine.mjs +2 -2
- package/src/tui/hooks/useSharedTick.mjs +0 -2
- package/src/tui/index.jsx +5 -5
- package/src/ui/statusline-agents.mjs +44 -11
- package/src/vendor/statusline/bin/statusline-route.mjs +26 -3
- package/src/workflows/default/WORKFLOW.md +3 -3
- package/src/workflows/solo/WORKFLOW.md +5 -3
- package/src/runtime/media/index.mjs +0 -18
- package/src/runtime/memory/lib/embedding-warmup.mjs +0 -68
- package/src/standalone/agent-shard/shard-child.mjs +0 -300
- package/src/standalone/agent-shard/shard-pool.mjs +0 -443
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mixdog",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.89",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Standalone mixdog coding-agent CLI/TUI workspace.",
|
|
@@ -49,6 +49,8 @@
|
|
|
49
49
|
"smoke:all": "npm run smoke && npm run smoke:boot && npm run smoke:patch && npm run smoke:output && npm run smoke:tui && npm run smoke:live-worker",
|
|
50
50
|
"smoke:boot": "node scripts/boot-smoke.mjs",
|
|
51
51
|
"smoke:compact": "node scripts/compact-smoke.mjs",
|
|
52
|
+
"test:compact": "node --test scripts/compact-active-turn-test.mjs scripts/compact-file-reattach-test.mjs scripts/compact-prior-context-flatten-test.mjs scripts/compact-recall-digest-test.mjs scripts/compact-pressure-test.mjs",
|
|
53
|
+
"test:context": "node --test scripts/context-mcp-metering-test.mjs scripts/v4a-context-miss-excerpt-test.mjs",
|
|
52
54
|
"smoke:loop": "node scripts/smoke-loop.mjs",
|
|
53
55
|
"smoke:loop:final": "node scripts/smoke-loop-report.mjs --require-complete --min-elapsed 5h --min-iterations 400 --max-gap 60s --max-smoke-ms 10000 --max-avg-smoke-ms 8500 --max-step-ms smoke.mjs=4000 --max-step-ms boot-smoke.mjs=8000 --max-rss-mb 140 --max-rss-growth-mb 50",
|
|
54
56
|
"smoke:loop:report": "node scripts/smoke-loop-report.mjs",
|
|
@@ -61,12 +63,13 @@
|
|
|
61
63
|
"smoke:live-worker": "node scripts/live-worker-smoke.mjs",
|
|
62
64
|
"smoke:agent-tag-reuse": "node scripts/agent-tag-reuse-smoke.mjs",
|
|
63
65
|
"test:agent-terminal-reap": "node scripts/agent-terminal-reap-test.mjs",
|
|
66
|
+
"test:agent-job-views": "node --test scripts/agent-job-terminal-view-test.mjs",
|
|
64
67
|
"test:agent-fanout": "node scripts/agent-parallel-smoke.mjs && node --test scripts/agent-route-batch-test.mjs scripts/execution-completion-dedup-test.mjs",
|
|
65
68
|
"test:toolcall": "node --test scripts/toolcall-args-test.mjs",
|
|
66
69
|
"test:shipmode": "node --test scripts/ship-mode-test.mjs",
|
|
67
|
-
"test:shellhardening": "node --test scripts/shell-hardening-test.mjs scripts/shell-failure-diagnostics-test.mjs",
|
|
70
|
+
"test:shellhardening": "node --test scripts/shell-hardening-test.mjs scripts/shell-failure-diagnostics-test.mjs scripts/windows-hide-spawn-options-test.mjs",
|
|
68
71
|
"test:placeholder": "node --test scripts/compacted-placeholder-scrub-test.mjs",
|
|
69
|
-
"test:providers": "node --test scripts/provider-toolcall-test.mjs scripts/provider-contract-test.mjs",
|
|
72
|
+
"test:providers": "node --test scripts/provider-toolcall-test.mjs scripts/provider-contract-test.mjs scripts/provider-stream-stall-test.mjs scripts/provider-stream-outcome-test.mjs scripts/stream-frame-fault-matrix-test.mjs scripts/gemini-provider-test.mjs scripts/anthropic-transport-policy-test.mjs scripts/anthropic-native-block-replay-test.mjs scripts/openai-oauth-ws-1006-retry-test.mjs scripts/openai-end-turn-signal-test.mjs",
|
|
70
73
|
"test:provider-admission": "node --test scripts/provider-admission-scheduler-test.mjs",
|
|
71
74
|
"test:resource-admission": "node --test scripts/resource-admission-test.mjs",
|
|
72
75
|
"test:deferred-tools": "node --test scripts/deferred-tool-loading-test.mjs",
|
|
@@ -80,20 +83,23 @@
|
|
|
80
83
|
"test:embedding-runtime:warmup": "node scripts/verify-embedding-runtime.mjs --warmup",
|
|
81
84
|
"test:code-graph-dispatch": "node --test scripts/code-graph-dispatch-test.mjs",
|
|
82
85
|
"test:code-graph-clean-cache": "node --test scripts/code-graph-dispatch-test.mjs",
|
|
83
|
-
"test:tui-queue": "node --test scripts/submit-commandbusy-race-test.mjs scripts/steering-drain-buckets-test.mjs scripts/abort-recovery-test.mjs scripts/execution-pending-resume-kick-test.mjs scripts/execution-resume-esc-integration-test.mjs",
|
|
86
|
+
"test:tui-queue": "node --test scripts/submit-commandbusy-race-test.mjs scripts/steering-drain-buckets-test.mjs scripts/abort-recovery-test.mjs scripts/execution-pending-resume-kick-test.mjs scripts/execution-resume-esc-integration-test.mjs scripts/pending-stale-injection-test.mjs",
|
|
84
87
|
"test:tui-input-render": "node --test scripts/prompt-immediate-render-test.mjs",
|
|
85
88
|
"test:tui-streaming-window": "node --test scripts/streaming-tail-window-test.mjs",
|
|
86
89
|
"test:tui-ambiguous-width": "node --test scripts/tui-ambiguous-width-test.mjs",
|
|
87
90
|
"test:release-assets": "node --check scripts/verify-release-assets.mjs && node --check scripts/verify-release-assets-test.mjs && node --check scripts/deploy-workflow-test.mjs && node --test scripts/verify-release-assets-test.mjs scripts/deploy-workflow-test.mjs",
|
|
88
|
-
"test:release-focused": "npm run test:release-assets && npm run test:tool-contracts && npm run test:placeholder && npm run smoke:patch && npm run test:patch-binary-cache && npm run test:providers && npm run test:deferred-tools && npm run smoke:compact && node --test scripts/code-graph-root-federation-test.mjs scripts/code-graph-aggregate-cwd-test.mjs && npm run test:code-graph-dispatch && node --test scripts/code-graph-disk-hit-test.mjs && npm run test:shellhardening &&
|
|
91
|
+
"test:release-focused": "npm run test:release-assets && npm run test:tool-contracts && npm run test:placeholder && npm run smoke:patch && npm run test:patch-binary-cache && npm run test:providers && npm run test:deferred-tools && npm run smoke:compact && npm run test:compact && npm run test:context && node --test scripts/code-graph-root-federation-test.mjs scripts/code-graph-aggregate-cwd-test.mjs && npm run test:code-graph-dispatch && node --test scripts/code-graph-disk-hit-test.mjs && npm run test:shellhardening && npm run test:project-registry && npm run test:session && npm run test:workflow-editor && npm run test:embedding-runtime && node --test scripts/tui-transcript-perf-test.mjs",
|
|
89
92
|
"test:native-edit-wire": "node --test scripts/native-edit-wire-test.mjs",
|
|
90
93
|
"test:patch-binary-cache": "node --test scripts/patch-binary-cache-test.mjs",
|
|
91
|
-
"test:
|
|
94
|
+
"test:patch-parity": "node --test scripts/v4a-codex-parity-test.mjs",
|
|
95
|
+
"test:project-registry": "node --test scripts/project-registry-isolation-test.mjs",
|
|
96
|
+
"test:session": "node --test scripts/session-orphan-sweep-test.mjs scripts/interrupted-turn-history-test.mjs scripts/turn-checkpoint-crash-test.mjs scripts/turn-outcome-fault-matrix-test.mjs scripts/session-save-fault-store-test.mjs scripts/session-disk-authority-test.mjs scripts/session-load-cache-race-test.mjs scripts/agent-loop-complete-turn-test.mjs scripts/session-heartbeat-lifecycle-test.mjs scripts/remote-transition-order-test.mjs scripts/session-new-reset-test.mjs",
|
|
97
|
+
"test:live-canary": "node --test scripts/live-canary-test.mjs",
|
|
92
98
|
"test:rebindtail": "node --test scripts/forwarder-rebind-tail-test.mjs",
|
|
93
99
|
"test:workflow-editor": "node --test scripts/workflow-id-test.mjs scripts/workflow-pack-editor-test.mjs",
|
|
94
100
|
"test:route-scope": "node --test scripts/route-scope-isolation-test.mjs",
|
|
95
101
|
"test:schedule-reload": "node --test scripts/schedule-reload-arm-test.mjs",
|
|
96
|
-
"test:media": "node --test src/runtime/media/store.test.mjs",
|
|
102
|
+
"test:media": "node --test src/runtime/media/store.test.mjs src/runtime/media/renditions.test.mjs",
|
|
97
103
|
"failures": "node scripts/tool-failures.mjs",
|
|
98
104
|
"trace:llm": "node scripts/llm-trace-summary.mjs",
|
|
99
105
|
"diag:sessions": "node scripts/session-diag.mjs",
|
|
@@ -88,6 +88,7 @@ function rowCategory(row) {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
const sinceTs = parseSince(sinceArg);
|
|
91
|
+
const onlyArg = String(argValue('--only', 'all') || 'all').toLowerCase();
|
|
91
92
|
const rows = files.flatMap(readRows)
|
|
92
93
|
.filter((row) => sinceTs == null || Number(row.ts || 0) >= sinceTs)
|
|
93
94
|
.filter((row) => !toolFilter || rowTool(row) === toolFilter)
|
|
@@ -95,6 +96,11 @@ const rows = files.flatMap(readRows)
|
|
|
95
96
|
.filter((row) => !categoryFilter || rowCategory(row) === categoryFilter)
|
|
96
97
|
.sort((a, b) => Number(a.ts || 0) - Number(b.ts || 0));
|
|
97
98
|
const isCommandExit = (row) => rowCategory(row) === 'command-exit';
|
|
99
|
+
// Absorbed-by-design outcomes (compacted-history placeholder preflight, etc.):
|
|
100
|
+
// retained in the log and displayed, but never counted as actionable work.
|
|
101
|
+
const isExpectedAbsorbed = (row) => /^expected-/.test(String(rowCategory(row)));
|
|
102
|
+
const isPatchFailure = (row) => /^patch\//.test(String(rowCategory(row)));
|
|
103
|
+
const categoryFamily = (row) => String(rowCategory(row)).split('/')[0] || '(uncategorized)';
|
|
98
104
|
const rowLeadingErrorLine = (row) => [
|
|
99
105
|
row.error_first_line,
|
|
100
106
|
row.error_preview,
|
|
@@ -109,25 +115,41 @@ const isExpectedCancellation = (row) => {
|
|
|
109
115
|
if (rowCategory(row) === 'expected-cancellation') return true;
|
|
110
116
|
return /^Session\s+"[^"]+"\s+closed:\s*(?:aborted|closed)\s+during call\b/i.test(rowLeadingErrorLine(row));
|
|
111
117
|
};
|
|
112
|
-
const
|
|
113
|
-
const
|
|
118
|
+
const cancellationRows = rows.filter(isExpectedCancellation);
|
|
119
|
+
const liveRows = rows.filter((row) => !isExpectedCancellation(row));
|
|
120
|
+
const commandExitRows = liveRows.filter(isCommandExit);
|
|
121
|
+
// Ordinary non-zero test/command exits and absorbed preflights are reported
|
|
122
|
+
// separately so a green-but-noisy run never reads as N tool/patch failures.
|
|
123
|
+
const expectedRows = liveRows.filter((row) => !isCommandExit(row) && isExpectedAbsorbed(row));
|
|
124
|
+
const actionableRows = liveRows.filter((row) => !isCommandExit(row) && !isExpectedAbsorbed(row));
|
|
125
|
+
const patchRows = actionableRows.filter(isPatchFailure);
|
|
126
|
+
const wants = (kind) => onlyArg === 'all' || onlyArg === kind;
|
|
114
127
|
// Limit each partition independently so a burst of ordinary command exits
|
|
115
128
|
// cannot crowd runtime/actionable failures out of the displayed report.
|
|
116
|
-
const actionableRecent = actionableRows.slice(-limit);
|
|
117
|
-
const commandExitRecent = commandExitRows.slice(-limit);
|
|
118
|
-
const
|
|
129
|
+
const actionableRecent = wants('actionable') ? actionableRows.slice(-limit) : [];
|
|
130
|
+
const commandExitRecent = wants('exits') ? commandExitRows.slice(-limit) : [];
|
|
131
|
+
const expectedRecent = wants('expected') ? expectedRows.slice(-limit) : [];
|
|
132
|
+
const recent = [...actionableRecent, ...commandExitRecent, ...expectedRecent]
|
|
119
133
|
.sort((a, b) => Number(a.ts || 0) - Number(b.ts || 0));
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
for (const row of recent) {
|
|
125
|
-
const tool = rowTool(row);
|
|
126
|
-
const category = rowCategory(row);
|
|
127
|
-
inc(byTool, tool);
|
|
128
|
-
inc(byCategory, `${tool} / ${category}`);
|
|
129
|
-
inc(isCommandExit(row) ? commandExitByTool : actionableByTool, tool);
|
|
134
|
+
function tally(list, keyFn) {
|
|
135
|
+
const map = new Map();
|
|
136
|
+
for (const row of list) inc(map, keyFn(row));
|
|
137
|
+
return map;
|
|
130
138
|
}
|
|
139
|
+
const sortedEntries = (map) => [...map.entries()].sort((a, b) => b[1] - a[1]);
|
|
140
|
+
const asObject = (map) => Object.fromEntries(sortedEntries(map));
|
|
141
|
+
const asText = (map) => sortedEntries(map).map(([k, v]) => `${k}:${v}`).join(', ') || '(none)';
|
|
142
|
+
// Aggregates cover every MATCHED row in the window (not just the displayed
|
|
143
|
+
// tail) so `--since 24h` headline totals cannot be read as the whole picture
|
|
144
|
+
// while a truncated tail hides the rest.
|
|
145
|
+
const byTool = tally(recent, rowTool);
|
|
146
|
+
const byCategory = tally(recent, (row) => `${rowTool(row)} / ${rowCategory(row)}`);
|
|
147
|
+
const actionableByTool = tally(actionableRows, rowTool);
|
|
148
|
+
const actionableByCategory = tally(actionableRows, rowCategory);
|
|
149
|
+
const actionableByFamily = tally(actionableRows, categoryFamily);
|
|
150
|
+
const commandExitByTool = tally(commandExitRows, rowTool);
|
|
151
|
+
const expectedByCategory = tally(expectedRows, rowCategory);
|
|
152
|
+
const patchByCategory = tally(patchRows, rowCategory);
|
|
131
153
|
|
|
132
154
|
if (jsonMode) {
|
|
133
155
|
console.log(JSON.stringify({
|
|
@@ -135,36 +157,50 @@ if (jsonMode) {
|
|
|
135
157
|
matched: rows.length,
|
|
136
158
|
actionable_failures: { shown: actionableRecent.length, matched: actionableRows.length },
|
|
137
159
|
command_exits: { shown: commandExitRecent.length, matched: commandExitRows.length },
|
|
160
|
+
expected_absorbed: { shown: expectedRecent.length, matched: expectedRows.length },
|
|
161
|
+
session_cancellations: { shown: 0, matched: cancellationRows.length },
|
|
162
|
+
patch_failures: { matched: patchRows.length, categories: asObject(patchByCategory) },
|
|
138
163
|
since: sinceTs ? new Date(sinceTs).toISOString() : null,
|
|
139
164
|
filters: {
|
|
140
165
|
tool: toolFilter,
|
|
141
166
|
agent: agentFilter,
|
|
142
167
|
category: categoryFilter,
|
|
168
|
+
only: onlyArg,
|
|
143
169
|
},
|
|
144
170
|
sources: files.filter(existsSync),
|
|
145
|
-
tools:
|
|
146
|
-
actionable_tools:
|
|
147
|
-
|
|
148
|
-
|
|
171
|
+
tools: asObject(byTool),
|
|
172
|
+
actionable_tools: asObject(actionableByTool),
|
|
173
|
+
actionable_categories: asObject(actionableByCategory),
|
|
174
|
+
actionable_families: asObject(actionableByFamily),
|
|
175
|
+
command_exit_tools: asObject(commandExitByTool),
|
|
176
|
+
expected_categories: asObject(expectedByCategory),
|
|
177
|
+
categories: asObject(byCategory),
|
|
149
178
|
rows: recent,
|
|
150
179
|
}, null, 2));
|
|
151
180
|
process.exit(0);
|
|
152
181
|
}
|
|
153
182
|
|
|
154
|
-
console.log(`actionable failures: ${actionableRecent.length}/${actionableRows.length} shown`);
|
|
155
|
-
console.log(`command exits: ${commandExitRecent.length}/${commandExitRows.length} shown (retained)`);
|
|
183
|
+
console.log(`actionable failures: ${actionableRecent.length}/${actionableRows.length} shown (excludes command exits, absorbed preflights, session cancellations)`);
|
|
184
|
+
console.log(`command exits: ${commandExitRecent.length}/${commandExitRows.length} shown (retained) — ordinary non-zero test/command exits, not tool failures`);
|
|
185
|
+
console.log(`expected/absorbed: ${expectedRecent.length}/${expectedRows.length} shown (retained) — absorbed by design, not actionable`);
|
|
186
|
+
console.log(`session cancellations: ${cancellationRows.length} matched (not shown)`);
|
|
156
187
|
console.log(`rows: ${recent.length}/${rows.length} shown`);
|
|
157
188
|
if (sinceTs) console.log(`since: ${new Date(sinceTs).toISOString()}`);
|
|
158
189
|
const filterParts = [
|
|
159
190
|
toolFilter ? `tool=${toolFilter}` : '',
|
|
160
191
|
agentFilter ? `agent=${agentFilter}` : '',
|
|
161
192
|
categoryFilter ? `category=${categoryFilter}` : '',
|
|
193
|
+
onlyArg !== 'all' ? `only=${onlyArg}` : '',
|
|
162
194
|
].filter(Boolean);
|
|
163
195
|
if (filterParts.length) console.log(`filters: ${filterParts.join(', ')}`);
|
|
164
196
|
if (files.length > 0) console.log(`sources: ${files.filter(existsSync).join(', ') || '(none)'}`);
|
|
165
|
-
console.log(`actionable tools
|
|
166
|
-
console.log(`
|
|
167
|
-
console.log(`
|
|
197
|
+
console.log(`actionable tools (matched): ${asText(actionableByTool)}`);
|
|
198
|
+
console.log(`actionable categories (matched): ${asText(actionableByCategory)}`);
|
|
199
|
+
console.log(`actionable families (matched): ${asText(actionableByFamily)}`);
|
|
200
|
+
console.log(`patch failures (matched): ${patchRows.length} — ${asText(patchByCategory)}`);
|
|
201
|
+
console.log(`command-exit tools (matched): ${asText(commandExitByTool)}`);
|
|
202
|
+
console.log(`expected/absorbed categories (matched): ${asText(expectedByCategory)}`);
|
|
203
|
+
console.log(`shown categories: ${asText(byCategory)}`);
|
|
168
204
|
for (const row of recent) {
|
|
169
205
|
const tool = rowTool(row);
|
|
170
206
|
const category = rowCategory(row);
|
|
@@ -6,14 +6,13 @@ permission: read-write
|
|
|
6
6
|
Own the assigned implementation slice through staged delivery.
|
|
7
7
|
|
|
8
8
|
Break work into bounded, dependency-aware slices and execute them in sequence.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
rewriting adjacent systems.
|
|
9
|
+
Keep the smallest coherent change; control blast radius rather than rewriting
|
|
10
|
+
adjacent systems.
|
|
12
11
|
|
|
13
12
|
EDIT-FIRST DISCIPLINE. Patch incrementally and stop at the first explicit
|
|
14
13
|
boundary: unclear ownership, a missing dependency, or growing blast radius.
|
|
15
14
|
Do not cross that boundary without a new bounded assignment; report blocked
|
|
16
15
|
work with the relevant file:line.
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
Finish the slice and report the changed `file:line`; verification belongs to the Lead and Reviewer.
|
|
19
18
|
|
|
@@ -12,6 +12,5 @@ smallest coherent patch. No drive-by cleanup or scope expansion.
|
|
|
12
12
|
EDIT-FIRST DISCIPLINE. Patch promptly rather than repeating read-only turns;
|
|
13
13
|
stop and report blocked when the assigned scope cannot be completed.
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
test), then report the changed `file:line` and stop.
|
|
15
|
+
Patch and report the changed `file:line`; verification belongs to the Lead and Reviewer.
|
|
17
16
|
|
package/src/cli.mjs
CHANGED
|
@@ -10,6 +10,14 @@ import { stagedChildExitCode } from './runtime/shared/staged-child-result.mjs';
|
|
|
10
10
|
|
|
11
11
|
const argv = process.argv.slice(2);
|
|
12
12
|
|
|
13
|
+
// V8 compile cache: the whole runtime loads via dynamic import below, so
|
|
14
|
+
// enabling the cache here persists compiled bytecode across CLI launches
|
|
15
|
+
// (measurable cold-start parse savings). Best-effort on older Node builds.
|
|
16
|
+
try {
|
|
17
|
+
const { enableCompileCache } = await import('node:module');
|
|
18
|
+
enableCompileCache?.();
|
|
19
|
+
} catch { /* launch-speed optimization only */ }
|
|
20
|
+
|
|
13
21
|
// React/ink resolve their build flavor from NODE_ENV at require time. Unset
|
|
14
22
|
// NODE_ENV loads react-reconciler's DEVELOPMENT build, whose per-commit debug
|
|
15
23
|
// bookkeeping consumed ~16% of TUI frame CPU under transcript load (cpuprofile
|
|
@@ -23,7 +23,7 @@ CORE is durable standing knowledge that lands in one of three layers:
|
|
|
23
23
|
- **L3 — Current map:** one-line project-landscape summaries, live long-running
|
|
24
24
|
goals, environment anchors documented nowhere else.
|
|
25
25
|
|
|
26
|
-
Every entry must be ONE compact ENGLISH clause
|
|
26
|
+
Every entry must be ONE compact ENGLISH clause, regardless of
|
|
27
27
|
source language. Keep identifiers, paths, and exact phrases coined by the user
|
|
28
28
|
verbatim. CORE is not a log.
|
|
29
29
|
|
|
@@ -52,7 +52,7 @@ or inconclusive, keep the CORE entry.
|
|
|
52
52
|
|
|
53
53
|
- `keep` — durable and already one compact ENGLISH clause.
|
|
54
54
|
- `update` — durable but verbose, multi-sentence, or non-English → rewrite as
|
|
55
|
-
one compact
|
|
55
|
+
one compact ENGLISH clause; keep identifiers, paths, and exact
|
|
56
56
|
phrases coined by the user verbatim.
|
|
57
57
|
- `merge` — duplicates another entry → fold into the survivor (same project pool).
|
|
58
58
|
- `reclassify` — the entry is filed under the WRONG project pool. Its subject
|
|
@@ -86,7 +86,7 @@ or inconclusive, keep the CORE entry.
|
|
|
86
86
|
"needs confirmation" and only removed on an explicit APPLY CYCLE3 run.
|
|
87
87
|
|
|
88
88
|
A verbose, multi-sentence, or non-English durable entry is always `update`,
|
|
89
|
-
never `keep`; rewrite it as a
|
|
89
|
+
never `keep`; rewrite it as a compact English clause while keeping
|
|
90
90
|
identifiers, paths, and exact user-coined phrases verbatim.
|
|
91
91
|
Delete is the rarest verdict. Prefer `keep` for durable rules/preferences and
|
|
92
92
|
`update` for compression when the current behavior is still valid.
|
|
@@ -122,5 +122,5 @@ One line per entry id, any order:
|
|
|
122
122
|
<id>|delete|<reason>
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
`summary`
|
|
125
|
+
`summary` is one compact clause. No literal `|` or newline inside a field
|
|
126
126
|
(replace `|` with `/`). No prose, no fences. First character is a digit.
|
|
@@ -10,3 +10,6 @@
|
|
|
10
10
|
unrequested headings/tables, prose narration, raw logs/tool traces,
|
|
11
11
|
speculative next checks, restated briefs, articles, or politeness.
|
|
12
12
|
- Follow stricter role contracts and runtime wrap-up requirements.
|
|
13
|
+
- Your final message ends the task: emit the handoff text only when the work is
|
|
14
|
+
done. If a tool failed and stays unresolved, fix and re-run it, or say so
|
|
15
|
+
explicitly in the handoff.
|
|
@@ -13,12 +13,11 @@ prose, or preamble.
|
|
|
13
13
|
|
|
14
14
|
CORE is durable standing knowledge: rules, preferences, identity, goals, and
|
|
15
15
|
current system/structure descriptions—not a log. Each entry is one short clause
|
|
16
|
-
|
|
17
|
-
not durable. When unsure, keep.
|
|
16
|
+
without a hard character cap. Current rule/preference/live structure = durable;
|
|
17
|
+
a past event = not durable. When unsure, keep.
|
|
18
18
|
|
|
19
19
|
- `keep`: durable, already one short clause.
|
|
20
|
-
- `update`: durable but verbose/multi-sentence; compress to one
|
|
21
|
-
clause.
|
|
20
|
+
- `update`: durable but verbose/multi-sentence; compress to one short clause.
|
|
22
21
|
- `merge`: duplicate; fold into its survivor in the same project pool.
|
|
23
22
|
- `delete`: past event, not a current rule or structure.
|
|
24
23
|
|
|
@@ -29,7 +28,7 @@ Verbose durable is always `update`, never `keep`.
|
|
|
29
28
|
`<id>|merge|<target_id>|<source_ids_csv>`
|
|
30
29
|
`<id>|delete`
|
|
31
30
|
|
|
32
|
-
IDs match input rows; never invent them. An `update` summary is one
|
|
33
|
-
clause and its `element` is
|
|
31
|
+
IDs match input rows; never invent them. An `update` summary is one short
|
|
32
|
+
clause and its `element` is compact. A `merge` retains `target_id`, absorbs
|
|
34
33
|
sources, and stays within one `project_id`. Replace literal `|` with `/`;
|
|
35
34
|
fields contain no newlines. Emit a digit-starting verdict for every input row.
|
|
@@ -6,3 +6,5 @@
|
|
|
6
6
|
headings, labels, or routine lookup narration.
|
|
7
7
|
- Destructive/hard-to-reverse action needs explicit confirmation.
|
|
8
8
|
- Act proactively; ask only for decisions.
|
|
9
|
+
- Your final message ends the turn: answer only when the work is done. After a
|
|
10
|
+
failed tool call, fix and re-run it, or state plainly that it is unresolved.
|
|
@@ -6,41 +6,35 @@
|
|
|
6
6
|
`find`; verified root+wildcard→
|
|
7
7
|
`glob`; quoted/non-identifier literal or regex→`grep`; exact code
|
|
8
8
|
identifier/relation→`code_graph` before grep; known file/span→`read`
|
|
9
|
-
directly without `grep`; verified directory→`list`; edit
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
of tool
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
verified. Use `find` first for every genuinely guessed path/name fragment, in
|
|
26
|
-
the same turn as independent probes. Never find verified roots or use
|
|
27
|
-
`path:"."` with guessed `src/**`. On ENOENT, find the basename; never retry
|
|
28
|
-
the guess. Unscoped root grep/glob/list requires no find.
|
|
9
|
+
directly without `grep`; verified directory→`list`; known edit→
|
|
10
|
+
`apply_patch` directly, with no preparatory `read`;
|
|
11
|
+
program/state change→`shell`; web/current external info→`search`.
|
|
12
|
+
- Shortest total calls, maximum batching — every turn. Combine variants,
|
|
13
|
+
symbols, scopes, paths, and queries into one call; put all independent
|
|
14
|
+
calls (probes, reads, hypotheses, commands) in one message — concurrent
|
|
15
|
+
regardless of tool, shell included. Sequential singles only for a
|
|
16
|
+
genuinely dependent next step. Distinct facets, not alternative routes.
|
|
17
|
+
Only apply_patch executes in order.
|
|
18
|
+
- Batch compatible reads — same-file regions as real `{path,offset,limit}`
|
|
19
|
+
arrays covering the whole logical unit — in one `path[]` call, and graph
|
|
20
|
+
targets in arrays. Don't reread returned spans. Put all new edits in one
|
|
21
|
+
patch.
|
|
22
|
+
- Verified paths: project root, session cwd, user-provided, tool-returned.
|
|
23
|
+
`find` first for guessed path/name fragments (same turn as other probes);
|
|
24
|
+
on ENOENT, find the basename.
|
|
29
25
|
- At task start, batch all `explore` facets in one `query[]` call, maximum 8,
|
|
30
26
|
without rephrased duplicates. Retry `EXPLORATION_FAILED` once with changed
|
|
31
27
|
tokens.
|
|
32
|
-
- Stop when evidence covers the deliverable;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
otherwise diagnose the bottleneck and switch routes. Choose waiting
|
|
46
|
-
explicitly.
|
|
28
|
+
- Stop when evidence covers the deliverable; don't re-locate or re-verify a
|
|
29
|
+
sufficient anchor. A returned `path:line` freezes the location; inspecting
|
|
30
|
+
its content with read/code_graph is valid.
|
|
31
|
+
- A nonzero `content_with_context` result resolves that concept — act on it;
|
|
32
|
+
only zero/error results justify changed tokens or scope.
|
|
33
|
+
- `apply_patch` is the primary edit tool: send the patch as soon as the target
|
|
34
|
+
path and new content are known. `read` is for discovery or for recovery
|
|
35
|
+
after a patch failed on insufficient context.
|
|
36
|
+
- A shell placed after `apply_patch` in the same turn runs after the patch
|
|
37
|
+
lands — batch edits and their verification freely.
|
|
38
|
+
- A command promoted to background is a decision point: continue only if
|
|
39
|
+
observed progress fits the budget, otherwise switch routes. Waiting is an
|
|
40
|
+
explicit choice.
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
import { loadConfig } from '../config.mjs';
|
|
25
25
|
import { resolveRuntimeSpec } from '../config.mjs';
|
|
26
26
|
import { getHiddenAgent, resolveAgentSessionPermission } from '../internal-agents.mjs';
|
|
27
|
-
import { isKnownProvider } from '../../../../standalone/provider-admin.mjs';
|
|
28
27
|
import { prepareAgentSession } from './session-builder.mjs';
|
|
28
|
+
import { resolveMaintenanceRoute } from './maintenance-route.mjs';
|
|
29
29
|
import {
|
|
30
30
|
askSession,
|
|
31
31
|
updateSessionStatus,
|
|
@@ -43,6 +43,8 @@ import {
|
|
|
43
43
|
} from './agent-progress-watchdog.mjs';
|
|
44
44
|
import { resourceAdmission } from '../../../shared/resource-admission.mjs';
|
|
45
45
|
|
|
46
|
+
export { resolveMaintenanceRoute } from './maintenance-route.mjs';
|
|
47
|
+
|
|
46
48
|
// Cap agent role synthesis to ~3000 tokens (~12 KB at the 4 B/tok
|
|
47
49
|
// working average). Pool B explore/recall/search answers occasionally land
|
|
48
50
|
// 8-10k-token walls that then ride in the Lead context for the rest of the
|
|
@@ -153,56 +155,6 @@ export function resolveHiddenRoleSchemaAllowedTools(hidden) {
|
|
|
153
155
|
* maintenance route → Main. The cycle1/2/3 agents share the memory knob via
|
|
154
156
|
* their `maintKey: 'memory'` override. Scheduler and webhook are unchanged.
|
|
155
157
|
*/
|
|
156
|
-
const DEFAULT_AGENT_ROUTE_PROVIDER = 'anthropic-oauth';
|
|
157
|
-
|
|
158
|
-
function normalizeMaintenanceCandidate(candidate, config) {
|
|
159
|
-
if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) return candidate || null;
|
|
160
|
-
const configuredProvider = String(config?.defaultProvider || '').trim();
|
|
161
|
-
const fallbackProvider = isKnownProvider(configuredProvider)
|
|
162
|
-
? configuredProvider
|
|
163
|
-
: DEFAULT_AGENT_ROUTE_PROVIDER;
|
|
164
|
-
const provider = String(candidate.provider || fallbackProvider).trim();
|
|
165
|
-
const model = String(candidate.model || '').trim();
|
|
166
|
-
if (!provider || !model) return null;
|
|
167
|
-
return {
|
|
168
|
-
provider,
|
|
169
|
-
model,
|
|
170
|
-
effort: String(candidate.effort || '').trim() || undefined,
|
|
171
|
-
fast: candidate.fast === true,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export function resolveMaintenanceRoute({ preset, optsPreset, agent, config: cfgIn = null }) {
|
|
176
|
-
if (preset) return preset;
|
|
177
|
-
if (optsPreset) return optsPreset;
|
|
178
|
-
if (!agent) return null;
|
|
179
|
-
const hidden = getHiddenAgent(agent);
|
|
180
|
-
if (hidden) {
|
|
181
|
-
try {
|
|
182
|
-
const config = cfgIn || loadConfig({ secrets: false });
|
|
183
|
-
const maint = config?.maintenance || {};
|
|
184
|
-
const key = hidden.maintKey || hidden.slot;
|
|
185
|
-
const role = key === 'explore' ? 'explore' : (key === 'memory' ? 'maintainer' : '');
|
|
186
|
-
const workflowSlot = key === 'explore' ? 'explorer' : (key === 'memory' ? 'memory' : '');
|
|
187
|
-
if (!role) return maint[key] ?? null;
|
|
188
|
-
const candidates = [
|
|
189
|
-
role ? config?.agents?.[role] : null,
|
|
190
|
-
key === 'memory' ? config?.agents?.maintenance : null,
|
|
191
|
-
workflowSlot ? config?.workflowRoutes?.[workflowSlot] : null,
|
|
192
|
-
maint[key],
|
|
193
|
-
role ? config?.default : null,
|
|
194
|
-
];
|
|
195
|
-
for (const candidate of candidates) {
|
|
196
|
-
const route = normalizeMaintenanceCandidate(candidate, config);
|
|
197
|
-
if (route) return route;
|
|
198
|
-
}
|
|
199
|
-
return null;
|
|
200
|
-
} catch { return null; }
|
|
201
|
-
}
|
|
202
|
-
return null;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
158
|
// A maintenance slot value is a direct route when it carries provider+model.
|
|
207
159
|
function maintenanceRouteToPreset(routeOrName, agent) {
|
|
208
160
|
if (!routeOrName || typeof routeOrName !== 'object') return null;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { isKnownProvider } from '../../../../standalone/provider-admin.mjs';
|
|
2
|
+
import { loadConfig } from '../config.mjs';
|
|
3
|
+
import { getHiddenAgent } from '../internal-agents.mjs';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_AGENT_ROUTE_PROVIDER = 'anthropic-oauth';
|
|
6
|
+
|
|
7
|
+
function normalizeMaintenanceCandidate(candidate, config) {
|
|
8
|
+
if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) return candidate || null;
|
|
9
|
+
const configuredProvider = String(config?.defaultProvider || '').trim();
|
|
10
|
+
const fallbackProvider = isKnownProvider(configuredProvider)
|
|
11
|
+
? configuredProvider
|
|
12
|
+
: DEFAULT_AGENT_ROUTE_PROVIDER;
|
|
13
|
+
const provider = String(candidate.provider || fallbackProvider).trim();
|
|
14
|
+
const model = String(candidate.model || '').trim();
|
|
15
|
+
if (!provider || !model) return null;
|
|
16
|
+
return {
|
|
17
|
+
provider,
|
|
18
|
+
model,
|
|
19
|
+
effort: String(candidate.effort || '').trim() || undefined,
|
|
20
|
+
fast: candidate.fast === true,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the maintenance route for a hidden role without creating an agent
|
|
26
|
+
* session. Session-backed dispatch and tiny one-shot completions share this
|
|
27
|
+
* model-selection boundary.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveMaintenanceRoute({ preset, optsPreset, agent, config: cfgIn = null }) {
|
|
30
|
+
if (preset) return preset;
|
|
31
|
+
if (optsPreset) return optsPreset;
|
|
32
|
+
if (!agent) return null;
|
|
33
|
+
const hidden = getHiddenAgent(agent);
|
|
34
|
+
if (hidden) {
|
|
35
|
+
try {
|
|
36
|
+
const config = cfgIn || loadConfig({ secrets: false });
|
|
37
|
+
const maint = config?.maintenance || {};
|
|
38
|
+
const key = hidden.maintKey || hidden.slot;
|
|
39
|
+
const role = key === 'explore' ? 'explore' : (key === 'memory' ? 'maintainer' : '');
|
|
40
|
+
const workflowSlot = key === 'explore' ? 'explorer' : (key === 'memory' ? 'memory' : '');
|
|
41
|
+
if (!role) return maint[key] ?? null;
|
|
42
|
+
const candidates = [
|
|
43
|
+
role ? config?.agents?.[role] : null,
|
|
44
|
+
key === 'memory' ? config?.agents?.maintenance : null,
|
|
45
|
+
workflowSlot ? config?.workflowRoutes?.[workflowSlot] : null,
|
|
46
|
+
maint[key],
|
|
47
|
+
role ? config?.default : null,
|
|
48
|
+
];
|
|
49
|
+
for (const candidate of candidates) {
|
|
50
|
+
const route = normalizeMaintenanceCandidate(candidate, config);
|
|
51
|
+
if (route) return route;
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
@@ -91,8 +91,8 @@ export function prepareAgentSession({
|
|
|
91
91
|
// or fall through to the shared runaway guard (LEAD_MAX_LOOP_ITERATIONS).
|
|
92
92
|
const effectiveMaxLoopIterations = maxLoopIterations;
|
|
93
93
|
// Pass cwd through verbatim — null is the fixed agent sentinel meaning
|
|
94
|
-
// "no caller workspace context" (cycle1
|
|
95
|
-
// null → process.cwd() here would defeat cache-
|
|
94
|
+
// "no caller workspace context" (cycle1 agents, etc). Upgrading
|
|
95
|
+
// null → process.cwd() here would defeat cache-key fork suppression.
|
|
96
96
|
// Downstream collectors (collect.mjs) handle null as "no project cwd".
|
|
97
97
|
const effectiveCwd = cwd == null ? null : cwd;
|
|
98
98
|
const effectiveOwnerSessionId = ownerSessionId === undefined
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { loadConfig } from '../config.mjs';
|
|
2
|
+
import { getProvider, initProviders } from '../providers/registry.mjs';
|
|
3
|
+
import { resolveMaintenanceRoute } from './maintenance-route.mjs';
|
|
4
|
+
|
|
5
|
+
export const TITLE_SYSTEM_PROMPT = "Create a concise session title from the provided message or conversation. Output only one title on one line, at most 32 characters; no quotes, markdown, or trailing period.";
|
|
6
|
+
|
|
7
|
+
export function titleSystemPrompt(locale = '') {
|
|
8
|
+
const systemLocale = String(locale || '').trim();
|
|
9
|
+
return systemLocale
|
|
10
|
+
? `${TITLE_SYSTEM_PROMPT} System language/locale: ${systemLocale}. Prefer that language when the source is ambiguous; preserve a clearly different source language.`
|
|
11
|
+
: TITLE_SYSTEM_PROMPT;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function resultText(result) {
|
|
15
|
+
if (typeof result === 'string') return result;
|
|
16
|
+
if (typeof result?.content === 'string') return result.content;
|
|
17
|
+
if (Array.isArray(result?.content)) {
|
|
18
|
+
return result.content
|
|
19
|
+
.map((part) => part?.type === 'text' ? String(part.text || '') : '')
|
|
20
|
+
.filter(Boolean)
|
|
21
|
+
.join('\n');
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createTitleCompletion(deps = {}) {
|
|
27
|
+
const load = deps.loadConfig || loadConfig;
|
|
28
|
+
const resolveRoute = deps.resolveMaintenanceRoute || resolveMaintenanceRoute;
|
|
29
|
+
const initialize = deps.initProviders || initProviders;
|
|
30
|
+
const providerFor = deps.getProvider || getProvider;
|
|
31
|
+
|
|
32
|
+
return async function generateSessionTitle(source, options = {}) {
|
|
33
|
+
const text = String(source || '').trim();
|
|
34
|
+
if (!text) return '';
|
|
35
|
+
const signal = options.signal || null;
|
|
36
|
+
const config = load();
|
|
37
|
+
const route = resolveRoute({
|
|
38
|
+
agent: 'title-agent',
|
|
39
|
+
config,
|
|
40
|
+
});
|
|
41
|
+
if (!route || typeof route !== 'object') {
|
|
42
|
+
throw new Error('Session title maintenance route is unresolved.');
|
|
43
|
+
}
|
|
44
|
+
const providerName = String(route.provider || '').trim();
|
|
45
|
+
const model = String(route.model || '').trim();
|
|
46
|
+
if (!providerName || !model) {
|
|
47
|
+
throw new Error('Session title maintenance route requires provider and model.');
|
|
48
|
+
}
|
|
49
|
+
await initialize(config.providers || {}, { signal });
|
|
50
|
+
const provider = providerFor(providerName);
|
|
51
|
+
if (!provider || typeof provider.send !== 'function') {
|
|
52
|
+
throw new Error(`Session title provider is unavailable: ${providerName}`);
|
|
53
|
+
}
|
|
54
|
+
const response = await provider.send([
|
|
55
|
+
{ role: 'system', content: titleSystemPrompt(options.locale) },
|
|
56
|
+
{ role: 'user', content: text },
|
|
57
|
+
], model, undefined, {
|
|
58
|
+
signal,
|
|
59
|
+
effort: String(route.effort || '').trim() || 'low',
|
|
60
|
+
fast: route.fast === true,
|
|
61
|
+
maxOutputTokens: 128,
|
|
62
|
+
});
|
|
63
|
+
return resultText(response).trim();
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const generateSessionTitle = createTitleCompletion();
|