@dsh-cc/tui 0.5.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/LICENSE +201 -0
- package/README.md +144 -0
- package/lib/bash-history.d.ts +31 -0
- package/lib/bash-history.d.ts.map +1 -0
- package/lib/bash-history.js +94 -0
- package/lib/bash-history.js.map +1 -0
- package/lib/compact-fold.d.ts +35 -0
- package/lib/compact-fold.d.ts.map +1 -0
- package/lib/compact-fold.js +60 -0
- package/lib/compact-fold.js.map +1 -0
- package/lib/components/arg-completers.d.ts +22 -0
- package/lib/components/arg-completers.d.ts.map +1 -0
- package/lib/components/arg-completers.js +75 -0
- package/lib/components/arg-completers.js.map +1 -0
- package/lib/components/code-theme.d.ts +25 -0
- package/lib/components/code-theme.d.ts.map +1 -0
- package/lib/components/code-theme.js +137 -0
- package/lib/components/code-theme.js.map +1 -0
- package/lib/components/completion.d.ts +50 -0
- package/lib/components/completion.d.ts.map +1 -0
- package/lib/components/completion.js +279 -0
- package/lib/components/completion.js.map +1 -0
- package/lib/components/diff-card.d.ts +29 -0
- package/lib/components/diff-card.d.ts.map +1 -0
- package/lib/components/diff-card.js +175 -0
- package/lib/components/diff-card.js.map +1 -0
- package/lib/components/diff-hunks.d.ts +44 -0
- package/lib/components/diff-hunks.d.ts.map +1 -0
- package/lib/components/diff-hunks.js +188 -0
- package/lib/components/diff-hunks.js.map +1 -0
- package/lib/components/editor-history.d.ts +23 -0
- package/lib/components/editor-history.d.ts.map +1 -0
- package/lib/components/editor-history.js +29 -0
- package/lib/components/editor-history.js.map +1 -0
- package/lib/components/markdown-theme.d.ts +11 -0
- package/lib/components/markdown-theme.d.ts.map +1 -0
- package/lib/components/markdown-theme.js +29 -0
- package/lib/components/markdown-theme.js.map +1 -0
- package/lib/components/masked-input.d.ts +24 -0
- package/lib/components/masked-input.d.ts.map +1 -0
- package/lib/components/masked-input.js +168 -0
- package/lib/components/masked-input.js.map +1 -0
- package/lib/components/overlay-host.d.ts +31 -0
- package/lib/components/overlay-host.d.ts.map +1 -0
- package/lib/components/overlay-host.js +128 -0
- package/lib/components/overlay-host.js.map +1 -0
- package/lib/components/overlays.d.ts +94 -0
- package/lib/components/overlays.d.ts.map +1 -0
- package/lib/components/overlays.js +450 -0
- package/lib/components/overlays.js.map +1 -0
- package/lib/components/provider-box.d.ts +23 -0
- package/lib/components/provider-box.d.ts.map +1 -0
- package/lib/components/provider-box.js +164 -0
- package/lib/components/provider-box.js.map +1 -0
- package/lib/components/read-group.d.ts +51 -0
- package/lib/components/read-group.d.ts.map +1 -0
- package/lib/components/read-group.js +105 -0
- package/lib/components/read-group.js.map +1 -0
- package/lib/components/root-bash.d.ts +36 -0
- package/lib/components/root-bash.d.ts.map +1 -0
- package/lib/components/root-bash.js +112 -0
- package/lib/components/root-bash.js.map +1 -0
- package/lib/components/root-types.d.ts +42 -0
- package/lib/components/root-types.d.ts.map +1 -0
- package/lib/components/root-types.js +8 -0
- package/lib/components/root-types.js.map +1 -0
- package/lib/components/root-utils.d.ts +22 -0
- package/lib/components/root-utils.d.ts.map +1 -0
- package/lib/components/root-utils.js +45 -0
- package/lib/components/root-utils.js.map +1 -0
- package/lib/components/root.d.ts +25 -0
- package/lib/components/root.d.ts.map +1 -0
- package/lib/components/root.js +357 -0
- package/lib/components/root.js.map +1 -0
- package/lib/components/theme.d.ts +61 -0
- package/lib/components/theme.d.ts.map +1 -0
- package/lib/components/theme.js +99 -0
- package/lib/components/theme.js.map +1 -0
- package/lib/components/transcript.d.ts +43 -0
- package/lib/components/transcript.d.ts.map +1 -0
- package/lib/components/transcript.js +203 -0
- package/lib/components/transcript.js.map +1 -0
- package/lib/components/working-line.d.ts +35 -0
- package/lib/components/working-line.d.ts.map +1 -0
- package/lib/components/working-line.js +66 -0
- package/lib/components/working-line.js.map +1 -0
- package/lib/effort-catalog.d.ts +27 -0
- package/lib/effort-catalog.d.ts.map +1 -0
- package/lib/effort-catalog.js +36 -0
- package/lib/effort-catalog.js.map +1 -0
- package/lib/export-markdown.d.ts +18 -0
- package/lib/export-markdown.d.ts.map +1 -0
- package/lib/export-markdown.js +124 -0
- package/lib/export-markdown.js.map +1 -0
- package/lib/harness/approval-preview.d.ts +33 -0
- package/lib/harness/approval-preview.d.ts.map +1 -0
- package/lib/harness/approval-preview.js +179 -0
- package/lib/harness/approval-preview.js.map +1 -0
- package/lib/harness/boot-banner.d.ts +14 -0
- package/lib/harness/boot-banner.d.ts.map +1 -0
- package/lib/harness/boot-banner.js +89 -0
- package/lib/harness/boot-banner.js.map +1 -0
- package/lib/harness/driver-agent.d.ts +78 -0
- package/lib/harness/driver-agent.d.ts.map +1 -0
- package/lib/harness/driver-agent.js +314 -0
- package/lib/harness/driver-agent.js.map +1 -0
- package/lib/harness/driver-agents.d.ts +20 -0
- package/lib/harness/driver-agents.d.ts.map +1 -0
- package/lib/harness/driver-agents.js +123 -0
- package/lib/harness/driver-agents.js.map +1 -0
- package/lib/harness/driver-approvals.d.ts +38 -0
- package/lib/harness/driver-approvals.d.ts.map +1 -0
- package/lib/harness/driver-approvals.js +277 -0
- package/lib/harness/driver-approvals.js.map +1 -0
- package/lib/harness/driver-bash.d.ts +15 -0
- package/lib/harness/driver-bash.d.ts.map +1 -0
- package/lib/harness/driver-bash.js +73 -0
- package/lib/harness/driver-bash.js.map +1 -0
- package/lib/harness/driver-catalog.d.ts +84 -0
- package/lib/harness/driver-catalog.d.ts.map +1 -0
- package/lib/harness/driver-catalog.js +256 -0
- package/lib/harness/driver-catalog.js.map +1 -0
- package/lib/harness/driver-ctx.d.ts +462 -0
- package/lib/harness/driver-ctx.d.ts.map +1 -0
- package/lib/harness/driver-ctx.js +11 -0
- package/lib/harness/driver-ctx.js.map +1 -0
- package/lib/harness/driver-hud.d.ts +31 -0
- package/lib/harness/driver-hud.d.ts.map +1 -0
- package/lib/harness/driver-hud.js +204 -0
- package/lib/harness/driver-hud.js.map +1 -0
- package/lib/harness/driver-live.d.ts +36 -0
- package/lib/harness/driver-live.d.ts.map +1 -0
- package/lib/harness/driver-live.js +44 -0
- package/lib/harness/driver-live.js.map +1 -0
- package/lib/harness/driver-modal.d.ts +52 -0
- package/lib/harness/driver-modal.d.ts.map +1 -0
- package/lib/harness/driver-modal.js +78 -0
- package/lib/harness/driver-modal.js.map +1 -0
- package/lib/harness/driver-mode.d.ts +35 -0
- package/lib/harness/driver-mode.d.ts.map +1 -0
- package/lib/harness/driver-mode.js +84 -0
- package/lib/harness/driver-mode.js.map +1 -0
- package/lib/harness/driver-pickers.d.ts +48 -0
- package/lib/harness/driver-pickers.d.ts.map +1 -0
- package/lib/harness/driver-pickers.js +249 -0
- package/lib/harness/driver-pickers.js.map +1 -0
- package/lib/harness/driver-promote.d.ts +29 -0
- package/lib/harness/driver-promote.d.ts.map +1 -0
- package/lib/harness/driver-promote.js +36 -0
- package/lib/harness/driver-promote.js.map +1 -0
- package/lib/harness/driver-queue.d.ts +19 -0
- package/lib/harness/driver-queue.d.ts.map +1 -0
- package/lib/harness/driver-queue.js +281 -0
- package/lib/harness/driver-queue.js.map +1 -0
- package/lib/harness/driver-run-local.d.ts +32 -0
- package/lib/harness/driver-run-local.d.ts.map +1 -0
- package/lib/harness/driver-run-local.js +366 -0
- package/lib/harness/driver-run-local.js.map +1 -0
- package/lib/harness/driver-sessions.d.ts +28 -0
- package/lib/harness/driver-sessions.d.ts.map +1 -0
- package/lib/harness/driver-sessions.js +386 -0
- package/lib/harness/driver-sessions.js.map +1 -0
- package/lib/harness/driver.d.ts +22 -0
- package/lib/harness/driver.d.ts.map +1 -0
- package/lib/harness/driver.js +459 -0
- package/lib/harness/driver.js.map +1 -0
- package/lib/harness/preset.d.ts +32 -0
- package/lib/harness/preset.d.ts.map +1 -0
- package/lib/harness/preset.js +34 -0
- package/lib/harness/preset.js.map +1 -0
- package/lib/harness/session-list.d.ts +65 -0
- package/lib/harness/session-list.d.ts.map +1 -0
- package/lib/harness/session-list.js +91 -0
- package/lib/harness/session-list.js.map +1 -0
- package/lib/harness/shell-output.d.ts +44 -0
- package/lib/harness/shell-output.d.ts.map +1 -0
- package/lib/harness/shell-output.js +90 -0
- package/lib/harness/shell-output.js.map +1 -0
- package/lib/harness/statusline-cc-transcript.d.ts +51 -0
- package/lib/harness/statusline-cc-transcript.d.ts.map +1 -0
- package/lib/harness/statusline-cc-transcript.js +191 -0
- package/lib/harness/statusline-cc-transcript.js.map +1 -0
- package/lib/harness/statusline-command.d.ts +54 -0
- package/lib/harness/statusline-command.d.ts.map +1 -0
- package/lib/harness/statusline-command.js +161 -0
- package/lib/harness/statusline-command.js.map +1 -0
- package/lib/harness/statusline-payload.d.ts +79 -0
- package/lib/harness/statusline-payload.d.ts.map +1 -0
- package/lib/harness/statusline-payload.js +93 -0
- package/lib/harness/statusline-payload.js.map +1 -0
- package/lib/harness/statusline-settings.d.ts +47 -0
- package/lib/harness/statusline-settings.d.ts.map +1 -0
- package/lib/harness/statusline-settings.js +57 -0
- package/lib/harness/statusline-settings.js.map +1 -0
- package/lib/harness/statusline-wiring.d.ts +45 -0
- package/lib/harness/statusline-wiring.d.ts.map +1 -0
- package/lib/harness/statusline-wiring.js +247 -0
- package/lib/harness/statusline-wiring.js.map +1 -0
- package/lib/harness/usage-view.d.ts +84 -0
- package/lib/harness/usage-view.d.ts.map +1 -0
- package/lib/harness/usage-view.js +199 -0
- package/lib/harness/usage-view.js.map +1 -0
- package/lib/harness/worktree-exit.d.ts +105 -0
- package/lib/harness/worktree-exit.d.ts.map +1 -0
- package/lib/harness/worktree-exit.js +168 -0
- package/lib/harness/worktree-exit.js.map +1 -0
- package/lib/history.d.ts +50 -0
- package/lib/history.d.ts.map +1 -0
- package/lib/history.js +139 -0
- package/lib/history.js.map +1 -0
- package/lib/index.d.ts +63 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +54 -0
- package/lib/index.js.map +1 -0
- package/lib/input.d.ts +158 -0
- package/lib/input.d.ts.map +1 -0
- package/lib/input.js +400 -0
- package/lib/input.js.map +1 -0
- package/lib/invariant.d.ts +14 -0
- package/lib/invariant.d.ts.map +1 -0
- package/lib/invariant.js +20 -0
- package/lib/invariant.js.map +1 -0
- package/lib/mode-cycle.d.ts +22 -0
- package/lib/mode-cycle.d.ts.map +1 -0
- package/lib/mode-cycle.js +32 -0
- package/lib/mode-cycle.js.map +1 -0
- package/lib/model-catalog.d.ts +22 -0
- package/lib/model-catalog.d.ts.map +1 -0
- package/lib/model-catalog.js +45 -0
- package/lib/model-catalog.js.map +1 -0
- package/lib/packaged-preset.d.ts +32 -0
- package/lib/packaged-preset.d.ts.map +1 -0
- package/lib/packaged-preset.js +94 -0
- package/lib/packaged-preset.js.map +1 -0
- package/lib/plugin.d.ts +11 -0
- package/lib/plugin.d.ts.map +1 -0
- package/lib/plugin.js +88 -0
- package/lib/plugin.js.map +1 -0
- package/lib/profile.d.ts +4 -0
- package/lib/profile.d.ts.map +1 -0
- package/lib/profile.js +7 -0
- package/lib/profile.js.map +1 -0
- package/lib/project-sessions.d.ts +29 -0
- package/lib/project-sessions.d.ts.map +1 -0
- package/lib/project-sessions.js +60 -0
- package/lib/project-sessions.js.map +1 -0
- package/lib/project.d.ts +75 -0
- package/lib/project.d.ts.map +1 -0
- package/lib/project.js +196 -0
- package/lib/project.js.map +1 -0
- package/lib/provider-actions.d.ts +37 -0
- package/lib/provider-actions.d.ts.map +1 -0
- package/lib/provider-actions.js +417 -0
- package/lib/provider-actions.js.map +1 -0
- package/lib/provider-command.d.ts +109 -0
- package/lib/provider-command.d.ts.map +1 -0
- package/lib/provider-command.js +220 -0
- package/lib/provider-command.js.map +1 -0
- package/lib/provider-detail.d.ts +15 -0
- package/lib/provider-detail.d.ts.map +1 -0
- package/lib/provider-detail.js +201 -0
- package/lib/provider-detail.js.map +1 -0
- package/lib/provider-flow.d.ts +191 -0
- package/lib/provider-flow.d.ts.map +1 -0
- package/lib/provider-flow.js +192 -0
- package/lib/provider-flow.js.map +1 -0
- package/lib/provider-presets.d.ts +32 -0
- package/lib/provider-presets.d.ts.map +1 -0
- package/lib/provider-presets.js +105 -0
- package/lib/provider-presets.js.map +1 -0
- package/lib/provider-read.d.ts +63 -0
- package/lib/provider-read.d.ts.map +1 -0
- package/lib/provider-read.js +115 -0
- package/lib/provider-read.js.map +1 -0
- package/lib/provider-settings.d.ts +30 -0
- package/lib/provider-settings.d.ts.map +1 -0
- package/lib/provider-settings.js +65 -0
- package/lib/provider-settings.js.map +1 -0
- package/lib/resume-target.d.ts +59 -0
- package/lib/resume-target.d.ts.map +1 -0
- package/lib/resume-target.js +143 -0
- package/lib/resume-target.js.map +1 -0
- package/lib/slash.d.ts +44 -0
- package/lib/slash.d.ts.map +1 -0
- package/lib/slash.js +81 -0
- package/lib/slash.js.map +1 -0
- package/lib/state/driver-types.d.ts +505 -0
- package/lib/state/driver-types.d.ts.map +1 -0
- package/lib/state/driver-types.js +8 -0
- package/lib/state/driver-types.js.map +1 -0
- package/lib/state/driver-usage-types.d.ts +59 -0
- package/lib/state/driver-usage-types.d.ts.map +1 -0
- package/lib/state/driver-usage-types.js +8 -0
- package/lib/state/driver-usage-types.js.map +1 -0
- package/lib/statusline.d.ts +63 -0
- package/lib/statusline.d.ts.map +1 -0
- package/lib/statusline.js +97 -0
- package/lib/statusline.js.map +1 -0
- package/lib/store/pickers.d.ts +34 -0
- package/lib/store/pickers.d.ts.map +1 -0
- package/lib/store/pickers.js +111 -0
- package/lib/store/pickers.js.map +1 -0
- package/lib/store/provider-panel.d.ts +107 -0
- package/lib/store/provider-panel.d.ts.map +1 -0
- package/lib/store/provider-panel.js +151 -0
- package/lib/store/provider-panel.js.map +1 -0
- package/lib/store/question.d.ts +21 -0
- package/lib/store/question.d.ts.map +1 -0
- package/lib/store/question.js +59 -0
- package/lib/store/question.js.map +1 -0
- package/lib/store/queue.d.ts +27 -0
- package/lib/store/queue.d.ts.map +1 -0
- package/lib/store/queue.js +34 -0
- package/lib/store/queue.js.map +1 -0
- package/lib/store/session.d.ts +73 -0
- package/lib/store/session.d.ts.map +1 -0
- package/lib/store/session.js +172 -0
- package/lib/store/session.js.map +1 -0
- package/lib/store/subagents.d.ts +16 -0
- package/lib/store/subagents.d.ts.map +1 -0
- package/lib/store/subagents.js +44 -0
- package/lib/store/subagents.js.map +1 -0
- package/lib/store/todos.d.ts +35 -0
- package/lib/store/todos.d.ts.map +1 -0
- package/lib/store/todos.js +68 -0
- package/lib/store/todos.js.map +1 -0
- package/lib/store/usage.d.ts +15 -0
- package/lib/store/usage.d.ts.map +1 -0
- package/lib/store/usage.js +27 -0
- package/lib/store/usage.js.map +1 -0
- package/lib/store/views.d.ts +419 -0
- package/lib/store/views.d.ts.map +1 -0
- package/lib/store/views.js +3 -0
- package/lib/store/views.js.map +1 -0
- package/lib/store.d.ts +19 -0
- package/lib/store.d.ts.map +1 -0
- package/lib/store.js +10 -0
- package/lib/store.js.map +1 -0
- package/lib/terminal/lease.d.ts +33 -0
- package/lib/terminal/lease.d.ts.map +1 -0
- package/lib/terminal/lease.js +99 -0
- package/lib/terminal/lease.js.map +1 -0
- package/lib/tool-card.d.ts +75 -0
- package/lib/tool-card.d.ts.map +1 -0
- package/lib/tool-card.js +109 -0
- package/lib/tool-card.js.map +1 -0
- package/lib/tool-verbs.d.ts +12 -0
- package/lib/tool-verbs.d.ts.map +1 -0
- package/lib/tool-verbs.js +29 -0
- package/lib/tool-verbs.js.map +1 -0
- package/lib/transcript.d.ts +40 -0
- package/lib/transcript.d.ts.map +1 -0
- package/lib/transcript.js +413 -0
- package/lib/transcript.js.map +1 -0
- package/lib/working-line.d.ts +44 -0
- package/lib/working-line.d.ts.map +1 -0
- package/lib/working-line.js +56 -0
- package/lib/working-line.js.map +1 -0
- package/package.json +72 -0
- package/presets/cc/.dsh-cc-managed.json +5 -0
- package/presets/cc/agent.cordis.yml +524 -0
- package/presets/cc/preset.yml +3 -0
- package/scripts/stage-preset.mjs +26 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/provider` overlay box (design doc §4.2–§4.6): the two-section provider
|
|
3
|
+
* list with credential badges, the manage detail view (§4.4), the add /
|
|
4
|
+
* custom / rotate wizard phases (§4.3, §4.6), and the remove double-confirm.
|
|
5
|
+
* The wizard's live text entry is a real pi-tui `Input` owned by the runtime
|
|
6
|
+
* (provider-command.ts) and rendered inside this box when a text step is
|
|
7
|
+
* active; the box itself stays a pure function of the panel state.
|
|
8
|
+
* @module @dsh-cc/tui/components/provider-box
|
|
9
|
+
*/
|
|
10
|
+
import { Container, Text } from '@dsh-cc/pi-tui';
|
|
11
|
+
import { defaultTheme } from "./theme.js";
|
|
12
|
+
/** Badge text for one row's credential state (§4.2). */
|
|
13
|
+
function badgeText(row) {
|
|
14
|
+
const credential = row.credential;
|
|
15
|
+
if (credential === undefined || credential.badge === 'missing')
|
|
16
|
+
return 'key ✗ missing';
|
|
17
|
+
return `key ✓ (${credential.badge})`;
|
|
18
|
+
}
|
|
19
|
+
const CUSTOM_PROTOCOLS = ['openai-completions', 'openai-responses', 'anthropic-messages'];
|
|
20
|
+
/** Render the live text field's lines inside the box (masked Input shows bullets). */
|
|
21
|
+
function renderField(box, field) {
|
|
22
|
+
if (field === undefined)
|
|
23
|
+
return;
|
|
24
|
+
for (const line of field.render(100))
|
|
25
|
+
box.addChild(new Text(line, 0, 0));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Provider list box: "Providers" title, then the Configured section (live
|
|
29
|
+
* settings dict, document order) and the Available section (presets), with
|
|
30
|
+
* `●`/`○` current markers, credential badges, model counts, ⚠ on configured
|
|
31
|
+
* routes with models but no key, and the directory tail collapsed under
|
|
32
|
+
* "More providers (…)".
|
|
33
|
+
*/
|
|
34
|
+
export function createProviderPanelBox(view, theme = defaultTheme, field) {
|
|
35
|
+
const box = new Container();
|
|
36
|
+
if (view.phase === 'detail')
|
|
37
|
+
return detailBox(box, view, theme);
|
|
38
|
+
if (view.phase === 'wizard')
|
|
39
|
+
return wizardBox(box, view, theme, field);
|
|
40
|
+
if (view.phase === 'confirm-remove')
|
|
41
|
+
return confirmRemoveBox(box, view, theme);
|
|
42
|
+
box.addChild(new Text(theme.bold('Providers'), 0, 0));
|
|
43
|
+
const renderRow = (row, index) => {
|
|
44
|
+
const focused = view.phase === 'list' && view.cursor === index;
|
|
45
|
+
const marker = row.isCurrent ? '●' : '○';
|
|
46
|
+
const models = row.modelCount > 0 ? ` ${row.modelCount} models` : '';
|
|
47
|
+
const warning = row.credential?.warning === true ? ' ⚠' : '';
|
|
48
|
+
const prefix = focused ? '❯ ' : ' ';
|
|
49
|
+
box.addChild(new Text(`${prefix}${marker} ${row.route} ${row.displayName} ${badgeText(row)}${models}${warning}`, 0, 0));
|
|
50
|
+
};
|
|
51
|
+
// Rows arrive flat (configured block then available block); the section
|
|
52
|
+
// boundary is the first `available` row.
|
|
53
|
+
const split = view.rows.findIndex(row => row.section === 'available');
|
|
54
|
+
const configuredEnd = split === -1 ? view.rows.length : split;
|
|
55
|
+
box.addChild(new Text(theme.muted(' Configured'), 0, 0));
|
|
56
|
+
for (let index = 0; index < configuredEnd; index += 1)
|
|
57
|
+
renderRow(view.rows[index], index);
|
|
58
|
+
if (configuredEnd < view.rows.length) {
|
|
59
|
+
box.addChild(new Text(theme.muted(' Available'), 0, 0));
|
|
60
|
+
for (let index = configuredEnd; index < view.rows.length; index += 1)
|
|
61
|
+
renderRow(view.rows[index], index);
|
|
62
|
+
}
|
|
63
|
+
if (view.more.length > 0) {
|
|
64
|
+
box.addChild(new Text(` … More providers (${view.more.map(m => m.provider).join(', ')})`, 0, 0));
|
|
65
|
+
}
|
|
66
|
+
if (view.message !== undefined) {
|
|
67
|
+
box.addChild(new Text(theme.warning(view.message), 0, 0));
|
|
68
|
+
}
|
|
69
|
+
box.addChild(new Text(theme.muted('j/k move · enter open · n add custom · esc close'), 0, 0));
|
|
70
|
+
return box;
|
|
71
|
+
}
|
|
72
|
+
/** Detail view (§4.4): resolved facts + raw profile JSON + action rows. */
|
|
73
|
+
function detailBox(box, view, theme) {
|
|
74
|
+
box.addChild(new Text(theme.bold(`Provider ${view.selected ?? ''}`), 0, 0));
|
|
75
|
+
const detail = view.detail;
|
|
76
|
+
if (detail !== undefined) {
|
|
77
|
+
box.addChild(new Text(`endpoint ${detail.endpoint}`, 0, 0));
|
|
78
|
+
box.addChild(new Text(`protocol ${detail.api}`, 0, 0));
|
|
79
|
+
box.addChild(new Text(`models ${detail.modelCount}`, 0, 0));
|
|
80
|
+
box.addChild(new Text(`key ${detail.credentialLine}`, 0, 0));
|
|
81
|
+
box.addChild(new Text(theme.muted('profile (read-only):'), 0, 0));
|
|
82
|
+
for (const line of detail.profileJson.split('\n')) {
|
|
83
|
+
box.addChild(new Text(theme.muted(` ${line}`), 0, 0));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const actions = view.actions ?? [];
|
|
87
|
+
for (let index = 0; index < actions.length; index += 1) {
|
|
88
|
+
const action = actions[index];
|
|
89
|
+
const marker = (view.actionCursor ?? 0) === index ? '❯ ' : ' ';
|
|
90
|
+
const suffix = action.disabled === true ? ` (unavailable — ${action.reason ?? ''})` : '';
|
|
91
|
+
box.addChild(new Text(`${marker}${action.label}${suffix}`, 0, 0));
|
|
92
|
+
}
|
|
93
|
+
if (view.message !== undefined) {
|
|
94
|
+
box.addChild(new Text(theme.warning(view.message), 0, 0));
|
|
95
|
+
}
|
|
96
|
+
box.addChild(new Text(theme.muted('j/k move · enter select · esc back'), 0, 0));
|
|
97
|
+
return box;
|
|
98
|
+
}
|
|
99
|
+
/** Wizard phases (§4.3/§4.6/rotate): step rail, live field, notes, prompts. */
|
|
100
|
+
function wizardBox(box, view, theme, field) {
|
|
101
|
+
const wizard = view.wizard;
|
|
102
|
+
if (wizard === undefined)
|
|
103
|
+
return box;
|
|
104
|
+
const title = wizard.kind === 'rotate'
|
|
105
|
+
? `Rotate key — ${wizard.route}`
|
|
106
|
+
: wizard.kind === 'custom' ? 'Add custom provider' : `Add ${wizard.route}${wizard.displayName === undefined ? '' : ` (${wizard.displayName})`}`;
|
|
107
|
+
box.addChild(new Text(theme.bold(title), 0, 0));
|
|
108
|
+
box.addChild(new Text(theme.muted(wizard.steps.map((step, index) => index === wizard.stepIndex ? `[${step}]` : step).join(' → ')), 0, 0));
|
|
109
|
+
const step = wizard.steps[wizard.stepIndex];
|
|
110
|
+
if (step === 'protocol') {
|
|
111
|
+
for (let index = 0; index < CUSTOM_PROTOCOLS.length; index += 1) {
|
|
112
|
+
const marker = (wizard.selectIndex ?? 0) === index ? '❯ ' : ' ';
|
|
113
|
+
box.addChild(new Text(`${marker}${CUSTOM_PROTOCOLS[index]}`, 0, 0));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else if (step === 'credential' || step === 'key') {
|
|
117
|
+
box.addChild(new Text(theme.muted(`API key for ${wizard.answers['ref'] ?? wizard.route} — stored in ~/.dsh/.credentials.yaml, never in settings`), 0, 0));
|
|
118
|
+
renderField(box, field);
|
|
119
|
+
}
|
|
120
|
+
else if (step === 'models') {
|
|
121
|
+
box.addChild(new Text(theme.muted('model ids — one per entry: id | Name | contextWindow | maxTokens'), 0, 0));
|
|
122
|
+
renderField(box, field);
|
|
123
|
+
box.addChild(new Text(theme.muted('tab fetch from endpoint · enter save'), 0, 0));
|
|
124
|
+
}
|
|
125
|
+
else if (step === 'verify') {
|
|
126
|
+
const verify = wizard.verify;
|
|
127
|
+
if (verify !== undefined)
|
|
128
|
+
box.addChild(new Text(verify.message ?? 'verifying…', 0, 0));
|
|
129
|
+
}
|
|
130
|
+
else if (step === 'done') {
|
|
131
|
+
const where = wizard.answers['ref'] === undefined ? '' : ` — key in ${wizard.answers['ref']}`;
|
|
132
|
+
box.addChild(new Text(`Added ${wizard.route || wizard.answers['route'] || ''}${where}.`, 0, 0));
|
|
133
|
+
box.addChild(new Text(theme.muted('Set as default? enter yes · esc no (/model switches the running session)'), 0, 0));
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
renderField(box, field);
|
|
137
|
+
}
|
|
138
|
+
if (wizard.note !== undefined)
|
|
139
|
+
box.addChild(new Text(theme.warning(wizard.note), 0, 0));
|
|
140
|
+
if (wizard.modelErrors !== undefined) {
|
|
141
|
+
for (const error of wizard.modelErrors)
|
|
142
|
+
box.addChild(new Text(theme.warning(error), 0, 0));
|
|
143
|
+
}
|
|
144
|
+
if (view.message !== undefined)
|
|
145
|
+
box.addChild(new Text(theme.warning(view.message), 0, 0));
|
|
146
|
+
box.addChild(new Text(theme.muted('enter next · esc back'), 0, 0));
|
|
147
|
+
return box;
|
|
148
|
+
}
|
|
149
|
+
/** Remove double-confirm (§4.4): the unset confirm, then the credential-drop offer. */
|
|
150
|
+
function confirmRemoveBox(box, view, theme) {
|
|
151
|
+
box.addChild(new Text(theme.bold(`Remove provider ${view.selected ?? ''}?`), 0, 0));
|
|
152
|
+
if (view.message !== undefined)
|
|
153
|
+
box.addChild(new Text(theme.warning(view.message), 0, 0));
|
|
154
|
+
if (view.stage === 'drop-credential') {
|
|
155
|
+
box.addChild(new Text('Route removed. Also drop the stored credential?', 0, 0));
|
|
156
|
+
box.addChild(new Text(theme.muted('enter drop · x keep · esc keep'), 0, 0));
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
box.addChild(new Text(theme.muted('This unsets llm-pi-ai.providers.' + (view.selected ?? '')), 0, 0));
|
|
160
|
+
box.addChild(new Text(theme.muted('enter remove · esc cancel'), 0, 0));
|
|
161
|
+
}
|
|
162
|
+
return box;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=provider-box.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-box.js","sourceRoot":"","sources":["../../src/components/provider-box.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View-layer grouping of consecutive completed file-read tool rows. The store
|
|
3
|
+
* keeps a strict 1:1 mapping between rows and durable events, so collapsing
|
|
4
|
+
* N reads into one summary line can only happen here — after the transcript's
|
|
5
|
+
* line-budget clipping and purely for rendering. Nothing in this module feeds
|
|
6
|
+
* back into state.
|
|
7
|
+
* @module @dsh-cc/tui/components/read-group
|
|
8
|
+
*/
|
|
9
|
+
import type { TranscriptRow } from '../store.ts';
|
|
10
|
+
/**
|
|
11
|
+
* One slot in the grouped render sequence: either an untouched row (rendered
|
|
12
|
+
* by the normal per-row path) or a group of completed read rows collapsed
|
|
13
|
+
* into a single summary line.
|
|
14
|
+
*/
|
|
15
|
+
export type RenderItem = {
|
|
16
|
+
kind: 'row';
|
|
17
|
+
row: TranscriptRow;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'readGroup';
|
|
20
|
+
rows: readonly TranscriptRow[];
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Collapse runs of ≥2 consecutive groupable read rows into `readGroup`
|
|
24
|
+
* items. Any other row (running/errored read, non-read tool, user text,
|
|
25
|
+
* status, …) closes the current segment. Single reads pass through as plain
|
|
26
|
+
* rows so a lone call keeps its familiar per-row rendering.
|
|
27
|
+
*/
|
|
28
|
+
export declare function groupReadRows(rows: readonly TranscriptRow[]): readonly RenderItem[];
|
|
29
|
+
/**
|
|
30
|
+
* Stable cache key for a group: its member callId list. Deliberately free of
|
|
31
|
+
* row references — the store replaces row objects in place as results arrive,
|
|
32
|
+
* and the collapsed summary never depends on results.
|
|
33
|
+
*/
|
|
34
|
+
export declare function readGroupCacheKey(rows: readonly TranscriptRow[]): string;
|
|
35
|
+
/** Most paths shown before the remainder collapses into "+M more". */
|
|
36
|
+
export declare const READ_GROUP_MAX_PATHS = 4;
|
|
37
|
+
/** Character cap for the rendered path list before it is truncated. */
|
|
38
|
+
export declare const READ_GROUP_LIST_MAX_CHARS = 160;
|
|
39
|
+
/**
|
|
40
|
+
* Extract the display path for one read row: the `file_path`/`path` field of
|
|
41
|
+
* the call's args JSON first, then the presenter title, then the bare tool
|
|
42
|
+
* name as a last resort (so the slot is never empty — an unstyled fallback
|
|
43
|
+
* beats rendering nothing between commas).
|
|
44
|
+
*/
|
|
45
|
+
export declare function readDisplayPath(row: TranscriptRow): string;
|
|
46
|
+
/**
|
|
47
|
+
* Render a read group as one line:
|
|
48
|
+
* `⏺ Read N files · a.ts, b.ts +M more`
|
|
49
|
+
*/
|
|
50
|
+
export declare function renderReadGroup(rows: readonly TranscriptRow[]): string;
|
|
51
|
+
//# sourceMappingURL=read-group.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-group.d.ts","sourceRoot":"","sources":["../../src/components/read-group.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,aAAa,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CAAA;AAgBzD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,SAAS,UAAU,EAAE,CAwBnF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAExE;AAED,sEAAsE;AACtE,eAAO,MAAM,oBAAoB,IAAI,CAAA;AAErC,uEAAuE;AACvE,eAAO,MAAM,yBAAyB,MAAM,CAAA;AAE5C;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAgB1D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAYtE"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View-layer grouping of consecutive completed file-read tool rows. The store
|
|
3
|
+
* keeps a strict 1:1 mapping between rows and durable events, so collapsing
|
|
4
|
+
* N reads into one summary line can only happen here — after the transcript's
|
|
5
|
+
* line-budget clipping and purely for rendering. Nothing in this module feeds
|
|
6
|
+
* back into state.
|
|
7
|
+
* @module @dsh-cc/tui/components/read-group
|
|
8
|
+
*/
|
|
9
|
+
/** Tool names that collapse together (case-insensitive). */
|
|
10
|
+
const READ_TOOL_NAMES = new Set(['read', 'read_image']);
|
|
11
|
+
/**
|
|
12
|
+
* A read row is groupable only when it has finished cleanly: a running call
|
|
13
|
+
* still streams its own trail line, and an errored call must stay visible.
|
|
14
|
+
*/
|
|
15
|
+
function isGroupableRead(row) {
|
|
16
|
+
return row.kind === 'tool'
|
|
17
|
+
&& READ_TOOL_NAMES.has(row.name.toLowerCase())
|
|
18
|
+
&& !row.running
|
|
19
|
+
&& row.error !== true;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Collapse runs of ≥2 consecutive groupable read rows into `readGroup`
|
|
23
|
+
* items. Any other row (running/errored read, non-read tool, user text,
|
|
24
|
+
* status, …) closes the current segment. Single reads pass through as plain
|
|
25
|
+
* rows so a lone call keeps its familiar per-row rendering.
|
|
26
|
+
*/
|
|
27
|
+
export function groupReadRows(rows) {
|
|
28
|
+
const items = [];
|
|
29
|
+
let segment = [];
|
|
30
|
+
const flush = () => {
|
|
31
|
+
if (segment.length === 1) {
|
|
32
|
+
items.push({ kind: 'row', row: segment[0] });
|
|
33
|
+
}
|
|
34
|
+
else if (segment.length > 1) {
|
|
35
|
+
items.push({ kind: 'readGroup', rows: segment });
|
|
36
|
+
}
|
|
37
|
+
segment = [];
|
|
38
|
+
};
|
|
39
|
+
for (const row of rows) {
|
|
40
|
+
if (isGroupableRead(row)) {
|
|
41
|
+
segment.push(row);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
flush();
|
|
45
|
+
items.push({ kind: 'row', row });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
flush();
|
|
49
|
+
return items;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Stable cache key for a group: its member callId list. Deliberately free of
|
|
53
|
+
* row references — the store replaces row objects in place as results arrive,
|
|
54
|
+
* and the collapsed summary never depends on results.
|
|
55
|
+
*/
|
|
56
|
+
export function readGroupCacheKey(rows) {
|
|
57
|
+
return rows.map(row => row.kind === 'tool' ? row.callId : '').join('\n');
|
|
58
|
+
}
|
|
59
|
+
/** Most paths shown before the remainder collapses into "+M more". */
|
|
60
|
+
export const READ_GROUP_MAX_PATHS = 4;
|
|
61
|
+
/** Character cap for the rendered path list before it is truncated. */
|
|
62
|
+
export const READ_GROUP_LIST_MAX_CHARS = 160;
|
|
63
|
+
/**
|
|
64
|
+
* Extract the display path for one read row: the `file_path`/`path` field of
|
|
65
|
+
* the call's args JSON first, then the presenter title, then the bare tool
|
|
66
|
+
* name as a last resort (so the slot is never empty — an unstyled fallback
|
|
67
|
+
* beats rendering nothing between commas).
|
|
68
|
+
*/
|
|
69
|
+
export function readDisplayPath(row) {
|
|
70
|
+
if (row.kind !== 'tool')
|
|
71
|
+
return '';
|
|
72
|
+
try {
|
|
73
|
+
const parsed = JSON.parse(row.args);
|
|
74
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
75
|
+
const record = parsed;
|
|
76
|
+
for (const key of ['file_path', 'path']) {
|
|
77
|
+
const value = record[key];
|
|
78
|
+
if (typeof value === 'string' && value.length > 0)
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Unparseable args fall through to the title fallback.
|
|
85
|
+
}
|
|
86
|
+
if (row.title.length > 0)
|
|
87
|
+
return row.title;
|
|
88
|
+
return row.name;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Render a read group as one line:
|
|
92
|
+
* `⏺ Read N files · a.ts, b.ts +M more`
|
|
93
|
+
*/
|
|
94
|
+
export function renderReadGroup(rows) {
|
|
95
|
+
const paths = rows.map(readDisplayPath);
|
|
96
|
+
const shown = paths.slice(0, READ_GROUP_MAX_PATHS);
|
|
97
|
+
const moreCount = paths.length - shown.length;
|
|
98
|
+
const more = moreCount > 0 ? ` +${moreCount} more` : '';
|
|
99
|
+
let list = shown.join(', ');
|
|
100
|
+
if (list.length > READ_GROUP_LIST_MAX_CHARS) {
|
|
101
|
+
list = `${list.slice(0, READ_GROUP_LIST_MAX_CHARS)}…`;
|
|
102
|
+
}
|
|
103
|
+
return `⏺ Read ${rows.length} files · ${list}${more}`;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=read-group.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read-group.js","sourceRoot":"","sources":["../../src/components/read-group.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `!` shell-mode behavior for the root pi-tui mount, factored out of
|
|
3
|
+
* components/root.ts so that file stays under its line budget.
|
|
4
|
+
*
|
|
5
|
+
* Shell mode is derived, not stored: the composer is in shell mode exactly
|
|
6
|
+
* while its text starts with `!`. The border switches to the warning role
|
|
7
|
+
* so the mode is visible, ↑/↓ browse the bash-only history stack, and Esc
|
|
8
|
+
* exits the mode ahead of the generic busy-interrupt branch (the ordering
|
|
9
|
+
* in root.ts's input listener is deliberate). Paste normalization lives at
|
|
10
|
+
* the driver's submit — a `!`-prefixed line runs locally no matter how it
|
|
11
|
+
* got into the buffer.
|
|
12
|
+
* @module @dsh-cc/tui/components/root-bash
|
|
13
|
+
*/
|
|
14
|
+
import type { Editor, TUI } from '@dsh-cc/pi-tui';
|
|
15
|
+
import type { Theme } from './theme.ts';
|
|
16
|
+
import type { Driver } from '../state/driver-types.ts';
|
|
17
|
+
export interface AttachBashModeArgs {
|
|
18
|
+
editor: Editor;
|
|
19
|
+
driver: Driver;
|
|
20
|
+
tui: TUI;
|
|
21
|
+
theme: Theme;
|
|
22
|
+
}
|
|
23
|
+
export interface BashModeHandle {
|
|
24
|
+
/** True while a `!` command is in flight; the composer is disabled. */
|
|
25
|
+
bashRunning(): boolean;
|
|
26
|
+
inShellMode(): boolean;
|
|
27
|
+
browseBashHistory(towardsOlder: boolean): void;
|
|
28
|
+
resetBashHistoryBrowsing(): void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Install the `!` shell-mode state and the editor change/submit hooks that
|
|
32
|
+
* drive it. Owns the bash-history browsing stack; assigns editor.onChange /
|
|
33
|
+
* editor.onSubmit exactly as root.ts did inline, so behavior is unchanged.
|
|
34
|
+
*/
|
|
35
|
+
export declare function attachBashMode(args: AttachBashModeArgs): BashModeHandle;
|
|
36
|
+
//# sourceMappingURL=root-bash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-bash.d.ts","sourceRoot":"","sources":["../../src/components/root-bash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AAGtD,MAAM,WAAW,kBAAkB;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,GAAG,CAAA;IACR,KAAK,EAAE,KAAK,CAAA;CACZ;AAED,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,WAAW,IAAI,OAAO,CAAA;IACtB,WAAW,IAAI,OAAO,CAAA;IACtB,iBAAiB,CAAC,YAAY,EAAE,OAAO,GAAG,IAAI,CAAA;IAC9C,wBAAwB,IAAI,IAAI,CAAA;CACjC;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,cAAc,CA6FvE"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `!` shell-mode behavior for the root pi-tui mount, factored out of
|
|
3
|
+
* components/root.ts so that file stays under its line budget.
|
|
4
|
+
*
|
|
5
|
+
* Shell mode is derived, not stored: the composer is in shell mode exactly
|
|
6
|
+
* while its text starts with `!`. The border switches to the warning role
|
|
7
|
+
* so the mode is visible, ↑/↓ browse the bash-only history stack, and Esc
|
|
8
|
+
* exits the mode ahead of the generic busy-interrupt branch (the ordering
|
|
9
|
+
* in root.ts's input listener is deliberate). Paste normalization lives at
|
|
10
|
+
* the driver's submit — a `!`-prefixed line runs locally no matter how it
|
|
11
|
+
* got into the buffer.
|
|
12
|
+
* @module @dsh-cc/tui/components/root-bash
|
|
13
|
+
*/
|
|
14
|
+
import { parseSlash } from "../slash.js";
|
|
15
|
+
/**
|
|
16
|
+
* Install the `!` shell-mode state and the editor change/submit hooks that
|
|
17
|
+
* drive it. Owns the bash-history browsing stack; assigns editor.onChange /
|
|
18
|
+
* editor.onSubmit exactly as root.ts did inline, so behavior is unchanged.
|
|
19
|
+
*/
|
|
20
|
+
export function attachBashMode(args) {
|
|
21
|
+
const { editor, driver, tui, theme } = args;
|
|
22
|
+
let bashBrowsing = false;
|
|
23
|
+
let bashBrowsingIndex = -1;
|
|
24
|
+
let bashDraft = '';
|
|
25
|
+
let bashRecallApplied = false;
|
|
26
|
+
let bashRunning = false;
|
|
27
|
+
const inShellMode = () => editor.getText().startsWith('!');
|
|
28
|
+
const resetBashHistoryBrowsing = () => {
|
|
29
|
+
bashBrowsing = false;
|
|
30
|
+
bashBrowsingIndex = -1;
|
|
31
|
+
bashDraft = '';
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Browse the bash history stack (driver-owned, newest-first). ↑ walks
|
|
35
|
+
* toward older entries; ↓ walks back and restores the pre-browsing draft
|
|
36
|
+
* past the newest. Recalled entries are re-prefixed with `!` so the buffer
|
|
37
|
+
* stays shell-shaped and Enter re-runs them through the same submit path.
|
|
38
|
+
*/
|
|
39
|
+
const browseBashHistory = (towardsOlder) => {
|
|
40
|
+
const entries = driver.bashHistory;
|
|
41
|
+
if (entries.length === 0)
|
|
42
|
+
return;
|
|
43
|
+
if (!bashBrowsing) {
|
|
44
|
+
bashBrowsing = true;
|
|
45
|
+
bashBrowsingIndex = -1;
|
|
46
|
+
bashDraft = editor.getText();
|
|
47
|
+
}
|
|
48
|
+
if (towardsOlder) {
|
|
49
|
+
if (bashBrowsingIndex + 1 >= entries.length)
|
|
50
|
+
return; // clamped at the oldest
|
|
51
|
+
bashBrowsingIndex += 1;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
bashBrowsingIndex -= 1;
|
|
55
|
+
if (bashBrowsingIndex < 0) {
|
|
56
|
+
// Down past the newest entry: restore the pre-browsing draft.
|
|
57
|
+
const draft = bashDraft;
|
|
58
|
+
resetBashHistoryBrowsing();
|
|
59
|
+
bashRecallApplied = true;
|
|
60
|
+
editor.setText(draft);
|
|
61
|
+
bashRecallApplied = false;
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
bashRecallApplied = true;
|
|
66
|
+
editor.setText(`!${entries[bashBrowsingIndex]}`);
|
|
67
|
+
bashRecallApplied = false;
|
|
68
|
+
};
|
|
69
|
+
// Mirror the shell-mode border on every buffer change: the warning role
|
|
70
|
+
// while the buffer holds a `!`-prefixed line, the accent role otherwise.
|
|
71
|
+
const syncShellModeBorder = () => {
|
|
72
|
+
const styler = inShellMode() ? theme.warning : theme.accent;
|
|
73
|
+
if (editor.borderColor !== styler) {
|
|
74
|
+
editor.borderColor = styler;
|
|
75
|
+
tui.requestRender();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
editor.onChange = (text) => {
|
|
79
|
+
driver.setDraft(text);
|
|
80
|
+
syncShellModeBorder();
|
|
81
|
+
// Any buffer change that was not a bash recall ends history browsing,
|
|
82
|
+
// so the next ↑ starts fresh (mirrors the editor's own navigation).
|
|
83
|
+
if (!bashRecallApplied)
|
|
84
|
+
resetBashHistoryBrowsing();
|
|
85
|
+
};
|
|
86
|
+
editor.onSubmit = (text) => {
|
|
87
|
+
if (text.startsWith('!')) {
|
|
88
|
+
// Shell command: never a composer prompt. While the driver runs it,
|
|
89
|
+
// the composer is disabled — the input listener swallows every key
|
|
90
|
+
// until submit settles (bounded by the command's own timeout).
|
|
91
|
+
resetBashHistoryBrowsing();
|
|
92
|
+
bashRunning = true;
|
|
93
|
+
void driver.submit(text)
|
|
94
|
+
.catch(() => { })
|
|
95
|
+
.then(() => {
|
|
96
|
+
bashRunning = false;
|
|
97
|
+
tui.requestRender();
|
|
98
|
+
});
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const parsed = parseSlash(text);
|
|
102
|
+
// Only prompts join editor recall; slash commands are not prompts.
|
|
103
|
+
if (parsed.kind === 'none')
|
|
104
|
+
editor.addToHistory(text);
|
|
105
|
+
// Submit is fire-and-forget. Quit/exit finalization — including the
|
|
106
|
+
// /quit worktree-exit confirmation — is owned by the driver's quit path
|
|
107
|
+
// (config.onQuit), not by the onSubmit special-case it used to have here.
|
|
108
|
+
void driver.submit(text);
|
|
109
|
+
};
|
|
110
|
+
return { bashRunning: () => bashRunning, inShellMode, browseBashHistory, resetBashHistoryBrowsing };
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=root-bash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-bash.js","sourceRoot":"","sources":["../../src/components/root-bash.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public mount contracts for the root pi-tui component, split out of root.ts
|
|
3
|
+
* to keep the factory under the line budget. Deliberately a leaf — must not
|
|
4
|
+
* import root.ts.
|
|
5
|
+
* @module @dsh-cc/tui/components/root-types
|
|
6
|
+
*/
|
|
7
|
+
import type { Editor, Terminal, TUI, TuiMode } from '@dsh-cc/pi-tui';
|
|
8
|
+
import type { ThemeOverrides } from './theme.ts';
|
|
9
|
+
export interface BuildRootOptions {
|
|
10
|
+
terminal?: Terminal;
|
|
11
|
+
onQuit?: () => void;
|
|
12
|
+
/**
|
|
13
|
+
* 'regular' (default) renders inline into the main screen scrollback;
|
|
14
|
+
* 'fullscreen' enters the alternate screen on start: the transcript scrolls
|
|
15
|
+
* inside a primary ScrollView while the dock (queue, todos, overlays,
|
|
16
|
+
* editor, statusline) stays pinned at the bottom.
|
|
17
|
+
*/
|
|
18
|
+
uiMode?: TuiMode;
|
|
19
|
+
/** Fullscreen-only: mouse capture for wheel scrolling and app-owned selection. Default true. */
|
|
20
|
+
mouse?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Per-role palette overrides for the terminal theme. Every role accepts a
|
|
23
|
+
* basic ANSI color name or a raw SGR code string; invalid values keep the
|
|
24
|
+
* built-in default, so an absent (or partial) override renders exactly like
|
|
25
|
+
* the historical fixed palette.
|
|
26
|
+
*/
|
|
27
|
+
theme?: ThemeOverrides;
|
|
28
|
+
}
|
|
29
|
+
export interface RootHandle {
|
|
30
|
+
readonly tui: TUI;
|
|
31
|
+
readonly editor: Editor;
|
|
32
|
+
readonly mode: TuiMode;
|
|
33
|
+
destroy(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Stop the surface. In fullscreen mode this leaves the alternate screen
|
|
36
|
+
* with the final frame preserved, then replays the chrome through a one-shot
|
|
37
|
+
* main-screen renderer so native scrollback ends up with the same inline
|
|
38
|
+
* layout a regular session would have produced.
|
|
39
|
+
*/
|
|
40
|
+
stopForExit(): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=root-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-types.d.ts","sourceRoot":"","sources":["../../src/components/root-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,gGAAgG;IAChG,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,cAAc,CAAA;CACtB;AAED,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;IACtB,OAAO,IAAI,IAAI,CAAA;IACf;;;;;OAKG;IACH,WAAW,IAAI,IAAI,CAAA;CACnB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public mount contracts for the root pi-tui component, split out of root.ts
|
|
3
|
+
* to keep the factory under the line budget. Deliberately a leaf — must not
|
|
4
|
+
* import root.ts.
|
|
5
|
+
* @module @dsh-cc/tui/components/root-types
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=root-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-types.js","sourceRoot":"","sources":["../../src/components/root-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone helpers and constants extracted from the root mount: OS URL
|
|
3
|
+
* opening, active-task text capping, window-title sanitizing, and the
|
|
4
|
+
* double-press quit window.
|
|
5
|
+
* Deliberately a leaf — must not import root.ts.
|
|
6
|
+
* @module @dsh-cc/tui/components/root-utils
|
|
7
|
+
*/
|
|
8
|
+
/** How long after the first idle Ctrl+C a second press still quits (ms). */
|
|
9
|
+
export declare const DOUBLE_PRESS_WINDOW_MS = 2000;
|
|
10
|
+
export declare function truncateActive(content: string): string;
|
|
11
|
+
/**
|
|
12
|
+
* Make a string safe for an OSC 0 window-title write: strip control
|
|
13
|
+
* characters, trim, cap the length, and fall back to 'dsh-cc' when nothing
|
|
14
|
+
* printable remains.
|
|
15
|
+
*/
|
|
16
|
+
export declare function sanitizeWindowTitle(title: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Open an OSC 8 hyperlink with the OS handler. Fullscreen mouse capture takes
|
|
19
|
+
* over the terminal's native link activation, so clicks are routed here.
|
|
20
|
+
*/
|
|
21
|
+
export declare function openSystemUrl(url: string): void;
|
|
22
|
+
//# sourceMappingURL=root-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"root-utils.d.ts","sourceRoot":"","sources":["../../src/components/root-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,4EAA4E;AAC5E,eAAO,MAAM,sBAAsB,OAAO,CAAA;AAK1C,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEtD;AAWD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIzD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAM/C"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone helpers and constants extracted from the root mount: OS URL
|
|
3
|
+
* opening, active-task text capping, window-title sanitizing, and the
|
|
4
|
+
* double-press quit window.
|
|
5
|
+
* Deliberately a leaf — must not import root.ts.
|
|
6
|
+
* @module @dsh-cc/tui/components/root-utils
|
|
7
|
+
*/
|
|
8
|
+
import { spawn } from 'node:child_process';
|
|
9
|
+
/** How long after the first idle Ctrl+C a second press still quits (ms). */
|
|
10
|
+
export const DOUBLE_PRESS_WINDOW_MS = 2000;
|
|
11
|
+
/** Cap the active-task text shown in the todo strip (ellipsis past the cap). */
|
|
12
|
+
const TODO_ACTIVE_CAP = 60;
|
|
13
|
+
export function truncateActive(content) {
|
|
14
|
+
return content.length > TODO_ACTIVE_CAP ? `${content.slice(0, TODO_ACTIVE_CAP - 1)}…` : content;
|
|
15
|
+
}
|
|
16
|
+
/** Cap the terminal window title (chars, post-sanitize). */
|
|
17
|
+
const WINDOW_TITLE_CAP = 120;
|
|
18
|
+
// C0 controls (ESC/BEL included — they terminate or inject OSC sequences),
|
|
19
|
+
// DEL, and C1 controls. The session-title service already normalizes; this
|
|
20
|
+
// is defense-in-depth on an LLM-derived string crossing into the terminal.
|
|
21
|
+
// eslint-disable-next-line no-control-regex
|
|
22
|
+
const WINDOW_TITLE_CONTROL_CHARS = /[\x00-\x1f\x7f\x80-\x9f]/g;
|
|
23
|
+
/**
|
|
24
|
+
* Make a string safe for an OSC 0 window-title write: strip control
|
|
25
|
+
* characters, trim, cap the length, and fall back to 'dsh-cc' when nothing
|
|
26
|
+
* printable remains.
|
|
27
|
+
*/
|
|
28
|
+
export function sanitizeWindowTitle(title) {
|
|
29
|
+
const cleaned = title.replace(WINDOW_TITLE_CONTROL_CHARS, '').trim();
|
|
30
|
+
if (cleaned.length === 0)
|
|
31
|
+
return 'dsh-cc';
|
|
32
|
+
return cleaned.length > WINDOW_TITLE_CAP ? cleaned.slice(0, WINDOW_TITLE_CAP) : cleaned;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Open an OSC 8 hyperlink with the OS handler. Fullscreen mouse capture takes
|
|
36
|
+
* over the terminal's native link activation, so clicks are routed here.
|
|
37
|
+
*/
|
|
38
|
+
export function openSystemUrl(url) {
|
|
39
|
+
const child = process.platform === 'win32'
|
|
40
|
+
? spawn('cmd.exe', ['/c', 'start', '', url], { stdio: 'ignore', detached: true })
|
|
41
|
+
: spawn(process.platform === 'darwin' ? 'open' : 'xdg-open', [url], { stdio: 'ignore', detached: true });
|
|
42
|
+
child.on('error', () => { });
|
|
43
|
+
child.unref();
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=root-utils.js.map
|