@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,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transcript view: a Container that mirrors the TuiState rows. Assistant rows
|
|
3
|
+
* render through the vendored Markdown component; other row kinds use Text.
|
|
4
|
+
* Per-row identity caching avoids re-parsing unchanged historical markdown on
|
|
5
|
+
* every streaming chunk, and a source-line budget clips the oldest rows when
|
|
6
|
+
* the transcript grows very long.
|
|
7
|
+
* @module @dsh-cc/tui/components/transcript
|
|
8
|
+
*/
|
|
9
|
+
import { Container, Markdown, Text, } from '@dsh-cc/pi-tui';
|
|
10
|
+
import { toolVerb } from "../tool-verbs.js";
|
|
11
|
+
import { renderDiffLines } from "./diff-card.js";
|
|
12
|
+
import { createMarkdownTheme } from "./markdown-theme.js";
|
|
13
|
+
import { groupReadRows, readGroupCacheKey, renderReadGroup } from "./read-group.js";
|
|
14
|
+
import { defaultTheme } from "./theme.js";
|
|
15
|
+
/** Drop oldest rows once the total source-line count exceeds this. */
|
|
16
|
+
export const TRANSCRIPT_LINE_BUDGET = 2000;
|
|
17
|
+
/** Cheap source-line count for a row (NOT rendered lines). */
|
|
18
|
+
export function rowSourceLines(row, theme, options) {
|
|
19
|
+
if (row.kind === 'tool') {
|
|
20
|
+
return 1 + toolOutputLines(row, theme);
|
|
21
|
+
}
|
|
22
|
+
if (row.kind === 'compact') {
|
|
23
|
+
const expanded = options?.compactExpanded ?? false;
|
|
24
|
+
if (!expanded || row.summary.length === 0)
|
|
25
|
+
return 1;
|
|
26
|
+
return 1 + row.summary.split('\n').length;
|
|
27
|
+
}
|
|
28
|
+
return row.text.split('\n').length;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Line count of a tool row's collapsible output: rendered diff hunks when a
|
|
32
|
+
* diff card is present, otherwise the summary body/result (args as the last
|
|
33
|
+
* fallback, matching the expanded renderer). 0 when there is nothing to hide.
|
|
34
|
+
*/
|
|
35
|
+
function toolOutputLines(row, theme) {
|
|
36
|
+
if (row.diffs !== undefined && row.diffs.length > 0) {
|
|
37
|
+
// Diff hunks replace the summary body; count their rendered lines.
|
|
38
|
+
return renderDiffLines(row.diffs, undefined, theme).length;
|
|
39
|
+
}
|
|
40
|
+
const body = row.body ?? row.result ?? row.args;
|
|
41
|
+
if (body === undefined || body.length === 0)
|
|
42
|
+
return 0;
|
|
43
|
+
return body.split('\n').length;
|
|
44
|
+
}
|
|
45
|
+
/** Collapse-mode line for a compact boundary row. */
|
|
46
|
+
function compactRowText(row, options, theme) {
|
|
47
|
+
const expanded = options?.compactExpanded ?? false;
|
|
48
|
+
const head = `${row.trigger === 'auto' ? 'Auto-compacted' : 'Compacted'} ${row.items} messages (~${row.tokens} tokens)`;
|
|
49
|
+
if (!expanded) {
|
|
50
|
+
return theme.muted(theme.italic(`── ${head} — Ctrl+O to show summary ──`));
|
|
51
|
+
}
|
|
52
|
+
return row.summary.length > 0
|
|
53
|
+
? theme.muted(`── ${head} ──\n${row.summary}`)
|
|
54
|
+
: theme.muted(`── ${head} ──`);
|
|
55
|
+
}
|
|
56
|
+
export function renderRowText(row, options, theme = defaultTheme) {
|
|
57
|
+
switch (row.kind) {
|
|
58
|
+
case 'user':
|
|
59
|
+
return theme.accent(`> ${row.text}`);
|
|
60
|
+
case 'assistant':
|
|
61
|
+
return row.text;
|
|
62
|
+
case 'thinking': {
|
|
63
|
+
const expanded = options?.thinkingExpanded ?? false;
|
|
64
|
+
if (!expanded) {
|
|
65
|
+
const lines = row.text.split('\n').length;
|
|
66
|
+
return theme.muted(theme.italic(`▸ thinking (${lines} lines — Ctrl+O to toggle)`));
|
|
67
|
+
}
|
|
68
|
+
return theme.muted(theme.italic(`▾ ${row.text}`));
|
|
69
|
+
}
|
|
70
|
+
case 'tool': {
|
|
71
|
+
// Running rows lead with a muted present-tense verb (Running/Reading/…);
|
|
72
|
+
// completed rows drop the verb and show only a result glyph.
|
|
73
|
+
const status = row.running ? '…' : (row.error === true ? '✗' : '✓');
|
|
74
|
+
const verbPrefix = row.running ? `${theme.muted(toolVerb(row.name))} ` : '';
|
|
75
|
+
const head = theme.warning(`⏺ ${verbPrefix}${row.title} ${status}`);
|
|
76
|
+
const headLine = row.error === true ? theme.error(head) : head;
|
|
77
|
+
// Collapsed: drop the output entirely (diff hunks, body, or result) and
|
|
78
|
+
// point at the toggle. Rows with no output keep the bare head line.
|
|
79
|
+
if (!(options?.toolOutputExpanded ?? true)) {
|
|
80
|
+
const lines = toolOutputLines(row, theme);
|
|
81
|
+
return lines > 0
|
|
82
|
+
? `${headLine}\n${theme.muted(`▸ output (${lines} lines — Ctrl+O to toggle)`)}`
|
|
83
|
+
: headLine;
|
|
84
|
+
}
|
|
85
|
+
// When structured diffs are present, render real hunks beneath the head.
|
|
86
|
+
// The one-line summary body is replaced to avoid duplicating the path info.
|
|
87
|
+
if (row.diffs !== undefined && row.diffs.length > 0) {
|
|
88
|
+
const diffLines = renderDiffLines(row.diffs, undefined, theme);
|
|
89
|
+
return diffLines.length > 0 ? `${headLine}\n${diffLines.join('\n')}` : headLine;
|
|
90
|
+
}
|
|
91
|
+
const body = row.body ?? row.result ?? row.args;
|
|
92
|
+
if (body !== undefined && body.length > 0) {
|
|
93
|
+
const firstLine = body.split('\n')[0] ?? '';
|
|
94
|
+
return `${headLine}\n ⎿ ${row.error === true ? theme.error(firstLine) : firstLine}`;
|
|
95
|
+
}
|
|
96
|
+
return headLine;
|
|
97
|
+
}
|
|
98
|
+
case 'compact':
|
|
99
|
+
return compactRowText(row, options, theme);
|
|
100
|
+
case 'banner':
|
|
101
|
+
// Pre-styled UI chrome (boot whale): rendered verbatim, never re-styled.
|
|
102
|
+
return row.text;
|
|
103
|
+
case 'status':
|
|
104
|
+
// Error status rows (turn/end failures) render in the error role; plain
|
|
105
|
+
// status notices stay muted.
|
|
106
|
+
return row.error === true ? theme.error(row.text) : theme.muted(row.text);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Banner art Text: suppresses the boot whale below 44 columns — pi-tui's
|
|
111
|
+
* word-wrap shreds multi-line block art at narrow widths (internal spaces
|
|
112
|
+
* become wrap opportunities and continuation lines lose leading whitespace),
|
|
113
|
+
* so instead of a mangled smear the art collapses to a blank line.
|
|
114
|
+
*/
|
|
115
|
+
class BannerText extends Text {
|
|
116
|
+
render(width) {
|
|
117
|
+
if (width < 44)
|
|
118
|
+
return [''];
|
|
119
|
+
return super.render(width);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Build the pi-tui component for a single row. */
|
|
123
|
+
function buildChild(row, options, theme) {
|
|
124
|
+
if (row.kind === 'assistant') {
|
|
125
|
+
return new Markdown(row.text, 0, 0, createMarkdownTheme(theme));
|
|
126
|
+
}
|
|
127
|
+
if (row.kind === 'banner') {
|
|
128
|
+
return new BannerText(renderRowText(row, options, theme), 0, 0);
|
|
129
|
+
}
|
|
130
|
+
return new Text(renderRowText(row, options, theme), 0, 0);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Container that renders transcript rows as stacked Text/Markdown components.
|
|
134
|
+
* Call `setRows` whenever the driver emits a new state. Styling comes from the
|
|
135
|
+
* injected `theme` (default: the built-in palette).
|
|
136
|
+
*/
|
|
137
|
+
export class TranscriptView extends Container {
|
|
138
|
+
theme;
|
|
139
|
+
prevCache = new Map();
|
|
140
|
+
prevThinkingExpanded = false;
|
|
141
|
+
prevToolOutputExpanded = true;
|
|
142
|
+
prevCompactExpanded = false;
|
|
143
|
+
constructor(theme = defaultTheme) {
|
|
144
|
+
super();
|
|
145
|
+
this.theme = theme;
|
|
146
|
+
}
|
|
147
|
+
setRows(rows, options) {
|
|
148
|
+
const thinkingExpanded = options?.thinkingExpanded ?? false;
|
|
149
|
+
const toolOutputExpanded = options?.toolOutputExpanded ?? true;
|
|
150
|
+
const compactExpanded = options?.compactExpanded ?? false;
|
|
151
|
+
const thinkingFlagChanged = thinkingExpanded !== this.prevThinkingExpanded;
|
|
152
|
+
const toolFlagChanged = toolOutputExpanded !== this.prevToolOutputExpanded;
|
|
153
|
+
const compactFlagChanged = compactExpanded !== this.prevCompactExpanded;
|
|
154
|
+
// Apply the line budget: drop oldest rows until under budget (always keep
|
|
155
|
+
// at least one row so a single huge paste is not emptied entirely). The
|
|
156
|
+
// budget counts RAW rows; read grouping happens strictly after clipping
|
|
157
|
+
// and only affects rendering.
|
|
158
|
+
const clipped = Array.from(rows);
|
|
159
|
+
let dropped = 0;
|
|
160
|
+
let total = clipped.reduce((sum, r) => sum + rowSourceLines(r, this.theme, { compactExpanded }), 0);
|
|
161
|
+
while (total > TRANSCRIPT_LINE_BUDGET && clipped.length > 1) {
|
|
162
|
+
total -= rowSourceLines(clipped[0], this.theme, { compactExpanded });
|
|
163
|
+
clipped.shift();
|
|
164
|
+
dropped++;
|
|
165
|
+
}
|
|
166
|
+
// Build children with identity caching. The store's immutable updates
|
|
167
|
+
// only replace changed row objects, so reference-keyed reuse keeps the
|
|
168
|
+
// existing component (and its render cache) for unchanged rows. Thinking
|
|
169
|
+
// and tool rows are the exception: their rendering depends on the
|
|
170
|
+
// thinkingExpanded / toolOutputExpanded flags, so a flag change forces a
|
|
171
|
+
// rebuild even when the row reference is unchanged (the collapse toggles
|
|
172
|
+
// do not touch the rows array). Read-group children are flag-independent
|
|
173
|
+
// (their cache key is the member callId list), so they reuse across flips.
|
|
174
|
+
const cache = new Map();
|
|
175
|
+
const rowChildren = [];
|
|
176
|
+
for (const item of groupReadRows(clipped)) {
|
|
177
|
+
if (item.kind === 'readGroup') {
|
|
178
|
+
const key = readGroupCacheKey(item.rows);
|
|
179
|
+
const child = this.prevCache.get(key) ?? new Text(renderReadGroup(item.rows), 0, 0);
|
|
180
|
+
cache.set(key, child);
|
|
181
|
+
rowChildren.push(child);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
const row = item.row;
|
|
185
|
+
const stale = (thinkingFlagChanged && row.kind === 'thinking') ||
|
|
186
|
+
(toolFlagChanged && row.kind === 'tool') ||
|
|
187
|
+
(compactFlagChanged && row.kind === 'compact');
|
|
188
|
+
const child = (stale ? undefined : this.prevCache.get(row))
|
|
189
|
+
?? buildChild(row, { thinkingExpanded, toolOutputExpanded, compactExpanded }, this.theme);
|
|
190
|
+
cache.set(row, child);
|
|
191
|
+
rowChildren.push(child);
|
|
192
|
+
}
|
|
193
|
+
// Prepend a muted clip indicator when rows were dropped.
|
|
194
|
+
this.children = dropped > 0
|
|
195
|
+
? [new Text(this.theme.muted(`… earlier output hidden (${dropped} rows)`), 0, 0), ...rowChildren]
|
|
196
|
+
: rowChildren;
|
|
197
|
+
this.prevCache = cache;
|
|
198
|
+
this.prevThinkingExpanded = thinkingExpanded;
|
|
199
|
+
this.prevToolOutputExpanded = toolOutputExpanded;
|
|
200
|
+
this.prevCompactExpanded = compactExpanded;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=transcript.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript.js","sourceRoot":"","sources":["../../src/components/transcript.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live working line rendered above the editor: a braille spinner plus a
|
|
3
|
+
* per-tick message (elapsed time, output-token delta). The component owns its
|
|
4
|
+
* own 80ms interval — it is the SINGLE file in tui/src allowed to create one
|
|
5
|
+
* (whitelisted in tests/no-polling.spec.ts; any new exemption means touching
|
|
6
|
+
* that test first).
|
|
7
|
+
* @module @dsh-cc/tui/components/working-line
|
|
8
|
+
*/
|
|
9
|
+
import { Text } from '@dsh-cc/pi-tui';
|
|
10
|
+
/** A function that wraps text in an SGR style (same shape as the theme roles). */
|
|
11
|
+
type Styler = (text: string) => string;
|
|
12
|
+
/**
|
|
13
|
+
* Self-driving status row: `start()` shows the line and ticks the spinner,
|
|
14
|
+
* `stop()` tears the interval down and blanks the text (an empty Text renders
|
|
15
|
+
* zero lines, so an idle row collapses). The message is re-evaluated through
|
|
16
|
+
* `messageFn` on every tick, so elapsed time and token deltas keep moving
|
|
17
|
+
* even when no driver events arrive. Not auto-started: the root starts/stops
|
|
18
|
+
* it on `state.turn` anchor jumps.
|
|
19
|
+
*/
|
|
20
|
+
export declare class WorkingLine extends Text {
|
|
21
|
+
private frameIndex;
|
|
22
|
+
private intervalId;
|
|
23
|
+
private readonly spinnerColorFn;
|
|
24
|
+
private readonly messageColorFn;
|
|
25
|
+
private readonly messageFn;
|
|
26
|
+
private readonly onDirty;
|
|
27
|
+
constructor(spinnerColorFn: Styler, messageColorFn: Styler, messageFn: () => string, onDirty: () => void);
|
|
28
|
+
/** (Re)arm the tick loop. Stops first, so a double start leaves no orphan. */
|
|
29
|
+
start(): void;
|
|
30
|
+
/** Tear the interval down and collapse the row (explicit blank, no freeze). */
|
|
31
|
+
stop(): void;
|
|
32
|
+
private tick;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=working-line.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-line.d.ts","sourceRoot":"","sources":["../../src/components/working-line.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAQrC,kFAAkF;AAClF,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;AAEtC;;;;;;;GAOG;AACH,qBAAa,WAAY,SAAQ,IAAI;IACnC,OAAO,CAAC,UAAU,CAAI;IACtB,OAAO,CAAC,UAAU,CAA4C;IAC9D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;gBAGlC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM,EACtB,SAAS,EAAE,MAAM,MAAM,EACvB,OAAO,EAAE,MAAM,IAAI;IASrB,8EAA8E;IAC9E,KAAK,IAAI,IAAI;IASb,+EAA+E;IAC/E,IAAI,IAAI,IAAI;IASZ,OAAO,CAAC,IAAI;CAWb"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live working line rendered above the editor: a braille spinner plus a
|
|
3
|
+
* per-tick message (elapsed time, output-token delta). The component owns its
|
|
4
|
+
* own 80ms interval — it is the SINGLE file in tui/src allowed to create one
|
|
5
|
+
* (whitelisted in tests/no-polling.spec.ts; any new exemption means touching
|
|
6
|
+
* that test first).
|
|
7
|
+
* @module @dsh-cc/tui/components/working-line
|
|
8
|
+
*/
|
|
9
|
+
import { Text } from '@dsh-cc/pi-tui';
|
|
10
|
+
/** Spinner frames — the same braille set as pi-tui's Loader. */
|
|
11
|
+
const FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
12
|
+
/** Frame interval in ms — matches pi-tui's Loader default. */
|
|
13
|
+
const TICK_MS = 80;
|
|
14
|
+
/**
|
|
15
|
+
* Self-driving status row: `start()` shows the line and ticks the spinner,
|
|
16
|
+
* `stop()` tears the interval down and blanks the text (an empty Text renders
|
|
17
|
+
* zero lines, so an idle row collapses). The message is re-evaluated through
|
|
18
|
+
* `messageFn` on every tick, so elapsed time and token deltas keep moving
|
|
19
|
+
* even when no driver events arrive. Not auto-started: the root starts/stops
|
|
20
|
+
* it on `state.turn` anchor jumps.
|
|
21
|
+
*/
|
|
22
|
+
export class WorkingLine extends Text {
|
|
23
|
+
frameIndex = 0;
|
|
24
|
+
intervalId;
|
|
25
|
+
spinnerColorFn;
|
|
26
|
+
messageColorFn;
|
|
27
|
+
messageFn;
|
|
28
|
+
onDirty;
|
|
29
|
+
constructor(spinnerColorFn, messageColorFn, messageFn, onDirty) {
|
|
30
|
+
super('', 0, 0);
|
|
31
|
+
this.spinnerColorFn = spinnerColorFn;
|
|
32
|
+
this.messageColorFn = messageColorFn;
|
|
33
|
+
this.messageFn = messageFn;
|
|
34
|
+
this.onDirty = onDirty;
|
|
35
|
+
}
|
|
36
|
+
/** (Re)arm the tick loop. Stops first, so a double start leaves no orphan. */
|
|
37
|
+
start() {
|
|
38
|
+
this.stop();
|
|
39
|
+
this.tick();
|
|
40
|
+
this.intervalId = setInterval(() => {
|
|
41
|
+
this.frameIndex = (this.frameIndex + 1) % FRAMES.length;
|
|
42
|
+
this.tick();
|
|
43
|
+
}, TICK_MS);
|
|
44
|
+
}
|
|
45
|
+
/** Tear the interval down and collapse the row (explicit blank, no freeze). */
|
|
46
|
+
stop() {
|
|
47
|
+
if (this.intervalId !== undefined) {
|
|
48
|
+
clearInterval(this.intervalId);
|
|
49
|
+
this.intervalId = undefined;
|
|
50
|
+
}
|
|
51
|
+
this.setText('');
|
|
52
|
+
this.onDirty();
|
|
53
|
+
}
|
|
54
|
+
tick() {
|
|
55
|
+
const message = this.messageFn();
|
|
56
|
+
if (message.length === 0) {
|
|
57
|
+
this.setText('');
|
|
58
|
+
this.onDirty();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const frame = FRAMES[this.frameIndex] ?? FRAMES[0];
|
|
62
|
+
this.setText(`${this.spinnerColorFn(frame)} ${this.messageColorFn(message)}`);
|
|
63
|
+
this.onDirty();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=working-line.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"working-line.js","sourceRoot":"","sources":["../../src/components/working-line.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAA;AAErC,gEAAgE;AAChE,MAAM,MAAM,GAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA;AAEpF,8DAA8D;AAC9D,MAAM,OAAO,GAAG,EAAE,CAAA;AAKlB;;;;;;;GAOG;AACH,MAAM,OAAO,WAAY,SAAQ,IAAI;IAC3B,UAAU,GAAG,CAAC,CAAA;IACd,UAAU,CAA4C;IAC7C,cAAc,CAAQ;IACtB,cAAc,CAAQ;IACtB,SAAS,CAAc;IACvB,OAAO,CAAY;IAEpC,YACE,cAAsB,EACtB,cAAsB,EACtB,SAAuB,EACvB,OAAmB;QAEnB,KAAK,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACf,IAAI,CAAC,cAAc,GAAG,cAAc,CAAA;QACpC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAA;QACpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,8EAA8E;IAC9E,KAAK;QACH,IAAI,CAAC,IAAI,EAAE,CAAA;QACX,IAAI,CAAC,IAAI,EAAE,CAAA;QACX,IAAI,CAAC,UAAU,GAAG,WAAW,CAAC,GAAG,EAAE;YACjC,IAAI,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAA;YACvD,IAAI,CAAC,IAAI,EAAE,CAAA;QACb,CAAC,EAAE,OAAO,CAAC,CAAA;IACb,CAAC;IAED,+EAA+E;IAC/E,IAAI;QACF,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAClC,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;YAC9B,IAAI,CAAC,UAAU,GAAG,SAAS,CAAA;QAC7B,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAChB,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;IAEO,IAAI;QACV,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAChC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;YAChB,IAAI,CAAC,OAAO,EAAE,CAAA;YACd,OAAM;QACR,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,CAAC,CAAE,CAAA;QACnD,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC7E,IAAI,CAAC,OAAO,EAAE,CAAA;IAChB,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure reasoning-effort choice parsing and picker formatting for `/effort`.
|
|
3
|
+
* Mirrors model-catalog.ts; levels always come from the resolved model's
|
|
4
|
+
* advertised efforts — never a hard-coded universal list.
|
|
5
|
+
* @module @dsh-cc/tui/effort-catalog
|
|
6
|
+
*/
|
|
7
|
+
export type EffortChoice = {
|
|
8
|
+
kind: 'default';
|
|
9
|
+
} | {
|
|
10
|
+
kind: 'level';
|
|
11
|
+
level: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Resolve an `/effort` argument. `default` is a reserved keyword — it wins
|
|
15
|
+
* even when a model advertises an effort literally named `default`. Anything
|
|
16
|
+
* else must exactly match one of the model's efforts.
|
|
17
|
+
* @param input - the raw argument (trimmed here).
|
|
18
|
+
* @param efforts - the resolved model's advertised effort levels.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseEffortChoice(input: string, efforts: readonly string[]): EffortChoice | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Render the effort picker rows: the model's levels plus a trailing
|
|
23
|
+
* `default (provider)` entry, starring the live effort. No effort set means
|
|
24
|
+
* the provider default is live, so the default entry carries the star.
|
|
25
|
+
*/
|
|
26
|
+
export declare function formatEffortList(efforts: readonly string[], current: string | undefined): string;
|
|
27
|
+
//# sourceMappingURL=effort-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effort-catalog.d.ts","sourceRoot":"","sources":["../src/effort-catalog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAEjF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,YAAY,GAAG,SAAS,CAMrG;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAIhG"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure reasoning-effort choice parsing and picker formatting for `/effort`.
|
|
3
|
+
* Mirrors model-catalog.ts; levels always come from the resolved model's
|
|
4
|
+
* advertised efforts — never a hard-coded universal list.
|
|
5
|
+
* @module @dsh-cc/tui/effort-catalog
|
|
6
|
+
*/
|
|
7
|
+
/** Trailing picker/status entry that resets effort to the provider default. */
|
|
8
|
+
const DEFAULT_ENTRY = 'default (provider)';
|
|
9
|
+
/**
|
|
10
|
+
* Resolve an `/effort` argument. `default` is a reserved keyword — it wins
|
|
11
|
+
* even when a model advertises an effort literally named `default`. Anything
|
|
12
|
+
* else must exactly match one of the model's efforts.
|
|
13
|
+
* @param input - the raw argument (trimmed here).
|
|
14
|
+
* @param efforts - the resolved model's advertised effort levels.
|
|
15
|
+
*/
|
|
16
|
+
export function parseEffortChoice(input, efforts) {
|
|
17
|
+
const token = input.trim();
|
|
18
|
+
if (token.length === 0)
|
|
19
|
+
return undefined;
|
|
20
|
+
if (token === 'default')
|
|
21
|
+
return { kind: 'default' };
|
|
22
|
+
if (efforts.includes(token))
|
|
23
|
+
return { kind: 'level', level: token };
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Render the effort picker rows: the model's levels plus a trailing
|
|
28
|
+
* `default (provider)` entry, starring the live effort. No effort set means
|
|
29
|
+
* the provider default is live, so the default entry carries the star.
|
|
30
|
+
*/
|
|
31
|
+
export function formatEffortList(efforts, current) {
|
|
32
|
+
return [...efforts, DEFAULT_ENTRY]
|
|
33
|
+
.map(row => `${(row === current || (current === undefined && row === DEFAULT_ENTRY)) ? '*' : ' '} ${row}`)
|
|
34
|
+
.join('\n');
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=effort-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effort-catalog.js","sourceRoot":"","sources":["../src/effort-catalog.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,+EAA+E;AAC/E,MAAM,aAAa,GAAG,oBAAoB,CAAA;AAI1C;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa,EAAE,OAA0B;IACzE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC1B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAA;IACxC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;IACnD,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACnE,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAA0B,EAAE,OAA2B;IACtF,OAAO,CAAC,GAAG,OAAO,EAAE,aAAa,CAAC;SAC/B,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,GAAG,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;SACzG,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render the transcript rows as a Markdown document for `/export-md`. Pure
|
|
3
|
+
* formatting: no fs access, no driver imports, so it unit-tests without a
|
|
4
|
+
* harness. Row mapping: user → blockquote, assistant → verbatim text,
|
|
5
|
+
* thinking → collapsed `<details>`, tool → fenced `tool <name>` block (with
|
|
6
|
+
* the result summary, or a `…running` marker) plus a fenced `diff` block when
|
|
7
|
+
* structured diffs are present, status → italics (errors get a ⚠ marker), banner
|
|
8
|
+
* → skipped (pre-styled UI chrome must not leak raw SGR/block glyphs).
|
|
9
|
+
* @module @dsh-cc/tui/export-markdown
|
|
10
|
+
*/
|
|
11
|
+
import type { TranscriptRow } from './store.ts';
|
|
12
|
+
/**
|
|
13
|
+
* Render the whole transcript as one Markdown document: blocks separated by
|
|
14
|
+
* a blank line, terminated by a single trailing newline. An empty transcript
|
|
15
|
+
* produces an empty string.
|
|
16
|
+
*/
|
|
17
|
+
export declare function rowsToMarkdown(rows: readonly TranscriptRow[]): string;
|
|
18
|
+
//# sourceMappingURL=export-markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-markdown.d.ts","sourceRoot":"","sources":["../src/export-markdown.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AA8F/C;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,CAarE"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Render the transcript rows as a Markdown document for `/export-md`. Pure
|
|
3
|
+
* formatting: no fs access, no driver imports, so it unit-tests without a
|
|
4
|
+
* harness. Row mapping: user → blockquote, assistant → verbatim text,
|
|
5
|
+
* thinking → collapsed `<details>`, tool → fenced `tool <name>` block (with
|
|
6
|
+
* the result summary, or a `…running` marker) plus a fenced `diff` block when
|
|
7
|
+
* structured diffs are present, status → italics (errors get a ⚠ marker), banner
|
|
8
|
+
* → skipped (pre-styled UI chrome must not leak raw SGR/block glyphs).
|
|
9
|
+
* @module @dsh-cc/tui/export-markdown
|
|
10
|
+
*/
|
|
11
|
+
/** Placeholder for a tool call still running (or one that never returned a result). */
|
|
12
|
+
const RUNNING_MARK = '…running';
|
|
13
|
+
/** Prefix every line so multi-line text stays inside one blockquote. */
|
|
14
|
+
function blockquote(text) {
|
|
15
|
+
return text.split('\n').map(line => `> ${line}`).join('\n');
|
|
16
|
+
}
|
|
17
|
+
/** Wrap text in a collapsed-by-default details block. */
|
|
18
|
+
function details(text) {
|
|
19
|
+
return ['<details>', '<summary>thinking</summary>', '', text, '', '</details>'].join('\n');
|
|
20
|
+
}
|
|
21
|
+
function fence(tag, body) {
|
|
22
|
+
return ['```' + tag, body, '```'].join('\n');
|
|
23
|
+
}
|
|
24
|
+
/** Split into lines, dropping the phantom empty element of a trailing newline. */
|
|
25
|
+
function lines(text) {
|
|
26
|
+
const parts = text.split('\n');
|
|
27
|
+
return parts.at(-1) === '' ? parts.slice(0, -1) : parts;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* One self-contained ```diff fence per FileDiff list: `---`/`+++` headers are
|
|
31
|
+
* assembled here (oldText `null` renders as a new file against /dev/null),
|
|
32
|
+
* with the full old text as `-` lines followed by the new text as `+` lines.
|
|
33
|
+
*/
|
|
34
|
+
function diffBlock(diffs) {
|
|
35
|
+
const out = [];
|
|
36
|
+
for (const diff of diffs) {
|
|
37
|
+
out.push(diff.oldText === null ? '--- /dev/null' : `--- a/${diff.path}`);
|
|
38
|
+
out.push(`+++ b/${diff.path}`);
|
|
39
|
+
if (diff.oldText !== null) {
|
|
40
|
+
for (const line of lines(diff.oldText))
|
|
41
|
+
out.push(`-${line}`);
|
|
42
|
+
}
|
|
43
|
+
for (const line of lines(diff.newText))
|
|
44
|
+
out.push(`+${line}`);
|
|
45
|
+
}
|
|
46
|
+
return fence('diff', out.join('\n'));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A tool row renders a fenced `tool <name>` block with the result summary —
|
|
50
|
+
* running or result-less calls show the {@link RUNNING_MARK} marker, an
|
|
51
|
+
* explicit empty result renders an empty fence, errored results get a ⚠
|
|
52
|
+
* prefix. Structured diffs, when present, follow as their own ```diff block
|
|
53
|
+
* (a finished diff-only row skips the otherwise-bogus running marker).
|
|
54
|
+
*/
|
|
55
|
+
function toolBlocks(row) {
|
|
56
|
+
const blocks = [];
|
|
57
|
+
// Summary fence: running calls (and result-less calls without diffs) show
|
|
58
|
+
// the running marker; an explicit empty result renders an empty fence. A
|
|
59
|
+
// finished diff-only row skips the summary — its diff block IS the payload.
|
|
60
|
+
if (row.running || row.result !== undefined || row.diffs === undefined) {
|
|
61
|
+
let summary = row.running || row.result === undefined ? RUNNING_MARK : row.result;
|
|
62
|
+
if (row.error === true)
|
|
63
|
+
summary = `⚠ ${summary}`;
|
|
64
|
+
blocks.push(fence(`tool ${row.name}`, summary));
|
|
65
|
+
}
|
|
66
|
+
if (row.diffs !== undefined)
|
|
67
|
+
blocks.push(diffBlock(row.diffs));
|
|
68
|
+
return blocks;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A compact boundary exports as an italic one-liner plus a collapsed details
|
|
72
|
+
* block carrying the checkpoint summary (omitted when there is none).
|
|
73
|
+
*/
|
|
74
|
+
function compactBlock(row) {
|
|
75
|
+
const head = `${row.trigger === 'auto' ? 'Auto-compacted' : 'Compacted'} ${row.items} messages (~${row.tokens} tokens)`;
|
|
76
|
+
if (row.summary.length === 0)
|
|
77
|
+
return `*${head}*`;
|
|
78
|
+
const details = [
|
|
79
|
+
'<details>',
|
|
80
|
+
'<summary>compacted summary</summary>',
|
|
81
|
+
'',
|
|
82
|
+
row.summary,
|
|
83
|
+
'',
|
|
84
|
+
'</details>',
|
|
85
|
+
].join('\n');
|
|
86
|
+
return `*${head}*\n\n${details}`;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Italicize per line so multi-line status text stays valid Markdown. Error
|
|
90
|
+
* rows get a ⚠ marker — unless the text already carries one (the transcript
|
|
91
|
+
* fold bakes `⚠` into turn-failure texts), in which case it must not double.
|
|
92
|
+
*/
|
|
93
|
+
function statusBlock(text, error) {
|
|
94
|
+
const body = text.split('\n').map(line => `*${line}*`).join('\n');
|
|
95
|
+
return error === true && !text.startsWith('⚠') ? `⚠ ${body}` : body;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Render the whole transcript as one Markdown document: blocks separated by
|
|
99
|
+
* a blank line, terminated by a single trailing newline. An empty transcript
|
|
100
|
+
* produces an empty string.
|
|
101
|
+
*/
|
|
102
|
+
export function rowsToMarkdown(rows) {
|
|
103
|
+
const blocks = [];
|
|
104
|
+
for (const row of rows) {
|
|
105
|
+
if (row.kind === 'banner')
|
|
106
|
+
continue;
|
|
107
|
+
else if (row.kind === 'user')
|
|
108
|
+
blocks.push(blockquote(row.text));
|
|
109
|
+
else if (row.kind === 'assistant')
|
|
110
|
+
blocks.push(row.text);
|
|
111
|
+
else if (row.kind === 'thinking')
|
|
112
|
+
blocks.push(details(row.text));
|
|
113
|
+
else if (row.kind === 'tool')
|
|
114
|
+
blocks.push(...toolBlocks(row));
|
|
115
|
+
else if (row.kind === 'compact')
|
|
116
|
+
blocks.push(compactBlock(row));
|
|
117
|
+
else
|
|
118
|
+
blocks.push(statusBlock(row.text, row.error));
|
|
119
|
+
}
|
|
120
|
+
if (blocks.length === 0)
|
|
121
|
+
return '';
|
|
122
|
+
return `${blocks.join('\n\n')}\n`;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=export-markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"export-markdown.js","sourceRoot":"","sources":["../src/export-markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval-prompt preview builders extracted from harness/driver.ts: argument
|
|
3
|
+
* restoration from the session log, structured payload previews, permission
|
|
4
|
+
* rule derivation, and settings-conflict detection. Pure functions over the
|
|
5
|
+
* approval request and store view types — no I/O and no harness state.
|
|
6
|
+
* @module @dsh-cc/tui/harness/approval-preview
|
|
7
|
+
*/
|
|
8
|
+
import type { ApprovalRequest } from '@deepseek-ai/dsh-user-approval';
|
|
9
|
+
import type { ApprovalPreview } from '../store.ts';
|
|
10
|
+
/**
|
|
11
|
+
* Build the approval prompt's structured payload preview from the restored
|
|
12
|
+
* call arguments: shell-style `command` arguments map to the command kind;
|
|
13
|
+
* Edit/MultiEdit/Write arguments map to per-file diffs (rendered with the
|
|
14
|
+
* transcript's multi-hunk diff renderer); anything else pretty-prints the raw
|
|
15
|
+
* arguments, and a failed recovery degrades to tool name + reason only.
|
|
16
|
+
*/
|
|
17
|
+
export declare function payloadOf(req: ApprovalRequest): ApprovalPreview;
|
|
18
|
+
/**
|
|
19
|
+
* Derive the permission rule an "always" answer persists for the approved
|
|
20
|
+
* call. Shell commands get a trailing-space first-word prefix rule
|
|
21
|
+
* (`Bash(npm )` matches `npm install …` but not `npmx …` — the deliberate
|
|
22
|
+
* trailing space replaces the colon-carrying `:*` legacy form, which would
|
|
23
|
+
* otherwise embed the colon in the prefix and never match). Environment
|
|
24
|
+
* variable prefixes (e.g., `FOO=bar`) are stripped before extracting the
|
|
25
|
+
* first word, so `FOO=bar npm install` derives a rule for `npm`, not `FOO=bar`.
|
|
26
|
+
* A WebFetch call derives a `WebFetch(domain:<host>)` rule on the exact host
|
|
27
|
+
* from its `url` argument; every other tool gets a whole-tool rule. Undefined
|
|
28
|
+
* (stay once-only) when nothing usable remains, e.g. a blank command.
|
|
29
|
+
*/
|
|
30
|
+
export declare function allowRuleOf(toolName: string, preview: ApprovalPreview | undefined): string | undefined;
|
|
31
|
+
/** Whether an error is the settings provider's revision-conflict rejection. */
|
|
32
|
+
export declare function isSettingsConflict(error: unknown): boolean;
|
|
33
|
+
//# sourceMappingURL=approval-preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approval-preview.d.ts","sourceRoot":"","sources":["../../src/harness/approval-preview.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAErE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AA6ClD;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,eAAe,GAAG,eAAe,CAa/D;AA+BD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAsDtG;AAED,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAI1D"}
|