@adhdev/daemon-core 0.9.76-rc.65 → 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
@@ -42,6 +42,7 @@ var init_repo_mesh_types = __esm({
42
42
  requireApprovalForDestructiveGit: true,
43
43
  dirtyWorkspaceBehavior: "warn",
44
44
  maxParallelTasks: 2,
45
+ spawnedSessionVisibility: "visible",
45
46
  sessionCleanupOnNodeRemove: "preserve"
46
47
  };
47
48
  }
@@ -471,6 +472,9 @@ function mergeMeshPolicy(base, patch) {
471
472
  if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
472
473
  policy.sessionCleanupOnNodeRemove = "preserve";
473
474
  }
475
+ if (!SPAWNED_SESSION_VISIBILITY_MODES.has(String(policy.spawnedSessionVisibility))) {
476
+ policy.spawnedSessionVisibility = "visible";
477
+ }
474
478
  return policy;
475
479
  }
476
480
  function listMeshes() {
@@ -575,7 +579,7 @@ function updateNode(meshId, nodeId, opts) {
575
579
  saveMeshConfig(config);
576
580
  return node;
577
581
  }
578
- var import_fs2, import_path2, import_crypto3, SESSION_CLEANUP_MODES;
582
+ var import_fs2, import_path2, import_crypto3, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES;
579
583
  var init_mesh_config = __esm({
580
584
  "src/config/mesh-config.ts"() {
581
585
  "use strict";
@@ -585,6 +589,7 @@ var init_mesh_config = __esm({
585
589
  init_config();
586
590
  init_repo_mesh_types();
587
591
  SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
592
+ SPAWNED_SESSION_VISIBILITY_MODES = /* @__PURE__ */ new Set(["visible", "hidden"]);
588
593
  }
589
594
  });
590
595
 
@@ -1335,13 +1340,25 @@ var init_pty_transport = __esm({
1335
1340
 
1336
1341
  // src/cli-adapters/provider-cli-shared.ts
1337
1342
  function stripAnsi(str) {
1338
- 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);
1339
1355
  }
1340
1356
  function stripTerminalNoise(str) {
1341
- 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");
1342
1358
  }
1343
1359
  function sanitizeTerminalText(str) {
1344
- return stripTerminalNoise(stripAnsi(str));
1360
+ const accumulator = new TerminalTranscriptAccumulator();
1361
+ return stripTerminalNoise(stripAnsi(accumulator.append(str)));
1345
1362
  }
1346
1363
  function listCliScriptNames(scripts) {
1347
1364
  if (!scripts) return [];
@@ -1520,7 +1537,7 @@ function normalizeCliProviderForRuntime(raw) {
1520
1537
  }
1521
1538
  };
1522
1539
  }
1523
- var os9, path14, import_child_process4, buildCliSpawnEnv;
1540
+ var os9, path14, import_child_process4, TerminalTranscriptAccumulator, buildCliSpawnEnv;
1524
1541
  var init_provider_cli_shared = __esm({
1525
1542
  "src/cli-adapters/provider-cli-shared.ts"() {
1526
1543
  "use strict";
@@ -1528,6 +1545,155 @@ var init_provider_cli_shared = __esm({
1528
1545
  path14 = __toESM(require("path"));
1529
1546
  import_child_process4 = require("child_process");
1530
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
+ };
1531
1697
  buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
1532
1698
  }
1533
1699
  });
@@ -1875,8 +2041,10 @@ var init_provider_cli_adapter = __esm({
1875
2041
  // ─── CLI Scripts (script-based parsing) ───
1876
2042
  cliScripts;
1877
2043
  runtimeSettings = {};
1878
- /** Full accumulated ANSI-stripped PTY output */
2044
+ /** Full accumulated rendered PTY transcript for parser/readback use */
1879
2045
  accumulatedBuffer = "";
2046
+ /** Stateful rendered transcript accumulator; raw debug remains in accumulatedRawBuffer. */
2047
+ transcriptAccumulator = new TerminalTranscriptAccumulator();
1880
2048
  /** Full accumulated raw PTY output (with ANSI) */
1881
2049
  accumulatedRawBuffer = "";
1882
2050
  /** Current visible terminal screen snapshot */
@@ -1942,6 +2110,7 @@ ${lastSnapshot}`;
1942
2110
  }
1943
2111
  resetTerminalScreen(rows, cols) {
1944
2112
  this.terminalScreen.reset(rows, cols);
2113
+ this.transcriptAccumulator.reset();
1945
2114
  this.lastScreenText = "";
1946
2115
  this.lastScreenSnapshot = "";
1947
2116
  this.lastScreenChangeAt = 0;
@@ -2200,6 +2369,7 @@ ${lastSnapshot}`;
2200
2369
  handleOutput(rawData) {
2201
2370
  this.terminalScreen.write(rawData);
2202
2371
  const cleanData = sanitizeTerminalText(rawData);
2372
+ const renderedTranscript = this.transcriptAccumulator.append(rawData);
2203
2373
  const now = Date.now();
2204
2374
  const shouldReadScreen = this.shouldReadTerminalScreenSnapshot(now);
2205
2375
  const screenText = shouldReadScreen ? this.readTerminalScreenText(now) : this.lastScreenText;
@@ -2240,13 +2410,14 @@ ${lastSnapshot}`;
2240
2410
  }
2241
2411
  }
2242
2412
  const prevRecentLen = this.recentOutputBuffer.length;
2243
- const prevAccumulatedLen = this.accumulatedBuffer.length;
2244
2413
  const prevAccumulatedRawLen = this.accumulatedRawBuffer.length;
2245
- this.recentOutputBuffer = appendBoundedText(this.recentOutputBuffer, cleanData, _ProviderCliAdapter.MAX_RECENT_OUTPUT_BUFFER);
2246
- 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;
2247
2418
  this.accumulatedRawBuffer = appendBoundedText(this.accumulatedRawBuffer, rawData, _ProviderCliAdapter.MAX_ACCUMULATED_BUFFER);
2248
- const droppedRecent = this.recordBoundedAppendDrop(prevRecentLen, cleanData.length, this.recentOutputBuffer.length);
2249
- 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);
2250
2421
  const droppedRaw = this.recordBoundedAppendDrop(prevAccumulatedRawLen, rawData.length, this.accumulatedRawBuffer.length);
2251
2422
  this.recentOutputDroppedChars += droppedRecent;
2252
2423
  this.accumulatedBufferDroppedChars += droppedClean;
@@ -21196,6 +21367,15 @@ init_logger();
21196
21367
  function readNonEmptyString(value) {
21197
21368
  return typeof value === "string" && value.trim() ? value.trim() : "";
21198
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
+ }
21199
21379
  function formatCompletionMetadata(event) {
21200
21380
  const parts = [
21201
21381
  readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
@@ -21212,6 +21392,12 @@ function buildMeshSystemMessage(args) {
21212
21392
  if (args.event === "agent:waiting_approval") {
21213
21393
  return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
21214
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
+ }
21215
21401
  return "";
21216
21402
  }
21217
21403
  function injectMeshSystemMessage(components, args) {
@@ -21237,7 +21423,7 @@ function injectMeshSystemMessage(components, args) {
21237
21423
  }
21238
21424
  function handleMeshForwardEvent(components, payload) {
21239
21425
  const eventName = readNonEmptyString(payload.event);
21240
- if (eventName !== "agent:generating_completed" && eventName !== "agent:waiting_approval") {
21426
+ if (!isMeshCoordinatorEvent(eventName)) {
21241
21427
  return { success: false, error: "unsupported mesh event" };
21242
21428
  }
21243
21429
  const meshId = readNonEmptyString(payload.meshId);
@@ -21258,7 +21444,7 @@ function handleMeshForwardEvent(components, payload) {
21258
21444
  }
21259
21445
  function setupMeshEventForwarding(components) {
21260
21446
  components.instanceManager.onEvent((event) => {
21261
- if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
21447
+ if (!isMeshCoordinatorEvent(event.event)) return;
21262
21448
  const instanceId = readNonEmptyString(event.instanceId);
21263
21449
  if (!instanceId) return;
21264
21450
  const sourceInstance = components.instanceManager.getInstance(instanceId);