@aiwayds/dsh-tui-pi 2.11.4 → 2.13.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.
Files changed (44) hide show
  1. package/README.md +4 -4
  2. package/README.zh-CN.md +1 -1
  3. package/lib/agents.d.ts +5 -1
  4. package/lib/agents.js +28 -3
  5. package/lib/agents.js.map +1 -1
  6. package/lib/history.js +2 -2
  7. package/lib/history.js.map +1 -1
  8. package/lib/index.js +28 -10
  9. package/lib/index.js.map +1 -1
  10. package/lib/live-widgets.d.ts +25 -9
  11. package/lib/live-widgets.js +81 -29
  12. package/lib/live-widgets.js.map +1 -1
  13. package/lib/log-repair.d.ts +10 -13
  14. package/lib/log-repair.js +11 -26
  15. package/lib/log-repair.js.map +1 -1
  16. package/lib/messages.d.ts +11 -1
  17. package/lib/messages.js +18 -4
  18. package/lib/messages.js.map +1 -1
  19. package/lib/retention.d.ts +10 -4
  20. package/lib/retention.js +15 -4
  21. package/lib/retention.js.map +1 -1
  22. package/lib/session-dir.d.ts +26 -0
  23. package/lib/session-dir.js +53 -0
  24. package/lib/session-dir.js.map +1 -0
  25. package/lib/session.d.ts +37 -44
  26. package/lib/session.js +167 -232
  27. package/lib/session.js.map +1 -1
  28. package/lib/sessions.d.ts +51 -4
  29. package/lib/sessions.js +45 -3
  30. package/lib/sessions.js.map +1 -1
  31. package/lib/subagent-policy.d.ts +41 -9
  32. package/lib/subagent-policy.js +133 -20
  33. package/lib/subagent-policy.js.map +1 -1
  34. package/lib/subagent-status-tool.d.ts +50 -0
  35. package/lib/subagent-status-tool.js +125 -0
  36. package/lib/subagent-status-tool.js.map +1 -0
  37. package/lib/theme-settings.d.ts +12 -1
  38. package/lib/theme-settings.js +12 -0
  39. package/lib/theme-settings.js.map +1 -1
  40. package/package.json +5 -5
  41. package/skills/dsh-tui-pi-config/SKILL.md +3 -2
  42. package/lib/writer-lock.d.ts +0 -70
  43. package/lib/writer-lock.js +0 -206
  44. package/lib/writer-lock.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: dsh-tui-pi-config
3
- description: "dsh TUI 增强套件(@aiwayds/dsh-tui-pi)使用与配置指南。凡涉及 TUI 主题/面板/footer、子代理并发与轮数限制、模型收藏与隐藏、会话保留清理与 /resume 过滤、preset 记忆,或要配置 dsh-tui 段时先读本指南:settings.yaml 顶层 `dsh-tui:` 段 14 键(theme/panelHeight/maxAgents/maxRounds/maxRoundsGrace/disableSubagent/footerHints/cacheHitMode/iconSet/rememberPreset/favoriteModels/hiddenModels/retention/resume)、DSH_TUI_* 环境变量、ask_user_question 快速上手向导、keybindings.json 与 /hotkeys。触发词:tui、主题、theme、面板、footer、收藏模型、隐藏模型、保留策略、panelHeight、resume、preset。"
3
+ description: "dsh TUI 增强套件(@aiwayds/dsh-tui-pi)使用与配置指南。凡涉及 TUI 主题/面板/footer、子代理并发与轮数限制、模型收藏与隐藏、会话保留清理与 /resume 过滤、preset 记忆,或要配置 dsh-tui 段时先读本指南:settings.yaml 顶层 `dsh-tui:` 段 15 键(theme/panelHeight/maxAgents/maxRounds/maxRoundsGrace/disableSubagent/registeredOnly/footerHints/cacheHitMode/iconSet/rememberPreset/favoriteModels/hiddenModels/retention/resume)、DSH_TUI_* 环境变量、ask_user_question 快速上手向导、keybindings.json 与 /hotkeys。触发词:tui、主题、theme、面板、footer、收藏模型、隐藏模型、保留策略、panelHeight、resume、preset。"
4
4
  ---
