shadok-ai 0.13.11 → 0.13.12

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/public/index.html +38 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shadok-ai",
3
- "version": "0.13.11",
3
+ "version": "0.13.12",
4
4
  "main": "dist/session.js",
5
5
  "scripts": {
6
6
  "test": "node --import tsx --test test/*.ts context/*/test/*.test.mjs",
package/public/index.html CHANGED
@@ -4840,6 +4840,29 @@
4840
4840
  tab.livePreviewBubble = null;
4841
4841
  }
4842
4842
 
4843
+ /**
4844
+ * The message an agent writes just BEFORE it asks a question lives only on the
4845
+ * TUI screen until the turn finalises — which, for a turn suspended ON that
4846
+ * question, is only AFTER you answer. So the dialog appeared with nothing above
4847
+ * it, and the message "came back" once a choice was made (the reported bug).
4848
+ *
4849
+ * On a dialog we therefore PROMOTE that in-flight text (the grey live preview)
4850
+ * into a persistent bubble, rendered just before the question, instead of
4851
+ * clearing it. When `stream-text` later delivers the authoritative block it is
4852
+ * de-duplicated against this (a screen window is a substring of the full text),
4853
+ * so it is not shown twice. Mirrors the Telegram bridge's `preface`.
4854
+ */
4855
+ function promotePreface(tab) {
4856
+ if (tab.prefaceEl) return; // already promoted (multi-select re-render)
4857
+ const txt = tab.livePreviewBubble ? tab.livePreviewBubble.textContent : "";
4858
+ const nT = normPreview(txt);
4859
+ if (!nT || isFinalizedBlock(tab, nT)) return; // nothing new to show (already a real block)
4860
+ const b = addTurn(tab, "claude", "claude", txt, "live", Date.now());
4861
+ tab.prefaceEl = b.parentElement;
4862
+ tab.prefaceNorm = nT;
4863
+ }
4864
+ function clearPreface(tab) { tab.prefaceEl = null; tab.prefaceNorm = null; }
4865
+
4843
4866
  /* ── Activity log ────────────────────────────────────────
4844
4867
  Tool traffic is grouped instead of stacked. A *block* is a run of tool
4845
4868
  events between two pieces of assistant text; inside it, consecutive calls
@@ -5937,6 +5960,15 @@
5937
5960
  {
5938
5961
  const fin = normPreview(msg.text);
5939
5962
  if (fin) (t.finalizedNorms ||= []).push(fin);
5963
+ // This authoritative block IS the preface we promoted for a pending
5964
+ // question: drop the promoted copy so the addTurn below re-adds it once,
5965
+ // clean (markdown, not the screen's plain wrap). Either contains the
5966
+ // other — the screen window can be a truncated substring of the full
5967
+ // block, or carry a transient trailing char (a cursor) the block lacks.
5968
+ if (t.prefaceEl && t.prefaceNorm && (fin.includes(t.prefaceNorm) || t.prefaceNorm.includes(fin))) {
5969
+ t.prefaceEl.remove();
5970
+ clearPreface(t);
5971
+ }
5940
5972
  }
5941
5973
  clearLivePreview(t);
5942
5974
  // Visible text arrived (NOTHING TO SHOW is filtered by the tail before
@@ -5967,6 +5999,9 @@
5967
5999
  case "turn-done":
5968
6000
  retireChoices(t);
5969
6001
  clearLivePreview(t);
6002
+ // A promoted preface that was never matched by a stream-text stays as the
6003
+ // shown text; just stop tracking it so the next turn starts clean.
6004
+ clearPreface(t);
5970
6005
  // Activity recedes now the turn is over — errors excepted.
5971
6006
  sealTurn(t);
5972
6007
  if (msg.sessionId && msg.sessionId !== t.sessionId) {
@@ -6005,6 +6040,9 @@
6005
6040
  case "dialog":
6006
6041
  // Re-rendered in place when a dialog is already shown (multi toggle).
6007
6042
  closeActivity(t);
6043
+ // Keep the message the agent wrote BEFORE the question visible — promote
6044
+ // the in-flight preview into a real bubble instead of dropping it.
6045
+ promotePreface(t);
6008
6046
  clearLivePreview(t);
6009
6047
  renderDialog(t, msg);
6010
6048
  stopTurnTimer(t);