@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
|
@@ -4,6 +4,21 @@ description: "Use when a dsh plugin checkout must be tested against a real profi
|
|
|
4
4
|
---
|
|
5
5
|
# Dogfood a dsh plugin checkout
|
|
6
6
|
|
|
7
|
+
For a dsh-tui checkout, run `pnpm verify` after development. It runs golden
|
|
8
|
+
frames and all free dogfood scenarios automatically. `pnpm dogfood` starts the
|
|
9
|
+
installed Harness with the base bundle and worktree in credential-free scratch
|
|
10
|
+
homes. In a Herdr-managed caller, the same free gate also runs real native-pane workflows in an owned disposable named session.
|
|
11
|
+
Without that prerequisite, Herdr evidence remains `environment-not-run`; portable PTY checks still run.
|
|
12
|
+
When tmux is installed, the free gate also verifies its private server and actual restoration.
|
|
13
|
+
Native controllers do not launch the caller's configured shell or source its startup files.
|
|
14
|
+
Read `FEATURES.md` in the checkout for scope and evidence rules.
|
|
15
|
+
|
|
16
|
+
Paid live-model use requires an explicit human request. List scenarios with
|
|
17
|
+
`pnpm dogfood:paid --list`, then select one with `--scenario`, `--home`,
|
|
18
|
+
`--provider`, and `--model`. Use a cloned profile for its credentials and model
|
|
19
|
+
adapter. Never submit a model prompt automatically, even a short smoke prompt.
|
|
20
|
+
|
|
21
|
+
|
|
7
22
|
A fresh `DSH_HOME` misses the installed bundles, profile patch, settings, and themes.
|
|
8
23
|
A run against the real home writes real sessions and state. Clone the source
|
|
9
24
|
home and relink only the plugin under test inside the clone.
|
|
@@ -23,8 +38,9 @@ runs `pnpm run build` only when the checkout declares a build script. It adds
|
|
|
23
38
|
the bundle once if absent from the cloned profile, updates only its dependency,
|
|
24
39
|
restores local links from `link:` specifications, and launches
|
|
25
40
|
`dsh --profile tui` by default. For this TUI, the packaged helper checks
|
|
26
|
-
the launcher against
|
|
27
|
-
|
|
41
|
+
the launcher against `dsh.compatibility.dshReleases` in the checkout’s
|
|
42
|
+
`package.json` before cloning, not against the declared version range. This
|
|
43
|
+
checkout lists only installed `dsh 0.2.0-rc.2` as verified for PTY tests. Never
|
|
28
44
|
substitute `pnpm dsh` or a `--dsh` path from a Harness source checkout: that
|
|
29
45
|
host may migrate the cloned `settings.yaml`. The legacy
|
|
30
46
|
`scripts/dogfood/run-tui-from-worktree.sh` remains available in dsh-tui and
|
|
@@ -8,7 +8,7 @@ profile. It gives the operational detail behind [../SKILL.md](../SKILL.md).
|
|
|
8
8
|
| Entry | Kind | What reads or writes it |
|
|
9
9
|
| --- | --- | --- |
|
|
10
10
|
| `.credentials.yaml` | secret | the provider layer, at start-up; read-only |
|
|
11
|
-
| `settings.yaml`, `settings.yaml.imported` | config |
|
|
11
|
+
| `settings.yaml`, `settings.yaml.imported` | legacy config | On verified `0.2.0-rc.2`, settings migration renames the file before attempting a one-time import into profile entries. Rejected sections remain in `.imported`; neither file is the live TUI configuration. |
|
|
12
12
|
| `themes/` | data | created and watched at start-up; saving a file changes the live surface |
|
|
13
13
|
| `prompt-history.json` | data | the editor's history recall; appended as prompts are sent |
|
|
14
14
|
| `tui-stash/` | data | the parked-draft bank, one file per session, behind a lock |
|
|
@@ -20,9 +20,9 @@ profile. It gives the operational detail behind [../SKILL.md](../SKILL.md).
|
|
|
20
20
|
|
|
21
21
|
## Home state versus profile state
|
|
22
22
|
|
|
23
|
-
Credentials,
|
|
24
|
-
|
|
25
|
-
overlay belong to the **profile**: a new profile name starts from the base plus
|
|
23
|
+
Credentials, themes, history, the stash, storages, and sessions belong to the
|
|
24
|
+
**home**: every profile in it shares them. On verified `0.2.0-rc.2`, live settings,
|
|
25
|
+
the bundle list, and the patch overlay belong to the **profile**: a new profile name starts from the base plus
|
|
26
26
|
whatever is added to it, and inherits none of another profile's bundles or
|
|
27
27
|
patches. That is the trap behind "test it in a profile named after the feature" —
|
|
28
28
|
the run is compositionally thinner than the developer's own while still writing
|
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Link policy for the dogfood clone.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* is state the run may write, and a link out of the clone would let that write
|
|
12
|
-
* reach the developer's own home. Refusing is the safe answer there.
|
|
5
|
+
* Protect mutable home state from writes reaching the source home. Package
|
|
6
|
+
* links remain external for dependency loading; writes through them are not
|
|
7
|
+
* isolated. Other links must stay inside the clone. The instruction files below
|
|
8
|
+
* are only read, so their external targets can be copied into the clone instead
|
|
9
|
+
* of blocking a run. Refuse escaping links for other home entries so writes
|
|
10
|
+
* cannot follow them into the developer's own home.
|
|
13
11
|
*
|
|
14
12
|
* Usage: clone-links.mjs check|materialize <home> <source>
|
|
15
13
|
*/
|
|
@@ -25,8 +23,9 @@ import { pathToFileURL } from 'node:url'
|
|
|
25
23
|
export const INSTRUCTION_ENTRIES = new Set(['AGENTS.md', 'CLAUDE.md'])
|
|
26
24
|
|
|
27
25
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
26
|
+
* Package entries may resolve externally so cloned profiles can load installed
|
|
27
|
+
* packages or checkouts, except source-home targets. Other retained links must stay
|
|
28
|
+
* inside the clone to keep home-state writes local.
|
|
30
29
|
*/
|
|
31
30
|
export const packageEntry = (parts) => parts[0] === 'profiles' && (
|
|
32
31
|
parts[1] === 'node_modules' && parts.length > 2 ||
|
|
@@ -34,8 +33,14 @@ export const packageEntry = (parts) => parts[0] === 'profiles' && (
|
|
|
34
33
|
parts[2] === '.dsh-module-fallback' && parts[3] === 'node_modules' && parts.length > 4
|
|
35
34
|
)
|
|
36
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Boundary checks require physical absolute paths; this lexical check cannot resolve aliases.
|
|
38
|
+
* The separator prevents sibling names sharing a prefix from passing the home boundary.
|
|
39
|
+
*/
|
|
37
40
|
export const inside = (root, file) => file === root || file.startsWith(root + path.sep)
|
|
38
41
|
|
|
42
|
+
// Keep the read-only exception scoped to home instruction entries; matching names
|
|
43
|
+
// inside mutable state do not establish read-only use.
|
|
39
44
|
const instruction = (home, file) => {
|
|
40
45
|
const parts = path.relative(home, file).split(path.sep)
|
|
41
46
|
return parts.length === 1 && INSTRUCTION_ENTRIES.has(parts[0])
|
|
@@ -59,7 +64,6 @@ export function destination(file) {
|
|
|
59
64
|
const entries = (root) => fs.readdirSync(root, { withFileTypes: true })
|
|
60
65
|
const partsOf = (home, file) => path.relative(home, file).split(path.sep)
|
|
61
66
|
|
|
62
|
-
/** Every reason the clone cannot be run as a sandbox, in the order they are met. */
|
|
63
67
|
export function problems(home, source) {
|
|
64
68
|
const found = []
|
|
65
69
|
const visit = (dir) => {
|
|
@@ -73,6 +77,8 @@ export function problems(home, source) {
|
|
|
73
77
|
} else if (entry.isDirectory()) {
|
|
74
78
|
visit(file)
|
|
75
79
|
} else if (entry.isFile() && !packageEntry(parts) && fs.lstatSync(file).nlink > 1) {
|
|
80
|
+
// Hardlink names share writable contents; the link count cannot prove every name stays inside the clone.
|
|
81
|
+
// Reject non-package hardlinks conservatively rather than risk writes reaching another home.
|
|
76
82
|
found.push('unsafe cloned hardlink outside package modules: ' + file)
|
|
77
83
|
}
|
|
78
84
|
}
|
|
@@ -93,6 +99,8 @@ export function materialize(home) {
|
|
|
93
99
|
const target = destination(path.resolve(dir, fs.readlinkSync(file)))
|
|
94
100
|
if (inside(home, target)) continue
|
|
95
101
|
if (!fs.existsSync(target)) {
|
|
102
|
+
// No instruction content exists to copy; dropping the external link lets
|
|
103
|
+
// boundary validation proceed without retaining an escape path.
|
|
96
104
|
fs.rmSync(file)
|
|
97
105
|
console.log('materialize: dropped dangling link ' + path.relative(home, file))
|
|
98
106
|
report.dropped += 1
|
|
@@ -4,8 +4,12 @@ set -euo pipefail
|
|
|
4
4
|
|
|
5
5
|
name="$(basename "${BASH_SOURCE[0]}")"
|
|
6
6
|
TUI_PACKAGE_NAME='@sagmans/dsh-tui'
|
|
7
|
+
ISOLATED_ENV_PREFIXES=('HERDR_' 'DSH_TUI_MOSHI_')
|
|
8
|
+
CLEAN_PREVIEW_PREFIX='would remove'
|
|
7
9
|
# The link policy is shared with the validator, so both read one rule set.
|
|
8
10
|
helper_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
11
|
+
# Default to the caller checkout so this packaged helper is not tied to its install location;
|
|
12
|
+
# the legacy wrapper overrides it to remain anchored when invoked from another directory.
|
|
9
13
|
default_repo="${DSH_DOGFOOD_DEFAULT_REPO:-$PWD}"
|
|
10
14
|
default_repo="$(cd "$default_repo" && pwd -P)"
|
|
11
15
|
|
|
@@ -54,6 +58,7 @@ EOF
|
|
|
54
58
|
|
|
55
59
|
target=""
|
|
56
60
|
home=""
|
|
61
|
+
# Agent sessions may set DSH_HOME to scratch state, not the developer home to clone.
|
|
57
62
|
source_home="$HOME/.dsh"
|
|
58
63
|
profile="tui"
|
|
59
64
|
dsh_bin="${DSH_BIN:-}"
|
|
@@ -93,6 +98,8 @@ if [[ -n "$source_home" ]]; then source_home="${source_home/#\~/$HOME}"; fi
|
|
|
93
98
|
|
|
94
99
|
# --- the repository's worktrees ---------------------------------------------
|
|
95
100
|
|
|
101
|
+
# Git discovery is best-effort so an unavailable registry does not block the
|
|
102
|
+
# sibling-directory fallback; the chosen directory still needs a plugin manifest.
|
|
96
103
|
worktree_lines() {
|
|
97
104
|
git -C "$default_repo" worktree list --porcelain 2>/dev/null || true
|
|
98
105
|
}
|
|
@@ -143,6 +150,8 @@ resolve_target() {
|
|
|
143
150
|
local hit sibling
|
|
144
151
|
hit="$(resolve_by_name "$target")"
|
|
145
152
|
if [[ -z "$hit" ]]; then
|
|
153
|
+
# Anchor sibling lookup to the selected repository, not the caller's cwd,
|
|
154
|
+
# so neighboring plugin checkouts need not appear in its Git worktree registry.
|
|
146
155
|
sibling="$(cd "$default_repo/.." 2>/dev/null && pwd -P)/$target"
|
|
147
156
|
if [[ -d "$sibling" ]]; then hit="$sibling"; fi
|
|
148
157
|
fi
|
|
@@ -195,6 +204,7 @@ else
|
|
|
195
204
|
[[ -d "$source_home" ]] || die "no home to clone at $source_home; pass --source-home"
|
|
196
205
|
source_home="$(cd "$source_home" && pwd -P)"
|
|
197
206
|
fi
|
|
207
|
+
# Physical paths keep parent symlink aliases from bypassing overlap checks.
|
|
198
208
|
[[ ! -L "$home" ]] || die "scratch home cannot be a symlink: $home"
|
|
199
209
|
home="$(node -e "const fs=require('node:fs'),p=require('node:path');let x=p.resolve(process.argv[1]),b=x;while(!fs.existsSync(b))b=p.dirname(b);console.log(p.join(fs.realpathSync(b),p.relative(b,x)))" "$home")"
|
|
200
210
|
[[ ! -L "$home" ]] || die "scratch home cannot be a symlink: $home"
|
|
@@ -203,10 +213,12 @@ user_home="$(cd "$HOME" && pwd -P)"
|
|
|
203
213
|
[[ "$home/" != "$user_home/"* && "$user_home/" != "$home/"* ]] || die "scratch home cannot overlap the user home"
|
|
204
214
|
[[ "$home/" != "$target_path/"* && "$target_path/" != "$home/"* ]] || die "scratch home cannot overlap the target checkout"
|
|
205
215
|
[[ "$home" != / ]] || die "scratch home cannot be filesystem root"
|
|
216
|
+
# Marker identities occupy one line each; embedded newlines would break identity checks.
|
|
206
217
|
for path in "$home" "$source_home" "$target_path"; do [[ "$path" != *$'\n'* ]] || die "paths cannot contain newlines"; done
|
|
207
218
|
marker="$home/.dsh-dogfood"
|
|
208
219
|
profile_json="$home/profiles/$profile/package.json"
|
|
209
220
|
|
|
221
|
+
# Credential permission changes must not affect a shared inode or an external symlink target.
|
|
210
222
|
check_credentials() {
|
|
211
223
|
[[ ! -L "$home/.credentials.yaml" ]] || die "cloned credentials cannot be a symlink"
|
|
212
224
|
[[ -e "$home/.credentials.yaml" ]] || return 0
|
|
@@ -253,6 +265,11 @@ fi
|
|
|
253
265
|
if [[ "$action" == "clean" ]]; then
|
|
254
266
|
[[ -d "$home" ]] || { note "nothing at $home"; exit 0; }
|
|
255
267
|
validate_marker
|
|
268
|
+
# Preview must honor cleanup guards without deleting the state being inspected.
|
|
269
|
+
if [[ "$dry_run" == 1 ]]; then
|
|
270
|
+
note "$CLEAN_PREVIEW_PREFIX $home"
|
|
271
|
+
exit 0
|
|
272
|
+
fi
|
|
256
273
|
rm -rf "$home"
|
|
257
274
|
note "removed $home"
|
|
258
275
|
exit 0
|
|
@@ -285,9 +302,8 @@ fi
|
|
|
285
302
|
|
|
286
303
|
if [[ -d "$home" && "$action" != "clean" && "$dry_run" != 1 ]]; then
|
|
287
304
|
validate_marker
|
|
288
|
-
#
|
|
289
|
-
#
|
|
290
|
-
# home whose copy stopped halfway. A marker without the line predates this.
|
|
305
|
+
# Copy or later setup failures can leave ready=0; require --reseed rather than
|
|
306
|
+
# reuse an incomplete clone.
|
|
291
307
|
[[ "$reseed" == 1 ]] || [[ "$(marker_value ready)" != 0 ]] || die "$home is a half-seeded clone; pass --reseed to clone it again"
|
|
292
308
|
check_credentials
|
|
293
309
|
chmod 700 "$home"
|
|
@@ -311,7 +327,7 @@ if [[ ! -d "$home" ]]; then
|
|
|
311
327
|
chmod 700 "$home"
|
|
312
328
|
# Written before the copy, so whatever the copy does this directory is one that
|
|
313
329
|
# --clean and --reseed already own: an interrupted clone is recoverable rather
|
|
314
|
-
# than a husk neither action will touch.
|
|
330
|
+
# than a husk neither action will touch. It becomes reusable only after setup.
|
|
315
331
|
printf 'home=%s\nsource=%s\ntarget=%s\nprofile=%s\nready=0\n' "$home" "$source_home" "$target_path" "$profile" > "$marker"
|
|
316
332
|
chmod 600 "$marker"
|
|
317
333
|
if [[ "$fresh" == 1 ]]; then
|
|
@@ -342,6 +358,7 @@ check_clone_links
|
|
|
342
358
|
|
|
343
359
|
# --- build, link, run --------------------------------------------------------
|
|
344
360
|
|
|
361
|
+
# Linked TUI profiles load lib/, not src/, so rebuilding makes source edits visible to the run.
|
|
345
362
|
if [[ "$build" == 1 && ! -d "$target_path/node_modules" ]]; then
|
|
346
363
|
die "$target_path has no node_modules; run pnpm install there first (or pass --no-build)"
|
|
347
364
|
fi
|
|
@@ -392,6 +409,8 @@ const state = (file) => fs.lstatSync(file, { throwIfNoEntry: false })
|
|
|
392
409
|
for (const part of [directory, path.dirname(directory), moduleDir]) {
|
|
393
410
|
if (state(part)?.isSymbolicLink()) throw Error("unsafe symlink in profile path: " + part)
|
|
394
411
|
}
|
|
412
|
+
// Reject invalid names and unsafe existing destinations before replacing links;
|
|
413
|
+
// target-boundary checks run afterward and do not roll back earlier relinking.
|
|
395
414
|
for (const [name, spec] of entries) {
|
|
396
415
|
if (!packagePattern.test(name)) throw Error("invalid link dependency name: " + name)
|
|
397
416
|
if (name.includes("\n") || spec.includes("\n") || spec.includes("\0")) throw Error("unsafe link dependency: " + name)
|
|
@@ -417,8 +436,8 @@ if ! node -e "process.exit(require(process.argv[1]).dsh.profile.bundles.includes
|
|
|
417
436
|
die "profile '$profile' does not list $package_name after relink (bundles: $bundles)"
|
|
418
437
|
fi
|
|
419
438
|
|
|
420
|
-
#
|
|
421
|
-
#
|
|
439
|
+
# Completed setup permits clone reuse; link safety and bundle membership checks
|
|
440
|
+
# do not prove that the bundles load or answer at runtime.
|
|
422
441
|
printf 'home=%s\nsource=%s\ntarget=%s\nprofile=%s\nready=1\n' "$home" "$source_home" "$target_path" "$profile" > "$marker"
|
|
423
442
|
chmod 600 "$marker"
|
|
424
443
|
|
|
@@ -431,9 +450,12 @@ printf 'profile: %s (%s)\n' "$profile" "$bundles" >&2
|
|
|
431
450
|
# started with them claims that pane's agent row for this run: the row comes back
|
|
432
451
|
# released, and the pane's real agent disappears from Herdr's pickers until it is
|
|
433
452
|
# restarted. The clone is launched as a surface in a bare terminal instead.
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
453
|
+
# Incidental model notifications must not borrow the caller's production token.
|
|
454
|
+
for isolated_prefix in "${ISOLATED_ENV_PREFIXES[@]}"; do
|
|
455
|
+
while IFS= read -r isolated_var; do
|
|
456
|
+
if [[ "$isolated_var" == "$isolated_prefix"* ]]; then unset "$isolated_var"; fi
|
|
457
|
+
done < <(compgen -e)
|
|
458
|
+
done
|
|
437
459
|
|
|
438
460
|
run_command=(env "DSH_HOME=$home" "$dsh_bin" --profile "$profile")
|
|
439
461
|
if [[ "${#passthrough[@]}" -gt 0 ]]; then
|
|
@@ -13,7 +13,7 @@ the ctx gauge. Find the owner first; then edit exactly one place.
|
|
|
13
13
|
| Where the wiring is | What it owns |
|
|
14
14
|
| --- | --- |
|
|
15
15
|
| `~/.dsh/profiles/<profile>/cordis.patch.yml` | The patch layer: applied after every bundle layer, last entry wins. Holds the catalog or `llm-pi-ai` config a developer actually edits. |
|
|
16
|
-
| `~/.dsh/settings.yaml`
|
|
16
|
+
| `~/.dsh/settings.yaml`, `settings.yaml.imported` | Legacy input, not a live overlay on verified `0.2.0-rc.2`. Settings migration renames the file before attempting a one-time import into matching profile entries. Configure adapter rows in the active profile patch. Keep catalog edits in that patch and consult the installed catalog documentation. |
|
|
17
17
|
| `~/.dsh/profiles/<profile>/package.json` | Bundles and their dependency specs (`link:` for a checkout, a range for a release). |
|
|
18
18
|
| `node_modules/<bundle>/cordis.patch.yml` | The bundle's own defaults: disabled base rows, inserted rows, default config. |
|
|
19
19
|
| `node_modules/@earendil-works/pi-ai/dist/providers/data/<source>.json` | Installed per-provider catalog: ids, and the cost/context/effort data a template clone or a `filter` match inherits. |
|
|
@@ -12,12 +12,12 @@ Companion to [SKILL.md](../SKILL.md): exact fields, files, and checks.
|
|
|
12
12
|
4. The model directory a profile sees is owned by whichever row is enabled:
|
|
13
13
|
`llm-pi-ai` (additive provider config), `dsh-provider-extra` (owned catalog),
|
|
14
14
|
or both, if the profile is not using exclusive ownership.
|
|
15
|
-
5.
|
|
16
|
-
|
|
17
|
-
`
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
a
|
|
15
|
+
5. On verified `0.2.0-rc.2`, settings forms read and update Config-backed
|
|
16
|
+
profile entries. `$DSH_HOME/settings.yaml` is legacy input, not a live adapter
|
|
17
|
+
overlay. Migration renames it to `.imported` before a one-time import; rejected
|
|
18
|
+
sections remain only in that renamed file. Edit adapter and catalog config in
|
|
19
|
+
the active profile patch. Do not assume legacy per-request settings behavior
|
|
20
|
+
on a host that exposes only Config-backed forms.
|
|
21
21
|
|
|
22
22
|
Exclusive ownership is a set of disable rows plus the catalog itself:
|
|
23
23
|
|
|
@@ -1,30 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Inspect the profile's owned catalog and inherited model facts without
|
|
4
|
+
* composing the profile.
|
|
5
5
|
*
|
|
6
6
|
* The surface reads prices, context windows, and reasoning levels from the
|
|
7
7
|
* composition, not from the vendor's page, so an inherited or stale value is
|
|
8
8
|
* invisible in the UI. This reads the same two inputs the resolver does - the
|
|
9
9
|
* owned catalog in the profile patch, and the installed pi-ai provider data -
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* catalog declares.
|
|
10
|
+
* to expose inheritance and overrides that the UI does not distinguish.
|
|
11
|
+
* Installed facts are the unlabeled baseline; "template:<id>", "route", and
|
|
12
|
+
* "metadata" identify departures from it.
|
|
14
13
|
*
|
|
15
14
|
* An entry the catalog spells out completely needs no installed entry at all,
|
|
16
15
|
* so a missing harness install must not hide it. A `filter` route is the
|
|
17
16
|
* exception: its membership is the installed catalog's, so it cannot be read
|
|
18
|
-
* without
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* without provider data. Selected resolution checks expose unusable declarations,
|
|
18
|
+
* but this inspection does not validate every template, schema, or ownership rule.
|
|
19
|
+
* Compose the candidate before trusting it as a usable profile.
|
|
21
20
|
*
|
|
22
21
|
* Usage: dump-model-catalog.mjs [--home <dsh home>] [--profile <name>]
|
|
23
22
|
* [--data <pi-ai data dir>] [--json]
|
|
24
23
|
*
|
|
25
|
-
* `--data`
|
|
26
|
-
*
|
|
27
|
-
* and every template clone need one.
|
|
24
|
+
* `--data` supplies inherited facts when no harness is installed, so filter
|
|
25
|
+
* membership and template-derived values can still be inspected offline.
|
|
28
26
|
*/
|
|
29
27
|
import { execFileSync } from 'node:child_process'
|
|
30
28
|
import { readFileSync, realpathSync } from 'node:fs'
|
|
@@ -55,6 +53,7 @@ export function supportedLevels(levelMap) {
|
|
|
55
53
|
})
|
|
56
54
|
}
|
|
57
55
|
|
|
56
|
+
/** Defaults target the documented TUI patch; DSH_HOME keeps inspection on the caller-selected home. */
|
|
58
57
|
function parseArgs(argv) {
|
|
59
58
|
const options = { home: process.env.DSH_HOME ?? join(homedir(), '.dsh'), profile: 'tui', data: undefined, json: false }
|
|
60
59
|
for (let index = 0; index < argv.length; index += 1) {
|
|
@@ -80,7 +79,10 @@ function dataDirectory() {
|
|
|
80
79
|
}
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* The catalog:setup flow map is the machine-readable inspection boundary;
|
|
84
|
+
* block YAML needs list-models composition. Later patch entries take precedence.
|
|
85
|
+
*/
|
|
84
86
|
export function catalogConfig(patch) {
|
|
85
87
|
const lines = readFileSync(patch, 'utf8').split('\n')
|
|
86
88
|
let catalog
|
|
@@ -92,6 +94,10 @@ export function catalogConfig(patch) {
|
|
|
92
94
|
return catalog
|
|
93
95
|
}
|
|
94
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Unusable inherited data must not prevent inspection of fully declared models.
|
|
99
|
+
* Read and parse failures lose their diagnostics here; dependent entries get resolution errors instead.
|
|
100
|
+
*/
|
|
95
101
|
export function providerData(directory, source) {
|
|
96
102
|
if (directory === undefined || source === undefined) return undefined
|
|
97
103
|
try {
|
|
@@ -229,6 +235,8 @@ function rowsOf(catalog, directory) {
|
|
|
229
235
|
...(result.requestMax === undefined ? {} : { requestMax: result.requestMax }),
|
|
230
236
|
...(result.aliases === undefined ? {} : { aliases: result.aliases }),
|
|
231
237
|
...(result.tiers === undefined ? {} : { tiers: result.tiers }),
|
|
238
|
+
// Installed facts are the baseline; name only other origins to expose
|
|
239
|
+
// template inheritance and catalog overrides without repeating that baseline.
|
|
232
240
|
origins: INHERITED_FIELDS
|
|
233
241
|
.map(field => [field, result.origins[field]])
|
|
234
242
|
.filter(([, origin]) => origin !== INSTALLED)
|
package/README.md
CHANGED
|
@@ -108,7 +108,9 @@ The profile then keeps `@deepseek-ai/dsh-base` and no application, so `dsh --pro
|
|
|
108
108
|
|
|
109
109
|
### Use the installed Harness launcher
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
The manifest declares `>=0.2.0-rc.2 <0.3.0`, but lists only `0.2.0-rc.2` as a verified release. Range membership alone does not prove compatibility. Run `dsh --version` and use that installed release for dogfooding. `pnpm dsh` from a Harness source checkout runs a development host, not the verified installed release. It can migrate `settings.yaml`; do not use it for TUI dogfooding.
|
|
112
|
+
|
|
113
|
+
The surface probes required and optional services at startup, and selects settings APIs by capability. These checks do not validate the host version or prove full-profile behavior. The dogfood helper and PTY driver separately check the launcher against the manifest's verified releases.
|
|
112
114
|
|
|
113
115
|
## Troubleshooting
|
|
114
116
|
|
|
@@ -118,7 +120,7 @@ Two facts explain most failures.
|
|
|
118
120
|
|
|
119
121
|
**`dsh plugin install` removes a bundle it cannot resolve, and says nothing.** The command reconciles `dsh.profile.bundles` against the installed dependencies. A bundle whose path does not resolve leaves the list, and the command still exits 0. The next launch composes `@deepseek-ai/dsh-base` alone. No application plugin mounts, so nothing reads the command line: `dsh --profile tui` then prints nothing and never exits, and `--help` waits with it.
|
|
120
122
|
|
|
121
|
-
**npm
|
|
123
|
+
**npm can report `overriding peer dependency` while a harness tree resolves.** A warning alone does not mean the install failed; check its exit status. This plugin pins its mounted harness dependencies to `0.2.0-rc.2` and declares optional harness peers as `*`. Optional peers avoid automatic installation when absent; neither open peers nor exact dependencies guarantee consumer deduplication. The consumer install smoke checks package-copy counts for its selected release and install paths, not every host in the declared range.
|
|
122
124
|
|
|
123
125
|
| Symptom | Cause | Fix |
|
|
124
126
|
|---|---|---|
|
|
@@ -127,7 +129,7 @@ Two facts explain most failures.
|
|
|
127
129
|
| `dsh-tui: both stdin and stdout must be TTYs` | stdin or stdout is a pipe, a file, or a CI runner | run the command from a terminal |
|
|
128
130
|
| Node warnings, such as `ExperimentalWarning: stripTypeScriptTypes …`, appear after exit | the TUI holds runtime warnings until it returns the terminal to your shell; startup warnings remain visible before the TUI starts | read the warnings in your shell after exit; no warning-suppression flag is needed |
|
|
129
131
|
| Changes under `src/` have no effect | a linked profile loads `lib/`, not `src/` | `pnpm run build` in the plugin checkout |
|
|
130
|
-
| TUI preferences disappear after launching a Harness source checkout | that host treats `settings.yaml` as migration input, not live preferences | use
|
|
132
|
+
| TUI preferences disappear after launching a Harness source checkout | that host treats `settings.yaml` as migration input, not live preferences | use the verified installed release with a cloned home; preserve the original settings file |
|
|
131
133
|
| `--preset <id>` is refused, because the session's agent preset is fixed | a session keeps the mode that composed it, and this session already took a turn | `/preset <id>` before the first turn, or resume without `--preset` |
|
|
132
134
|
| `--resume <id>` starts a new session | the id is a bare UUID | pass the stored id, `tui-session-…` included; a bare `--resume` opens the picker |
|
|
133
135
|
| `dsh: profile "tui" does not exist` | the profile is not created yet | the `add` command creates it |
|
|
@@ -446,6 +448,8 @@ an action with one, so the surface can be restyled and rebound without touching
|
|
|
446
448
|
code. On the supported line a preference lives in the active profile's own patch,
|
|
447
449
|
under the TUI entry's `config`; `/theme <name>` writes a chosen theme there for
|
|
448
450
|
you. Use the actual entry ID, normally `tui`, not the legacy `dsh-tui` namespace.
|
|
451
|
+
Merge preferences into the existing `config`; preserve its startup `!!js` fields.
|
|
452
|
+
The verified host replaces `config` wholesale, so a partial replacement loses the launch identity.
|
|
449
453
|
|
|
450
454
|
```yaml
|
|
451
455
|
- id: tui
|
|
@@ -500,27 +504,27 @@ The plugin exports a Config schema for all preferences shown above, including
|
|
|
500
504
|
`prefix`, `prefixWindow`, and `keys`. Launch fields such as `sessionId`,
|
|
501
505
|
`model`, and `provider` remain separate from live preference edits.
|
|
502
506
|
The settings service owns persistence. TUI does not create another preference store.
|
|
503
|
-
It uses
|
|
507
|
+
It uses legacy section-style `installSection` or `register` APIs, or Config-backed
|
|
504
508
|
`describe` and revision-checked `update` APIs. Unsupported or read-only writes
|
|
505
509
|
show a notice instead of reporting success. A rejected theme selection restores
|
|
506
510
|
the applied theme, and `/theme tokens` reports that same appearance.
|
|
507
511
|
|
|
508
512
|
On Config-backed hosts, absent `history.enabled` and `history.ghost` stay off.
|
|
509
513
|
Set each switch to `true` explicitly to enable it. This prevents recording while
|
|
510
|
-
the host's asynchronous legacy import is pending or has failed.
|
|
511
|
-
|
|
514
|
+
the host's asynchronous legacy import is pending or has failed. Legacy section-style
|
|
515
|
+
settings providers retain their existing defaults. If the host reports unreadable preferences,
|
|
512
516
|
history stays off. Readable `false` switches survive errors in other fields.
|
|
513
517
|
Malformed updates retain the last valid appearance and do not overwrite their source.
|
|
514
518
|
|
|
515
519
|
When public descriptors expose raw user layers, history checks those layers at use
|
|
516
520
|
time. A readable opt-out survives rejected siblings even without a change event.
|
|
517
521
|
Another rejected opt-in cannot clear this protection; a valid committed update can.
|
|
518
|
-
A
|
|
522
|
+
A section-provider limit remains: after an absent user section, rejected scalar
|
|
519
523
|
sections can produce identical public descriptors. TUI cannot detect that transition
|
|
520
|
-
without host validity metadata, so
|
|
524
|
+
without host validity metadata, so section-provider defaults remain active.
|
|
521
525
|
|
|
522
|
-
The
|
|
523
|
-
Exporting Config does not resolve that namespace mismatch. The
|
|
526
|
+
The verified `0.2.0-rc.2` settings service has no legacy import alias from `dsh-tui` to `tui`.
|
|
527
|
+
Exporting Config does not resolve that namespace mismatch. The service renames
|
|
524
528
|
`settings.yaml` to `settings.yaml.imported` before import completes.
|
|
525
529
|
TUI does not retry or restore that file automatically. Preserve current privacy
|
|
526
530
|
opt-outs and copy only the intended legacy fields into the actual TUI entry's
|
|
@@ -804,8 +808,8 @@ The mode is re-read rather than remembered: resuming mounts what that session's
|
|
|
804
808
|
The package is a Cordis plugin bundle that stacks over `@deepseek-ai/dsh-base`:
|
|
805
809
|
|
|
806
810
|
- `@sagmans/dsh-tui/startup` parses this app's own flags and publishes the launch identity.
|
|
807
|
-
- The roster of modes holds the id a session starts in when nobody names one: `@deepseek-ai/dsh-agent-preset-registry` owns that service on the supported line, and each mode arrives as a row of `@deepseek-ai/dsh-agent-preset`, so this bundle declares the four modes itself. Both are mounted through this bundle's own `host/roster` entry point, because a patch row is applied before any service exists and the registry and the modes arrive with the harness's own agent services — after the surface that needs the roster. A mode names a selection rather than a composition: the plugins an agent runs on belong to the bundle shipping each of them, and the profile's own layers compose them, so
|
|
808
|
-
- `@deepseek-ai/dsh-cordis-host-runner` is the host machinery creator mode needs, and the base mounts no such row, so a terminal profile mounts it through this bundle's own `host/runner` entry point. The code runtime PTC mode runs programs against is a base row of its own (`ptc-runtime`) on the supported line, so this bundle mounts none of its own.
|
|
811
|
+
- The roster of modes holds the id a session starts in when nobody names one: `@deepseek-ai/dsh-agent-preset-registry` owns that service on the supported line, and each mode arrives as a row of `@deepseek-ai/dsh-agent-preset`, so this bundle declares the four modes itself. Both are mounted through this bundle's own `host/roster` entry point, because a patch row is applied before any service exists and the registry and the modes arrive with the harness's own agent services — after the surface that needs the roster. A mode names a selection rather than a composition: the plugins an agent runs on belong to the bundle shipping each of them, and the profile's own layers compose them, so the other shipped modes declare no plugin row and the patch disables none. The one row a mode does own is its presentation: `ptc` mounts `@deepseek-ai/dsh-agent-tool-presentation` with `mode: ptc`, because the form an agent's tools take is declared per agent — a session's own row cannot say it, and a mode without the row presents natively whatever its id says.
|
|
812
|
+
- `@deepseek-ai/dsh-cordis-host-runner` is the host machinery creator mode needs, and the base mounts no such row, so a terminal profile mounts it through this bundle's own `host/runner` entry point. The code runtime PTC mode runs programs against is a base row of its own (`ptc-runtime`) on the supported line, so this bundle mounts none of its own. The registry, preset, and runner packages are plain dependencies pinned to `0.2.0-rc.2`; these pins do not guarantee one copy in every consumer tree.
|
|
809
813
|
- `@sagmans/dsh-tui` owns the terminal: it creates or resumes one agent through `ctx.agents`, folds `session/event` into transcript rows and work state, renders them with `@earendil-works/pi-tui`, and releases the terminal on exit, on a boot failure, and on a signal.
|
|
810
814
|
- `@sagmans/dsh-tui/todo-guard` is the one advisory row this bundle adds to the agent plane: it watches the harness's own `todos` and `plan` projections and rides the next tool result with a reminder when a plan ages. See [Todo discipline](#todo-discipline).
|
|
811
815
|
|
|
@@ -823,7 +827,7 @@ A PTC card is the one card with children: every call the `run_code` program disp
|
|
|
823
827
|
|
|
824
828
|
A card's header names the tool, then, on a skill card, the skill it loaded in the `tool.skill` colour, then the argument the call was made with — a path or a command — in the `tool.args` colour, then the facts the result measured: a read reports its line range, line count, and token size; a file change that carried no prior content to compare against reports its lines and tokens; one that did reports added, changed, and removed lines as `+n ~n -n` in green, yellow, and red. Each stat is its own token, so any of them can be recoloured or hidden independently, and so are the elements a call in flight is drawn with — hiding `tool.running.elapsed` leaves the name in its running colour, hiding `tool.running.title` leaves the seconds counting, hiding `tool.elapsed.done` takes the total off a program's settled row, and a dispatched row is toned the same way per state with `tool.subcall.running` and `tool.subcall.title`. A state is only how a name is painted, so hiding one of those colours leaves the name in the colour a call with no state is read in rather than taking the name away. Hiding `tool.skill` is the same promise for a subject: the skill keeps its name in the label's colour. `/export` and a dispatched row spell the name too, so the words survive where no colour is.
|
|
825
829
|
|
|
826
|
-
The bundle
|
|
830
|
+
The bundle disables no base row. The profile's layers supply the agent tools, prompt sections, skills, and planning. The shipped modes do not duplicate those rows; PTC adds only its tool-presentation row.
|
|
827
831
|
|
|
828
832
|
### Todo discipline
|
|
829
833
|
|
|
@@ -882,18 +886,51 @@ rows = [
|
|
|
882
886
|
|
|
883
887
|
With that row present, a pane waiting on a decision names the tool that asked instead of showing a colour alone. A label longer than the 80 characters Herdr holds whole is cut here rather than server-side, so the ellipsis lands where this surface put it; the message that rides the state report keeps its own, longer bound.
|
|
884
888
|
|
|
889
|
+
## Moshi notifications
|
|
890
|
+
|
|
891
|
+
[Moshi](https://getmoshi.app/docs/notifications) can send optional notifications for the session this terminal drives.
|
|
892
|
+
Set `DSH_TUI_MOSHI_TOKEN` in the process environment before you start `dsh --profile tui`.
|
|
893
|
+
Use a Moshi API token, not the host secret used by `moshi-hook`.
|
|
894
|
+
The reporter is disabled when this variable is absent or empty.
|
|
895
|
+
It works without Herdr or the Moshi daemon.
|
|
896
|
+
|
|
897
|
+
Load the token through your secret manager. Do not put it in profile YAML, shell history, or a conversation.
|
|
898
|
+
Unset `DSH_TUI_MOSHI_TOKEN` and restart the surface to disable notifications.
|
|
899
|
+
|
|
900
|
+
The reporter sends these fixed messages:
|
|
901
|
+
|
|
902
|
+
- **DSH needs attention:** “Return to the terminal to continue.” An agent approval or question triggers this notification.
|
|
903
|
+
- **DSH finished:** “The current session is ready for input.” The driven agent and its background work must both stop.
|
|
904
|
+
|
|
905
|
+
Reader navigation does not trigger attention notifications. Duplicate status events do not produce duplicate notifications.
|
|
906
|
+
A finished run can include cancellation or failure; the message does not report task success.
|
|
907
|
+
Switching sessions discards queued notifications and aborts outstanding delivery.
|
|
908
|
+
Notifications already delivered cannot be recalled.
|
|
909
|
+
|
|
910
|
+
The only JSON fields sent to `https://api.getmoshi.app/api/webhook` are `token`, `title`, and `message`.
|
|
911
|
+
The message contains no transcript, prompt, tool arguments, approval text, working directory, or session/pane identifiers.
|
|
912
|
+
The token selects its owning Moshi device; the reporter does not request multi-device delivery.
|
|
913
|
+
Requests abort after three seconds. Network and HTTP failures remain silent, with no retries.
|
|
914
|
+
Notification delivery never blocks agent work or terminal teardown.
|
|
915
|
+
|
|
916
|
+
This integration does not provide native Chat View, Live Activity, remote approval controls, or automatic pane navigation.
|
|
917
|
+
Use the existing Moshi SSH connection to return to the terminal.
|
|
918
|
+
|
|
885
919
|
## Development
|
|
886
920
|
|
|
887
921
|
```sh
|
|
888
|
-
pnpm install
|
|
889
|
-
pnpm
|
|
890
|
-
pnpm test
|
|
891
|
-
pnpm run build
|
|
922
|
+
pnpm install --frozen-lockfile
|
|
923
|
+
pnpm verify
|
|
892
924
|
```
|
|
893
925
|
|
|
894
926
|
**A linked profile loads the built entry point**, so edits under `src/` are invisible to `dsh --profile tui` until `pnpm run build` runs. The PTY driver rebuilds, checks nested links in the isolated `--home`, and rejects a launcher whose version `dsh.compatibility.dshReleases` does not list.
|
|
895
927
|
|
|
896
|
-
|
|
928
|
+
`pnpm verify` preserves golden snapshots and automatically drives free real-profile
|
|
929
|
+
scenarios without credentials. [FEATURES.md](FEATURES.md) owns feature inventory
|
|
930
|
+
and evidence rules. Unit suites are not maintained.
|
|
931
|
+
|
|
932
|
+
Paid model use runs only on explicit demand. For those checks, clone your
|
|
933
|
+
configured home with the dogfood helper. These commands include paid model calls:
|
|
897
934
|
|
|
898
935
|
```sh
|
|
899
936
|
S=$(mktemp -d)
|
|
@@ -905,10 +942,11 @@ node tools/pty-drive.mjs --home "$S" --seconds 20 --prompt ''
|
|
|
905
942
|
node tools/pty-drive.mjs --home "$S" --prompt 'Run: echo hi' --click 20:12
|
|
906
943
|
```
|
|
907
944
|
|
|
908
|
-
A minimal home starts on the shipped defaults
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
945
|
+
A minimal home starts on the shipped defaults. On verified `0.2.0-rc.2`, the
|
|
946
|
+
settings service renames legacy `settings.yaml` before attempting a one-time
|
|
947
|
+
import into matching profile entries. Rejected sections remain only in
|
|
948
|
+
`settings.yaml.imported`. Use the active profile patch for current preferences,
|
|
949
|
+
or the dogfood clone above when a run needs your own composition.
|
|
912
950
|
|
|
913
951
|
Test specs import plugin sources through the `@/` alias. Under this test runner the spec file is resolved with a root-relative id, so parent-relative imports (`../src/...`) do not resolve; the alias and its matching `tsconfig.test.json` path mapping avoid that.
|
|
914
952
|
|
|
@@ -1026,7 +1064,7 @@ discipline as this one.
|
|
|
1026
1064
|
|
|
1027
1065
|
| Plugin | What it adds |
|
|
1028
1066
|
|---|---|
|
|
1029
|
-
| [`@sagmans/dsh-auto-compact`](https://github.com/sagmans/dsh-auto-compact) | An absolute token trigger for automatic compaction: the conversation condenses at `min(thresholdTokens, contextWindow × thresholdRatio)` instead of the window ratio alone, so a large-window model pays a fixed price, with per-route overrides. Its patch swaps the shipped `compaction-basic` backend —
|
|
1067
|
+
| [`@sagmans/dsh-auto-compact`](https://github.com/sagmans/dsh-auto-compact) | An absolute token trigger for automatic compaction: the conversation condenses at `min(thresholdTokens, contextWindow × thresholdRatio)` instead of the window ratio alone, so a large-window model pays a fixed price, with per-route overrides. Its patch swaps the shipped `compaction-basic` backend — a row this bundle does not disable — so the profile still keeps exactly one compaction service, and this surface needs no setting for it. |
|
|
1030
1068
|
| [`@sagmans/dsh-provider-extra`](https://github.com/sagmans/dsh-provider-extra) | Extra provider routes: OpenCode Go, which sends the live conversation id in `x-opencode-session` for routing and prompt caching, and OpenAI Codex over a ChatGPT subscription's OAuth flow with the harness credential store. Its routes join the `/model` picker like every configured provider. TUI also works without this package, using the core `llm` and `agentDefaultModel` services. |
|
|
1031
1069
|
|
|
1032
1070
|
```sh
|
package/cordis.patch.yml
CHANGED
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
- id: tui-keymaps
|
|
30
30
|
name: '@sagmans/dsh-tui/keymaps'
|
|
31
31
|
|
|
32
|
+
# Parse launcher intent once; injection keeps the surface behind committed startup state
|
|
33
|
+
# and prevents --help or usage errors from mounting the interactive screen.
|
|
32
34
|
- id: tui-startup
|
|
33
35
|
name: '@sagmans/dsh-tui/startup'
|
|
34
36
|
|
package/lib/agent/fork.d.ts
CHANGED
|
@@ -3,12 +3,14 @@ export interface ForkEvent {
|
|
|
3
3
|
readonly type: string;
|
|
4
4
|
readonly data?: unknown;
|
|
5
5
|
readonly seq?: number;
|
|
6
|
+
/** Re-folding a log must preserve the clock of its recorded work. */
|
|
7
|
+
readonly time?: number;
|
|
6
8
|
}
|
|
7
9
|
/** Where a fork may branch, and how much of the log the child inherits. */
|
|
8
10
|
export interface ForkPoint {
|
|
9
11
|
/** Events the child inherits, counted from the start of the log. */
|
|
10
12
|
readonly inheritedEvents: number;
|
|
11
|
-
/**
|
|
13
|
+
/** Boundary label for the fork notice, not the inherited-prefix offset. */
|
|
12
14
|
readonly boundarySeq: number;
|
|
13
15
|
}
|
|
14
16
|
/**
|
package/lib/agent/fork.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fork.d.ts","sourceRoot":"","sources":["../../src/agent/fork.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"fork.d.ts","sourceRoot":"","sources":["../../src/agent/fork.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;IACrB,qEAAqE;IACrE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,2EAA2E;AAC3E,MAAM,WAAW,SAAS;IACxB,oEAAoE;IACpE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAA;IAChC,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,GAAG,SAAS,GAAG,SAAS,CAc7E"}
|
package/lib/agent/fork.js
CHANGED
|
@@ -20,6 +20,8 @@ export function forkPoint(events) {
|
|
|
20
20
|
let cut = boundary + 1;
|
|
21
21
|
while (cut < events.length && events[cut]?.type !== 'turn/start')
|
|
22
22
|
cut += 1;
|
|
23
|
+
// The notice still needs a boundary label when seq is absent; only the array
|
|
24
|
+
// cut determines inheritance, so this index does not stand in for a durable seq.
|
|
23
25
|
return { inheritedEvents: cut, boundarySeq: events[boundary]?.seq ?? boundary };
|
|
24
26
|
}
|
|
25
27
|
//# sourceMappingURL=fork.js.map
|