5
5
 
6
6
  # dsh-tui-pi 使用指南(TUI 主题 / 子代理治理 / 会话管理)
@@ -22,6 +22,7 @@ description: "dsh TUI 增强套件(@aiwayds/dsh-tui-pi)使用与配置指南
22
22
  | `maxRounds` | 非负整数 | `75` | 每个子代理 assistant 消息数上限,到达后注入收尾请求;`0` = 不限 |
23
23
  | `maxRoundsGrace` | 非负整数 | `7` | 收尾请求后的宽限轮数,超出即强制终止(one-shot cancel / continuable 保留会话可续聊);`0` = 仅警告不终止 |
24
24
  | `disableSubagent` | 布尔 | `true` | 禁原生 `subagent` 工具,委派改走 `~/.dsh/agents/*.md` 注册代理(`use_agent`);`subagent_fork`/`workflow`/`ralph` 不受影响 |
25
+ | `registeredOnly` | 布尔 | `false` | 仅 `use_agent` 可派生(子代理必须由 `~/.dsh/agents/*.md` 注册代理承载);`subagent`/`subagent_fork`/`workflow`/`ralph` 全部拒绝 |
25
26
  | `footerHints` | 7 个布尔 | 全 `true` | footer 快捷键提示分段开关:`send`/`stop`/`quit`/`quitEmpty`/`subagents`/`search`/`history` |
26
27
  | `cacheHitMode` | `'lastMessage'\|'session'` | `lastMessage` | footer CH 段口径:最新一条消息的命中率(pi-tui 语义)或全会话累计 |
27
28
  | `iconSet` | `'auto'\|'nerdfont'\|'plain'` | `auto` | 风险字形集;`auto` 按启动时字体探测选 nerdfont/plain |
@@ -73,7 +74,7 @@ favoriteModels/hiddenModels、retention/resume。
73
74
  | `/preset` | 切换 agent preset(确认对话框:fork 携带历史 / 全新开始 / 取消;`/preset next` 循环);默认按工作区记忆上次选择(`rememberPreset`) |
74
75
  | `/history` | 只读回看会话逐轮历史;`f` 在选中轮 fork 新会话,`/history <id>` 冷读任意存档 |
75
76
  | `/resume` | 恢复持久会话(受 `resume.*` 显示窗口过滤;`--resume <id>` 启动参数同源) |
76
- | `/agents` | 管理 `~/.dsh/agents/*.md`;`l` 进 limits 面板热调 `maxAgents`/`maxRounds`/`maxRoundsGrace`/`disableSubagent` |
77
+ | `/agents` | 管理 `~/.dsh/agents/*.md`;`l` 进 limits 面板热调 `maxAgents`/`maxRounds`/`maxRoundsGrace`/`disableSubagent`/`registeredOnly`(`r` 快捷切换 registered-only 栅栏) |
77
78
  | `/profile-switch` / `/profile-cfg` | 模型配置档,存储于 `$DSH_HOME/model-profiles.json` |
78
79
  | `~/.dsh/APPEND_SYSTEM.md` | 用户可编辑的主 agent system prompt 追加文件(不作用于子代理) |
79
80
 
