@adhdev/daemon-core 0.9.76-rc.66 → 0.9.76-rc.67

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.
@@ -78,8 +78,10 @@ export declare class ProviderCliAdapter implements CliAdapter {
78
78
  private statusHistory;
79
79
  private cliScripts;
80
80
  private runtimeSettings;
81
- /** Full accumulated ANSI-stripped PTY output */
81
+ /** Full accumulated rendered PTY transcript for parser/readback use */
82
82
  private accumulatedBuffer;
83
+ /** Stateful rendered transcript accumulator; raw debug remains in accumulatedRawBuffer. */
84
+ private transcriptAccumulator;
83
85
  /** Full accumulated raw PTY output (with ANSI) */
84
86
  private accumulatedRawBuffer;
85
87
  /** Current visible terminal screen snapshot */
@@ -186,6 +186,30 @@ export interface CliProviderModule {
186
186
  _resolvedScriptsSource?: string | null;
187
187
  _versionWarning?: string | null;
188
188
  }
189
+ /**
190
+ * Stateful, transcript-oriented terminal cell accumulator.
191
+ *
192
+ * CLI transcript parsing must not consume raw PTY append text for user-visible
193
+ * readback: CLIs rewrite prompts/status/tool lines with CR, BS, CSI cursor
194
+ * motion and erase-line. This accumulator preserves parser state across chunks
195
+ * and mutates rendered cells before exposing plain transcript text. It is a
196
+ * deliberately small terminal model for readback buffers; live UI rendering still
197
+ * uses TerminalScreen's ghostty/xterm backend.
198
+ */
199
+ export declare class TerminalTranscriptAccumulator {
200
+ private lines;
201
+ private row;
202
+ private col;
203
+ private savedCursor;
204
+ private pendingEscape;
205
+ append(data: string): string;
206
+ reset(): void;
207
+ getText(): string;
208
+ private ensureRow;
209
+ private writeControlOrChar;
210
+ private consumeEscape;
211
+ private applyCsi;
212
+ }
189
213
  export declare function sanitizeTerminalText(str: string): string;
190
214
  export declare function listCliScriptNames(scripts: CliScripts | undefined): string[];
191
215
  export declare function buildCliScreenSnapshot(text: string): CliScreenSnapshot;
package/dist/index.js CHANGED
@@ -1340,13 +1340,25 @@ var init_pty_transport = __esm({
1340
1340
 
1341
1341
  // src/cli-adapters/provider-cli-shared.ts
1342
1342
  function stripAnsi(str) {
1343
- return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
1343
+ return str.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
1344
+ }
1345
+ function parseCount(params, fallback = 1) {
1346
+ const first = Number(String(params || "").split(";")[0] || fallback);
1347
+ return Math.max(1, Number.isFinite(first) ? first : fallback);
1348
+ }
1349
+ function isCombiningMark(ch) {
1350
+ return /[\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/.test(ch);
1351
+ }
1352
+ function isWideCodePoint(ch) {
1353
+ const cp = ch.codePointAt(0) || 0;
1354
+ return cp >= 4352 && (cp <= 4447 || cp === 9001 || cp === 9002 || cp >= 11904 && cp <= 42191 && cp !== 12351 || cp >= 44032 && cp <= 55203 || cp >= 63744 && cp <= 64255 || cp >= 65040 && cp <= 65049 || cp >= 65072 && cp <= 65135 || cp >= 65280 && cp <= 65376 || cp >= 65504 && cp <= 65510 || cp >= 127744 && cp <= 129791);
1344
1355
  }
1345
1356
  function stripTerminalNoise(str) {
1346
- return String(str || "").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, "").replace(/(^|[\s([])(?:\??\d{1,4}(?:;\d{1,4})*[A-Za-z])(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\[\??\d{1,4}(?:;\d{1,4})*[A-Za-z])(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\d{1,4};\?)(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\d+\$r[0-9;\" ]*[A-Za-z]?)(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:>\|[A-Za-z0-9_.:-]+(?:\([^)]*\))?)(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:[A-Z]\d(?:\s+[A-Z]\d)+)(?=$|[\s)\]])/g, "$1").replace(/(^|[\s([])(?:\d+;[^\s)\]]+)(?=$|[\s)\]])/g, "$1").replace(/\r+/g, "\n").replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").replace(/ {2,}/g, " ");
1357
+ return String(str || "").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, "").replace(/\r+/g, "\n").replace(/[ \t]+\n/g, "\n").replace(/\n{4,}/g, "\n\n\n");
1347
1358
  }
1348
1359
  function sanitizeTerminalText(str) {
1349
- return stripTerminalNoise(stripAnsi(str));
1360
+ const accumulator = new TerminalTranscriptAccumulator();
1361
+ return stripTerminalNoise(stripAnsi(accumulator.append(str)));
1350
1362
  }
1351
1363
  function listCliScriptNames(scripts) {
1352
1364
  if (!scripts) return [];
@@ -1525,7 +1537,7 @@ function normalizeCliProviderForRuntime(raw) {
1525
1537
  }
1526
1538
  };
1527
1539
  }
1528
- var os9, path14, import_child_process4, buildCliSpawnEnv;
1540
+ var os9, path14, import_child_process4, TerminalTranscriptAccumulator, buildCliSpawnEnv;
1529
1541
  var init_provider_cli_shared = __esm({
1530
1542
  "src/cli-adapters/provider-cli-shared.ts"() {
1531
1543
  "use strict";
@@ -1533,6 +1545,155 @@ var init_provider_cli_shared = __esm({
1533
1545
  path14 = __toESM(require("path"));
1534
1546
  import_child_process4 = require("child_process");
1535
1547
  init_spawn_env();
1548
+ TerminalTranscriptAccumulator = class {
1549
+ lines = [[]];
1550
+ row = 0;
1551
+ col = 0;
1552
+ savedCursor = null;
1553
+ pendingEscape = "";
1554
+ append(data) {
1555
+ const input = this.pendingEscape + String(data || "");
1556
+ this.pendingEscape = "";
1557
+ for (let i = 0; i < input.length; i += 1) {
1558
+ let ch = input[i];
1559
+ if (ch === "\x1B") {
1560
+ const consumed = this.consumeEscape(input.slice(i));
1561
+ if (consumed === 0) {
1562
+ this.pendingEscape = input.slice(i);
1563
+ break;
1564
+ }
1565
+ i += consumed - 1;
1566
+ continue;
1567
+ }
1568
+ const cp = input.codePointAt(i);
1569
+ if (cp && cp > 65535) {
1570
+ ch = String.fromCodePoint(cp);
1571
+ i += 1;
1572
+ }
1573
+ this.writeControlOrChar(ch);
1574
+ }
1575
+ return this.getText();
1576
+ }
1577
+ reset() {
1578
+ this.lines = [[]];
1579
+ this.row = 0;
1580
+ this.col = 0;
1581
+ this.savedCursor = null;
1582
+ this.pendingEscape = "";
1583
+ }
1584
+ getText() {
1585
+ return this.lines.map((line) => line.join("").replace(/[ \t]+$/g, "")).join("\n");
1586
+ }
1587
+ ensureRow(row = this.row) {
1588
+ while (this.lines.length <= row) this.lines.push([]);
1589
+ }
1590
+ writeControlOrChar(ch) {
1591
+ if (ch === "\r") {
1592
+ this.col = 0;
1593
+ return;
1594
+ }
1595
+ if (ch === "\n") {
1596
+ this.row += 1;
1597
+ this.col = 0;
1598
+ this.ensureRow();
1599
+ return;
1600
+ }
1601
+ if (ch === "\b") {
1602
+ this.col = Math.max(0, this.col - 1);
1603
+ return;
1604
+ }
1605
+ if (ch < " " || ch === "\x7F") return;
1606
+ this.ensureRow();
1607
+ const line = this.lines[this.row];
1608
+ if (isCombiningMark(ch) && this.col > 0) {
1609
+ line[this.col - 1] = `${line[this.col - 1] || ""}${ch}`;
1610
+ return;
1611
+ }
1612
+ while (line.length < this.col) line.push(" ");
1613
+ line[this.col] = ch;
1614
+ this.col += isWideCodePoint(ch) ? 2 : 1;
1615
+ }
1616
+ consumeEscape(seq) {
1617
+ if (seq.length < 2) return 0;
1618
+ const next = seq[1];
1619
+ if (next === "7") {
1620
+ this.savedCursor = { row: this.row, col: this.col };
1621
+ return 2;
1622
+ }
1623
+ if (next === "8") {
1624
+ if (this.savedCursor) {
1625
+ this.row = this.savedCursor.row;
1626
+ this.col = this.savedCursor.col;
1627
+ this.ensureRow();
1628
+ }
1629
+ return 2;
1630
+ }
1631
+ if (next === "]") {
1632
+ const bel = seq.indexOf("\x07", 2);
1633
+ const st = seq.indexOf("\x1B\\", 2);
1634
+ const end = bel >= 0 && (st < 0 || bel < st) ? bel + 1 : st >= 0 ? st + 2 : 0;
1635
+ return end;
1636
+ }
1637
+ if (next === "[") {
1638
+ const match = seq.match(/^\x1B\[([0-?]*)([ -/]*)([@-~])/);
1639
+ if (!match) return seq.length < 32 ? 0 : 1;
1640
+ this.applyCsi(match[1] || "", match[3]);
1641
+ return match[0].length;
1642
+ }
1643
+ if (/[P^_X]/.test(next)) {
1644
+ const bel = seq.indexOf("\x07", 2);
1645
+ const st = seq.indexOf("\x1B\\", 2);
1646
+ const end = bel >= 0 && (st < 0 || bel < st) ? bel + 1 : st >= 0 ? st + 2 : 0;
1647
+ return end;
1648
+ }
1649
+ return 2;
1650
+ }
1651
+ applyCsi(params, final) {
1652
+ const count = parseCount(params);
1653
+ this.ensureRow();
1654
+ if (final === "A") this.row = Math.max(0, this.row - count);
1655
+ else if (final === "B") this.row += count;
1656
+ else if (final === "C") this.col += count;
1657
+ else if (final === "D") this.col = Math.max(0, this.col - count);
1658
+ else if (final === "G") this.col = Math.max(0, count - 1);
1659
+ else if (final === "H" || final === "f") {
1660
+ const parts = String(params || "").split(";");
1661
+ this.row = Math.max(0, (Number(parts[0] || 1) || 1) - 1);
1662
+ this.col = Math.max(0, (Number(parts[1] || 1) || 1) - 1);
1663
+ } else if (final === "J") {
1664
+ const mode = Number(params || 0) || 0;
1665
+ if (mode === 2 || mode === 3) {
1666
+ this.lines = [[]];
1667
+ this.row = 0;
1668
+ this.col = 0;
1669
+ } else if (mode === 0) {
1670
+ this.lines[this.row] = this.lines[this.row].slice(0, this.col);
1671
+ this.lines.splice(this.row + 1);
1672
+ } else if (mode === 1) {
1673
+ for (let r = 0; r < this.row; r += 1) this.lines[r] = [];
1674
+ const line = this.lines[this.row];
1675
+ for (let c = 0; c <= Math.min(this.col, line.length - 1); c += 1) line[c] = " ";
1676
+ }
1677
+ } else if (final === "K") {
1678
+ const mode = Number(params || 0) || 0;
1679
+ const line = this.lines[this.row];
1680
+ if (mode === 2) this.lines[this.row] = [];
1681
+ else if (mode === 1) {
1682
+ for (let c = 0; c <= Math.min(this.col, line.length - 1); c += 1) line[c] = " ";
1683
+ } else {
1684
+ this.lines[this.row] = line.slice(0, this.col);
1685
+ }
1686
+ } else if (final === "s") {
1687
+ this.savedCursor = { row: this.row, col: this.col };
1688
+ } else if (final === "u") {
1689
+ if (this.savedCursor) {
1690
+ this.row = this.savedCursor.row;
1691
+ this.col = this.savedCursor.col;
1692
+ }
1693
+ }
1694
+ this.ensureRow();
1695
+ }
1696
+ };
1536
1697
  buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
1537
1698
  }
1538
1699
  });
@@ -1880,8 +2041,10 @@ var init_provider_cli_adapter = __esm({
1880
2041
  // ─── CLI Scripts (script-based parsing) ───
1881
2042
  cliScripts;
1882
2043
  runtimeSettings = {};
1883
- /** Full accumulated ANSI-stripped PTY output */
2044
+ /** Full accumulated rendered PTY transcript for parser/readback use */
1884
2045
  accumulatedBuffer = "";
2046
+ /** Stateful rendered transcript accumulator; raw debug remains in accumulatedRawBuffer. */
2047
+ transcriptAccumulator = new TerminalTranscriptAccumulator();
1885
2048
  /** Full accumulated raw PTY output (with ANSI) */
1886
2049
  accumulatedRawBuffer = "";
1887
2050
  /** Current visible terminal screen snapshot */
@@ -1947,6 +2110,7 @@ ${lastSnapshot}`;
1947
2110
  }
1948
2111
  resetTerminalScreen(rows, cols) {
1949
2112
  this.terminalScreen.reset(rows, cols);
2113
+ this.transcriptAccumulator.reset();
1950
2114
  this.lastScreenText = "";
1951
2115
  this.lastScreenSnapshot = "";
1952
2116
  this.lastScreenChangeAt = 0;
@@ -2205,6 +2369,7 @@ ${lastSnapshot}`;
2205
2369
  handleOutput(rawData) {
2206
2370
  this.terminalScreen.write(rawData);
2207
2371
  const cleanData = sanitizeTerminalText(rawData);
2372
+ const renderedTranscript = this.transcriptAccumulator.append(rawData);
2208
2373
  const now = Date.now();
2209
2374
  const shouldReadScreen = this.shouldReadTerminalScreenSnapshot(now);
2210
2375
  const screenText = shouldReadScreen ? this.readTerminalScreenText(now) : this.lastScreenText;
@@ -2245,13 +2410,14 @@ ${lastSnapshot}`;
2245
2410
  }
2246
2411
  }
2247
2412
  const prevRecentLen = this.recentOutputBuffer.length;
2248
- const prevAccumulatedLen = this.accumulatedBuffer.length;
2249
2413
  const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
2250
- this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
2251
- this.accumulatedBuffer = appendBoundedText(this.accumulatedBuffer, cleanData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
2414
+ const nextAccumulatedBuffer = renderedTranscript.length <= _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER ? renderedTranscript : renderedTranscript.slice(-_ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
2415
+ const nextRecentOutputBuffer = nextAccumulatedBuffer.slice(-_ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
2416
+ this.recentOutputBuffer = nextRecentOutputBuffer;
2417
+ this.accumulatedBuffer = nextAccumulatedBuffer;
2252
2418
  this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
2253
- const droppedRecent = this.recordBoundedAppendDrop(prevRecentLen, cleanData.length, this.recentOutputBuffer.length);
2254
- const droppedClean = this.recordBoundedAppendDrop(prevAccumulatedLen, cleanData.length, this.accumulatedBuffer.length);
2419
+ const droppedRecent = Math.max(0, prevRecentLen - this.recentOutputBuffer.length);
2420
+ const droppedClean = Math.max(0, renderedTranscript.length - this.accumulatedBuffer.length);
2255
2421
  const droppedRaw = this.recordBoundedAppendDrop(prevAccumulatedRawLen, rawData.length, this.accumulatedRawBuffer.length);
2256
2422
  this.recentOutputDroppedChars += droppedRecent;
2257
2423
  this.accumulatedBufferDroppedChars += droppedClean;
@@ -21201,6 +21367,15 @@ init_logger();
21201
21367
  function readNonEmptyString(value) {
21202
21368
  return typeof value === "string" && value.trim() ? value.trim() : "";
21203
21369
  }
21370
+ var MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
21371
+ "agent:generating_completed",
21372
+ "agent:waiting_approval",
21373
+ "agent:stopped",
21374
+ "monitor:long_generating"
21375
+ ]);
21376
+ function isMeshCoordinatorEvent(eventName) {
21377
+ return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
21378
+ }
21204
21379
  function formatCompletionMetadata(event) {
21205
21380
  const parts = [
21206
21381
  readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
@@ -21217,6 +21392,12 @@ function buildMeshSystemMessage(args) {
21217
21392
  if (args.event === "agent:waiting_approval") {
21218
21393
  return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
21219
21394
  }
21395
+ if (args.event === "agent:stopped") {
21396
+ return `[System] ${args.nodeLabel} has stopped${metadata}. Use mesh_read_chat once if you need to inspect its last output.`;
21397
+ }
21398
+ if (args.event === "monitor:long_generating") {
21399
+ return `[System] ${args.nodeLabel} has been generating for a long time${metadata}. Use mesh_read_chat once for a status check, but do not poll repeatedly.`;
21400
+ }
21220
21401
  return "";
21221
21402
  }
21222
21403
  function injectMeshSystemMessage(components, args) {
@@ -21242,7 +21423,7 @@ function injectMeshSystemMessage(components, args) {
21242
21423
  }
21243
21424
  function handleMeshForwardEvent(components, payload) {
21244
21425
  const eventName = readNonEmptyString(payload.event);
21245
- if (eventName !== "agent:generating_completed" && eventName !== "agent:waiting_approval") {
21426
+ if (!isMeshCoordinatorEvent(eventName)) {
21246
21427
  return { success: false, error: "unsupported mesh event" };
21247
21428
  }
21248
21429
  const meshId = readNonEmptyString(payload.meshId);
@@ -21263,7 +21444,7 @@ function handleMeshForwardEvent(components, payload) {
21263
21444
  }
21264
21445
  function setupMeshEventForwarding(components) {
21265
21446
  components.instanceManager.onEvent((event) => {
21266
- if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
21447
+ if (!isMeshCoordinatorEvent(event.event)) return;
21267
21448
  const instanceId = readNonEmptyString(event.instanceId);
21268
21449
  if (!instanceId) return;
21269
21450
  const sourceInstance = components.instanceManager.getInstance(instanceId);