@deepseek-harness-tui/dsh-tui 0.8.4 → 0.8.6

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 (80) hide show
  1. package/lib/types/activityPrefs.d.ts +10 -0
  2. package/lib/types/activityPrefs.d.ts.map +1 -1
  3. package/lib/types/activityPrefs.js +17 -0
  4. package/lib/types/cc/figures.d.ts +7 -0
  5. package/lib/types/cc/figures.d.ts.map +1 -1
  6. package/lib/types/cc/figures.js +23 -0
  7. package/lib/types/cc/markdown.d.ts.map +1 -1
  8. package/lib/types/cc/markdown.js +47 -14
  9. package/lib/types/cc/syntaxTheme.d.ts +12 -0
  10. package/lib/types/cc/syntaxTheme.d.ts.map +1 -0
  11. package/lib/types/cc/syntaxTheme.js +76 -0
  12. package/lib/types/components/EffortChargeGlyph.d.ts +26 -0
  13. package/lib/types/components/EffortChargeGlyph.d.ts.map +1 -0
  14. package/lib/types/components/EffortChargeGlyph.js +70 -0
  15. package/lib/types/components/EffortInputBorder.d.ts +36 -0
  16. package/lib/types/components/EffortInputBorder.d.ts.map +1 -0
  17. package/lib/types/components/EffortInputBorder.js +73 -0
  18. package/lib/types/components/EffortTierBadge.d.ts +26 -0
  19. package/lib/types/components/EffortTierBadge.d.ts.map +1 -0
  20. package/lib/types/components/EffortTierBadge.js +97 -0
  21. package/lib/types/components/LoadedContextPanel.js +1 -1
  22. package/lib/types/components/MessageList.d.ts +4 -1
  23. package/lib/types/components/MessageList.d.ts.map +1 -1
  24. package/lib/types/components/MessageList.js +9 -11
  25. package/lib/types/components/PromptInput.d.ts.map +1 -1
  26. package/lib/types/components/PromptInput.js +8 -3
  27. package/lib/types/components/SplitDiffView.d.ts +4 -5
  28. package/lib/types/components/SplitDiffView.d.ts.map +1 -1
  29. package/lib/types/components/SplitDiffView.js +18 -65
  30. package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
  31. package/lib/types/components/StreamingMarkdown.js +10 -2
  32. package/lib/types/components/activityFrames.d.ts +7 -28
  33. package/lib/types/components/activityFrames.d.ts.map +1 -1
  34. package/lib/types/components/activityFrames.js +7 -94
  35. package/lib/types/components/design-system/ThemedBox.d.ts.map +1 -1
  36. package/lib/types/components/design-system/ThemedBox.js +4 -1
  37. package/lib/types/components/design-system/ThemedText.js +2 -2
  38. package/lib/types/components/messages/AssistantThinkingMessage.d.ts +12 -6
  39. package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
  40. package/lib/types/components/messages/AssistantThinkingMessage.js +25 -9
  41. package/lib/types/components/messages/AssistantToolUseMessage.d.ts +4 -1
  42. package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
  43. package/lib/types/components/messages/AssistantToolUseMessage.js +45 -17
  44. package/lib/types/components/messages/UserPromptMessage.d.ts +4 -6
  45. package/lib/types/components/messages/UserPromptMessage.d.ts.map +1 -1
  46. package/lib/types/components/messages/UserPromptMessage.js +5 -9
  47. package/lib/types/dsh-adapter/channel.d.ts +22 -0
  48. package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
  49. package/lib/types/dsh-adapter/channel.js +204 -19
  50. package/lib/types/dsh-adapter/index.d.ts +5 -0
  51. package/lib/types/dsh-adapter/index.d.ts.map +1 -1
  52. package/lib/types/dsh-adapter/index.js +19 -0
  53. package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
  54. package/lib/types/dsh-adapter/plugin.js +176 -4
  55. package/lib/types/dsh-adapter/settings-sections.d.ts +13 -0
  56. package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
  57. package/lib/types/dsh-adapter/settings-sections.js +31 -6
  58. package/lib/types/ink/ink.d.ts +9 -0
  59. package/lib/types/ink/ink.d.ts.map +1 -1
  60. package/lib/types/ink/ink.js +24 -1
  61. package/lib/types/screens/Chat.d.ts.map +1 -1
  62. package/lib/types/screens/Chat.js +35 -6
  63. package/lib/types/screens/Settings.d.ts.map +1 -1
  64. package/lib/types/screens/Settings.js +109 -50
  65. package/lib/types/screens/StatusLine.d.ts +8 -0
  66. package/lib/types/screens/StatusLine.d.ts.map +1 -1
  67. package/lib/types/screens/StatusLine.js +62 -39
  68. package/lib/types/settings-sections.d.ts +1 -1
  69. package/lib/types/settings-sections.d.ts.map +1 -1
  70. package/lib/types/theme.d.ts +12 -0
  71. package/lib/types/theme.d.ts.map +1 -1
  72. package/lib/types/theme.js +51 -21
  73. package/lib/types/tips.js +2 -2
  74. package/lib/types/trajectory/effortIgnition.d.ts +66 -0
  75. package/lib/types/trajectory/effortIgnition.d.ts.map +1 -0
  76. package/lib/types/trajectory/effortIgnition.js +142 -0
  77. package/lib/types/tuiDisplayPrefs.d.ts +47 -0
  78. package/lib/types/tuiDisplayPrefs.d.ts.map +1 -0
  79. package/lib/types/tuiDisplayPrefs.js +60 -0
  80. package/package.json +6 -3
