@deepseek-harness-tui/dsh-tui 0.8.2 → 0.8.4
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 +37 -12
- package/bin/dsh-tui.js +93 -18
- package/lib/types/commands.d.ts.map +1 -1
- package/lib/types/commands.js +1 -0
- package/lib/types/components/LogoV2.d.ts +4 -1
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +8 -3
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +1 -3
- package/lib/types/components/TipsPanel.d.ts +14 -0
- package/lib/types/components/TipsPanel.d.ts.map +1 -0
- package/lib/types/components/TipsPanel.js +37 -0
- package/lib/types/components/activityFrames.d.ts.map +1 -1
- package/lib/types/components/activityFrames.js +10 -0
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +8 -14
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +17 -0
- package/lib/types/effortPrefs.d.ts +7 -6
- package/lib/types/effortPrefs.d.ts.map +1 -1
- package/lib/types/effortPrefs.js +7 -6
- package/lib/types/i18n.d.ts +50 -14
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +21 -4
- package/lib/types/ink/ink.d.ts +1 -0
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +11 -0
- package/lib/types/ink/parse-keypress.d.ts.map +1 -1
- package/lib/types/ink/parse-keypress.js +15 -0
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +10 -3
- package/lib/types/screens/StatusLine.js +3 -3
- package/lib/types/tips.d.ts +30 -0
- package/lib/types/tips.d.ts.map +1 -0
- package/lib/types/tips.js +575 -0
- package/package.json +5 -3
- package/presets/liangshen/.dsh-tui-managed.json +1 -1
- package/presets/liangshen/agent.cordis.yml +7 -5
- package/presets/liangshen/custom-bash.mjs +184 -9
|
@@ -112,6 +112,23 @@ export async function apply(ctx, config) {
|
|
|
112
112
|
`可能是镜像 registry 未同步,请稍后重试或检查 registry 配置。\n`);
|
|
113
113
|
}
|
|
114
114
|
}
|
|
115
|
+
else if (process.stderr.isTTY) {
|
|
116
|
+
// Launcher alignment bridge (0.8.3): /update only replaces the
|
|
117
|
+
// package inside the DSH profile; a globally installed `dsh-tui`
|
|
118
|
+
// launcher is a separate copy that keeps its old version. Launchers
|
|
119
|
+
// >=0.8.3 export DSH_TUI_LAUNCHER_VERSION so we can tell whether
|
|
120
|
+
// the outer launcher lags the freshly installed profile. Launchers
|
|
121
|
+
// <=0.8.2 never set the marker — the generic branch below is
|
|
122
|
+
// intentionally one-shot: DSH_TUI_UPDATED_FROM exists only on the
|
|
123
|
+
// replacement process immediately after /update.
|
|
124
|
+
const launcherVersion = process.env.DSH_TUI_LAUNCHER_VERSION;
|
|
125
|
+
if (launcherVersion === undefined) {
|
|
126
|
+
process.stderr.write(`\n[dsh-tui] ${t('update-launcher-align-unknown', { version: now })}\n`);
|
|
127
|
+
}
|
|
128
|
+
else if (isVersionNewer(now, launcherVersion)) {
|
|
129
|
+
process.stderr.write(`\n[dsh-tui] ${t('update-launcher-outdated', { profile: now, launcher: launcherVersion })}\n`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
115
132
|
}
|
|
116
133
|
}
|
|
117
134
|
// DSH user-interaction seam: the model's ask_user_question tool parks on
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Persisted reasoning-effort preference (`~/.dsh-tui/effort.json`).
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
2
|
+
* Persisted reasoning-effort preference (`~/.dsh-tui/effort.json`). Set via
|
|
3
|
+
* `/effort` (slider or `/effort <id>`; `/effort status` reports the current
|
|
4
|
+
* level) — note Shift+Tab cycles session modes (default/plan/full), not
|
|
5
|
+
* effort levels. The choice lands here so the next boot starts on it. The
|
|
6
|
+
* file is best-effort: a missing/corrupt file or a level the current adapter
|
|
7
|
+
* does not offer just falls back to the provider default — the first
|
|
8
|
+
* request/header event always re-asserts the truth on the status line.
|
|
8
9
|
*/
|
|
9
10
|
/**
|
|
10
11
|
* The persisted reasoning-effort id, or undefined when unset or invalid.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effortPrefs.d.ts","sourceRoot":"","sources":["../../src/effortPrefs.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"effortPrefs.d.ts","sourceRoot":"","sources":["../../src/effortPrefs.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAkB,GAAG,MAAM,GAAG,SAAS,CAS1E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAkB,GAAG,OAAO,CAQhF"}
|
package/lib/types/effortPrefs.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Persisted reasoning-effort preference (`~/.dsh-tui/effort.json`).
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
2
|
+
* Persisted reasoning-effort preference (`~/.dsh-tui/effort.json`). Set via
|
|
3
|
+
* `/effort` (slider or `/effort <id>`; `/effort status` reports the current
|
|
4
|
+
* level) — note Shift+Tab cycles session modes (default/plan/full), not
|
|
5
|
+
* effort levels. The choice lands here so the next boot starts on it. The
|
|
6
|
+
* file is best-effort: a missing/corrupt file or a level the current adapter
|
|
7
|
+
* does not offer just falls back to the provider default — the first
|
|
8
|
+
* request/header event always re-asserts the truth on the status line.
|
|
8
9
|
*/
|
|
9
10
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
10
11
|
import { join } from 'node:path';
|
package/lib/types/i18n.d.ts
CHANGED
|
@@ -867,6 +867,14 @@ declare const dict: {
|
|
|
867
867
|
readonly zh: "再次按 Ctrl+C 退出";
|
|
868
868
|
readonly en: "Press Ctrl+C again to exit";
|
|
869
869
|
};
|
|
870
|
+
readonly 'esc-again-rewind': {
|
|
871
|
+
readonly zh: "再次按 Esc 时间回溯";
|
|
872
|
+
readonly en: "Press Esc again to rewind";
|
|
873
|
+
};
|
|
874
|
+
readonly 'esc-again-clear': {
|
|
875
|
+
readonly zh: "再次按 Esc 清空";
|
|
876
|
+
readonly en: "Press Esc again to clear";
|
|
877
|
+
};
|
|
870
878
|
readonly 'new-session-started': {
|
|
871
879
|
readonly zh: "已新建会话";
|
|
872
880
|
readonly en: "New session started";
|
|
@@ -907,6 +915,14 @@ declare const dict: {
|
|
|
907
915
|
readonly zh: "dsh-tui 更新中止:未解析到 dsh profile。";
|
|
908
916
|
readonly en: "dsh-tui update aborted: no dsh profile resolved.";
|
|
909
917
|
};
|
|
918
|
+
readonly 'update-launcher-align-unknown': {
|
|
919
|
+
readonly zh: "Profile 已更新到 v{{version}}。如果你平时使用全局 dsh-tui 命令启动,请同步更新全局启动器:\n npm install -g @deepseek-harness-tui/dsh-tui@{{version}}";
|
|
920
|
+
readonly en: "The profile is now v{{version}}. If you normally launch with the global dsh-tui command, align the global launcher too:\n npm install -g @deepseek-harness-tui/dsh-tui@{{version}}";
|
|
921
|
+
};
|
|
922
|
+
readonly 'update-launcher-outdated': {
|
|
923
|
+
readonly zh: "Profile 已更新到 v{{profile}},但全局启动器仍是 v{{launcher}}。请同步更新:\n npm install -g @deepseek-harness-tui/dsh-tui@{{profile}}";
|
|
924
|
+
readonly en: "The profile is now v{{profile}}, but the global launcher is still v{{launcher}}. Align it with:\n npm install -g @deepseek-harness-tui/dsh-tui@{{profile}}";
|
|
925
|
+
};
|
|
910
926
|
readonly 'activity-ctx-warn': {
|
|
911
927
|
readonly zh: "⚠ 上下文";
|
|
912
928
|
readonly en: "⚠ ctx ";
|
|
@@ -979,22 +995,14 @@ declare const dict: {
|
|
|
979
995
|
readonly zh: "探索未至之境!";
|
|
980
996
|
readonly en: "Explore the uncharted!";
|
|
981
997
|
};
|
|
982
|
-
readonly 'logo-tip-model': {
|
|
983
|
-
readonly zh: "切换模型";
|
|
984
|
-
readonly en: "switch model";
|
|
985
|
-
};
|
|
986
|
-
readonly 'logo-tip-help': {
|
|
987
|
-
readonly zh: "查看命令";
|
|
988
|
-
readonly en: "view commands";
|
|
989
|
-
};
|
|
990
|
-
readonly 'logo-tip-tab': {
|
|
991
|
-
readonly zh: "自动补全";
|
|
992
|
-
readonly en: "autocomplete";
|
|
993
|
-
};
|
|
994
998
|
readonly 'logo-tip-prefix': {
|
|
995
999
|
readonly zh: "提示:";
|
|
996
1000
|
readonly en: "Tip: ";
|
|
997
1001
|
};
|
|
1002
|
+
readonly 'logo-tip-more': {
|
|
1003
|
+
readonly zh: "更多技巧";
|
|
1004
|
+
readonly en: "more tips";
|
|
1005
|
+
};
|
|
998
1006
|
readonly 'input-sent-after-turn': {
|
|
999
1007
|
readonly zh: "已发送,当前回合结束后处理";
|
|
1000
1008
|
readonly en: "Sent, processed after the current turn";
|
|
@@ -1179,6 +1187,14 @@ declare const dict: {
|
|
|
1179
1187
|
readonly zh: "命令:";
|
|
1180
1188
|
readonly en: "commands:";
|
|
1181
1189
|
};
|
|
1190
|
+
readonly 'tips-title': {
|
|
1191
|
+
readonly zh: "使用技巧(快捷键 · 命令 · 工作流 · 个性化 · 避坑)";
|
|
1192
|
+
readonly en: "Usage tips (shortcuts · commands · workflow · display · gotchas)";
|
|
1193
|
+
};
|
|
1194
|
+
readonly 'tips-hint': {
|
|
1195
|
+
readonly zh: "↑/↓ 滚动 · Esc 关闭";
|
|
1196
|
+
readonly en: "↑/↓ scroll · Esc to close";
|
|
1197
|
+
};
|
|
1182
1198
|
readonly 'interrupted-by-user': {
|
|
1183
1199
|
readonly zh: "已打断 ";
|
|
1184
1200
|
readonly en: "Interrupted ";
|
|
@@ -1247,6 +1263,10 @@ declare const dict: {
|
|
|
1247
1263
|
readonly zh: "没有可配置的插件设置(尚无插件注册设置区块)";
|
|
1248
1264
|
readonly en: "No configurable plugin settings (no plugin has registered a section)";
|
|
1249
1265
|
};
|
|
1266
|
+
readonly 'settings-group-empty': {
|
|
1267
|
+
readonly zh: "此分组没有可配置字段";
|
|
1268
|
+
readonly en: "No configurable fields in this group";
|
|
1269
|
+
};
|
|
1250
1270
|
readonly 'settings-section-unavailable': {
|
|
1251
1271
|
readonly zh: "命名空间未注册";
|
|
1252
1272
|
readonly en: "namespace not served";
|
|
@@ -1312,8 +1332,12 @@ declare const dict: {
|
|
|
1312
1332
|
readonly en: "Discarded all unsaved edits";
|
|
1313
1333
|
};
|
|
1314
1334
|
readonly 'settings-hint-list': {
|
|
1315
|
-
readonly zh: "**Enter**
|
|
1316
|
-
readonly en: "**Enter** edit/toggle · s save · d discard · Esc discard/exit";
|
|
1335
|
+
readonly zh: "**Enter** 进入/编辑/切换 · s 保存 · d 放弃 · Esc 放弃/退出";
|
|
1336
|
+
readonly en: "**Enter** open/edit/toggle · s save · d discard · Esc discard/exit";
|
|
1337
|
+
};
|
|
1338
|
+
readonly 'settings-hint-group': {
|
|
1339
|
+
readonly zh: "**Enter** 编辑/切换 · s 保存 · d 放弃 · Esc 返回";
|
|
1340
|
+
readonly en: "**Enter** edit/toggle · s save · d discard · Esc back";
|
|
1317
1341
|
};
|
|
1318
1342
|
readonly 'settings-hint-edit': {
|
|
1319
1343
|
readonly zh: "**Enter** 确认 · Esc 取消";
|
|
@@ -1451,6 +1475,18 @@ declare const dict: {
|
|
|
1451
1475
|
readonly zh: "**Enter** 回退 · Esc 返回";
|
|
1452
1476
|
readonly en: "**Enter** to rewind · Esc to back";
|
|
1453
1477
|
};
|
|
1478
|
+
readonly 'statusline-hint-select': {
|
|
1479
|
+
readonly zh: "esc 返回输入";
|
|
1480
|
+
readonly en: "esc to return to input";
|
|
1481
|
+
};
|
|
1482
|
+
readonly 'statusline-hint-working': {
|
|
1483
|
+
readonly zh: "esc 中断";
|
|
1484
|
+
readonly en: "esc to interrupt";
|
|
1485
|
+
};
|
|
1486
|
+
readonly 'statusline-hint-shortcuts': {
|
|
1487
|
+
readonly zh: "? 查看快捷键";
|
|
1488
|
+
readonly en: "? for shortcuts";
|
|
1489
|
+
};
|
|
1454
1490
|
readonly 'hint-ext-dialog-input': {
|
|
1455
1491
|
readonly zh: "**Enter** 确认 · Esc 取消";
|
|
1456
1492
|
readonly en: "**Enter** to confirm · Esc to cancel";
|
package/lib/types/i18n.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAI9B,+DAA+D;AAC/D,eAAO,MAAM,KAAK,uBAAwB,CAAA;AAE1C,QAAA,MAAM,IAAI
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/i18n.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;AAI9B,+DAA+D;AAC/D,eAAO,MAAM,KAAK,uBAAwB,CAAA;AAE1C,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsuBA,CAAA;AAEV,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,IAAI,CAAA;AACvC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAA;AAUxD,uEAAuE;AACvE,KAAK,QAAQ,GAAG,MAAM,IAAI,CAAA;AAG1B,8EAA8E;AAC9E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,IAAI,CAG5D;AAED,qCAAqC;AACrC,wBAAgB,OAAO,IAAI,IAAI,CAE9B;AAED,yDAAyD;AACzD,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAGxC;AAED,iDAAiD;AACjD,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,UAAe,GAAG,MAAM,CAM/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGzD;AAID;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAS5D;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAkB,GAAG,IAAI,GAAG,SAAS,CAMtE;AAED,iDAAiD;AACjD,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,GAAE,MAAkB,GAAG,OAAO,CAQ1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAavC;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAIzC"}
|
package/lib/types/i18n.js
CHANGED
|
@@ -239,6 +239,8 @@ const dict = {
|
|
|
239
239
|
'btw-hint-done': { zh: '↑/↓ 滚动 · Space/Enter/Esc 关闭 · c 复制', en: '↑/↓ scroll · Space/Enter/Esc dismiss · c copy' },
|
|
240
240
|
'btw-llm-unavailable': { zh: '侧问不可用(llm 服务未挂载)', en: 'Side question unavailable (llm service not mounted)' },
|
|
241
241
|
'exit-press-again': { zh: '再次按 Ctrl+C 退出', en: 'Press Ctrl+C again to exit' },
|
|
242
|
+
'esc-again-rewind': { zh: '再次按 Esc 时间回溯', en: 'Press Esc again to rewind' },
|
|
243
|
+
'esc-again-clear': { zh: '再次按 Esc 清空', en: 'Press Esc again to clear' },
|
|
242
244
|
'new-session-started': { zh: '已新建会话', en: 'New session started' },
|
|
243
245
|
'command-not-found': { zh: '/{{name}}:没有这个命令', en: '/{{name}}: no such command' },
|
|
244
246
|
'thinking-toggled': { zh: '思考模式:{{state}}', en: 'Thinking {{state}}' },
|
|
@@ -251,6 +253,16 @@ const dict = {
|
|
|
251
253
|
'legacy-env-renamed': { zh: '环境变量 {{old}} 已更名为 {{new}},旧名不再生效', en: 'Environment variable {{old}} was renamed to {{new}}; the old name no longer takes effect' },
|
|
252
254
|
// ── plugin.ts — /update flow ───────────────────────────────────────
|
|
253
255
|
'update-aborted-no-profile': { zh: 'dsh-tui 更新中止:未解析到 dsh profile。', en: 'dsh-tui update aborted: no dsh profile resolved.' },
|
|
256
|
+
// 0.8.3 launcher alignment bridge: /update only replaces the profile
|
|
257
|
+
// copy; the global `dsh-tui` launcher must be aligned separately.
|
|
258
|
+
'update-launcher-align-unknown': {
|
|
259
|
+
zh: 'Profile 已更新到 v{{version}}。如果你平时使用全局 dsh-tui 命令启动,请同步更新全局启动器:\n npm install -g @deepseek-harness-tui/dsh-tui@{{version}}',
|
|
260
|
+
en: 'The profile is now v{{version}}. If you normally launch with the global dsh-tui command, align the global launcher too:\n npm install -g @deepseek-harness-tui/dsh-tui@{{version}}',
|
|
261
|
+
},
|
|
262
|
+
'update-launcher-outdated': {
|
|
263
|
+
zh: 'Profile 已更新到 v{{profile}},但全局启动器仍是 v{{launcher}}。请同步更新:\n npm install -g @deepseek-harness-tui/dsh-tui@{{profile}}',
|
|
264
|
+
en: 'The profile is now v{{profile}}, but the global launcher is still v{{launcher}}. Align it with:\n npm install -g @deepseek-harness-tui/dsh-tui@{{profile}}',
|
|
265
|
+
},
|
|
254
266
|
// ── components/ActivityLine.tsx ──────────────────────────────────────
|
|
255
267
|
'activity-ctx-warn': { zh: '⚠ 上下文', en: '⚠ ctx ' },
|
|
256
268
|
// ── components/ActivityPicker.tsx ─────────────────────────────────────
|
|
@@ -275,10 +287,8 @@ const dict = {
|
|
|
275
287
|
'mode-plan-unavailable': { zh: '当前 preset 未注册 /plan 命令,无法切换计划模式', en: 'The active preset does not register /plan; cannot toggle plan mode' },
|
|
276
288
|
// ── components/LogoV2.tsx ───────────────────────────────────────────
|
|
277
289
|
'logo-tagline': { zh: '探索未至之境!', en: 'Explore the uncharted!' },
|
|
278
|
-
'logo-tip-model': { zh: '切换模型', en: 'switch model' },
|
|
279
|
-
'logo-tip-help': { zh: '查看命令', en: 'view commands' },
|
|
280
|
-
'logo-tip-tab': { zh: '自动补全', en: 'autocomplete' },
|
|
281
290
|
'logo-tip-prefix': { zh: '提示:', en: 'Tip: ' },
|
|
291
|
+
'logo-tip-more': { zh: '更多技巧', en: 'more tips' },
|
|
282
292
|
// ── components/PromptInput.tsx ──────────────────────────────────────
|
|
283
293
|
'input-sent-after-turn': { zh: '已发送,当前回合结束后处理', en: 'Sent, processed after the current turn' },
|
|
284
294
|
'input-interrupted-next': { zh: '已插话 · 下一步立即处理', en: 'Interrupted · processed next' },
|
|
@@ -328,6 +338,8 @@ const dict = {
|
|
|
328
338
|
'help-cycle-mode': { zh: 'shift+tab 切换模式', en: 'shift+tab to cycle mode' },
|
|
329
339
|
'help-open-editor': { zh: 'ctrl+x 打开编辑器', en: 'ctrl+x to open editor' },
|
|
330
340
|
'help-commands-title': { zh: '命令:', en: 'commands:' },
|
|
341
|
+
'tips-title': { zh: '使用技巧(快捷键 · 命令 · 工作流 · 个性化 · 避坑)', en: 'Usage tips (shortcuts · commands · workflow · display · gotchas)' },
|
|
342
|
+
'tips-hint': { zh: '↑/↓ 滚动 · Esc 关闭', en: '↑/↓ scroll · Esc to close' },
|
|
331
343
|
// ── components/InterruptedByUser.tsx ────────────────────────────────
|
|
332
344
|
'interrupted-by-user': { zh: '已打断 ', en: 'Interrupted ' },
|
|
333
345
|
'interrupted-ask-next': { zh: '· 接下来想让 DeepSeek 做什么?', en: '· What should DeepSeek do instead?' },
|
|
@@ -349,6 +361,7 @@ const dict = {
|
|
|
349
361
|
'settings-title': { zh: '插件设置', en: 'Plugin settings' },
|
|
350
362
|
'settings-unavailable': { zh: '设置服务未挂载——只读', en: 'settings service absent — read-only' },
|
|
351
363
|
'settings-empty': { zh: '没有可配置的插件设置(尚无插件注册设置区块)', en: 'No configurable plugin settings (no plugin has registered a section)' },
|
|
364
|
+
'settings-group-empty': { zh: '此分组没有可配置字段', en: 'No configurable fields in this group' },
|
|
352
365
|
'settings-section-unavailable': { zh: '命名空间未注册', en: 'namespace not served' },
|
|
353
366
|
'settings-readonly-heading': { zh: '其他设置命名空间(只读)', en: 'Other settings namespaces (read-only)' },
|
|
354
367
|
'settings-readonly-hint': { zh: '以上命名空间尚无 TUI 设置区块,可手工编辑 {{path}}', en: 'No TUI section for these namespaces yet — edit {{path}} by hand' },
|
|
@@ -365,7 +378,8 @@ const dict = {
|
|
|
365
378
|
'settings-saved': { zh: '已保存 {{ns}}', en: 'Saved {{ns}}' },
|
|
366
379
|
'settings-save-failed': { zh: '保存 {{ns}} 失败——请重试', en: 'Saving {{ns}} failed — please retry' },
|
|
367
380
|
'settings-discarded': { zh: '已放弃所有未保存的修改', en: 'Discarded all unsaved edits' },
|
|
368
|
-
'settings-hint-list': { zh: '**Enter**
|
|
381
|
+
'settings-hint-list': { zh: '**Enter** 进入/编辑/切换 · s 保存 · d 放弃 · Esc 放弃/退出', en: '**Enter** open/edit/toggle · s save · d discard · Esc discard/exit' },
|
|
382
|
+
'settings-hint-group': { zh: '**Enter** 编辑/切换 · s 保存 · d 放弃 · Esc 返回', en: '**Enter** edit/toggle · s save · d discard · Esc back' },
|
|
369
383
|
'settings-hint-edit': { zh: '**Enter** 确认 · Esc 取消', en: '**Enter** to confirm · Esc to cancel' },
|
|
370
384
|
// ── 会话浏览器:行、计数、筛选、预览 ───────────────────────────────
|
|
371
385
|
'session-loading': { zh: '正在读取会话…', en: 'Reading sessions…' },
|
|
@@ -405,6 +419,9 @@ const dict = {
|
|
|
405
419
|
'hint-select-exit': { zh: '**Enter** 选择 · Esc 退出', en: '**Enter** to select · Esc to exit' },
|
|
406
420
|
'hint-fill-exit': { zh: '**Enter** 填入命令 · Esc 退出', en: '**Enter** to insert · Esc to exit' },
|
|
407
421
|
'hint-rewind-back': { zh: '**Enter** 回退 · Esc 返回', en: '**Enter** to rewind · Esc to back' },
|
|
422
|
+
'statusline-hint-select': { zh: 'esc 返回输入', en: 'esc to return to input' },
|
|
423
|
+
'statusline-hint-working': { zh: 'esc 中断', en: 'esc to interrupt' },
|
|
424
|
+
'statusline-hint-shortcuts': { zh: '? 查看快捷键', en: '? for shortcuts' },
|
|
408
425
|
'hint-ext-dialog-input': { zh: '**Enter** 确认 · Esc 取消', en: '**Enter** to confirm · Esc to cancel' },
|
|
409
426
|
'hint-adjust-done': { zh: '**←/→** 调整 · Enter/Esc 完成', en: '**←/→** to adjust · Enter/Esc to done' },
|
|
410
427
|
'hint-history-search': { zh: '↑/↓ 选择 · **Enter** 确认 · Esc 取消', en: '↑/↓ to navigate · **Enter** to select · Esc to cancel' },
|
package/lib/types/ink/ink.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ink.d.ts","sourceRoot":"","sources":["../../../src/ink/ink.tsx"],"names":[],"mappings":"AAIA,OAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAa9C,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAEhC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAA0B,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAQrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGrD,OAAO,EAA4B,KAAK,aAAa,EAAiB,MAAM,uBAAuB,CAAC;AAIpG,OAAO,EAAqG,KAAK,SAAS,EAAgE,KAAK,cAAc,EAAqH,MAAM,gBAAgB,CAAC;AAgCzV,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC,CAAC;AACF,MAAM,CAAC,OAAO,OAAO,GAAG;
|
|
1
|
+
{"version":3,"file":"ink.d.ts","sourceRoot":"","sources":["../../../src/ink/ink.tsx"],"names":[],"mappings":"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"}
|
package/lib/types/ink/ink.js
CHANGED
|
@@ -153,9 +153,20 @@ export default class Ink {
|
|
|
153
153
|
// for log-update's relative-move invariants). Alt-screen doesn't need
|
|
154
154
|
// this — every frame begins with CSI H. null = no move emitted last frame.
|
|
155
155
|
displayCursor = null;
|
|
156
|
+
handleStdinError(error) {
|
|
157
|
+
if (this.isUnmounted && error.code === 'EIO') {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
156
162
|
constructor(options) {
|
|
157
163
|
this.options = options;
|
|
158
164
|
autoBind(this);
|
|
165
|
+
if (options.stdin.isTTY) {
|
|
166
|
+
// Keep this listener through teardown: a pending libuv TTY read can
|
|
167
|
+
// report EIO only after raw mode and React have already been released.
|
|
168
|
+
options.stdin.on('error', this.handleStdinError);
|
|
169
|
+
}
|
|
159
170
|
if (this.options.patchConsole) {
|
|
160
171
|
this.restoreConsole = this.patchConsole();
|
|
161
172
|
this.restoreStderr = this.patchStderr();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-keypress.d.ts","sourceRoot":"","sources":["../../../src/ink/parse-keypress.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"parse-keypress.d.ts","sourceRoot":"","sources":["../../../src/ink/parse-keypress.ts"],"names":[],"mappings":"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"}
|
|
@@ -42,6 +42,8 @@ const MODIFY_OTHER_KEYS_RE = /^\x1b\[27;(\d+);(\d+)~/;
|
|
|
42
42
|
// win32 instead of kitty/modifyOtherKeys.
|
|
43
43
|
// eslint-disable-next-line no-control-regex
|
|
44
44
|
const WIN32_INPUT_RE = /^\x1b\[([\d;]*)_$/;
|
|
45
|
+
const WIN32_INPUT_TAIL_RE = /\[\d*;\d*;\d*;[01](?:;\d*){0,2}_/g;
|
|
46
|
+
const WIN32_INPUT_TAILS_RE = /^(?:\[\d*;\d*;\d*;[01](?:;\d*){0,2}_)+$/;
|
|
45
47
|
// dwControlKeyState modifier bits (others — NUMLOCK_ON 0x20, CAPSLOCK_ON
|
|
46
48
|
// 0x80, ENHANCED_KEY 0x100 — are state indicators, not pressed modifiers)
|
|
47
49
|
const WIN32_CS_ALT = 0x01 | 0x02;
|
|
@@ -623,6 +625,19 @@ export function parseMultipleKeypresses(prevState, input = '') {
|
|
|
623
625
|
if (inPaste) {
|
|
624
626
|
pasteBuffer += token.value;
|
|
625
627
|
}
|
|
628
|
+
else if (WIN32_INPUT_TAILS_RE.test(token.value)) {
|
|
629
|
+
// A delayed win32-input-mode continuation can arrive after App's
|
|
630
|
+
// escape timer has already flushed its ESC prefix. Recover complete
|
|
631
|
+
// record tails so their protocol bytes do not leak into the prompt.
|
|
632
|
+
for (const tail of token.value.match(WIN32_INPUT_TAIL_RE) ?? []) {
|
|
633
|
+
const win32 = parseWin32KeyEvent('\x1b' + tail, win32Ctx);
|
|
634
|
+
if (win32 !== undefined && win32 !== null) {
|
|
635
|
+
for (let i = 0; i < win32.repeat; i++) {
|
|
636
|
+
keys.push(...feedWin32Paste(win32Paste, win32.key));
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
626
641
|
else if (/^\[<\d+;\d+;\d+[Mm]$/.test(token.value) ||
|
|
627
642
|
/^\[M[\x60-\x7f][\x20-\uffff]{2}$/.test(token.value)) {
|
|
628
643
|
// Orphaned SGR/X10 mouse tail (fullscreen only — mouse tracking is off
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/screens/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,EAAqB,KAAK,OAAO,EAAsE,MAAM,2BAA2B,CAAA;AAC/I,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"Chat.d.ts","sourceRoot":"","sources":["../../../src/screens/Chat.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AASzB,OAAO,EAAqB,KAAK,OAAO,EAAsE,MAAM,2BAA2B,CAAA;AAC/I,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAyI3D,wBAAgB,IAAI,CAAC,EACnB,OAAO,EACP,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,MAAM,EACN,QAAQ,EACR,UAAkB,EAClB,cAAc,EAAE,kBAAkB,GACnC,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,aAAa,EAAE,aAAa,CAAA;IAC5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAA;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAA;IACjC,oEAAoE;IACpE,eAAe,CAAC,EAAE,cAAc,CAAA;IAChC,iDAAiD;IACjD,kBAAkB,CAAC,EAAE,eAAe,CAAA;IACpC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IACrB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,qBAkmEA"}
|
|
@@ -46,6 +46,7 @@ import { ThinkingToggle } from '../components/ThinkingToggle.js';
|
|
|
46
46
|
import { HistorySearchDialog } from '../components/HistorySearchDialog.js';
|
|
47
47
|
import { RewindPicker } from '../components/RewindPicker.js';
|
|
48
48
|
import { BtwPanel } from '../components/BtwPanel.js';
|
|
49
|
+
import { TipsPanel } from '../components/TipsPanel.js';
|
|
49
50
|
import { setClipboard } from '../ink/termio/osc.js';
|
|
50
51
|
import instances from '../ink/instances.js';
|
|
51
52
|
import { useAnimationFrame } from '../ink/hooks/use-animation-frame.js';
|
|
@@ -262,6 +263,8 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
262
263
|
btwAbortRef.current = null;
|
|
263
264
|
setBtw(null);
|
|
264
265
|
};
|
|
266
|
+
/** /tips usage-tips overlay: pure UI state, no session side effects. */
|
|
267
|
+
const [tipsOpen, setTipsOpen] = React.useState(false);
|
|
265
268
|
React.useEffect(() => () => btwAbortRef.current?.abort(), []);
|
|
266
269
|
/**
|
|
267
270
|
* The trajectory scene (issue #80 evolution). Unlike every other overlay
|
|
@@ -1030,6 +1033,10 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
1030
1033
|
});
|
|
1031
1034
|
return true;
|
|
1032
1035
|
}
|
|
1036
|
+
case 'tips':
|
|
1037
|
+
setHelpOpen(false);
|
|
1038
|
+
setTipsOpen(true);
|
|
1039
|
+
return true;
|
|
1033
1040
|
case 'connect':
|
|
1034
1041
|
setHelpOpen(false);
|
|
1035
1042
|
channel.pushLocal('/connect', [t('connect-none')]);
|
|
@@ -1977,7 +1984,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
1977
1984
|
/** Prompt input is inert while a modal dialog owns the keyboard. */
|
|
1978
1985
|
const promptSelectionActive = selectionActive || modelPickerOpen || skillsPickerOpen || workspacePickerOpen || workspaceFlow !== null || activityPickerOpen ||
|
|
1979
1986
|
effortSliderOpen || presetPickerOpen || themePickerOpen || thinkingOpen || historyOpen || rewindOpen || searchOpen ||
|
|
1980
|
-
btw !== null;
|
|
1987
|
+
btw !== null || tipsOpen;
|
|
1981
1988
|
// The trajectory scene replaces the conversation for as long as it is open.
|
|
1982
1989
|
// Rendering it INSTEAD of (not above) the transcript is what makes it a
|
|
1983
1990
|
// screen rather than an overlay: it owns the full viewport, and the
|
|
@@ -1999,7 +2006,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
1999
2006
|
modelPickerOpen || skillsPickerOpen ||
|
|
2000
2007
|
activityPickerOpen || (effortSliderOpen && effortOptions.length > 1) ||
|
|
2001
2008
|
(presetPickerOpen && presetOptions.length > 0) || themePickerOpen || historyOpen ||
|
|
2002
|
-
rewindOpen || searchOpen;
|
|
2009
|
+
rewindOpen || searchOpen || tipsOpen;
|
|
2003
2010
|
return (_jsxs(Box, { ref: wakeTickRef, flexDirection: "column", flexGrow: 1, width: "100%", children: [!isSticky && channel.lastUserText && (_jsx(StickyPromptHeader, { text: channel.lastUserText, onClick: () => {
|
|
2004
2011
|
// Click jumps back to the pinned prompt (CC's StickyPromptHeader).
|
|
2005
2012
|
const lastUser = [...channel.rows].reverse().find(row => row.kind === 'user');
|
|
@@ -2016,7 +2023,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
|
|
|
2016
2023
|
// the animated chars/4 estimate, matching the classic
|
|
2017
2024
|
// spinner's counter (the suffix used raw chars before,
|
|
2018
2025
|
// inflating the reading next to a real upload number).
|
|
2019
|
-
suffix: `${lastUploadTokens > 0 ? ` · ↑ ${formatTokens(lastUploadTokens)}` : ''} · ↓ ${formatTokens(Math.round(channel.responseChars / 4))} tokens` }) })) : (_jsx(WorkingSpinner, { mode: channel.spinnerMode, hasActiveTools: channel.activeToolCount > 0, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, thinkingStatus: thinkingStatus }))), _jsx(GoalTodoPanel, { channel: channel }), statusEntries.length > 0 && (_jsx(Text, { dimColor: true, wrap: "truncate", children: statusEntries.map(entry => entry.text).join(' · ') })), approvalSnapshot !== null ? (_jsx(ApprovalPanel, { approval: approvalSnapshot, onDecide: outcome => approvals.decide(outcome) }, approvalSnapshot.key)) : dialogSnapshot !== null ? (_jsx(ExtensionDialog, { dialog: dialogSnapshot, onDecide: value => dialogs.decide(dialogSnapshot.key, value), onCancel: () => dialogs.cancel(dialogSnapshot.key) }, dialogSnapshot.key)) : btw !== null ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(BtwPanel, { question: btw.question, answer: btw.answer, error: btw.error, streaming: !btw.done, onClose: closeBtw, onCopy: () => {
|
|
2026
|
+
suffix: `${lastUploadTokens > 0 ? ` · ↑ ${formatTokens(lastUploadTokens)}` : ''} · ↓ ${formatTokens(Math.round(channel.responseChars / 4))} tokens` }) })) : (_jsx(WorkingSpinner, { mode: channel.spinnerMode, hasActiveTools: channel.activeToolCount > 0, responseLengthRef: responseLengthRef, uploadTokensRef: uploadTokensRef, loadingStartTimeRef: loadingStartTimeRef, totalPausedMsRef: totalPausedMsRef, pauseStartTimeRef: pauseStartTimeRef, thinkingStatus: thinkingStatus }))), _jsx(GoalTodoPanel, { channel: channel }), statusEntries.length > 0 && (_jsx(Text, { dimColor: true, wrap: "truncate", children: statusEntries.map(entry => entry.text).join(' · ') })), approvalSnapshot !== null ? (_jsx(ApprovalPanel, { approval: approvalSnapshot, onDecide: outcome => approvals.decide(outcome) }, approvalSnapshot.key)) : dialogSnapshot !== null ? (_jsx(ExtensionDialog, { dialog: dialogSnapshot, onDecide: value => dialogs.decide(dialogSnapshot.key, value), onCancel: () => dialogs.cancel(dialogSnapshot.key) }, dialogSnapshot.key)) : tipsOpen ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(TipsPanel, { onClose: () => setTipsOpen(false) }) })) : btw !== null ? (_jsx(Box, { flexDirection: "column", marginTop: 1, children: _jsx(BtwPanel, { question: btw.question, answer: btw.answer, error: btw.error, streaming: !btw.done, onClose: closeBtw, onCopy: () => {
|
|
2020
2027
|
void setClipboard(btw.answer ?? '').then(raw => { if (raw)
|
|
2021
2028
|
process.stdout.write(raw); });
|
|
2022
2029
|
channel.notify(t('copied-chars', { n: (btw.answer ?? '').length }), { timeoutMs: 1500 });
|
|
@@ -82,11 +82,11 @@ export function StatusLine({ channel, selectionActive = false, helpOpen = false,
|
|
|
82
82
|
// summary (the live working line itself moves to the spinner slot above
|
|
83
83
|
// the input while a turn runs, so the two never duplicate).
|
|
84
84
|
const hint = selectionActive
|
|
85
|
-
? '
|
|
85
|
+
? t('statusline-hint-select')
|
|
86
86
|
: channel.working
|
|
87
|
-
? '
|
|
87
|
+
? t('statusline-hint-working')
|
|
88
88
|
: !helpOpen
|
|
89
|
-
? '
|
|
89
|
+
? t('statusline-hint-shortcuts')
|
|
90
90
|
: '';
|
|
91
91
|
const activity = channel.workingActivity;
|
|
92
92
|
const showActivity = !channel.working &&
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 精简 Tips 池 —— 启动首屏轮换(LogoV2)与 `/tips` 命令面板共用。
|
|
3
|
+
*
|
|
4
|
+
* 设计约定:
|
|
5
|
+
* - 每条 tip 一句话,中文 ≤ 约 60 字符、英文 ≤ 约 100 字符,首屏单行可读
|
|
6
|
+
* (窄终端自动截断);
|
|
7
|
+
* - 文案只讲"用户能立刻用上"的操作,不讲实现细节;
|
|
8
|
+
* - id 稳定(面板按 id 去重/排序),group 用于 `/tips` 面板分组展示;
|
|
9
|
+
* - 与 docs/user-guide.md 同源:文档是详版,这里是精版,覆盖全部功能面。
|
|
10
|
+
*/
|
|
11
|
+
export type TipGroup = 'keys' | 'commands' | 'workflow' | 'display' | 'pitfalls';
|
|
12
|
+
export interface Tip {
|
|
13
|
+
id: string;
|
|
14
|
+
group: TipGroup;
|
|
15
|
+
zh: string;
|
|
16
|
+
en: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const TIP_GROUP_LABELS: Record<TipGroup, {
|
|
19
|
+
zh: string;
|
|
20
|
+
en: string;
|
|
21
|
+
}>;
|
|
22
|
+
export declare const TIPS: readonly Tip[];
|
|
23
|
+
/**
|
|
24
|
+
* 启动随机轮换选择:每次启动随机取一条,让首屏每次都有新鲜感。
|
|
25
|
+
* random 可注入以便测试固定(默认 Math.random)。
|
|
26
|
+
*/
|
|
27
|
+
export declare function pickRandomTip(random?: () => number): Tip;
|
|
28
|
+
/** 按分组取 tips(/tips 面板展示用,保持 TIPS 内顺序)。 */
|
|
29
|
+
export declare function tipsByGroup(group: TipGroup): Tip[];
|
|
30
|
+
//# sourceMappingURL=tips.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tips.d.ts","sourceRoot":"","sources":["../../src/tips.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;AAEhF,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,QAAQ,CAAA;IACf,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAMzE,CAAA;AAED,eAAO,MAAM,IAAI,EAAE,SAAS,GAAG,EAsiB9B,CAAA;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,MAAM,MAAoB,GAAG,GAAG,CAErE;AAED,0CAA0C;AAC1C,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,GAAG,EAAE,CAElD"}
|