@@ -1,70 +0,0 @@
1
- /**
2
- * Single-writer guard — a vendored, zero-dependency per-session pid-file
3
- * lock, byte-for-byte the same contract the feishu plugin's guard uses so
4
- * both surfaces compete on one file.
5
- *
6
- * Why it exists: two dsh processes pointed at the same profile each keep
7
- * their own agent registry; `agents.get` cannot see the other process's
8
- * live agent. A cold resume there therefore forks the log: two agents
9
- * append to one jsonl and the interleaved seq numbers make the loader
10
- * reject the session ("corrupt session log"). The lock sits NEXT to the
11
- * log (`<sessionDir>/writer.lock`), derived with the exact path encoding
12
- * upstream's jsonl backend uses, so every process about to create or
13
- * cold-resume competes on the same file.
14
- *
15
- * Claiming protocol (concurrency-critical):
16
- * - The payload is written FULLY to `<lock>.tmp-<pid>-<uniq>` first, then
17
- * claimed with `link(2)` — atomic at the kernel level, never writable
18
- * half-way, so no observer can read an empty/partial lock file.
19
- * - Two processes that both judge the same residue dead cannot both win:
20
- * they race ONE link(); the loser sees EEXIST and re-evaluates against
21
- * the WINNER's fresh live pid, then refuses. Stealing (renaming the dead
22
- * residue aside) is merely garbage collection of readable history — the
23
- * exclusive right is granted by link(), not by who cleared what.
24
- * - PID reuse can misreport a dead lock as alive; removing such a residual
25
- * stays an explicit manual act (delete the file), never automatic.
26
- */
27
- /** Who holds the lock, as recorded inside the file. */
28
- export interface WriterLockHolder {
29
- readonly pid: number;
30
- /** ISO timestamp written at creation time (informational). */
31
- readonly createdAt: string;
32
- /** Logical owner label (`'tui'` here; `'feishu'` in the mirror module). */
33
- readonly holder: string;
34
- }
35
- export type WriterLockAcquisition = {
36
- ok: true;
37
- } | {
38
- ok: false;
39
- holder: WriterLockHolder;
40
- };
41
- /** Thrown when a cold arm refused to open a second writer for a session. */
42
- export declare class WriterLockedError extends Error {
43
- readonly holder: WriterLockHolder;
44
- constructor(holder: WriterLockHolder);
45
- }
46
- export declare function writerLockPath(dir: string): string;
47
- /**
48
- * Project-directory name under which the jsonl backend groups a cwd's
49
- * sessions — byte-identical port of upstream `projectKey()` in
50
- * @deepseek-ai/dsh-session-persistence-jsonl (also mirrored by the feishu
51
- * plugin's guard). The derived session dir additionally relies on upstream's
52
- * `encodeSegment(sessionId)` being the IDENTITY for dsh ids — true while ids
53
- * are UUIDs (safe charset ⊇ UUID charset). If upstream ever introduces
54
- * non-UUID ids, port encodeSegment too or locks land beside decoy paths;
55
- * update only in lockstep with upstream either way.
56
- */
57
- export declare function projectKeyFor(cwd: string): string;
58
- /**
59
- * Acquire the single-writer lock for `dir`. Fresh creation or a cleared
60
- * residue establishes ownership (releasable later); a same-pid token is a
61
- * cooperative re-acquire — success WITHOUT rewriting the existing file and
62
- * without release rights. A lock held by another LIVE process refuses with
63
- * its holder info.
64
- */
65
- export declare function acquireWriterLock(dir: string): Promise<WriterLockAcquisition>;
66
- /**
67
- * Release the lock on `dir`, but ONLY when this process established it.
68
- * A cooperative/inherited token — or a dir we never touched — is untouched.
69
- */
70
- export declare function releaseOwnedWriterLock(dir: string): Promise<void>;
@@ -1,206 +0,0 @@
1
- /**
2
- * Single-writer guard — a vendored, zero-dependency per-session pid-file
3
- * lock, byte-for-byte the same contract the feishu plugin's guard uses so
4
- * both surfaces compete on one file.
5
- *
6
- * Why it exists: two dsh processes pointed at the same profile each keep
7
- * their own agent registry; `agents.get` cannot see the other process's
8
- * live agent. A cold resume there therefore forks the log: two agents
9
- * append to one jsonl and the interleaved seq numbers make the loader
10
- * reject the session ("corrupt session log"). The lock sits NEXT to the
11
- * log (`<sessionDir>/writer.lock`), derived with the exact path encoding
12
- * upstream's jsonl backend uses, so every process about to create or
13
- * cold-resume competes on the same file.
14
- *
15
- * Claiming protocol (concurrency-critical):
16
- * - The payload is written FULLY to `<lock>.tmp-<pid>-<uniq>` first, then
17
- * claimed with `link(2)` — atomic at the kernel level, never writable
18
- * half-way, so no observer can read an empty/partial lock file.
19
- * - Two processes that both judge the same residue dead cannot both win:
20
- * they race ONE link(); the loser sees EEXIST and re-evaluates against
21
- * the WINNER's fresh live pid, then refuses. Stealing (renaming the dead
22
- * residue aside) is merely garbage collection of readable history — the
23
- * exclusive right is granted by link(), not by who cleared what.
24
- * - PID reuse can misreport a dead lock as alive; removing such a residual
25
- * stays an explicit manual act (delete the file), never automatic.
26
- */
27
- import { link, mkdir, readFile, rename, unlink, writeFile } from 'node:fs/promises';
28
- import { randomBytes } from 'node:crypto';
29
- import { join, resolve } from 'node:path';
30
- /** Thrown when a cold arm refused to open a second writer for a session. */
31
- export class WriterLockedError extends Error {
32
- holder;
33
- constructor(holder) {
34
- super(`session is locked by a live process (pid ${holder.pid}`
35
- + `${holder.createdAt !== '' ? `, since ${holder.createdAt}` : ''})`
36
- + ' — refusing to fork the log');
37
- this.name = 'WriterLockedError';
38
- this.holder = holder;
39
- }
40
- }
41
- const LOCK_HOLDER = 'tui';
42
- /** Contention budget across residue-clearing rounds before giving up loudly. */
43
- const MAX_CLAIM_ROUNDS = 4;
44
- /**
45
- * Dirs where THIS process established (created or stole) the lock. Only an
46
- * establishing acquisition may release the file: a cooperative re-acquire
47
- * (same pid already recorded) inherits it without removal rights.
48
- */
49
- const established = new Set();
50
- export function writerLockPath(dir) {
51
- return join(dir, 'writer.lock');
52
- }
53
- /**
54
- * Project-directory name under which the jsonl backend groups a cwd's
55
- * sessions — byte-identical port of upstream `projectKey()` in
56
- * @deepseek-ai/dsh-session-persistence-jsonl (also mirrored by the feishu
57
- * plugin's guard). The derived session dir additionally relies on upstream's
58
- * `encodeSegment(sessionId)` being the IDENTITY for dsh ids — true while ids
59
- * are UUIDs (safe charset ⊇ UUID charset). If upstream ever introduces
60
- * non-UUID ids, port encodeSegment too or locks land beside decoy paths;
61
- * update only in lockstep with upstream either way.
62
- */
63
- export function projectKeyFor(cwd) {
64
- if (cwd.length === 0)
65
- throw new Error('cannot encode an empty project path');
66
- let readable = '';
67
- let separatorRun = false;
68
- for (let i = 0; i < cwd.length; i++) {
69
- const code = cwd.charCodeAt(i);
70
- const ch = String.fromCharCode(code);
71
- if (ch === '/' || ch === '\\' || ch === ':') {
72
- if (!separatorRun)
73
- readable += '-';
74
- separatorRun = true;
75
- }
76
- else if (ch !== '~' && /^[A-Za-z0-9._-]$/.test(ch)) {
77
- readable += ch;
78
- separatorRun = false;
79
- }
80
- else {
81
- readable += `~${code.toString(16).toUpperCase().padStart(4, '0')}`;
82
- separatorRun = false;
83
- }
84
- }
85
- return `--${(readable.replace(/^-+/, '') || 'root').slice(0, 251)}--`;
86
- }
87
- function processAlive(pid) {
88
- try {
89
- process.kill(pid, 0);
90
- return true;
91
- }
92
- catch (error) {
93
- // EPERM means the process exists but belongs to another user — alive.
94
- return error.code === 'EPERM';
95
- }
96
- }
97
- async function readHolder(path) {
98
- let raw;
99
- try {
100
- raw = await readFile(path, 'utf8');
101
- }
102
- catch {
103
- return undefined;
104
- }
105
- try {
106
- const parsed = JSON.parse(raw);
107
- if (!Number.isInteger(parsed.pid) || parsed.pid <= 0)
108
- return undefined;
109
- return {
110
- pid: parsed.pid,
111
- createdAt: typeof parsed.createdAt === 'string' ? parsed.createdAt : '',
112
- holder: typeof parsed.holder === 'string' ? parsed.holder : LOCK_HOLDER,
113
- };
114
- }
115
- catch {
116
- return undefined;
117
- }
118
- }
119
- /**
120
- * Fully write the payload to a private temp file, then CLAIM the lock name
121
- * with link() — atomic: exactly one contender wins; everyone else gets
122
- * EEXIST and re-reads whoever actually holds the name. Returns true iff WE
123
- * claimed it (and thus own its release).
124
- */
125
- async function claimFresh(path) {
126
- const tmp = `${path}.tmp-${process.pid}-${randomBytes(4).toString('hex')}`;
127
- await writeFile(tmp, JSON.stringify({
128
- pid: process.pid,
129
- createdAt: new Date().toISOString(),
130
- holder: LOCK_HOLDER,
131
- }));
132
- try {
133
- try {
134
- await link(tmp, path);
135
- return true;
136
- }
137
- catch (error) {
138
- if (error.code === 'EEXIST')
139
- return false;
140
- throw error;
141
- }
142
- }
143
- finally {
144
- await unlink(tmp).catch(() => { });
145
- }
146
- }
147
- async function clearResidue(path) {
148
- try {
149
- await rename(path, `${path}.stale-${Date.now()}-${randomBytes(3).toString('hex')}`);
150
- }
151
- catch (error) {
152
- // Another contender cleared (or replaced) it already — harmless; the
153
- // caller simply loops and re-reads the CURRENT state of the name.
154
- if (error.code !== 'ENOENT')
155
- throw error;
156
- }
157
- }
158
- /**
159
- * Acquire the single-writer lock for `dir`. Fresh creation or a cleared
160
- * residue establishes ownership (releasable later); a same-pid token is a
161
- * cooperative re-acquire — success WITHOUT rewriting the existing file and
162
- * without release rights. A lock held by another LIVE process refuses with
163
- * its holder info.
164
- */
165
- export async function acquireWriterLock(dir) {
166
- await mkdir(dir, { recursive: true });
167
- const path = writerLockPath(dir);
168
- for (let round = 0; round < MAX_CLAIM_ROUNDS; round++) {
169
- if (await claimFresh(path)) {
170
- established.add(resolve(dir));
171
- return { ok: true };
172
- }
173
- const holder = await readHolder(path);
174
- if (holder !== undefined && holder.pid === process.pid) {
175
- // Cooperative re-acquire: inherit, do not rewrite, never releasable.
176
- return { ok: true };
177
- }
178
- if (holder !== undefined && processAlive(holder.pid)) {
179
- return { ok: false, holder };
180
- }
181
- // Dead-or-corrupt-or-raced-away holder: collect the residue and re-try
182
- // the atomic claim; any live winner introduced meanwhile is re-read and
183
- // respected on the next round.
184
- await clearResidue(path);
185
- }
186
- fail(`writer.lock contention did not settle after ${MAX_CLAIM_ROUNDS} rounds: ${path}`);
187
- }
188
- function fail(message) {
189
- throw new Error(message);
190
- }
191
- /**
192
- * Release the lock on `dir`, but ONLY when this process established it.
193
- * A cooperative/inherited token — or a dir we never touched — is untouched.
194
- */
195
- export async function releaseOwnedWriterLock(dir) {
196
- const key = resolve(dir);
197
- if (!established.delete(key))
198
- return;
199
- try {
200
- await unlink(writerLockPath(dir));
201
- }
202
- catch {
203
- // Already gone (or raced away) — nothing left to clean.
204
- }
205
- }
206
- //# sourceMappingURL=writer-lock.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"writer-lock.js","sourceRoot":"","sources":["../src/writer-lock.ts"],"names":[],"mappings":"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"}