@sagmans/dsh-tui 0.1.2 → 0.3.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/README.md +196 -17
- package/cordis.patch.yml +4 -2
- package/lib/agent/host.d.ts +14 -0
- package/lib/agent/host.d.ts.map +1 -1
- package/lib/agent/host.js +20 -4
- package/lib/agent/host.js.map +1 -1
- package/lib/agent/model.d.ts +50 -0
- package/lib/agent/model.d.ts.map +1 -1
- package/lib/agent/model.js +87 -1
- package/lib/agent/model.js.map +1 -1
- package/lib/agent/present.d.ts +7 -1
- package/lib/agent/present.d.ts.map +1 -1
- package/lib/agent/present.js +33 -4
- package/lib/agent/present.js.map +1 -1
- package/lib/agent/presets.d.ts +7 -1
- package/lib/agent/presets.d.ts.map +1 -1
- package/lib/agent/presets.js +7 -3
- package/lib/agent/presets.js.map +1 -1
- package/lib/agent/status.d.ts +10 -0
- package/lib/agent/status.d.ts.map +1 -1
- package/lib/agent/status.js +2 -0
- package/lib/agent/status.js.map +1 -1
- package/lib/cards.d.ts +127 -7
- package/lib/cards.d.ts.map +1 -1
- package/lib/cards.js +381 -52
- package/lib/cards.js.map +1 -1
- package/lib/export.d.ts +5 -4
- package/lib/export.d.ts.map +1 -1
- package/lib/export.js +62 -13
- package/lib/export.js.map +1 -1
- package/lib/fold-cursor.d.ts +23 -0
- package/lib/fold-cursor.d.ts.map +1 -0
- package/lib/fold-cursor.js +31 -0
- package/lib/fold-cursor.js.map +1 -0
- package/lib/gates.d.ts +145 -2
- package/lib/gates.d.ts.map +1 -1
- package/lib/gates.js +335 -40
- package/lib/gates.js.map +1 -1
- package/lib/index.d.ts +7 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +651 -92
- package/lib/index.js.map +1 -1
- package/lib/input/actions.d.ts +136 -0
- package/lib/input/actions.d.ts.map +1 -0
- package/lib/input/actions.js +740 -0
- package/lib/input/actions.js.map +1 -0
- package/lib/input/keymap-settings.d.ts +21 -0
- package/lib/input/keymap-settings.d.ts.map +1 -0
- package/lib/input/keymap-settings.js +28 -0
- package/lib/input/keymap-settings.js.map +1 -0
- package/lib/input/keymap.d.ts +91 -0
- package/lib/input/keymap.d.ts.map +1 -0
- package/lib/input/keymap.js +170 -0
- package/lib/input/keymap.js.map +1 -0
- package/lib/input/match.d.ts +10 -0
- package/lib/input/match.d.ts.map +1 -0
- package/lib/input/match.js +83 -0
- package/lib/input/match.js.map +1 -0
- package/lib/input/submission.d.ts +8 -1
- package/lib/input/submission.d.ts.map +1 -1
- package/lib/input/submission.js +9 -2
- package/lib/input/submission.js.map +1 -1
- package/lib/input.d.ts +17 -0
- package/lib/input.d.ts.map +1 -0
- package/lib/input.js +27 -0
- package/lib/input.js.map +1 -0
- package/lib/keys-command.d.ts +16 -0
- package/lib/keys-command.d.ts.map +1 -0
- package/lib/keys-command.js +60 -0
- package/lib/keys-command.js.map +1 -0
- package/lib/queue.d.ts +6 -0
- package/lib/queue.d.ts.map +1 -0
- package/lib/queue.js +68 -0
- package/lib/queue.js.map +1 -0
- package/lib/settings-notice.d.ts +19 -0
- package/lib/settings-notice.d.ts.map +1 -0
- package/lib/settings-notice.js +30 -0
- package/lib/settings-notice.js.map +1 -0
- package/lib/terminal/warning-screen.d.ts +8 -0
- package/lib/terminal/warning-screen.d.ts.map +1 -0
- package/lib/terminal/warning-screen.js +66 -0
- package/lib/terminal/warning-screen.js.map +1 -0
- package/lib/theme-capability.d.ts +36 -0
- package/lib/theme-capability.d.ts.map +1 -0
- package/lib/theme-capability.js +190 -0
- package/lib/theme-capability.js.map +1 -0
- package/lib/theme-command.d.ts +10 -0
- package/lib/theme-command.d.ts.map +1 -0
- package/lib/theme-command.js +61 -0
- package/lib/theme-command.js.map +1 -0
- package/lib/theme-settings.d.ts +196 -0
- package/lib/theme-settings.d.ts.map +1 -0
- package/lib/theme-settings.js +229 -0
- package/lib/theme-settings.js.map +1 -0
- package/lib/theme-tokens.d.ts +110 -0
- package/lib/theme-tokens.d.ts.map +1 -0
- package/lib/theme-tokens.js +427 -0
- package/lib/theme-tokens.js.map +1 -0
- package/lib/theme.d.ts +32 -35
- package/lib/theme.d.ts.map +1 -1
- package/lib/theme.js +112 -63
- package/lib/theme.js.map +1 -1
- package/lib/tokens.d.ts +15 -0
- package/lib/tokens.d.ts.map +1 -0
- package/lib/tokens.js +29 -0
- package/lib/tokens.js.map +1 -0
- package/lib/transcript.d.ts +26 -1
- package/lib/transcript.d.ts.map +1 -1
- package/lib/transcript.js +153 -25
- package/lib/transcript.js.map +1 -1
- package/lib/ui/dock.d.ts.map +1 -1
- package/lib/ui/dock.js +67 -28
- package/lib/ui/dock.js.map +1 -1
- package/lib/ui/editor.d.ts +51 -0
- package/lib/ui/editor.d.ts.map +1 -0
- package/lib/ui/editor.js +159 -0
- package/lib/ui/editor.js.map +1 -0
- package/lib/ui/frame.d.ts +54 -0
- package/lib/ui/frame.d.ts.map +1 -0
- package/lib/ui/frame.js +79 -0
- package/lib/ui/frame.js.map +1 -0
- package/lib/ui/gate-input.d.ts +20 -0
- package/lib/ui/gate-input.d.ts.map +1 -0
- package/lib/ui/gate-input.js +96 -0
- package/lib/ui/gate-input.js.map +1 -0
- package/lib/ui/markdown.d.ts +19 -2
- package/lib/ui/markdown.d.ts.map +1 -1
- package/lib/ui/markdown.js +37 -6
- package/lib/ui/markdown.js.map +1 -1
- package/lib/ui/mermaid.d.ts +44 -0
- package/lib/ui/mermaid.d.ts.map +1 -0
- package/lib/ui/mermaid.js +178 -0
- package/lib/ui/mermaid.js.map +1 -0
- package/lib/ui/picker.d.ts +66 -7
- package/lib/ui/picker.d.ts.map +1 -1
- package/lib/ui/picker.js +112 -19
- package/lib/ui/picker.js.map +1 -1
- package/lib/ui/prompt.d.ts +30 -0
- package/lib/ui/prompt.d.ts.map +1 -0
- package/lib/ui/prompt.js +45 -0
- package/lib/ui/prompt.js.map +1 -0
- package/lib/ui/queue.d.ts +24 -0
- package/lib/ui/queue.d.ts.map +1 -0
- package/lib/ui/queue.js +57 -0
- package/lib/ui/queue.js.map +1 -0
- package/lib/ui/status.d.ts +7 -1
- package/lib/ui/status.d.ts.map +1 -1
- package/lib/ui/status.js +84 -24
- package/lib/ui/status.js.map +1 -1
- package/lib/ui/view.d.ts +65 -2
- package/lib/ui/view.d.ts.map +1 -1
- package/lib/ui/view.js +319 -59
- package/lib/ui/view.js.map +1 -1
- package/lib/work.d.ts +48 -0
- package/lib/work.d.ts.map +1 -1
- package/lib/work.js +44 -0
- package/lib/work.js.map +1 -1
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -88,6 +88,7 @@ Two facts explain most failures.
|
|
|
88
88
|
| `dsh: cannot resolve profile bundle "@sagmans/dsh-tui" ...` | the linked checkout moved or was deleted | `dsh plugin --profile tui add "$PLUGIN_CHECKOUT"` |
|
|
89
89
|
| `dsh --profile tui` prints nothing and never exits | the bundle left `dsh.profile.bundles`, usually after a broken link and a `plugin install` | confirm the layer list, then run the `add` command again |
|
|
90
90
|
| `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 |
|
|
91
|
+
| 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 |
|
|
91
92
|
| Changes under `src/` have no effect | a linked profile loads `lib/`, not `src/` | `pnpm run build` in the plugin checkout |
|
|
92
93
|
| `pnpm dsh --profile tui` exits before the surface appears | pnpm's dependency check fails on the harness checkout's own postinstall | see [Launching from a harness checkout](#launching-from-a-harness-checkout) |
|
|
93
94
|
| `--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` |
|
|
@@ -110,32 +111,43 @@ node -p "require((process.env.DSH_HOME ?? require('node:os').homedir() + '/.dsh'
|
|
|
110
111
|
dsh --profile tui # new session in the current directory
|
|
111
112
|
dsh --profile tui --resume # pick a stored session, titled by its first prompt
|
|
112
113
|
dsh --profile tui --resume <session-id>
|
|
113
|
-
dsh --profile tui --preset
|
|
114
|
+
dsh --profile tui --preset minimal # start in a shipped mode other than the default (PTC)
|
|
114
115
|
dsh --profile tui --model deepseek-chat
|
|
115
116
|
dsh --profile tui --no-color
|
|
116
117
|
dsh --profile tui --no-bell # do not ring when a long turn finishes
|
|
117
118
|
```
|
|
118
119
|
|
|
120
|
+
Every key below is a shipped default. `/keys` lists every action the surface
|
|
121
|
+
and its library can perform with the keys in force, and the `keys:` section
|
|
122
|
+
moves any of them — see [Keys](#keys).
|
|
123
|
+
|
|
119
124
|
| Key | Action |
|
|
120
125
|
|---|---|
|
|
121
|
-
| Enter |
|
|
126
|
+
| Enter / Shift+Enter | break the line: a prompt is written before it is sent |
|
|
127
|
+
| Ctrl+Enter / Alt+Enter / Ctrl+S | submit the prompt |
|
|
122
128
|
| Ctrl+C | interrupt the running turn, or leave when idle |
|
|
123
|
-
| Ctrl+O |
|
|
124
|
-
| Ctrl+
|
|
129
|
+
| Ctrl+O | open every tool card: its header plus every retained row. Folded, a card is one line, and a shell card keeps its command plus the last 20 rows of output with a hint naming what it dropped |
|
|
130
|
+
| Ctrl+Y | show or hide the calls a PTC program dispatched: one two-space-indented entry per call under its `run_code` card, named and argued from the tool's own header and wrapped at the screen edge; shown by default |
|
|
131
|
+
| Shift+Tab | expand or fold the reasoning behind an answer: folded, the row names itself, its token count, and the key; opened, it adds the thought |
|
|
132
|
+
| Ctrl+T | pick the reasoning effort for the next step |
|
|
133
|
+
| Ctrl+X then M | open the model picker |
|
|
134
|
+
| Ctrl+X then Y | copy the last answer to the clipboard |
|
|
125
135
|
| `y` / `n` / Esc | allow once, reject, or cancel a pending approval |
|
|
126
|
-
| digits / space / ↑↓ / Enter / Esc | answer a question: pick or toggle, confirm, or skip one |
|
|
136
|
+
| digits / space / ↑↓ / Enter / Esc | answer a question: pick or toggle, confirm, or skip one; `0` answers with your own text in the input bar |
|
|
137
|
+
| typing in any picker or question | narrow the rows by fragment (`glm53` finds `GLM-5.3`); backspace widens, `esc` or Ctrl+C leaves |
|
|
127
138
|
| `/` then Tab | complete commands, including every command this session registered |
|
|
128
139
|
| `@` or a path then Tab | complete workspace file references |
|
|
129
140
|
| `ctrl+shift+f` | search the transcript (`enter` next, `shift+enter` previous, `esc` close) |
|
|
130
141
|
| `home` / `end` | jump to the start or the end of the transcript |
|
|
131
142
|
| `ctrl+down` | jump to the next prompt |
|
|
132
|
-
| `ctrl+b` | leave a child's conversation and return to this session |
|
|
143
|
+
| `ctrl+b` | leave a child's conversation and return to this session (the status line names the key you have now) |
|
|
133
144
|
| mouse wheel, drag | scroll, and copy a selection through OSC 52 |
|
|
134
145
|
| `/help` | list registered and local commands |
|
|
135
146
|
| `/status` | show the session id, model, permissions, context, and directory |
|
|
136
|
-
| `/model` |
|
|
147
|
+
| `/model` | open the picker for the configured providers and their models; it heads itself with the route the next step will use, and typing filters it by fragment (`glm53` finds `GLM-5.3`) |
|
|
137
148
|
| `/model <provider>` | list that provider's advertised models |
|
|
138
149
|
| `/model <provider>/<model>` | use that route from the next step on (session only, nothing is written to settings) |
|
|
150
|
+
| `/model <provider>/<model>/<effort>` | use that route and reasoning effort (the effort must be one the route advertises) |
|
|
139
151
|
| `/preset` | pick the agent mode for this session from the roster |
|
|
140
152
|
| `/preset <id>` | switch to that mode, while the session is still blank |
|
|
141
153
|
| `/jobs` | list background jobs with their state and duration |
|
|
@@ -148,10 +160,156 @@ dsh --profile tui --no-bell # do not ring when a long turn finishes
|
|
|
148
160
|
| `/export [path]` | write the visible transcript as markdown (default `dsh-session-<id>.md`) |
|
|
149
161
|
| `/resume` | open another stored session without leaving the terminal |
|
|
150
162
|
| `/clear` | clear the visible transcript |
|
|
163
|
+
| `/theme` | list every styled element and the value in force |
|
|
164
|
+
| `/keys` | list every action and the keys in force; `/keys <layer>` narrows it (see [Keys](#keys)) |
|
|
151
165
|
| `/quit` | leave and print the resume command |
|
|
152
166
|
|
|
167
|
+
`Ctrl+X` starts a chord. For the next two seconds the footer leads with the
|
|
168
|
+
prefix alone — enough to say that a key is waiting, without reciting the map —
|
|
169
|
+
and a key that finishes nothing is typed as usual rather than swallowed, so a
|
|
170
|
+
prefix pressed by accident costs nothing; `/help` lists the chords, `m` for the
|
|
171
|
+
model picker, `p` for plan mode, and `y` for the last answer.
|
|
172
|
+
`keys.chord.prefix: alt+x` starts the chord with another key — or with a list of
|
|
173
|
+
them, as so many ways in — and `prefixWindow: 0` waits for the next key instead
|
|
174
|
+
of lapsing; every second key is a row of its own (`chord.model`, `chord.plan`,
|
|
175
|
+
`chord.copy`), so a chord can be respelled whole. A prefix that is not a modifier chord, that
|
|
176
|
+
the surface or the prompt bar already answers (`ctrl+c`, `ctrl+s`), or that the
|
|
177
|
+
terminal keeps (`ctrl+q`) is refused with the reason, and the shipped keymap
|
|
178
|
+
stays in force. The chords themselves are the commands they stand for: `m`, `p`,
|
|
179
|
+
and `y` ask the same dispatcher `/model`, `/plan`, and `/copy` do. Plan mode is
|
|
180
|
+
the one pair that cannot share a name: `/plan` only enters, so the chord names
|
|
181
|
+
`/plan off` instead when the agent is in plan mode — or is waiting for the turn
|
|
182
|
+
boundary to become so — and reads that state from the plan package rather than
|
|
183
|
+
from the dock.
|
|
184
|
+
|
|
185
|
+
An approval or a question draws inline above the editor and takes the keyboard. A question that lists options always adds row `0. other — type your own answer`: type or paste an answer the model did not offer, and the seam receives it as that question's free text — replacing a single-select choice, or supplementing a multi-select one. `0`, or `↓` past the last option, reaches the row; `↑` walks back to the list with the text kept, and `esc` does the same from that row, because a question skipped by accident is a question answered twice — an escape from the list skips it. Free text is written in the prompt bar's own editor, drawn under that row: movement, word and line deletion, undo, completion, and multi-line paste are all the editor the reader already uses, and the prompt bar steps aside while a question is open, so a prompt written but not sent comes back untouched once the question is answered. No question hides its answer — the reader is the one who has to check what they are about to send. Every gate row wraps at the screen edge under its own label, so a long option or question is readable rather than cut.
|
|
186
|
+
|
|
187
|
+
While a turn runs, a prompt submitted into the editor waits in the agent's own inbox instead of disappearing: it is drawn above the editor in the input bar's own frame, faint and italic, and moves into the transcript when the agent takes it — where it keeps that frame in the prompt's own mint shade, so what the reader typed is never mistaken for what the agent said. `editor.queued` and `editor.queued.more` restyle or hide the waiting rows; `transcript.user` restyles the submitted prompt.
|
|
188
|
+
|
|
153
189
|
Any other `/command` goes to the command registry, so `/plan`, `/compact`, `/goal`, and `/feedback` behave as they do on the other surfaces.
|
|
154
190
|
|
|
191
|
+
## Settings
|
|
192
|
+
|
|
193
|
+
Every styled element is a named token with a shipped default, and every key is
|
|
194
|
+
an action with one, so the surface can be restyled and rebound without touching
|
|
195
|
+
code. Preferences live in the same user-settings document as every other
|
|
196
|
+
(`$DSH_HOME/settings.yaml`), under a `dsh-tui:` section:
|
|
197
|
+
|
|
198
|
+
```yaml
|
|
199
|
+
dsh-tui:
|
|
200
|
+
subcalls: collapsed # fold the calls a PTC program dispatched (default inline)
|
|
201
|
+
mermaid: streaming # draw a reply's mermaid fences: off, final, or streaming (default streaming)
|
|
202
|
+
prefixWindow: 2 # seconds a chord waits for its second key; 0 waits for the next key instead
|
|
203
|
+
keys:
|
|
204
|
+
chord.prefix: ctrl+x # the key that starts a chord; "prefix:" is the older spelling of this row
|
|
205
|
+
prompt.submit: [ctrl+enter, alt+enter, ctrl+s]
|
|
206
|
+
surface.effort: ctrl+t # one key, or a list of them
|
|
207
|
+
tui.editor.yank: ctrl+y # any action the library draws, by the id /keys prints
|
|
208
|
+
palette:
|
|
209
|
+
muted: '#5c5c5c' # one shade quiets every receding element
|
|
210
|
+
tokens:
|
|
211
|
+
transcript.reasoning.body:
|
|
212
|
+
fg: '#7a7a7a'
|
|
213
|
+
italic: true
|
|
214
|
+
tool.title:
|
|
215
|
+
fg: accent # a palette name, a hex value, or an index 0-255
|
|
216
|
+
bold: true
|
|
217
|
+
dock.jobs.heading:
|
|
218
|
+
hidden: true # the element renders nothing at all
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Every field is optional, so a section that changes one shade is enough. The
|
|
222
|
+
document is hot-reloaded: an edit restyles a running session and re-arms the
|
|
223
|
+
keymap on the next press, and `/theme` shows each element's effective value and
|
|
224
|
+
whether it came from an override, the palette, or the default.
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
The section is not only shades. By default every session draws the calls a PTC
|
|
228
|
+
program dispatched under their card, and `subcalls: collapsed` starts with the
|
|
229
|
+
card alone instead. `Ctrl+Y` toggles the same choice for the current session,
|
|
230
|
+
and an edit to the document re-seeds it. An unknown key or value is
|
|
231
|
+
refused with a notice naming it, so a typo cannot quietly do nothing.
|
|
232
|
+
|
|
233
|
+
A reply whose fenced block names `mermaid` is drawn as terminal box art instead
|
|
234
|
+
of source, laid out at the width the transcript has. `mermaid: streaming` (the
|
|
235
|
+
default) draws a diagram while the reply is still arriving, `final` waits for
|
|
236
|
+
the turn to end, and `off` leaves every fence exactly as written. A diagram
|
|
237
|
+
wider than the terminal, one the renderer cannot draw at all, or one whose source
|
|
238
|
+
is larger than a frame can lay out stays as the source fence rather than being
|
|
239
|
+
truncated; a settled diagram whose source was only partly readable keeps the
|
|
240
|
+
fence and names what was dropped. The drawing is
|
|
241
|
+
restyleable like anything else through `markdown.diagram.border`,
|
|
242
|
+
`.text`, `.edge`, `.edgeLabel`, `.title`, and `.warning`, so `/theme`
|
|
243
|
+
lists it with the rest. Nothing is lost by drawing: `/export` and the session
|
|
244
|
+
file keep the reply exactly as the model wrote it.
|
|
245
|
+
|
|
246
|
+
`fg` and `bg` accept `#rrggbb`, a palette name (`default`, `muted`, `accent`,
|
|
247
|
+
`arg`, `warn`, `added`, `removed`, `user`, `assistant`), or an index. A colour is
|
|
248
|
+
emitted as 24-bit when the terminal advertises it (`COLORTERM`) and degraded to
|
|
249
|
+
the nearest 256-colour entry or 16-colour slot otherwise; a hue keeps its family
|
|
250
|
+
there, so an addition stays green instead of collapsing to black. Muted elements
|
|
251
|
+
name the palette rather than a terminal slot, so on anything but a 16-colour
|
|
252
|
+
terminal their contrast does not depend on what the reader's colour scheme maps
|
|
253
|
+
slot 8 to. `arg` is the pale blue a card gives the argument it was called with,
|
|
254
|
+
so `tool.args` is restyled on its own and stays distinct from the tool's own
|
|
255
|
+
label and from its output. `user` is the mint a submitted prompt takes, so a
|
|
256
|
+
reader's own turns stand apart from the reply without reading either.
|
|
257
|
+
|
|
258
|
+
`NO_COLOR` and `--no-color` disable styling entirely, attributes included, and
|
|
259
|
+
outrank everything in this section. A token or palette name the surface does not
|
|
260
|
+
have is refused with the offending name, and the surface prints the refusal as a
|
|
261
|
+
notice when the document loads, so a typo cannot quietly paint nothing.
|
|
262
|
+
|
|
263
|
+
### Keys
|
|
264
|
+
|
|
265
|
+
Every press the surface answers is an action with an id and a shipped key.
|
|
266
|
+
`/keys` prints all of them with the keys in force, marks the rows you wrote,
|
|
267
|
+
names the keys your map took from the library, and ends with a sample `keys:`
|
|
268
|
+
section rather than a whole one; the table above it is the complete account.
|
|
269
|
+
`/keys prompt`, `surface`, `chord`, `gate`, `question`,
|
|
270
|
+
`picker`, and `library` narrow that list to one part of the surface.
|
|
271
|
+
|
|
272
|
+
An entry is one key or a list of them. A key is a modifier chord
|
|
273
|
+
(`ctrl`/`alt`/`shift` joined by `+`, written in that order), a named key
|
|
274
|
+
(`enter`, `escape`, `tab`, `space`, `backspace`, `delete`, `home`, `end`,
|
|
275
|
+
`pageUp`, `pageDown`, the arrows, `f1`–`f12`), or a bare character where the
|
|
276
|
+
layer reads one: `y` and `n` for an approval, or a chord's second key. Ids
|
|
277
|
+
beginning `tui.` are pi-tui's own actions, so the editor, the search, and the
|
|
278
|
+
transcript move where you tell them to.
|
|
279
|
+
|
|
280
|
+
Refused, with the reason in a notice and the shipped map left in force: an
|
|
281
|
+
action the surface does not have, a key no terminal reports, `ctrl+q` (the
|
|
282
|
+
terminal keeps it), a bare character outside the chord and gate layers, two
|
|
283
|
+
actions of one layer on one press, a key the library already answers on a row you
|
|
284
|
+
never wrote, a key the viewport reads before the surface sees it, whichever of the
|
|
285
|
+
two the map moved onto it (`pageUp`, or `tui.altScreen.search` moved onto a
|
|
286
|
+
surface key), a `chord.prefix` that is not a modifier chord or that takes a key
|
|
287
|
+
the surface or the prompt bar answers, and `prefix:` beside
|
|
288
|
+
`keys.chord.prefix:`, which are the same row under two names.
|
|
289
|
+
|
|
290
|
+
Two rows count as one press when some sequence reaches both, not merely when they
|
|
291
|
+
are spelled alike, because one press can arrive as several bytes and one byte can
|
|
292
|
+
spell several keys. A bare terminal reports Return for `enter` and `ctrl+m`, a
|
|
293
|
+
line feed for `ctrl+j` and, without the keyboard protocol, Return as well, one
|
|
294
|
+
control byte carries both `ctrl+-` and `ctrl+_`, and an escape with a letter
|
|
295
|
+
reaches `alt+up` as readily as `alt+p`.
|
|
296
|
+
|
|
297
|
+
A key the surface or a chord answers is a key the library never sees: that is
|
|
298
|
+
how `ctrl+y` shows nested calls instead of yanking a line in the editor.
|
|
299
|
+
`/keys` names every shadow your map introduces, and moving the surface key
|
|
300
|
+
hands the library its own key back.
|
|
301
|
+
|
|
302
|
+
Left alone, because they are typing rather than commands: the keys a question's
|
|
303
|
+
filter narrows with and the ones that leave its free-text row, the digits and
|
|
304
|
+
row `0` that name an option, and the mouse.
|
|
305
|
+
|
|
306
|
+
One residual escapes that promise, and it is not the surface's to close. After a
|
|
307
|
+
component returns its rows, the framework appends a reset to each row and closes
|
|
308
|
+
the hyperlink it wraps them in, so a session can still receive a bare `ESC[0m`
|
|
309
|
+
with colour off. It paints nothing. It is recorded here because "no escapes at
|
|
310
|
+
all" is otherwise the claim, and because the surface cannot make good on it
|
|
311
|
+
alone.
|
|
312
|
+
|
|
155
313
|
## Modes
|
|
156
314
|
|
|
157
315
|
A mode is an **agent preset**: the plugin composition an agent's own scope joins. It decides that agent's tools, prompt sections, skills, and planning rows, which is why a mode is fixed once a session has produced a turn — it is what composed the agent that answered.
|
|
@@ -160,8 +318,8 @@ Four ship, under the ids a session log records:
|
|
|
160
318
|
|
|
161
319
|
| `--preset` | Mode | What the agent gets |
|
|
162
320
|
|---|---|---|
|
|
321
|
+
| `ptc` | PTC (default) | the same agent, reaching its tools through one TypeScript program |
|
|
163
322
|
| `standard` | standard | full agent: editing, shell, search, skills, planning, goals, subagents, workflows |
|
|
164
|
-
| `ptc` | PTC | the same agent, reaching its tools through one TypeScript program |
|
|
165
323
|
| `minimal` | minimal | one tool: a persistent shell |
|
|
166
324
|
| `cordis` | creator | harness authoring: runtime inspection and composition guidance |
|
|
167
325
|
|
|
@@ -169,7 +327,7 @@ A session takes its mode from the first of these that applies:
|
|
|
169
327
|
|
|
170
328
|
1. `--preset <id>`, refused before the terminal is taken over when the roster does not ship that id.
|
|
171
329
|
2. `/preset` while the session is still blank: a bare command opens the picker, `/preset <id>` switches directly, and the choice is written to the log.
|
|
172
|
-
3. The roster's default, `
|
|
330
|
+
3. The roster's default, `ptc`, when nobody names one.
|
|
173
331
|
|
|
174
332
|
The mode is re-read rather than remembered: resuming mounts what that session's own log recorded, resuming with a `--preset` that disagrees with it is refused instead of silently ignored, and forking inherits the mode of the conversation being branched. The status line names the mode, and `/status` lists it with the rest.
|
|
175
333
|
|
|
@@ -182,8 +340,16 @@ The package is a Cordis plugin bundle that stacks over `@deepseek-ai/dsh-base`:
|
|
|
182
340
|
- `@deepseek-ai/dsh-code-runtime-worker-thread` and `@deepseek-ai/dsh-cordis-host-runner` are the host machinery PTC mode and creator mode need; only the Web bundle shipped them, so a terminal profile has to mount them to offer those modes at all.
|
|
183
341
|
- `@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.
|
|
184
342
|
|
|
343
|
+
A question whose id ends in `:secret` declares its typed answer a credential: the bar hides everything but its first and last four characters, and the free-text row a question with options offers is labelled `API KEY`. Wording is not a declaration, because hiding every question that mentions a key would hide answers their authors meant to be read.
|
|
344
|
+
|
|
185
345
|
The fold is durable-only: the live stream decorates the row that is still being written, and everything else — cards, reasoning, work state, compaction markers — comes from the log, so a resumed session renders what the live one did. Subagent start and finish are the exception: they arrive as service events, and the transcript shows them as decoration because the durable record of a delegation is the tool call that asked for it.
|
|
186
346
|
|
|
347
|
+
Tool cards are folded by default: a card draws its header and nothing else, so a long read, diff, or search cannot bury the conversation. A shell card is the exception, because its output is the answer the reader asked for: it names the tool in its header, always shows the command that ran, keeps the last 20 output rows, and adds a hint naming the rows it dropped. `Ctrl+O` opens every card to its header plus every retained row.
|
|
348
|
+
|
|
349
|
+
A PTC card is the one card with children: every call the `run_code` program dispatched hangs off the card that made it, and each draws under the header as the tool's own name and argument, wrapping rather than being cut. `Ctrl+Y` folds them away again, and `subcalls: collapsed` starts every session folded; see [Settings](#settings).
|
|
350
|
+
|
|
351
|
+
A card's header names the tool, 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.
|
|
352
|
+
|
|
187
353
|
The bundle also takes the base's global agent rows out of the composition, twenty-three of them. Every one is a row the shipped modes supply per session instead, so leaving it mounted registers the same tool names in two layers and doubles each prompt section it owns. What stays mounted is the host: sessions, storage, models, permissions, jobs, and the command registry.
|
|
188
354
|
|
|
189
355
|
## Development
|
|
@@ -227,13 +393,24 @@ The automated checks drive a real PTY, but they run on this machine's terminal.
|
|
|
227
393
|
| `NO_COLOR=1 dsh --profile tui` | no styling anywhere, layout unchanged |
|
|
228
394
|
| `dsh --profile tui --no-bell` | a turn that runs for minutes still ends silently |
|
|
229
395
|
| `dsh --profile tui --preset ptc`, then a turn | the status line names `ptc`, and the agent reaches its tools through one TypeScript program rather than one shell call at a time |
|
|
396
|
+
| a PTC turn | one entry per dispatched call draws two spaces indented under the `run_code` header, from the first frame and with no keypress |
|
|
397
|
+
| that turn in a terminal narrower than a call's own argument | the argument wraps onto continuation rows indented to the same two spaces, with no ellipsis |
|
|
398
|
+
| that same turn, then `ctrl+y` | the lines fold away; `ctrl+y` again draws them back |
|
|
399
|
+
| `dsh-tui: { subcalls: collapsed }` in `$DSH_HOME/settings.yaml`, then a PTC turn | the card arrives alone, and editing the document to `inline` unfolds a running session |
|
|
400
|
+
| a reply carrying a mermaid fence | it draws as box art at the transcript width, with the prose around it untouched |
|
|
401
|
+
| that reply in a terminal narrower than the drawing | the fence stays source, and widening the window draws it without a new turn |
|
|
402
|
+
| `dsh-tui: { mermaid: off }` in `$DSH_HOME/settings.yaml`, then a mermaid reply | the fence stays source; editing the value to `streaming` draws a settled reply without a restart |
|
|
403
|
+
| `/model` on a configured profile | the picker lists only the configured providers' advertised models, heads itself with the route in force, and typing filters it while later rows stream in; `esc` or Ctrl+C leaves without changing the route, and `enter` chains into the route's reasoning efforts |
|
|
230
404
|
| `/preset` on a fresh session | the picker lists four modes, marks the current one, and the switch survives a resume |
|
|
231
405
|
| `/preset minimal` after a turn | refused, naming the reason; the session keeps the mode it composed with |
|
|
232
406
|
| `--resume --preset <mode>` and then picking a session that runs another mode | the list stays open and says why that row cannot be taken; `esc` leaves the picker |
|
|
233
407
|
| `dsh --profile tui --preset nope` | exits non-zero naming the modes that do exist, before the alternate screen appears |
|
|
234
408
|
| arrow keys in a picker, or on a question's options, in a terminal that reports key events (Kitty, WezTerm, Ghostty, iTerm2) | one press moves one row, and holding a key still repeats; a terminal that sends only the legacy sequence behaves the same |
|
|
235
409
|
| resize the window mid-turn | the transcript rewraps; the dock, editor, and status row stay put |
|
|
236
|
-
| a 40-column terminal | rows end in `…` instead of wrapping into the next line |
|
|
410
|
+
| a 40-column terminal | transcript and card rows end in `…` instead of wrapping into the next line |
|
|
411
|
+
| a question with a long option at 40 columns | the option wraps onto rows indented under its label, and `0. other — type your own answer` sits under the list |
|
|
412
|
+
| press `0` on a question, type an answer, press Enter | the editor under row `0` shows the text as it is edited, and the model receives it as that question's answer |
|
|
413
|
+
| type a prompt without sending it, then answer a question | the prompt bar steps aside while the question is open and holds the same prompt again afterwards |
|
|
237
414
|
| `echo hi \| dsh --profile tui` | refuses with a non-zero exit and a message naming the TTY requirement |
|
|
238
415
|
| `/quit`, Ctrl+C while idle, `kill -TERM <pid>` | the shell returns with cursor, echo, mouse, and title restored |
|
|
239
416
|
|
|
@@ -241,25 +418,27 @@ The automated checks drive a real PTY, but they run on this machine's terminal.
|
|
|
241
418
|
|
|
242
419
|
Published artefacts carry a provenance attestation, which only a CI provider can issue, so releases ship from the tag workflow rather than a laptop.
|
|
243
420
|
|
|
244
|
-
1. Bump `version` in `package.json
|
|
421
|
+
1. Bump `version` in `package.json` and move `CHANGELOG.md`'s `Unreleased` section to that version, land both on `main` through a reviewed PR, and wait for CI to pass on the merged SHA.
|
|
245
422
|
2. Tag that SHA with a signed tag and push it. The tag ruleset admits repository admins only.
|
|
246
423
|
3. `.github/workflows/release.yml` re-runs typecheck, tests, and the package smoke; the publish job then waits for a maintainer's approval on the `npm-release` environment before it publishes with OIDC trusted publishing and automatic provenance.
|
|
247
424
|
|
|
248
|
-
The workflow stores no npm token: the registry trusts `release.yml` on the `npm-release` environment, and [`scripts/npm/release.py`](scripts/npm/release.py) creates both the environment and that trust. The full runbook is [RELEASE.md](RELEASE.md).
|
|
425
|
+
The workflow stores no npm token: the registry trusts `release.yml` on the `npm-release` environment, and [`scripts/npm/release.py`](scripts/npm/release.py) creates both the environment and that trust. The full runbook is [RELEASE.md](RELEASE.md); the user-visible history is [CHANGELOG.md](CHANGELOG.md).
|
|
249
426
|
|
|
250
427
|
## Limitations
|
|
251
428
|
|
|
252
429
|
- Two different things are called a preset. The agent mode (`--preset`, `/preset`) is fixed once a session has produced a turn; the permission preset (`/permission <preset>`, named in the status line) can change at any time.
|
|
253
|
-
- `/model` changes the route for the running session only. Catalog membership is advisory — an adapter may accept an id it does not advertise.
|
|
430
|
+
- `/model` changes the route and reasoning effort for the running session only. Catalog membership is advisory — an adapter may accept an id it does not advertise, while an explicit effort is checked against the route's own levels before it is applied. The picker offers the routes this deployment configured, not the ones it can prove credentialed: a provider whose key or sign-in is still missing appears like any other, and its first request names the missing credential.
|
|
254
431
|
- Scrolling is the mouse wheel, or the terminal's own scrollback keys where it offers them.
|
|
255
432
|
- A turn that ran longer than ten seconds rings the terminal bell when it ends, because the reader may have walked away; `--no-bell` turns that off.
|
|
256
|
-
- The dock shows the goal, plan mode, the todo
|
|
433
|
+
- The dock shows the goal, plan mode, the todo items still to do, and any background job or delegation still running; a settled item leaves rather than turns into a completed row. The transcript marks where older history was compacted away. `/plan` toggles plan mode; `/plan <message>` also steers that message, which is the base command's own behaviour.
|
|
257
434
|
- Background jobs and subagent runs are live process state, not durable events: they disappear when the run ends, and a resumed session starts with an empty board and roster.
|
|
258
|
-
-
|
|
435
|
+
- A card reads its tool's own render intent through the agent whose session is on screen, so a stored session with no live agent — one this process is not running, or a child that has already finished — folds to the generic card instead of the tool's own.
|
|
436
|
+
- Reading a child's conversation does not move the terminal: commands, approvals, and the status line stay with the session you launched, and the transcript is the only thing that switches. The status line carries the way back, read from the map in force, so a remap shows up without reopening the view.
|
|
259
437
|
- Delete is unimplemented: the session store exposes no delete, and the surface does not reach around that seam into its files. `/fork` covers the case that needs it — it branches into a new session and leaves the original alone.
|
|
260
|
-
- Approvals and questions render inline and take the keyboard; a question batch is answered in order
|
|
261
|
-
- Styling
|
|
438
|
+
- Approvals and questions render inline and take the keyboard; a question batch is answered in order, and a question that lists options can always be answered with free text on row `0`.
|
|
439
|
+
- Styling is per element and overridable; see [Settings](#settings). Shipped defaults are emitted as 24-bit colour where the terminal advertises it and degraded to 256 or 16 colours otherwise, so a light or dark terminal still follows its own palette where it has one.
|
|
262
440
|
- Tool text, model text, and file content are escaped before rendering, so a hostile result cannot inject terminal control sequences; the cost is that a literal tab shows as \x09.
|
|
441
|
+
- Mermaid fences draw in assistant replies only, and only at the top level of one: a fence nested in a list, quoted inside another fence, or carried by a prompt, a thought, or a tool card stays source. Author `:::class` styling and diagram links are ignored — the renderer reports what each run is, and the theme decides how it looks.
|
|
263
442
|
|
|
264
443
|
## License
|
|
265
444
|
|
package/cordis.patch.yml
CHANGED
|
@@ -98,11 +98,13 @@
|
|
|
98
98
|
bell: !!js ctx.tuiStartup.bell
|
|
99
99
|
|
|
100
100
|
# The roster of agent compositions, and the mode a session starts in when
|
|
101
|
-
# nobody names one.
|
|
101
|
+
# nobody names one. PTC leads because a flagless run should reach every tool
|
|
102
|
+
# through one program rather than one shell call at a time. A profile patch
|
|
103
|
+
# may override this row's config.
|
|
102
104
|
- id: agent-presets
|
|
103
105
|
name: '@deepseek-ai/dsh-agent-presets'
|
|
104
106
|
config:
|
|
105
|
-
default:
|
|
107
|
+
default: ptc
|
|
106
108
|
|
|
107
109
|
# A preset's subagent tool samples its delegation model from this host-owned
|
|
108
110
|
# settings row. It is host machinery rather than agent plane, which is why
|
package/lib/agent/host.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
3
3
|
import { type SessionId } from '@deepseek-ai/dsh-session';
|
|
4
|
+
import { ReasoningEffortId } from '@deepseek-ai/dsh-llm';
|
|
4
5
|
/** Everything the terminal surface needs to own one interactive agent. */
|
|
5
6
|
export interface TuiAgent {
|
|
6
7
|
readonly sessionId: SessionId;
|
|
@@ -47,6 +48,19 @@ export interface StartAgentOptions {
|
|
|
47
48
|
*/
|
|
48
49
|
readonly preset?: string | undefined;
|
|
49
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* The route an agent starts on.
|
|
53
|
+
*
|
|
54
|
+
* A launch flag is explicit, so it stands alone; otherwise the deployment
|
|
55
|
+
* default supplies the whole selection, effort included. The effort has to
|
|
56
|
+
* travel with the route here because an absent one is what the reader sees in
|
|
57
|
+
* the status line but never reaches a request.
|
|
58
|
+
*/
|
|
59
|
+
export declare function agentRoute(ctx: Context, options: Pick<StartAgentOptions, 'model' | 'provider'>): {
|
|
60
|
+
provider?: string;
|
|
61
|
+
model?: string;
|
|
62
|
+
reasoningEffort?: ReasoningEffortId;
|
|
63
|
+
};
|
|
50
64
|
/**
|
|
51
65
|
* Create or resume the one agent this surface drives.
|
|
52
66
|
*
|
package/lib/agent/host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/agent/host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../../src/agent/host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAC9F,OAAO,EAAE,iBAAiB,EAAqB,MAAM,sBAAsB,CAAA;AAE3E,0EAA0E;AAC1E,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,yDAAyD;IACzD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,8DAA8D;IAC9D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,0DAA0D;IAC1D,SAAS,IAAI,IAAI,CAAA;IACjB,6CAA6C;IAC7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB;AAED,gEAAgE;AAChE,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAA;CACpC;AAED,6DAA6D;AAC7D,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IAC5C,iFAAiF;IACjF,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,CAAA;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACrC;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,UAAU,CAAC,GACrD;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,iBAAiB,CAAA;CAAE,CAiB5E;AAMD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAkC5F"}
|
package/lib/agent/host.js
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { SessionLogOffset } from '@deepseek-ai/dsh-session';
|
|
2
|
-
import { createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
3
|
-
|
|
2
|
+
import { ReasoningEffortId, createUserMessage } from '@deepseek-ai/dsh-llm';
|
|
3
|
+
/**
|
|
4
|
+
* The route an agent starts on.
|
|
5
|
+
*
|
|
6
|
+
* A launch flag is explicit, so it stands alone; otherwise the deployment
|
|
7
|
+
* default supplies the whole selection, effort included. The effort has to
|
|
8
|
+
* travel with the route here because an absent one is what the reader sees in
|
|
9
|
+
* the status line but never reaches a request.
|
|
10
|
+
*/
|
|
11
|
+
export function agentRoute(ctx, options) {
|
|
4
12
|
if (options.model !== undefined || options.provider !== undefined) {
|
|
5
13
|
return {
|
|
6
14
|
...(options.provider === undefined ? {} : { provider: options.provider }),
|
|
@@ -8,7 +16,15 @@ function routeOf(ctx, options) {
|
|
|
8
16
|
};
|
|
9
17
|
}
|
|
10
18
|
const selection = ctx.get('agentDefaultModel')?.currentSelection();
|
|
11
|
-
return selection === undefined
|
|
19
|
+
return selection === undefined
|
|
20
|
+
? {}
|
|
21
|
+
: {
|
|
22
|
+
provider: selection.provider,
|
|
23
|
+
model: selection.model,
|
|
24
|
+
...(selection.reasoningEffort === undefined
|
|
25
|
+
? {}
|
|
26
|
+
: { reasoningEffort: ReasoningEffortId(selection.reasoningEffort) }),
|
|
27
|
+
};
|
|
12
28
|
}
|
|
13
29
|
function userMessage(text) {
|
|
14
30
|
return createUserMessage({ content: [{ type: 'text', text }], source: { kind: 'user' } });
|
|
@@ -21,7 +37,7 @@ function userMessage(text) {
|
|
|
21
37
|
* session is not an error the user should see, so creation is the fallback.
|
|
22
38
|
*/
|
|
23
39
|
export async function startAgent(ctx, options) {
|
|
24
|
-
const agentOptions =
|
|
40
|
+
const agentOptions = agentRoute(ctx, options);
|
|
25
41
|
const meta = { cwd: options.cwd };
|
|
26
42
|
const setup = options.setup === undefined ? {} : { setup: options.setup };
|
|
27
43
|
// A branch inherits a prefix of its parent's log, so the child is marked as
|
package/lib/agent/host.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/agent/host.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAqC,MAAM,0BAA0B,CAAA;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../src/agent/host.ts"],"names":[],"mappings":"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"}
|
package/lib/agent/model.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { PickerRow } from '../ui/picker.ts';
|
|
2
3
|
/** The route a reader chose for the next step. */
|
|
3
4
|
export interface ModelChoice {
|
|
4
5
|
readonly provider: string;
|
|
@@ -10,6 +11,13 @@ export interface ProviderEntry {
|
|
|
10
11
|
readonly id: string;
|
|
11
12
|
readonly name: string;
|
|
12
13
|
}
|
|
14
|
+
/** One route a configured provider advertises, as the picker lists it. */
|
|
15
|
+
export interface ModelRoute {
|
|
16
|
+
readonly provider: string;
|
|
17
|
+
readonly model: string;
|
|
18
|
+
/** The adapter's display name; the id stays the value a request names. */
|
|
19
|
+
readonly name: string;
|
|
20
|
+
}
|
|
13
21
|
/** What a `/model` argument asks the surface to do. */
|
|
14
22
|
export type ModelCommand = {
|
|
15
23
|
readonly kind: 'current';
|
|
@@ -30,8 +38,30 @@ export type ModelCommand = {
|
|
|
30
38
|
* lists that provider's models, `provider/model` switches, and anything else is
|
|
31
39
|
* taken as a model id inside the route already in use, because a reader
|
|
32
40
|
* switching between two models of one provider should not have to repeat it.
|
|
41
|
+
* A complete route may carry one more segment, the reasoning effort, so
|
|
42
|
+
* `provider/model/effort` selects both at once: the last segment is the effort
|
|
43
|
+
* and the model is everything between it and the provider, which reads a model
|
|
44
|
+
* id containing a slash as an effort the adapters in use do not mint.
|
|
33
45
|
*/
|
|
34
46
|
export declare function parseModelArgument(argument: string, providers: readonly ProviderEntry[], current: ModelChoice | undefined): ModelCommand;
|
|
47
|
+
/** The picker's stable id for one route. */
|
|
48
|
+
export declare function modelRouteKey(route: {
|
|
49
|
+
readonly provider: string;
|
|
50
|
+
readonly model: string;
|
|
51
|
+
}): string;
|
|
52
|
+
/** Read a route key back; undefined for a string this surface never minted. */
|
|
53
|
+
export declare function readModelRouteKey(key: string): {
|
|
54
|
+
provider: string;
|
|
55
|
+
model: string;
|
|
56
|
+
} | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* How one advertised route appears in the picker.
|
|
59
|
+
*
|
|
60
|
+
* The name leads because it is what a reader recognizes, and the id follows
|
|
61
|
+
* only when it says something the name does not; the route in force carries
|
|
62
|
+
* its effort, since that is the other half of the choice on screen.
|
|
63
|
+
*/
|
|
64
|
+
export declare function describeModelRoute(route: ModelRoute, current: ModelChoice | undefined): PickerRow;
|
|
35
65
|
/**
|
|
36
66
|
* Own the reader's model choice for one session.
|
|
37
67
|
*
|
|
@@ -46,10 +76,29 @@ export declare class ModelSwitch {
|
|
|
46
76
|
install(agentCtx: Context): void;
|
|
47
77
|
choose(choice: ModelChoice): void;
|
|
48
78
|
current(): ModelChoice | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Take the deployment default as this session's route, unless the reader
|
|
81
|
+
* already named one.
|
|
82
|
+
*
|
|
83
|
+
* The default is settings-backed and only trustworthy once it is read, which
|
|
84
|
+
* is after the agent was created; adopting it here is what makes the effort
|
|
85
|
+
* the status line shows reach the request, and a reader's own `/model` or
|
|
86
|
+
* picker choice must never be overwritten by it.
|
|
87
|
+
*/
|
|
88
|
+
adopt(choice: ModelChoice): void;
|
|
49
89
|
/** Forget the choice, so the session returns to the composition default. */
|
|
50
90
|
reset(): void;
|
|
51
91
|
dispose(): void;
|
|
52
92
|
}
|
|
93
|
+
/** The reasoning levels one exact route offers, described structurally. */
|
|
94
|
+
export interface ModelEfforts {
|
|
95
|
+
readonly efforts: readonly {
|
|
96
|
+
readonly id: string;
|
|
97
|
+
readonly name: string;
|
|
98
|
+
readonly description?: string;
|
|
99
|
+
}[];
|
|
100
|
+
readonly defaultEffort?: string;
|
|
101
|
+
}
|
|
53
102
|
/** Read the advisory catalog of routes this composition can reach. */
|
|
54
103
|
export declare function createModelCatalog(ctx: Context): {
|
|
55
104
|
providers(): readonly ProviderEntry[];
|
|
@@ -57,5 +106,6 @@ export declare function createModelCatalog(ctx: Context): {
|
|
|
57
106
|
readonly id: string;
|
|
58
107
|
readonly name: string;
|
|
59
108
|
}[]>;
|
|
109
|
+
efforts(provider: string, model: string): Promise<ModelEfforts | undefined>;
|
|
60
110
|
} | undefined;
|
|
61
111
|
//# sourceMappingURL=model.d.ts.map
|
package/lib/agent/model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/agent/model.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/agent/model.ts"],"names":[],"mappings":"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"}
|