mixdog 0.9.19 → 0.9.21
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/LICENSE +21 -0
- package/README.md +100 -34
- package/package.json +3 -2
- package/scripts/build-tui.mjs +6 -0
- package/scripts/hook-bus-test.mjs +8 -0
- package/scripts/log-writer-guard-smoke.mjs +131 -0
- package/scripts/reactive-compact-persist-smoke.mjs +22 -6
- package/scripts/recall-bench-cases.json +0 -1
- package/scripts/recall-quality-cases.json +1 -2
- package/scripts/session-ingest-compaction-smoke.mjs +241 -0
- package/scripts/tool-smoke.mjs +150 -45
- package/src/defaults/skills/setup/SKILL.md +327 -0
- package/src/help.mjs +2 -5
- package/src/lib/mixdog-debug.cjs +13 -0
- package/src/mixdog-session-runtime.mjs +7 -3328
- package/src/runtime/agent/orchestrator/context/collect.mjs +33 -9
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +34 -2
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth.mjs +67 -10
- package/src/runtime/agent/orchestrator/providers/openai-compat.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +40 -3
- package/src/runtime/agent/orchestrator/providers/openai-ws.mjs +73 -3
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +663 -0
- package/src/runtime/agent/orchestrator/session/compact/engine.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +153 -0
- package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +49 -0
- package/src/runtime/agent/orchestrator/session/loop/stored-tool-args.mjs +9 -1
- package/src/runtime/agent/orchestrator/session/loop.mjs +8 -1860
- package/src/runtime/agent/orchestrator/session/manager/agent-runtime-singleton.mjs +29 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +686 -0
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +60 -12
- package/src/runtime/agent/orchestrator/session/manager/env-utils.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +159 -0
- package/src/runtime/agent/orchestrator/session/manager/message-sanitize.mjs +143 -0
- package/src/runtime/agent/orchestrator/session/manager/prefetch-bridge.mjs +268 -0
- package/src/runtime/agent/orchestrator/session/manager/provider-cache-key.mjs +22 -0
- package/src/runtime/agent/orchestrator/session/manager/runtime-loaders.mjs +26 -0
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +124 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +258 -0
- package/src/runtime/agent/orchestrator/session/manager/session-errors.mjs +20 -0
- package/src/runtime/agent/orchestrator/session/manager/session-id.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +475 -0
- package/src/runtime/agent/orchestrator/session/manager/session-lock.mjs +23 -0
- package/src/runtime/agent/orchestrator/session/manager.mjs +88 -2285
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +440 -0
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +153 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +642 -0
- package/src/runtime/agent/orchestrator/tools/bash-session.mjs +23 -3
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-paths.mjs +108 -2
- package/src/runtime/agent/orchestrator/tools/builtin/shell-job-process.mjs +15 -3
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +7 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-runtime.mjs +24 -2
- package/src/runtime/agent/orchestrator/tools/patch/orchestrator.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/patch/parsing.mjs +72 -8
- package/src/runtime/agent/orchestrator/tools/shell-policy-danger-target.mjs +5 -1
- package/src/runtime/channels/index.mjs +6 -2183
- package/src/runtime/channels/lib/inbound-handler.mjs +328 -0
- package/src/runtime/channels/lib/interaction-handlers.mjs +260 -0
- package/src/runtime/channels/lib/network-retry.mjs +23 -0
- package/src/runtime/channels/lib/owned-runtime.mjs +627 -0
- package/src/runtime/channels/lib/runtime-paths.mjs +20 -9
- package/src/runtime/channels/lib/transcript-binding.mjs +336 -0
- package/src/runtime/channels/lib/voice-runtime-fetcher.mjs +39 -2
- package/src/runtime/channels/lib/worker-bootstrap.mjs +97 -0
- package/src/runtime/channels/lib/worker-ipc.mjs +201 -0
- package/src/runtime/channels/lib/worker-main.mjs +777 -0
- package/src/runtime/memory/index.mjs +163 -1725
- package/src/runtime/memory/lib/embedding-provider.mjs +4 -2
- package/src/runtime/memory/lib/embedding-worker.mjs +47 -6
- package/src/runtime/memory/lib/http-router.mjs +811 -0
- package/src/runtime/memory/lib/memory-action-handlers.mjs +901 -0
- package/src/runtime/memory/lib/memory-cycle2-gate.mjs +6 -0
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +46 -9
- package/src/runtime/memory/lib/memory-cycle2.mjs +87 -11
- package/src/runtime/memory/lib/memory-embed.mjs +28 -7
- package/src/runtime/memory/lib/memory-recall-store.mjs +4 -4
- package/src/runtime/memory/lib/memory.mjs +39 -0
- package/src/runtime/memory/lib/query-handlers.mjs +2 -2
- package/src/runtime/memory/lib/session-ingest-runtime.mjs +401 -0
- package/src/runtime/shared/atomic-file.mjs +138 -80
- package/src/runtime/shared/child-guardian.mjs +61 -3
- package/src/session-runtime/boot-profile.mjs +36 -0
- package/src/session-runtime/channel-config-api.mjs +70 -0
- package/src/session-runtime/context-status.mjs +181 -0
- package/src/session-runtime/env.mjs +17 -0
- package/src/session-runtime/lifecycle-api.mjs +242 -0
- package/src/session-runtime/model-route-api.mjs +198 -0
- package/src/session-runtime/provider-auth-api.mjs +135 -0
- package/src/session-runtime/resource-api.mjs +282 -0
- package/src/session-runtime/runtime-core.mjs +2104 -0
- package/src/session-runtime/session-turn-api.mjs +274 -0
- package/src/session-runtime/tool-catalog.mjs +18 -264
- package/src/session-runtime/tool-defs.mjs +2 -2
- package/src/session-runtime/workflow-agents-api.mjs +238 -0
- package/src/standalone/agent-tool.mjs +2 -2
- package/src/standalone/channel-worker.mjs +67 -7
- package/src/standalone/folder-dialog.mjs +4 -1
- package/src/standalone/memory-runtime-proxy.mjs +154 -17
- package/src/standalone/seeds.mjs +28 -1
- package/src/tui/App.jsx +40 -28
- package/src/tui/app/core-memory-picker.mjs +1 -1
- package/src/tui/app/doctor.mjs +175 -0
- package/src/tui/app/slash-commands.mjs +1 -0
- package/src/tui/app/slash-dispatch.mjs +9 -0
- package/src/tui/app/use-mouse-input.mjs +6 -0
- package/src/tui/app/use-transcript-scroll.mjs +77 -3
- package/src/tui/dist/index.mjs +2851 -2162
- package/src/tui/engine/context-state.mjs +145 -0
- package/src/tui/engine/prompt-history.mjs +27 -0
- package/src/tui/engine/session-api-ext.mjs +478 -0
- package/src/tui/engine/session-api.mjs +564 -0
- package/src/tui/engine/session-flow.mjs +485 -0
- package/src/tui/engine/turn.mjs +1078 -0
- package/src/tui/engine.mjs +68 -2620
- package/src/tui/index.jsx +7 -0
- package/vendor/ink/build/ink.js +16 -1
- package/vendor/ink/build/output.js +30 -4
- package/vendor/ink/build/render.js +5 -0
- package/src/workflows/sequential/WORKFLOW.md +0 -51
package/src/tui/index.jsx
CHANGED
|
@@ -17,6 +17,7 @@ import { touchUiHeartbeat } from '../runtime/channels/lib/runtime-paths.mjs';
|
|
|
17
17
|
import { emitTerminalBackground, loadThemeSettingFromConfig, theme } from './theme.mjs';
|
|
18
18
|
import { POP_KITTY, DISABLE_MODIFY_OTHER_KEYS } from './keyboard-protocol.mjs';
|
|
19
19
|
import { displayWidth } from './display-width.mjs';
|
|
20
|
+
import { rotateBoundedLog, PLUGIN_LOG_MAX_BYTES, PLUGIN_LOG_KEEP_BYTES } from '../lib/mixdog-debug.cjs';
|
|
20
21
|
|
|
21
22
|
const TERMINAL_MODE_RESET = '\x1b[?1006l\x1b[?1005l\x1b[?1015l\x1b[?1003l\x1b[?1002l\x1b[?1000l\x1b[?2004l\x1b[?25h';
|
|
22
23
|
const TERMINAL_OSC_RESET_BG = '\x1b]111\x07';
|
|
@@ -326,6 +327,9 @@ function installTuiStderrGuard() {
|
|
|
326
327
|
const originalWrite = process.stderr.write.bind(process.stderr);
|
|
327
328
|
const logPath = resolveTuiStderrLogPath();
|
|
328
329
|
try { mkdirSync(dirname(logPath), { recursive: true }); } catch { /* ignore */ }
|
|
330
|
+
// One-shot bound before the append stream opens: this TUI process never
|
|
331
|
+
// passes through the channels-worker rotation path, so cap it writer-side.
|
|
332
|
+
rotateBoundedLog(logPath, PLUGIN_LOG_MAX_BYTES, PLUGIN_LOG_KEEP_BYTES);
|
|
329
333
|
let logStream = null;
|
|
330
334
|
try {
|
|
331
335
|
logStream = createWriteStream(logPath, { flags: 'a' });
|
|
@@ -543,6 +547,9 @@ export async function runTui({ provider, model, toolMode, remote, forceOnboardin
|
|
|
543
547
|
if (mouseTracking && typeof instance.getLineRectAt === 'function') {
|
|
544
548
|
store.getLineRectAt = instance.getLineRectAt;
|
|
545
549
|
}
|
|
550
|
+
if (mouseTracking && typeof instance.getSelectionRows === 'function') {
|
|
551
|
+
store.getRenderSelectionRows = instance.getSelectionRows;
|
|
552
|
+
}
|
|
546
553
|
await waitUntilExit();
|
|
547
554
|
} finally {
|
|
548
555
|
stopPerfProbe();
|
package/vendor/ink/build/ink.js
CHANGED
|
@@ -221,6 +221,10 @@ export default class Ink {
|
|
|
221
221
|
// [mixdog fork] column-indexed cell values per grid row from the last frame,
|
|
222
222
|
// used by getWordRectAt() to compute word boundaries for double-click select.
|
|
223
223
|
lastPlainRows = null;
|
|
224
|
+
// [mixdog fork] per-row {y, text} selection harvest from the last frame,
|
|
225
|
+
// refreshed every render; read back via getSelectionRows() so the app can
|
|
226
|
+
// stitch selections taller than the viewport. null when no selection.
|
|
227
|
+
lastSelectionRows = null;
|
|
224
228
|
constructor(options) {
|
|
225
229
|
autoBind(this);
|
|
226
230
|
this.options = options;
|
|
@@ -558,6 +562,13 @@ export default class Ink {
|
|
|
558
562
|
return null;
|
|
559
563
|
return { x1: 0, y1: y, x2, y2: y };
|
|
560
564
|
};
|
|
565
|
+
// [mixdog fork] Return the per-row {y, text} selection harvest cached from the
|
|
566
|
+
// last frame, or null when there is no selection. y is the absolute screen row
|
|
567
|
+
// of the last frame; text is trailing-space-trimmed (partial first/last rows
|
|
568
|
+
// respect x1/x2). Lets the app stitch selections taller than the viewport.
|
|
569
|
+
getSelectionRows = () => {
|
|
570
|
+
return this.lastSelectionRows;
|
|
571
|
+
};
|
|
561
572
|
restoreLastOutput = () => {
|
|
562
573
|
if (!this.interactive) {
|
|
563
574
|
return;
|
|
@@ -604,7 +615,7 @@ export default class Ink {
|
|
|
604
615
|
this.isRendering = true;
|
|
605
616
|
try {
|
|
606
617
|
const startTime = performance.now();
|
|
607
|
-
const { output, outputHeight, staticOutput, cursor, selectedText, plainRows } = render(this.rootNode, this.isScreenReaderEnabled, this.selectionRect);
|
|
618
|
+
const { output, outputHeight, staticOutput, cursor, selectedText, plainRows, selectionRows } = render(this.rootNode, this.isScreenReaderEnabled, this.selectionRect);
|
|
608
619
|
// [mixdog fork] Cache the text under the current selection rect so the App
|
|
609
620
|
// can read it back on drag-release to copy it to the OS clipboard.
|
|
610
621
|
if (selectedText !== undefined) {
|
|
@@ -614,6 +625,10 @@ export default class Ink {
|
|
|
614
625
|
if (plainRows !== undefined) {
|
|
615
626
|
this.lastPlainRows = plainRows ?? null;
|
|
616
627
|
}
|
|
628
|
+
// [mixdog fork] Cache per-row selection harvest for getSelectionRows().
|
|
629
|
+
if (selectionRows !== undefined) {
|
|
630
|
+
this.lastSelectionRows = selectionRows ?? null;
|
|
631
|
+
}
|
|
617
632
|
this.options.onRender?.({ renderTime: performance.now() - startTime });
|
|
618
633
|
// [mixdog fork] Drive the hardware cursor from the anchored input node's
|
|
619
634
|
// real render-time position, computed fresh every frame. This replaces
|
|
@@ -262,6 +262,12 @@ export default class Output {
|
|
|
262
262
|
// dim text, and status colors do not bleed through.
|
|
263
263
|
const sel = this.selection;
|
|
264
264
|
let selectedText = null;
|
|
265
|
+
// [mixdog fork] Per-row selection harvest ({y, text}) exposed via the
|
|
266
|
+
// instance getSelectionRows() so the app can stitch selections taller
|
|
267
|
+
// than the viewport. y is the absolute screen row of the last frame;
|
|
268
|
+
// text is trailing-space-trimmed and partial first/last rows respect
|
|
269
|
+
// x1/x2. Null when there is no selection (mirrors selectedText).
|
|
270
|
+
let selectionRows = null;
|
|
265
271
|
// [mixdog fork] noSelect exclusion (claude-code skips gutter / line-number
|
|
266
272
|
// / diff-sigil cells from both highlight and copy via screen.noSelect):
|
|
267
273
|
// mixdog's cell model has NO noSelect marker — the Output grid stores only
|
|
@@ -303,9 +309,16 @@ export default class Output {
|
|
|
303
309
|
const y2 = Math.min(this.height - 1, clipY2, linear ? end.y : Math.max(sel.y1, sel.y2));
|
|
304
310
|
const lineMode = linear && y1 !== y2;
|
|
305
311
|
const selRows = captureSelectedText ? [] : null;
|
|
312
|
+
// [mixdog fork] selRowObjs is built UNCONDITIONALLY whenever a
|
|
313
|
+
// selection rect exists, independent of captureSelectedText: a
|
|
314
|
+
// capture-disabled drag (rect.captureText === false) still needs a
|
|
315
|
+
// per-row harvest so getSelectionRows() can stitch tall selections.
|
|
316
|
+
// Only selectedText/selRows honor the captureSelectedText gate.
|
|
317
|
+
const selRowObjs = [];
|
|
306
318
|
for (let y = y1; y <= y2; y++) {
|
|
307
319
|
const row = output[y];
|
|
308
320
|
if (!row) {
|
|
321
|
+
selRowObjs.push({ y, text: '' });
|
|
309
322
|
if (captureSelectedText) {
|
|
310
323
|
selRows.push('');
|
|
311
324
|
}
|
|
@@ -338,9 +351,9 @@ export default class Output {
|
|
|
338
351
|
}
|
|
339
352
|
// Collect the visible glyph. Wide-char trailing placeholders
|
|
340
353
|
// carry value '' and contribute nothing, which is correct.
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
354
|
+
// Always accumulated so the unconditional selRowObjs harvest
|
|
355
|
+
// has row text even when captureSelectedText is false.
|
|
356
|
+
rowText += cell.value ?? '';
|
|
344
357
|
if (contentStart === -1 || x < contentStart || x > contentEnd) {
|
|
345
358
|
continue;
|
|
346
359
|
}
|
|
@@ -357,10 +370,22 @@ export default class Output {
|
|
|
357
370
|
};
|
|
358
371
|
}
|
|
359
372
|
// Trailing spaces in a selected row are padding, not content.
|
|
373
|
+
const trimmedRowText = rowText.replace(/\s+$/u, '');
|
|
374
|
+
selRowObjs.push({ y, text: trimmedRowText });
|
|
360
375
|
if (captureSelectedText) {
|
|
361
|
-
selRows.push(
|
|
376
|
+
selRows.push(trimmedRowText);
|
|
362
377
|
}
|
|
363
378
|
}
|
|
379
|
+
// [mixdog fork] Outer-trim the per-row harvest (same rule as
|
|
380
|
+
// selectedText below) but UNCONDITIONALLY, keeping the absolute row
|
|
381
|
+
// index per entry so the app can stitch rows across the viewport.
|
|
382
|
+
while (selRowObjs.length > 0 && selRowObjs[0].text.trim() === '') {
|
|
383
|
+
selRowObjs.shift();
|
|
384
|
+
}
|
|
385
|
+
while (selRowObjs.length > 0 && selRowObjs[selRowObjs.length - 1].text.trim() === '') {
|
|
386
|
+
selRowObjs.pop();
|
|
387
|
+
}
|
|
388
|
+
selectionRows = selRowObjs;
|
|
364
389
|
if (captureSelectedText) {
|
|
365
390
|
// Blank edge rows come from selecting through padded alt-screen
|
|
366
391
|
// space around rendered content. Native terminal selection does
|
|
@@ -433,6 +458,7 @@ export default class Output {
|
|
|
433
458
|
cursor: this.cursor, // [mixdog fork] absolute cursor cell or null
|
|
434
459
|
selectedText, // [mixdog fork] text inside the selection rect, or null
|
|
435
460
|
plainRows, // [mixdog fork] column-indexed cell values per row for word lookup
|
|
461
|
+
selectionRows, // [mixdog fork] per-row {y, text} selection harvest, or null
|
|
436
462
|
};
|
|
437
463
|
}
|
|
438
464
|
}
|
|
@@ -45,6 +45,11 @@ const render = (node, options) => {
|
|
|
45
45
|
// line select. Symmetric to getWordRectAt; index.jsx wires it into the
|
|
46
46
|
// store as store.getLineRectAt.
|
|
47
47
|
getLineRectAt: (y) => instance.getLineRectAt(y),
|
|
48
|
+
// [mixdog fork] read the per-row {y, text} selection harvest from the last
|
|
49
|
+
// frame (or null when no selection); index.jsx wires it into the store as
|
|
50
|
+
// store.getRenderSelectionRows so the app can stitch selections taller
|
|
51
|
+
// than the viewport.
|
|
52
|
+
getSelectionRows: () => instance.getSelectionRows(),
|
|
48
53
|
};
|
|
49
54
|
};
|
|
50
55
|
export default render;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
id: sequential
|
|
3
|
-
name: Sequential
|
|
4
|
-
description: "Sequential workflow — delegates 1:1 with no fan-out; one agent at a time."
|
|
5
|
-
agents: worker, heavy-worker, reviewer, debugger, maintainer
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Sequential Workflow
|
|
9
|
-
|
|
10
|
-
Unlike Default, which fans out independent scopes in parallel, this mode runs
|
|
11
|
-
with no fan-out: it delegates one scope at a time, 1:1, and only moves to the
|
|
12
|
-
next after the current one completes.
|
|
13
|
-
|
|
14
|
-
Lead supervises: delegates, coordinates, judges, decides. Route by complexity:
|
|
15
|
-
- Lead handles directly: simple 1–2 step work, plus coordination, pre-planning,
|
|
16
|
-
config changes, and final git deployment.
|
|
17
|
-
- Worker: implementation that takes several steps.
|
|
18
|
-
- Heavy Worker: high-complexity, multi-step implementation.
|
|
19
|
-
- Reviewer: verify implementation scopes (diff, regressions, missing checks).
|
|
20
|
-
- Debugger: deploy for very high complexity, or when root-causing has already
|
|
21
|
-
failed at least once.
|
|
22
|
-
|
|
23
|
-
1. Plan — discuss the request with the user, form a plan, wait for approval.
|
|
24
|
-
Only an explicit go-ahead is approval; diagnosis agreement is not. When
|
|
25
|
-
ambiguous, restate the plan and ask before executing.
|
|
26
|
-
2. Delegate — split into ordered scopes and hand off ONE AT A TIME.
|
|
27
|
-
- NO PARALLEL, NO FAN-OUT. Even when scopes are independent, spawn exactly
|
|
28
|
-
one agent per turn; never multiple in the same turn. Wait for the current
|
|
29
|
-
scope's completion notification before spawning the next (1:1 sequential).
|
|
30
|
-
- SEQUENTIAL within a single complex scope — split into ordered steps rather
|
|
31
|
-
than one shot, with a build/test-green gate between steps.
|
|
32
|
-
- Write briefs per the Lead brief contract (token-optimized labeled
|
|
33
|
-
fragments).
|
|
34
|
-
- After spawning an async agent, END THE TURN — do not poll, guess, or start
|
|
35
|
-
dependent or subsequent work until the completion notification resumes
|
|
36
|
-
you. Then wait and continue automatically.
|
|
37
|
-
3. Review — after each implementation scope completes, pair one reviewer 1:1
|
|
38
|
-
with that scope (spawned on its own turn, not batched); never defer the
|
|
39
|
-
reviewer call — wait for its result. Fact-check the agent response and
|
|
40
|
-
cross-check implementation and review results yourself before acting. Send
|
|
41
|
-
fixes back to the original scope and loop verify -> fix -> re-verify until
|
|
42
|
-
clean. Skip review only for simple, low-risk tasks. If the user asks for
|
|
43
|
-
debugging, or a bug survives 2+ fix cycles, have the debugger investigate
|
|
44
|
-
first instead of another fix round.
|
|
45
|
-
4. Report — synthesize results (outcome + key evidence; never forward raw agent
|
|
46
|
-
output), state the final state, and ask whether to ship/deploy when
|
|
47
|
-
relevant. Only after user feedback with no issues prepare
|
|
48
|
-
deploy/build/commit.
|
|
49
|
-
|
|
50
|
-
On any major change or direction shift mid-work, pause and re-consult the user
|
|
51
|
-
before continuing.
|