mixdog 0.8.1 → 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 +205 -33
- 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 +1222 -90
- 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 +2212 -446
- 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 +110 -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 +76 -28
- 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/compact.mjs +1173 -267
- package/src/runtime/agent/orchestrator/session/context-utils.mjs +199 -36
- package/src/runtime/agent/orchestrator/session/loop.mjs +840 -612
- package/src/runtime/agent/orchestrator/session/manager.mjs +1574 -459
- package/src/runtime/agent/orchestrator/session/manager.reactive-persist.test.mjs +107 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +67 -29
- 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/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.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/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 +520 -98
- 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 +28 -7
- package/src/runtime/memory/lib/memory-cycle2.mjs +4 -5
- package/src/runtime/memory/lib/memory-cycle3.mjs +2 -2
- 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 +1 -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 -95
- 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 +4788 -2151
- package/src/tui/components/AnsiText.jsx +39 -28
- package/src/tui/components/ContextPanel.jsx +14 -4
- 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 +592 -362
- 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 +8826 -2390
- 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 +2 -13
- 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
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Solo Workflow
|
|
2
|
+
|
|
3
|
+
1. Plan — Lead discusses the request with the user, forms a plan, and waits for
|
|
4
|
+
approval before execution.
|
|
5
|
+
2. Execute — Lead performs all implementation, research, debugging, review, and
|
|
6
|
+
verification work directly. Delegation to any agent is forbidden.
|
|
7
|
+
3. Verify — Lead checks the result directly, fixes issues directly, and repeats
|
|
8
|
+
until the work is clean or a blocker must be reported.
|
|
9
|
+
4. Report — Lead summarizes the final state, verification result, and any
|
|
10
|
+
remaining risk or requested next step.
|
|
11
|
+
|
|
12
|
+
Delegation rule:
|
|
13
|
+
- Do not delegate, spawn, send, or ask any agent to perform work.
|
|
14
|
+
- Ignore any available-agent section while this workflow is active; all work is
|
|
15
|
+
handled by Lead directly.
|
|
@@ -308,7 +308,12 @@ export default class Output {
|
|
|
308
308
|
// [mixdog fork] Snapshot per-row, column-indexed cell values so the App
|
|
309
309
|
// can compute word boundaries (double-click select) without retaining
|
|
310
310
|
// this Output instance, which is created fresh per render and discarded.
|
|
311
|
-
|
|
311
|
+
// ALWAYS build this, even while a selection rect is active: gating it on
|
|
312
|
+
// `!sel` froze the snapshot at the frame the first selection appeared, so
|
|
313
|
+
// every later double-click read STALE cell rows (wrong/empty words) until
|
|
314
|
+
// the selection cleared. Applying the selection above only rewrites cell
|
|
315
|
+
// `styles`, never `value`, so reading `value` here stays correct.
|
|
316
|
+
const plainRows = output.map((row) => (row || []).map((cell) => (cell?.value ?? '')));
|
|
312
317
|
const generatedOutput = output
|
|
313
318
|
.map(line => {
|
|
314
319
|
// See https://github.com/vadimdemedes/ink/pull/564#issuecomment-1637022742
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
# Lead Tool Use
|
|
2
|
-
|
|
3
|
-
- Lead owns repo-local shell work: git, build, test, run, and verification commands.
|
|
4
|
-
- Use `shell` directly for approved git/build/test/run work; do not delegate those commands to bridge agents.
|
|
5
|
-
- Use bridge agents for scoped implementation, research, review, and debugging, not for git commit/push/stash or Ship.
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'fs';
|
|
2
|
-
import { dirname, join, resolve } from 'path';
|
|
3
|
-
import { performance } from 'perf_hooks';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import { snapshotCoversFullFile } from './snapshot-helpers.mjs';
|
|
6
|
-
import { getPluginData } from '../../config.mjs';
|
|
7
|
-
import { findCachedPatchBinary } from '../patch-binary-fetcher.mjs';
|
|
8
|
-
import { runServerEdit } from '../patch.mjs';
|
|
9
|
-
|
|
10
|
-
const PLUGIN_ROOT = process.env.MIXDOG_ROOT
|
|
11
|
-
|| resolve(dirname(fileURLToPath(import.meta.url)), '../../../../..');
|
|
12
|
-
const NATIVE_EDIT_DEFAULT_BIN = join(
|
|
13
|
-
PLUGIN_ROOT,
|
|
14
|
-
'native/mixdog-patch/target/release',
|
|
15
|
-
process.platform === 'win32' ? 'mixdog-patch.exe' : 'mixdog-patch',
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
export function nativeEditMode() {
|
|
19
|
-
return String(process.env.MIXDOG_EDIT_NATIVE || 'auto').toLowerCase();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function nativeEditBinCandidate() {
|
|
23
|
-
const override = process.env.MIXDOG_EDIT_NATIVE_BIN || process.env.MIXDOG_PATCH_NATIVE_BIN;
|
|
24
|
-
if (override) return { path: override, kind: 'override' };
|
|
25
|
-
if (existsSync(NATIVE_EDIT_DEFAULT_BIN)) return { path: NATIVE_EDIT_DEFAULT_BIN, kind: 'local' };
|
|
26
|
-
const cached = findCachedPatchBinary(getPluginData());
|
|
27
|
-
if (cached) return { path: cached, kind: 'cached' };
|
|
28
|
-
return { path: NATIVE_EDIT_DEFAULT_BIN, kind: 'missing' };
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function nativeEditBinPath() {
|
|
32
|
-
return nativeEditBinCandidate().path;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function nativeEditShouldAttempt({ editSnapshot, oldStr, newStr, preloadedContent, preloadedRawBuf }) {
|
|
36
|
-
const mode = nativeEditMode();
|
|
37
|
-
if (/^(0|false|no|off|js|legacy)$/i.test(mode)) return false;
|
|
38
|
-
const forcedNative = /^(1|true|yes|on|native)$/i.test(mode);
|
|
39
|
-
const candidate = nativeEditBinCandidate();
|
|
40
|
-
if (!existsSync(candidate.path)) return false;
|
|
41
|
-
// Cached release prebuilds are guaranteed valid for apply_patch, but older
|
|
42
|
-
// manifests (currently v0.6.5 in clean CI) predate the EDIT server protocol.
|
|
43
|
-
// In auto mode, native edit is only an acceleration, so require either a
|
|
44
|
-
// local cargo build or an explicit override. If a user forces native mode,
|
|
45
|
-
// still try the cached binary and surface any protocol failure.
|
|
46
|
-
if (candidate.kind === 'cached' && !forcedNative) return false;
|
|
47
|
-
if (!snapshotCoversFullFile(editSnapshot)) return false;
|
|
48
|
-
if (preloadedContent !== null || preloadedRawBuf !== null) return false;
|
|
49
|
-
if (typeof oldStr !== 'string' || oldStr.length === 0 || typeof newStr !== 'string') return false;
|
|
50
|
-
if (forcedNative) return true;
|
|
51
|
-
// auto: the persistent server removed per-call spawn cost, so route edits to
|
|
52
|
-
// native edit2 by default (B3). Same-size edits keep the JS in-place partial
|
|
53
|
-
// write, which rewrites bytes in place instead of the whole file.
|
|
54
|
-
const oldBytes = Buffer.byteLength(oldStr, 'utf-8');
|
|
55
|
-
const newBytes = Buffer.byteLength(newStr, 'utf-8');
|
|
56
|
-
if (oldBytes === newBytes) return false;
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export async function runNativeExactEdit({ fullPath, oldStr, newStr, replaceAll, signal = null }) {
|
|
61
|
-
const forcedNative = /^(1|true|yes|on|native)$/i.test(nativeEditMode());
|
|
62
|
-
if (signal?.aborted) {
|
|
63
|
-
return { ok: false, fallback: false, error: signal.reason?.message || signal.reason || 'native edit aborted' };
|
|
64
|
-
}
|
|
65
|
-
const oldBuf = Buffer.from(oldStr, 'utf-8');
|
|
66
|
-
const newBuf = Buffer.from(newStr, 'utf-8');
|
|
67
|
-
const started = performance.now();
|
|
68
|
-
try {
|
|
69
|
-
// PARITY GUARD: the native engine MATCHES via the curly-quote fold
|
|
70
|
-
// tier but applies new_string verbatim, silently downgrading the
|
|
71
|
-
// file's typographic quotes (JS slow path preserves them via
|
|
72
|
-
// preserveQuoteTypography). When old_string carries quote-family
|
|
73
|
-
// chars — the only inputs that can land on the curly tier — probe
|
|
74
|
-
// with a dry run (persistent server, ~ms) and defer curly-tier
|
|
75
|
-
// matches to the JS editor.
|
|
76
|
-
if (/["'‘’“”]/.test(oldStr)) {
|
|
77
|
-
const probe = await runServerEdit({ fullPath, oldBuf, newBuf, replaceAll, dryRun: true, signal });
|
|
78
|
-
if (probe?.tier === 'curly') {
|
|
79
|
-
return { ok: false, fallback: true, error: 'curly-quote fold match — deferred to JS editor for typography preservation' };
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
const res = await runServerEdit({ fullPath, oldBuf, newBuf, replaceAll, signal });
|
|
83
|
-
return {
|
|
84
|
-
ok: true,
|
|
85
|
-
replacements: res.replacements,
|
|
86
|
-
readMs: res.readMs,
|
|
87
|
-
applyMs: res.applyMs,
|
|
88
|
-
writeMs: res.writeMs,
|
|
89
|
-
totalMs: res.totalMs,
|
|
90
|
-
roundtripMs: res.roundtripMs ?? (performance.now() - started),
|
|
91
|
-
stage: res.tier,
|
|
92
|
-
contentHash: res.contentHash,
|
|
93
|
-
};
|
|
94
|
-
} catch (err) {
|
|
95
|
-
if (err?.name === 'AbortError') {
|
|
96
|
-
return { ok: false, fallback: false, error: err.message };
|
|
97
|
-
}
|
|
98
|
-
const msg = String(err?.message || err);
|
|
99
|
-
// Tier misses and not-found map to a JS fallback; transport/spawn errors
|
|
100
|
-
// also fall back so a server hiccup never blocks an edit. Older cached
|
|
101
|
-
// mixdog-patch binaries (for example the v0.6.5 release prebuilds used
|
|
102
|
-
// by clean CI before a local cargo build exists) support APPLY but not
|
|
103
|
-
// the EDIT server protocol, and answer EDIT with the APPLY parser's
|
|
104
|
-
// "bad header" error. In auto mode that means "native edit unavailable",
|
|
105
|
-
// not "the edit is invalid", so fall through to the JS editor. When the
|
|
106
|
-
// user explicitly forces native mode, keep surfacing the native failure.
|
|
107
|
-
const fallback = !forcedNative && /old_string (?:not found|found \d+ times)|not valid UTF-8|no exact match|not found|server|bad header|bad edit header/i.test(msg);
|
|
108
|
-
return { ok: false, fallback, error: msg };
|
|
109
|
-
}
|
|
110
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import * as nodeBuffer from 'node:buffer';
|
|
2
|
-
import { readFileSync } from 'node:fs';
|
|
3
|
-
import { readFile as readFileAsync } from 'node:fs/promises';
|
|
4
|
-
import { decodeRawBufferForSnapshotCheck } from './builtin/snapshot-helpers.mjs';
|
|
5
|
-
|
|
6
|
-
function keyForPath(fullPath) {
|
|
7
|
-
const text = String(fullPath || '');
|
|
8
|
-
return process.platform === 'win32' ? text.toLowerCase() : text;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function isValidUtf8Buffer(buf) {
|
|
12
|
-
if (typeof nodeBuffer.isUtf8 === 'function') return nodeBuffer.isUtf8(buf);
|
|
13
|
-
if (typeof Buffer.isUtf8 === 'function') return Buffer.isUtf8(buf);
|
|
14
|
-
return Buffer.from(buf.toString('utf-8'), 'utf-8').equals(buf);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export function createMutationContentCache() {
|
|
18
|
-
const entries = new Map();
|
|
19
|
-
|
|
20
|
-
function getOrCreate(fullPath) {
|
|
21
|
-
const key = keyForPath(fullPath);
|
|
22
|
-
let entry = entries.get(key);
|
|
23
|
-
if (!entry) {
|
|
24
|
-
entry = { fullPath, rawBuf: null, content: null };
|
|
25
|
-
entries.set(key, entry);
|
|
26
|
-
}
|
|
27
|
-
return entry;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function seedBuffer(fullPath, rawBuf) {
|
|
31
|
-
const entry = getOrCreate(fullPath);
|
|
32
|
-
entry.rawBuf = rawBuf;
|
|
33
|
-
entry.content = null;
|
|
34
|
-
return entry;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function readBufferSync(fullPath) {
|
|
38
|
-
const entry = getOrCreate(fullPath);
|
|
39
|
-
if (!Buffer.isBuffer(entry.rawBuf)) entry.rawBuf = readFileSync(fullPath);
|
|
40
|
-
return entry.rawBuf;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async function readBuffer(fullPath) {
|
|
44
|
-
const entry = getOrCreate(fullPath);
|
|
45
|
-
if (!Buffer.isBuffer(entry.rawBuf)) entry.rawBuf = await readFileAsync(fullPath);
|
|
46
|
-
return entry.rawBuf;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function readTextSync(fullPath) {
|
|
50
|
-
const entry = getOrCreate(fullPath);
|
|
51
|
-
if (typeof entry.content !== 'string') {
|
|
52
|
-
entry.content = decodeRawBufferForSnapshotCheck(readBufferSync(fullPath));
|
|
53
|
-
}
|
|
54
|
-
return entry.content;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function getEntry(fullPath) {
|
|
58
|
-
return entries.get(keyForPath(fullPath)) || null;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function clear(fullPath = null) {
|
|
62
|
-
if (fullPath) entries.delete(keyForPath(fullPath));
|
|
63
|
-
else entries.clear();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return { seedBuffer, readBuffer, readBufferSync, readTextSync, getEntry, clear };
|
|
67
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
// bridge-trace-queries.mjs — SQL helpers for the bridge analytic tables.
|
|
2
|
-
// All functions accept a `db` handle from openTraceDatabase() and return
|
|
3
|
-
// plain row arrays. Query parameters are always $N — no interpolation.
|
|
4
|
-
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
// topSessionsByIteration(db, hours, limit)
|
|
7
|
-
// Sessions with the highest max_iteration seen in the last N hours.
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
export async function topSessionsByIteration(db, hours = 24, limit = 20) {
|
|
10
|
-
const { rows } = await db.query(`
|
|
11
|
-
SELECT s.session_id,
|
|
12
|
-
s.role,
|
|
13
|
-
s.model,
|
|
14
|
-
s.max_iteration,
|
|
15
|
-
s.tool_calls,
|
|
16
|
-
s.llm_calls,
|
|
17
|
-
s.total_input_tokens,
|
|
18
|
-
s.total_output_tokens,
|
|
19
|
-
s.started_at,
|
|
20
|
-
s.last_seen_at
|
|
21
|
-
FROM bridge_sessions s
|
|
22
|
-
WHERE s.last_seen_at >= now() - ($1 || ' hours')::interval
|
|
23
|
-
ORDER BY s.max_iteration DESC, s.tool_calls DESC
|
|
24
|
-
LIMIT $2
|
|
25
|
-
`, [String(hours), limit])
|
|
26
|
-
return rows
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// repeatToolCalls(db, sessionId)
|
|
31
|
-
// Tool calls whose (tool_name, md5(tool_args::text)) combo appears ≥3 times
|
|
32
|
-
// in a single session — strong signal for a tool-loop.
|
|
33
|
-
// ---------------------------------------------------------------------------
|
|
34
|
-
export async function repeatToolCalls(db, sessionId) {
|
|
35
|
-
const { rows } = await db.query(`
|
|
36
|
-
SELECT tool_name,
|
|
37
|
-
md5(tool_args::text) AS args_hash,
|
|
38
|
-
COUNT(*) AS call_count,
|
|
39
|
-
MIN(ts) AS first_at,
|
|
40
|
-
MAX(ts) AS last_at,
|
|
41
|
-
(array_agg(tool_args ORDER BY ts))[1] AS sample_args
|
|
42
|
-
FROM bridge_calls
|
|
43
|
-
WHERE session_id = $1
|
|
44
|
-
AND tool_name IS NOT NULL
|
|
45
|
-
GROUP BY tool_name, md5(tool_args::text)
|
|
46
|
-
HAVING COUNT(*) >= 3
|
|
47
|
-
ORDER BY call_count DESC, tool_name
|
|
48
|
-
`, [sessionId])
|
|
49
|
-
return rows
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// ---------------------------------------------------------------------------
|
|
53
|
-
// mixedToolPattern(db, sessionId)
|
|
54
|
-
// Sliding 3-tool window where grep and read alternate AND share a path token.
|
|
55
|
-
// Returns the centre-row of each such window.
|
|
56
|
-
// ---------------------------------------------------------------------------
|
|
57
|
-
export async function mixedToolPattern(db, sessionId) {
|
|
58
|
-
const { rows } = await db.query(`
|
|
59
|
-
WITH ordered AS (
|
|
60
|
-
SELECT id, ts, tool_name,
|
|
61
|
-
tool_args->>'path' AS path,
|
|
62
|
-
-- basename: last segment after splitting on '/'
|
|
63
|
-
regexp_replace(tool_args->>'path', '^.*/', '') AS basename,
|
|
64
|
-
LAG (tool_name, 1) OVER (ORDER BY ts, id) AS prev1,
|
|
65
|
-
LAG (tool_name, 2) OVER (ORDER BY ts, id) AS prev2,
|
|
66
|
-
LEAD(tool_name, 1) OVER (ORDER BY ts, id) AS next1,
|
|
67
|
-
LAG (tool_args->>'path', 1) OVER (ORDER BY ts, id) AS prev_path,
|
|
68
|
-
LEAD(tool_args->>'path', 1) OVER (ORDER BY ts, id) AS next_path,
|
|
69
|
-
-- basenames of neighbours
|
|
70
|
-
regexp_replace(LAG (tool_args->>'path', 1) OVER (ORDER BY ts, id), '^.*/', '') AS prev_base,
|
|
71
|
-
regexp_replace(LEAD(tool_args->>'path', 1) OVER (ORDER BY ts, id), '^.*/', '') AS next_base
|
|
72
|
-
FROM bridge_calls
|
|
73
|
-
WHERE session_id = $1
|
|
74
|
-
AND tool_name IN ('grep','read')
|
|
75
|
-
)
|
|
76
|
-
SELECT id, ts, tool_name, path
|
|
77
|
-
FROM ordered
|
|
78
|
-
WHERE -- true 3-tool alternation: centre plus BOTH flanking neighbours (window size = 3)
|
|
79
|
-
(
|
|
80
|
-
(tool_name = 'read' AND prev1 = 'grep' AND next1 = 'grep')
|
|
81
|
-
OR (tool_name = 'grep' AND prev1 = 'read' AND next1 = 'read')
|
|
82
|
-
)
|
|
83
|
-
-- path-token sharing: basename or exact path matches across all 3 slots
|
|
84
|
-
AND basename IS NOT NULL
|
|
85
|
-
AND (
|
|
86
|
-
-- exact path shared with both neighbours
|
|
87
|
-
(path = prev_path AND path = next_path)
|
|
88
|
-
-- or basename shared with both neighbours
|
|
89
|
-
OR (basename = prev_base AND basename = next_base)
|
|
90
|
-
-- or mixed: exact on one side, basename on other
|
|
91
|
-
OR (path = prev_path AND basename = next_base)
|
|
92
|
-
OR (path = next_path AND basename = prev_base)
|
|
93
|
-
)
|
|
94
|
-
ORDER BY ts, id
|
|
95
|
-
`, [sessionId])
|
|
96
|
-
return rows
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// ---------------------------------------------------------------------------
|
|
100
|
-
// tokenUsageByRole(db, hours)
|
|
101
|
-
// Sum of input/output tokens grouped by role over the last N hours.
|
|
102
|
-
// ---------------------------------------------------------------------------
|
|
103
|
-
export async function tokenUsageByRole(db, hours = 24) {
|
|
104
|
-
const { rows } = await db.query(`
|
|
105
|
-
SELECT s.role,
|
|
106
|
-
COUNT(DISTINCT l.session_id) AS sessions,
|
|
107
|
-
SUM(l.input_tokens) AS total_input,
|
|
108
|
-
SUM(l.output_tokens) AS total_output,
|
|
109
|
-
SUM(l.cached_tokens) AS total_cached,
|
|
110
|
-
SUM(l.cache_write_tokens) AS total_cache_write,
|
|
111
|
-
AVG(l.input_tokens)::int AS avg_input_per_call,
|
|
112
|
-
AVG(l.output_tokens)::int AS avg_output_per_call
|
|
113
|
-
FROM bridge_llm l
|
|
114
|
-
JOIN bridge_sessions s USING (session_id)
|
|
115
|
-
WHERE l.ts >= now() - ($1 || ' hours')::interval
|
|
116
|
-
GROUP BY s.role
|
|
117
|
-
ORDER BY total_input DESC NULLS LAST
|
|
118
|
-
`, [String(hours)])
|
|
119
|
-
return rows
|
|
120
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* pid-cleanup.mjs — Orphaned bridge CLI process cleanup.
|
|
3
|
-
* Used by server.mjs on startup and shutdown.
|
|
4
|
-
*/
|
|
5
|
-
import fs from 'fs'
|
|
6
|
-
import path from 'path'
|
|
7
|
-
import os from 'os'
|
|
8
|
-
|
|
9
|
-
const PID_DIR = path.join(os.tmpdir(), 'mixdog-bridge')
|
|
10
|
-
const PID_FILE = path.join(PID_DIR, 'bridge-pids.json')
|
|
11
|
-
|
|
12
|
-
export function cleanupOrphanedPids() {
|
|
13
|
-
let killed = 0
|
|
14
|
-
try {
|
|
15
|
-
const pids = JSON.parse(fs.readFileSync(PID_FILE, 'utf8'))
|
|
16
|
-
for (const pid of pids) {
|
|
17
|
-
try {
|
|
18
|
-
process.kill(pid, 0)
|
|
19
|
-
process.kill(pid, 'SIGTERM')
|
|
20
|
-
process.stderr.write(`[bridge-cleanup] killed orphaned PID ${pid}\n`)
|
|
21
|
-
killed++
|
|
22
|
-
} catch {}
|
|
23
|
-
}
|
|
24
|
-
fs.writeFileSync(PID_FILE, JSON.stringify([]))
|
|
25
|
-
} catch {}
|
|
26
|
-
return killed
|
|
27
|
-
}
|