mixdog 0.8.1 → 0.9.1
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 +34 -28
- 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 -29
- package/src/lib/plugin-paths.cjs +1 -7
- package/src/lib/rules-builder.cjs +242 -98
- package/src/lib/text-utils.cjs +1 -1
- package/src/mixdog-session-runtime.mjs +2211 -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 +108 -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 +380 -268
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +131 -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 +203 -71
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +512 -312
- package/src/runtime/agent/orchestrator/providers/openai-oauth.mjs +343 -518
- 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 +289 -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 +35 -8
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +19 -8
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +10 -53
- 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 +149 -51
- package/src/runtime/channels/lib/cli-worker-host.mjs +1 -8
- package/src/runtime/channels/lib/config.mjs +0 -1
- package/src/runtime/channels/lib/drop-trace.mjs +1 -1
- package/src/runtime/channels/lib/executor.mjs +0 -3
- package/src/runtime/channels/lib/memory-client.mjs +0 -38
- package/src/runtime/channels/lib/output-forwarder.mjs +1 -8
- package/src/runtime/channels/lib/runtime-paths.mjs +0 -6
- package/src/runtime/channels/lib/scheduler.mjs +18 -14
- package/src/runtime/channels/lib/session-discovery.mjs +3 -6
- package/src/runtime/channels/lib/tool-format.mjs +0 -1
- package/src/runtime/channels/lib/transcript-discovery.mjs +4 -12
- package/src/runtime/channels/lib/webhook.mjs +1 -1
- package/src/runtime/channels/tool-defs.mjs +29 -29
- package/src/runtime/lib/keychain-cjs.cjs +0 -1
- package/src/runtime/memory/data/runtime-manifest.json +6 -7
- package/src/runtime/memory/index.mjs +519 -118
- 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/llm-worker-host.mjs +0 -4
- 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 -2
- 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 +80 -21
- package/src/runtime/memory/lib/session-ingest.mjs +196 -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 +104 -473
- package/src/runtime/search/lib/config.mjs +0 -4
- package/src/runtime/search/lib/state.mjs +1 -15
- package/src/runtime/search/lib/web-tools.mjs +44 -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 +139 -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 +1 -78
- package/src/standalone/usage-dashboard.mjs +96 -8
- package/src/tui/App.jsx +4800 -2140
- 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 +428 -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 +597 -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 +499 -0
- package/src/tui/components/tool-output-format.test.mjs +312 -0
- package/src/tui/dist/index.mjs +9192 -2399
- 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 +671 -69
- package/src/tui/markdown/format-token.test.mjs +312 -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 +756 -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 +1 -620
- 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/ink.js +54 -8
- 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/hooks/lib/permission-rules.cjs +0 -170
- package/src/hooks/lib/settings-loader.cjs +0 -112
- package/src/lib/hook-pipe-path.cjs +0 -10
- 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/channels/lib/hook-pipe-server.mjs +0 -671
- 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
package/src/tui/figures.mjs
CHANGED
|
@@ -1,50 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* figures.mjs — TUI glyph constants.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Unicode markers are used heavily in the TUI. Each glyph is declared with its
|
|
5
|
+
* `\uXXXX` escape (encoding-safe across editors/transports) and the literal
|
|
6
|
+
* glyph + usage is kept in the trailing comment for readability.
|
|
6
7
|
*/
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export const
|
|
11
|
-
export const
|
|
12
|
-
export const
|
|
13
|
-
export const
|
|
14
|
-
export const EFFORT_LOW = '○';
|
|
15
|
-
export const EFFORT_MEDIUM = '◐';
|
|
16
|
-
export const EFFORT_HIGH = '●';
|
|
17
|
-
export const EFFORT_MAX = '◉';
|
|
9
|
+
// Turn marker. \u23fa (⏺) aligns better but is poorly supported off macOS, so
|
|
10
|
+
// other platforms use \u25cf (●).
|
|
11
|
+
export const BLACK_CIRCLE = process.platform === 'darwin' ? '\u23fa' : '\u25cf'; // ⏺ / ● - turn marker
|
|
12
|
+
export const BULLET_OPERATOR = '\u00b7'; // · - inline separator
|
|
13
|
+
export const UP_ARROW = '\u2191'; // ↑ - history/scroll up
|
|
14
|
+
export const DOWN_ARROW = '\u2193'; // ↓ - history/scroll down
|
|
18
15
|
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
// Tool-result tree gutter. \u2514 (└, BOX DRAWINGS LIGHT UP AND RIGHT) renders
|
|
17
|
+
// in virtually every monospace font; the previous \u23bf (bracket extension)
|
|
18
|
+
// had no glyph in common terminal fonts (Cascadia/Consolas) and fell back to a
|
|
19
|
+
// literal "L", breaking the result tree alignment.
|
|
20
|
+
export const RESULT_GUTTER_GLYPH = '\u2514'; // └ - tool-result tree gutter
|
|
21
|
+
export const RESULT_GUTTER_CONT_GLYPH = '\u2502'; // │ - tool-result continuation rail
|
|
22
22
|
|
|
23
|
-
//
|
|
24
|
-
export const RESULT_GUTTER_GLYPH = '⎿';
|
|
23
|
+
export const BLOCKQUOTE_BAR = '\u258e'; // ▎ - blockquote line prefix
|
|
25
24
|
|
|
26
|
-
//
|
|
27
|
-
export const REFRESH_ARROW = '↻';
|
|
28
|
-
export const CHANNEL_ARROW = '←';
|
|
29
|
-
export const INJECTED_ARROW = '→';
|
|
30
|
-
export const FORK_GLYPH = '⑂';
|
|
31
|
-
|
|
32
|
-
// Review status indicators
|
|
33
|
-
export const DIAMOND_OPEN = '◇';
|
|
34
|
-
export const DIAMOND_FILLED = '◆';
|
|
35
|
-
export const REFERENCE_MARK = '※';
|
|
36
|
-
|
|
37
|
-
// Issue flag indicator
|
|
38
|
-
export const FLAG_ICON = '⚑';
|
|
39
|
-
|
|
40
|
-
// Blockquote indicator
|
|
41
|
-
export const BLOCKQUOTE_BAR = '▎';
|
|
42
|
-
export const HEAVY_HORIZONTAL = '━';
|
|
43
|
-
|
|
44
|
-
// The "therefore" sign — Claude Code's collapsed-thinking prefix (∴ Thinking).
|
|
45
|
-
export const THEREFORE = '∴';
|
|
25
|
+
export const THEREFORE = '\u2234'; // ∴ - collapsed-thinking prefix (∴ Thinking)
|
|
46
26
|
// Turn-complete marker — kept distinct from live-thinking's therefore sign.
|
|
47
|
-
export const TURN_DONE_MARKER = '
|
|
27
|
+
export const TURN_DONE_MARKER = '\u25c8'; // ◈ - turn-complete marker
|
|
48
28
|
|
|
49
|
-
//
|
|
50
|
-
|
|
29
|
+
// Horizontal rule fill — BOX DRAWINGS LIGHT HORIZONTAL. Repeated to span the
|
|
30
|
+
// available content width for a clean full-width `---` rule.
|
|
31
|
+
export const HR_LINE = '\u2500'; // ─ - markdown horizontal rule
|
package/src/tui/index.jsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* src/tui/index.jsx — entry that mounts the React/ink TUI.
|
|
3
|
-
*
|
|
4
|
-
* Creates the engine session (runs OUR agentLoop outside React) and ink-renders
|
|
1
|
+
/**
|
|
2
|
+
* src/tui/index.jsx — entry that mounts the React/ink TUI.
|
|
3
|
+
*
|
|
4
|
+
* Creates the engine session (runs OUR agentLoop outside React) and ink-renders
|
|
5
5
|
* <App store={...}/>. Resolves when the app exits (/exit or /quit).
|
|
6
|
-
*/
|
|
6
|
+
*/
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import { render } from 'ink';
|
|
9
9
|
import { createWriteStream, mkdirSync } from 'node:fs';
|
|
@@ -13,8 +13,10 @@ import { performance } from 'node:perf_hooks';
|
|
|
13
13
|
import { App } from './App.jsx';
|
|
14
14
|
import { createEngineSession } from './engine.mjs';
|
|
15
15
|
import { installProcessSignalCleanup } from '../runtime/shared/process-shutdown.mjs';
|
|
16
|
-
|
|
16
|
+
import { emitTerminalBackground, loadThemeSettingFromConfig, theme } from './theme.mjs';
|
|
17
|
+
|
|
17
18
|
const TERMINAL_MODE_RESET = '\x1b[?1006l\x1b[?1005l\x1b[?1015l\x1b[?1003l\x1b[?1002l\x1b[?1000l\x1b[?2004l\x1b[?25h';
|
|
19
|
+
const TERMINAL_OSC_RESET_BG = '\x1b]111\x07';
|
|
18
20
|
const TERMINAL_MODE_RESET_HIDDEN_CURSOR = TERMINAL_MODE_RESET.replace('\x1b[?25h', '\x1b[?25l');
|
|
19
21
|
const MOUSE_TRACKING_ON = '\x1b[?1000h\x1b[?1002h\x1b[?1006h';
|
|
20
22
|
const BOOT_PROFILE_ENABLED = /^(1|true|yes|on)$/i.test(String(process.env.MIXDOG_BOOT_PROFILE || ''));
|
|
@@ -23,12 +25,43 @@ const EXIT_WAIT_TIMEOUT_MS = positiveIntEnv('MIXDOG_TUI_EXIT_WAIT_MS', 2500);
|
|
|
23
25
|
const EXIT_HARD_DELAY_MS = positiveIntEnv('MIXDOG_TUI_HARD_EXIT_DELAY_MS', 500);
|
|
24
26
|
const EXIT_HARD_ENABLED = !/^(0|false|no|off)$/i.test(String(process.env.MIXDOG_TUI_HARD_EXIT || '1'));
|
|
25
27
|
const EXIT_DEBUG_ENABLED = /^(1|true|yes|on)$/i.test(String(process.env.MIXDOG_TUI_EXIT_DEBUG || ''));
|
|
28
|
+
const PERF_ENABLED = /^(1|true|yes|on)$/i.test(String(process.env.MIXDOG_TUI_PERF || ''));
|
|
26
29
|
|
|
27
30
|
function positiveIntEnv(name, fallback) {
|
|
28
31
|
const value = Number(process.env[name]);
|
|
29
32
|
return Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
30
33
|
}
|
|
31
34
|
|
|
35
|
+
// Lightweight render-frame profiler. Forked ink calls options.onRender with the
|
|
36
|
+
// per-frame render() wall time (renderNodeToOutput serialization). We aggregate
|
|
37
|
+
// and emit a rolling summary every PERF_REPORT_EVERY frames so typing latency
|
|
38
|
+
// can be measured without flooding output. Entirely no-op unless
|
|
39
|
+
// MIXDOG_TUI_PERF=1, so it costs nothing in normal runs.
|
|
40
|
+
const PERF_REPORT_EVERY = positiveIntEnv('MIXDOG_TUI_PERF_EVERY', 60);
|
|
41
|
+
function makeRenderProfiler() {
|
|
42
|
+
if (!PERF_ENABLED) return undefined;
|
|
43
|
+
let count = 0;
|
|
44
|
+
let sum = 0;
|
|
45
|
+
let max = 0;
|
|
46
|
+
let slow = 0;
|
|
47
|
+
return ({ renderTime } = {}) => {
|
|
48
|
+
const ms = Number(renderTime) || 0;
|
|
49
|
+
count += 1;
|
|
50
|
+
sum += ms;
|
|
51
|
+
if (ms > max) max = ms;
|
|
52
|
+
if (ms >= 16) slow += 1;
|
|
53
|
+
if (count >= PERF_REPORT_EVERY) {
|
|
54
|
+
const avg = sum / count;
|
|
55
|
+
try {
|
|
56
|
+
process.stderr.write(
|
|
57
|
+
`[mixdog-perf] frames=${count} avg=${avg.toFixed(2)}ms max=${max.toFixed(2)}ms slow16+=${slow}\n`,
|
|
58
|
+
);
|
|
59
|
+
} catch { /* ignore */ }
|
|
60
|
+
count = 0; sum = 0; max = 0; slow = 0;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
32
65
|
function bootProfile(event, fields = {}) {
|
|
33
66
|
if (!BOOT_PROFILE_ENABLED) return;
|
|
34
67
|
const elapsedMs = performance.now() - BOOT_PROFILE_START;
|
|
@@ -92,7 +125,7 @@ function scheduleHardExit(code = 0) {
|
|
|
92
125
|
if (!EXIT_HARD_ENABLED) return;
|
|
93
126
|
const timer = setTimeout(() => {
|
|
94
127
|
dumpActiveHandles('hard-exit');
|
|
95
|
-
try { process.stdout.write(TERMINAL_MODE_RESET); } catch { /* ignore */ }
|
|
128
|
+
try { process.stdout.write(`${TERMINAL_MODE_RESET}${TERMINAL_OSC_RESET_BG}`); } catch { /* ignore */ }
|
|
96
129
|
process.exit(code);
|
|
97
130
|
}, EXIT_HARD_DELAY_MS);
|
|
98
131
|
timer.unref?.();
|
|
@@ -158,27 +191,48 @@ export async function runTui({ provider, model, toolMode } = {}) {
|
|
|
158
191
|
}
|
|
159
192
|
|
|
160
193
|
const restoreStderr = installTuiStderrGuard();
|
|
194
|
+
const restorePrimedInput = () => {}; // stdin raw mode is owned by Ink's useInput effects
|
|
195
|
+
let restored = false;
|
|
196
|
+
const restoreTerminal = () => {
|
|
197
|
+
if (restored) return;
|
|
198
|
+
restored = true;
|
|
199
|
+
restorePrimedInput();
|
|
200
|
+
try { process.stdout.write(`${TERMINAL_MODE_RESET}\x1b[0 q\x1b[?1049l${TERMINAL_MODE_RESET}${TERMINAL_OSC_RESET_BG}`); } catch { /* ignore */ }
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Enter the alternate screen buffer before session/runtime boot so no stale
|
|
204
|
+
// shell rows are visible while the statusline/TUI data warms up. The first
|
|
205
|
+
// real Ink frame may still arrive after createEngineSession(), but the user
|
|
206
|
+
// sees a clean fullscreen surface immediately instead of the previous terminal
|
|
207
|
+
// contents bleeding through the bottom status area.
|
|
208
|
+
process.stdout.write(`${TERMINAL_MODE_RESET_HIDDEN_CURSOR}\x1b[?1049h${TERMINAL_MODE_RESET_HIDDEN_CURSOR}\x1b[2J\x1b[H`);
|
|
209
|
+
|
|
210
|
+
// Use a blinking BAR cursor (DECSCUSR 5) — a thin caret behind the text, not a
|
|
211
|
+
// fat block. PromptInput parks this hardware cursor at the insertion point via
|
|
212
|
+
// useCursor; the terminal also anchors IME composition to it.
|
|
213
|
+
process.stdout.write('\x1b[5 q'); // blinking bar
|
|
214
|
+
|
|
215
|
+
process.on('exit', restoreTerminal);
|
|
216
|
+
|
|
217
|
+
// Apply the persisted UI theme (ui.theme in mixdog-config.json) before the
|
|
218
|
+
// first React frame so the whole tree paints in the chosen palette. Unknown
|
|
219
|
+
// or missing values leave the default Mixdog dark palette in place; a failed
|
|
220
|
+
// config read never blocks boot.
|
|
221
|
+
try { await loadThemeSettingFromConfig(); } catch { /* default theme stays */ }
|
|
222
|
+
emitTerminalBackground(theme.background);
|
|
223
|
+
|
|
161
224
|
let store;
|
|
162
225
|
try {
|
|
163
226
|
store = await createEngineSession({ provider, model, toolMode });
|
|
164
227
|
bootProfile('store:ready', { ms: (performance.now() - startedAt).toFixed(1) });
|
|
165
228
|
} catch (error) {
|
|
229
|
+
restoreTerminal();
|
|
230
|
+
try { process.off('exit', restoreTerminal); } catch { /* ignore */ }
|
|
166
231
|
restoreStderr();
|
|
167
232
|
process.stderr.write(`mixdog: ${error?.message || error}\n`);
|
|
168
233
|
return 1;
|
|
169
234
|
}
|
|
170
|
-
|
|
171
|
-
// Enter the alternate screen buffer for a true fullscreen UI: the input bar
|
|
172
|
-
// pins to the physical bottom (App uses height={rows}) and, on exit, the
|
|
173
|
-
// shell's original screen is restored untouched. \x1b[?1049h enters alt
|
|
174
|
-
// screen; then clear it and home the cursor so we start from a clean top.
|
|
175
|
-
process.stdout.write(`${TERMINAL_MODE_RESET_HIDDEN_CURSOR}\x1b[?1049h${TERMINAL_MODE_RESET_HIDDEN_CURSOR}\x1b[2J\x1b[H`);
|
|
176
|
-
|
|
177
|
-
// Use a blinking BAR cursor (DECSCUSR 5) — a thin caret behind the text, not a
|
|
178
|
-
// fat block. PromptInput parks this hardware cursor at the insertion point via
|
|
179
|
-
// useCursor; the terminal also anchors IME composition to it.
|
|
180
|
-
process.stdout.write('\x1b[5 q'); // blinking bar
|
|
181
|
-
|
|
235
|
+
|
|
182
236
|
// Keep mouse handling app-owned by default: native terminal selections are
|
|
183
237
|
// cleared by the fullscreen redraws that happen while a turn streams. Users
|
|
184
238
|
// who prefer their terminal's native mouse behavior can opt out with
|
|
@@ -187,16 +241,6 @@ export async function runTui({ provider, model, toolMode } = {}) {
|
|
|
187
241
|
if (mouseTracking) {
|
|
188
242
|
process.stdout.write(MOUSE_TRACKING_ON);
|
|
189
243
|
}
|
|
190
|
-
const restorePrimedInput = () => {}; // stdin raw mode is owned by Ink's useInput effects
|
|
191
|
-
|
|
192
|
-
let restored = false;
|
|
193
|
-
const restoreTerminal = () => {
|
|
194
|
-
if (restored) return;
|
|
195
|
-
restored = true;
|
|
196
|
-
restorePrimedInput();
|
|
197
|
-
try { process.stdout.write(`${TERMINAL_MODE_RESET}\x1b[0 q\x1b[?1049l${TERMINAL_MODE_RESET}`); } catch { /* ignore */ }
|
|
198
|
-
};
|
|
199
|
-
process.on('exit', restoreTerminal);
|
|
200
244
|
let storeDisposed = false;
|
|
201
245
|
const disposeStoreOnce = async (reason = 'cli-react-exit') => {
|
|
202
246
|
if (storeDisposed) return;
|
|
@@ -215,12 +259,12 @@ export async function runTui({ provider, model, toolMode } = {}) {
|
|
|
215
259
|
restoreStderr();
|
|
216
260
|
},
|
|
217
261
|
});
|
|
218
|
-
|
|
262
|
+
|
|
219
263
|
// exitOnCtrlC:false — App handles Ctrl+C as an interrupt/line-clear so Ink
|
|
220
264
|
// does not exit abruptly. Explicit exits go through /exit or /quit so teardown
|
|
221
265
|
// still restores the cursor, mouse mode, and alternate screen cleanly.
|
|
222
266
|
try {
|
|
223
|
-
const instance = render(<App store={store} />, { exitOnCtrlC: false, maxFps: 120 });
|
|
267
|
+
const instance = render(<App store={store} />, { exitOnCtrlC: false, maxFps: 120, onRender: makeRenderProfiler() });
|
|
224
268
|
bootProfile('render:mounted', { ms: (performance.now() - startedAt).toFixed(1) });
|
|
225
269
|
const { waitUntilExit } = instance;
|
|
226
270
|
// [mixdog fork] Hand the ink renderer's drag-selection setter to the store so
|
|
@@ -154,6 +154,31 @@ export function caretPosition(text, offset, width) {
|
|
|
154
154
|
return { row, col };
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
// Inverse of caretPosition: given a visual (row, col) cell inside the wrapped
|
|
158
|
+
// content of `width` columns, return the character offset whose caret sits
|
|
159
|
+
// closest to that cell. Used to map a mouse click/drag cell in the prompt box
|
|
160
|
+
// to an edit offset so mouse selection can drive selectionAnchor + cursor.
|
|
161
|
+
export function offsetAtCell(text, row, col, width) {
|
|
162
|
+
const w = safeWidth(width);
|
|
163
|
+
const value = String(text || '');
|
|
164
|
+
const positions = boundaryPositions(value, w);
|
|
165
|
+
if (positions.length === 0) return 0;
|
|
166
|
+
let best = positions[0];
|
|
167
|
+
let bestScore = Infinity;
|
|
168
|
+
for (const position of positions) {
|
|
169
|
+
const rowDist = Math.abs(position.row - row);
|
|
170
|
+
const colDist = Math.abs(position.col - col);
|
|
171
|
+
// Row distance dominates so a click never jumps to a different visual line;
|
|
172
|
+
// within the matched row the nearest column wins.
|
|
173
|
+
const score = rowDist * 100000 + colDist;
|
|
174
|
+
if (score < bestScore) {
|
|
175
|
+
best = position;
|
|
176
|
+
bestScore = score;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return best.offset;
|
|
180
|
+
}
|
|
181
|
+
|
|
157
182
|
function boundaryPositions(text, width) {
|
|
158
183
|
const value = String(text || '');
|
|
159
184
|
const offsets = [0];
|