@sagmans/dsh-tui 0.13.0 → 0.14.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/.agents/skills/dsh-tui-dogfood/SKILL.md +18 -2
- package/.agents/skills/dsh-tui-dogfood/references/home-state.md +4 -4
- package/.agents/skills/dsh-tui-dogfood/scripts/clone-links.mjs +19 -11
- package/.agents/skills/dsh-tui-dogfood/scripts/run-plugin-from-worktree.sh +31 -9
- package/.agents/skills/dsh-tui-update-models/SKILL.md +1 -1
- package/.agents/skills/dsh-tui-update-models/references/model-wiring.md +6 -6
- package/.agents/skills/dsh-tui-update-models/scripts/dump-model-catalog.mjs +21 -13
- package/README.md +61 -23
- package/cordis.patch.yml +2 -0
- package/lib/agent/fork.d.ts +3 -1
- package/lib/agent/fork.d.ts.map +1 -1
- package/lib/agent/fork.js +2 -0
- package/lib/agent/fork.js.map +1 -1
- package/lib/agent/history.d.ts +14 -22
- package/lib/agent/history.d.ts.map +1 -1
- package/lib/agent/history.js +20 -14
- package/lib/agent/history.js.map +1 -1
- package/lib/agent/host.d.ts.map +1 -1
- package/lib/agent/host.js +6 -0
- package/lib/agent/host.js.map +1 -1
- package/lib/agent/model.d.ts +10 -8
- package/lib/agent/model.d.ts.map +1 -1
- package/lib/agent/model.js +9 -7
- package/lib/agent/model.js.map +1 -1
- package/lib/agent/present.d.ts +1 -1
- package/lib/agent/present.d.ts.map +1 -1
- package/lib/agent/present.js +1 -1
- package/lib/agent/present.js.map +1 -1
- package/lib/agent/presets.d.ts +4 -1
- package/lib/agent/presets.d.ts.map +1 -1
- package/lib/agent/presets.js +9 -2
- package/lib/agent/presets.js.map +1 -1
- package/lib/agent/projections.d.ts +8 -2
- package/lib/agent/projections.d.ts.map +1 -1
- package/lib/agent/projections.js +8 -2
- package/lib/agent/projections.js.map +1 -1
- package/lib/agent/prompt-history.d.ts +8 -48
- package/lib/agent/prompt-history.d.ts.map +1 -1
- package/lib/agent/prompt-history.js +34 -15
- package/lib/agent/prompt-history.js.map +1 -1
- package/lib/agent/status.d.ts +9 -24
- package/lib/agent/status.d.ts.map +1 -1
- package/lib/agent/status.js +7 -2
- package/lib/agent/status.js.map +1 -1
- package/lib/agent/undo.d.ts +2 -4
- package/lib/agent/undo.d.ts.map +1 -1
- package/lib/agent/undo.js +10 -5
- package/lib/agent/undo.js.map +1 -1
- package/lib/cards/composition.d.ts +7 -7
- package/lib/cards/composition.d.ts.map +1 -1
- package/lib/cards/composition.js +13 -12
- package/lib/cards/composition.js.map +1 -1
- package/lib/cards/presenter.d.ts +11 -14
- package/lib/cards/presenter.d.ts.map +1 -1
- package/lib/cards/presenter.js +40 -19
- package/lib/cards/presenter.js.map +1 -1
- package/lib/cards/preview.d.ts.map +1 -1
- package/lib/cards/preview.js +5 -1
- package/lib/cards/preview.js.map +1 -1
- package/lib/cards.d.ts +17 -23
- package/lib/cards.d.ts.map +1 -1
- package/lib/cards.js +27 -12
- package/lib/cards.js.map +1 -1
- package/lib/compat/probe.d.ts +2 -5
- package/lib/compat/probe.d.ts.map +1 -1
- package/lib/compat/probe.js +2 -2
- package/lib/compat/probe.js.map +1 -1
- package/lib/compat/section.d.ts +5 -4
- package/lib/compat/section.d.ts.map +1 -1
- package/lib/compat/section.js +4 -0
- package/lib/compat/section.js.map +1 -1
- package/lib/config.d.ts +0 -3
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +7 -1
- package/lib/config.js.map +1 -1
- package/lib/export.d.ts +5 -7
- package/lib/export.d.ts.map +1 -1
- package/lib/export.js +48 -10
- package/lib/export.js.map +1 -1
- package/lib/fold-cursor.d.ts +3 -3
- package/lib/fold-cursor.d.ts.map +1 -1
- package/lib/fold-cursor.js +5 -3
- package/lib/fold-cursor.js.map +1 -1
- package/lib/gates/question-card.d.ts +3 -38
- package/lib/gates/question-card.d.ts.map +1 -1
- package/lib/gates/question-card.js +13 -10
- package/lib/gates/question-card.js.map +1 -1
- package/lib/gates/questions.d.ts +14 -8
- package/lib/gates/questions.d.ts.map +1 -1
- package/lib/gates/questions.js +16 -12
- package/lib/gates/questions.js.map +1 -1
- package/lib/gates.d.ts +17 -25
- package/lib/gates.d.ts.map +1 -1
- package/lib/gates.js +2 -4
- package/lib/gates.js.map +1 -1
- package/lib/herdr/client.d.ts +10 -12
- package/lib/herdr/client.d.ts.map +1 -1
- package/lib/herdr/client.js +9 -8
- package/lib/herdr/client.js.map +1 -1
- package/lib/herdr/constants.d.ts +3 -2
- package/lib/herdr/constants.d.ts.map +1 -1
- package/lib/herdr/constants.js +3 -2
- package/lib/herdr/constants.js.map +1 -1
- package/lib/herdr/reporter.d.ts +4 -39
- package/lib/herdr/reporter.d.ts.map +1 -1
- package/lib/herdr/reporter.js +13 -19
- package/lib/herdr/reporter.js.map +1 -1
- package/lib/herdr/state.d.ts +4 -3
- package/lib/herdr/state.d.ts.map +1 -1
- package/lib/herdr/state.js +6 -5
- package/lib/herdr/state.js.map +1 -1
- package/lib/host/preset-files.d.ts +0 -17
- package/lib/host/preset-files.d.ts.map +1 -1
- package/lib/host/preset-files.js +7 -2
- package/lib/host/preset-files.js.map +1 -1
- package/lib/host/roster.d.ts +1 -1
- package/lib/host/roster.d.ts.map +1 -1
- package/lib/host/roster.js +3 -3
- package/lib/host/roster.js.map +1 -1
- package/lib/host/runner.d.ts +2 -5
- package/lib/host/runner.d.ts.map +1 -1
- package/lib/host/runner.js +2 -5
- package/lib/host/runner.js.map +1 -1
- package/lib/identity.d.ts +6 -3
- package/lib/identity.d.ts.map +1 -1
- package/lib/identity.js +18 -3
- package/lib/identity.js.map +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +42 -14
- package/lib/index.js.map +1 -1
- package/lib/injection.d.ts.map +1 -1
- package/lib/injection.js +1 -0
- package/lib/injection.js.map +1 -1
- package/lib/input/action-catalog.d.ts.map +1 -1
- package/lib/input/action-catalog.js +4 -0
- package/lib/input/action-catalog.js.map +1 -1
- package/lib/input/actions.d.ts +4 -3
- package/lib/input/actions.d.ts.map +1 -1
- package/lib/input/actions.js +8 -3
- package/lib/input/actions.js.map +1 -1
- package/lib/input/completion.d.ts +3 -11
- package/lib/input/completion.d.ts.map +1 -1
- package/lib/input/completion.js +4 -4
- package/lib/input/completion.js.map +1 -1
- package/lib/input/file-index.d.ts +1 -12
- package/lib/input/file-index.d.ts.map +1 -1
- package/lib/input/file-index.js +21 -17
- package/lib/input/file-index.js.map +1 -1
- package/lib/input/file-search.d.ts +4 -3
- package/lib/input/file-search.d.ts.map +1 -1
- package/lib/input/file-search.js +8 -5
- package/lib/input/file-search.js.map +1 -1
- package/lib/input/fuzzy.d.ts +6 -12
- package/lib/input/fuzzy.d.ts.map +1 -1
- package/lib/input/fuzzy.js +18 -27
- package/lib/input/fuzzy.js.map +1 -1
- package/lib/input/ghost.d.ts +5 -5
- package/lib/input/ghost.d.ts.map +1 -1
- package/lib/input/ghost.js +4 -3
- package/lib/input/ghost.js.map +1 -1
- package/lib/input/key-press.d.ts +8 -7
- package/lib/input/key-press.d.ts.map +1 -1
- package/lib/input/key-press.js +8 -6
- package/lib/input/key-press.js.map +1 -1
- package/lib/input/keymap-conflicts.d.ts +6 -6
- package/lib/input/keymap-conflicts.d.ts.map +1 -1
- package/lib/input/keymap-conflicts.js +6 -6
- package/lib/input/keymap-conflicts.js.map +1 -1
- package/lib/input/keymap.d.ts +6 -18
- package/lib/input/keymap.d.ts.map +1 -1
- package/lib/input/keymap.js +7 -10
- package/lib/input/keymap.js.map +1 -1
- package/lib/input/match.js +4 -4
- package/lib/input/match.js.map +1 -1
- package/lib/input/submission.d.ts +7 -3
- package/lib/input/submission.d.ts.map +1 -1
- package/lib/input/submission.js +2 -2
- package/lib/input/submission.js.map +1 -1
- package/lib/input/workspace-files.d.ts +1 -2
- package/lib/input/workspace-files.d.ts.map +1 -1
- package/lib/input/workspace-files.js +20 -11
- package/lib/input/workspace-files.js.map +1 -1
- package/lib/input.d.ts.map +1 -1
- package/lib/input.js +3 -1
- package/lib/input.js.map +1 -1
- package/lib/install-skills.d.ts +5 -22
- package/lib/install-skills.d.ts.map +1 -1
- package/lib/install-skills.js +18 -18
- package/lib/install-skills.js.map +1 -1
- package/lib/jobs.d.ts +10 -5
- package/lib/jobs.d.ts.map +1 -1
- package/lib/jobs.js +39 -13
- package/lib/jobs.js.map +1 -1
- package/lib/keymaps.d.ts.map +1 -1
- package/lib/keymaps.js +2 -0
- package/lib/keymaps.js.map +1 -1
- package/lib/keys-command.d.ts +1 -1
- package/lib/keys-command.d.ts.map +1 -1
- package/lib/model-list.d.ts +0 -27
- package/lib/model-list.d.ts.map +1 -1
- package/lib/model-list.js +1 -1
- package/lib/model-list.js.map +1 -1
- package/lib/moshi.d.ts +13 -0
- package/lib/moshi.d.ts.map +1 -0
- package/lib/moshi.js +130 -0
- package/lib/moshi.js.map +1 -0
- package/lib/spacing.d.ts +0 -7
- package/lib/spacing.d.ts.map +1 -1
- package/lib/spacing.js +1 -1
- package/lib/spacing.js.map +1 -1
- package/lib/startup.d.ts +1 -1
- package/lib/startup.d.ts.map +1 -1
- package/lib/startup.js +9 -1
- package/lib/startup.js.map +1 -1
- package/lib/stash/lock.d.ts +1 -37
- package/lib/stash/lock.d.ts.map +1 -1
- package/lib/stash/lock.js +41 -35
- package/lib/stash/lock.js.map +1 -1
- package/lib/stash/paths.d.ts +8 -7
- package/lib/stash/paths.d.ts.map +1 -1
- package/lib/stash/paths.js +21 -17
- package/lib/stash/paths.js.map +1 -1
- package/lib/stash/private-fs.d.ts +14 -5
- package/lib/stash/private-fs.d.ts.map +1 -1
- package/lib/stash/private-fs.js +30 -8
- package/lib/stash/private-fs.js.map +1 -1
- package/lib/stash/schema.d.ts +3 -6
- package/lib/stash/schema.d.ts.map +1 -1
- package/lib/stash/schema.js +11 -9
- package/lib/stash/schema.js.map +1 -1
- package/lib/stash/store.d.ts +9 -40
- package/lib/stash/store.d.ts.map +1 -1
- package/lib/stash/store.js +26 -24
- package/lib/stash/store.js.map +1 -1
- package/lib/stash.d.ts +7 -11
- package/lib/stash.d.ts.map +1 -1
- package/lib/stash.js +18 -11
- package/lib/stash.js.map +1 -1
- package/lib/subagents.d.ts +9 -9
- package/lib/subagents.d.ts.map +1 -1
- package/lib/subagents.js +19 -18
- package/lib/subagents.js.map +1 -1
- package/lib/surface/appearance-preferences.d.ts.map +1 -1
- package/lib/surface/appearance-preferences.js +7 -0
- package/lib/surface/appearance-preferences.js.map +1 -1
- package/lib/surface/appearance.d.ts.map +1 -1
- package/lib/surface/appearance.js +7 -2
- package/lib/surface/appearance.js.map +1 -1
- package/lib/surface/background-work.d.ts +2 -0
- package/lib/surface/background-work.d.ts.map +1 -1
- package/lib/surface/background-work.js +45 -36
- package/lib/surface/background-work.js.map +1 -1
- package/lib/surface/commands.d.ts.map +1 -1
- package/lib/surface/commands.js +17 -9
- package/lib/surface/commands.js.map +1 -1
- package/lib/surface/modal-input.d.ts +3 -0
- package/lib/surface/modal-input.d.ts.map +1 -1
- package/lib/surface/modal-input.js +4 -1
- package/lib/surface/modal-input.js.map +1 -1
- package/lib/surface/model-choice.d.ts.map +1 -1
- package/lib/surface/model-choice.js +10 -8
- package/lib/surface/model-choice.js.map +1 -1
- package/lib/surface/plugin-actions.d.ts.map +1 -1
- package/lib/surface/plugin-actions.js +4 -0
- package/lib/surface/plugin-actions.js.map +1 -1
- package/lib/surface/preset-choice.d.ts.map +1 -1
- package/lib/surface/preset-choice.js +15 -17
- package/lib/surface/preset-choice.js.map +1 -1
- package/lib/surface/prompt-input.js +1 -1
- package/lib/surface/prompt-input.js.map +1 -1
- package/lib/surface/prompt-memory.d.ts +7 -6
- package/lib/surface/prompt-memory.d.ts.map +1 -1
- package/lib/surface/prompt-memory.js +3 -3
- package/lib/surface/session-lifecycle.d.ts +7 -1
- package/lib/surface/session-lifecycle.d.ts.map +1 -1
- package/lib/surface/session-lifecycle.js +17 -12
- package/lib/surface/session-lifecycle.js.map +1 -1
- package/lib/surface/session-picker.js +1 -1
- package/lib/surface/session-picker.js.map +1 -1
- package/lib/surface/session-view.d.ts +1 -1
- package/lib/surface/session-view.d.ts.map +1 -1
- package/lib/surface/session-view.js +4 -5
- package/lib/surface/session-view.js.map +1 -1
- package/lib/surface/staged-turns.d.ts.map +1 -1
- package/lib/surface/staged-turns.js +8 -4
- package/lib/surface/staged-turns.js.map +1 -1
- package/lib/surface/terminal-lifecycle.d.ts +1 -1
- package/lib/surface/terminal-lifecycle.d.ts.map +1 -1
- package/lib/surface/terminal-lifecycle.js +8 -5
- package/lib/surface/terminal-lifecycle.js.map +1 -1
- package/lib/terminal/bell.d.ts +0 -2
- package/lib/terminal/bell.d.ts.map +1 -1
- package/lib/terminal/bell.js +2 -1
- package/lib/terminal/bell.js.map +1 -1
- package/lib/terminal/clipboard.d.ts +4 -4
- package/lib/terminal/clipboard.js +4 -4
- package/lib/terminal/external-editor.d.ts +4 -60
- package/lib/terminal/external-editor.d.ts.map +1 -1
- package/lib/terminal/external-editor.js +28 -40
- package/lib/terminal/external-editor.js.map +1 -1
- package/lib/terminal/host-writes.d.ts +7 -18
- package/lib/terminal/host-writes.d.ts.map +1 -1
- package/lib/terminal/host-writes.js +9 -14
- package/lib/terminal/host-writes.js.map +1 -1
- package/lib/terminal/input.d.ts +6 -0
- package/lib/terminal/input.d.ts.map +1 -0
- package/lib/terminal/input.js +15 -0
- package/lib/terminal/input.js.map +1 -0
- package/lib/terminal/restore.d.ts +2 -1
- package/lib/terminal/restore.d.ts.map +1 -1
- package/lib/terminal/signals.d.ts +2 -1
- package/lib/terminal/signals.d.ts.map +1 -1
- package/lib/terminal/signals.js +1 -1
- package/lib/terminal/signals.js.map +1 -1
- package/lib/terminal/title.d.ts +1 -11
- package/lib/terminal/title.d.ts.map +1 -1
- package/lib/terminal/title.js +5 -4
- package/lib/terminal/title.js.map +1 -1
- package/lib/terminal/warning-screen.d.ts +2 -0
- package/lib/terminal/warning-screen.d.ts.map +1 -1
- package/lib/terminal/warning-screen.js +21 -3
- package/lib/terminal/warning-screen.js.map +1 -1
- package/lib/terminal-text/scan.d.ts +4 -5
- package/lib/terminal-text/scan.d.ts.map +1 -1
- package/lib/terminal-text/scan.js +16 -9
- package/lib/terminal-text/scan.js.map +1 -1
- package/lib/terminal-text/sgr.d.ts +4 -3
- package/lib/terminal-text/sgr.d.ts.map +1 -1
- package/lib/terminal-text/sgr.js +9 -14
- package/lib/terminal-text/sgr.js.map +1 -1
- package/lib/terminal-text.d.ts +7 -12
- package/lib/terminal-text.d.ts.map +1 -1
- package/lib/terminal-text.js +31 -28
- package/lib/terminal-text.js.map +1 -1
- package/lib/text.d.ts +8 -14
- package/lib/text.d.ts.map +1 -1
- package/lib/text.js +14 -15
- package/lib/text.js.map +1 -1
- package/lib/theme-capability.d.ts +3 -15
- package/lib/theme-capability.d.ts.map +1 -1
- package/lib/theme-capability.js +18 -15
- package/lib/theme-capability.js.map +1 -1
- package/lib/theme-defaults.d.ts +3 -57
- package/lib/theme-defaults.d.ts.map +1 -1
- package/lib/theme-defaults.js +25 -14
- package/lib/theme-defaults.js.map +1 -1
- package/lib/theme-files.d.ts +16 -32
- package/lib/theme-files.d.ts.map +1 -1
- package/lib/theme-files.js +43 -27
- package/lib/theme-files.js.map +1 -1
- package/lib/theme-resolver.d.ts +3 -3
- package/lib/theme-resolver.d.ts.map +1 -1
- package/lib/theme-resolver.js +9 -6
- package/lib/theme-resolver.js.map +1 -1
- package/lib/theme-schema.d.ts +7 -42
- package/lib/theme-schema.d.ts.map +1 -1
- package/lib/theme-schema.js +9 -11
- package/lib/theme-schema.js.map +1 -1
- package/lib/theme-settings.d.ts +19 -10
- package/lib/theme-settings.d.ts.map +1 -1
- package/lib/theme-settings.js +23 -17
- package/lib/theme-settings.js.map +1 -1
- package/lib/theme-tokens.d.ts +6 -12
- package/lib/theme-tokens.d.ts.map +1 -1
- package/lib/theme-tokens.js +2 -2
- package/lib/theme-tokens.js.map +1 -1
- package/lib/theme.d.ts +5 -10
- package/lib/theme.d.ts.map +1 -1
- package/lib/theme.js +11 -18
- package/lib/theme.js.map +1 -1
- package/lib/todo-guard.d.ts +8 -4
- package/lib/todo-guard.d.ts.map +1 -1
- package/lib/todo-guard.js +17 -6
- package/lib/todo-guard.js.map +1 -1
- package/lib/tokens.d.ts +0 -2
- package/lib/tokens.d.ts.map +1 -1
- package/lib/tokens.js +1 -1
- package/lib/tokens.js.map +1 -1
- package/lib/tool-display.d.ts +1 -13
- package/lib/tool-display.d.ts.map +1 -1
- package/lib/tool-display.js +4 -4
- package/lib/tool-display.js.map +1 -1
- package/lib/transcript/message-content.d.ts.map +1 -1
- package/lib/transcript/message-content.js +31 -9
- package/lib/transcript/message-content.js.map +1 -1
- package/lib/transcript/tool-calls.d.ts +9 -7
- package/lib/transcript/tool-calls.d.ts.map +1 -1
- package/lib/transcript/tool-calls.js +27 -20
- package/lib/transcript/tool-calls.js.map +1 -1
- package/lib/transcript.d.ts +10 -18
- package/lib/transcript.d.ts.map +1 -1
- package/lib/transcript.js +40 -28
- package/lib/transcript.js.map +1 -1
- package/lib/ui/copy.d.ts +5 -4
- package/lib/ui/copy.d.ts.map +1 -1
- package/lib/ui/copy.js +9 -6
- package/lib/ui/copy.js.map +1 -1
- package/lib/ui/diff.d.ts +0 -30
- package/lib/ui/diff.d.ts.map +1 -1
- package/lib/ui/diff.js +16 -9
- package/lib/ui/diff.js.map +1 -1
- package/lib/ui/dock.d.ts +4 -10
- package/lib/ui/dock.d.ts.map +1 -1
- package/lib/ui/dock.js +10 -14
- package/lib/ui/dock.js.map +1 -1
- package/lib/ui/editor.d.ts +4 -3
- package/lib/ui/editor.d.ts.map +1 -1
- package/lib/ui/editor.js +2 -2
- package/lib/ui/editor.js.map +1 -1
- package/lib/ui/frame.d.ts +4 -12
- package/lib/ui/frame.d.ts.map +1 -1
- package/lib/ui/frame.js +6 -6
- package/lib/ui/frame.js.map +1 -1
- package/lib/ui/gap.d.ts +0 -4
- package/lib/ui/gap.d.ts.map +1 -1
- package/lib/ui/gap.js +4 -3
- package/lib/ui/gap.js.map +1 -1
- package/lib/ui/gate-input.d.ts +3 -3
- package/lib/ui/gate-input.d.ts.map +1 -1
- package/lib/ui/gate-input.js +9 -9
- package/lib/ui/gate-input.js.map +1 -1
- package/lib/ui/layout.d.ts +1 -8
- package/lib/ui/layout.d.ts.map +1 -1
- package/lib/ui/layout.js +5 -3
- package/lib/ui/layout.js.map +1 -1
- package/lib/ui/markdown.d.ts +3 -5
- package/lib/ui/markdown.d.ts.map +1 -1
- package/lib/ui/markdown.js +18 -7
- package/lib/ui/markdown.js.map +1 -1
- package/lib/ui/mermaid.d.ts +0 -11
- package/lib/ui/mermaid.d.ts.map +1 -1
- package/lib/ui/mermaid.js +32 -17
- package/lib/ui/mermaid.js.map +1 -1
- package/lib/ui/picker-card.d.ts +4 -8
- package/lib/ui/picker-card.d.ts.map +1 -1
- package/lib/ui/picker-card.js +17 -15
- package/lib/ui/picker-card.js.map +1 -1
- package/lib/ui/picker.d.ts +10 -17
- package/lib/ui/picker.d.ts.map +1 -1
- package/lib/ui/picker.js +14 -8
- package/lib/ui/picker.js.map +1 -1
- package/lib/ui/stash-picker.d.ts +1 -10
- package/lib/ui/stash-picker.d.ts.map +1 -1
- package/lib/ui/stash-picker.js +4 -4
- package/lib/ui/stash-picker.js.map +1 -1
- package/lib/ui/status.d.ts +2 -19
- package/lib/ui/status.d.ts.map +1 -1
- package/lib/ui/status.js +15 -17
- package/lib/ui/status.js.map +1 -1
- package/lib/ui/view/document.d.ts +4 -1
- package/lib/ui/view/document.d.ts.map +1 -1
- package/lib/ui/view/document.js +15 -6
- package/lib/ui/view/document.js.map +1 -1
- package/lib/ui/view/gate-card.d.ts +2 -0
- package/lib/ui/view/gate-card.d.ts.map +1 -1
- package/lib/ui/view/gate-card.js +12 -10
- package/lib/ui/view/gate-card.js.map +1 -1
- package/lib/ui/view/tool-card.d.ts +7 -4
- package/lib/ui/view/tool-card.d.ts.map +1 -1
- package/lib/ui/view/tool-card.js +12 -17
- package/lib/ui/view/tool-card.js.map +1 -1
- package/lib/ui/view/transcript-message.d.ts +7 -7
- package/lib/ui/view/transcript-message.d.ts.map +1 -1
- package/lib/ui/view/transcript-message.js +19 -10
- package/lib/ui/view/transcript-message.js.map +1 -1
- package/lib/ui/view.d.ts +8 -8
- package/lib/ui/view.d.ts.map +1 -1
- package/lib/ui/view.js +11 -13
- package/lib/ui/view.js.map +1 -1
- package/lib/work.d.ts +13 -10
- package/lib/work.d.ts.map +1 -1
- package/lib/work.js +30 -8
- package/lib/work.js.map +1 -1
- package/package.json +11 -7
- package/presets/cordis.patch.yml +1 -0
- package/presets/minimal.patch.yml +1 -0
- package/presets/ptc.patch.yml +1 -0
- package/presets/standard.patch.yml +1 -0
- package/themes/deepseek-blue.yaml +38 -51
- package/themes/marine-static.yaml +27 -35
- package/themes/pine-slope.yaml +13 -11
- package/themes/polar-drift.yaml +6 -0
- package/themes/violet-orbit.yaml +14 -18
- package/themes/wine-thicket.yaml +13 -13
|
@@ -22,7 +22,7 @@ import { stripControlCharacters } from "../text.js";
|
|
|
22
22
|
* distinction a surface that gives up the whole screen cares about; a reader
|
|
23
23
|
* who set only one of them still gets it.
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
const EDITOR_ENV_KEYS = ['VISUAL', 'EDITOR'];
|
|
26
26
|
/** The buffer's name, so the editor's filetype, syntax, and wrap settings see prose. */
|
|
27
27
|
const DRAFT_FILE_NAME = 'draft.md';
|
|
28
28
|
/** A directory the reader's draft is written into must not be readable by others. */
|
|
@@ -30,21 +30,20 @@ const DRAFT_DIR_MODE = 0o700;
|
|
|
30
30
|
const DRAFT_FILE_MODE = 0o600;
|
|
31
31
|
const DRAFT_DIR_PREFIX = 'dsh-tui-draft-';
|
|
32
32
|
/** A draft larger than this is left where it is rather than handed to the bar. */
|
|
33
|
-
|
|
33
|
+
const MAX_DRAFT_BYTES = 1_048_576;
|
|
34
34
|
/** The same budget as a word, so the notice reads as a size and cannot drift from it. */
|
|
35
35
|
const MAX_DRAFT_LABEL = `${Math.round(MAX_DRAFT_BYTES / 1024 / 1024)} MiB`;
|
|
36
36
|
const SECOND_MS = 1000;
|
|
37
37
|
const MINUTE_MS = 60 * SECOND_MS;
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* The timeout for requesting termination while the editor owns the terminal.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* morning, which is the line between a slow reader and a stuck process.
|
|
41
|
+
* The surface cannot read its own input during the handoff, so a timeout gives
|
|
42
|
+
* an editor that never exits a recovery path. Restoration still waits for the
|
|
43
|
+
* child after the stop request, and its saved draft is read back after exit
|
|
44
|
+
* so timing out does not itself discard saved work.
|
|
46
45
|
*/
|
|
47
|
-
|
|
46
|
+
const EDITOR_TIMEOUT_MS = 30 * MINUTE_MS;
|
|
48
47
|
const NO_EDITOR_MESSAGE = 'no editor configured: set $VISUAL or $EDITOR to open the draft in one';
|
|
49
48
|
const launchFailureMessage = (command, error) => `could not start ${command}: ${error.message}`;
|
|
50
49
|
const useFailureMessage = (error) => `could not use the edited draft: ${error instanceof Error ? error.message : 'unknown error'}`;
|
|
@@ -61,14 +60,14 @@ const SEPARATORS = new Set([' ', '\t', '\n', '\r']);
|
|
|
61
60
|
/**
|
|
62
61
|
* One configured command line as argv, or undefined when it names nothing.
|
|
63
62
|
*
|
|
64
|
-
*
|
|
65
|
-
* `
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
63
|
+
* Quote grouping and whitespace separation support commands such as
|
|
64
|
+
* `code --wait` without executing editor configuration through a shell.
|
|
65
|
+
* This is not shell parsing: backslashes stay literal, and empty quoted
|
|
66
|
+
* arguments are omitted. An unterminated quote takes the rest of the line
|
|
67
|
+
* rather than refusing the whole binding: a missing quote should not leave
|
|
68
|
+
* the reader with no editor at all.
|
|
70
69
|
*/
|
|
71
|
-
|
|
70
|
+
function parseEditorCommand(value) {
|
|
72
71
|
const argv = [];
|
|
73
72
|
let token = '';
|
|
74
73
|
let started = false;
|
|
@@ -101,9 +100,9 @@ export function parseEditorCommand(value) {
|
|
|
101
100
|
return argv.length === 0 ? undefined : argv;
|
|
102
101
|
}
|
|
103
102
|
/** The editor this environment configures, or undefined when none is usable. */
|
|
104
|
-
|
|
103
|
+
function resolveEditorCommand() {
|
|
105
104
|
for (const name of EDITOR_ENV_KEYS) {
|
|
106
|
-
const configured = env[name];
|
|
105
|
+
const configured = process.env[name];
|
|
107
106
|
if (configured === undefined)
|
|
108
107
|
continue;
|
|
109
108
|
const argv = parseEditorCommand(configured);
|
|
@@ -112,39 +111,25 @@ export function resolveEditorCommand(env = process.env) {
|
|
|
112
111
|
}
|
|
113
112
|
return undefined;
|
|
114
113
|
}
|
|
115
|
-
/**
|
|
116
|
-
* The real spawn, wrapped rather than passed.
|
|
117
|
-
*
|
|
118
|
-
* `child_process.spawn` carries overloads that do not narrow to a single
|
|
119
|
-
* callable signature, and a wrapper keeps the injectable seam honest about
|
|
120
|
-
* which call this module actually makes.
|
|
121
|
-
*/
|
|
122
|
-
const SPAWN = (file, args, options) => spawn(file, [...args], options);
|
|
123
114
|
/**
|
|
124
115
|
* The reader's editor, opened over one draft.
|
|
125
116
|
*
|
|
126
|
-
*
|
|
127
|
-
* ("keep what the bar had") rather than thrown,
|
|
128
|
-
* press with nowhere to put an error.
|
|
117
|
+
* A refused handoff or unusable draft is reported through the host and
|
|
118
|
+
* answered with `undefined` ("keep what the bar had") rather than thrown,
|
|
119
|
+
* because the caller is a key press with nowhere to put an error.
|
|
129
120
|
*/
|
|
130
121
|
export class ExternalEditor {
|
|
131
122
|
host;
|
|
132
|
-
env;
|
|
133
|
-
tempRoot;
|
|
134
|
-
spawn;
|
|
135
123
|
/** Whether a child holds the terminal; a second handoff would stop it twice. */
|
|
136
124
|
running = false;
|
|
137
|
-
constructor(host
|
|
125
|
+
constructor(host) {
|
|
138
126
|
this.host = host;
|
|
139
|
-
this.env = options.env ?? process.env;
|
|
140
|
-
this.tempRoot = options.tempRoot ?? tmpdir();
|
|
141
|
-
this.spawn = options.spawn ?? SPAWN;
|
|
142
127
|
}
|
|
143
128
|
/** Edit `text` in the reader's editor, and return what was saved, or undefined to keep the bar. */
|
|
144
129
|
async edit(text) {
|
|
145
130
|
if (this.running)
|
|
146
131
|
return undefined;
|
|
147
|
-
const argv = resolveEditorCommand(
|
|
132
|
+
const argv = resolveEditorCommand();
|
|
148
133
|
const command = argv?.[0];
|
|
149
134
|
if (argv === undefined || command === undefined) {
|
|
150
135
|
this.host.notice(NO_EDITOR_MESSAGE);
|
|
@@ -168,7 +153,7 @@ export class ExternalEditor {
|
|
|
168
153
|
return undefined;
|
|
169
154
|
}
|
|
170
155
|
try {
|
|
171
|
-
directory = await mkdtemp(join(
|
|
156
|
+
directory = await mkdtemp(join(tmpdir(), DRAFT_DIR_PREFIX));
|
|
172
157
|
// mkdtemp makes the directory owner-only on POSIX; setting it here makes
|
|
173
158
|
// the guarantee this module's rather than the platform's.
|
|
174
159
|
await chmod(directory, DRAFT_DIR_MODE);
|
|
@@ -243,9 +228,11 @@ export class ExternalEditor {
|
|
|
243
228
|
}
|
|
244
229
|
if (filled > MAX_DRAFT_BYTES)
|
|
245
230
|
return { kind: 'too-large' };
|
|
231
|
+
// Prevent edited file content from injecting terminal controls or disguising text in the live prompt.
|
|
246
232
|
return { kind: 'text', text: stripControlCharacters(buffer.subarray(0, filled).toString('utf8')) };
|
|
247
233
|
}
|
|
248
234
|
finally {
|
|
235
|
+
// Closing must not replace the accepted draft or mask the original read failure.
|
|
249
236
|
await handle.close().catch(() => undefined);
|
|
250
237
|
}
|
|
251
238
|
}
|
|
@@ -264,10 +251,11 @@ export class ExternalEditor {
|
|
|
264
251
|
*/
|
|
265
252
|
run(command, args, file) {
|
|
266
253
|
return new Promise(resolve => {
|
|
267
|
-
|
|
254
|
+
// Keep the session's project context and editor environment, not the scratch directory's context.
|
|
255
|
+
const child = spawn(command, [...args, file], {
|
|
268
256
|
stdio: 'inherit',
|
|
269
257
|
cwd: process.cwd(),
|
|
270
|
-
env:
|
|
258
|
+
env: process.env,
|
|
271
259
|
});
|
|
272
260
|
// Armed before the wait so no exit can slip past between the two, and
|
|
273
261
|
// cleared by whichever event settles it, because a pending timer would
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-editor.js","sourceRoot":"","sources":["../../src/terminal/external-editor.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,EAAE;AACF,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,+EAA+E;AAC/E,yDAAyD;AACzD,EAAE;AACF,gFAAgF;AAChF,iFAAiF;AACjF,yEAAyE;AAEzE,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEnD;;;;;;GAMG;AACH,MAAM,
|
|
1
|
+
{"version":3,"file":"external-editor.js","sourceRoot":"","sources":["../../src/terminal/external-editor.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,34 +6,25 @@
|
|
|
6
6
|
* already on screen: the damage is skipped as unchanged and stays until
|
|
7
7
|
* something forces a full repaint. Warnings are deferred separately; this is the
|
|
8
8
|
* channel a library, a stray `console.log`, or an unhandled rejection report
|
|
9
|
-
* writes to directly. Text
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* writes to directly. Text waits until the screen is given back so diagnostics
|
|
10
|
+
* do not ruin a frame. Retained writes preserve order within each stream;
|
|
11
|
+
* streams replay in target order, not in cross-stream arrival order.
|
|
12
12
|
*
|
|
13
13
|
* The surface's own drawing goes through the terminal object, which is wrapped
|
|
14
14
|
* here: a write made inside that call passes through, and everything else waits.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* one write. A write larger than the budget is therefore held whole, because
|
|
20
|
-
* this is the reader's own program's output and half a line is corruption where
|
|
21
|
-
* a bigger hold is only memory.
|
|
16
|
+
* Retained text stays within each stream's byte budget. Oversized writes are
|
|
17
|
+
* rejected whole, and older writes are evicted to make room for later ones:
|
|
18
|
+
* truncating individual writes would present incomplete diagnostics as intact.
|
|
22
19
|
*/
|
|
23
20
|
/** One stream a host may write to without asking the surface. */
|
|
24
21
|
export interface HostWritable {
|
|
25
22
|
write(...args: unknown[]): unknown;
|
|
26
23
|
}
|
|
27
24
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* Trimming counts whole writes, so this is the point the oldest write is given
|
|
31
|
-
* up at rather than a ceiling on the bytes a stream holds; the header says what
|
|
32
|
-
* the newest write does to it.
|
|
25
|
+
* A per-stream byte ceiling prevents deferred diagnostics from growing without bound.
|
|
33
26
|
*/
|
|
34
27
|
export declare const HOST_WRITE_LIMIT: number;
|
|
35
|
-
/** What a reader is told when the held text had to be trimmed. */
|
|
36
|
-
export declare const HOST_WRITE_DROPPED = "\u2026 host output dropped";
|
|
37
28
|
/** The streams a host reaches for when it writes without the surface's help. */
|
|
38
29
|
export declare const HOST_WRITE_TARGETS: readonly HostWritable[];
|
|
39
30
|
export interface HostWriteGuard {
|
|
@@ -45,8 +36,6 @@ export interface HostWriteOptions {
|
|
|
45
36
|
terminal: HostWritable;
|
|
46
37
|
/** The streams the host writes to directly. */
|
|
47
38
|
targets: readonly HostWritable[];
|
|
48
|
-
/** Per-stream hold budget; the oldest whole write is dropped past it. */
|
|
49
|
-
limit?: number;
|
|
50
39
|
}
|
|
51
40
|
export declare function holdHostWrites(options: HostWriteOptions): HostWriteGuard;
|
|
52
41
|
//# sourceMappingURL=host-writes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-writes.d.ts","sourceRoot":"","sources":["../../src/terminal/host-writes.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"host-writes.d.ts","sourceRoot":"","sources":["../../src/terminal/host-writes.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,iEAAiE;AACjE,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;CACnC;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB,QAAY,CAAA;AAKzC,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,EAAE,SAAS,YAAY,EAAqC,CAAA;AAE3F,MAAM,WAAW,cAAc;IAC7B,2EAA2E;IAC3E,OAAO,IAAI,IAAI,CAAA;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,kFAAkF;IAClF,QAAQ,EAAE,YAAY,CAAA;IACtB,+CAA+C;IAC/C,OAAO,EAAE,SAAS,YAAY,EAAE,CAAA;CACjC;AAoHD,wBAAgB,cAAc,CAAC,OAAO,EAAE,gBAAgB,GAAG,cAAc,CAwBxE"}
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
import { Buffer } from 'node:buffer';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Trimming counts whole writes, so this is the point the oldest write is given
|
|
6
|
-
* up at rather than a ceiling on the bytes a stream holds; the header says what
|
|
7
|
-
* the newest write does to it.
|
|
3
|
+
* A per-stream byte ceiling prevents deferred diagnostics from growing without bound.
|
|
8
4
|
*/
|
|
9
5
|
export const HOST_WRITE_LIMIT = 64 * 1024;
|
|
10
6
|
/** What a reader is told when the held text had to be trimmed. */
|
|
11
|
-
|
|
12
|
-
const INVALID_HOST_LIMIT = 'host write limit must be a finite non-negative integer';
|
|
7
|
+
const HOST_WRITE_DROPPED = '… host output dropped';
|
|
13
8
|
/** The streams a host reaches for when it writes without the surface's help. */
|
|
14
9
|
export const HOST_WRITE_TARGETS = [process.stdout, process.stderr];
|
|
15
10
|
/**
|
|
@@ -19,13 +14,15 @@ export const HOST_WRITE_TARGETS = [process.stdout, process.stderr];
|
|
|
19
14
|
* property, an inherited one disappears again — so a host that patched the
|
|
20
15
|
* stream before this ran keeps its own seam.
|
|
21
16
|
*/
|
|
22
|
-
function holdStream(target, held, isSurfaceWrite
|
|
17
|
+
function holdStream(target, held, isSurfaceWrite) {
|
|
23
18
|
const own = Object.getOwnPropertyDescriptor(target, 'write');
|
|
24
19
|
const original = target.write;
|
|
25
20
|
target.write = function (...args) {
|
|
26
21
|
if (isSurfaceWrite())
|
|
27
22
|
return Reflect.apply(original, this, args);
|
|
28
23
|
const [chunk, encoding, callback] = args;
|
|
24
|
+
// Retention and replay share a UTF-8 text budget so held diagnostics have a bounded replay size.
|
|
25
|
+
// This is not byte-preserving: original bytes and write encodings are not preserved.
|
|
29
26
|
const text = typeof chunk === 'string'
|
|
30
27
|
? chunk
|
|
31
28
|
: chunk instanceof Uint8Array
|
|
@@ -33,16 +30,17 @@ function holdStream(target, held, isSurfaceWrite, limit) {
|
|
|
33
30
|
: String(chunk);
|
|
34
31
|
const bytes = Buffer.byteLength(text);
|
|
35
32
|
// Cutting a write corrupts diagnostics; an oversized write must be dropped whole, not retained without bound.
|
|
36
|
-
if (bytes >
|
|
33
|
+
if (bytes > HOST_WRITE_LIMIT)
|
|
37
34
|
held.dropped += 1;
|
|
38
35
|
else if (bytes > 0) {
|
|
39
36
|
held.chunks.push(text);
|
|
40
37
|
held.bytes += bytes;
|
|
41
|
-
while (held.bytes >
|
|
38
|
+
while (held.bytes > HOST_WRITE_LIMIT) {
|
|
42
39
|
held.bytes -= Buffer.byteLength(held.chunks.shift() ?? '');
|
|
43
40
|
held.dropped += 1;
|
|
44
41
|
}
|
|
45
42
|
}
|
|
43
|
+
// Producers must not wait for a drain this hold never emits; acknowledgment is not terminal delivery.
|
|
46
44
|
if (typeof encoding === 'function')
|
|
47
45
|
encoding();
|
|
48
46
|
else if (typeof callback === 'function')
|
|
@@ -117,15 +115,12 @@ function markTerminalCalls(terminal, call) {
|
|
|
117
115
|
};
|
|
118
116
|
}
|
|
119
117
|
export function holdHostWrites(options) {
|
|
120
|
-
const limit = options.limit ?? HOST_WRITE_LIMIT;
|
|
121
|
-
if (!Number.isSafeInteger(limit) || limit < 0)
|
|
122
|
-
throw new RangeError(INVALID_HOST_LIMIT);
|
|
123
118
|
const held = new Map();
|
|
124
119
|
for (const target of options.targets)
|
|
125
120
|
held.set(target, { chunks: [], bytes: 0, dropped: 0 });
|
|
126
121
|
const surface = { depth: 0 };
|
|
127
122
|
const restoreTerminal = markTerminalCalls(options.terminal, surface);
|
|
128
|
-
const streams = options.targets.map(target => holdStream(target, held.get(target), () => surface.depth > 0
|
|
123
|
+
const streams = options.targets.map(target => holdStream(target, held.get(target), () => surface.depth > 0));
|
|
129
124
|
let active = true;
|
|
130
125
|
return {
|
|
131
126
|
release() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host-writes.js","sourceRoot":"","sources":["../../src/terminal/host-writes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"host-writes.js","sourceRoot":"","sources":["../../src/terminal/host-writes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ProcessTerminal } from '@earendil-works/pi-tui';
|
|
2
|
+
/** Normalize before viewport, modal, and editor readers so the same physical press keeps one meaning. */
|
|
3
|
+
export declare class EventSafeTerminal extends ProcessTerminal {
|
|
4
|
+
start(onInput: (data: string) => void, onResize: () => void): void;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/terminal/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAMxD,yGAAyG;AACzG,qBAAa,iBAAkB,SAAQ,eAAe;IAC3C,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;CAO5E"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ProcessTerminal } from '@earendil-works/pi-tui';
|
|
2
|
+
/** The pinned decoder recognizes SS3 F1–F4, but not their valid unmodified CSI event forms. */
|
|
3
|
+
const FUNCTION_PRESS_EVENT = /^\u001b\[1;1:[12]([PQRS])$/u;
|
|
4
|
+
const SS3_PREFIX = '\u001bO';
|
|
5
|
+
/** Normalize before viewport, modal, and editor readers so the same physical press keeps one meaning. */
|
|
6
|
+
export class EventSafeTerminal extends ProcessTerminal {
|
|
7
|
+
start(onInput, onResize) {
|
|
8
|
+
super.start(data => {
|
|
9
|
+
const match = FUNCTION_PRESS_EVENT.exec(data);
|
|
10
|
+
// Releases and modified keys retain their metadata rather than becoming unmodified presses.
|
|
11
|
+
onInput(match === null ? data : SS3_PREFIX + match[1]);
|
|
12
|
+
}, onResize);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/terminal/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD,+FAA+F;AAC/F,MAAM,oBAAoB,GAAG,6BAA6B,CAAA;AAC1D,MAAM,UAAU,GAAG,SAAS,CAAA;AAE5B,yGAAyG;AACzG,MAAM,OAAO,iBAAkB,SAAQ,eAAe;IAC3C,KAAK,CAAC,OAA+B,EAAE,QAAoB;QAClE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;YACjB,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC7C,4FAA4F;YAC5F,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QACxD,CAAC,EAAE,QAAQ,CAAC,CAAA;IACd,CAAC;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** One reversible terminal mutation. */
|
|
2
|
-
|
|
2
|
+
type RestoreHook = () => void;
|
|
3
3
|
/** Registry that guarantees every registered hook runs exactly once. */
|
|
4
4
|
export interface RestoreRegistry {
|
|
5
5
|
add(hook: RestoreHook): void;
|
|
@@ -13,4 +13,5 @@ export interface RestoreRegistry {
|
|
|
13
13
|
* a throwing hook must not strand the ones registered before it.
|
|
14
14
|
*/
|
|
15
15
|
export declare function createRestoreRegistry(): RestoreRegistry;
|
|
16
|
+
export {};
|
|
16
17
|
//# sourceMappingURL=restore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/terminal/restore.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,
|
|
1
|
+
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/terminal/restore.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,KAAK,WAAW,GAAG,MAAM,IAAI,CAAA;AAE7B,wEAAwE;AACxE,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;IAC5B,OAAO,IAAI,IAAI,CAAA;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAyBvD"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* status a shell reports for the signal.
|
|
9
9
|
*/
|
|
10
10
|
/** Signals whose default action ends the process without unwinding the surface. */
|
|
11
|
-
|
|
11
|
+
declare const TERMINATING_SIGNALS: readonly ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT"];
|
|
12
12
|
export type TerminatingSignal = (typeof TERMINATING_SIGNALS)[number];
|
|
13
13
|
/**
|
|
14
14
|
* Run a shutdown once for the first terminating signal, then leave.
|
|
@@ -21,4 +21,5 @@ export type TerminatingSignal = (typeof TERMINATING_SIGNALS)[number];
|
|
|
21
21
|
export declare function installSignalRestore(options: {
|
|
22
22
|
shutdown(code: number, signal: TerminatingSignal): void;
|
|
23
23
|
}): () => void;
|
|
24
|
+
export {};
|
|
24
25
|
//# sourceMappingURL=signals.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../src/terminal/signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,mFAAmF;AACnF,
|
|
1
|
+
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../src/terminal/signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,mFAAmF;AACnF,QAAA,MAAM,mBAAmB,qDAAsD,CAAA;AAE/E,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAA;AAKpE;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAA;CACxD,GAAG,MAAM,IAAI,CAeb"}
|
package/lib/terminal/signals.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* status a shell reports for the signal.
|
|
9
9
|
*/
|
|
10
10
|
/** Signals whose default action ends the process without unwinding the surface. */
|
|
11
|
-
|
|
11
|
+
const TERMINATING_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP', 'SIGQUIT'];
|
|
12
12
|
/** The status a shell reports for a process ended by one of those signals. */
|
|
13
13
|
const SIGNAL_EXIT = { SIGINT: 130, SIGTERM: 143, SIGHUP: 129, SIGQUIT: 131 };
|
|
14
14
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../src/terminal/signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,mFAAmF;AACnF,MAAM,
|
|
1
|
+
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../src/terminal/signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,mFAAmF;AACnF,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAU,CAAA;AAI/E,8EAA8E;AAC9E,MAAM,WAAW,GAAsC,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAA;AAE/G;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAEpC;IACC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAiC,CAAA;IACzD,MAAM,MAAM,GAAG,GAAS,EAAE;QACxB,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,QAAQ;YAAE,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QACjF,QAAQ,CAAC,KAAK,EAAE,CAAA;IAClB,CAAC,CAAA;IACD,KAAK,MAAM,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,GAAS,EAAE;YACzB,MAAM,EAAE,CAAA;YACR,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAA;QAC/C,CAAC,CAAA;QACD,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAC3B,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC/B,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/lib/terminal/title.d.ts
CHANGED
|
@@ -5,17 +5,7 @@
|
|
|
5
5
|
* surface is not on screen — in a tab bar, a window list, or a multiplexer — so
|
|
6
6
|
* it says what this session is and whether it is working.
|
|
7
7
|
*/
|
|
8
|
-
/**
|
|
9
|
-
export declare const TITLE_DIR_LIMIT = 40;
|
|
10
|
-
/**
|
|
11
|
-
* Build the title sequence.
|
|
12
|
-
*
|
|
13
|
-
* Anything a terminal would read as the end of the title is removed rather than
|
|
14
|
-
* escaped: this is a window label, and a hostile directory name has no business
|
|
15
|
-
* reaching the terminal as a control character.
|
|
16
|
-
*/
|
|
17
|
-
export declare function titleSequence(title: string): string;
|
|
18
|
-
/** The window title for a session, in the terms a tab bar can show. */
|
|
8
|
+
/** Keep the directory and its parent as session context; the suffix takes priority when tab space is tight. */
|
|
19
9
|
export declare function windowTitle(cwd: string, activity: 'ready' | 'working'): string;
|
|
20
10
|
/** Hand the title back: the shell sets its own on the next prompt. */
|
|
21
11
|
export declare const CLEAR_TITLE: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"title.d.ts","sourceRoot":"","sources":["../../src/terminal/title.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"title.d.ts","sourceRoot":"","sources":["../../src/terminal/title.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAoCH,+GAA+G;AAC/G,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAK9E;AAED,sEAAsE;AACtE,eAAO,MAAM,WAAW,QAAoB,CAAA"}
|
package/lib/terminal/title.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* it says what this session is and whether it is working.
|
|
7
7
|
*/
|
|
8
8
|
import { stripControlCharacters } from "../text.js";
|
|
9
|
+
// OSC 0 gives icon and window labels the same session context; BEL terminates this OSC payload.
|
|
9
10
|
const OSC_INTRODUCER = '\u001b]';
|
|
10
11
|
const STRING_TERMINATOR = '\u0007';
|
|
11
12
|
const TITLE_CODE = '0';
|
|
@@ -21,8 +22,8 @@ const TITLE_CODE = '0';
|
|
|
21
22
|
* neither: a tab moves the cursor inside a tab bar and a line feed splits it.
|
|
22
23
|
*/
|
|
23
24
|
const TITLE_BREAKS = /[\t\n]/gu;
|
|
24
|
-
/**
|
|
25
|
-
|
|
25
|
+
/** Keep tab labels compact without spending their directory budget on shared path prefixes. */
|
|
26
|
+
const TITLE_DIR_LIMIT = 40;
|
|
26
27
|
/**
|
|
27
28
|
* Build the title sequence.
|
|
28
29
|
*
|
|
@@ -30,10 +31,10 @@ export const TITLE_DIR_LIMIT = 40;
|
|
|
30
31
|
* escaped: this is a window label, and a hostile directory name has no business
|
|
31
32
|
* reaching the terminal as a control character.
|
|
32
33
|
*/
|
|
33
|
-
|
|
34
|
+
function titleSequence(title) {
|
|
34
35
|
return `${OSC_INTRODUCER}${TITLE_CODE};${stripControlCharacters(title).replace(TITLE_BREAKS, '')}${STRING_TERMINATOR}`;
|
|
35
36
|
}
|
|
36
|
-
/**
|
|
37
|
+
/** Keep the directory and its parent as session context; the suffix takes priority when tab space is tight. */
|
|
37
38
|
export function windowTitle(cwd, activity) {
|
|
38
39
|
const segments = cwd.split('/').filter(segment => segment !== '');
|
|
39
40
|
const tail = segments.slice(-2).join('/');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"title.js","sourceRoot":"","sources":["../../src/terminal/title.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEnD,MAAM,cAAc,GAAG,SAAS,CAAA;AAChC,MAAM,iBAAiB,GAAG,QAAQ,CAAA;AAClC,MAAM,UAAU,GAAG,GAAG,CAAA;AAEtB;;;;;;;;;;GAUG;AACH,MAAM,YAAY,GAAG,UAAU,CAAA;AAE/B
|
|
1
|
+
{"version":3,"file":"title.js","sourceRoot":"","sources":["../../src/terminal/title.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEnD,gGAAgG;AAChG,MAAM,cAAc,GAAG,SAAS,CAAA;AAChC,MAAM,iBAAiB,GAAG,QAAQ,CAAA;AAClC,MAAM,UAAU,GAAG,GAAG,CAAA;AAEtB;;;;;;;;;;GAUG;AACH,MAAM,YAAY,GAAG,UAAU,CAAA;AAE/B,+FAA+F;AAC/F,MAAM,eAAe,GAAG,EAAE,CAAA;AAE1B;;;;;;GAMG;AACH,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,GAAG,cAAc,GAAG,UAAU,IAAI,sBAAsB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,GAAG,iBAAiB,EAAE,CAAA;AACxH,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,QAA6B;IACpE,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAA;IACjE,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;IAC3F,OAAO,aAAa,CAAC,aAAa,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAC,CAAA;AAC3E,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,CAAC,EAAE,CAAC,CAAA"}
|
|
@@ -13,6 +13,8 @@ export declare class WarningSafeTui extends TuiAltScreen {
|
|
|
13
13
|
private cursorModesActive;
|
|
14
14
|
/** Initialization follows super(): only the native constructor listener needs interception. */
|
|
15
15
|
private readonly applicationListenersReady;
|
|
16
|
+
/** Fatal cleanup must preserve Node's original diagnostic and nonzero exit rather than claiming the exception. */
|
|
17
|
+
private readonly restoreAfterCrash;
|
|
16
18
|
/** Each failure episode deserves a report, but repeated retries must not flood the surface. */
|
|
17
19
|
onFrameError: ((error: unknown) => void) | undefined;
|
|
18
20
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"warning-screen.d.ts","sourceRoot":"","sources":["../../src/terminal/warning-screen.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"warning-screen.d.ts","sourceRoot":"","sources":["../../src/terminal/warning-screen.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAA;AA0G1I;;;;GAIG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,eAAe,CAA0B;IACjD,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,WAAW,CAAQ;IAC3B,OAAO,CAAC,aAAa,CAAoB;IACzC,2EAA2E;IAC3E,OAAO,CAAC,iBAAiB,CAAQ;IACjC,+FAA+F;IAC/F,OAAO,CAAC,QAAQ,CAAC,yBAAyB,CAAO;IACjD,kHAAkH;IAClH,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAMjC;IAED,+FAA+F;IAC/F,YAAY,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAA;IAEpD;;;;;OAKG;gBACS,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,mBAAmB;IAiB7D,gHAAgH;IACvG,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,MAAM,IAAI;IAUxD,KAAK,IAAI,IAAI;IAkBtB;;;;;;;;OAQG;IACM,QAAQ,IAAI,IAAI;IAgBhB,IAAI,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,IAAI;CAwC9C"}
|
|
@@ -8,6 +8,8 @@ const SAVE_CURSOR_MODES = '\x1b[?12s\x1b[?1004s';
|
|
|
8
8
|
const ENABLE_CURSOR_MODES = '\x1b[?12h\x1b[?1004h';
|
|
9
9
|
const RESTORE_CURSOR_MODES = '\x1b[?1004r\x1b[?12r';
|
|
10
10
|
const WARNING_EVENT = 'warning';
|
|
11
|
+
const FATAL_EVENT = 'uncaughtExceptionMonitor';
|
|
12
|
+
const EXIT_EVENT = 'exit';
|
|
11
13
|
const WARNING_EVENT_LIMIT = 256;
|
|
12
14
|
const ERROR_STACK_FIELD = 'stack';
|
|
13
15
|
const WARNING_TEXT_FIELDS = ['name', 'message', ERROR_STACK_FIELD, 'code', 'detail'];
|
|
@@ -106,6 +108,8 @@ function deferWarnings() {
|
|
|
106
108
|
failures.push(error);
|
|
107
109
|
}
|
|
108
110
|
}
|
|
111
|
+
// Keep the first listener error intact for stop()'s post-cleanup rethrow;
|
|
112
|
+
// later failures must not prevent remaining warnings from replaying.
|
|
109
113
|
if (failures.length > 0)
|
|
110
114
|
throw failures[0];
|
|
111
115
|
};
|
|
@@ -124,6 +128,15 @@ export class WarningSafeTui extends TuiAltScreen {
|
|
|
124
128
|
cursorModesActive = false;
|
|
125
129
|
/** Initialization follows super(): only the native constructor listener needs interception. */
|
|
126
130
|
applicationListenersReady = true;
|
|
131
|
+
/** Fatal cleanup must preserve Node's original diagnostic and nonzero exit rather than claiming the exception. */
|
|
132
|
+
restoreAfterCrash = () => {
|
|
133
|
+
try {
|
|
134
|
+
this.stop({ preserveScreen: true });
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// A restoration failure cannot replace the fatal error Node is already reporting.
|
|
138
|
+
}
|
|
139
|
+
};
|
|
127
140
|
/** Each failure episode deserves a report, but repeated retries must not flood the surface. */
|
|
128
141
|
onFrameError;
|
|
129
142
|
/**
|
|
@@ -165,6 +178,8 @@ export class WarningSafeTui extends TuiAltScreen {
|
|
|
165
178
|
try {
|
|
166
179
|
if (!this.cursorModesActive) {
|
|
167
180
|
this.cursorModesActive = true;
|
|
181
|
+
process.on(FATAL_EVENT, this.restoreAfterCrash);
|
|
182
|
+
process.on(EXIT_EVENT, this.restoreAfterCrash);
|
|
168
183
|
this.terminal.write(SAVE_CURSOR_MODES + ENABLE_CURSOR_MODES);
|
|
169
184
|
}
|
|
170
185
|
this.setShowHardwareCursor(true);
|
|
@@ -203,6 +218,9 @@ export class WarningSafeTui extends TuiAltScreen {
|
|
|
203
218
|
}
|
|
204
219
|
}
|
|
205
220
|
stop(options) {
|
|
221
|
+
// A stopped or restarting owner must leave no fatal hooks pointing at its former terminal.
|
|
222
|
+
process.removeListener(FATAL_EVENT, this.restoreAfterCrash);
|
|
223
|
+
process.removeListener(EXIT_EVENT, this.restoreAfterCrash);
|
|
206
224
|
this.highSurrogate = undefined;
|
|
207
225
|
try {
|
|
208
226
|
super.stop(options);
|
|
@@ -221,9 +239,9 @@ export class WarningSafeTui extends TuiAltScreen {
|
|
|
221
239
|
}
|
|
222
240
|
}
|
|
223
241
|
finally {
|
|
224
|
-
//
|
|
225
|
-
//
|
|
226
|
-
//
|
|
242
|
+
// Replay warnings before releasing host writes, so direct host-stream output
|
|
243
|
+
// remains buffered until cleanup releases diagnostics. Replay cannot recover
|
|
244
|
+
// the warnings' original positions among host writes.
|
|
227
245
|
const release = this.releaseWarnings;
|
|
228
246
|
this.releaseWarnings = undefined;
|
|
229
247
|
let warningFailure;
|