@sagmans/dsh-tui 0.5.2 → 0.7.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 +83 -0
- package/.agents/skills/dsh-tui-dogfood/references/home-state.md +78 -0
- package/.agents/skills/dsh-tui-dogfood/scripts/clone-links.mjs +133 -0
- package/.agents/skills/dsh-tui-dogfood/scripts/run-plugin-from-worktree.sh +417 -0
- package/.agents/skills/dsh-tui-update-models/SKILL.md +121 -0
- package/.agents/skills/dsh-tui-update-models/references/model-wiring.md +162 -0
- package/.agents/skills/dsh-tui-update-models/scripts/dump-model-catalog.mjs +178 -0
- package/README.md +131 -17
- package/lib/agent/host.d.ts +11 -0
- package/lib/agent/host.d.ts.map +1 -1
- package/lib/agent/host.js +16 -2
- package/lib/agent/host.js.map +1 -1
- package/lib/agent/present.d.ts.map +1 -1
- package/lib/agent/present.js +2 -1
- package/lib/agent/present.js.map +1 -1
- package/lib/agent/undo.d.ts +52 -0
- package/lib/agent/undo.d.ts.map +1 -0
- package/lib/agent/undo.js +106 -0
- package/lib/agent/undo.js.map +1 -0
- package/lib/cards/composition.d.ts +68 -0
- package/lib/cards/composition.d.ts.map +1 -0
- package/lib/cards/composition.js +117 -0
- package/lib/cards/composition.js.map +1 -0
- package/lib/cards/presenter.d.ts +23 -0
- package/lib/cards/presenter.d.ts.map +1 -0
- package/lib/cards/presenter.js +394 -0
- package/lib/cards/presenter.js.map +1 -0
- package/lib/cards/preview.d.ts +42 -0
- package/lib/cards/preview.d.ts.map +1 -0
- package/lib/cards/preview.js +51 -0
- package/lib/cards/preview.js.map +1 -0
- package/lib/cards.d.ts +42 -95
- package/lib/cards.d.ts.map +1 -1
- package/lib/cards.js +4 -526
- package/lib/cards.js.map +1 -1
- package/lib/compat/section.d.ts +29 -0
- package/lib/compat/section.d.ts.map +1 -0
- package/lib/compat/section.js +82 -0
- package/lib/compat/section.js.map +1 -0
- package/lib/config.d.ts +27 -2
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +61 -1
- package/lib/config.js.map +1 -1
- package/lib/contracts.d.ts +28 -0
- package/lib/contracts.d.ts.map +1 -1
- package/lib/fold-cursor.d.ts +8 -0
- package/lib/fold-cursor.d.ts.map +1 -1
- package/lib/fold-cursor.js +18 -0
- package/lib/fold-cursor.js.map +1 -1
- package/lib/gates/question-card.d.ts +77 -0
- package/lib/gates/question-card.d.ts.map +1 -0
- package/lib/gates/question-card.js +113 -0
- package/lib/gates/question-card.js.map +1 -0
- package/lib/gates/questions.d.ts +127 -0
- package/lib/gates/questions.d.ts.map +1 -0
- package/lib/gates/questions.js +418 -0
- package/lib/gates/questions.js.map +1 -0
- package/lib/gates.d.ts +1 -113
- package/lib/gates.d.ts.map +1 -1
- package/lib/gates.js +1 -484
- package/lib/gates.js.map +1 -1
- package/lib/herdr/reporter.d.ts +9 -4
- package/lib/herdr/reporter.d.ts.map +1 -1
- package/lib/herdr/reporter.js +5 -9
- package/lib/herdr/reporter.js.map +1 -1
- package/lib/herdr/state.d.ts +35 -4
- package/lib/herdr/state.d.ts.map +1 -1
- package/lib/herdr/state.js +37 -4
- package/lib/herdr/state.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +343 -2267
- package/lib/index.js.map +1 -1
- package/lib/input/action-catalog.d.ts +74 -0
- package/lib/input/action-catalog.d.ts.map +1 -0
- package/lib/input/action-catalog.js +137 -0
- package/lib/input/action-catalog.js.map +1 -0
- package/lib/input/actions.d.ts +5 -81
- package/lib/input/actions.d.ts.map +1 -1
- package/lib/input/actions.js +4 -621
- package/lib/input/actions.js.map +1 -1
- package/lib/input/completion.d.ts +11 -1
- package/lib/input/completion.d.ts.map +1 -1
- package/lib/input/completion.js +17 -1
- package/lib/input/completion.js.map +1 -1
- package/lib/input/file-index.d.ts +40 -0
- package/lib/input/file-index.d.ts.map +1 -0
- package/lib/input/file-index.js +141 -0
- package/lib/input/file-index.js.map +1 -0
- package/lib/input/file-search.d.ts +1 -38
- package/lib/input/file-search.d.ts.map +1 -1
- package/lib/input/file-search.js +1 -487
- package/lib/input/file-search.js.map +1 -1
- package/lib/input/key-press.d.ts +57 -0
- package/lib/input/key-press.d.ts.map +1 -0
- package/lib/input/key-press.js +218 -0
- package/lib/input/key-press.js.map +1 -0
- package/lib/input/keymap-conflicts.d.ts +59 -0
- package/lib/input/keymap-conflicts.d.ts.map +1 -0
- package/lib/input/keymap-conflicts.js +292 -0
- package/lib/input/keymap-conflicts.js.map +1 -0
- package/lib/input/keymap-settings.js +1 -1
- package/lib/input/keymap-settings.js.map +1 -1
- package/lib/input/keymap.d.ts.map +1 -1
- package/lib/input/keymap.js +5 -1
- package/lib/input/keymap.js.map +1 -1
- package/lib/input/submission.d.ts +11 -1
- package/lib/input/submission.d.ts.map +1 -1
- package/lib/input/submission.js +10 -1
- package/lib/input/submission.js.map +1 -1
- package/lib/input/workspace-files.d.ts +10 -0
- package/lib/input/workspace-files.d.ts.map +1 -0
- package/lib/input/workspace-files.js +359 -0
- package/lib/input/workspace-files.js.map +1 -0
- package/lib/install-skills.d.ts +20 -0
- package/lib/install-skills.d.ts.map +1 -0
- package/lib/install-skills.js +198 -0
- package/lib/install-skills.js.map +1 -0
- package/lib/keys-command.d.ts +2 -1
- package/lib/keys-command.d.ts.map +1 -1
- package/lib/keys-command.js +2 -1
- package/lib/keys-command.js.map +1 -1
- package/lib/model-list.d.ts +37 -0
- package/lib/model-list.d.ts.map +1 -0
- package/lib/model-list.js +60 -0
- package/lib/model-list.js.map +1 -0
- package/lib/startup.d.ts +8 -0
- package/lib/startup.d.ts.map +1 -1
- package/lib/startup.js +120 -24
- package/lib/startup.js.map +1 -1
- package/lib/subagents.d.ts +7 -3
- package/lib/subagents.d.ts.map +1 -1
- package/lib/subagents.js +28 -4
- package/lib/subagents.js.map +1 -1
- package/lib/surface/appearance-preferences.d.ts +26 -0
- package/lib/surface/appearance-preferences.d.ts.map +1 -0
- package/lib/surface/appearance-preferences.js +139 -0
- package/lib/surface/appearance-preferences.js.map +1 -0
- package/lib/surface/appearance.d.ts +87 -0
- package/lib/surface/appearance.d.ts.map +1 -0
- package/lib/surface/appearance.js +353 -0
- package/lib/surface/appearance.js.map +1 -0
- package/lib/surface/background-work.d.ts +49 -0
- package/lib/surface/background-work.d.ts.map +1 -0
- package/lib/surface/background-work.js +146 -0
- package/lib/surface/background-work.js.map +1 -0
- package/lib/surface/commands.d.ts +80 -0
- package/lib/surface/commands.d.ts.map +1 -0
- package/lib/surface/commands.js +364 -0
- package/lib/surface/commands.js.map +1 -0
- package/lib/surface/modal-input.d.ts +58 -0
- package/lib/surface/modal-input.d.ts.map +1 -0
- package/lib/surface/modal-input.js +237 -0
- package/lib/surface/modal-input.js.map +1 -0
- package/lib/surface/model-choice.d.ts +54 -0
- package/lib/surface/model-choice.d.ts.map +1 -0
- package/lib/surface/model-choice.js +325 -0
- package/lib/surface/model-choice.js.map +1 -0
- package/lib/surface/preset-choice.d.ts +78 -0
- package/lib/surface/preset-choice.d.ts.map +1 -0
- package/lib/surface/preset-choice.js +163 -0
- package/lib/surface/preset-choice.js.map +1 -0
- package/lib/surface/prompt-input.d.ts +97 -0
- package/lib/surface/prompt-input.d.ts.map +1 -0
- package/lib/surface/prompt-input.js +215 -0
- package/lib/surface/prompt-input.js.map +1 -0
- package/lib/surface/prompt-memory.d.ts +76 -0
- package/lib/surface/prompt-memory.d.ts.map +1 -0
- package/lib/surface/prompt-memory.js +167 -0
- package/lib/surface/prompt-memory.js.map +1 -0
- package/lib/surface/session-lifecycle.d.ts +120 -0
- package/lib/surface/session-lifecycle.d.ts.map +1 -0
- package/lib/surface/session-lifecycle.js +321 -0
- package/lib/surface/session-lifecycle.js.map +1 -0
- package/lib/surface/session-picker.d.ts +39 -0
- package/lib/surface/session-picker.d.ts.map +1 -0
- package/lib/surface/session-picker.js +107 -0
- package/lib/surface/session-picker.js.map +1 -0
- package/lib/surface/session-view.d.ts +86 -0
- package/lib/surface/session-view.d.ts.map +1 -0
- package/lib/surface/session-view.js +215 -0
- package/lib/surface/session-view.js.map +1 -0
- package/lib/surface/staged-turns.d.ts +81 -0
- package/lib/surface/staged-turns.d.ts.map +1 -0
- package/lib/surface/staged-turns.js +206 -0
- package/lib/surface/staged-turns.js.map +1 -0
- package/lib/surface/terminal-lifecycle.d.ts +76 -0
- package/lib/surface/terminal-lifecycle.d.ts.map +1 -0
- package/lib/surface/terminal-lifecycle.js +222 -0
- package/lib/surface/terminal-lifecycle.js.map +1 -0
- package/lib/terminal/warning-screen.d.ts +8 -1
- package/lib/terminal/warning-screen.d.ts.map +1 -1
- package/lib/terminal/warning-screen.js +9 -0
- package/lib/terminal/warning-screen.js.map +1 -1
- package/lib/terminal-text/scan.d.ts +44 -0
- package/lib/terminal-text/scan.d.ts.map +1 -0
- package/lib/terminal-text/scan.js +195 -0
- package/lib/terminal-text/scan.js.map +1 -0
- package/lib/terminal-text/sgr.d.ts +32 -0
- package/lib/terminal-text/sgr.d.ts.map +1 -0
- package/lib/terminal-text/sgr.js +203 -0
- package/lib/terminal-text/sgr.js.map +1 -0
- package/lib/terminal-text.d.ts +1 -1
- package/lib/terminal-text.d.ts.map +1 -1
- package/lib/terminal-text.js +2 -379
- package/lib/terminal-text.js.map +1 -1
- package/lib/theme-command.js +2 -1
- package/lib/theme-command.js.map +1 -1
- package/lib/theme-defaults.d.ts +64 -0
- package/lib/theme-defaults.d.ts.map +1 -0
- package/lib/theme-defaults.js +248 -0
- package/lib/theme-defaults.js.map +1 -0
- package/lib/theme-resolver.d.ts +36 -0
- package/lib/theme-resolver.d.ts.map +1 -0
- package/lib/theme-resolver.js +112 -0
- package/lib/theme-resolver.js.map +1 -0
- package/lib/theme-schema.d.ts +6 -6
- package/lib/theme-schema.d.ts.map +1 -1
- package/lib/theme-schema.js +3 -2
- package/lib/theme-schema.js.map +1 -1
- package/lib/theme-settings.d.ts +13 -15
- package/lib/theme-settings.d.ts.map +1 -1
- package/lib/theme-settings.js +27 -19
- package/lib/theme-settings.js.map +1 -1
- package/lib/theme-tokens.d.ts +1 -90
- package/lib/theme-tokens.d.ts.map +1 -1
- package/lib/theme-tokens.js +11 -341
- package/lib/theme-tokens.js.map +1 -1
- package/lib/theme.d.ts +1 -1
- package/lib/theme.d.ts.map +1 -1
- package/lib/theme.js +2 -1
- package/lib/theme.js.map +1 -1
- package/lib/tool-display.d.ts.map +1 -1
- package/lib/tool-display.js +2 -1
- package/lib/tool-display.js.map +1 -1
- package/lib/transcript/message-content.d.ts +21 -0
- package/lib/transcript/message-content.d.ts.map +1 -0
- package/lib/transcript/message-content.js +61 -0
- package/lib/transcript/message-content.js.map +1 -0
- package/lib/transcript/tool-calls.d.ts +106 -0
- package/lib/transcript/tool-calls.d.ts.map +1 -0
- package/lib/transcript/tool-calls.js +254 -0
- package/lib/transcript/tool-calls.js.map +1 -0
- package/lib/transcript.d.ts +38 -43
- package/lib/transcript.d.ts.map +1 -1
- package/lib/transcript.js +58 -245
- package/lib/transcript.js.map +1 -1
- package/lib/ui/copy.d.ts +17 -0
- package/lib/ui/copy.d.ts.map +1 -0
- package/lib/ui/copy.js +104 -0
- package/lib/ui/copy.js.map +1 -0
- package/lib/ui/dock.d.ts +35 -3
- package/lib/ui/dock.d.ts.map +1 -1
- package/lib/ui/dock.js +124 -23
- package/lib/ui/dock.js.map +1 -1
- package/lib/ui/editor.d.ts.map +1 -1
- package/lib/ui/editor.js +2 -1
- package/lib/ui/editor.js.map +1 -1
- package/lib/ui/frame.d.ts +31 -0
- package/lib/ui/frame.d.ts.map +1 -1
- package/lib/ui/frame.js +27 -4
- package/lib/ui/frame.js.map +1 -1
- package/lib/ui/keymap-picker.d.ts +2 -1
- package/lib/ui/keymap-picker.d.ts.map +1 -1
- package/lib/ui/keymap-picker.js +1 -0
- package/lib/ui/keymap-picker.js.map +1 -1
- package/lib/ui/view/gate-card.d.ts +21 -0
- package/lib/ui/view/gate-card.d.ts.map +1 -0
- package/lib/ui/view/gate-card.js +104 -0
- package/lib/ui/view/gate-card.js.map +1 -0
- package/lib/ui/view/tool-card.d.ts +138 -0
- package/lib/ui/view/tool-card.d.ts.map +1 -0
- package/lib/ui/view/tool-card.js +413 -0
- package/lib/ui/view/tool-card.js.map +1 -0
- package/lib/ui/view/transcript-message.d.ts +62 -0
- package/lib/ui/view/transcript-message.d.ts.map +1 -0
- package/lib/ui/view/transcript-message.js +158 -0
- package/lib/ui/view/transcript-message.js.map +1 -0
- package/lib/ui/view.d.ts +87 -156
- package/lib/ui/view.d.ts.map +1 -1
- package/lib/ui/view.js +122 -556
- package/lib/ui/view.js.map +1 -1
- package/package.json +3 -1
- package/themes/deepseek-blue.yaml +9 -0
- package/themes/violet-orbit.yaml +7 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
import { defaultKeymap } from "../input/actions.js";
|
|
2
|
+
import { DEFAULT_PREFIX_KEYS, DEFAULT_PREFIX_WINDOW_S } from "../input/keymap.js";
|
|
3
|
+
import { createDeferredNotice } from "../settings-notice.js";
|
|
4
|
+
import { createTheme, forwardEditorTheme, forwardMarkdownTheme } from "../theme.js";
|
|
5
|
+
import { detectColourMode } from "../theme-capability.js";
|
|
6
|
+
import { renderThemeTable } from "../theme-command.js";
|
|
7
|
+
import { DEFAULT_THEME, builtinNames, builtinThemesDir, ensureThemesHome, exportTheme, loadThemes, themesHomeDir, watchThemes } from "../theme-files.js";
|
|
8
|
+
import { defaultSettings, toOverrides } from "../theme-settings.js";
|
|
9
|
+
import { ThemePicker } from "../ui/theme-picker.js";
|
|
10
|
+
import { DEFAULT_VIEW_STATE } from "../ui/view.js";
|
|
11
|
+
import { createAppearancePreferences } from "./appearance-preferences.js";
|
|
12
|
+
/** One second in the unit a chord window is scheduled in. */
|
|
13
|
+
const MS_PER_SECOND = 1000;
|
|
14
|
+
/**
|
|
15
|
+
* The reader's appearance and display preferences, and the theme's lifetime.
|
|
16
|
+
*
|
|
17
|
+
* Every preference is read through a getter rather than captured, and the theme
|
|
18
|
+
* table is replaced behind a delegate the renderers already hold, because the
|
|
19
|
+
* document is hot-reloaded and the shade the reader saves has to reach a session
|
|
20
|
+
* that is already on screen.
|
|
21
|
+
*/
|
|
22
|
+
export function createAppearance(ctx, ports) {
|
|
23
|
+
const themeMode = () => (ports.color() ? detectColourMode(process.env) : 'none');
|
|
24
|
+
/**
|
|
25
|
+
* The themes this session can draw.
|
|
26
|
+
*
|
|
27
|
+
* Read from disk rather than compiled in, so a file the reader saves is a theme
|
|
28
|
+
* the moment the save lands. Held beside the settings rather than inside them
|
|
29
|
+
* because the two answer different questions: the section says which name the
|
|
30
|
+
* reader chose, and this says which names exist — including the one they typed
|
|
31
|
+
* into the directory a second ago.
|
|
32
|
+
*/
|
|
33
|
+
const themesHome = themesHomeDir();
|
|
34
|
+
let themeLibrary = loadThemes(themesHome, builtinThemesDir());
|
|
35
|
+
/**
|
|
36
|
+
* A refused settings edit, kept until the surface can show it: stderr is
|
|
37
|
+
* behind the alt screen, and the section is read on a schedule of its own.
|
|
38
|
+
*/
|
|
39
|
+
const settingsNotice = createDeferredNotice();
|
|
40
|
+
let current = createTheme(themeMode());
|
|
41
|
+
/**
|
|
42
|
+
* The section as it was last read.
|
|
43
|
+
*
|
|
44
|
+
* Held so a preview can rebuild the table without reading the document again:
|
|
45
|
+
* the picker repaints on every arrow key, and a read there would report a
|
|
46
|
+
* refused section once per press.
|
|
47
|
+
*/
|
|
48
|
+
let appliedSection;
|
|
49
|
+
/**
|
|
50
|
+
* The theme the picker's cursor is on, while its list is open.
|
|
51
|
+
*
|
|
52
|
+
* A preview is a name and nothing else — the document is not written — so
|
|
53
|
+
* leaving the list is one more rebuild from the section, and a session that
|
|
54
|
+
* ends mid-preview has still persisted only what the reader chose.
|
|
55
|
+
*/
|
|
56
|
+
let previewTheme;
|
|
57
|
+
/**
|
|
58
|
+
* The theme in force: the reader's section, then the name the row pins, then
|
|
59
|
+
* whatever file answers to no name at all.
|
|
60
|
+
*
|
|
61
|
+
* One question asked at two scopes. A section belongs to the settings document,
|
|
62
|
+
* so a reader who has one is naming a theme for it; the row belongs to the
|
|
63
|
+
* profile, and a harness that keeps configuration per row has no document left
|
|
64
|
+
* to hold a name — which is why the row is read here, below the section and
|
|
65
|
+
* above the default, rather than as the only answer.
|
|
66
|
+
*/
|
|
67
|
+
const themeName = (section) => section.theme ?? (preferences.configBacked() ? undefined : ports.rowTheme);
|
|
68
|
+
const applyTheme = (section) => {
|
|
69
|
+
// The row under the cursor outranks both while a list is open, so a theme is
|
|
70
|
+
// judged on the reader's own transcript before it is taken.
|
|
71
|
+
current = createTheme(themeMode(), toOverrides({ ...section, theme: previewTheme ?? themeName(section) }, themeLibrary));
|
|
72
|
+
};
|
|
73
|
+
/** Repaint the surface: both caches hold rows drawn under the table this replaced. */
|
|
74
|
+
const restyle = () => {
|
|
75
|
+
ports.invalidateMarkdown();
|
|
76
|
+
ports.invalidateView();
|
|
77
|
+
ports.render();
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Show a theme without choosing it.
|
|
81
|
+
*
|
|
82
|
+
* The list's cursor is the preview: every row paints the surface and writes
|
|
83
|
+
* nothing, so two themes are compared on the reader's own transcript rather
|
|
84
|
+
* than on a name. Clearing the name puts back what the document says, which is
|
|
85
|
+
* what cancelling the list has to leave behind.
|
|
86
|
+
*/
|
|
87
|
+
const showTheme = (name) => {
|
|
88
|
+
previewTheme = name;
|
|
89
|
+
// Nothing to rebuild from before the first read, and nothing to show either.
|
|
90
|
+
if (appliedSection === undefined)
|
|
91
|
+
return;
|
|
92
|
+
applyTheme(appliedSection);
|
|
93
|
+
restyle();
|
|
94
|
+
};
|
|
95
|
+
const theme = {
|
|
96
|
+
get revision() { return current.revision; },
|
|
97
|
+
get color() { return current.color; },
|
|
98
|
+
style: (token, text) => current.style(token, text),
|
|
99
|
+
rich: (raw, options) => current.rich(raw, options),
|
|
100
|
+
cut: (text, width, ellipsis) => current.cut(text, width, ellipsis),
|
|
101
|
+
glyph: token => current.glyph(token),
|
|
102
|
+
visible: token => current.visible(token),
|
|
103
|
+
// Forwarded rather than read, because the editor and the markdown view keep
|
|
104
|
+
// the theme object they were built with: a settings change has to reach them
|
|
105
|
+
// through a stable delegate or they would keep the boot appearance.
|
|
106
|
+
editor: forwardEditorTheme(() => current.editor),
|
|
107
|
+
markdown: forwardMarkdownTheme(() => current.markdown),
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Rows the reader has opened by key. The model stays untouched; only the view
|
|
111
|
+
* reads this, and a click on one message overrides it there. A thought starts
|
|
112
|
+
* folded: it is the longest, least scannable row in the transcript, so leaving
|
|
113
|
+
* it open pushes the answer a reader came for off the screen, and a folded row
|
|
114
|
+
* still names itself and its key. Cards start from the reader's own `tools:`
|
|
115
|
+
* settings, and a PTC card's calls start open for the opposite reason: each is
|
|
116
|
+
* one clipped line under a header that already names the program.
|
|
117
|
+
*/
|
|
118
|
+
const viewState = { ...DEFAULT_VIEW_STATE };
|
|
119
|
+
const toggleCards = () => {
|
|
120
|
+
viewState.expandCards = !viewState.expandCards;
|
|
121
|
+
};
|
|
122
|
+
const toggleSubCalls = () => {
|
|
123
|
+
viewState.expandSubCalls = !viewState.expandSubCalls;
|
|
124
|
+
};
|
|
125
|
+
const toggleReasoning = () => {
|
|
126
|
+
viewState.expandReasoning = !viewState.expandReasoning;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* How a reply's mermaid fences draw, seeded from the reader's section.
|
|
130
|
+
*
|
|
131
|
+
* The transform reads this per render instead of capturing it, because the
|
|
132
|
+
* settings document is hot-reloaded and a session already on screen has to
|
|
133
|
+
* follow the edit.
|
|
134
|
+
*/
|
|
135
|
+
let mermaidMode = defaultSettings().mermaid;
|
|
136
|
+
/** How each tool's cards draw; the settings document owns it and the view reads it live. */
|
|
137
|
+
let toolDisplay = defaultSettings().tools;
|
|
138
|
+
/** The keys that start a chord, and how long one waits; the settings document owns all of it. */
|
|
139
|
+
let prefixKeys = DEFAULT_PREFIX_KEYS;
|
|
140
|
+
let prefixWindowMs = DEFAULT_PREFIX_WINDOW_S * MS_PER_SECOND;
|
|
141
|
+
/** Every action's keys in force; the settings document owns it and a press reads it live. */
|
|
142
|
+
let keymap = defaultKeymap();
|
|
143
|
+
/** Whether prompts are recorded and offered, and the cap on how many; the settings document owns all three. */
|
|
144
|
+
let historyEnabled = false;
|
|
145
|
+
let historyGhost = false;
|
|
146
|
+
let historyMaxEntries = defaultSettings().history.maxEntries;
|
|
147
|
+
/**
|
|
148
|
+
* Seed the display the reader configured.
|
|
149
|
+
*
|
|
150
|
+
* The key toggles nested calls for one session, but a settings edit is a
|
|
151
|
+
* deliberate act, so it re-seeds and becomes the new starting point; the
|
|
152
|
+
* mermaid mode and the per-tool card fold have no key of their own and only
|
|
153
|
+
* ever come from the document. Installing the keys, and ending a chord armed
|
|
154
|
+
* under the map this edit replaced, belong to the prompt bar's owner.
|
|
155
|
+
*/
|
|
156
|
+
const applyDisplay = (section) => {
|
|
157
|
+
viewState.expandSubCalls = section.subcalls === 'inline';
|
|
158
|
+
mermaidMode = section.mermaid;
|
|
159
|
+
toolDisplay = section.tools;
|
|
160
|
+
prefixKeys = section.prefixes;
|
|
161
|
+
prefixWindowMs = section.prefixWindow * MS_PER_SECOND;
|
|
162
|
+
keymap = section.keymap;
|
|
163
|
+
ports.keybindings().installBindings();
|
|
164
|
+
historyEnabled = section.history.enabled;
|
|
165
|
+
historyGhost = section.history.ghost;
|
|
166
|
+
historyMaxEntries = section.history.maxEntries;
|
|
167
|
+
ports.keybindings().disarmChord();
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Read the reader's section once and apply everything it configures.
|
|
171
|
+
*
|
|
172
|
+
* One read per change, because a refused section is reported on the way past:
|
|
173
|
+
* reading it once per field would show the reader the same refusal twice.
|
|
174
|
+
*/
|
|
175
|
+
let applyingSettings = false;
|
|
176
|
+
const applySettings = () => {
|
|
177
|
+
// describe() can synchronously announce its first snapshot while it is being read.
|
|
178
|
+
if (applyingSettings)
|
|
179
|
+
return;
|
|
180
|
+
applyingSettings = true;
|
|
181
|
+
try {
|
|
182
|
+
const section = preferences.read();
|
|
183
|
+
previewTheme = undefined;
|
|
184
|
+
reportMissingTheme(section);
|
|
185
|
+
applyTheme(section);
|
|
186
|
+
appliedSection = section;
|
|
187
|
+
applyDisplay(section);
|
|
188
|
+
}
|
|
189
|
+
finally {
|
|
190
|
+
applyingSettings = false;
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Say so when the reader named a theme that nothing answers to.
|
|
195
|
+
*
|
|
196
|
+
* The schema cannot refuse the name: a theme is a file, so the set of names is
|
|
197
|
+
* known to the directory rather than to this build, and one can stop answering
|
|
198
|
+
* between two reads. Falling back to the default without a word would leave the
|
|
199
|
+
* reader looking at shades they did not choose, so the refusal lands here
|
|
200
|
+
* instead — beside the read that found it, and alongside the rest of the
|
|
201
|
+
* section, which is still theirs.
|
|
202
|
+
*/
|
|
203
|
+
const reportMissingTheme = (section) => {
|
|
204
|
+
const name = themeName(section);
|
|
205
|
+
if (name === undefined || themeLibrary.get(name) !== undefined)
|
|
206
|
+
return;
|
|
207
|
+
settingsNotice.post(`dsh-tui theme "${name}" is not a theme · themes: ${themeLibrary.names().join(' · ')} · the default, ${DEFAULT_THEME}, is drawn instead`);
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Choose a theme from a list the screen follows.
|
|
211
|
+
*
|
|
212
|
+
* Enter writes the choice through the settings document, the same path a typed
|
|
213
|
+
* name takes, so what lands is what the reader was looking at. Leaving the list
|
|
214
|
+
* restores the theme in force, because the document never changed while they
|
|
215
|
+
* looked.
|
|
216
|
+
*/
|
|
217
|
+
const openThemePicker = async () => {
|
|
218
|
+
const picked = await ports.openPicker(new ThemePicker(() => themeLibrary,
|
|
219
|
+
// What the surface draws right now, so a name pinned in the row is the
|
|
220
|
+
// row the list opens on instead of reading as no choice at all.
|
|
221
|
+
() => appliedSection === undefined ? ports.rowTheme : themeName(appliedSection), () => keymap, theme => showTheme(theme?.name)));
|
|
222
|
+
if (picked === undefined) {
|
|
223
|
+
showTheme(undefined);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// The row stays on screen until the document carries it: restoring first
|
|
227
|
+
// would flash the theme the reader just left. The write clears the preview as
|
|
228
|
+
// it lands, and a write that fails says so, leaving a theme that is still one
|
|
229
|
+
// of theirs rather than shades nothing chose.
|
|
230
|
+
preferences.chooseTheme(picked);
|
|
231
|
+
};
|
|
232
|
+
const runThemeCommand = (argument) => {
|
|
233
|
+
// A bare command is the list: a theme is judged by looking at it, so
|
|
234
|
+
// choosing one belongs in a list the screen follows rather than in a name
|
|
235
|
+
// the reader has to already know.
|
|
236
|
+
if (argument === '') {
|
|
237
|
+
void openThemePicker();
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
const [head = '', ...rest] = argument.split(/\s+/u);
|
|
241
|
+
// The table answers the other question a theme raises — which layer drew a
|
|
242
|
+
// shade — and stays reachable by name now that the list has the command.
|
|
243
|
+
if (head === 'tokens') {
|
|
244
|
+
// The table answers for the appearance on screen, not only for the
|
|
245
|
+
// document: a row-pinned theme would otherwise read as every shade
|
|
246
|
+
// untouched, which is the opposite of the question this command answers.
|
|
247
|
+
const section = appliedSection ?? preferences.read();
|
|
248
|
+
for (const line of renderThemeTable(toOverrides({ ...section, theme: previewTheme ?? themeName(section) }, themeLibrary), themeLibrary))
|
|
249
|
+
ports.notice(line);
|
|
250
|
+
ports.render();
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
// The one way a built-in becomes editable. Its file ships inside the
|
|
254
|
+
// package and the next version replaces it, so a reader who wants to
|
|
255
|
+
// change one needs a copy that is theirs — and the copy is a theme the
|
|
256
|
+
// moment it lands, which is why the table is re-read rather than patched.
|
|
257
|
+
if (head === 'export') {
|
|
258
|
+
const chosen = rest.join(' ').trim();
|
|
259
|
+
if (chosen === '') {
|
|
260
|
+
ports.notice(`theme export · which built-in? ${builtinNames(themeLibrary).join(' · ')}`);
|
|
261
|
+
ports.render();
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const outcome = exportTheme(themeLibrary, chosen);
|
|
265
|
+
if (outcome.ok) {
|
|
266
|
+
themeLibrary = loadThemes(themesHome, builtinThemesDir());
|
|
267
|
+
ports.notice(`theme · exported ${chosen} to ${outcome.path} · /theme ${outcome.select} applies it`);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
ports.notice(outcome.problem);
|
|
271
|
+
}
|
|
272
|
+
ports.render();
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
// A name nothing answers to is refused by name, like an unknown key
|
|
276
|
+
// layer: the reader asked for something, so the answer lists names.
|
|
277
|
+
if (themeLibrary.get(head) === undefined) {
|
|
278
|
+
ports.notice(`unknown theme "${head}" · themes: ${themeLibrary.names().join(' · ')}`);
|
|
279
|
+
ports.render();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
preferences.chooseTheme(head);
|
|
283
|
+
};
|
|
284
|
+
const preferences = createAppearancePreferences(ctx, {
|
|
285
|
+
rowSettings: ports.rowSettings,
|
|
286
|
+
rowSettingsLive: ports.rowSettingsLive,
|
|
287
|
+
applied: () => appliedSection,
|
|
288
|
+
apply: applySettings,
|
|
289
|
+
restyle,
|
|
290
|
+
restorePreview: () => showTheme(undefined),
|
|
291
|
+
disableHistory: () => { historyEnabled = false; historyGhost = false; },
|
|
292
|
+
notice: ports.notice,
|
|
293
|
+
problem: message => settingsNotice.post(message),
|
|
294
|
+
});
|
|
295
|
+
let reportedThemes = new Set();
|
|
296
|
+
const reportThemes = () => {
|
|
297
|
+
// Only what is newly wrong: the watcher re-reads the whole directory on every
|
|
298
|
+
// save, so an unfixed file would otherwise repeat its complaint on each one,
|
|
299
|
+
// and a reader who has just been told is not helped by being told again.
|
|
300
|
+
const problems = themeLibrary.problems();
|
|
301
|
+
for (const problem of problems) {
|
|
302
|
+
if (!reportedThemes.has(problem))
|
|
303
|
+
settingsNotice.post(problem);
|
|
304
|
+
}
|
|
305
|
+
reportedThemes = new Set(problems);
|
|
306
|
+
};
|
|
307
|
+
/**
|
|
308
|
+
* The reader's own themes: created, reported, and then watched.
|
|
309
|
+
*
|
|
310
|
+
* Created because a directory that is not there is a command that cannot work —
|
|
311
|
+
* `/theme export` names a path the reader should find where the surface said it
|
|
312
|
+
* would be. Watched because a theme is a file they are editing by hand, so
|
|
313
|
+
* saving one is how they ask for it; a session that needed a restart per shade
|
|
314
|
+
* would make the whole table useless for tuning. Everything unreadable is
|
|
315
|
+
* reported through the deferred notice rather than stderr, which the alternate
|
|
316
|
+
* screen is drawn over.
|
|
317
|
+
*/
|
|
318
|
+
const createThemesHome = () => {
|
|
319
|
+
for (const problem of ensureThemesHome(themesHome))
|
|
320
|
+
settingsNotice.post(problem);
|
|
321
|
+
reportThemes();
|
|
322
|
+
};
|
|
323
|
+
const watchThemeFiles = () => watchThemes(themesHome, () => {
|
|
324
|
+
themeLibrary = loadThemes(themesHome, builtinThemesDir());
|
|
325
|
+
reportThemes();
|
|
326
|
+
// The file that was just saved may be the theme already in force, so the
|
|
327
|
+
// table is rebuilt rather than only repainted.
|
|
328
|
+
applySettings();
|
|
329
|
+
restyle();
|
|
330
|
+
});
|
|
331
|
+
return {
|
|
332
|
+
theme,
|
|
333
|
+
viewState: () => viewState,
|
|
334
|
+
toggleCards,
|
|
335
|
+
toggleSubCalls,
|
|
336
|
+
toggleReasoning,
|
|
337
|
+
mermaidMode: () => mermaidMode,
|
|
338
|
+
toolDisplay: () => toolDisplay,
|
|
339
|
+
keymap: () => keymap,
|
|
340
|
+
prefixKeys: () => prefixKeys,
|
|
341
|
+
prefixWindowMs: () => prefixWindowMs,
|
|
342
|
+
historyEnabled: () => preferences.allowsHistory('enabled', historyEnabled),
|
|
343
|
+
historyGhost: () => preferences.allowsHistory('ghost', historyGhost),
|
|
344
|
+
historyMaxEntries: () => historyMaxEntries,
|
|
345
|
+
openNotices: sink => settingsNotice.open(sink),
|
|
346
|
+
registerSection: preferences.register,
|
|
347
|
+
createThemesHome,
|
|
348
|
+
settingsListener: preferences.listen,
|
|
349
|
+
watchThemes: watchThemeFiles,
|
|
350
|
+
runThemeCommand,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
//# sourceMappingURL=appearance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appearance.js","sourceRoot":"","sources":["../../src/surface/appearance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { SessionId } from '@deepseek-ai/dsh-session';
|
|
3
|
+
import type { TuiAgent } from '../agent/host.ts';
|
|
4
|
+
import { type JobSummary } from '../jobs.ts';
|
|
5
|
+
import { SubagentRoster } from '../subagents.ts';
|
|
6
|
+
/**
|
|
7
|
+
* What the background-work owner needs from the surface that composes it.
|
|
8
|
+
*
|
|
9
|
+
* The agent and the session on screen are read at call time: a command, a
|
|
10
|
+
* listener, or the job watch each has to follow whatever this terminal drives
|
|
11
|
+
* now, and a captured identity would follow the one it drove at construction.
|
|
12
|
+
*/
|
|
13
|
+
export interface BackgroundWorkPorts {
|
|
14
|
+
readonly drivingAgent: () => TuiAgent | undefined;
|
|
15
|
+
readonly activeSession: () => SessionId;
|
|
16
|
+
readonly notice: (text: string) => void;
|
|
17
|
+
readonly marker: (text: string) => void;
|
|
18
|
+
readonly render: () => void;
|
|
19
|
+
/** Show the session a child runs in; the viewed-session owner performs it. */
|
|
20
|
+
readonly navigate: (id: string) => void;
|
|
21
|
+
}
|
|
22
|
+
/** The commands and live reads the composing surface routes to this owner. */
|
|
23
|
+
export interface BackgroundWork {
|
|
24
|
+
readonly roster: SubagentRoster;
|
|
25
|
+
readonly jobs: () => readonly JobSummary[];
|
|
26
|
+
readonly refresh: () => void;
|
|
27
|
+
/** Fold the parent's durable catalog, which is where a child's task name lives. */
|
|
28
|
+
readonly acceptCatalog: (info: unknown) => void;
|
|
29
|
+
readonly resetRoster: () => void;
|
|
30
|
+
readonly runSubagentsCommand: (argument: string) => void;
|
|
31
|
+
readonly runJobsCommand: (argument: string) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Register the two subagent lifecycle listeners.
|
|
34
|
+
*
|
|
35
|
+
* They are returned rather than pushed here so the composition root keeps one
|
|
36
|
+
* ordered list of teardowns, which is unwound in reverse registration order.
|
|
37
|
+
*/
|
|
38
|
+
readonly subagentListeners: () => readonly (() => void)[];
|
|
39
|
+
readonly watchJobs: () => () => void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The work that runs beside the conversation: background jobs and child agents.
|
|
43
|
+
*
|
|
44
|
+
* Neither is folded from the transcript. A job board is live state owned by a
|
|
45
|
+
* service, and a child's name arrives on its own event, so this owner keeps
|
|
46
|
+
* those reads and the two commands that show them in one place.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createBackgroundWork(ctx: Context, ports: BackgroundWorkPorts): BackgroundWork;
|
|
49
|
+
//# sourceMappingURL=background-work.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-work.d.ts","sourceRoot":"","sources":["../../src/surface/background-work.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAML,KAAK,UAAU,EAChB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,cAAc,EAAgF,MAAM,iBAAiB,CAAA;AAO9H;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,QAAQ,GAAG,SAAS,CAAA;IACjD,QAAQ,CAAC,aAAa,EAAE,MAAM,SAAS,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,IAAI,CAAA;IAC3B,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAA;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,SAAS,UAAU,EAAE,CAAA;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAA;IAC5B,mFAAmF;IACnF,QAAQ,CAAC,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAC/C,QAAQ,CAAC,WAAW,EAAE,MAAM,IAAI,CAAA;IAChC,QAAQ,CAAC,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACxD,QAAQ,CAAC,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACnD;;;;;OAKG;IACH,QAAQ,CAAC,iBAAiB,EAAE,MAAM,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,CAAA;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,MAAM,IAAI,CAAA;CACrC;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,mBAAmB,GAAG,cAAc,CAwI7F"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { JOB_READ_LINES, createJobDirectory, describeJobs, parseJobsArgument, } from "../jobs.js";
|
|
2
|
+
import { SubagentRoster, createSubagentControl, describeSubagents, parseSubagentsArgument, resolveRun } from "../subagents.js";
|
|
3
|
+
/** Decode a lifecycle payload the roster only takes when it carries the shape it expects. */
|
|
4
|
+
function asRecord(value) {
|
|
5
|
+
return typeof value === 'object' && value !== null ? value : undefined;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* The work that runs beside the conversation: background jobs and child agents.
|
|
9
|
+
*
|
|
10
|
+
* Neither is folded from the transcript. A job board is live state owned by a
|
|
11
|
+
* service, and a child's name arrives on its own event, so this owner keeps
|
|
12
|
+
* those reads and the two commands that show them in one place.
|
|
13
|
+
*/
|
|
14
|
+
export function createBackgroundWork(ctx, ports) {
|
|
15
|
+
const jobDirectory = createJobDirectory(ctx);
|
|
16
|
+
let jobs = [];
|
|
17
|
+
const roster = new SubagentRoster();
|
|
18
|
+
const subagentControl = createSubagentControl(ctx);
|
|
19
|
+
/** Re-read the job board; it is live state, so nothing else can fold it. */
|
|
20
|
+
const refresh = () => {
|
|
21
|
+
const agent = ports.drivingAgent();
|
|
22
|
+
jobs = agent === undefined || jobDirectory === undefined ? [] : jobDirectory.list(agent.agent);
|
|
23
|
+
ports.render();
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* List or stop the delegations this session started.
|
|
27
|
+
*
|
|
28
|
+
* A child runs in the same process as an ordinary agent, so a stop is the
|
|
29
|
+
* cancel a reader's Ctrl+C sends to the parent; nothing here reaches into the
|
|
30
|
+
* child's own session, which keeps its own transcript either way.
|
|
31
|
+
*/
|
|
32
|
+
const runSubagentsCommand = (argument) => {
|
|
33
|
+
const command = parseSubagentsArgument(argument);
|
|
34
|
+
switch (command.kind) {
|
|
35
|
+
case 'list':
|
|
36
|
+
ports.notice(describeSubagents(roster.list(), Date.now()));
|
|
37
|
+
ports.render();
|
|
38
|
+
return;
|
|
39
|
+
case 'open': {
|
|
40
|
+
const run = resolveRun(roster.list(), command.id);
|
|
41
|
+
if (run === undefined) {
|
|
42
|
+
ports.notice(`${command.id}: no single child matches; /subagents lists them`);
|
|
43
|
+
ports.render();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
ports.navigate(run.id);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
case 'kill': {
|
|
50
|
+
const stopped = subagentControl?.stop(command.id) ?? false;
|
|
51
|
+
ports.notice(stopped
|
|
52
|
+
? `${command.id}: stop requested`
|
|
53
|
+
: `${command.id}: no live child with that id`);
|
|
54
|
+
ports.render();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
case 'invalid':
|
|
58
|
+
ports.notice(`/subagents: ${command.reason}`);
|
|
59
|
+
ports.render();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const runJobsCommand = (argument) => {
|
|
64
|
+
const agent = ports.drivingAgent();
|
|
65
|
+
if (jobDirectory === undefined) {
|
|
66
|
+
ports.notice('this profile has no job registry, so there is nothing to list');
|
|
67
|
+
ports.render();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (agent === undefined) {
|
|
71
|
+
ports.notice('the agent is still starting; try again in a moment');
|
|
72
|
+
ports.render();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const command = parseJobsArgument(argument);
|
|
76
|
+
switch (command.kind) {
|
|
77
|
+
case 'list':
|
|
78
|
+
refresh();
|
|
79
|
+
ports.notice(describeJobs(jobs, Date.now()));
|
|
80
|
+
ports.render();
|
|
81
|
+
return;
|
|
82
|
+
case 'read': {
|
|
83
|
+
const result = jobDirectory.read(agent.agent, command.id);
|
|
84
|
+
const text = result?.text.trim() ?? '';
|
|
85
|
+
ports.notice(text === ''
|
|
86
|
+
? `${command.id}: no output yet`
|
|
87
|
+
: `${command.id} output\n${text.split('\n').slice(-JOB_READ_LINES).join('\n')}`);
|
|
88
|
+
refresh();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
case 'kill': {
|
|
92
|
+
const outcome = jobDirectory.kill(agent.agent, command.id);
|
|
93
|
+
ports.notice(outcome === undefined
|
|
94
|
+
? `${command.id}: no such job`
|
|
95
|
+
: outcome === 'requested' ? `${command.id}: stop requested` : `${command.id} had already finished`);
|
|
96
|
+
refresh();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
case 'invalid':
|
|
100
|
+
ports.notice(`/jobs: ${command.reason}`);
|
|
101
|
+
ports.render();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Subagent lifecycle arrives as a service event rather than a session event,
|
|
107
|
+
* so it is decoration in the transcript: the parent's durable catalog
|
|
108
|
+
* carries the child's task. The name is cast so a rename in the
|
|
109
|
+
* harness cannot break compilation of this surface.
|
|
110
|
+
*/
|
|
111
|
+
const listenFor = (name, handler) => ctx.on(name, handler);
|
|
112
|
+
return {
|
|
113
|
+
roster,
|
|
114
|
+
jobs: () => jobs,
|
|
115
|
+
refresh,
|
|
116
|
+
acceptCatalog: info => roster.catalog(info),
|
|
117
|
+
resetRoster: () => roster.reset(),
|
|
118
|
+
runSubagentsCommand,
|
|
119
|
+
runJobsCommand,
|
|
120
|
+
subagentListeners: () => [
|
|
121
|
+
listenFor('subagent/start', info => {
|
|
122
|
+
roster.start(info);
|
|
123
|
+
const record = asRecord(info);
|
|
124
|
+
const provider = typeof record?.provider === 'string' ? record.provider : 'subagent';
|
|
125
|
+
const id = typeof record?.id === 'string' ? record.id : '';
|
|
126
|
+
ports.marker(`subagent ${provider} started${id === '' ? '' : ` · ${id}`}`);
|
|
127
|
+
ports.render();
|
|
128
|
+
}),
|
|
129
|
+
listenFor('subagent/end', info => {
|
|
130
|
+
roster.end(info);
|
|
131
|
+
const record = asRecord(info);
|
|
132
|
+
const provider = typeof record?.provider === 'string' ? record.provider : 'subagent';
|
|
133
|
+
const stop = typeof record?.stopReason === 'string' ? record.stopReason : undefined;
|
|
134
|
+
ports.marker(`subagent ${provider} finished${stop === undefined ? '' : ` · ${stop}`}`);
|
|
135
|
+
ports.render();
|
|
136
|
+
}),
|
|
137
|
+
],
|
|
138
|
+
// The board is live state: watch it directly rather than folding events.
|
|
139
|
+
watchJobs: () => jobDirectory?.watch(owner => {
|
|
140
|
+
if (owner !== undefined && owner.id !== ports.activeSession())
|
|
141
|
+
return;
|
|
142
|
+
refresh();
|
|
143
|
+
}) ?? (() => { }),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=background-work.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"background-work.js","sourceRoot":"","sources":["../../src/surface/background-work.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
3
|
+
import type { PresetRoster } from '../agent/presets.ts';
|
|
4
|
+
import type { RegisteredCommand } from '../input/completion.ts';
|
|
5
|
+
import { type Submission } from '../input/submission.ts';
|
|
6
|
+
import type { PromptStash } from '../stash.ts';
|
|
7
|
+
import type { StatusFacts } from '../ui/status.ts';
|
|
8
|
+
import type { Appearance } from './appearance.ts';
|
|
9
|
+
import type { BackgroundWork } from './background-work.ts';
|
|
10
|
+
import type { ModalInput } from './modal-input.ts';
|
|
11
|
+
import type { ModelChoice } from './model-choice.ts';
|
|
12
|
+
import type { PresetChoice, PresetLaunch } from './preset-choice.ts';
|
|
13
|
+
import type { PromptMemory } from './prompt-memory.ts';
|
|
14
|
+
import type { SessionLifecycle } from './session-lifecycle.ts';
|
|
15
|
+
import type { SessionView } from './session-view.ts';
|
|
16
|
+
import type { StagedTurns } from './staged-turns.ts';
|
|
17
|
+
import type { TerminalLifecycle } from './terminal-lifecycle.ts';
|
|
18
|
+
/**
|
|
19
|
+
* What the command plane needs from the surface that composes it.
|
|
20
|
+
*
|
|
21
|
+
* Each owner arrives whole, because this module is the one place that knows
|
|
22
|
+
* which of their operations a typed line, a chord, or the launch maps onto; the
|
|
23
|
+
* reads it takes of them are live, so a command typed after a session switch
|
|
24
|
+
* answers for the session now on screen. The launch facts and the mode roster
|
|
25
|
+
* are the two things no owner holds, and the notice and render sinks are what a
|
|
26
|
+
* refusal and a repaint are printed through.
|
|
27
|
+
*/
|
|
28
|
+
export interface CommandsPorts {
|
|
29
|
+
/** The launch this run was started for, and the mode its own flag named. */
|
|
30
|
+
readonly launch: PresetLaunch;
|
|
31
|
+
readonly preset: string | undefined;
|
|
32
|
+
/** The roster that can say whether a stored session's mode still exists. */
|
|
33
|
+
readonly presetRoster: PresetRoster | undefined;
|
|
34
|
+
/** A composition row that is missing, printed before the screen is taken. */
|
|
35
|
+
readonly missingOptional: () => string | undefined;
|
|
36
|
+
readonly session: SessionLifecycle;
|
|
37
|
+
readonly transcript: SessionView;
|
|
38
|
+
readonly route: ModelChoice;
|
|
39
|
+
readonly modes: PresetChoice;
|
|
40
|
+
readonly work: BackgroundWork;
|
|
41
|
+
readonly staged: StagedTurns;
|
|
42
|
+
readonly memory: PromptMemory;
|
|
43
|
+
readonly appearance: Appearance;
|
|
44
|
+
/** The terminal this surface owns, which is where a copy is written. */
|
|
45
|
+
readonly terminal: TerminalLifecycle;
|
|
46
|
+
/** The one modal interaction at a time, which lends its keyboard to a list. */
|
|
47
|
+
readonly modals: ModalInput;
|
|
48
|
+
readonly statusFacts: () => StatusFacts;
|
|
49
|
+
/** The bank the parked-draft commands read, late-bound behind the picker it needs. */
|
|
50
|
+
readonly stash: () => PromptStash | undefined;
|
|
51
|
+
readonly render: () => void;
|
|
52
|
+
}
|
|
53
|
+
/** The operations the composing surface routes back into the command plane. */
|
|
54
|
+
export interface Commands {
|
|
55
|
+
/** Carry out one classified line, wherever it was asked for. */
|
|
56
|
+
readonly runSubmission: (submission: Submission) => void;
|
|
57
|
+
/**
|
|
58
|
+
* The commands one agent can run, or undefined when no registry answers.
|
|
59
|
+
*
|
|
60
|
+
* A scoped read rather than the registry itself: the registry stays with this
|
|
61
|
+
* owner, and completion only ever needs the names it offers.
|
|
62
|
+
*/
|
|
63
|
+
readonly registeredCommands: (agent: Agent) => readonly RegisteredCommand[] | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Take the screen, then open the session this run was launched for.
|
|
66
|
+
*
|
|
67
|
+
* The launch belongs to this owner because the resume it may ask is the same
|
|
68
|
+
* question the resume command asks, answered by the same list.
|
|
69
|
+
*/
|
|
70
|
+
readonly start: () => Promise<void>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The router over everything the reader and the launcher can ask for.
|
|
74
|
+
*
|
|
75
|
+
* The registry is read from the composition rather than taken as a port: it is
|
|
76
|
+
* scoped to the agent in service, so its listing, lookup and dispatch all have
|
|
77
|
+
* to follow whichever agent the surface is driving now.
|
|
78
|
+
*/
|
|
79
|
+
export declare function createCommands(ctx: Context, ports: CommandsPorts): Commands;
|
|
80
|
+
//# sourceMappingURL=commands.d.ts.map
|