mixdog 0.8.0 → 0.9.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/README.md +47 -23
- package/package.json +33 -27
- package/scripts/_test-folder-dialog.mjs +30 -0
- package/scripts/agent-parallel-smoke.mjs +388 -0
- package/scripts/agent-tag-reuse-smoke.mjs +183 -0
- package/scripts/background-task-meta-smoke.mjs +38 -0
- package/scripts/boot-smoke.mjs +52 -9
- package/scripts/build-runtime-linux.sh +348 -0
- package/scripts/build-runtime-macos.sh +217 -0
- package/scripts/build-runtime-windows.ps1 +242 -0
- package/scripts/compact-active-turn-test.mjs +68 -0
- package/scripts/compact-smoke.mjs +859 -129
- package/scripts/compact-trigger-migration-smoke.mjs +187 -0
- package/scripts/fix-brief-fn.mjs +35 -0
- package/scripts/fix-format-tool-surface.mjs +24 -0
- package/scripts/fix-tool-exec-visible.mjs +42 -0
- package/scripts/generate-runtime-manifest.mjs +166 -0
- package/scripts/hook-bus-test.mjs +330 -0
- package/scripts/lead-workflow-smoke.mjs +33 -39
- package/scripts/live-worker-smoke.mjs +43 -37
- package/scripts/llm-trace-summary.mjs +315 -0
- package/scripts/memory-meta-concurrency-test.mjs +20 -0
- package/scripts/output-style-smoke.mjs +56 -15
- package/scripts/parent-abort-link-test.mjs +44 -0
- package/scripts/patch-agent-brief.mjs +48 -0
- package/scripts/patch-app.mjs +21 -0
- package/scripts/patch-app2.mjs +18 -0
- package/scripts/patch-dist-brief.mjs +96 -0
- package/scripts/patch-tool-exec.mjs +70 -0
- package/scripts/pretool-ask-runtime-test.mjs +54 -0
- package/scripts/provider-toolcall-test.mjs +376 -0
- package/scripts/reactive-compact-persist-smoke.mjs +124 -0
- package/scripts/sanitize-tool-pairs-test.mjs +260 -0
- package/scripts/session-context-bench.mjs +344 -0
- package/scripts/session-ingest-smoke.mjs +177 -0
- package/scripts/set-effort-config-test.mjs +41 -0
- package/scripts/smoke-runtime-negative.ps1 +106 -0
- package/scripts/smoke-runtime-negative.sh +97 -0
- package/scripts/smoke.mjs +25 -0
- package/scripts/tool-result-hook-test.mjs +48 -0
- package/scripts/tool-smoke.mjs +1223 -95
- package/scripts/toolcall-args-test.mjs +150 -0
- package/scripts/tui-background-failure-smoke.mjs +73 -0
- package/scripts/usage-metrics-epoch-smoke.mjs +114 -0
- package/src/agents/debugger/AGENT.md +8 -0
- package/src/agents/explore/AGENT.md +4 -0
- package/src/agents/heavy-worker/AGENT.md +9 -3
- package/src/agents/maintainer/AGENT.md +4 -0
- package/src/agents/reviewer/AGENT.md +8 -0
- package/src/agents/scheduler-task/AGENT.md +12 -0
- package/src/agents/scheduler-task/agent.json +6 -0
- package/src/agents/webhook-handler/AGENT.md +12 -0
- package/src/agents/webhook-handler/agent.json +6 -0
- package/src/agents/worker/AGENT.md +9 -3
- package/src/app.mjs +77 -3
- package/src/defaults/hidden-roles.json +17 -12
- package/src/headless-role.mjs +117 -0
- package/src/help.mjs +30 -0
- package/src/hooks/lib/permission-evaluator.cjs +11 -475
- package/src/lib/keychain-cjs.cjs +9 -1
- package/src/lib/mixdog-debug.cjs +0 -7
- package/src/lib/rules-builder.cjs +240 -96
- package/src/lib/text-utils.cjs +1 -1
- package/src/mixdog-session-runtime.mjs +2325 -450
- package/src/output-styles/default.md +12 -28
- package/src/output-styles/extreme-simple.md +9 -6
- package/src/output-styles/simple.md +22 -9
- package/src/repl.mjs +118 -59
- package/src/rules/agent/00-common.md +15 -0
- package/src/rules/{bridge → agent}/20-skip-protocol.md +1 -2
- package/src/rules/agent/30-explorer.md +22 -0
- package/src/rules/{bridge → agent}/40-cycle1-agent.md +7 -0
- package/src/rules/{bridge → agent}/41-cycle2-agent.md +7 -0
- package/src/rules/{bridge → agent}/42-cycle3-agent.md +7 -0
- package/src/rules/lead/01-general.md +9 -5
- package/src/rules/lead/04-workflow.md +51 -12
- package/src/rules/lead/lead-tool.md +6 -0
- package/src/rules/shared/01-tool.md +12 -1
- package/src/runtime/agent/orchestrator/activity-bus.mjs +7 -18
- package/src/runtime/agent/orchestrator/agent-owner.mjs +11 -0
- package/src/runtime/agent/orchestrator/{smart-bridge/bridge-llm.mjs → agent-runtime/agent-dispatch.mjs} +138 -111
- package/src/runtime/agent/orchestrator/agent-runtime/agent-progress-watchdog.mjs +94 -0
- package/src/runtime/agent/orchestrator/{smart-bridge → agent-runtime}/cache-strategy.mjs +32 -23
- package/src/runtime/agent/orchestrator/{smart-bridge → agent-runtime}/session-builder.mjs +33 -27
- package/src/runtime/agent/orchestrator/{bridge-trace.mjs → agent-trace.mjs} +132 -81
- package/src/runtime/agent/orchestrator/cache-mtime.mjs +0 -21
- package/src/runtime/agent/orchestrator/config.mjs +174 -55
- package/src/runtime/agent/orchestrator/context/collect.mjs +195 -487
- package/src/runtime/agent/orchestrator/dispatch-persist.mjs +1 -1
- package/src/runtime/agent/orchestrator/internal-roles.mjs +77 -29
- package/src/runtime/agent/orchestrator/internal-tools.mjs +5 -6
- package/src/runtime/agent/orchestrator/mcp/client.mjs +15 -9
- package/src/runtime/agent/orchestrator/providers/anthropic-betas.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +377 -243
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +146 -93
- package/src/runtime/agent/orchestrator/providers/api-usage.mjs +236 -4
- package/src/runtime/agent/orchestrator/providers/custom-tool-wire.mjs +49 -0
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +58 -13
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +67 -149
- package/src/runtime/agent/orchestrator/providers/media-normalization.mjs +132 -2
- package/src/runtime/agent/orchestrator/providers/model-catalog.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +45 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +61 -116
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +25 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +79 -255
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +221 -70
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +477 -147
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +343 -496
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +6 -6
- package/src/runtime/agent/orchestrator/providers/registry.mjs +88 -51
- package/src/runtime/agent/orchestrator/providers/retry-classifier.mjs +31 -11
- package/src/runtime/agent/orchestrator/providers/statusline-route-meta.mjs +41 -8
- package/src/runtime/agent/orchestrator/session/cache/post-edit-marks.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/cache/read-cache.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact.mjs +1173 -267
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +199 -36
- package/src/runtime/agent/orchestrator/session/loop.mjs +851 -674
- package/src/runtime/agent/orchestrator/session/manager.mjs +1593 -466
- package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +107 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +291 -46
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +2 -2
- package/src/runtime/agent/orchestrator/stall-policy.mjs +31 -16
- package/src/runtime/agent/orchestrator/tool-loop-guard.mjs +3 -219
- package/src/runtime/agent/orchestrator/tools/bash-session.mjs +34 -7
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +19 -0
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +9 -9
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +60 -37
- package/src/runtime/agent/orchestrator/tools/builtin/cache-layers.mjs +21 -2
- package/src/runtime/agent/orchestrator/tools/builtin/device-paths.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +0 -7
- package/src/runtime/agent/orchestrator/tools/builtin/glob-walk.mjs +1 -3
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +36 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-args.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/builtin/read-constants.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +5 -12
- package/src/runtime/agent/orchestrator/tools/builtin/read-image-resize.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-tool.mjs +4 -36
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool.mjs +2 -40
- package/src/runtime/agent/orchestrator/tools/builtin/rg-runner.mjs +148 -27
- package/src/runtime/agent/orchestrator/tools/builtin/search-builders.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/builtin/search-tool.mjs +43 -75
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +90 -20
- package/src/runtime/agent/orchestrator/tools/builtin/snapshot-store.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +59 -5
- package/src/runtime/agent/orchestrator/tools/code-graph-state.mjs +86 -0
- package/src/runtime/agent/orchestrator/tools/code-graph-tool-defs.mjs +11 -11
- package/src/runtime/agent/orchestrator/tools/code-graph.mjs +4106 -4019
- package/src/runtime/agent/orchestrator/tools/patch-tool-defs.mjs +33 -4
- package/src/runtime/agent/orchestrator/tools/patch.mjs +90 -6
- package/src/runtime/agent/orchestrator/tools/progress-message.mjs +6 -4
- package/src/runtime/agent/orchestrator/tools/result-compression.mjs +4 -4
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +8 -1
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +4 -4
- package/src/runtime/channels/index.mjs +152 -24
- package/src/runtime/channels/lib/scheduler.mjs +18 -14
- package/src/runtime/channels/lib/session-discovery.mjs +3 -2
- package/src/runtime/channels/lib/tool-format.mjs +0 -2
- package/src/runtime/channels/lib/transcript-discovery.mjs +3 -2
- package/src/runtime/channels/lib/webhook.mjs +1 -1
- package/src/runtime/channels/tool-defs.mjs +29 -29
- package/src/runtime/memory/index.mjs +635 -107
- package/src/runtime/memory/lib/agent-ipc.mjs +29 -12
- package/src/runtime/memory/lib/core-memory-store.mjs +2 -2
- package/src/runtime/memory/lib/embedding-model-config.mjs +55 -0
- package/src/runtime/memory/lib/embedding-provider.mjs +31 -4
- package/src/runtime/memory/lib/embedding-worker.mjs +19 -10
- package/src/runtime/memory/lib/memory-cycle1.mjs +38 -17
- package/src/runtime/memory/lib/memory-cycle2.mjs +6 -7
- package/src/runtime/memory/lib/memory-cycle3.mjs +4 -4
- package/src/runtime/memory/lib/memory-ops-policy.mjs +2 -1
- package/src/runtime/memory/lib/memory-session-merge.mjs +38 -0
- package/src/runtime/memory/lib/memory.mjs +88 -9
- package/src/runtime/memory/lib/model-profile.mjs +1 -1
- package/src/runtime/memory/lib/pg/adapter.mjs +15 -1
- package/src/runtime/memory/lib/pg/supervisor.mjs +12 -0
- package/src/runtime/memory/lib/runtime-fetcher.mjs +37 -3
- package/src/runtime/memory/lib/session-ingest.mjs +194 -0
- package/src/runtime/memory/lib/trace-store.mjs +96 -51
- package/src/runtime/memory/tool-defs.mjs +46 -37
- package/src/runtime/search/index.mjs +102 -466
- package/src/runtime/search/lib/web-tools.mjs +45 -25
- package/src/runtime/search/tool-defs.mjs +16 -23
- package/src/runtime/shared/abort-controller.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +4 -3
- package/src/runtime/shared/background-tasks.mjs +122 -11
- package/src/runtime/shared/child-spawn-gate.mjs +145 -0
- package/src/runtime/shared/config.mjs +7 -4
- package/src/runtime/shared/err-text.mjs +131 -4
- package/src/runtime/shared/llm/cost.mjs +2 -2
- package/src/runtime/shared/llm/http-agent.mjs +23 -7
- package/src/runtime/shared/llm/index.mjs +34 -11
- package/src/runtime/shared/llm/usage-log.mjs +4 -4
- package/src/runtime/shared/markdown-frontmatter.mjs +56 -0
- package/src/runtime/shared/singleton-owner.mjs +104 -0
- package/src/runtime/shared/tool-execution-contract.mjs +199 -20
- package/src/runtime/shared/tool-execution-contract.test.mjs +183 -0
- package/src/runtime/shared/tool-surface.mjs +624 -98
- package/src/runtime/shared/user-data-guard.mjs +0 -2
- package/src/standalone/agent-task-status.mjs +203 -0
- package/src/standalone/agent-task-status.test.mjs +76 -0
- package/src/standalone/agent-tool.mjs +1913 -0
- package/src/standalone/channel-worker.mjs +370 -14
- package/src/standalone/explore-tool.mjs +165 -70
- package/src/standalone/folder-dialog.mjs +314 -0
- package/src/standalone/hook-bus.mjs +898 -22
- package/src/standalone/memory-runtime-proxy.mjs +320 -0
- package/src/standalone/projects.mjs +226 -0
- package/src/standalone/provider-admin.mjs +41 -24
- package/src/standalone/seeds.mjs +2 -69
- package/src/standalone/usage-dashboard.mjs +96 -8
- package/src/tui/App.jsx +4798 -2153
- package/src/tui/components/AnsiText.jsx +39 -28
- package/src/tui/components/ContextPanel.jsx +87 -29
- package/src/tui/components/Markdown.jsx +43 -77
- package/src/tui/components/MarkdownTable.jsx +9 -184
- package/src/tui/components/Message.jsx +28 -11
- package/src/tui/components/Picker.jsx +95 -56
- package/src/tui/components/PromptInput.jsx +367 -239
- package/src/tui/components/QueuedCommands.jsx +1 -1
- package/src/tui/components/SlashCommandPalette.jsx +27 -21
- package/src/tui/components/Spinner.jsx +67 -38
- package/src/tui/components/StatusLine.jsx +606 -38
- package/src/tui/components/TextEntryPanel.jsx +128 -9
- package/src/tui/components/ToolExecution.jsx +617 -368
- package/src/tui/components/TurnDone.jsx +3 -3
- package/src/tui/components/UsagePanel.jsx +3 -5
- package/src/tui/components/tool-output-format.mjs +365 -0
- package/src/tui/components/tool-output-format.test.mjs +220 -0
- package/src/tui/dist/index.mjs +8915 -2418
- package/src/tui/engine-runtime-notification.test.mjs +115 -0
- package/src/tui/engine-tool-result-text.test.mjs +75 -0
- package/src/tui/engine.mjs +1455 -279
- package/src/tui/figures.mjs +21 -40
- package/src/tui/index.jsx +75 -31
- package/src/tui/input-editing.mjs +25 -0
- package/src/tui/markdown/format-token.mjs +511 -68
- package/src/tui/markdown/format-token.test.mjs +216 -0
- package/src/tui/markdown/render-ansi.mjs +94 -0
- package/src/tui/markdown/render-ansi.test.mjs +108 -0
- package/src/tui/markdown/stream-fence.mjs +34 -0
- package/src/tui/markdown/stream-fence.test.mjs +26 -0
- package/src/tui/markdown/table-layout.mjs +250 -0
- package/src/tui/paste-attachments.mjs +0 -7
- package/src/tui/spinner-verbs.mjs +1 -2
- package/src/tui/statusline-ansi-bridge.mjs +172 -0
- package/src/tui/statusline-ansi-bridge.test.mjs +159 -0
- package/src/tui/theme.mjs +746 -24
- package/src/tui/time-format.mjs +1 -1
- package/src/tui/transcript-tool-failures.mjs +67 -0
- package/src/tui/transcript-tool-failures.test.mjs +111 -0
- package/src/ui/ansi.mjs +1 -2
- package/src/ui/markdown.mjs +85 -26
- package/src/ui/markdown.test.mjs +70 -0
- package/src/ui/model-display.mjs +121 -0
- package/src/ui/session-stats.mjs +44 -0
- package/src/ui/statusline-context-label.test.mjs +15 -0
- package/src/ui/statusline.mjs +386 -178
- package/src/ui/tool-card.mjs +3 -16
- package/src/vendor/statusline/bin/statusline-lib.mjs +8 -4
- package/src/vendor/statusline/bin/statusline-route.mjs +169 -37
- package/src/vendor/statusline/bin/statusline-route.test.mjs +80 -0
- package/src/vendor/statusline/scripts/lib/gateway-settings.mjs +3 -3
- package/src/vendor/statusline/src/gateway/claude-current.mjs +1 -1
- package/src/vendor/statusline/src/gateway/route-meta.mjs +44 -6
- package/src/vendor/statusline/src/gateway/session-routes.mjs +1 -1
- package/src/workflows/default/WORKFLOW.md +12 -5
- package/src/workflows/default/workflow.json +0 -1
- package/src/workflows/solo/WORKFLOW.md +15 -0
- package/src/workflows/solo/workflow.json +7 -0
- package/vendor/ink/build/output.js +6 -1
- package/src/agents/scheduler-task.md +0 -3
- package/src/agents/web-researcher/AGENT.md +0 -3
- package/src/agents/web-researcher/agent.json +0 -6
- package/src/agents/webhook-handler.md +0 -3
- package/src/rules/bridge/00-common.md +0 -5
- package/src/rules/bridge/30-explorer.md +0 -4
- package/src/rules/lead/00-tool-lead.md +0 -5
- package/src/rules/shared/00-language.md +0 -3
- package/src/runtime/agent/orchestrator/tools/builtin/native-edit-runner.mjs +0 -110
- package/src/runtime/agent/orchestrator/tools/mutation-content-cache.mjs +0 -67
- package/src/runtime/memory/lib/bridge-trace-queries.mjs +0 -120
- package/src/runtime/shared/llm/pid-cleanup.mjs +0 -27
- package/src/standalone/bridge-tool.mjs +0 -1414
- package/src/tui/runtime/shared/process-shutdown.mjs +0 -1
|
@@ -8,7 +8,7 @@ function __mixdogMemoryLog(...args) {
|
|
|
8
8
|
// Uses pg-adapter (schema='trace') so trace_events live in the trace schema.
|
|
9
9
|
// Isolated from memory schema; shares the same PG instance.
|
|
10
10
|
|
|
11
|
-
import { ensurePgInstance, checkedConnect } from './pg/adapter.mjs'
|
|
11
|
+
import { ensurePgInstance, checkedConnect, closePgInstance } from './pg/adapter.mjs'
|
|
12
12
|
import { resolve } from 'path'
|
|
13
13
|
|
|
14
14
|
const dbs = new Map()
|
|
@@ -123,15 +123,15 @@ async function init(client) {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
// ---------------------------------------------------------------------------
|
|
126
|
-
//
|
|
126
|
+
// Agent-specific analytic tables (added post-init via initAgentTables)
|
|
127
127
|
// ---------------------------------------------------------------------------
|
|
128
128
|
|
|
129
129
|
// Called once per openTraceDatabase boot (after the advisory lock is released).
|
|
130
130
|
// Safe to call concurrently — all DDL is IF NOT EXISTS.
|
|
131
|
-
export async function
|
|
132
|
-
// ──
|
|
131
|
+
export async function initAgentTables(client) {
|
|
132
|
+
// ── agent_calls: one row per tool invocation ─────────────────────────────
|
|
133
133
|
await client.query(`
|
|
134
|
-
CREATE TABLE IF NOT EXISTS
|
|
134
|
+
CREATE TABLE IF NOT EXISTS agent_calls (
|
|
135
135
|
id BIGSERIAL PRIMARY KEY,
|
|
136
136
|
session_id TEXT NOT NULL,
|
|
137
137
|
iteration INT,
|
|
@@ -142,18 +142,18 @@ export async function initBridgeTables(client) {
|
|
|
142
142
|
tool_args JSONB
|
|
143
143
|
)
|
|
144
144
|
`)
|
|
145
|
-
await client.query(`CREATE INDEX IF NOT EXISTS
|
|
146
|
-
await client.query(`CREATE INDEX IF NOT EXISTS
|
|
147
|
-
await client.query(`CREATE INDEX IF NOT EXISTS
|
|
145
|
+
await client.query(`CREATE INDEX IF NOT EXISTS idx_ac_session ON agent_calls (session_id, iteration)`)
|
|
146
|
+
await client.query(`CREATE INDEX IF NOT EXISTS idx_ac_ts ON agent_calls USING BRIN (ts)`)
|
|
147
|
+
await client.query(`CREATE INDEX IF NOT EXISTS idx_ac_tool_name ON agent_calls (tool_name)`)
|
|
148
148
|
// Expression indexes covering the two actual query patterns (md5 dedup + path lookup).
|
|
149
149
|
// The old GIN index had no @> callers and was write-heavy; dropped in favour of these.
|
|
150
|
-
await client.query(`CREATE INDEX IF NOT EXISTS
|
|
151
|
-
await client.query(`CREATE INDEX IF NOT EXISTS
|
|
152
|
-
await client.query(`DROP INDEX IF EXISTS
|
|
150
|
+
await client.query(`CREATE INDEX IF NOT EXISTS idx_ac_args_md5 ON agent_calls (session_id, tool_name, md5(tool_args::text))`)
|
|
151
|
+
await client.query(`CREATE INDEX IF NOT EXISTS idx_ac_args_path ON agent_calls (session_id, tool_name, (tool_args->>'path'), ts, id)`)
|
|
152
|
+
await client.query(`DROP INDEX IF EXISTS idx_ac_args`)
|
|
153
153
|
|
|
154
|
-
// ──
|
|
154
|
+
// ── agent_llm: one row per LLM usage event ───────────────────────────────
|
|
155
155
|
await client.query(`
|
|
156
|
-
CREATE TABLE IF NOT EXISTS
|
|
156
|
+
CREATE TABLE IF NOT EXISTS agent_llm (
|
|
157
157
|
id BIGSERIAL PRIMARY KEY,
|
|
158
158
|
session_id TEXT NOT NULL,
|
|
159
159
|
iteration INT,
|
|
@@ -167,13 +167,13 @@ export async function initBridgeTables(client) {
|
|
|
167
167
|
response_id TEXT
|
|
168
168
|
)
|
|
169
169
|
`)
|
|
170
|
-
await client.query(`CREATE INDEX IF NOT EXISTS
|
|
171
|
-
await client.query(`CREATE INDEX IF NOT EXISTS
|
|
172
|
-
await client.query(`CREATE INDEX IF NOT EXISTS
|
|
170
|
+
await client.query(`CREATE INDEX IF NOT EXISTS idx_al_session ON agent_llm (session_id, iteration)`)
|
|
171
|
+
await client.query(`CREATE INDEX IF NOT EXISTS idx_al_ts ON agent_llm USING BRIN (ts)`)
|
|
172
|
+
await client.query(`CREATE INDEX IF NOT EXISTS idx_al_model ON agent_llm (model)`)
|
|
173
173
|
|
|
174
|
-
// ──
|
|
174
|
+
// ── agent_sessions: denormalised summary upserted on each insert ─────────
|
|
175
175
|
await client.query(`
|
|
176
|
-
CREATE TABLE IF NOT EXISTS
|
|
176
|
+
CREATE TABLE IF NOT EXISTS agent_sessions (
|
|
177
177
|
session_id TEXT PRIMARY KEY,
|
|
178
178
|
role TEXT,
|
|
179
179
|
model TEXT,
|
|
@@ -189,7 +189,7 @@ export async function initBridgeTables(client) {
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
// ---------------------------------------------------------------------------
|
|
192
|
-
//
|
|
192
|
+
// insertAgentCalls — batch insert tool rows + upsert session summary
|
|
193
193
|
// ---------------------------------------------------------------------------
|
|
194
194
|
const TOOL_ARGS_MAX_BYTES = 65536 // 64 KB cap; oversized → sha256 + truncated preview
|
|
195
195
|
|
|
@@ -207,7 +207,7 @@ function _capToolArgsSync(args) {
|
|
|
207
207
|
return { _oversized: true, sha256: _createHash('sha256').update(raw).digest('hex'), preview: raw.slice(0, 512) }
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
export async function
|
|
210
|
+
export async function insertAgentCalls(db, events) {
|
|
211
211
|
if (!Array.isArray(events) || events.length === 0) return { calls: 0, llm: 0 }
|
|
212
212
|
const toolRows = []
|
|
213
213
|
const llmRows = []
|
|
@@ -237,7 +237,7 @@ export async function insertBridgeCalls(db, events) {
|
|
|
237
237
|
|
|
238
238
|
// Wrap all three inserts in a single transaction — one flush/fsync.
|
|
239
239
|
// checkedConnect ensures search_path = trace, public on fresh connections;
|
|
240
|
-
// raw _pool.connect() leaves search_path at PG default and
|
|
240
|
+
// raw _pool.connect() leaves search_path at PG default and agent_* lookups
|
|
241
241
|
// resolve in the wrong schema.
|
|
242
242
|
const client = await checkedConnect(db._pool, 'trace')
|
|
243
243
|
try {
|
|
@@ -245,7 +245,7 @@ export async function insertBridgeCalls(db, events) {
|
|
|
245
245
|
|
|
246
246
|
if (toolRows.length > 0) {
|
|
247
247
|
await client.query(
|
|
248
|
-
`INSERT INTO
|
|
248
|
+
`INSERT INTO agent_calls (session_id,iteration,ts,tool_name,tool_kind,tool_ms,tool_args)
|
|
249
249
|
SELECT u.session_id, u.iteration::int, u.ts::timestamptz,
|
|
250
250
|
u.tool_name, u.tool_kind, u.tool_ms::int, u.tool_args::jsonb
|
|
251
251
|
FROM unnest($1::text[],$2::int[],$3::text[],$4::text[],$5::text[],$6::int[],$7::text[])
|
|
@@ -264,7 +264,7 @@ export async function insertBridgeCalls(db, events) {
|
|
|
264
264
|
|
|
265
265
|
if (llmRows.length > 0) {
|
|
266
266
|
await client.query(
|
|
267
|
-
`INSERT INTO
|
|
267
|
+
`INSERT INTO agent_llm (session_id,iteration,ts,model,input_tokens,output_tokens,cached_tokens,cache_write_tokens,prompt_tokens,response_id)
|
|
268
268
|
SELECT u.session_id, u.iteration::int, u.ts::timestamptz,
|
|
269
269
|
u.model, u.input_tokens::int, u.output_tokens::int,
|
|
270
270
|
u.cached_tokens::int, u.cache_write_tokens::int,
|
|
@@ -330,7 +330,7 @@ export async function insertBridgeCalls(db, events) {
|
|
|
330
330
|
})
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
-
// Coalesce
|
|
333
|
+
// Coalesce agent_sessions upserts: batch all sessions in one unnest INSERT.
|
|
334
334
|
// Also within the same transaction.
|
|
335
335
|
if (sessionMap.size > 0) {
|
|
336
336
|
const sids = [], roles = [], models = [], ts0s = [], ts1s = [],
|
|
@@ -343,7 +343,7 @@ export async function insertBridgeCalls(db, events) {
|
|
|
343
343
|
tinputs.push(String(s.total_input)); toutputs.push(String(s.total_output))
|
|
344
344
|
}
|
|
345
345
|
await client.query(`
|
|
346
|
-
INSERT INTO
|
|
346
|
+
INSERT INTO agent_sessions (session_id, role, model, started_at, last_seen_at, tool_calls, llm_calls, max_iteration, total_input_tokens, total_output_tokens)
|
|
347
347
|
SELECT u.session_id, u.role, u.model,
|
|
348
348
|
u.started_at::timestamptz, u.last_seen_at::timestamptz,
|
|
349
349
|
u.tool_calls::int, u.llm_calls::int, u.max_iteration::int,
|
|
@@ -351,15 +351,15 @@ export async function insertBridgeCalls(db, events) {
|
|
|
351
351
|
FROM unnest($1::text[],$2::text[],$3::text[],$4::text[],$5::text[],$6::int[],$7::int[],$8::int[],$9::text[],$10::text[])
|
|
352
352
|
AS u(session_id,role,model,started_at,last_seen_at,tool_calls,llm_calls,max_iteration,total_input_tokens,total_output_tokens)
|
|
353
353
|
ON CONFLICT (session_id) DO UPDATE SET
|
|
354
|
-
role = COALESCE(EXCLUDED.role,
|
|
355
|
-
model = COALESCE(EXCLUDED.model,
|
|
356
|
-
started_at = LEAST(
|
|
357
|
-
last_seen_at = GREATEST(
|
|
358
|
-
tool_calls =
|
|
359
|
-
llm_calls =
|
|
360
|
-
max_iteration = GREATEST(
|
|
361
|
-
total_input_tokens =
|
|
362
|
-
total_output_tokens =
|
|
354
|
+
role = COALESCE(EXCLUDED.role, agent_sessions.role),
|
|
355
|
+
model = COALESCE(EXCLUDED.model, agent_sessions.model),
|
|
356
|
+
started_at = LEAST(agent_sessions.started_at, EXCLUDED.started_at),
|
|
357
|
+
last_seen_at = GREATEST(agent_sessions.last_seen_at, EXCLUDED.last_seen_at),
|
|
358
|
+
tool_calls = agent_sessions.tool_calls + EXCLUDED.tool_calls,
|
|
359
|
+
llm_calls = agent_sessions.llm_calls + EXCLUDED.llm_calls,
|
|
360
|
+
max_iteration = GREATEST(agent_sessions.max_iteration, EXCLUDED.max_iteration),
|
|
361
|
+
total_input_tokens = agent_sessions.total_input_tokens + EXCLUDED.total_input_tokens,
|
|
362
|
+
total_output_tokens = agent_sessions.total_output_tokens + EXCLUDED.total_output_tokens
|
|
363
363
|
`, [sids, roles, models, ts0s, ts1s, tcalls, lcalls, maxiters, tinputs, toutputs])
|
|
364
364
|
}
|
|
365
365
|
|
|
@@ -519,8 +519,8 @@ export async function openTraceDatabase(dataDir) {
|
|
|
519
519
|
} finally {
|
|
520
520
|
client.release()
|
|
521
521
|
}
|
|
522
|
-
//
|
|
523
|
-
await
|
|
522
|
+
// Agent-specific analytic tables — idempotent, no advisory lock needed.
|
|
523
|
+
await initAgentTables(db)
|
|
524
524
|
|
|
525
525
|
dbs.set(key, db)
|
|
526
526
|
|
|
@@ -633,32 +633,77 @@ function _scheduleFlush(db, q) {
|
|
|
633
633
|
// Issue 4: timer is unref()'d so it won't prevent exit; register drain handlers.
|
|
634
634
|
// ---------------------------------------------------------------------------
|
|
635
635
|
|
|
636
|
-
const _registeredExitDbs = new
|
|
636
|
+
const _registeredExitDbs = new WeakMap()
|
|
637
|
+
|
|
638
|
+
async function drainTraceQueue(db) {
|
|
639
|
+
const q = _traceQueues.get(db)
|
|
640
|
+
if (!q) return
|
|
641
|
+
try {
|
|
642
|
+
if (q.timer) { clearTimeout(q.timer); q.timer = null }
|
|
643
|
+
if (q.flushPromise) await q.flushPromise.catch(() => {})
|
|
644
|
+
if (q.pending.length > 0) await _insertTraceEventsDirect(db, q.pending.splice(0).flatMap(w => w.events))
|
|
645
|
+
} catch (e) {
|
|
646
|
+
__mixdogMemoryLog(`[trace-queue] drain failed: ${e?.message}\n`)
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
function clearTraceQueue(db) {
|
|
651
|
+
const q = _traceQueues.get(db)
|
|
652
|
+
if (!q) return
|
|
653
|
+
if (q.timer) { clearTimeout(q.timer); q.timer = null }
|
|
654
|
+
q.pending.length = 0
|
|
655
|
+
q.flushPromise = null
|
|
656
|
+
_traceQueues.delete(db)
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
function unregisterTraceExitDrain(db) {
|
|
660
|
+
const handlers = _registeredExitDbs.get(db)
|
|
661
|
+
if (!handlers) return
|
|
662
|
+
try { process.off('exit', handlers.onExit) } catch {}
|
|
663
|
+
try { process.off('SIGTERM', handlers.onSigterm) } catch {}
|
|
664
|
+
try { process.off('beforeExit', handlers.onBeforeExit) } catch {}
|
|
665
|
+
_registeredExitDbs.delete(db)
|
|
666
|
+
}
|
|
637
667
|
|
|
638
668
|
export function registerTraceExitDrain(db) {
|
|
639
669
|
if (_registeredExitDbs.has(db)) return
|
|
640
|
-
_registeredExitDbs.add(db)
|
|
641
670
|
|
|
642
671
|
async function drainOnExit() {
|
|
643
|
-
|
|
644
|
-
if (!q || q.pending.length === 0) return
|
|
645
|
-
try {
|
|
646
|
-
if (q.timer) { clearTimeout(q.timer); q.timer = null }
|
|
647
|
-
if (q.flushPromise) await q.flushPromise.catch(() => {})
|
|
648
|
-
if (q.pending.length > 0) await _insertTraceEventsDirect(db, q.pending.splice(0).flatMap(w => w.events))
|
|
649
|
-
} catch (e) {
|
|
650
|
-
__mixdogMemoryLog(`[trace-queue] exit drain failed: ${e?.message}\n`)
|
|
651
|
-
}
|
|
672
|
+
await drainTraceQueue(db)
|
|
652
673
|
}
|
|
653
674
|
|
|
654
|
-
|
|
675
|
+
const onExit = () => {
|
|
655
676
|
const q = _traceQueues.get(db)
|
|
656
677
|
if (q?.pending.length) __mixdogMemoryLog(`[trace-queue] exit with ${q.pending.length} unflushed events\n`)
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
process.on('SIGTERM', async () => { await drainOnExit(); process.exit(0) })
|
|
678
|
+
}
|
|
679
|
+
const onSigterm = async () => { await drainOnExit(); process.exit(0) }
|
|
660
680
|
|
|
681
|
+
process.on('exit', onExit)
|
|
682
|
+
process.on('SIGTERM', onSigterm)
|
|
661
683
|
process.once('beforeExit', drainOnExit)
|
|
684
|
+
|
|
685
|
+
_registeredExitDbs.set(db, { onExit, onSigterm, onBeforeExit: drainOnExit })
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
export async function closeTraceDatabase(dataDir) {
|
|
689
|
+
const key = resolve(dataDir)
|
|
690
|
+
let db = dbs.get(key)
|
|
691
|
+
if (!db && opening.has(key)) {
|
|
692
|
+
try { db = await opening.get(key) } catch { db = null }
|
|
693
|
+
}
|
|
694
|
+
if (!db) return false
|
|
695
|
+
const timer = partitionTimers.get(key)
|
|
696
|
+
if (timer) {
|
|
697
|
+
try { clearInterval(timer) } catch {}
|
|
698
|
+
partitionTimers.delete(key)
|
|
699
|
+
}
|
|
700
|
+
await drainTraceQueue(db)
|
|
701
|
+
clearTraceQueue(db)
|
|
702
|
+
unregisterTraceExitDrain(db)
|
|
703
|
+
dbs.delete(key)
|
|
704
|
+
try { await db.close?.() } catch {}
|
|
705
|
+
try { await closePgInstance(dataDir, { schema: 'trace' }) } catch {}
|
|
706
|
+
return true
|
|
662
707
|
}
|
|
663
708
|
|
|
664
709
|
/**
|
|
@@ -8,24 +8,28 @@ export const TOOL_DEFS = [
|
|
|
8
8
|
name: 'memory',
|
|
9
9
|
title: 'Memory Cycle',
|
|
10
10
|
annotations: { title: 'Memory Cycle', readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
|
|
11
|
-
description: '
|
|
11
|
+
description: 'Memory status/lifecycle or explicit mutation. Use recall for retrieval. Destructive jobs require exact confirm strings.',
|
|
12
12
|
inputSchema: {
|
|
13
13
|
type: 'object',
|
|
14
14
|
properties: {
|
|
15
|
-
action: { type: 'string', enum: ['core','manage','status','sleep','cycle1','cycle2','cycle3','flush','backfill','prune','rebuild','purge','retro_eval_active'], description: 'Operation
|
|
16
|
-
op: { type: 'string', enum: ['add','edit','delete','list'], description: 'Mutation
|
|
17
|
-
id: { type: 'number', description: 'Exact memory id
|
|
18
|
-
element: { type: 'string', description: '
|
|
19
|
-
summary: { type: 'string', description: 'Memory content
|
|
20
|
-
category: { type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'], description: '
|
|
21
|
-
status: { type: 'string', enum: ['pending','active','archived'], description: '
|
|
22
|
-
maxDays: { type: 'number', description: 'Prune
|
|
23
|
-
window: { type: 'string', description: '
|
|
24
|
-
limit: { type: 'number', description: '
|
|
25
|
-
concurrency: { type: 'number', description: 'Worker concurrency
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
15
|
+
action: { type: 'string', enum: ['core','manage','status','sleep','cycle1','cycle2','cycle3','flush','backfill','prune','rebuild','purge','retro_eval_active'], description: 'Operation.' },
|
|
16
|
+
op: { type: 'string', enum: ['add','edit','delete','list'], description: 'Mutation op.' },
|
|
17
|
+
id: { type: 'number', description: 'Exact memory id.' },
|
|
18
|
+
element: { type: 'string', description: 'Memory key/title.' },
|
|
19
|
+
summary: { type: 'string', description: 'Memory content.' },
|
|
20
|
+
category: { type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'], description: 'Category.' },
|
|
21
|
+
status: { type: 'string', enum: ['pending','active','archived'], description: 'Lifecycle status.' },
|
|
22
|
+
maxDays: { type: 'number', description: 'Prune age days.' },
|
|
23
|
+
window: { type: 'string', description: 'Window, e.g. 24h/7d/30d.' },
|
|
24
|
+
limit: { type: 'number', description: 'Max rows/items.' },
|
|
25
|
+
concurrency: { type: 'number', description: 'Worker concurrency.' },
|
|
26
|
+
sessionId: { type: 'string', description: 'Scoped session id.' },
|
|
27
|
+
session_id: { type: 'string', description: 'Alias for sessionId.' },
|
|
28
|
+
window_size: { type: 'number', description: 'cycle1 rows/window.' },
|
|
29
|
+
rows_per_session: { type: 'number', description: 'cycle1 rows/session.' },
|
|
30
|
+
confirm: { type: 'string', description: 'Exact confirmation phrase for destructive actions.' },
|
|
31
|
+
cycle3Mode: { type: 'string', enum: ['proposal','conservative'], description: 'cycle3 mode.' },
|
|
32
|
+
project_id: { type: 'string', description: 'Core pool: common, slug, or *.' },
|
|
29
33
|
},
|
|
30
34
|
required: ['action'],
|
|
31
35
|
},
|
|
@@ -34,20 +38,23 @@ export const TOOL_DEFS = [
|
|
|
34
38
|
name: 'recall',
|
|
35
39
|
title: 'Recall',
|
|
36
40
|
annotations: { title: 'Recall', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
37
|
-
description: 'Retrieve stored memory
|
|
41
|
+
description: 'Retrieve stored memory/session history. Use for earlier work, resumes, or possibly decided items; when in doubt, recall first.',
|
|
38
42
|
inputSchema: {
|
|
39
43
|
type: 'object',
|
|
40
44
|
properties: {
|
|
41
45
|
query: { anyOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' }, minItems: 1 }], description: 'Search text, or array for independent fan-out queries.' },
|
|
42
|
-
id: { anyOf: [{ type: 'number' }, { type: 'array', items: { type: 'number' }, minItems: 1 }], description: '
|
|
43
|
-
period: { type: 'string', description: '
|
|
44
|
-
limit: { type: 'number', description: '
|
|
45
|
-
offset: { type: 'number', description: 'Skip
|
|
46
|
-
sort: { type: 'string', enum: ['importance', 'date'], description: 'importance
|
|
47
|
-
category: { anyOf: [{ type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'] }, { type: 'array', items: { type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'] }, minItems: 1 }], description: '
|
|
48
|
-
includeArchived: { type: 'boolean', description: 'Include archived
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
id: { anyOf: [{ type: 'number' }, { type: 'array', items: { type: 'number' }, minItems: 1 }], description: 'Exact #id(s) from recall. Do not invent ids.' },
|
|
47
|
+
period: { type: 'string', description: 'last, 24h/7d/30d, all, date, or range.' },
|
|
48
|
+
limit: { type: 'number', description: 'Max entries.' },
|
|
49
|
+
offset: { type: 'number', description: 'Skip entries.' },
|
|
50
|
+
sort: { type: 'string', enum: ['importance', 'date'], description: 'importance or date.' },
|
|
51
|
+
category: { anyOf: [{ type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'] }, { type: 'array', items: { type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'] }, minItems: 1 }], description: 'Category filter.' },
|
|
52
|
+
includeArchived: { type: 'boolean', description: 'Include archived entries.' },
|
|
53
|
+
sessionId: { type: 'string', description: 'Scoped session id.' },
|
|
54
|
+
session_id: { type: 'string', description: 'Alias for sessionId.' },
|
|
55
|
+
includeMembers: { type: 'boolean', description: 'Include chunk members.' },
|
|
56
|
+
projectScope: { type: 'string', description: 'Project pool selector: inferred from cwd, common, all, or slug.' },
|
|
57
|
+
cwd: { type: 'string', description: 'Infer projectScope.' },
|
|
51
58
|
},
|
|
52
59
|
additionalProperties: false,
|
|
53
60
|
},
|
|
@@ -57,21 +64,23 @@ export const TOOL_DEFS = [
|
|
|
57
64
|
title: 'Search Memories',
|
|
58
65
|
public: false,
|
|
59
66
|
annotations: { title: 'Search Memories', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
60
|
-
description: 'Search past context
|
|
67
|
+
description: 'Search past context/memory. Returns root entries.',
|
|
61
68
|
inputSchema: {
|
|
62
69
|
type: 'object',
|
|
63
70
|
properties: {
|
|
64
|
-
query: { type: 'string', description: 'Search text.
|
|
65
|
-
period: { type: 'string', description: '
|
|
66
|
-
sort: { type: 'string', enum: ['date', 'importance'], description: 'date
|
|
67
|
-
category: { anyOf: [{ type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'] }, { type: 'array', items: { type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'] }, minItems: 1 }], description: '
|
|
68
|
-
limit: { type: 'number', default: 30, description: '
|
|
69
|
-
offset: { type: 'number', default: 0, description: 'Skip
|
|
70
|
-
includeMembers: { type: 'boolean', description: 'Include
|
|
71
|
-
includeRaw: { type: 'boolean', description: '
|
|
72
|
-
includeArchived: { type: 'boolean', description: '
|
|
73
|
-
|
|
74
|
-
|
|
71
|
+
query: { type: 'string', description: 'Search text.' },
|
|
72
|
+
period: { type: 'string', description: 'last, 24h/7d/30d, all, date, or range.' },
|
|
73
|
+
sort: { type: 'string', enum: ['date', 'importance'], description: 'date or importance.' },
|
|
74
|
+
category: { anyOf: [{ type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'] }, { type: 'array', items: { type: 'string', enum: ['rule','constraint','decision','fact','goal','preference','task','issue'] }, minItems: 1 }], description: 'Category filter.' },
|
|
75
|
+
limit: { type: 'number', default: 30, description: 'Max entries.' },
|
|
76
|
+
offset: { type: 'number', default: 0, description: 'Skip entries.' },
|
|
77
|
+
includeMembers: { type: 'boolean', description: 'Include members.' },
|
|
78
|
+
includeRaw: { type: 'boolean', description: 'Include raw rows.' },
|
|
79
|
+
includeArchived: { type: 'boolean', description: 'Include archived.' },
|
|
80
|
+
sessionId: { type: 'string', description: 'Scoped session id.' },
|
|
81
|
+
session_id: { type: 'string', description: 'Alias for sessionId.' },
|
|
82
|
+
projectScope: { type: 'string', description: 'Project pool selector.' },
|
|
83
|
+
cwd: { type: 'string', description: 'Infer projectScope.' },
|
|
75
84
|
},
|
|
76
85
|
required: [],
|
|
77
86
|
},
|