@@ -23,6 +23,7 @@ import { clearResumeTarget, writeResumeTarget } from '../sessionHistory.js';
23
23
  import { resolveSessionCwd } from '../utils/workspaceRoot.js';
24
24
  import { checkForTuiUpdate, installedTuiVersion, isBootDeadlockTarget, isVersionNewer, resolveDshProfileName, resolveTuiUpdateTarget, updateTuiAndRestart } from '../update.js';
25
25
  import { getLang, isLang, resolveStartupLang, setLang, t, writeLangPref } from '../i18n.js';
26
+ import { DEFAULT_STATUS_BAR, normalizeStatusBar, normalizeToolBackground } from '../tuiDisplayPrefs.js';
26
27
  import { detectLegacyEnv, migrateLegacyDataDir, RENAMED_ENV } from '../utils/paths.js';
27
28
  import { Chat } from '../screens/Chat.js';
28
29
  import { getHostDialogStore } from './dialogs.js';
@@ -326,6 +327,8 @@ export async function apply(ctx, config) {
326
327
  // screen edits this key live through the dsh-tui namespace.
327
328
  diffLayout: config.diffLayout,
328
329
  thinkingFold: config.thinkingFold,
330
+ toolBackground: config.toolBackground,
331
+ statusBar: config.statusBar,
329
332
  handle,
330
333
  });
331
334
  // Register the dsh-tui settings namespace so the /settings screen can
