@xmoon76/dsh-pi-tui 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -7
- package/README.zh-CN.md +22 -5
- package/dist/builtins.mjs +1 -1
- package/dist/extension/advanced.d.mts +1 -1
- package/dist/extension/unstable.d.mts +1 -1
- package/dist/extensions.d.mts +1 -1
- package/dist/extensions.mjs +1 -1
- package/dist/index.d.mts +237 -13
- package/dist/index.mjs +2 -2
- package/dist/{public-types-2omeXG8d.d.mts → public-types-CZz5_arj.d.mts} +3 -0
- package/dist/{src-ClAKiW0z.mjs → src-Txng8gIG.mjs} +7323 -1308
- package/package.json +5 -2
- package/scripts/bench.mts +6 -0
- package/scripts/e2e-session-lease.sh +388 -0
- package/scripts/preview-prompt.mts +62 -0
- package/scripts/preview-role-styles.mts +97 -0
- package/scripts/tarball-smoke.mjs +6 -2
package/README.md
CHANGED
|
@@ -336,17 +336,30 @@ the Advanced/Unstable roadmap).
|
|
|
336
336
|
pinned earlier** (`/rename` is an alias).
|
|
337
337
|
- `/tasks` — the merged task browser: background jobs AND subagents in one
|
|
338
338
|
searchable list (type to filter rows by kind/label/status — `subagent`,
|
|
339
|
-
`bash`, `failed`…).
|
|
340
|
-
subagent
|
|
341
|
-
|
|
339
|
+
`bash`, `failed`…). Subagent rows show their mode as part of the label
|
|
340
|
+
(`subagent · <label> · continuable` / `… · one-shot`) — you know before
|
|
341
|
+
Enter whether the viewer will be interactive. `Enter` opens the detail
|
|
342
|
+
(child viewer for a subagent, status viewer for a job), `i` interrupts
|
|
343
|
+
the selected subagent. `/subagents` is an alias.
|
|
342
344
|
- `/yolo` — switch to `danger-full-access` (alias of `/permission danger-full-access`).
|
|
343
345
|
- `/status` — show the current session's stats and identity (turn counts,
|
|
344
346
|
token usage, workspace, installed dsh version).
|
|
347
|
+
- `/rewind` — fork this conversation from an earlier user turn: the picker
|
|
348
|
+
lists every completed user prompt (newest first), and choosing one creates
|
|
349
|
+
a new child session whose history ends right before that turn, then
|
|
350
|
+
restores the selected prompt into the editor for editing. The original
|
|
351
|
+
session is never modified and stays reachable through `/sessions`;
|
|
352
|
+
**workspace and external side effects (files, shell, APIs) are not
|
|
353
|
+
reverted.** The same picker opens with `Esc Esc` on an empty editor.
|
|
345
354
|
- `/preset`, `/model`, `/settings`, `/export`, `/fork` — see
|
|
346
355
|
`dsh --profile pi-tui`'s command autocomplete (`/` + Tab).
|
|
347
356
|
|
|
348
357
|
## Keybindings (selection)
|
|
349
358
|
|
|
359
|
+
- `Esc Esc` — conversation rewind (on an empty editor while idle): open the
|
|
360
|
+
rewind picker and fork from an earlier user turn. One `Esc` while the
|
|
361
|
+
agent is busy still cancels the active turn/tool/shell command; with a
|
|
362
|
+
non-empty draft the double-Esc keeps its historical cancel behavior.
|
|
350
363
|
- `Ctrl+F` — toggle transcript search (the `/search <query>` overlay; a
|
|
351
364
|
second press closes it).
|
|
352
365
|
- `Shift+Tab` — cycle the permission preset (read-only → workspace-write →
|
|
@@ -366,10 +379,20 @@ the Advanced/Unstable roadmap).
|
|
|
366
379
|
fallback otherwise). The literal `@path` is submitted and the model reads
|
|
367
380
|
the file itself. With background work running, an empty editor's `↓` opens
|
|
368
381
|
the same merged task browser as `/tasks`:
|
|
369
|
-
- **subagent rows** (live
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
382
|
+
- **subagent rows** (live children, labeled with their catalog mode:
|
|
383
|
+
`continuable` or `one-shot`) — `Enter` opens the child's viewer:
|
|
384
|
+
a **continuable** child's viewer is **interactive** — type a
|
|
385
|
+
follow-up and press Enter, and it is delivered as the child's NEXT
|
|
386
|
+
turn through `ctx.subagents.followup` (FIFO — a running child is
|
|
387
|
+
never interrupted or steered; an inactive child cold-resumes
|
|
388
|
+
automatically), while `Esc` returns to your session. A **one-shot**
|
|
389
|
+
child's viewer stays **read-only** (`Esc` returns; the editor shows
|
|
390
|
+
the read-only placeholder). While a viewer is open the footer
|
|
391
|
+
switches to the CHILD's own identity (`[subagent · continuable]`
|
|
392
|
+
badge, label, activity, cwd, the child's own turns/steps/stats) and
|
|
393
|
+
returns to your session's on exit. `i` interrupts the selected
|
|
394
|
+
child. They never register job records, so this browser is their
|
|
395
|
+
only glanceable home.
|
|
373
396
|
- **job rows** (bash and one-shot subagent jobs) — `Enter` shows the status
|
|
374
397
|
viewer only: a bash job's output read cursor belongs to the model's
|
|
375
398
|
`job_output`, and a one-shot subagent job record carries no child session
|
package/README.zh-CN.md
CHANGED
|
@@ -299,18 +299,28 @@ SDK。原始终端访问、pre-host 输入拦截与完整输入所有权**不属
|
|
|
299
299
|
生成标题——这会覆盖当前标题,包括你之前固定的标题**(`/rename` 是
|
|
300
300
|
别名)。
|
|
301
301
|
- `/tasks` — 合并任务浏览器:后台 job 与子代理在同一个可搜索列表中
|
|
302
|
-
(直接输入过滤行——`subagent`、`bash`、`failed`…)
|
|
303
|
-
(
|
|
302
|
+
(直接输入过滤行——`subagent`、`bash`、`failed`…)。子代理行把 mode
|
|
303
|
+
写进主标签(`subagent · <label> · continuable` / `… · one-shot`),
|
|
304
|
+
按下 `Enter` 之前就能知道查看器是否可交互。`Enter` 打开详情
|
|
305
|
+
(子代理为子查看器,job 为状态查看器),`i` 中断选中的子代理。
|
|
304
306
|
`/subagents` 是别名。
|
|
305
307
|
- `/yolo` — 切换到 `danger-full-access`(`/permission danger-full-access`
|
|
306
308
|
的别名)。
|
|
307
309
|
- `/status` — 显示当前会话的统计与身份信息(回合数、token 用量、
|
|
308
310
|
工作区、已安装的 dsh 版本)。
|
|
311
|
+
- `/rewind` — 从更早的用户回合 fork 当前对话:选择器列出每个已完成
|
|
312
|
+
的用户提示(最新在上),选中一个会创建一个新的子会话,其历史恰好
|
|
313
|
+
止于该回合之前,并把选中的提示回填到编辑器供修改。原会话从不被
|
|
314
|
+
修改,仍可通过 `/sessions` 回到;**工作区与外部副作用(文件、shell、
|
|
315
|
+
API)不会回滚。** 空编辑器下按 `Esc Esc` 也会打开同一个选择器。
|
|
309
316
|
- `/preset`、`/model`、`/settings`、`/export`、`/fork` —
|
|
310
317
|
见 `dsh --profile pi-tui` 的命令自动补全(`/` + Tab)。
|
|
311
318
|
|
|
312
319
|
## 快捷键(节选)
|
|
313
320
|
|
|
321
|
+
- `Esc Esc` — 对话 rewind(空闲且编辑器为空时):打开 rewind 选择器,
|
|
322
|
+
从更早的用户回合 fork。agent 忙碌时按一次 `Esc` 仍只取消当前
|
|
323
|
+
回合/工具/shell 命令;草稿非空时双击 Esc 保持原有的取消语义。
|
|
314
324
|
- `Ctrl+F` — 切换转录搜索(`/search <query>` 覆盖层;再按一次关闭)。
|
|
315
325
|
- `Shift+Tab` — 循环切换权限预设(read-only → workspace-write →
|
|
316
326
|
danger-full-access);页脚的模式槽位会为每个预设显示徽章
|
|
@@ -327,9 +337,16 @@ SDK。原始终端访问、pre-host 输入拦截与完整输入所有权**不属
|
|
|
327
337
|
(`fd` 在 PATH 上时以其为后端,否则使用内置的递归回退)。字面
|
|
328
338
|
`@path` 会被提交,由模型自行读取文件。有后台工作时,空编辑器的 `↓`
|
|
329
339
|
会打开与 `/tasks` 相同的合并任务浏览器:
|
|
330
|
-
- **子代理行**(
|
|
331
|
-
|
|
332
|
-
|
|
340
|
+
- **子代理行**(实时子任务,标签携带目录 mode:`continuable` 或
|
|
341
|
+
`one-shot`)——`Enter` 打开子代理查看器:**continuable** 子代理的
|
|
342
|
+
查看器是**可交互的**——输入后续消息并回车,它会作为子代理的
|
|
343
|
+
**下一回合**通过 `ctx.subagents.followup` 投递(FIFO——运行中的
|
|
344
|
+
子代理不会被中断或 steer;非活跃的子代理会自动冷恢复),`Esc` 返回
|
|
345
|
+
主会话。**one-shot** 子代理的查看器保持**只读**(`Esc` 返回,编辑器
|
|
346
|
+
显示只读占位符)。查看器打开期间,页脚切换为**子代理自己的身份**
|
|
347
|
+
(`[subagent · continuable]` 徽章、标签、activity、cwd 与子代理自己的
|
|
348
|
+
turns/steps/stats),退出后恢复主会话页脚。`i` 中断选中的子代理。
|
|
349
|
+
它们从不注册 job 记录,所以此浏览器是它们唯一可一览的归宿。
|
|
333
350
|
- **job 行**(bash 与一次性子代理 job)——`Enter` 只显示状态查看器:
|
|
334
351
|
bash job 的输出读取游标属于模型的 `job_output`,而一次性子代理 job
|
|
335
352
|
记录不带子会话 id,因此子代理 job 的转录需通过 `/tasks` 按标签
|
package/dist/builtins.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TUI_STARTUP_SERVICE } from "./startup.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { H as PI_TUI_EXTENSIONS_SERVICE, L as dshVersion } from "./src-Txng8gIG.mjs";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
//#region src/builtins.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as PiTuiApiInfo, T as NormalizedKey, _ as ExtensionTier, at as TuiOverlayOptions, h as EditorSnapshot, v as ExtensionView } from "../public-types-
|
|
1
|
+
import { E as PiTuiApiInfo, T as NormalizedKey, _ as ExtensionTier, at as TuiOverlayOptions, h as EditorSnapshot, v as ExtensionView } from "../public-types-CZz5_arj.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/extension/advanced-types.d.ts
|
|
4
4
|
/** API level of the advanced tier. Bumped only on advanced breaking changes. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as PiTuiApiInfo, _ as ExtensionTier, at as TuiOverlayOptions } from "../public-types-
|
|
1
|
+
import { E as PiTuiApiInfo, _ as ExtensionTier, at as TuiOverlayOptions } from "../public-types-CZz5_arj.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/extension/unstable-types.d.ts
|
|
4
4
|
/** API level of the unstable tier. Bumped only on unstable breaking changes. */
|
package/dist/extensions.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as TuiKeybindingHandle, A as RegistrationHandle, B as ToolPresentationSnapshot, C as MarkdownView, D as PiTuiCapability, E as PiTuiApiInfo, F as StackView, G as TuiAutocompleteRegistryView, H as TuiAutocompleteItem, I as StyledSpan, J as TuiCommandBridgeSnapshot, K as TuiAutocompleteSuggestions, L as SurfaceSnapshot, M as RowsView, N as SessionSnapshot, O as PiTuiSlotName, P as SpacerView, Q as TuiKeybindingContribution, R as SurfaceStateValues, S as InputWidget, T as NormalizedKey, U as TuiAutocompleteProvider, V as TuiAction, W as TuiAutocompleteQuery, X as TuiCommandContribution, Y as TuiCommandBridgeView, Z as TuiCommandHandle, _t as TuiThemeRegistryView, a as ContributionHealth, at as TuiOverlayOptions, b as FrameView, c as DockItem, ct as TuiRendererRegistryView, d as EditorHost, dt as TuiSettingsRegistrySnapshot, et as TuiKeybindingRegistrySnapshot, f as EditorHostAction, ft as TuiSettingsRegistryView, g as ExtensionEditor, gt as TuiThemeRegistrySnapshot, h as EditorSnapshot, ht as TuiThemeHandle, i as AutocompleteProviderContribution, it as TuiOverlayHandle, j as RegistrationSpec, k as PiTuiSlotSemantic, l as EditorContribution, lt as TuiSettingContribution, m as EditorInputEvent, mt as TuiThemeContribution, n as ActivitySnapshot, nt as TuiLocalCommandHandler, o as ContributionRecord, ot as TuiRendererHandle, p as EditorHostActionResult, pt as TuiSizeValue, q as TuiColorPalette, r as AutocompleteHandle, rt as TuiMessageRendererContribution, s as ContributionState, st as TuiRendererRegistrySnapshot, t as API_VERSION, tt as TuiKeybindingRegistryView, u as EditorHandle, ut as TuiSettingHandle, v as ExtensionView, vt as TuiToolRendererContribution, w as MessagePresentationSnapshot, x as HeaderBadge, y as FooterSegment, yt as describeKey, z as TextView } from "./public-types-
|
|
1
|
+
import { $ as TuiKeybindingHandle, A as RegistrationHandle, B as ToolPresentationSnapshot, C as MarkdownView, D as PiTuiCapability, E as PiTuiApiInfo, F as StackView, G as TuiAutocompleteRegistryView, H as TuiAutocompleteItem, I as StyledSpan, J as TuiCommandBridgeSnapshot, K as TuiAutocompleteSuggestions, L as SurfaceSnapshot, M as RowsView, N as SessionSnapshot, O as PiTuiSlotName, P as SpacerView, Q as TuiKeybindingContribution, R as SurfaceStateValues, S as InputWidget, T as NormalizedKey, U as TuiAutocompleteProvider, V as TuiAction, W as TuiAutocompleteQuery, X as TuiCommandContribution, Y as TuiCommandBridgeView, Z as TuiCommandHandle, _t as TuiThemeRegistryView, a as ContributionHealth, at as TuiOverlayOptions, b as FrameView, c as DockItem, ct as TuiRendererRegistryView, d as EditorHost, dt as TuiSettingsRegistrySnapshot, et as TuiKeybindingRegistrySnapshot, f as EditorHostAction, ft as TuiSettingsRegistryView, g as ExtensionEditor, gt as TuiThemeRegistrySnapshot, h as EditorSnapshot, ht as TuiThemeHandle, i as AutocompleteProviderContribution, it as TuiOverlayHandle, j as RegistrationSpec, k as PiTuiSlotSemantic, l as EditorContribution, lt as TuiSettingContribution, m as EditorInputEvent, mt as TuiThemeContribution, n as ActivitySnapshot, nt as TuiLocalCommandHandler, o as ContributionRecord, ot as TuiRendererHandle, p as EditorHostActionResult, pt as TuiSizeValue, q as TuiColorPalette, r as AutocompleteHandle, rt as TuiMessageRendererContribution, s as ContributionState, st as TuiRendererRegistrySnapshot, t as API_VERSION, tt as TuiKeybindingRegistryView, u as EditorHandle, ut as TuiSettingHandle, v as ExtensionView, vt as TuiToolRendererContribution, w as MessagePresentationSnapshot, x as HeaderBadge, y as FooterSegment, yt as describeKey, z as TextView } from "./public-types-CZz5_arj.mjs";
|
|
2
2
|
import { Context, Service } from "@deepseek-ai/cordis";
|
|
3
3
|
|
|
4
4
|
//#region src/extension/service.d.ts
|
package/dist/extensions.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import "./startup.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { B as inject, H as PI_TUI_EXTENSIONS_SERVICE, U as API_VERSION, V as name, W as describeKey, z as apply } from "./src-Txng8gIG.mjs";
|
|
3
3
|
export { API_VERSION, PI_TUI_EXTENSIONS_SERVICE, apply, describeKey, inject, name };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,90 @@
|
|
|
1
|
+
import { V as TuiAction } from "./public-types-CZz5_arj.mjs";
|
|
1
2
|
import z from "@deepseek-ai/schemastery";
|
|
2
3
|
import { Agent, ModelSelectionRef } from "@deepseek-ai/dsh-agent";
|
|
3
4
|
import { ContentBlock } from "@deepseek-ai/dsh-llm";
|
|
4
5
|
import { SessionEvent, SessionId } from "@deepseek-ai/dsh-session";
|
|
5
6
|
import { CommandDescriptor } from "@deepseek-ai/dsh-commands";
|
|
6
7
|
import { Context } from "@deepseek-ai/cordis";
|
|
8
|
+
//#region src/image/admission.d.ts
|
|
9
|
+
/** Structural subset of `ImageAttachmentRef`. */
|
|
10
|
+
interface ImageAttachmentRefLike {
|
|
11
|
+
readonly attachmentId: string;
|
|
12
|
+
readonly mediaType: ImageMediaType;
|
|
13
|
+
readonly bytes: number;
|
|
14
|
+
readonly width: number;
|
|
15
|
+
readonly height: number;
|
|
16
|
+
readonly name?: string;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/image/types.d.ts
|
|
20
|
+
/**
|
|
21
|
+
* Image draft vocabulary for the TUI input pipeline (plan M1).
|
|
22
|
+
*
|
|
23
|
+
* The draft layer is TUI-owned: it stages clipboard/file bytes until a
|
|
24
|
+
* submission turns them into durable `ImageAttachmentRef`s through the dsh
|
|
25
|
+
* attachment service. Nothing in this module persists; the durable boundary
|
|
26
|
+
* is the harness's `ctx.attachments.saveImages()`.
|
|
27
|
+
*
|
|
28
|
+
* The media-type union mirrors `@deepseek-ai/dsh-attachment`'s
|
|
29
|
+
* `ImageMediaType` structurally, so drafts flow into the harness without a
|
|
30
|
+
* runtime dependency on the attachment package (AGENTS.md decision 7:
|
|
31
|
+
* structural typing for dsh services).
|
|
32
|
+
* @module @xmoon76/dsh-pi-tui/image/types
|
|
33
|
+
*/
|
|
34
|
+
/** Raster media types accepted by the TUI image intake. */
|
|
35
|
+
type ImageMediaType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif';
|
|
36
|
+
/** Per-TUI draft image identity; only meaningful inside one TUI run. */
|
|
37
|
+
type DraftImageId = number;
|
|
38
|
+
/** Where a staged image's bytes came from. */
|
|
39
|
+
type DraftImageSource = {
|
|
40
|
+
readonly type: 'clipboard';
|
|
41
|
+
} | {
|
|
42
|
+
readonly type: 'path';
|
|
43
|
+
readonly path: string;
|
|
44
|
+
}
|
|
45
|
+
/** The image was pulled back from a queued message: its bytes are ALREADY
|
|
46
|
+
* durable with the harness (the recalled ref) — the draft holds no local
|
|
47
|
+
* copy and re-submitting reuses the ref instead of re-uploading. */
|
|
48
|
+
| {
|
|
49
|
+
readonly type: 'recalled';
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* One image staged in the editor draft. The draft holds the raw bytes so
|
|
53
|
+
* clipboard and path entries share one shape and a submit never depends on
|
|
54
|
+
* the source file still existing (plan §5.1). A RECALLED draft (pulled
|
|
55
|
+
* back from the queue) instead carries the durable `ImageAttachmentRef`
|
|
56
|
+
* and NO local bytes — the bytes stay in harness storage and re-submitting
|
|
57
|
+
* reuses the ref.
|
|
58
|
+
*/
|
|
59
|
+
interface DraftImage {
|
|
60
|
+
/** Per-TUI draft identity (the `#N` of the placeholder). */
|
|
61
|
+
readonly id: DraftImageId;
|
|
62
|
+
readonly kind: 'image';
|
|
63
|
+
readonly source: DraftImageSource;
|
|
64
|
+
/** Exact encoded bytes, held only for the draft lifetime. Empty for a
|
|
65
|
+
* recalled draft (its bytes live in harness storage). */
|
|
66
|
+
readonly bytes: Uint8Array;
|
|
67
|
+
readonly mediaType: ImageMediaType;
|
|
68
|
+
/** Intrinsic encoded width in pixels. */
|
|
69
|
+
readonly width: number;
|
|
70
|
+
/** Intrinsic encoded height in pixels. */
|
|
71
|
+
readonly height: number;
|
|
72
|
+
/** Exact encoded byte length (`bytes.byteLength` for local drafts; the
|
|
73
|
+
* durable ref's recorded `bytes` for recalled drafts). */
|
|
74
|
+
readonly byteLength: number;
|
|
75
|
+
/** Optional display name (basename for path sources), never a path. */
|
|
76
|
+
readonly name?: string;
|
|
77
|
+
/** The canonical editor placeholder text for this draft. */
|
|
78
|
+
readonly placeholder: string;
|
|
79
|
+
/** The durable ref this draft reuses on submit; present ONLY for
|
|
80
|
+
* recalled drafts (already-durable images are never re-uploaded). */
|
|
81
|
+
readonly recalledRef?: ImageAttachmentRefLike;
|
|
82
|
+
}
|
|
83
|
+
/** The store surface the placeholder expansion needs (structural). */
|
|
84
|
+
interface DraftImageStoreLike {
|
|
85
|
+
values(): readonly DraftImage[];
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
7
88
|
//#region src/diag.d.ts
|
|
8
89
|
interface Diag {
|
|
9
90
|
debug(message: string, fields?: Record<string, unknown>): void;
|
|
@@ -15,6 +96,12 @@ interface Diag {
|
|
|
15
96
|
}
|
|
16
97
|
//#endregion
|
|
17
98
|
//#region src/tui-app.d.ts
|
|
99
|
+
/** The compaction lifecycle phase the working row advertises: idle (no
|
|
100
|
+
* compaction), summarizing (compaction/start seen, the summary is being
|
|
101
|
+
* generated), or applying (the summary landed, the compacted surface is
|
|
102
|
+
* being committed). Derived by the runner from compaction/start →
|
|
103
|
+
* compaction/summary → compaction/end (foldCompactionEvent). */
|
|
104
|
+
type CompactionPhase = 'idle' | 'summarizing' | 'applying';
|
|
18
105
|
/** One queued inbox row for the queue pane (mirrors the agent Inbox's lists). */
|
|
19
106
|
interface QueueItem {
|
|
20
107
|
/** The pending message id (agent inbox identity). */
|
|
@@ -159,6 +246,23 @@ declare const SESSIONLESS_COMMANDS: Set<string>;
|
|
|
159
246
|
* body — there is no command-execution wire for skills.
|
|
160
247
|
*/
|
|
161
248
|
declare const LOCAL_COMMANDS: Set<string>;
|
|
249
|
+
/**
|
|
250
|
+
* Command semantics matrix (plan §19.3/M12): a LOCAL command line carrying a
|
|
251
|
+
* staged image placeholder is REJECTED — local commands are pure UI
|
|
252
|
+
* controls, never LLM prompts. AGENT-FACING input (plain prompts AND
|
|
253
|
+
* per-skill slash invocations like `/grilling`) SUPPORTS images: the skill
|
|
254
|
+
* wrapper builds its message through the same prepared-input path, so an
|
|
255
|
+
* image-bearing skill line is a real multimodal prompt (review finding 4).
|
|
256
|
+
* There is never a silent drop.
|
|
257
|
+
* @param parsed - the parsed slash command, undefined for a plain prompt.
|
|
258
|
+
* @param text - the submission text.
|
|
259
|
+
* @param store - the live draft store.
|
|
260
|
+
* @param isLocal - whether the command name is a LOCAL (TUI-owned/UI)
|
|
261
|
+
* command; skill names answer false.
|
|
262
|
+
*/
|
|
263
|
+
declare function commandRejectsImages(parsed: {
|
|
264
|
+
name: string;
|
|
265
|
+
} | undefined, text: string, store: DraftImageStoreLike, isLocal: (name: string) => boolean): boolean;
|
|
162
266
|
/**
|
|
163
267
|
* The AUTHORITATIVE host-owned command catalog (P1-04): every command name
|
|
164
268
|
* the TUI registers itself (registerTuiCommands in commands.ts) plus the
|
|
@@ -183,7 +287,23 @@ declare const HOST_COMMAND_CATALOG: ReadonlySet<string>;
|
|
|
183
287
|
*/
|
|
184
288
|
declare function shouldSteerOnEnter(parsed: {
|
|
185
289
|
name: string;
|
|
290
|
+
rawInput?: string;
|
|
186
291
|
} | undefined, running: boolean, busyEnter: string | undefined, forceQueue: boolean, isDynamicLocal?: (name: string) => boolean): boolean;
|
|
292
|
+
/**
|
|
293
|
+
* Normalize an explicit `/skill <name> <args>` invocation to the skill's
|
|
294
|
+
* own slash line `/<name> <args>` (review finding 2). The harness's
|
|
295
|
+
* explicit skill gesture scans for `/<skill-name>` — it would extract
|
|
296
|
+
* `skill` from a raw `/skill grilling ...` line and never inject the
|
|
297
|
+
* grilling body. The command handler already performs this conversion
|
|
298
|
+
* (`loadSkill` builds `'/' + skill.name + ' ' + args`); the busy-Enter
|
|
299
|
+
* steer path must use the SAME normalized line so the body injects and
|
|
300
|
+
* any image placeholders ride along.
|
|
301
|
+
* @param text - the submitted line.
|
|
302
|
+
* @returns the normalized `/<name> <args>` line, or undefined when the
|
|
303
|
+
* line is not an explicit skill invocation (plain prompt, other
|
|
304
|
+
* commands, or the bare `/skill` picker).
|
|
305
|
+
*/
|
|
306
|
+
declare function normalizeSkillInvocation(text: string): string | undefined;
|
|
187
307
|
/**
|
|
188
308
|
* The advertised-claim miss decision (pure, exported for the headless
|
|
189
309
|
* suite): a slash input whose name was advertised by the completion list at
|
|
@@ -198,11 +318,94 @@ declare function shouldSteerOnEnter(parsed: {
|
|
|
198
318
|
declare function shouldConsumeAdvertisedMiss(execution: {
|
|
199
319
|
readonly result: unknown;
|
|
200
320
|
} | undefined, wasAdvertised: boolean): boolean;
|
|
321
|
+
/** The live-agent surface {@link interruptAgent} needs (structural — the
|
|
322
|
+
* TUI never imports the agent runtime for this call). */
|
|
323
|
+
interface InterruptAgentLike {
|
|
324
|
+
readonly status: string;
|
|
325
|
+
cancel(cause: {
|
|
326
|
+
kind: 'user';
|
|
327
|
+
}, options?: {
|
|
328
|
+
keepInbox?: boolean;
|
|
329
|
+
}): void;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Interrupt the live agent (web Stop parity): abort the current
|
|
333
|
+
* turn/tool run while PRESERVING the pending queue. dsh's DEFAULT
|
|
334
|
+
* `cancel()` clears queued AND steering input, so a bare cancel would
|
|
335
|
+
* destroy everything the user queued with Ctrl+S / queue-mode Enter —
|
|
336
|
+
* the Esc-interrupt semantic is "stop the current thinking", never
|
|
337
|
+
* "drop the queue". `keepInbox: true` parks the preserved work; dsh's
|
|
338
|
+
* cancel is a documented no-op when nothing is active, so an idle
|
|
339
|
+
* interrupt (double-Esc while idle) is harmless and still aborts a
|
|
340
|
+
* local shell / maintenance task through the caller.
|
|
341
|
+
*
|
|
342
|
+
* NOTE (upstream dependency): dsh currently PARKS the preserved queue
|
|
343
|
+
* after an abort — the "Esc with a queue continues immediately" UX
|
|
344
|
+
* needs an upstream `wakePending`/`continueInbox` capability (not yet
|
|
345
|
+
* in dsh). A TUI-side emulation (remove + re-send a queue message)
|
|
346
|
+
* would fabricate durable discarded/inserted events in the session
|
|
347
|
+
* log, which the design explicitly rejects — the parked queue is the
|
|
348
|
+
* agreed web-parity behavior until upstream lands the capability.
|
|
349
|
+
*/
|
|
350
|
+
declare function interruptAgent(agent: InterruptAgentLike | undefined): void;
|
|
201
351
|
/** One unsettled subagent delegation, in tool/call order. */
|
|
202
352
|
interface PendingSubagentCall {
|
|
203
353
|
readonly callId: string;
|
|
204
354
|
readonly description: string;
|
|
205
355
|
}
|
|
356
|
+
/**
|
|
357
|
+
* The async viewer-OPEN invalidation token (pure, exported for the headless
|
|
358
|
+
* suite — the runner closure itself is not drivable in the headless tests,
|
|
359
|
+
* so the lifecycle rule is tested through these token semantics). An open
|
|
360
|
+
* request captures a token; EVERY viewer session change — opening another
|
|
361
|
+
* child, leaving the viewer (Esc), or a session swap (which routes through
|
|
362
|
+
* exitView) — invalidates the token, so a slow transcript inspection can
|
|
363
|
+
* never commit an obsolete child over the current surface. Invalidation is
|
|
364
|
+
* unconditional: an exit that finds NO mounted viewer still invalidates,
|
|
365
|
+
* because the open is exactly then still in flight (round-5 finding).
|
|
366
|
+
*/
|
|
367
|
+
interface ViewerOpenToken {
|
|
368
|
+
/** The current token value (bumped by every open and every invalidate). */
|
|
369
|
+
readonly current: number;
|
|
370
|
+
/** Start one async open; returns the request's token. */
|
|
371
|
+
open(): number;
|
|
372
|
+
/** Invalidate every in-flight open (a viewer session change). */
|
|
373
|
+
invalidate(): void;
|
|
374
|
+
/** Whether a request may still commit. */
|
|
375
|
+
isCurrent(request: number): boolean;
|
|
376
|
+
}
|
|
377
|
+
declare function createViewerOpenToken(): ViewerOpenToken;
|
|
378
|
+
/**
|
|
379
|
+
* Session-swap viewer teardown (pure, exported for the headless suite —
|
|
380
|
+
* the runner closure is not headless-drivable, so the rule is pinned
|
|
381
|
+
* through this seam). A session swap must do BOTH: invalidate any
|
|
382
|
+
* in-flight viewer OPEN — UNCONDITIONALLY, because the open may still be
|
|
383
|
+
* loading when nothing is mounted yet, and the swap must still cancel it
|
|
384
|
+
* (round-6 finding) — and close a MOUNTED viewer when there is one.
|
|
385
|
+
* @param token - the shared viewer-open token.
|
|
386
|
+
* @param mounted - whether a viewer is currently mounted.
|
|
387
|
+
* @param closeMounted - closes the mounted viewer (a no-op when unmounted).
|
|
388
|
+
* @returns whether a mounted viewer was closed.
|
|
389
|
+
*/
|
|
390
|
+
declare function teardownViewerForSessionSwap(token: ViewerOpenToken, mounted: boolean, closeMounted: () => void): boolean;
|
|
391
|
+
/**
|
|
392
|
+
* The viewer capability gate for SEMANTIC plugin actions (pure, exported
|
|
393
|
+
* for the headless suite — the runner closure is not drivable there).
|
|
394
|
+
* While a subagent viewer is open, only actions that stay CHILD- or
|
|
395
|
+
* SURFACE-local are allowed; every action with PARENT-session side
|
|
396
|
+
* effects (steer, cancel/interrupt, permission cycling, the main
|
|
397
|
+
* transcript search) is blocked, so a plugin keybinding can never
|
|
398
|
+
* interrupt/steer/reconfigure the parent from inside the viewer. The
|
|
399
|
+
* raw-key viewer guard already consumes the parent chords — this gate
|
|
400
|
+
* closes the plugin-keybinding path, the only other way a semantic
|
|
401
|
+
* action reaches the runner.
|
|
402
|
+
* @param action - the semantic action the plugin requested.
|
|
403
|
+
* @param viewer - the open viewer (mode), or undefined when no viewer.
|
|
404
|
+
* @returns whether the runner may execute the action.
|
|
405
|
+
*/
|
|
406
|
+
declare function viewerActionCapability(action: TuiAction, viewer: {
|
|
407
|
+
mode: 'one-shot' | 'continuable';
|
|
408
|
+
} | undefined): boolean;
|
|
206
409
|
/**
|
|
207
410
|
* Match the child a user is about to view against the unsettled subagent
|
|
208
411
|
* calls (pure, exported for the headless suite). The child's durable label
|
|
@@ -336,17 +539,6 @@ interface QueueFoldResult {
|
|
|
336
539
|
/** Failed settlement summaries not yet notified (the caller notifies). */
|
|
337
540
|
readonly failures: readonly string[];
|
|
338
541
|
}
|
|
339
|
-
/**
|
|
340
|
-
* Build the queue-pane rows for one inbox batch, dropping background-subagent
|
|
341
|
-
* settlement notices (the task browser is their surface) and reporting which
|
|
342
|
-
* FAILED settlements should notify. Pure and injectable so the filter +
|
|
343
|
-
* once-notify semantics are testable without the agent.
|
|
344
|
-
* @param messages - one inbox batch (next-turn or next-step), in order.
|
|
345
|
-
* @param mode - the delivery mode for surviving rows.
|
|
346
|
-
* @param notified - the notify-once guard; failed notices already in it are
|
|
347
|
-
* skipped, and a newly-reported id is ADDED here so a re-render can never
|
|
348
|
-
* double-notify.
|
|
349
|
-
*/
|
|
350
542
|
declare function foldQueueRows(messages: readonly QueueInboxMessage[], mode: 'followup' | 'steer', notified: Set<string>): QueueFoldResult;
|
|
351
543
|
/**
|
|
352
544
|
* Whether a shell command matches a destructive pattern. `rm` is treated
|
|
@@ -397,6 +589,11 @@ interface CompactionFold {
|
|
|
397
589
|
* re-derived from the turn log (a stale end never clears a newer
|
|
398
590
|
* compaction's state). */
|
|
399
591
|
clear: boolean;
|
|
592
|
+
/** The compaction phase the event implies: compaction/start →
|
|
593
|
+
* 'summarizing', a MATCHED compaction/summary → 'applying'. Undefined
|
|
594
|
+
* when the event does not advance the phase (a stale summary, any
|
|
595
|
+
* compaction/end — the settle clears via {@link clear}). */
|
|
596
|
+
phase?: Exclude<CompactionPhase, 'idle'>;
|
|
400
597
|
/** The settle notification for compaction/end, when one fires. */
|
|
401
598
|
notify: {
|
|
402
599
|
text: string;
|
|
@@ -413,6 +610,23 @@ declare function foldCompactionEvent(state: {
|
|
|
413
610
|
error?: unknown;
|
|
414
611
|
};
|
|
415
612
|
}): CompactionFold;
|
|
613
|
+
/** The minimal compaction-settle surface the runner passes in — STRUCTURAL
|
|
614
|
+
* on purpose: referencing the full {@link TuiApp} class from a public
|
|
615
|
+
* export would inline the whole surface (and its internal registry/
|
|
616
|
+
* presentation dependencies) into the published declaration bundle. The
|
|
617
|
+
* settle contract only needs the three phase/busy/working setters. */
|
|
618
|
+
interface CompactionSettleSurface {
|
|
619
|
+
setCompactionPhase(phase: 'idle'): void;
|
|
620
|
+
setBusy(busy: boolean): void;
|
|
621
|
+
setWorking(busy: boolean): void;
|
|
622
|
+
}
|
|
623
|
+
/** The UI side effects of a MATCHED compaction settle: clear the phase,
|
|
624
|
+
* hand the working row back to the turn state, and re-measure the session
|
|
625
|
+
* surface so the footer context reflects the compacted log IMMEDIATELY —
|
|
626
|
+
* the next step/start or turn/end would otherwise delay the refresh.
|
|
627
|
+
* Exported as a seam so the settle contract is testable without a full
|
|
628
|
+
* runner driver (the firehose closure is not). */
|
|
629
|
+
declare function settleCompactionSurface(app: CompactionSettleSurface, refreshStatus: () => void, busyNow: boolean): void;
|
|
416
630
|
/** The busy flag after a turn-boundary event: a turn end must NOT clear
|
|
417
631
|
* the busy state while a compaction is still in flight — an interrupted
|
|
418
632
|
* turn can close (turn/end) before its compaction settles, and the
|
|
@@ -455,10 +669,20 @@ interface AgentComposition {
|
|
|
455
669
|
* @param ctx - the runner context (services read through `ctx.get`).
|
|
456
670
|
* @param selected - the mutable model selection every setup installs.
|
|
457
671
|
* @param presetId - the requested preset, or `undefined` for the default.
|
|
672
|
+
* @param focusState - the shared Focus runtime state (STRUCTURAL on
|
|
673
|
+
* purpose: the public declaration bundle must not inline src/focus.ts —
|
|
674
|
+
* the parameter only ever carries the runner's FocusState object, so a
|
|
675
|
+
* bare `{ enabled: boolean }` keeps the shipped .d.mts clean); when
|
|
676
|
+
* provided, the setup ALSO installs the dynamic Focus system-prompt
|
|
677
|
+
* section exactly once per composed agent (plan §9 — every composed
|
|
678
|
+
* root TUI agent gets it; /focus toggles never re-register).
|
|
679
|
+
* @param diag - the diagnostics channel, when the caller has one.
|
|
458
680
|
* @returns the id to record on the header (absent without a roster) and the setup callback.
|
|
459
681
|
* @throws when the roster supplies no such preset.
|
|
460
682
|
*/
|
|
461
|
-
declare function composeAgent(ctx: Context, selected: ModelSelectionRef, presetId?: string
|
|
683
|
+
declare function composeAgent(ctx: Context, selected: ModelSelectionRef, presetId?: string, focusState?: {
|
|
684
|
+
enabled: boolean;
|
|
685
|
+
}, diag?: Diag): Promise<AgentComposition>;
|
|
462
686
|
/**
|
|
463
687
|
* The preset a persisted session actually runs, from its log (newest
|
|
464
688
|
* selection winning), or undefined when persistence is absent, the session is
|
|
@@ -508,4 +732,4 @@ declare function recomposeBlank(ctx: Context, agent: {
|
|
|
508
732
|
*/
|
|
509
733
|
declare function apply(ctx: Context, config: Config): void;
|
|
510
734
|
//#endregion
|
|
511
|
-
export { AgentComposition, CompactionFold, Config, HOST_COMMAND_CATALOG, InitialCatalogResolution, LOCAL_COMMANDS, PendingSubagentCall, QueueFoldResult, QueueInboxMessage, QueueNoticeSource, RecomposableSession, RecomposeOutcome, ResolveInitialCatalogOptions, SESSIONLESS_COMMANDS, SessionLockRefusedError, apply, busyAfterTurnBoundary, compactingFromLog, composeAgent, dangerCommand, foldCompactionEvent, foldQueueRows, forkSeed, inject, isPlainExitPrompt, isSubagentSettlementNotice, isUserQueueInput, matchPendingSubagentCall, name, recomposeBlank, recordedPreset, registerCredentialSurfaceRefresh, resolveInitialCatalog, resumeCommand, runningProfile, shouldConsumeAdvertisedMiss, shouldSteerOnEnter, subagentJobTranscriptId, subagentJobViewHint, subagentNoticeIsFailure };
|
|
735
|
+
export { AgentComposition, CompactionFold, CompactionSettleSurface, Config, HOST_COMMAND_CATALOG, InitialCatalogResolution, InterruptAgentLike, LOCAL_COMMANDS, PendingSubagentCall, QueueFoldResult, QueueInboxMessage, QueueNoticeSource, RecomposableSession, RecomposeOutcome, ResolveInitialCatalogOptions, SESSIONLESS_COMMANDS, SessionLockRefusedError, ViewerOpenToken, apply, busyAfterTurnBoundary, commandRejectsImages, compactingFromLog, composeAgent, createViewerOpenToken, dangerCommand, foldCompactionEvent, foldQueueRows, forkSeed, inject, interruptAgent, isPlainExitPrompt, isSubagentSettlementNotice, isUserQueueInput, matchPendingSubagentCall, name, normalizeSkillInvocation, recomposeBlank, recordedPreset, registerCredentialSurfaceRefresh, resolveInitialCatalog, resumeCommand, runningProfile, settleCompactionSurface, shouldConsumeAdvertisedMiss, shouldSteerOnEnter, subagentJobTranscriptId, subagentJobViewHint, subagentNoticeIsFailure, teardownViewerForSessionSwap, viewerActionCapability };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import "./startup.mjs";
|
|
2
|
-
import { C as
|
|
3
|
-
export { Config, HOST_COMMAND_CATALOG, LOCAL_COMMANDS, SESSIONLESS_COMMANDS, SessionLockRefusedError, apply, busyAfterTurnBoundary, compactingFromLog, composeAgent, dangerCommand, foldCompactionEvent, foldQueueRows, forkSeed, inject, isPlainExitPrompt, isSubagentSettlementNotice, isUserQueueInput, matchPendingSubagentCall, name, recomposeBlank, recordedPreset, registerCredentialSurfaceRefresh, resolveInitialCatalog, resumeCommand, runningProfile, shouldConsumeAdvertisedMiss, shouldSteerOnEnter, subagentJobTranscriptId, subagentJobViewHint, subagentNoticeIsFailure };
|
|
2
|
+
import { A as shouldConsumeAdvertisedMiss, C as recomposeBlank, D as resumeCommand, E as resolveInitialCatalog, F as teardownViewerForSessionSwap, I as viewerActionCapability, M as subagentJobTranscriptId, N as subagentJobViewHint, O as runningProfile, P as subagentNoticeIsFailure, R as forkSeed, S as normalizeSkillInvocation, T as registerCredentialSurfaceRefresh, _ as isPlainExitPrompt, a as SessionLockRefusedError, b as matchPendingSubagentCall, c as commandRejectsImages, d as createViewerOpenToken, f as dangerCommand, g as interruptAgent, h as inject, i as SESSIONLESS_COMMANDS, j as shouldSteerOnEnter, k as settleCompactionSurface, l as compactingFromLog, m as foldQueueRows, n as HOST_COMMAND_CATALOG, o as apply, p as foldCompactionEvent, r as LOCAL_COMMANDS, s as busyAfterTurnBoundary, t as Config, u as composeAgent, v as isSubagentSettlementNotice, w as recordedPreset, x as name, y as isUserQueueInput } from "./src-Txng8gIG.mjs";
|
|
3
|
+
export { Config, HOST_COMMAND_CATALOG, LOCAL_COMMANDS, SESSIONLESS_COMMANDS, SessionLockRefusedError, apply, busyAfterTurnBoundary, commandRejectsImages, compactingFromLog, composeAgent, createViewerOpenToken, dangerCommand, foldCompactionEvent, foldQueueRows, forkSeed, inject, interruptAgent, isPlainExitPrompt, isSubagentSettlementNotice, isUserQueueInput, matchPendingSubagentCall, name, normalizeSkillInvocation, recomposeBlank, recordedPreset, registerCredentialSurfaceRefresh, resolveInitialCatalog, resumeCommand, runningProfile, settleCompactionSurface, shouldConsumeAdvertisedMiss, shouldSteerOnEnter, subagentJobTranscriptId, subagentJobViewHint, subagentNoticeIsFailure, teardownViewerForSessionSwap, viewerActionCapability };
|
|
@@ -35,6 +35,9 @@ interface TuiColorPalette {
|
|
|
35
35
|
diffGutter: string;
|
|
36
36
|
diffMeta: string;
|
|
37
37
|
roleUser: string;
|
|
38
|
+
/** Optional user-bubble background (dsh-web `--dsw-specific-bubble`
|
|
39
|
+
* parity); absent = no bubble block. */
|
|
40
|
+
roleUserBg?: string;
|
|
38
41
|
shellMode: string;
|
|
39
42
|
}
|
|
40
43
|
/** One autocomplete suggestion item (structural — the host maps it onto
|