mixdog 0.9.1 → 0.9.2
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 +8 -1
- package/scripts/_bench-cwc.json +20 -0
- package/scripts/agent-loop-policy-test.mjs +37 -0
- package/scripts/agent-parallel-smoke.mjs +54 -10
- package/scripts/background-task-meta-smoke.mjs +1 -1
- package/scripts/bench-run.mjs +262 -0
- package/scripts/compact-smoke.mjs +12 -0
- package/scripts/compact-trigger-migration-smoke.mjs +67 -1
- package/scripts/ingest-pure-conversation-smoke.mjs +148 -0
- package/scripts/internal-comms-bench.mjs +727 -0
- package/scripts/internal-comms-smoke.mjs +75 -0
- package/scripts/lead-workflow-smoke.mjs +4 -4
- package/scripts/live-worker-smoke.mjs +9 -9
- package/scripts/output-style-bench.mjs +285 -0
- package/scripts/output-style-smoke.mjs +13 -10
- package/scripts/patch-replay.mjs +90 -0
- package/scripts/provider-stream-stall-test.mjs +276 -0
- package/scripts/provider-toolcall-test.mjs +599 -1
- package/scripts/routing-corpus.mjs +281 -0
- package/scripts/session-bench.mjs +1526 -0
- package/scripts/session-diag.mjs +595 -0
- package/scripts/task-bench.mjs +207 -0
- package/scripts/tool-failures.mjs +6 -6
- package/scripts/tool-smoke.mjs +306 -66
- package/scripts/toolcall-args-test.mjs +81 -0
- package/src/agents/debugger/AGENT.md +4 -4
- package/src/agents/heavy-worker/AGENT.md +4 -2
- package/src/agents/reviewer/AGENT.md +4 -4
- package/src/agents/worker/AGENT.md +4 -2
- package/src/app.mjs +10 -6
- package/src/defaults/{hidden-roles.json → agents.json} +7 -7
- package/src/examples/schedules/SCHEDULE.example.md +32 -0
- package/src/examples/webhooks/WEBHOOK.example.md +40 -0
- package/src/headless-role.mjs +14 -14
- package/src/help.mjs +1 -0
- package/src/lib/rules-builder.cjs +32 -54
- package/src/mixdog-session-runtime.mjs +710 -318
- package/src/output-styles/default.md +12 -7
- package/src/output-styles/minimal.md +25 -0
- package/src/output-styles/oneline.md +21 -0
- package/src/output-styles/simple.md +10 -9
- package/src/repl.mjs +12 -2
- package/src/rules/agent/00-common.md +7 -5
- package/src/rules/agent/30-explorer.md +7 -8
- package/src/rules/lead/01-general.md +3 -1
- package/src/rules/lead/lead-tool.md +7 -0
- package/src/rules/shared/01-tool.md +17 -12
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch.mjs +90 -32
- package/src/runtime/agent/orchestrator/agent-runtime/agent-loop-policy.mjs +32 -0
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +18 -6
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +23 -20
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +48 -14
- package/src/runtime/agent/orchestrator/agent-trace.mjs +87 -12
- package/src/runtime/agent/orchestrator/config.mjs +3 -0
- package/src/runtime/agent/orchestrator/context/collect.mjs +131 -67
- package/src/runtime/agent/orchestrator/{internal-roles.mjs → internal-agents.mjs} +72 -72
- package/src/runtime/agent/orchestrator/internal-tools.mjs +13 -26
- package/src/runtime/agent/orchestrator/mcp/client.mjs +94 -16
- package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-effort.mjs +188 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-leaked-toolcall.mjs +444 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +332 -57
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +59 -32
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +27 -20
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +184 -17
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +8 -1
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +18 -8
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +210 -21
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +78 -3
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +202 -98
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +183 -20
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +18 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +11 -5
- package/src/runtime/agent/orchestrator/providers/registry.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +15 -9
- package/src/runtime/agent/orchestrator/session/compact.mjs +560 -51
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +250 -3
- package/src/runtime/agent/orchestrator/session/loop.mjs +394 -132
- package/src/runtime/agent/orchestrator/session/manager.mjs +217 -170
- package/src/runtime/agent/orchestrator/session/store.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +61 -0
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +5 -0
- package/src/runtime/agent/orchestrator/stall-policy.mjs +63 -15
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +194 -24
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.test.mjs +143 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +34 -18
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +0 -0
- package/src/runtime/agent/orchestrator/tools/builtin/list-formatting.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +5 -4
- package/src/runtime/agent/orchestrator/tools/builtin/path-utils.mjs +15 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +9 -44
- package/src/runtime/agent/orchestrator/tools/builtin/read-constants.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +13 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +10 -17
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +18 -2
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +3 -2
- package/src/runtime/agent/orchestrator/tools/builtin/tool-output-limit.mjs +10 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +59 -1
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +5 -5
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4076 -3985
- package/src/runtime/agent/orchestrator/tools/patch.mjs +116 -2
- package/src/runtime/channels/backends/discord.mjs +99 -9
- package/src/runtime/channels/backends/telegram.mjs +501 -0
- package/src/runtime/channels/index.mjs +441 -1224
- package/src/runtime/channels/lib/config.mjs +54 -2
- package/src/runtime/channels/lib/format.mjs +4 -2
- package/src/runtime/channels/lib/output-forwarder.mjs +80 -67
- package/src/runtime/channels/lib/runtime-paths.mjs +29 -0
- package/src/runtime/channels/lib/scheduler.mjs +1 -1
- package/src/runtime/channels/lib/telegram-format.mjs +283 -0
- package/src/runtime/channels/lib/tool-format.mjs +1 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +19 -1
- package/src/runtime/channels/lib/webhook.mjs +59 -31
- package/src/runtime/channels/tool-defs.mjs +1 -1
- package/src/runtime/memory/index.mjs +184 -19
- package/src/runtime/memory/lib/agent-ipc.mjs +2 -2
- package/src/runtime/memory/lib/core-memory-store.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle1.mjs +1 -1
- package/src/runtime/memory/lib/memory-cycle2.mjs +9 -6
- package/src/runtime/memory/lib/memory-cycle3.mjs +1 -1
- package/src/runtime/memory/lib/memory.mjs +101 -4
- package/src/runtime/memory/lib/pg/adapter.mjs +139 -15
- package/src/runtime/memory/lib/session-ingest.mjs +107 -0
- package/src/runtime/memory/lib/trace-store.mjs +69 -22
- package/src/runtime/memory/tool-defs.mjs +6 -3
- package/src/runtime/shared/channel-notification-routing.mjs +12 -0
- package/src/runtime/shared/channel-notification-routing.test.mjs +45 -0
- package/src/runtime/shared/config.mjs +9 -0
- package/src/runtime/shared/llm/http-agent.mjs +12 -5
- package/src/runtime/shared/schedules-store.mjs +21 -19
- package/src/runtime/shared/tool-surface.mjs +98 -13
- package/src/runtime/shared/transcript-writer.mjs +129 -0
- package/src/runtime/shared/update-checker.mjs +214 -0
- package/src/standalone/agent-tool.mjs +255 -109
- package/src/standalone/channel-admin.mjs +133 -40
- package/src/standalone/channel-worker.mjs +8 -291
- package/src/standalone/explore-tool.mjs +2 -2
- package/src/standalone/memory-runtime-proxy.mjs +3 -1
- package/src/standalone/provider-admin.mjs +11 -0
- package/src/standalone/usage-dashboard.mjs +1 -1
- package/src/tui/App.jsx +2096 -732
- package/src/tui/components/ConfirmBar.jsx +47 -0
- package/src/tui/components/ContextPanel.jsx +5 -3
- package/src/tui/components/ItemRightHintOverprint.jsx +54 -0
- package/src/tui/components/Markdown.jsx +22 -98
- package/src/tui/components/Message.jsx +14 -35
- package/src/tui/components/Picker.jsx +87 -12
- package/src/tui/components/PromptInput.jsx +83 -7
- package/src/tui/components/QueuedCommands.jsx +1 -1
- package/src/tui/components/SlashCommandPalette.jsx +8 -5
- package/src/tui/components/Spinner.jsx +7 -7
- package/src/tui/components/StatusLine.jsx +40 -21
- package/src/tui/components/TextEntryPanel.jsx +51 -7
- package/src/tui/components/ToolExecution.jsx +170 -98
- package/src/tui/components/TurnDone.jsx +4 -4
- package/src/tui/components/UsagePanel.jsx +1 -1
- package/src/tui/components/tool-output-format.mjs +159 -21
- package/src/tui/components/tool-output-format.test.mjs +87 -0
- package/src/tui/display-width.mjs +69 -0
- package/src/tui/display-width.test.mjs +35 -0
- package/src/tui/dist/index.mjs +6965 -2391
- package/src/tui/engine.mjs +287 -126
- package/src/tui/index.jsx +117 -7
- package/src/tui/keyboard-protocol.mjs +42 -0
- package/src/tui/lib/voice-recorder.mjs +453 -0
- package/src/tui/markdown/format-token.mjs +129 -76
- package/src/tui/markdown/format-token.test.mjs +61 -19
- package/src/tui/markdown/measure-rendered-rows.mjs +85 -0
- package/src/tui/markdown/render-ansi.test.mjs +1 -1
- package/src/tui/markdown/streaming-markdown.mjs +167 -0
- package/src/tui/markdown/streaming-markdown.test.mjs +70 -0
- package/src/tui/markdown/table-layout.mjs +9 -9
- package/src/tui/paste-attachments.mjs +0 -11
- package/src/tui/prompt-history-store.mjs +129 -0
- package/src/tui/prompt-history-store.test.mjs +52 -0
- package/src/tui/statusline-ansi-bridge.test.mjs +3 -3
- package/src/tui/theme.mjs +41 -657
- package/src/tui/themes/base.mjs +86 -0
- package/src/tui/themes/basic.mjs +85 -0
- package/src/tui/themes/catppuccin.mjs +72 -0
- package/src/tui/themes/dracula.mjs +70 -0
- package/src/tui/themes/everforest.mjs +71 -0
- package/src/tui/themes/gruvbox.mjs +71 -0
- package/src/tui/themes/index.mjs +71 -0
- package/src/tui/themes/indigo.mjs +78 -0
- package/src/tui/themes/kanagawa.mjs +80 -0
- package/src/tui/themes/light.mjs +81 -0
- package/src/tui/themes/nord.mjs +72 -0
- package/src/tui/themes/onedark.mjs +16 -0
- package/src/tui/themes/rosepine.mjs +70 -0
- package/src/tui/themes/teal.mjs +81 -0
- package/src/tui/themes/tokyonight.mjs +79 -0
- package/src/tui/themes/utils.mjs +106 -0
- package/src/tui/themes/warm.mjs +79 -0
- package/src/tui/transcript-tool-failures.mjs +13 -2
- package/src/ui/markdown.mjs +1 -1
- package/src/ui/model-display.mjs +2 -2
- package/src/ui/statusline.mjs +26 -27
- package/src/vendor/statusline/bin/statusline-route.mjs +5 -12
- package/src/vendor/statusline/src/gateway/claude-current.mjs +3 -3
- package/src/vendor/statusline/src/gateway/route-meta.mjs +30 -16
- package/src/workflows/default/WORKFLOW.md +39 -12
- package/src/workflows/sequential/WORKFLOW.md +46 -0
- package/src/workflows/solo/WORKFLOW.md +7 -0
- package/vendor/ink/build/display-width.js +62 -0
- package/vendor/ink/build/ink.js +100 -12
- package/vendor/ink/build/measure-text.js +4 -1
- package/vendor/ink/build/output.js +115 -9
- package/vendor/ink/build/render-node-to-output.js +4 -1
- package/vendor/ink/build/render.js +4 -0
- package/src/output-styles/extreme-simple.md +0 -20
- package/src/rules/lead/04-workflow.md +0 -51
- package/src/workflows/default/workflow.json +0 -13
- package/src/workflows/solo/workflow.json +0 -7
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* BP_1 system#1 (1h) — shared tool policy + compact skill manifest
|
|
11
11
|
* BP_2 system#2 (1h) — role/system rules (Lead / agent / hidden role)
|
|
12
12
|
* BP_3 system#3 (1h) — stable memory/meta marker (sessionMarker system block; tier3)
|
|
13
|
-
* BP_4 messages (
|
|
13
|
+
* BP_4 messages (5m) — sliding tool_result / prior user-text tail
|
|
14
14
|
*
|
|
15
15
|
* Tool schemas still sit before system in the provider prompt prefix. We do
|
|
16
16
|
* not spend a separate cache_control slot on tools; the first system BP covers
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
import { createHash } from 'crypto';
|
|
38
|
-
import {
|
|
38
|
+
import { getHiddenAgent } from '../internal-agents.mjs';
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* One-shot, LLM-only maintenance hidden roles (cycle1/cycle2/cycle3-agent):
|
|
@@ -49,8 +49,8 @@ import { getHiddenRole } from '../internal-roles.mjs';
|
|
|
49
49
|
* 'unified' and therefore excluded — they run a tool loop whose tail caches
|
|
50
50
|
* legitimately reuse across iterations.
|
|
51
51
|
*/
|
|
52
|
-
function
|
|
53
|
-
const hidden =
|
|
52
|
+
function isOneShotMaintenanceAgent(agent) {
|
|
53
|
+
const hidden = getHiddenAgent(agent);
|
|
54
54
|
return Boolean(
|
|
55
55
|
hidden
|
|
56
56
|
&& hidden.kind === 'maintenance'
|
|
@@ -66,12 +66,15 @@ function isOneShotMaintenanceRole(role) {
|
|
|
66
66
|
* '5m' → ephemeral 5m TTL (1.25x write premium, 0.1x read)
|
|
67
67
|
* 'none' → no breakpoint written on this layer
|
|
68
68
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
* session
|
|
73
|
-
*
|
|
74
|
-
*
|
|
69
|
+
* BP1~3 stay at 1h: the system/role/tier3 prefix is shared across sessions
|
|
70
|
+
* (pool-stable), so the 2x write premium is amortized cross-session and the
|
|
71
|
+
* warm window survives per-session gaps. The volatile message tail (BP4) is
|
|
72
|
+
* per-session and trace data (2026-06) shows request gaps are p99 ≈ 4.5min —
|
|
73
|
+
* 5m+ gaps mean a cold tail anyway, and the smart-compact path rebuilds the
|
|
74
|
+
* history at that boundary. So every session's tail uses the cheaper 5m TTL
|
|
75
|
+
* (1.25x write vs 2x), aligned with the 5m terminal-reap window for agents.
|
|
76
|
+
* (Tail TTL only affects explicit-breakpoint providers — Anthropic; no-op
|
|
77
|
+
* elsewhere.)
|
|
75
78
|
*
|
|
76
79
|
* Exception: one-shot LLM-only maintenance roles are asked once on a fresh
|
|
77
80
|
* session and closed, so their volatile per-call message tail is never read
|
|
@@ -81,15 +84,15 @@ function isOneShotMaintenanceRole(role) {
|
|
|
81
84
|
* the 1h TTL expiry (writes every run, 0 reads). All layers go 'none' for
|
|
82
85
|
* these roles — single-iteration calls pay the write premium with no reuse.
|
|
83
86
|
*/
|
|
84
|
-
export function resolveCacheStrategy(
|
|
85
|
-
if (
|
|
87
|
+
export function resolveCacheStrategy(agent) {
|
|
88
|
+
if (isOneShotMaintenanceAgent(agent)) {
|
|
86
89
|
return { tools: 'none', system: 'none', tier3: 'none', messages: 'none' };
|
|
87
90
|
}
|
|
88
|
-
if (
|
|
91
|
+
if (getHiddenAgent(agent)) {
|
|
89
92
|
return { tools: 'none', system: '1h', tier3: '1h', messages: '5m' };
|
|
90
93
|
}
|
|
91
|
-
//
|
|
92
|
-
return { tools: 'none', system: '1h', tier3: '1h', messages: '
|
|
94
|
+
// Lead + public agents: per-session volatile tail -> 5m (see doc above).
|
|
95
|
+
return { tools: 'none', system: '1h', tier3: '1h', messages: '5m' };
|
|
93
96
|
}
|
|
94
97
|
|
|
95
98
|
/**
|
|
@@ -97,7 +100,7 @@ export function resolveCacheStrategy(role) {
|
|
|
97
100
|
*
|
|
98
101
|
* @param {string} provider
|
|
99
102
|
* @param {string} [sessionId]
|
|
100
|
-
* @param {string} [
|
|
103
|
+
* @param {string} [agent]
|
|
101
104
|
* @returns {object} partial sendOpts — spread into provider.send call
|
|
102
105
|
*/
|
|
103
106
|
|
|
@@ -356,8 +359,8 @@ export function resolveProviderPromptCacheLane(provider, opts = {}, config = {})
|
|
|
356
359
|
};
|
|
357
360
|
}
|
|
358
361
|
|
|
359
|
-
export function buildProviderCacheOpts(provider, sessionId,
|
|
360
|
-
const ttls = resolveCacheStrategy(
|
|
362
|
+
export function buildProviderCacheOpts(provider, sessionId, agent) {
|
|
363
|
+
const ttls = resolveCacheStrategy(agent);
|
|
361
364
|
const capability = cacheCapabilityForProvider(provider);
|
|
362
365
|
if (capability === 'explicit-breakpoint') {
|
|
363
366
|
// 2026-03-06 Anthropic dropped default TTL 1h→5m. We send
|
|
@@ -400,8 +403,8 @@ export function computePrefixContent(systemPrompt, tools) {
|
|
|
400
403
|
/**
|
|
401
404
|
* Longest-lived layer TTL (seconds) for registry expiry tracking.
|
|
402
405
|
*/
|
|
403
|
-
export function ttlSecondsForCache(
|
|
404
|
-
const ttls = resolveCacheStrategy(
|
|
406
|
+
export function ttlSecondsForCache(agent) {
|
|
407
|
+
const ttls = resolveCacheStrategy(agent);
|
|
405
408
|
if (
|
|
406
409
|
ttls.tools === 'none'
|
|
407
410
|
&& ttls.system === 'none'
|
|
@@ -19,12 +19,44 @@
|
|
|
19
19
|
|
|
20
20
|
import { createSession } from '../session/manager.mjs';
|
|
21
21
|
import { traceAgentPreset } from '../agent-trace.mjs';
|
|
22
|
-
import { resolveAgentSessionPermission } from '../internal-
|
|
22
|
+
import { resolveAgentSessionPermission } from '../internal-agents.mjs';
|
|
23
23
|
import { loadConfig } from '../config.mjs';
|
|
24
|
+
import { AGENT_OWNER } from '../agent-owner.mjs';
|
|
25
|
+
|
|
26
|
+
import {
|
|
27
|
+
COMPACT_TYPE_RECALL_FASTTRACK,
|
|
28
|
+
COMPACT_TYPE_SEMANTIC,
|
|
29
|
+
normalizeCompactType,
|
|
30
|
+
} from '../session/compact.mjs';
|
|
31
|
+
|
|
32
|
+
function memoryModuleEnabled(config) {
|
|
33
|
+
const entry = config?.modules?.memory;
|
|
34
|
+
if (entry && typeof entry === 'object' && entry.enabled === false) return false;
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function normalizeAgentCompactionConfig(value = {}, { memoryEnabled = true } = {}) {
|
|
39
|
+
const raw = value && typeof value === 'object' ? value : {};
|
|
40
|
+
let compactType = normalizeCompactType(
|
|
41
|
+
raw.compactType ?? raw.compact_type ?? raw.type,
|
|
42
|
+
COMPACT_TYPE_SEMANTIC,
|
|
43
|
+
);
|
|
44
|
+
// recall-fasttrack depends on memory ingest/recall; fall back to semantic when
|
|
45
|
+
// the memory module is disabled (same rule as Lead session runtime).
|
|
46
|
+
if (compactType === COMPACT_TYPE_RECALL_FASTTRACK && memoryEnabled === false) {
|
|
47
|
+
compactType = COMPACT_TYPE_SEMANTIC;
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
...raw,
|
|
51
|
+
auto: raw.auto !== false && raw.enabled !== false,
|
|
52
|
+
type: compactType,
|
|
53
|
+
compactType,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
24
56
|
|
|
25
57
|
/**
|
|
26
58
|
* @param {object} opts
|
|
27
|
-
* @param {string} opts.
|
|
59
|
+
* @param {string} opts.agent — canonical agent name ('worker', 'explorer', ...)
|
|
28
60
|
* @param {string} opts.presetName — resolved preset identifier
|
|
29
61
|
* @param {object} opts.preset — resolved preset object from agent-config
|
|
30
62
|
* @param {object} opts.runtimeSpec — resolveRuntimeSpec output; must carry .scopeKey / .lane
|
|
@@ -32,7 +64,7 @@ import { loadConfig } from '../config.mjs';
|
|
|
32
64
|
* @param {string|null} [opts.cwd] — absolute working dir; null is the fixed agent sentinel meaning "no caller workspace context"
|
|
33
65
|
* @param {string} [opts.owner='agent']
|
|
34
66
|
* @param {string} [opts.permissionMode] — permissionMode forwarded from the MCP payload ('bypassPermissions', 'acceptEdits', 'plan', 'dontAsk', 'default')
|
|
35
|
-
* @param {string[]} [opts.schemaAllowedTools] — schema-level allowlist from a hidden-
|
|
67
|
+
* @param {string[]} [opts.schemaAllowedTools] — schema-level allowlist from a hidden-agent toolSchemaProfile
|
|
36
68
|
* @param {string} [opts.sourceType]
|
|
37
69
|
* @param {string} [opts.sourceName]
|
|
38
70
|
* @param {string} [opts.taskType]
|
|
@@ -42,7 +74,7 @@ import { loadConfig } from '../config.mjs';
|
|
|
42
74
|
* @returns {{ session: object, effectiveCwd: string|null }}
|
|
43
75
|
*/
|
|
44
76
|
export function prepareAgentSession({
|
|
45
|
-
|
|
77
|
+
agent,
|
|
46
78
|
presetName,
|
|
47
79
|
preset,
|
|
48
80
|
runtimeSpec,
|
|
@@ -61,7 +93,10 @@ export function prepareAgentSession({
|
|
|
61
93
|
cacheKeyOverride,
|
|
62
94
|
schemaAllowedTools,
|
|
63
95
|
}) {
|
|
64
|
-
const effectivePermission = resolveAgentSessionPermission(
|
|
96
|
+
const effectivePermission = resolveAgentSessionPermission(agent, permission);
|
|
97
|
+
// No per-agent loop caps: sessions either pin maxLoopIterations explicitly
|
|
98
|
+
// or fall through to the shared runaway guard (LEAD_MAX_LOOP_ITERATIONS).
|
|
99
|
+
const effectiveMaxLoopIterations = maxLoopIterations;
|
|
65
100
|
// Pass cwd through verbatim — null is the fixed agent sentinel meaning
|
|
66
101
|
// "no caller workspace context" (cycle1-agent shards, etc). Upgrading
|
|
67
102
|
// null → process.cwd() here would defeat cache-shard fork suppression.
|
|
@@ -73,12 +108,11 @@ export function prepareAgentSession({
|
|
|
73
108
|
let compaction = null;
|
|
74
109
|
try {
|
|
75
110
|
const cfg = loadConfig({ secrets: false });
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
compaction = { ...base, type: '1', compactType: '1' };
|
|
111
|
+
if (cfg?.compaction && typeof cfg.compaction === 'object') {
|
|
112
|
+
compaction = normalizeAgentCompactionConfig(cfg.compaction, {
|
|
113
|
+
memoryEnabled: memoryModuleEnabled(cfg),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
82
116
|
} catch { /* config is best-effort for agent compaction policy */ }
|
|
83
117
|
const sessionOpts = {
|
|
84
118
|
preset,
|
|
@@ -86,9 +120,9 @@ export function prepareAgentSession({
|
|
|
86
120
|
scopeKey: runtimeSpec.scopeKey,
|
|
87
121
|
lane: runtimeSpec.lane,
|
|
88
122
|
cwd: effectiveCwd,
|
|
89
|
-
|
|
123
|
+
agent: agent || undefined,
|
|
90
124
|
taskType: taskType || undefined,
|
|
91
|
-
maxLoopIterations: Number.isFinite(
|
|
125
|
+
maxLoopIterations: Number.isFinite(effectiveMaxLoopIterations) ? effectiveMaxLoopIterations : undefined,
|
|
92
126
|
sourceType: sourceType || undefined,
|
|
93
127
|
sourceName: sourceName || undefined,
|
|
94
128
|
ownerSessionId: effectiveOwnerSessionId || null,
|
|
@@ -106,7 +140,7 @@ export function prepareAgentSession({
|
|
|
106
140
|
try {
|
|
107
141
|
traceAgentPreset({
|
|
108
142
|
sessionId: session.id,
|
|
109
|
-
|
|
143
|
+
agent: agent || null,
|
|
110
144
|
presetName: presetName || null,
|
|
111
145
|
// runtimeSpec carries scopeKey/lane but resolveRuntimeSpec does not
|
|
112
146
|
// populate model/provider — fall back to preset fields.
|
|
@@ -29,7 +29,16 @@ let _toolFailureTimer = null;
|
|
|
29
29
|
let _toolFailureFlushInFlight = false;
|
|
30
30
|
const _LOCAL_TRACE_FLUSH_LINES = 100;
|
|
31
31
|
const _LOCAL_TRACE_FLUSH_MS = 1000;
|
|
32
|
-
const _LOCAL_TRACE_MAX_BYTES = 10 * 1024 * 1024; // 10 MB — rotate to .1 above this.
|
|
32
|
+
const _LOCAL_TRACE_MAX_BYTES = 10 * 1024 * 1024; // 10 MB — rotate to .1/.2/.3 above this.
|
|
33
|
+
// Rotation generations kept on disk (.1 newest … .N oldest). A single .1
|
|
34
|
+
// generation proved too short a window — bench rounds (session-bench /
|
|
35
|
+
// task-bench re-scoring) were losing their raw turn rows to a second rotation
|
|
36
|
+
// within hours. 3 generations ≈ 40 MB worst case per log. Env-overridable via
|
|
37
|
+
// MIXDOG_AGENT_TRACE_ROTATE_KEEP (positive integer).
|
|
38
|
+
const _LOCAL_TRACE_ROTATE_KEEP = (() => {
|
|
39
|
+
const v = parseInt(process.env.MIXDOG_AGENT_TRACE_ROTATE_KEEP, 10);
|
|
40
|
+
return Number.isFinite(v) && v > 0 ? v : 3;
|
|
41
|
+
})();
|
|
33
42
|
const _TOOL_FAILURE_FLUSH_LINES = 50;
|
|
34
43
|
const _TOOL_FAILURE_FLUSH_MS = 1000;
|
|
35
44
|
const MIXDOG_SLOW_TOOL_TRACE_MS = (() => {
|
|
@@ -59,7 +68,15 @@ function _rotateLocalTraceIfNeeded(path) {
|
|
|
59
68
|
try {
|
|
60
69
|
const stat = statSync(path);
|
|
61
70
|
if (stat && stat.size > _LOCAL_TRACE_MAX_BYTES) {
|
|
62
|
-
try {
|
|
71
|
+
try {
|
|
72
|
+
// Shift generations oldest-first: .2 → .3, .1 → .2, live → .1.
|
|
73
|
+
// The oldest (.KEEP) is overwritten by the rename below it.
|
|
74
|
+
for (let gen = _LOCAL_TRACE_ROTATE_KEEP - 1; gen >= 1; gen -= 1) {
|
|
75
|
+
const src = `${path}.${gen}`;
|
|
76
|
+
if (existsSync(src)) renameSync(src, `${path}.${gen + 1}`);
|
|
77
|
+
}
|
|
78
|
+
renameSync(path, `${path}.1`);
|
|
79
|
+
}
|
|
63
80
|
catch (err) {
|
|
64
81
|
warnAgentOnce('agent-trace:local-rotate', `[agent-trace] local rotate failed (${err?.message})`);
|
|
65
82
|
}
|
|
@@ -364,6 +381,7 @@ function traceAgentCompact({
|
|
|
364
381
|
iteration,
|
|
365
382
|
stage,
|
|
366
383
|
trigger,
|
|
384
|
+
compact_type,
|
|
367
385
|
prune_count,
|
|
368
386
|
compact_changed,
|
|
369
387
|
input_prefix_hash,
|
|
@@ -373,20 +391,26 @@ function traceAgentCompact({
|
|
|
373
391
|
after_bytes,
|
|
374
392
|
context_window,
|
|
375
393
|
budget_tokens,
|
|
394
|
+
boundary_tokens,
|
|
395
|
+
target_budget_tokens,
|
|
376
396
|
reserve_tokens,
|
|
397
|
+
pressure_tokens,
|
|
398
|
+
trigger_tokens,
|
|
377
399
|
message_tokens_est,
|
|
400
|
+
duration_ms,
|
|
378
401
|
provider,
|
|
379
402
|
model,
|
|
380
403
|
error,
|
|
381
404
|
error_code,
|
|
405
|
+
details,
|
|
382
406
|
}) {
|
|
383
|
-
if (process.env.MIXDOG_AGENT_TRACE_VERBOSE !== '1') return;
|
|
384
407
|
appendAgentTrace({
|
|
385
408
|
sessionId,
|
|
386
409
|
iteration,
|
|
387
410
|
kind: 'compact_meta',
|
|
388
411
|
stage: stage || null,
|
|
389
412
|
trigger: trigger || null,
|
|
413
|
+
compact_type: compact_type || null,
|
|
390
414
|
prune_count: prune_count ?? 0,
|
|
391
415
|
compact_changed: !!compact_changed,
|
|
392
416
|
input_prefix_hash: input_prefix_hash || null,
|
|
@@ -396,12 +420,18 @@ function traceAgentCompact({
|
|
|
396
420
|
after_bytes: after_bytes ?? null,
|
|
397
421
|
context_window: context_window ?? null,
|
|
398
422
|
budget_tokens: budget_tokens ?? null,
|
|
423
|
+
boundary_tokens: boundary_tokens ?? null,
|
|
424
|
+
target_budget_tokens: target_budget_tokens ?? null,
|
|
399
425
|
reserve_tokens: reserve_tokens ?? null,
|
|
426
|
+
pressure_tokens: pressure_tokens ?? null,
|
|
427
|
+
trigger_tokens: trigger_tokens ?? null,
|
|
400
428
|
message_tokens_est: message_tokens_est ?? null,
|
|
429
|
+
duration_ms: duration_ms ?? null,
|
|
401
430
|
provider: provider || null,
|
|
402
431
|
model: model || null,
|
|
403
432
|
error: error || null,
|
|
404
433
|
error_code: error_code || null,
|
|
434
|
+
details: details && typeof details === 'object' ? details : null,
|
|
405
435
|
});
|
|
406
436
|
}
|
|
407
437
|
|
|
@@ -488,6 +518,22 @@ function summarizeToolArgs(toolName, args) {
|
|
|
488
518
|
return Object.keys(out).length ? out : null;
|
|
489
519
|
}
|
|
490
520
|
|
|
521
|
+
function stableTraceStringify(value) {
|
|
522
|
+
if (value === null || value === undefined) return JSON.stringify(value);
|
|
523
|
+
if (typeof value !== 'object') return JSON.stringify(value);
|
|
524
|
+
if (Array.isArray(value)) return '[' + value.map(stableTraceStringify).join(',') + ']';
|
|
525
|
+
const keys = Object.keys(value).sort();
|
|
526
|
+
return '{' + keys.map((k) => `${JSON.stringify(k)}:${stableTraceStringify(value[k])}`).join(',') + '}';
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function hashTraceValue(value) {
|
|
530
|
+
try {
|
|
531
|
+
return createHash('sha256').update(stableTraceStringify(value)).digest('hex').slice(0, 16);
|
|
532
|
+
} catch {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
491
537
|
function _resolveToolFailurePath() {
|
|
492
538
|
if (process.env.MIXDOG_TOOL_FAILURE_LOG_DISABLE === '1') return null;
|
|
493
539
|
if (_toolFailurePath) return _toolFailurePath;
|
|
@@ -601,7 +647,7 @@ function classifyToolFailure(resultText, toolName) {
|
|
|
601
647
|
return 'runtime/failure';
|
|
602
648
|
}
|
|
603
649
|
|
|
604
|
-
function traceAgentToolFailure({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs,
|
|
650
|
+
function traceAgentToolFailure({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs, agent, model, cwd, resultText, resultKind = 'error' }) {
|
|
605
651
|
if (process.env.MIXDOG_AGENT_TRACE_DISABLE === '1') return;
|
|
606
652
|
if (!_resolveToolFailurePath()) return;
|
|
607
653
|
try {
|
|
@@ -614,7 +660,7 @@ function traceAgentToolFailure({ sessionId, iteration, toolName, toolKind, toolM
|
|
|
614
660
|
tool_kind: toolKind || null,
|
|
615
661
|
result_kind: resultKind || 'error',
|
|
616
662
|
category: classifyToolFailure(cleanText, toolName),
|
|
617
|
-
|
|
663
|
+
agent: agent || null,
|
|
618
664
|
model: model || null,
|
|
619
665
|
cwd: cwd || null,
|
|
620
666
|
tool_ms: Number.isFinite(Number(toolMs)) ? Number(toolMs) : null,
|
|
@@ -630,12 +676,13 @@ function traceAgentToolFailure({ sessionId, iteration, toolName, toolKind, toolM
|
|
|
630
676
|
}
|
|
631
677
|
}
|
|
632
678
|
|
|
633
|
-
function traceAgentTool({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs,
|
|
679
|
+
function traceAgentTool({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs, agent, resultKind, model, resultText, cwd }) {
|
|
634
680
|
const nextCallCount = countJsonNextCalls(resultText);
|
|
635
681
|
const resultBytesEst = typeof resultText === 'string' ? Buffer.byteLength(resultText, 'utf8') : 0;
|
|
636
682
|
const resultLinesEst = typeof resultText === 'string' && resultText.length > 0 ? resultText.split('\n').length : 0;
|
|
637
683
|
const numericToolMs = Number(toolMs);
|
|
638
684
|
const summarizedArgs = summarizeToolArgs(toolName, toolArgs);
|
|
685
|
+
const toolArgsHash = summarizedArgs ? hashTraceValue(summarizedArgs) : null;
|
|
639
686
|
// Flat shape — fields named exactly as the agent_calls PG columns so
|
|
640
687
|
// insertAgentCalls can pick them up by direct property access without
|
|
641
688
|
// a payload-unwrap step. result_kind has no column and rides as plain
|
|
@@ -644,12 +691,14 @@ function traceAgentTool({ sessionId, iteration, toolName, toolKind, toolMs, tool
|
|
|
644
691
|
sessionId,
|
|
645
692
|
iteration,
|
|
646
693
|
kind: 'tool',
|
|
647
|
-
|
|
694
|
+
agent: agent || null,
|
|
648
695
|
model: model || null,
|
|
649
696
|
tool_name: toolName,
|
|
650
697
|
tool_kind: toolKind,
|
|
651
698
|
tool_ms: toolMs,
|
|
652
699
|
tool_args: summarizedArgs,
|
|
700
|
+
tool_args_hash: toolArgsHash,
|
|
701
|
+
tool_args_summary: summarizedArgs,
|
|
653
702
|
result_kind: resultKind || null,
|
|
654
703
|
result_has_next_call: nextCallCount > 0,
|
|
655
704
|
result_next_call_count: nextCallCount,
|
|
@@ -665,7 +714,7 @@ function traceAgentTool({ sessionId, iteration, toolName, toolKind, toolMs, tool
|
|
|
665
714
|
sessionId,
|
|
666
715
|
iteration,
|
|
667
716
|
kind: 'tool_slow',
|
|
668
|
-
|
|
717
|
+
agent: agent || null,
|
|
669
718
|
model: model || null,
|
|
670
719
|
tool_name: toolName,
|
|
671
720
|
tool_kind: toolKind,
|
|
@@ -674,6 +723,8 @@ function traceAgentTool({ sessionId, iteration, toolName, toolKind, toolMs, tool
|
|
|
674
723
|
threshold_ms: MIXDOG_SLOW_TOOL_TRACE_MS,
|
|
675
724
|
result_kind: resultKind || null,
|
|
676
725
|
tool_args: summarizedArgs,
|
|
726
|
+
tool_args_hash: toolArgsHash,
|
|
727
|
+
tool_args_summary: summarizedArgs,
|
|
677
728
|
result_has_next_call: nextCallCount > 0,
|
|
678
729
|
result_next_call_count: nextCallCount,
|
|
679
730
|
result_bytes_est: resultBytesEst,
|
|
@@ -683,7 +734,7 @@ function traceAgentTool({ sessionId, iteration, toolName, toolKind, toolMs, tool
|
|
|
683
734
|
});
|
|
684
735
|
}
|
|
685
736
|
if (resultKind === 'error') {
|
|
686
|
-
traceAgentToolFailure({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs,
|
|
737
|
+
traceAgentToolFailure({ sessionId, iteration, toolName, toolKind, toolMs, toolArgs, agent, model, cwd, resultText, resultKind });
|
|
687
738
|
}
|
|
688
739
|
}
|
|
689
740
|
|
|
@@ -741,25 +792,27 @@ function traceStreamAborted({ sessionId, info }) {
|
|
|
741
792
|
});
|
|
742
793
|
}
|
|
743
794
|
|
|
744
|
-
function traceAgentPreset({ sessionId,
|
|
795
|
+
function traceAgentPreset({ sessionId, agent, presetName, model, provider, parentSessionId }) {
|
|
745
796
|
// Fires once per dispatch right after the preset has been resolved and
|
|
746
797
|
// its runtime spec (provider/model) assembled. Useful for after-the-fact
|
|
747
|
-
// routing analysis: "which
|
|
798
|
+
// routing analysis: "which agent landed on which preset / provider / model
|
|
748
799
|
// on this request?"
|
|
749
800
|
appendAgentTrace({
|
|
750
801
|
sessionId,
|
|
751
802
|
kind: 'preset_assign',
|
|
752
|
-
|
|
803
|
+
agent: agent || null,
|
|
753
804
|
preset_name: presetName || null,
|
|
754
805
|
model: model || null,
|
|
755
806
|
provider: provider || null,
|
|
756
807
|
parent_session_id: parentSessionId || null,
|
|
808
|
+
parentSessionId: parentSessionId || null,
|
|
757
809
|
});
|
|
758
810
|
}
|
|
759
811
|
|
|
760
812
|
function traceAgentFetch({ sessionId, headersMs, httpStatus, handshakeRetries, handshakeRetryClassifiers, provider, model, transport }) {
|
|
761
813
|
const payload = {
|
|
762
814
|
headers_ms: headersMs,
|
|
815
|
+
phase: 'http_response_headers',
|
|
763
816
|
http_status: httpStatus,
|
|
764
817
|
provider: provider || null,
|
|
765
818
|
model: model || null,
|
|
@@ -786,17 +839,23 @@ function traceAgentFetch({ sessionId, headersMs, httpStatus, handshakeRetries, h
|
|
|
786
839
|
}
|
|
787
840
|
|
|
788
841
|
function traceAgentSse({ sessionId, sseParseMs, ttftMs, provider, model, transport }) {
|
|
842
|
+
const streamTotalMs = sseParseMs;
|
|
843
|
+
const firstTokenMs = ttftMs;
|
|
789
844
|
appendAgentTrace({
|
|
790
845
|
sessionId,
|
|
791
846
|
kind: 'sse',
|
|
792
847
|
sse_parse_ms: sseParseMs,
|
|
848
|
+
stream_total_ms: streamTotalMs,
|
|
793
849
|
ttft_ms: ttftMs,
|
|
850
|
+
first_token_ms: firstTokenMs,
|
|
794
851
|
provider: provider || null,
|
|
795
852
|
model: model || null,
|
|
796
853
|
transport: transport || null,
|
|
797
854
|
payload: {
|
|
798
855
|
sse_parse_ms: sseParseMs,
|
|
856
|
+
stream_total_ms: streamTotalMs,
|
|
799
857
|
ttft_ms: ttftMs,
|
|
858
|
+
first_token_ms: firstTokenMs,
|
|
800
859
|
provider: provider || null,
|
|
801
860
|
model: model || null,
|
|
802
861
|
transport: transport || null,
|
|
@@ -804,6 +863,19 @@ function traceAgentSse({ sessionId, sseParseMs, ttftMs, provider, model, transpo
|
|
|
804
863
|
});
|
|
805
864
|
}
|
|
806
865
|
|
|
866
|
+
function extractThinkingTokens(rawUsage) {
|
|
867
|
+
if (!rawUsage || typeof rawUsage !== 'object') return null;
|
|
868
|
+
const direct = Number(rawUsage.thinking_tokens ?? rawUsage.thinkingTokens);
|
|
869
|
+
if (Number.isFinite(direct) && direct >= 0) return direct;
|
|
870
|
+
const details = rawUsage.output_tokens_details
|
|
871
|
+
|| rawUsage.completion_tokens_details;
|
|
872
|
+
if (details && typeof details === 'object') {
|
|
873
|
+
const nested = Number(details.reasoning_tokens ?? details.thinking_tokens);
|
|
874
|
+
if (Number.isFinite(nested) && nested >= 0) return nested;
|
|
875
|
+
}
|
|
876
|
+
return null;
|
|
877
|
+
}
|
|
878
|
+
|
|
807
879
|
function traceAgentUsage({ sessionId, iteration, inputTokens, outputTokens, cachedTokens, cacheWriteTokens, promptTokens, model, modelDisplay, responseId, rawUsage, provider, serviceTier, requestKind }) {
|
|
808
880
|
const inclusive = isInclusiveProvider(provider);
|
|
809
881
|
const inTok = inputTokens || 0;
|
|
@@ -816,12 +888,14 @@ function traceAgentUsage({ sessionId, iteration, inputTokens, outputTokens, cach
|
|
|
816
888
|
? Math.max(inTok, cacheRead + cacheWrite)
|
|
817
889
|
: inTok + cacheRead + cacheWrite);
|
|
818
890
|
const resolvedServiceTier = serviceTier || rawUsage?.service_tier || rawUsage?.serviceTier || null;
|
|
891
|
+
const thinkingTokens = extractThinkingTokens(rawUsage);
|
|
819
892
|
appendAgentTrace({
|
|
820
893
|
sessionId,
|
|
821
894
|
iteration,
|
|
822
895
|
kind: 'usage_raw',
|
|
823
896
|
input_tokens: inputTokens,
|
|
824
897
|
output_tokens: outputTokens,
|
|
898
|
+
thinking_tokens: thinkingTokens,
|
|
825
899
|
cached_tokens: cachedTokens,
|
|
826
900
|
cache_write_tokens: cacheWrite,
|
|
827
901
|
uncached_input_tokens: uncachedInputTokens,
|
|
@@ -837,6 +911,7 @@ function traceAgentUsage({ sessionId, iteration, inputTokens, outputTokens, cach
|
|
|
837
911
|
provider: provider || null,
|
|
838
912
|
prompt_tokens: promptTotal,
|
|
839
913
|
uncached_input_tokens: uncachedInputTokens,
|
|
914
|
+
thinking_tokens: thinkingTokens,
|
|
840
915
|
model_display: modelDisplay || null,
|
|
841
916
|
response_id: responseId || null,
|
|
842
917
|
service_tier: resolvedServiceTier,
|
|
@@ -383,6 +383,7 @@ export function loadConfig(options = {}) {
|
|
|
383
383
|
trajectory: { enabled: true, ...raw.trajectory },
|
|
384
384
|
runtime: raw.runtime && typeof raw.runtime === 'object' ? raw.runtime : {},
|
|
385
385
|
shell: raw.shell && typeof raw.shell === 'object' ? raw.shell : {},
|
|
386
|
+
update: raw.update && typeof raw.update === 'object' ? { ...raw.update } : {},
|
|
386
387
|
};
|
|
387
388
|
}
|
|
388
389
|
catch { /* fall through */ }
|
|
@@ -408,6 +409,7 @@ export function loadConfig(options = {}) {
|
|
|
408
409
|
trajectory: { enabled: true },
|
|
409
410
|
runtime: {},
|
|
410
411
|
shell: {},
|
|
412
|
+
update: {},
|
|
411
413
|
};
|
|
412
414
|
}
|
|
413
415
|
/**
|
|
@@ -482,6 +484,7 @@ export function saveConfig(config) {
|
|
|
482
484
|
trajectory: config.trajectory || {},
|
|
483
485
|
runtime: config.runtime || {},
|
|
484
486
|
shell: config.shell || {},
|
|
487
|
+
update: config.update || {},
|
|
485
488
|
}));
|
|
486
489
|
}
|
|
487
490
|
// --- Preset helpers ---
|