@@ -336,6 +339,24 @@ export async function apply(ctx, config) {
336
339
  const scope = settingsCtx.settings.register(settingsNamespace('dsh-tui'), Schema.object({
337
340
  diffLayout: Schema.union(['auto', 'split', 'unified']).default('auto'),
338
341
  thinkingFold: Schema.union(['preview', 'full']).default('preview'),
342
+ toolBackground: Schema.union(['none', 'subtle', 'strong']).default('none'),
343
+ statusBar: Schema.object({
344
+ compact: Schema.boolean().default(DEFAULT_STATUS_BAR.compact),
345
+ model: Schema.boolean().default(DEFAULT_STATUS_BAR.model),
346
+ thinking: Schema.boolean().default(DEFAULT_STATUS_BAR.thinking),
347
+ cwd: Schema.boolean().default(DEFAULT_STATUS_BAR.cwd),
348
+ contextUsage: Schema.boolean().default(DEFAULT_STATUS_BAR.contextUsage),
349
+ cache: Schema.boolean().default(DEFAULT_STATUS_BAR.cache),
350
+ tokens: Schema.boolean().default(DEFAULT_STATUS_BAR.tokens),
351
+ tps: Schema.boolean().default(DEFAULT_STATUS_BAR.tps),
352
+ gitBranch: Schema.boolean().default(DEFAULT_STATUS_BAR.gitBranch),
353
+ sessionTitle: Schema.boolean().default(DEFAULT_STATUS_BAR.sessionTitle),
354
+ mode: Schema.boolean().default(DEFAULT_STATUS_BAR.mode),
355
+ contextBar: Schema.boolean().default(DEFAULT_STATUS_BAR.contextBar),
356
+ activity: Schema.boolean().default(DEFAULT_STATUS_BAR.activity),
357
+ trajectory: Schema.boolean().default(DEFAULT_STATUS_BAR.trajectory),
358
+ shortcutHint: Schema.boolean().default(DEFAULT_STATUS_BAR.shortcutHint),
359
+ }).default({ ...DEFAULT_STATUS_BAR }),
339
360
  // No default on purpose: an unset `lang` keeps the field showing
340
361
  // the effective language (see the section's format below) and lets
341
362
  // cordis.yml / lang.json keep their precedence.
@@ -355,15 +376,17 @@ export async function apply(ctx, config) {
355
376
  writeLangPref(value.lang);
356
377
  }
357
378
  };
358
- // thinkingFold rides the same namespace: /settings writes it live and
359
- // the channel picks it up at the next step seal.
360
- const applyThinkingFold = (value) => {
379
+ // Display preferences ride the same namespace: /settings writes them
380
+ // live and future render consumers observe the channel version bump.
381
+ const applyDisplay = (value) => {
361
382
  channel.setThinkingFold(value.thinkingFold ?? config.thinkingFold ?? 'preview');
383
+ channel.setToolBackground(normalizeToolBackground(value.toolBackground ?? config.toolBackground));
384
+ channel.setStatusBar(normalizeStatusBar(value.statusBar ?? config.statusBar));
362
385
  };
363
386
  const apply = (next) => {
364
387
  applyLayout(next);
365
388
  applyLang(next);
366
- applyThinkingFold(next);
389
+ applyDisplay(next);
367
390
  };
368
391
  apply(scope.get());
369
392
  scope.watch(next => {
@@ -379,6 +402,7 @@ export async function apply(ctx, config) {
379
402
  const unregister = settingsSections.register({
380
403
  ns: 'dsh-tui',
381
404
  title: 'dsh-tui',
405
+ groups: [{ id: 'status-bar', title: 'Status bar', descriptions: { zh: '底栏设置' } }],
382
406
  fields: [
383
407
  {
384
408
  path: ['lang'],
@@ -423,6 +447,154 @@ export async function apply(ctx, config) {
423
447
  { value: 'full', label: 'Full until turn end', descriptions: { zh: '展开至轮末' } },
424
448
  ],
425
449
  },
450
+ {
451
+ path: ['toolBackground'],
452
+ label: 'Tool background',
453
+ descriptions: { zh: '工具卡背景' },
454
+ hint: 'Choose whether tool-call cards add no, subtle, or strong background emphasis.',
455
+ hintDescriptions: { zh: '选择工具调用卡片不添加、轻微或明显的背景强调。' },
456
+ kind: 'select',
457
+ options: [
458
+ { value: 'none', label: 'None', descriptions: { zh: '无' } },
459
+ { value: 'subtle', label: 'Subtle', descriptions: { zh: '轻微' } },
460
+ { value: 'strong', label: 'Strong', descriptions: { zh: '明显' } },
461
+ ],
462
+ },
463
+ {
464
+ path: ['statusBar', 'compact'],
465
+ label: 'Compact status bar',
466
+ descriptions: { zh: '紧凑状态栏' },
467
+ hint: 'Prefer the compact status presentation when terminal space allows.',
468
+ hintDescriptions: { zh: '终端空间允许时优先使用紧凑状态栏布局。' },
469
+ group: 'status-bar',
470
+ kind: 'boolean',
471
+ },
472
+ {
473
+ path: ['statusBar', 'model'],
474
+ label: 'Show model',
475
+ descriptions: { zh: '显示模型' },
476
+ hint: 'Show the live model id in the status bar.',
477
+ hintDescriptions: { zh: '在状态栏显示当前模型标识。' },
478
+ group: 'status-bar',
479
+ kind: 'boolean',
480
+ },
481
+ {
482
+ path: ['statusBar', 'thinking'],
483
+ label: 'Show thinking',
484
+ descriptions: { zh: '显示思考' },
485
+ hint: 'Show the live reasoning effort or thinking mode.',
486
+ hintDescriptions: { zh: '显示当前推理强度或思考模式。' },
487
+ group: 'status-bar',
488
+ kind: 'boolean',
489
+ },
490
+ {
491
+ path: ['statusBar', 'cwd'],
492
+ label: 'Show working directory',
493
+ descriptions: { zh: '显示工作目录' },
494
+ hint: 'Show the session working directory.',
495
+ hintDescriptions: { zh: '显示当前会话的工作目录。' },
496
+ group: 'status-bar',
497
+ kind: 'boolean',
498
+ },
499
+ {
500
+ path: ['statusBar', 'contextUsage'],
501
+ label: 'Show context usage',
502
+ descriptions: { zh: '显示上下文用量' },
503
+ hint: 'Show current context-window consumption.',
504
+ hintDescriptions: { zh: '显示当前上下文窗口占用情况。' },
505
+ group: 'status-bar',
506
+ kind: 'boolean',
507
+ },
508
+ {
509
+ path: ['statusBar', 'cache'],
510
+ label: 'Show cache',
511
+ descriptions: { zh: '显示缓存' },
512
+ hint: 'Show prompt-cache hit information.',
513
+ hintDescriptions: { zh: '显示提示词缓存命中信息。' },
514
+ group: 'status-bar',
515
+ kind: 'boolean',
516
+ },
517
+ {
518
+ path: ['statusBar', 'tokens'],
519
+ label: 'Show token totals',
520
+ descriptions: { zh: '显示 Token 总量' },
521
+ hint: 'Show running input and output token totals.',
522
+ hintDescriptions: { zh: '显示累计输入与输出 Token。' },
523
+ group: 'status-bar',
524
+ kind: 'boolean',
525
+ },
526
+ {
527
+ path: ['statusBar', 'tps'],
528
+ label: 'Show output speed',
529
+ descriptions: { zh: '显示输出速度' },
530
+ hint: 'Show live and recent tokens-per-second metrics.',
531
+ hintDescriptions: { zh: '显示实时及近期每秒 Token 指标。' },
532
+ group: 'status-bar',
533
+ kind: 'boolean',
534
+ },
535
+ {
536
+ path: ['statusBar', 'gitBranch'],
537
+ label: 'Show git branch',
538
+ descriptions: { zh: '显示 Git 分支' },
539
+ hint: 'Show the current git branch when available.',
540
+ hintDescriptions: { zh: '可用时显示当前 Git 分支。' },
541
+ group: 'status-bar',
542
+ kind: 'boolean',
543
+ },
544
+ {
545
+ path: ['statusBar', 'sessionTitle'],
546
+ label: 'Show session title',
547
+ descriptions: { zh: '显示会话标题' },
548
+ hint: 'Show the current session title.',
549
+ hintDescriptions: { zh: '显示当前会话标题。' },
550
+ group: 'status-bar',
551
+ kind: 'boolean',
552
+ },
553
+ {
554
+ path: ['statusBar', 'mode'],
555
+ label: 'Show session mode',
556
+ descriptions: { zh: '显示会话模式' },
557
+ hint: 'Show the active non-default session mode.',
558
+ hintDescriptions: { zh: '显示当前启用的非默认会话模式。' },
559
+ group: 'status-bar',
560
+ kind: 'boolean',
561
+ },
562
+ {
563
+ path: ['statusBar', 'contextBar'],
564
+ label: 'Show context progress bar',
565
+ descriptions: { zh: '显示上下文进度条' },
566
+ hint: 'Show the segmented context progress bar on its own footer row.',
567
+ hintDescriptions: { zh: '在底部单独一行显示分段上下文进度条。' },
568
+ group: 'status-bar',
569
+ kind: 'boolean',
570
+ },
571
+ {
572
+ path: ['statusBar', 'activity'],
573
+ label: 'Show activity summary',
574
+ descriptions: { zh: '显示活动摘要' },
575
+ hint: 'Show the idle working-activity summary.',
576
+ hintDescriptions: { zh: '显示空闲时的工作活动摘要。' },
577
+ group: 'status-bar',
578
+ kind: 'boolean',
579
+ },
580
+ {
581
+ path: ['statusBar', 'trajectory'],
582
+ label: 'Show trajectory strip',
583
+ descriptions: { zh: '显示轨迹条' },
584
+ hint: 'Show the animated mini trajectory strip at the footer edge.',
585
+ hintDescriptions: { zh: '在状态栏边缘显示动态迷你轨迹条。' },
586
+ group: 'status-bar',
587
+ kind: 'boolean',
588
+ },
589
+ {
590
+ path: ['statusBar', 'shortcutHint'],
591
+ label: 'Show shortcut reminder',
592
+ descriptions: { zh: '显示快捷键提示' },
593
+ hint: 'Control only the idle `? for shortcuts` reminder; pressing ? and the Esc shortcut hints are unaffected.',
594
+ hintDescriptions: { zh: '仅控制空闲时的 `? for shortcuts` 提示;按 ? 打开快捷键以及 Esc 快捷提示均不受影响。' },
595
+ group: 'status-bar',
596
+ kind: 'boolean',
597
+ },
426
598
  ],
427
599
  });
428
600
  ctx.effect(() => unregister);
@@ -21,6 +21,15 @@ export interface TuiSettingsFieldOption {
21
21
  /** Provider-owned translations for the label. */
22
22
  descriptions?: LocalizedDescriptions;
23
23
  }
24
+ /** Optional navigation group inside one settings section. */
25
+ export interface TuiSettingsGroup {
26
+ /** Stable identifier, unique inside the section. */
27
+ id: string;
28
+ /** Group title (English; also the fallback). */
29
+ title: string;
30
+ /** Provider-owned translations for the title. */
31
+ descriptions?: LocalizedDescriptions;
32
+ }
24
33
  /** The write one field's draft stages when the section is saved. */
25
34
  export type TuiSettingsFieldWrite = {
26
35
  kind: 'set';
@@ -42,6 +51,8 @@ export interface TuiSettingsField {
42
51
  hint?: string;
43
52
  /** Provider-owned translations for the hint. */
44
53
  hintDescriptions?: LocalizedDescriptions;
54
+ /** Optional group id; grouped fields render on that group's subpage. */
55
+ group?: string;
45
56
  kind: TuiSettingsFieldKind;
46
57
  /** Choices for `kind: 'select'` (ignored otherwise). */
47
58
  options?: readonly TuiSettingsFieldOption[];
@@ -83,6 +94,8 @@ export interface TuiSettingsSection {
83
94
  title: string;
84
95
  /** Provider-owned translations for the title. */
85
96
  descriptions?: LocalizedDescriptions;
97
+ /** Optional navigation groups, in display order. */
98
+ groups?: readonly TuiSettingsGroup[];
86
99
  /** Editable fields, in display order. */
87
100
  fields: readonly TuiSettingsField[];
88
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"settings-sections.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/settings-sections.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAG3D,iEAAiE;AACjE,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE3E,MAAM,WAAW,sBAAsB;IACrC,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAA;IACb,iDAAiD;IACjD,YAAY,CAAC,EAAE,qBAAqB,CAAA;CACrC;AAED,oEAAoE;AACpE,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAA;AAErB,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,iDAAiD;IACjD,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,qBAAqB,CAAA;IACxC,IAAI,EAAE,oBAAoB,CAAA;IAC1B,wDAAwD;IACxD,OAAO,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAC3C,uDAAuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IACxB;;;OAGG;IACH,MAAM,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IAC/B;;;;;;OAMG;IACH,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,qBAAqB,GAAG,SAAS,CAAA;CACxD;AAED,2DAA2D;AAC3D,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAA;IACV,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAA;IACb,iDAAiD;IACjD,YAAY,CAAC,EAAE,qBAAqB,CAAA;IACpC,yCAAyC;IACzC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAA;CACpC;AAED,6EAA6E;AAC7E,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,IAAI,CAAA;IACjD,IAAI,IAAI,SAAS,kBAAkB,EAAE,CAAA;IACrC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAA;CAC5C;AAED,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,mBAAmB,EAAE,0BAA0B,CAAA;KAChD;CACF;AAED,eAAO,MAAM,IAAI,8BAA8B,CAAA;AAE/C;;;GAGG;AACH,qBAAa,0BAA2B,SAAQ,OAAO;gBACzC,GAAG,EAAE,OAAO;IAmBxB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,IAAI;IASjD,iDAAiD;IACjD,IAAI,IAAI,SAAS,kBAAkB,EAAE;IAQrC,sDAAsD;IACtD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAQnD;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;CAS5C;AAgED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,0BAA0B,GAAG,SAAS,GAAG,uBAAuB,GAAG,SAAS,CAO5H;AAED,eAAe,0BAA0B,CAAA"}
1
+ {"version":3,"file":"settings-sections.d.ts","sourceRoot":"","sources":["../../../src/dsh-adapter/settings-sections.ts"],"names":[],"mappings":"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"}
@@ -88,12 +88,30 @@ function registerSection(runtime, section, owner) {
88
88
  throw new TypeError(`invalid TUI settings-section namespace: ${section.ns}`);
89
89
  if (state.sections.has(ns))
90
90
  throw new Error(`TUI settings section "${ns}" is already registered`);
91
- const normalized = Object.freeze({
92
- ...section,
93
- ns,
94
- descriptions: section.descriptions === undefined ? undefined : Object.freeze({ ...section.descriptions }),
95
- fields: Object.freeze(section.fields.map(field => Object.freeze({
91
+ const groupIds = new Set();
92
+ const groups = section.groups === undefined
93
+ ? undefined
94
+ : Object.freeze(section.groups.map(group => {
95
+ const id = group.id.trim();
96
+ if (!/^[a-z][a-z0-9_-]*$/u.test(id))
97
+ throw new TypeError(`invalid TUI settings group id: ${group.id}`);
98
+ if (groupIds.has(id))
99
+ throw new Error(`TUI settings group "${id}" is already declared in section "${ns}"`);
100
+ groupIds.add(id);
101
+ return Object.freeze({
102
+ ...group,
103
+ id,
104
+ descriptions: group.descriptions === undefined ? undefined : Object.freeze({ ...group.descriptions }),
105
+ });
106
+ }));
107
+ const fields = Object.freeze(section.fields.map(field => {
108
+ const group = field.group?.trim();
109
+ if (group !== undefined && !groupIds.has(group)) {
110
+ throw new TypeError(`TUI settings field "${field.path.join('.')}" references unknown group "${field.group}" in section "${ns}"`);
111
+ }
112
+ return Object.freeze({
96
113
  ...field,
114
+ group,
97
115
  path: Object.freeze([...field.path]),
98
116
  descriptions: field.descriptions === undefined ? undefined : Object.freeze({ ...field.descriptions }),
99
117
  hintDescriptions: field.hintDescriptions === undefined ? undefined : Object.freeze({ ...field.hintDescriptions }),
@@ -101,7 +119,14 @@ function registerSection(runtime, section, owner) {
101
119
  ? undefined
102
120
  : Object.freeze(field.options.map(option => Object.freeze({ ...option, descriptions: option.descriptions === undefined ? undefined : Object.freeze({ ...option.descriptions }) }))),
103
121
  secret: field.secret === undefined ? undefined : Object.freeze({ ...field.secret }),
104
- }))),
122
+ });
123
+ }));
124
+ const normalized = Object.freeze({
125
+ ...section,
126
+ ns,
127
+ descriptions: section.descriptions === undefined ? undefined : Object.freeze({ ...section.descriptions }),
128
+ groups,
129
+ fields,
105
130
  });
106
131
  state.sections.set(ns, normalized);
107
132
  if (owner !== undefined)
@@ -113,6 +113,15 @@ export default class Ink {
113
113
  * unchanged cells don't need repainting. Scrollback is preserved.
114
114
  */
115
115
  forceRedraw(): void;
116
+ /**
117
+ * Establish a genuinely fresh terminal page: clear both the visible screen
118
+ * and native scrollback, reset frame correspondence, then redraw the current
119
+ * React tree. This is intentionally stronger than Ctrl+L/forceRedraw(),
120
+ * which preserves history; use it only at a destructive UI boundary such as
121
+ * `/new`, where showing the previous conversation above the new session is
122
+ * misleading.
123
+ */
124
+ clearScrollbackAndRedraw(): void;
116
125
  /**
117
126
  * Mark the previous frame as untrustworthy for blit, forcing the next
118
127
  * render to do a full-damage diff instead of the per-node fast path.
@@ -1 +1 @@
1
- {"version":3,"file":"ink.d.ts","sourceRoot":"","sources":["../../../src/ink/ink.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ink.d.ts","sourceRoot":"","sources":["../../../src/ink/ink.tsx"],"names":[],"mappings":"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"}
@@ -32,7 +32,7 @@ import { CharPool, cellAt, createScreen, HyperlinkPool, isEmptyCellAt, migrateSc
32
32
  import { applySearchHighlight } from './searchHighlight.js';
33
33
  import { applySelectionOverlay, captureScrolledRows, clearSelection, createSelectionState, extendSelection, findPlainTextUrlAt, getSelectedText, hasSelection, moveFocus, selectLineAt, selectWordAt, shiftAnchor, shiftSelection, shiftSelectionForFollow, startSelection, updateSelection } from './selection.js';
34
34
  import { isDecstbmSafe, SYNC_OUTPUT_SUPPORTED, supportsExtendedKeys, supportsWin32InputMode, writeDiffToTerminal } from './terminal.js';
35
- import { CURSOR_HOME, cursorMove, cursorPosition, DISABLE_KITTY_KEYBOARD, DISABLE_MODIFY_OTHER_KEYS, DISABLE_WIN32_INPUT_MODE, ENABLE_KITTY_KEYBOARD, ENABLE_MODIFY_OTHER_KEYS, ENABLE_WIN32_INPUT_MODE, ERASE_SCREEN, SGR_RESET } from './termio/csi.js';
35
+ import { CURSOR_HOME, cursorMove, cursorPosition, DISABLE_KITTY_KEYBOARD, DISABLE_MODIFY_OTHER_KEYS, DISABLE_WIN32_INPUT_MODE, ENABLE_KITTY_KEYBOARD, ENABLE_MODIFY_OTHER_KEYS, ENABLE_WIN32_INPUT_MODE, ERASE_SCREEN, ERASE_SCROLLBACK, SGR_RESET } from './termio/csi.js';
36
36
  import { DBP, DFE, DISABLE_MOUSE_TRACKING, ENABLE_MOUSE_TRACKING, ENTER_ALT_SCREEN, EXIT_ALT_SCREEN, SHOW_CURSOR } from './termio/dec.js';
37
37
  import { CLEAR_ITERM2_PROGRESS, CLEAR_TAB_STATUS, setClipboard, supportsTabStatus, wrapForMultiplexer } from './termio/osc.js';
38
38
  import { TerminalWriteProvider } from './useTerminalNotification.js';
@@ -874,6 +874,29 @@ export default class Ink {
874
874
  }
875
875
  this.onRender();
876
876
  }
877
+ /**
878
+ * Establish a genuinely fresh terminal page: clear both the visible screen
879
+ * and native scrollback, reset frame correspondence, then redraw the current
880
+ * React tree. This is intentionally stronger than Ctrl+L/forceRedraw(),
881
+ * which preserves history; use it only at a destructive UI boundary such as
882
+ * `/new`, where showing the previous conversation above the new session is
883
+ * misleading.
884
+ */
885
+ clearScrollbackAndRedraw() {
886
+ if (!this.options.stdout.isTTY || this.isUnmounted || this.isPaused)
887
+ return;
888
+ // Keep 3J outside synchronized output. Windows Terminal can relocate the
889
+ // viewport when erase-buffer commands execute inside BSU/ESU.
890
+ this.options.stdout.write(SGR_RESET + ERASE_SCROLLBACK + ERASE_SCREEN + CURSOR_HOME);
891
+ if (this.altScreenActive) {
892
+ this.resetFramesForAltScreen();
893
+ }
894
+ else {
895
+ this.repaint();
896
+ this.prevFrameContaminated = true;
897
+ }
898
+ this.onRender();
899
+ }
877
900
  /**
878
901
  * Mark the previous frame as untrustworthy for blit, forcing the next
879
902
  * render to do a full-damage diff instead of the per-node fast path.
@@ -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;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"}
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,qBAioEA"}
@@ -298,6 +298,18 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
298
298
  const loadedContextVisible = channel.rows.length === 0 && channel.loadedContext !== undefined;
299
299
  /** Startup context panel: collapsed by default, toggled with Ctrl+P. */
300
300
  const [loadedContextOpen, setLoadedContextOpen] = React.useState(false);
301
+ /**
302
+ * The context panel changes the height of the main-screen transcript by a
303
+ * large amount. In inline mode that invalidates the renderer's previous
304
+ * scrollback/layout correspondence; asking it to repaint from the physical
305
+ * viewport prevents the collapsed frame from reusing stale blank cells.
306
+ */
307
+ const toggleLoadedContext = React.useCallback(() => {
308
+ setLoadedContextOpen(previous => !previous);
309
+ const ink = instances.get(process.stdout) ?? instances.values().next().value;
310
+ ink?.invalidatePrevFrame();
311
+ ink?.reanchorViewport();
312
+ }, []);
301
313
  /** `/` transcript search (less-style incsearch, ported from CC's REPL). */
302
314
  const [searchOpen, setSearchOpen] = React.useState(false);
303
315
  const [searchQuery, setSearchQuery] = React.useState('');
@@ -659,8 +671,26 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
659
671
  // non-destructive — no CC-style "press /new again" confirmation.
660
672
  setHelpOpen(false);
661
673
  void channel.newSession().then((ok) => {
662
- if (ok)
663
- channel.notify(t('new-session-started'));
674
+ if (!ok)
675
+ return;
676
+ // A new session is a fresh terminal page, not merely an emptied
677
+ // transcript. Reset view-local state, return the ScrollBox to the
678
+ // top, then clear native scrollback and repaint the whale homepage.
679
+ setExpanded(false);
680
+ setExpandedRows(new Set());
681
+ setSelectedId(null);
682
+ setSelectionActive(false);
683
+ setShowAllMessages(false);
684
+ setLoadedContextOpen(false);
685
+ handle?.scrollTo(0);
686
+ channel.notify(t('new-session-started'));
687
+ const ink = instances.get(process.stdout) ?? instances.values().next().value;
688
+ // Wait one task so React commits the empty transcript/homepage tree;
689
+ // clearing before that would immediately repaint the old session.
690
+ setTimeout(() => {
691
+ handle?.scrollTo(0);
692
+ ink?.clearScrollbackAndRedraw();
693
+ }, 0);
664
694
  });
665
695
  return true;
666
696
  }
@@ -1824,7 +1854,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
1824
1854
  // Ctrl+P toggles the startup loaded-context panel while it is on
1825
1855
  // screen (transcript still empty); once rows take over and the
1826
1856
  // panel disappears the key has nothing left to do.
1827
- setLoadedContextOpen(previous => !previous);
1857
+ toggleLoadedContext();
1828
1858
  return;
1829
1859
  }
1830
1860
  if (isMod(key) && input === 'r' && !helpOpen) {
@@ -2014,7 +2044,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
2014
2044
  seekRow(lastUser.id);
2015
2045
  else
2016
2046
  handle?.scrollToBottom();
2017
- } })), _jsxs(ScrollBox, { ref: setHandle, flexDirection: "column", flexGrow: 1, flexShrink: 1, stickyScroll: true, children: [_jsx(LogoHeader, { model: channel.model, effort: channel.reasoningEffort, cwd: channel.displayCwd }), loadedContextVisible && (_jsx(LoadedContextPanel, { context: channel.loadedContext, open: loadedContextOpen, onToggle: () => { setLoadedContextOpen(previous => !previous); } })), _jsx(MessageList, { rows: channel.rows, failureHintRowId: failureHintRowId, failureHint: t('traj-hint-failure', { key: `${modLabel}t` }), expanded: expanded, expandedRows: expandedRows, selectedId: selectionActive ? selectedId : null, onToggleRow: toggleRowExpanded, model: channel.model, diffLayout: channel.diffLayout, thinkingFold: channel.thinkingFold, showAll: showAllMessages, thinkingVisible: thinkingVisible, onToggleAll: () => { setShowAllMessages(previous => !previous); }, onLoadOlder: () => channel.loadOlder(), registerRowRef: registerRowRef, scrollHandle: handle, forceMountRowId: forceMountRowId, newSinceRowId: isSticky ? null : lastSeenRowIdRef.current, onUnseenCount: setUnseenCount })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [showPill && (_jsx(NewMessagesPill, { count: unseenCount, onClick: () => handle?.scrollToBottom() })), channel.working &&
2047
+ } })), _jsxs(ScrollBox, { ref: setHandle, flexDirection: "column", flexGrow: 1, flexShrink: 1, stickyScroll: true, children: [_jsx(LogoHeader, { model: channel.model, effort: channel.reasoningEffort, cwd: channel.displayCwd }), loadedContextVisible && (_jsx(LoadedContextPanel, { context: channel.loadedContext, open: loadedContextOpen, onToggle: toggleLoadedContext })), _jsx(MessageList, { rows: channel.rows, failureHintRowId: failureHintRowId, failureHint: t('traj-hint-failure', { key: `${modLabel}t` }), expanded: expanded, expandedRows: expandedRows, selectedId: selectionActive ? selectedId : null, onToggleRow: toggleRowExpanded, model: channel.model, diffLayout: channel.diffLayout, thinkingFold: channel.thinkingFold, toolBackground: channel.toolBackground, showAll: showAllMessages, thinkingVisible: thinkingVisible, onToggleAll: () => { setShowAllMessages(previous => !previous); }, onLoadOlder: () => channel.loadOlder(), registerRowRef: registerRowRef, scrollHandle: handle, forceMountRowId: forceMountRowId, newSinceRowId: isSticky ? null : lastSeenRowIdRef.current, onUnseenCount: setUnseenCount })] }), _jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [showPill && (_jsx(NewMessagesPill, { count: unseenCount, onClick: () => handle?.scrollToBottom() })), channel.working &&
2018
2048
  (channel.activityEnabled &&
2019
2049
  channel.workingActivity !== undefined &&
2020
2050
  channel.workingActivity.line !== '' &&
@@ -2041,8 +2071,7 @@ export function Chat({ channel, questionStore, approvalStore, extensionDialogs,
2041
2071
  * Fixed at 1 row so the ScrollBox never shifts when the text changes.
2042
2072
  */
2043
2073
  function StickyPromptHeader({ text, onClick, }) {
2044
- const [hover, setHover] = React.useState(false);
2045
- return (_jsx(Box, { flexShrink: 0, width: "100%", height: 1, paddingRight: 1, backgroundColor: hover ? 'userMessageBackgroundHover' : 'userMessageBackground', onMouseEnter: () => { setHover(true); }, onMouseLeave: () => { setHover(false); }, onClick: onClick, children: _jsxs(Text, { color: "subtle", wrap: "truncate-end", children: [POINTER, " ", text] }) }));
2074
+ return (_jsx(Box, { flexShrink: 0, width: "100%", height: 1, paddingRight: 1, onClick: onClick, children: _jsxs(Text, { color: "briefLabelYou", bold: true, wrap: "truncate-end", children: [POINTER, " ", text] }) }));
2046
2075
  }
2047
2076
  /** The `↓ N new messages` pill shown while scrolled up with new content. */
2048
2077
  function NewMessagesPill({ count, onClick, }) {
@@ -1 +1 @@
1
- {"version":3,"file":"Settings.d.ts","sourceRoot":"","sources":["../../../src/screens/Settings.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AA2CxD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CA0VlB"}
1
+ {"version":3,"file":"Settings.d.ts","sourceRoot":"","sources":["../../../src/screens/Settings.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AA+CxD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,OAAO,GACR,EAAE;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,GAAG,KAAK,CAAC,SAAS,CA0ZlB"}