dsh-neotui 0.0.14 → 0.0.15

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/views.js +21 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-neotui",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "description": "Neo-TUI: mouse-driven terminal UI client for DeepSeek Harness (B-tier per dsh-tui-design.md)",
5
5
  "type": "module",
6
6
  "bin": { "dsh-neotui": "bin/dsh-tui.js" },
package/src/views.js CHANGED
@@ -874,6 +874,12 @@ export class ChatView extends Widget {
874
874
  if (first < 0) return;
875
875
  const target = Math.min(first + topOffset, last);
876
876
  this.view.scrollY = Math.max(0, Math.min(target, this.view.maxScroll()));
877
+ // never park the viewport on a blank separator row — it reads as a
878
+ // spurious offset right after the click
879
+ while (
880
+ this.view.scrollY < this.lineMap.length - 1 &&
881
+ !(this.lines[this.view.scrollY] ?? []).some((g) => g.t.trim() !== "")
882
+ ) this.view.scrollY++;
877
883
  };
878
884
  if (node?.kind === "assistant" && info.blockIdx !== null) {
879
885
  const b = node.blocks[info.blockIdx];
@@ -1016,12 +1022,16 @@ export class ChatView extends Widget {
1016
1022
  const open = manuallyExpanded || (!manuallyCollapsed && this.thinkMode === "expanded");
1017
1023
  beginCard("THINKBG");
1018
1024
  // Live blocks tick (已经过…); finished blocks freeze at their
1019
- // total (已完成,耗时…). No timestamps no bogus timer shown.
1025
+ // total (已完成,耗时…). Snapshot-derived blocks may lack a
1026
+ // per-block start (the history projection has no block-start):
1027
+ // show a plain 已完成 then — never a bogus ticking timer.
1020
1028
  let timing = "";
1021
1029
  if (b.streaming) {
1022
1030
  timing = ` 已经过 ${fmtDuration(Date.now() - (b.startedAt ?? Date.now()))}`;
1023
1031
  } else if (b.startedAt !== undefined && b.endedAt !== undefined) {
1024
1032
  timing = ` 已完成,耗时 ${fmtDuration(b.endedAt - b.startedAt)}`;
1033
+ } else if (b.endedAt !== undefined) {
1034
+ timing = " 已完成";
1025
1035
  }
1026
1036
  const thinkMeta = `${stepTag}(${b.text?.length ?? 0} 字)${timing}`;
1027
1037
  lines.push([{ t: "💭 思考" + (b.streaming ? "…" : "") + thinkMeta + (open ? " [t 折叠]" : " [t 展开]"), fg: K.FAINT }]);
@@ -1041,16 +1051,23 @@ export class ChatView extends Widget {
1041
1051
  const key = `${realIdx}:${bi}`;
1042
1052
  const open = this.bashMode !== "collapsed" && !this.collapsedBlocks.has(key);
1043
1053
  const exitCode = b.view?.view?.exitCode;
1044
- const status = b.result == null && !b.done ? "TOOLBG" : exitCode !== undefined && exitCode !== 0 ? "TOOLERR" : "TOOLOK";
1045
- const glyph = b.result == null && !b.done ? "⏳" : exitCode !== undefined && exitCode !== 0 ? "✗" : "✓";
1054
+ // A tool only TICKS while its turn is live. A finalized turn
1055
+ // whose result never matched (orphan) must freeze at 无结果
1056
+ // otherwise the timer runs forever ("timing chaos").
1057
+ const running = b.result == null && !b.done && node.streaming;
1058
+ const orphan = b.result == null && !b.done && !node.streaming;
1059
+ const status = orphan ? "TOOLERR" : running ? "TOOLBG" : exitCode !== undefined && exitCode !== 0 ? "TOOLERR" : "TOOLOK";
1060
+ const glyph = orphan ? "✗" : running ? "⏳" : exitCode !== undefined && exitCode !== 0 ? "✗" : "✓";
1046
1061
  const card = b.view ? renderToolCard(b.view, w, open) : [];
1047
1062
  beginCard(status);
1048
1063
  let timing = "";
1049
- if (b.result == null && !b.done) {
1064
+ if (running) {
1050
1065
  timing = ` 已经过 ${fmtDuration(Date.now() - (b.startedAt ?? Date.now()))}`;
1051
1066
  } else if (b.startedAt !== undefined && b.endedAt !== undefined) {
1052
1067
  const failed = exitCode !== undefined && exitCode !== 0;
1053
1068
  timing = ` ${failed ? "失败" : "已完成"},耗时 ${fmtDuration(b.endedAt - b.startedAt)}`;
1069
+ } else if (orphan) {
1070
+ timing = " 无结果";
1054
1071
  }
1055
1072
  lines.push([
1056
1073
  { t: open ? "▾ " : "▸ ", fg: K.ACCENT },