@adhdev/daemon-standalone 0.8.84 → 0.8.85

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.
package/dist/index.js CHANGED
@@ -766,7 +766,7 @@ function Ec(s15, t) {
766
766
  function Tc(s15) {
767
767
  return s15.keyCode === 16 || s15.keyCode === 17 || s15.keyCode === 18;
768
768
  }
769
- var zs, Rl, Ll, M, S, Gs, mi, $s, _i, er, tr, ir, we, De, rt, q, js, Hn, Fn, F, rr, ge, Zs, xt, nr, H, sr, Js, Be, wt, nt, ae, Dt, ce, Qs, or, Re, lr, Wn, Bl, Un, bi, ar, Rt, cr, ro, so, At, lo, ao, oo, ur, zn, Wl, dt, hr, dr, Ee, D, ye, fe, kt, G, Ct, zl, mr, Gl, fo, $l, $, Mt, $n, po, br, Vn, gi, qn, Yn, Vl, Pt, ql, Yl, _r, v, jn, gr, Si, Eu, Tu, Ot, Ei, Bt, Ti, Sr, Iu, yu, vr, Nt, yr, xr, Ii, Zl, vo, go, Jl, Ql, ea, ta, Tr, Ir, bo, ia, $e, Ve, xe, So, ra, Xn, wr, Te, Zn, Dr, na, xu, Fe, st, sa, oa, Eo, la, wu, Du, Ru, Lu, ot, aa, yi, Jn, To, Io, yo, Qn, Rr, es, ua, ha, da, fa, ft, wo, Lr, qe, xi, Do, ma, ts, Ye, kr, ba, Ar, va, _e, Cr, Bh, be, Nh, Fh, Hh, Oo, Wh, Uh, No, Kh, zh, ss, os, wa, mt, Mr, Di, pt, Gh, Y, Da, ls, Wt, He, Q, Pr, lt, Uo, Or, cs, Ri, Br, Nr, Fr, Ca, Ut, Kt, Wr, Ur, Ma, Ko, zo, us, zr, hs, ds, Kr, zt, Gt, Gr, We, at, Li, bt, b, Ai, fs, $t, ue, he, de, J, ps, j, U, z, ve, $r, Vr, ct, Vt, Yr, ms, _s, Le, jr, jo, ki, Xr, Na, Yt, jt, Zr, bs, vs, Jr, gs, Qr, Xt, en, tn, Mi, Pi, Oi, Ss, Fa, Zo, Zt, Wa, Ua, Es, Bi, Ts, rn, Is, ys, Jt, nn, Qt, xs, on, Ds, Ya, ja, Xa, Za, Ja, ei, Hi, Wi, re, St, Ki, tl, il, Ui, Qa, ti, Rs, ln, ec, tc, ii, ic, zi, B, X, an, Ls, Ze, un, cn, ne, Je, cl, $i, hn, ks, Cs, ni, si, nc, dn, ul, hl, li, dl, Ps, fl, ai, Os, ac, se, fn, Ae, pn, Vi, uc, ci, qi, mn, pe, Yi, _n, ji, Xi, Fs, ke, hc, bn, dc, fc, mc, ut, _l, vl, gl, vn, Zi, _c, El, bc, gn, ui, Tl, Sn, gc, ee, En, Us, yl, Tn, Ks, Sc, In, xl, wl, Tt, hi, yn, xn, wn, Ji, Dn, Rn, Ln, Ic, Ue, Dl;
769
+ var zs, Rl, Ll, M, S, Gs, mi, $s, _i, er, tr, ir, we, De, rt, q, js, Hn, Fn, F, rr, ge, Zs, xt, nr, H, sr, Js, Be, wt, nt, ae, Dt, ce, Qs, or, Re, lr, Wn, Bl, Un, bi, ar, Rt, cr, ro, so, At, lo, ao, oo, ur, zn, Wl, dt, hr, dr, Ee, D, ye, fe, kt, G, Ct, zl, mr, Gl, fo, $l, $, Mt, $n, po, br, Vn, gi, qn, Yn, Vl, Pt, ql, Yl, _r, v, jn, gr, Si, Eu, Tu, Ot, Ei, Bt, Ti, Sr, Iu, yu, vr, Nt, yr, xr, Ii, Zl, vo, go, Jl, Ql, ea, ta, Tr, Ir, bo, ia, $e, Ve, xe, So, ra, Xn, wr, Te, Zn, Dr, na, xu, Fe, st, sa, oa, Eo, la, wu, Du, Ru, Lu, ot, aa, yi, Jn, To, Io, yo, Qn, Rr, es, ua, ha, da, fa, ft, wo, Lr, qe, xi, Do, ma, ts, Ye, kr, ba, Ar, va, _e, Cr, Bh, be, Nh, Fh, Hh, Oo, Wh, Uh, No, Kh, zh, ss, os, wa, mt, Mr, Di, pt, Gh, Y, Da, ls, Wt, He, Q, Pr, lt, Uo, Or, cs, Ri, Br, Nr, Fr, Ca, Ut, Kt, Wr, Ur, Ma, Ko, zo, us, zr, hs, ds, Kr, zt, Gt, Gr, We, at, Li, bt, b, Ai, fs2, $t, ue, he, de, J, ps, j, U, z, ve, $r, Vr, ct, Vt, Yr, ms, _s, Le, jr, jo, ki, Xr, Na, Yt, jt, Zr, bs, vs, Jr, gs, Qr, Xt, en, tn, Mi, Pi, Oi, Ss, Fa, Zo, Zt, Wa, Ua, Es, Bi, Ts, rn, Is, ys, Jt, nn, Qt, xs, on, Ds, Ya, ja, Xa, Za, Ja, ei, Hi, Wi, re, St, Ki, tl, il, Ui, Qa, ti, Rs, ln, ec, tc, ii, ic, zi, B, X, an, Ls, Ze, un, cn, ne, Je, cl, $i, hn, ks, Cs, ni, si, nc, dn, ul, hl, li, dl, Ps, fl, ai, Os, ac, se, fn, Ae, pn, Vi, uc, ci, qi, mn, pe, Yi, _n, ji, Xi, Fs, ke, hc, bn, dc, fc, mc, ut, _l, vl, gl, vn, Zi, _c, El, bc, gn, ui, Tl, Sn, gc, ee, En, Us, yl, Tn, Ks, Sc, In, xl, wl, Tt, hi, yn, xn, wn, Ji, Dn, Rn, Ln, Ic, Ue, Dl;
770
770
  var init_xterm = __esm({
771
771
  "../../node_modules/@xterm/xterm/lib/xterm.mjs"() {
772
772
  "use strict";
@@ -4041,7 +4041,7 @@ ${h.join(`
4041
4041
  ((E) => (E.NUL = "\0", E.SOH = "", E.STX = "", E.ETX = "", E.EOT = "", E.ENQ = "", E.ACK = "", E.BEL = "\x07", E.BS = "\b", E.HT = " ", E.LF = `
4042
4042
  `, E.VT = "\v", E.FF = "\f", E.CR = "\r", E.SO = "", E.SI = "", E.DLE = "", E.DC1 = "", E.DC2 = "", E.DC3 = "", E.DC4 = "", E.NAK = "", E.SYN = "", E.ETB = "", E.CAN = "", E.EM = "", E.SUB = "", E.ESC = "\x1B", E.FS = "", E.GS = "", E.RS = "", E.US = "", E.SP = " ", E.DEL = "\x7F"))(b ||= {});
4043
4043
  ((g) => (g.PAD = "\x80", g.HOP = "\x81", g.BPH = "\x82", g.NBH = "\x83", g.IND = "\x84", g.NEL = "\x85", g.SSA = "\x86", g.ESA = "\x87", g.HTS = "\x88", g.HTJ = "\x89", g.VTS = "\x8A", g.PLD = "\x8B", g.PLU = "\x8C", g.RI = "\x8D", g.SS2 = "\x8E", g.SS3 = "\x8F", g.DCS = "\x90", g.PU1 = "\x91", g.PU2 = "\x92", g.STS = "\x93", g.CCH = "\x94", g.MW = "\x95", g.SPA = "\x96", g.EPA = "\x97", g.SOS = "\x98", g.SGCI = "\x99", g.SCI = "\x9A", g.CSI = "\x9B", g.ST = "\x9C", g.OSC = "\x9D", g.PM = "\x9E", g.APC = "\x9F"))(Ai ||= {});
4044
- ((t) => t.ST = `${b.ESC}\\`)(fs ||= {});
4044
+ ((t) => t.ST = `${b.ESC}\\`)(fs2 ||= {});
4045
4045
  $t = class {
4046
4046
  constructor(t, e, i, r, n, o) {
4047
4047
  this._textarea = t;
@@ -8470,7 +8470,7 @@ ${h.join(`
8470
8470
  switch (i.type) {
8471
8471
  case 0:
8472
8472
  let o = U.toColorRGB(r === "ansi" ? this._themeService.colors.ansi[i.index] : this._themeService.colors[r]);
8473
- this.coreService.triggerDataEvent(`${b.ESC}]${n};${ml(o)}${fs.ST}`);
8473
+ this.coreService.triggerDataEvent(`${b.ESC}]${n};${ml(o)}${fs2.ST}`);
8474
8474
  break;
8475
8475
  case 1:
8476
8476
  if (r === "ansi") this._themeService.modifyColors((l) => l.ansi[i.index] = j.toColor(...i.color));
@@ -9573,7 +9573,7 @@ var require_dist = __commonJS({
9573
9573
  }
9574
9574
  };
9575
9575
  var os6 = __toESM2(require("os"));
9576
- var path22 = __toESM2(require("path"));
9576
+ var path23 = __toESM2(require("path"));
9577
9577
  var net3 = __toESM2(require("net"));
9578
9578
  var import_crypto22 = require("crypto");
9579
9579
  function getDefaultSessionHostEndpoint2(appName = "adhdev") {
@@ -9585,7 +9585,7 @@ var require_dist = __commonJS({
9585
9585
  }
9586
9586
  return {
9587
9587
  kind: "unix",
9588
- path: path22.join(os6.tmpdir(), `${appName}-session-host.sock`)
9588
+ path: path23.join(os6.tmpdir(), `${appName}-session-host.sock`)
9589
9589
  };
9590
9590
  }
9591
9591
  function serializeEnvelope3(envelope) {
@@ -9756,14 +9756,14 @@ var require_dist = __commonJS({
9756
9756
  function ensureNodePtySpawnHelperPermissions(logFn) {
9757
9757
  if (os22.platform() === "win32") return;
9758
9758
  try {
9759
- const fs4 = require("fs");
9759
+ const fs5 = require("fs");
9760
9760
  const ptyDir = path32.resolve(path32.dirname(require.resolve("node-pty")), "..");
9761
9761
  const platformArch = `${os22.platform()}-${os22.arch()}`;
9762
9762
  const helper = path32.join(ptyDir, "prebuilds", platformArch, "spawn-helper");
9763
- if (fs4.existsSync(helper)) {
9764
- const stat4 = fs4.statSync(helper);
9763
+ if (fs5.existsSync(helper)) {
9764
+ const stat4 = fs5.statSync(helper);
9765
9765
  if (!(stat4.mode & 73)) {
9766
- fs4.chmodSync(helper, stat4.mode | 493);
9766
+ fs5.chmodSync(helper, stat4.mode | 493);
9767
9767
  logFn?.(`Fixed spawn-helper permissions: ${helper}`);
9768
9768
  }
9769
9769
  }
@@ -26823,9 +26823,9 @@ var init_handler = __esm({
26823
26823
  if (this.fsw.closed) {
26824
26824
  return;
26825
26825
  }
26826
- const dirname4 = sp.dirname(file2);
26826
+ const dirname5 = sp.dirname(file2);
26827
26827
  const basename3 = sp.basename(file2);
26828
- const parent = this.fsw._getWatchedDir(dirname4);
26828
+ const parent = this.fsw._getWatchedDir(dirname5);
26829
26829
  let prevStats = stats;
26830
26830
  if (parent.has(basename3))
26831
26831
  return;
@@ -26852,7 +26852,7 @@ var init_handler = __esm({
26852
26852
  prevStats = newStats2;
26853
26853
  }
26854
26854
  } catch (error48) {
26855
- this.fsw._remove(dirname4, basename3);
26855
+ this.fsw._remove(dirname5, basename3);
26856
26856
  }
26857
26857
  } else if (parent.has(basename3)) {
26858
26858
  const at2 = newStats.atimeMs;
@@ -30347,6 +30347,58 @@ var require_dist2 = __commonJS({
30347
30347
  `[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
30348
30348
  );
30349
30349
  }
30350
+ clearStaleIdleResponseGuard(reason) {
30351
+ const screenText = this.terminalScreen.getText() || "";
30352
+ const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
30353
+ const blockingModal = this.activeModal || this.getStartupConfirmationModal(screenText);
30354
+ if (!this.isWaitingForResponse || this.currentStatus !== "idle" || !visibleIdlePrompt || !!blockingModal) {
30355
+ return false;
30356
+ }
30357
+ if (this.responseTimeout) {
30358
+ clearTimeout(this.responseTimeout);
30359
+ this.responseTimeout = null;
30360
+ }
30361
+ if (this.idleTimeout) {
30362
+ clearTimeout(this.idleTimeout);
30363
+ this.idleTimeout = null;
30364
+ }
30365
+ if (this.approvalExitTimeout) {
30366
+ clearTimeout(this.approvalExitTimeout);
30367
+ this.approvalExitTimeout = null;
30368
+ }
30369
+ if (this.finishRetryTimer) {
30370
+ clearTimeout(this.finishRetryTimer);
30371
+ this.finishRetryTimer = null;
30372
+ }
30373
+ this.clearIdleFinishCandidate(reason);
30374
+ this.responseBuffer = "";
30375
+ this.isWaitingForResponse = false;
30376
+ this.responseSettleIgnoreUntil = 0;
30377
+ this.submitRetryUsed = false;
30378
+ this.submitRetryPromptSnippet = "";
30379
+ this.finishRetryCount = 0;
30380
+ this.currentTurnScope = null;
30381
+ this.activeModal = null;
30382
+ this.recordTrace("stale_idle_response_cleared", {
30383
+ reason,
30384
+ screenText: summarizeCliTraceText(screenText, 240)
30385
+ });
30386
+ return true;
30387
+ }
30388
+ hasMeaningfulResponseBuffer(promptSnippet) {
30389
+ const raw = String(this.responseBuffer || "").trim();
30390
+ if (!raw) return false;
30391
+ const normalizedPrompt = compactPromptText(promptSnippet);
30392
+ if (!normalizedPrompt) return true;
30393
+ const normalizedBuffer = compactPromptText(raw);
30394
+ if (!normalizedBuffer) return false;
30395
+ if (normalizedBuffer === normalizedPrompt) return false;
30396
+ if (normalizedBuffer.startsWith(normalizedPrompt)) {
30397
+ const remainder = normalizedBuffer.slice(normalizedPrompt.length).replace(/[─═\-]+/g, "").replace(/⏵⏵accepteditson\([^)]*\)/gi, "").replace(/accepteditson\([^)]*\)/gi, "").replace(/(?:◐|◑|◒|◓|◔|◕|◉|●|·)?(?:x?high|medium|low|max)·?\/effort/gi, "").replace(/updateavailable!run:[a-z0-9:._\-/]+/gi, "").replace(/esctointerrupt/gi, "").replace(/❯/g, "").replace(/^[\s\-–—:;,.!/?]+/, "").trim();
30398
+ return remainder.length > 0;
30399
+ }
30400
+ return true;
30401
+ }
30350
30402
  evaluateSettled() {
30351
30403
  const now = Date.now();
30352
30404
  if (this.submitPendingUntil > now || this.responseSettleIgnoreUntil > now) {
@@ -30379,7 +30431,11 @@ var require_dist2 = __commonJS({
30379
30431
  scope: this.currentTurnScope,
30380
30432
  lastOutputAt: this.lastOutputAt
30381
30433
  }) : [];
30434
+ if (this.maybeCommitVisibleIdleTranscript(parsedTranscript)) {
30435
+ return;
30436
+ }
30382
30437
  const lastParsedAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
30438
+ const normalizedPromptSnippet = normalizePromptText(this.submitRetryPromptSnippet || this.currentTurnScope?.prompt || "");
30383
30439
  this.recordTrace("settled", {
30384
30440
  tail: summarizeCliTraceText(tail, 500),
30385
30441
  screenText: summarizeCliTraceText(screenText, 1200),
@@ -30397,6 +30453,24 @@ var require_dist2 = __commonJS({
30397
30453
  scope: this.currentTurnScope
30398
30454
  })
30399
30455
  });
30456
+ if (this.currentTurnScope && !lastParsedAssistant && !this.submitRetryUsed && this.ptyProcess && this.currentStatus !== "waiting_approval" && promptLikelyVisible(screenText, normalizedPromptSnippet) && !this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) {
30457
+ this.submitRetryUsed = true;
30458
+ this.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
30459
+ LOG2.info("CLI", `[${this.cliType}] Retrying submit key from settled parser (no assistant yet)`);
30460
+ this.recordTrace("submit_write", {
30461
+ mode: "settled_retry",
30462
+ sendKey: this.sendKey,
30463
+ screenText: summarizeCliTraceText(screenText, 500)
30464
+ });
30465
+ this.ptyProcess.write(this.sendKey);
30466
+ if (this.settleTimer) clearTimeout(this.settleTimer);
30467
+ this.settleTimer = setTimeout(() => {
30468
+ this.settleTimer = null;
30469
+ this.settledBuffer = this.recentOutputBuffer;
30470
+ this.evaluateSettled();
30471
+ }, this.timeouts.outputSettle + 150);
30472
+ return;
30473
+ }
30400
30474
  if (this.currentTurnScope && !lastParsedAssistant) {
30401
30475
  LOG2.info(
30402
30476
  "CLI",
@@ -30439,7 +30513,15 @@ var require_dist2 = __commonJS({
30439
30513
  }
30440
30514
  const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
30441
30515
  const statusActivityHoldMs = this.getStatusActivityHoldMs();
30442
- const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity;
30516
+ const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
30517
+ const visibleAssistantCandidate = this.looksLikeVisibleAssistantCandidate(screenText);
30518
+ if (this.currentTurnScope && this.cliType === "claude-cli") {
30519
+ LOG2.info(
30520
+ "CLI",
30521
+ `[${this.cliType}] settled diagnostics prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} scriptStatus=${String(scriptStatus || "")} parsedStatus=${String(parsedTranscript?.status || "")} parsedMsgCount=${parsedMessages.length} lastParsedAssistant=${JSON.stringify(summarizeCliTraceText(lastParsedAssistant?.content || "", 120)).slice(0, 160)} visibleIdlePrompt=${String(visibleIdlePrompt)} visibleAssistantCandidate=${String(visibleAssistantCandidate)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 160)).slice(0, 220)} screen=${JSON.stringify(summarizeCliTraceText(screenText, 160)).slice(0, 220)}`
30522
+ );
30523
+ }
30524
+ const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity && !(visibleIdlePrompt && visibleAssistantCandidate);
30443
30525
  if (shouldHoldGenerating) {
30444
30526
  this.clearIdleFinishCandidate("hold_generating_recent_activity");
30445
30527
  this.setStatus("generating", "recent_activity_hold");
@@ -30470,8 +30552,8 @@ var require_dist2 = __commonJS({
30470
30552
  if (scriptStatus === "waiting_approval") {
30471
30553
  this.clearIdleFinishCandidate("waiting_approval");
30472
30554
  const inCooldown = this.lastApprovalResolvedAt && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
30473
- const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
30474
- if ((inCooldown || visibleIdlePrompt) && !modal) {
30555
+ const visibleIdlePrompt2 = this.looksLikeVisibleIdlePrompt(screenText);
30556
+ if ((inCooldown || visibleIdlePrompt2) && !modal) {
30475
30557
  if (this.approvalExitTimeout) {
30476
30558
  clearTimeout(this.approvalExitTimeout);
30477
30559
  this.approvalExitTimeout = null;
@@ -30543,7 +30625,7 @@ var require_dist2 = __commonJS({
30543
30625
  this.lastApprovalResolvedAt = Date.now();
30544
30626
  }
30545
30627
  if (this.isWaitingForResponse) {
30546
- const visibleIdlePrompt = this.looksLikeVisibleIdlePrompt(screenText);
30628
+ const visibleIdlePrompt2 = this.looksLikeVisibleIdlePrompt(screenText);
30547
30629
  const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
30548
30630
  const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
30549
30631
  const hasAssistantTurn = !!lastParsedAssistant;
@@ -30551,12 +30633,12 @@ var require_dist2 = __commonJS({
30551
30633
  const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
30552
30634
  const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
30553
30635
  const idleStableThresholdMs = idleFinishConfirmMs;
30554
- const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
30636
+ const idleReady = visibleIdlePrompt2 && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
30555
30637
  const candidate = this.idleFinishCandidate;
30556
30638
  const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
30557
30639
  const canFinishImmediately = idleReady && candidateQuiet;
30558
30640
  this.recordTrace("idle_decision", {
30559
- visibleIdlePrompt,
30641
+ visibleIdlePrompt: visibleIdlePrompt2,
30560
30642
  quietForMs,
30561
30643
  screenStableMs,
30562
30644
  hasAssistantTurn,
@@ -30676,6 +30758,70 @@ var require_dist2 = __commonJS({
30676
30758
  this.setStatus("idle", "response_finished");
30677
30759
  this.onStatusChange?.();
30678
30760
  }
30761
+ maybeCommitVisibleIdleTranscript(parsed, options) {
30762
+ const allowImmediateScriptIdleCommit = this.provider.allowInputDuringGeneration === true;
30763
+ if (!allowImmediateScriptIdleCommit) return false;
30764
+ if (!parsed || !Array.isArray(parsed.messages) || parsed.status !== "idle" || !this.isWaitingForResponse || !this.currentTurnScope || this.activeModal || parsed.activeModal) {
30765
+ return false;
30766
+ }
30767
+ if (options?.requireVisibleAssistantCandidate) {
30768
+ const candidateText = options.screenText || this.terminalScreen.getText() || "";
30769
+ if (!this.looksLikeVisibleAssistantCandidate(candidateText)) {
30770
+ return false;
30771
+ }
30772
+ }
30773
+ const hydratedForIdleCommit = normalizeCliParsedMessages(parsed.messages, {
30774
+ committedMessages: this.committedMessages,
30775
+ scope: this.currentTurnScope,
30776
+ lastOutputAt: this.lastOutputAt
30777
+ });
30778
+ const visibleAssistant = [...hydratedForIdleCommit].reverse().find((message) => message.role === "assistant" && message.content.trim());
30779
+ if (!visibleAssistant) return false;
30780
+ this.committedMessages = hydratedForIdleCommit;
30781
+ const promptForTrim = this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages);
30782
+ if (promptForTrim) {
30783
+ const lastAssistantForTrim = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
30784
+ if (lastAssistantForTrim) {
30785
+ lastAssistantForTrim.content = trimPromptEchoPrefix(lastAssistantForTrim.content, promptForTrim);
30786
+ }
30787
+ }
30788
+ if (this.responseTimeout) {
30789
+ clearTimeout(this.responseTimeout);
30790
+ this.responseTimeout = null;
30791
+ }
30792
+ if (this.idleTimeout) {
30793
+ clearTimeout(this.idleTimeout);
30794
+ this.idleTimeout = null;
30795
+ }
30796
+ if (this.approvalExitTimeout) {
30797
+ clearTimeout(this.approvalExitTimeout);
30798
+ this.approvalExitTimeout = null;
30799
+ }
30800
+ if (this.submitRetryTimer) {
30801
+ clearTimeout(this.submitRetryTimer);
30802
+ this.submitRetryTimer = null;
30803
+ }
30804
+ if (this.finishRetryTimer) {
30805
+ clearTimeout(this.finishRetryTimer);
30806
+ this.finishRetryTimer = null;
30807
+ }
30808
+ this.syncMessageViews();
30809
+ this.responseBuffer = "";
30810
+ this.isWaitingForResponse = false;
30811
+ this.responseSettleIgnoreUntil = 0;
30812
+ this.submitRetryUsed = false;
30813
+ this.submitRetryPromptSnippet = "";
30814
+ this.finishRetryCount = 0;
30815
+ this.currentTurnScope = null;
30816
+ this.activeModal = null;
30817
+ this.setStatus("idle", "script_idle_commit");
30818
+ this.onStatusChange?.();
30819
+ this.recordTrace("script_idle_commit", {
30820
+ messageCount: this.committedMessages.length,
30821
+ lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
30822
+ });
30823
+ return true;
30824
+ }
30679
30825
  commitCurrentTranscript() {
30680
30826
  const parsed = this.parseCurrentTranscript(
30681
30827
  this.committedMessages,
@@ -30697,6 +30843,12 @@ var require_dist2 = __commonJS({
30697
30843
  }
30698
30844
  this.syncMessageViews();
30699
30845
  const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
30846
+ if (this.currentTurnScope) {
30847
+ LOG2.info(
30848
+ "CLI",
30849
+ `[${this.cliType}] commitCurrentTranscript committedMessages=${this.committedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || "", 220)).slice(0, 260)}`
30850
+ );
30851
+ }
30700
30852
  this.recordTrace("commit_transcript", {
30701
30853
  parsedStatus: parsed.status || null,
30702
30854
  messageCount: this.committedMessages.length,
@@ -30716,11 +30868,18 @@ var require_dist2 = __commonJS({
30716
30868
  `[${this.cliType}] Commit without assistant turn: prompt=${JSON.stringify(this.currentTurnScope.prompt).slice(0, 140)} responseBuffer=${JSON.stringify(summarizeCliTraceText(this.responseBuffer, 220)).slice(0, 260)} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"} scriptsPath=${this.providerResolutionMeta.scriptsPath || "-"}`
30717
30869
  );
30718
30870
  }
30871
+ const hasAssistant = !!lastAssistant;
30719
30872
  return {
30720
- hasAssistant: !!lastAssistant,
30873
+ hasAssistant,
30721
30874
  assistantContent: lastAssistant?.content || ""
30722
30875
  };
30723
30876
  }
30877
+ if (this.currentTurnScope) {
30878
+ LOG2.info(
30879
+ "CLI",
30880
+ `[${this.cliType}] commitCurrentTranscript parsed.messages=none responseBufferLen=${this.responseBuffer.length} accumulatedBufferLen=${this.accumulatedBuffer.length} parsedStatus=${parsed?.status || "-"} providerDir=${this.providerResolutionMeta.providerDir || "-"} scriptDir=${this.providerResolutionMeta.scriptDir || "-"}`
30881
+ );
30882
+ }
30724
30883
  return {
30725
30884
  hasAssistant: false,
30726
30885
  assistantContent: ""
@@ -30806,19 +30965,25 @@ var require_dist2 = __commonJS({
30806
30965
  this.currentTurnScope,
30807
30966
  screenText
30808
30967
  );
30809
- const shouldPreferCommittedMessages = !this.currentTurnScope && this.currentStatus === "idle" && !this.activeModal;
30968
+ if (this.maybeCommitVisibleIdleTranscript(parsed)) {
30969
+ return this.getScriptParsedStatus();
30970
+ }
30971
+ const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
30810
30972
  let result;
30811
30973
  if (parsed && Array.isArray(parsed.messages)) {
30812
- const hydratedMessages = shouldPreferCommittedMessages ? this.committedMessages.map((message, index) => buildChatMessage({
30813
- ...message,
30814
- id: message.id || `msg_${index}`,
30815
- index: typeof message.index === "number" ? message.index : index,
30816
- receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
30817
- })) : hydrateCliParsedMessages(parsed.messages, {
30974
+ const parsedHydratedMessages = hydrateCliParsedMessages(parsed.messages, {
30818
30975
  committedMessages: this.committedMessages,
30819
30976
  scope: this.currentTurnScope,
30820
30977
  lastOutputAt: this.lastOutputAt
30821
30978
  });
30979
+ const committedHydratedMessages = this.committedMessages.map((message, index) => buildChatMessage({
30980
+ ...message,
30981
+ id: message.id || `msg_${index}`,
30982
+ index: typeof message.index === "number" ? message.index : index,
30983
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
30984
+ }));
30985
+ const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && committedHydratedMessages.length > parsedHydratedMessages.length;
30986
+ const hydratedMessages = shouldPreferCommittedMessages || shouldPreferCommittedHistoryReplay ? committedHydratedMessages : parsedHydratedMessages;
30822
30987
  result = {
30823
30988
  id: parsed.id || "cli_session",
30824
30989
  status: parsed.status || this.currentStatus,
@@ -30842,6 +31007,23 @@ var require_dist2 = __commonJS({
30842
31007
  activeModal: this.activeModal
30843
31008
  };
30844
31009
  }
31010
+ const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
31011
+ const shouldClampStaleGeneratingToIdle = result?.status === "generating" && this.currentStatus === "idle" && !this.currentTurnScope && !result?.activeModal && hasVisibleAssistantMessage;
31012
+ if (shouldClampStaleGeneratingToIdle) {
31013
+ result = {
31014
+ ...result,
31015
+ status: "idle",
31016
+ messages: Array.isArray(result.messages) ? result.messages.map((message) => {
31017
+ if (message?.role !== "assistant" || !message?.meta?.streaming) return message;
31018
+ const nextMeta = { ...message.meta || {} };
31019
+ delete nextMeta.streaming;
31020
+ return {
31021
+ ...message,
31022
+ ...Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: void 0 }
31023
+ };
31024
+ }) : result.messages
31025
+ };
31026
+ }
30845
31027
  this.parsedStatusCache = {
30846
31028
  committedMessagesRef: this.committedMessages,
30847
31029
  responseBuffer: this.responseBuffer,
@@ -30974,9 +31156,27 @@ ${data.message || ""}`.trim();
30974
31156
  }
30975
31157
  }
30976
31158
  if (!this.ready) throw new Error(`${this.cliName} not ready (status: ${this.currentStatus})`);
30977
- if (this.isWaitingForResponse && !allowInputDuringGeneration) {
31159
+ const parsedStatusBeforeSend = !allowInputDuringGeneration ? (() => {
31160
+ try {
31161
+ return this.getScriptParsedStatus?.() || null;
31162
+ } catch {
31163
+ return null;
31164
+ }
31165
+ })() : null;
31166
+ const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
31167
+ const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages) ? parsedStatusBeforeSend.messages.filter((message) => message && (message.role === "user" || message.role === "assistant")) : [];
31168
+ const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration && parsedSessionStatus === "idle" && parsedMessagesBeforeSend.length > this.committedMessages.length && parsedMessagesBeforeSend.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
31169
+ if (shouldCommitParsedIdleBeforeSend) {
31170
+ this.commitCurrentTranscript();
31171
+ }
31172
+ if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
30978
31173
  throw new Error(`${this.cliName} is still processing the previous prompt`);
30979
31174
  }
31175
+ if (this.isWaitingForResponse && !allowInputDuringGeneration) {
31176
+ if (!this.clearStaleIdleResponseGuard("send_message_guard")) {
31177
+ throw new Error(`${this.cliName} is still processing the previous prompt`);
31178
+ }
31179
+ }
30980
31180
  const blockingModal = this.activeModal || this.getStartupConfirmationModal(this.terminalScreen.getText() || "");
30981
31181
  if (blockingModal || this.currentStatus === "waiting_approval") {
30982
31182
  throw new Error(`${this.cliName} is awaiting confirmation before it can accept a prompt`);
@@ -31056,7 +31256,7 @@ ${data.message || ""}`.trim();
31056
31256
  this.submitRetryTimer = null;
31057
31257
  if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
31058
31258
  if (this.currentStatus === "waiting_approval") return;
31059
- if ((this.responseBuffer || "").trim()) return;
31259
+ if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
31060
31260
  const screenText2 = this.terminalScreen.getText();
31061
31261
  if (!promptLikelyVisible(screenText2, normalizedPromptSnippet)) return;
31062
31262
  if (/Esc to interrupt|Do you want to proceed|This command requires approval|Allow Codex to|Approve and run now|Always approve this session|Running…|Running\.\.\./i.test(screenText2)) return;
@@ -31093,7 +31293,7 @@ ${data.message || ""}`.trim();
31093
31293
  this.submitRetryTimer = null;
31094
31294
  if (!this.ptyProcess || !this.isWaitingForResponse || this.submitRetryUsed) return;
31095
31295
  if (this.currentStatus === "waiting_approval") return;
31096
- if ((this.responseBuffer || "").trim()) return;
31296
+ if (this.hasMeaningfulResponseBuffer(normalizedPromptSnippet)) return;
31097
31297
  const screenText = this.terminalScreen.getText();
31098
31298
  if (!promptLikelyVisible(screenText, normalizedPromptSnippet)) return;
31099
31299
  LOG2.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
@@ -31627,7 +31827,7 @@ ${data.message || ""}`.trim();
31627
31827
  });
31628
31828
  module2.exports = __toCommonJS2(index_exports);
31629
31829
  init_config();
31630
- var fs4 = __toESM2(require("fs"));
31830
+ var fs5 = __toESM2(require("fs"));
31631
31831
  var os6 = __toESM2(require("os"));
31632
31832
  var path5 = __toESM2(require("path"));
31633
31833
  var import_crypto22 = require("crypto");
@@ -31641,8 +31841,8 @@ ${data.message || ""}`.trim();
31641
31841
  function validateWorkspacePath(absPath) {
31642
31842
  try {
31643
31843
  if (!absPath) return { ok: false, error: "Path required" };
31644
- if (!fs4.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
31645
- const st2 = fs4.statSync(absPath);
31844
+ if (!fs5.existsSync(absPath)) return { ok: false, error: "Path does not exist" };
31845
+ const st2 = fs5.statSync(absPath);
31646
31846
  if (!st2.isDirectory()) return { ok: false, error: "Not a directory" };
31647
31847
  return { ok: true };
31648
31848
  } catch (e) {
@@ -31749,9 +31949,9 @@ ${data.message || ""}`.trim();
31749
31949
  const abs = expandPath(rawPath);
31750
31950
  const createIfMissing = options?.createIfMissing === true;
31751
31951
  if (!abs) return { error: "Path required" };
31752
- if (!fs4.existsSync(abs) && createIfMissing) {
31952
+ if (!fs5.existsSync(abs) && createIfMissing) {
31753
31953
  try {
31754
- fs4.mkdirSync(abs, { recursive: true });
31954
+ fs5.mkdirSync(abs, { recursive: true });
31755
31955
  } catch (e) {
31756
31956
  return { error: e?.message || "Could not create directory" };
31757
31957
  }
@@ -31791,7 +31991,7 @@ ${data.message || ""}`.trim();
31791
31991
  if (validateWorkspacePath(abs).ok !== true) return { error: "Workspace path is no longer valid" };
31792
31992
  return { config: { ...config2, defaultWorkspaceId: id } };
31793
31993
  }
31794
- var path22 = __toESM2(require("path"));
31994
+ var path23 = __toESM2(require("path"));
31795
31995
  function normalizeSummaryItem(item) {
31796
31996
  if (!item || typeof item !== "object") return null;
31797
31997
  const id = String(item.id || "").trim();
@@ -31856,9 +32056,9 @@ ${data.message || ""}`.trim();
31856
32056
  function normalizeWorkspace(workspace) {
31857
32057
  if (!workspace) return "";
31858
32058
  try {
31859
- return path22.resolve(expandPath(workspace));
32059
+ return path23.resolve(expandPath(workspace));
31860
32060
  } catch {
31861
- return path22.resolve(workspace);
32061
+ return path23.resolve(workspace);
31862
32062
  }
31863
32063
  }
31864
32064
  function buildRecentActivityKey(entry) {
@@ -37510,6 +37710,7 @@ ${effect.notification.body || ""}`.trim();
37510
37710
  }
37511
37711
  function buildReadChatCommandResult(payload, args) {
37512
37712
  let validatedPayload;
37713
+ const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
37513
37714
  try {
37514
37715
  validatedPayload = validateReadChatResultPayload({
37515
37716
  ...payload,
@@ -37530,7 +37731,8 @@ ${effect.notification.body || ""}`.trim();
37530
37731
  syncMode: "full",
37531
37732
  replaceFrom: 0,
37532
37733
  totalMessages: messages.length,
37533
- lastMessageSignature
37734
+ lastMessageSignature,
37735
+ ...debugReadChat ? { debugReadChat } : {}
37534
37736
  };
37535
37737
  }
37536
37738
  const sync = computeReadChatSync(messages, cursor);
@@ -37541,7 +37743,8 @@ ${effect.notification.body || ""}`.trim();
37541
37743
  syncMode: sync.syncMode,
37542
37744
  replaceFrom: sync.replaceFrom,
37543
37745
  totalMessages: sync.totalMessages,
37544
- lastMessageSignature: sync.lastMessageSignature
37746
+ lastMessageSignature: sync.lastMessageSignature,
37747
+ ...debugReadChat ? { debugReadChat } : {}
37545
37748
  };
37546
37749
  }
37547
37750
  function didProviderConfirmSend(result) {
@@ -37632,14 +37835,33 @@ ${effect.notification.body || ""}`.trim();
37632
37835
  }
37633
37836
  }
37634
37837
  const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
37635
- const status = parsedRecord || adapter.getStatus();
37838
+ const adapterStatus = adapter.getStatus();
37839
+ const shouldPreferAdapterMessages = Array.isArray(adapterStatus.messages) && adapterStatus.messages.length > 0 && Array.isArray(parsedRecord?.messages) && adapterStatus.messages.length > parsedRecord.messages.length;
37840
+ const status = parsedRecord ? {
37841
+ ...parsedRecord,
37842
+ messages: shouldPreferAdapterMessages ? adapterStatus.messages : parsedRecord.messages,
37843
+ status: adapterStatus.status !== "idle" ? adapterStatus.status : parsedRecord.status || adapterStatus.status,
37844
+ activeModal: parsedRecord.activeModal || adapterStatus.activeModal
37845
+ } : adapterStatus;
37636
37846
  const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
37637
37847
  const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
37638
37848
  if (status) {
37849
+ LOG2.info("Command", `[read_chat] cli-like resolved provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord?.status || "")} shouldPreferAdapterMessages=${String(shouldPreferAdapterMessages)} adapterMsgCount=${Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0} parsedMsgCount=${Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0} returnedMsgCount=${Array.isArray(status.messages) ? status.messages.length : 0}`);
37639
37850
  return buildReadChatCommandResult({
37640
37851
  messages: status.messages || [],
37641
37852
  status: status.status,
37642
37853
  activeModal: status.activeModal,
37854
+ debugReadChat: {
37855
+ provider: adapter.cliType,
37856
+ targetSessionId: String(args?.targetSessionId || ""),
37857
+ adapterStatus: String(adapterStatus.status || ""),
37858
+ parsedStatus: String(parsedRecord?.status || ""),
37859
+ returnedStatus: String(status.status || ""),
37860
+ shouldPreferAdapterMessages,
37861
+ adapterMsgCount: Array.isArray(adapterStatus.messages) ? adapterStatus.messages.length : 0,
37862
+ parsedMsgCount: Array.isArray(parsedRecord?.messages) ? parsedRecord.messages.length : 0,
37863
+ returnedMsgCount: Array.isArray(status.messages) ? status.messages.length : 0
37864
+ },
37643
37865
  ...title ? { title } : {},
37644
37866
  ...providerSessionId ? { providerSessionId } : {}
37645
37867
  }, args);
@@ -39861,7 +40083,7 @@ ${effect.notification.body || ""}`.trim();
39861
40083
  var os11 = __toESM2(require("os"));
39862
40084
  var path11 = __toESM2(require("path"));
39863
40085
  var crypto3 = __toESM2(require("crypto"));
39864
- var fs5 = __toESM2(require("fs"));
40086
+ var fs52 = __toESM2(require("fs"));
39865
40087
  var import_node_module = require("module");
39866
40088
  init_contracts();
39867
40089
  init_provider_cli_adapter();
@@ -40082,7 +40304,7 @@ ${effect.notification.body || ""}`.trim();
40082
40304
  */
40083
40305
  probeSessionIdFromConfig(probe) {
40084
40306
  const resolvedDbPath = probe.dbPath.replace(/^~/, os11.homedir());
40085
- if (!fs5.existsSync(resolvedDbPath)) return null;
40307
+ if (!fs52.existsSync(resolvedDbPath)) return null;
40086
40308
  const directories = this.getProbeDirectories();
40087
40309
  const minCreatedAt = Math.max(0, this.startedAt - 6e4);
40088
40310
  const tsFormat = probe.timestampFormat || "unix_ms";
@@ -40180,7 +40402,7 @@ ${effect.notification.body || ""}`.trim();
40180
40402
  activeChat: {
40181
40403
  id: `${this.type}_${this.workingDir}`,
40182
40404
  title: parsedStatus?.title || dirName,
40183
- status: parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : parsedStatus?.status || visibleStatus,
40405
+ status: parseErrorMessage ? "error" : autoApproveActive && parsedStatus?.status === "waiting_approval" ? "generating" : adapterStatus.status !== "idle" ? visibleStatus : parsedStatus?.status || visibleStatus,
40184
40406
  messages: mergedMessages,
40185
40407
  activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
40186
40408
  inputContent: ""
@@ -40640,7 +40862,7 @@ ${effect.notification.body || ""}`.trim();
40640
40862
  };
40641
40863
  addDir(this.workingDir);
40642
40864
  try {
40643
- addDir(fs5.realpathSync.native(this.workingDir));
40865
+ addDir(fs52.realpathSync.native(this.workingDir));
40644
40866
  } catch {
40645
40867
  }
40646
40868
  return Array.from(dirs);
@@ -52548,6 +52770,13 @@ data: ${JSON.stringify(msg.data)}
52548
52770
  init_pty_transport();
52549
52771
  var import_session_host_core22 = require_dist();
52550
52772
  init_logger();
52773
+ function shouldResumeAttachedSession(record2) {
52774
+ if (!record2) return false;
52775
+ if (record2.lifecycle === "interrupted") return true;
52776
+ if (record2.lifecycle !== "stopped") return false;
52777
+ if (record2.meta?.restoredFromStorage === true) return true;
52778
+ return typeof record2.meta?.runtimeRecoveryState === "string" && String(record2.meta.runtimeRecoveryState).trim().length > 0;
52779
+ }
52551
52780
  var SessionHostRuntimeTransport = class {
52552
52781
  constructor(options) {
52553
52782
  this.options = options;
@@ -52721,7 +52950,7 @@ data: ${JSON.stringify(msg.data)}
52721
52950
  payload: {}
52722
52951
  });
52723
52952
  const existingRecord = existingRecords.success && existingRecords.result ? existingRecords.result.find((item) => item.sessionId === this.options.runtimeId) || null : null;
52724
- if (existingRecord?.lifecycle === "interrupted") {
52953
+ if (shouldResumeAttachedSession(existingRecord)) {
52725
52954
  const resumeResponse = await this.client.request({
52726
52955
  type: "resume_session",
52727
52956
  payload: {
@@ -53011,6 +53240,8 @@ data: ${JSON.stringify(msg.data)}
53011
53240
  }
53012
53241
  function shouldAutoRestoreHostedSessionsOnStartup2(env = process.env) {
53013
53242
  const raw = typeof env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";
53243
+ if (!raw) return true;
53244
+ if (raw === "0" || raw === "false" || raw === "no") return false;
53014
53245
  return raw === "1" || raw === "true" || raw === "yes";
53015
53246
  }
53016
53247
  var import_child_process10 = require("child_process");
@@ -53489,16 +53720,91 @@ data: ${JSON.stringify(msg.data)}
53489
53720
  var import_http = require("http");
53490
53721
  var import_ws = require("ws");
53491
53722
  var path4 = __toESM(require("path"));
53492
- var fs3 = __toESM(require("fs"));
53723
+ var fs4 = __toESM(require("fs"));
53493
53724
  var os5 = __toESM(require("os"));
53494
53725
  var import_crypto2 = require("crypto");
53726
+
53727
+ // src/standalone-preferences.ts
53728
+ var fs = __toESM(require("fs"));
53729
+ var path = __toESM(require("path"));
53730
+ var DEFAULT_STANDALONE_FONT_PREFERENCES = {
53731
+ chat: { preset: "default" },
53732
+ code: { preset: "default" },
53733
+ terminal: { preset: "default" }
53734
+ };
53735
+ var DEFAULT_STANDALONE_PREFERENCES_STATE = {
53736
+ standaloneBindHost: "127.0.0.1",
53737
+ standaloneFontPreferences: DEFAULT_STANDALONE_FONT_PREFERENCES
53738
+ };
53739
+ var VALID_CHAT_PRESETS = /* @__PURE__ */ new Set(["default", "system-ui", "inter", "pretendard", "noto-sans-kr", "serif", "custom"]);
53740
+ var VALID_MONO_PRESETS = /* @__PURE__ */ new Set(["default", "jetbrains-mono", "fira-code", "cascadia-code", "berkeley-mono", "custom"]);
53741
+ function normalizeStandaloneBindHost(value) {
53742
+ return value === "0.0.0.0" ? "0.0.0.0" : "127.0.0.1";
53743
+ }
53744
+ function normalizeStandaloneFontChoice(surface, value) {
53745
+ const fallback = DEFAULT_STANDALONE_FONT_PREFERENCES[surface];
53746
+ const input = value && typeof value === "object" && !Array.isArray(value) ? value : {};
53747
+ const preset = typeof input.preset === "string" ? input.preset.trim() : "";
53748
+ const customFamily = typeof input.customFamily === "string" ? input.customFamily.trim() : "";
53749
+ const validPresets = surface === "chat" ? VALID_CHAT_PRESETS : VALID_MONO_PRESETS;
53750
+ if (!validPresets.has(preset)) {
53751
+ return fallback;
53752
+ }
53753
+ if (preset === "custom") {
53754
+ if (!customFamily) return fallback;
53755
+ return { preset: "custom", customFamily };
53756
+ }
53757
+ return { preset };
53758
+ }
53759
+ function normalizeStandaloneFontPreferences(value) {
53760
+ const input = value && typeof value === "object" && !Array.isArray(value) ? value : {};
53761
+ return {
53762
+ chat: normalizeStandaloneFontChoice("chat", input.chat),
53763
+ code: normalizeStandaloneFontChoice("code", input.code),
53764
+ terminal: normalizeStandaloneFontChoice("terminal", input.terminal)
53765
+ };
53766
+ }
53767
+ function normalizeStandalonePreferences(value) {
53768
+ const input = value && typeof value === "object" && !Array.isArray(value) ? value : {};
53769
+ return {
53770
+ standaloneBindHost: normalizeStandaloneBindHost(input.standaloneBindHost),
53771
+ standaloneFontPreferences: normalizeStandaloneFontPreferences(input.standaloneFontPreferences)
53772
+ };
53773
+ }
53774
+ function loadStandalonePreferences(filePath) {
53775
+ if (!fs.existsSync(filePath)) return DEFAULT_STANDALONE_PREFERENCES_STATE;
53776
+ try {
53777
+ return normalizeStandalonePreferences(JSON.parse(fs.readFileSync(filePath, "utf8")));
53778
+ } catch {
53779
+ return DEFAULT_STANDALONE_PREFERENCES_STATE;
53780
+ }
53781
+ }
53782
+ function saveStandalonePreferences(filePath, value) {
53783
+ const current = loadStandalonePreferences(filePath);
53784
+ const next = normalizeStandalonePreferences({
53785
+ standaloneBindHost: Object.prototype.hasOwnProperty.call(value, "standaloneBindHost") ? value.standaloneBindHost : current.standaloneBindHost,
53786
+ standaloneFontPreferences: Object.prototype.hasOwnProperty.call(value, "standaloneFontPreferences") ? value.standaloneFontPreferences : current.standaloneFontPreferences
53787
+ });
53788
+ const dir = path.dirname(filePath);
53789
+ if (!fs.existsSync(dir)) {
53790
+ fs.mkdirSync(dir, { recursive: true, mode: 448 });
53791
+ }
53792
+ fs.writeFileSync(filePath, JSON.stringify(next, null, 2), { encoding: "utf8", mode: 384 });
53793
+ try {
53794
+ fs.chmodSync(filePath, 384);
53795
+ } catch {
53796
+ }
53797
+ return next;
53798
+ }
53799
+
53800
+ // src/index.ts
53495
53801
  var import_daemon_core2 = __toESM(require_dist2());
53496
53802
 
53497
53803
  // src/session-host.ts
53498
53804
  var childProcess = __toESM(require("child_process"));
53499
- var fs2 = __toESM(require("fs"));
53805
+ var fs3 = __toESM(require("fs"));
53500
53806
  var os2 = __toESM(require("os"));
53501
- var path = __toESM(require("path"));
53807
+ var path2 = __toESM(require("path"));
53502
53808
  var import_daemon_core = __toESM(require_dist2());
53503
53809
  var SESSION_HOST_APP_NAME_RESOLUTION = (0, import_daemon_core.resolveSessionHostAppNameResolution)({ standalone: true });
53504
53810
  var SESSION_HOST_APP_NAME = SESSION_HOST_APP_NAME_RESOLUTION.appName;
@@ -53533,18 +53839,18 @@ function buildSessionHostEnv(baseEnv) {
53533
53839
  }
53534
53840
  function resolveSessionHostEntry() {
53535
53841
  const localCandidates = [
53536
- path.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
53537
- path.resolve(__dirname, "../../vendor/session-host-daemon/index.js")
53842
+ path2.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
53843
+ path2.resolve(__dirname, "../../vendor/session-host-daemon/index.js")
53538
53844
  ];
53539
53845
  for (const candidate of localCandidates) {
53540
- if (fs2.existsSync(candidate)) {
53846
+ if (fs3.existsSync(candidate)) {
53541
53847
  return candidate;
53542
53848
  }
53543
53849
  }
53544
53850
  return require.resolve("@adhdev/session-host-daemon");
53545
53851
  }
53546
53852
  function getSessionHostPidFile() {
53547
- return path.join(os2.homedir(), ".adhdev", `${SESSION_HOST_APP_NAME}-session-host.pid`);
53853
+ return path2.join(os2.homedir(), ".adhdev", `${SESSION_HOST_APP_NAME}-session-host.pid`);
53548
53854
  }
53549
53855
  function killPid(pid) {
53550
53856
  try {
@@ -53562,8 +53868,8 @@ function stopManagedSessionHostProcess() {
53562
53868
  let stopped = false;
53563
53869
  const pidFile = getSessionHostPidFile();
53564
53870
  try {
53565
- if (fs2.existsSync(pidFile)) {
53566
- const pid = Number.parseInt(fs2.readFileSync(pidFile, "utf8").trim(), 10);
53871
+ if (fs3.existsSync(pidFile)) {
53872
+ const pid = Number.parseInt(fs3.readFileSync(pidFile, "utf8").trim(), 10);
53567
53873
  if (Number.isFinite(pid) && pid !== process.pid) {
53568
53874
  stopped = killPid(pid) || stopped;
53569
53875
  }
@@ -53571,7 +53877,7 @@ function stopManagedSessionHostProcess() {
53571
53877
  } catch {
53572
53878
  } finally {
53573
53879
  try {
53574
- fs2.unlinkSync(pidFile);
53880
+ fs3.unlinkSync(pidFile);
53575
53881
  } catch {
53576
53882
  }
53577
53883
  }
@@ -53639,12 +53945,14 @@ async function proxySessionHostAttach(target, options = {}) {
53639
53945
  // src/startup-restore-policy.ts
53640
53946
  function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
53641
53947
  const raw = typeof env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";
53948
+ if (!raw) return true;
53949
+ if (raw === "0" || raw === "false" || raw === "no") return false;
53642
53950
  return raw === "1" || raw === "true" || raw === "yes";
53643
53951
  }
53644
53952
 
53645
53953
  // ../session-host-core/dist/index.mjs
53646
53954
  var os3 = __toESM(require("os"), 1);
53647
- var path2 = __toESM(require("path"), 1);
53955
+ var path22 = __toESM(require("path"), 1);
53648
53956
  var net = __toESM(require("net"), 1);
53649
53957
  var import_crypto = require("crypto");
53650
53958
  function getDefaultSessionHostEndpoint(appName = "adhdev") {
@@ -53656,7 +53964,7 @@ function getDefaultSessionHostEndpoint(appName = "adhdev") {
53656
53964
  }
53657
53965
  return {
53658
53966
  kind: "unix",
53659
- path: path2.join(os3.tmpdir(), `${appName}-session-host.sock`)
53967
+ path: path22.join(os3.tmpdir(), `${appName}-session-host.sock`)
53660
53968
  };
53661
53969
  }
53662
53970
  function serializeEnvelope(envelope) {
@@ -54003,53 +54311,35 @@ var DEFAULT_PORT = 3847;
54003
54311
  var STATUS_INTERVAL = 2e3;
54004
54312
  var STANDALONE_AUTH_SESSION_COOKIE = "adhdev_standalone_session";
54005
54313
  var STANDALONE_PASSWORD_CONFIG_FILE = "standalone-auth.json";
54006
- var STANDALONE_BIND_HOST_CONFIG_FILE = "standalone-network.json";
54314
+ var STANDALONE_PREFERENCES_CONFIG_FILE = "standalone-network.json";
54007
54315
  var STANDALONE_BIND_HOST_DEFAULT = "127.0.0.1";
54008
54316
  var PASSWORD_KEYLEN = 64;
54009
54317
  var DEFAULT_SESSION_TTL_MS = 1e3 * 60 * 60 * 24 * 30;
54010
54318
  function getStandalonePasswordConfigPath() {
54011
54319
  const dir = path4.join(os5.homedir(), ".adhdev");
54012
- if (!fs3.existsSync(dir)) {
54013
- fs3.mkdirSync(dir, { recursive: true, mode: 448 });
54320
+ if (!fs4.existsSync(dir)) {
54321
+ fs4.mkdirSync(dir, { recursive: true, mode: 448 });
54014
54322
  }
54015
54323
  return path4.join(dir, STANDALONE_PASSWORD_CONFIG_FILE);
54016
54324
  }
54017
54325
  function getStandaloneConfigJsonPath() {
54018
54326
  const dir = path4.join(os5.homedir(), ".adhdev");
54019
- if (!fs3.existsSync(dir)) {
54020
- fs3.mkdirSync(dir, { recursive: true, mode: 448 });
54327
+ if (!fs4.existsSync(dir)) {
54328
+ fs4.mkdirSync(dir, { recursive: true, mode: 448 });
54021
54329
  }
54022
- return path4.join(dir, STANDALONE_BIND_HOST_CONFIG_FILE);
54330
+ return path4.join(dir, STANDALONE_PREFERENCES_CONFIG_FILE);
54023
54331
  }
54024
54332
  function loadStandaloneBindHostPreference() {
54025
- try {
54026
- const configPath = getStandaloneConfigJsonPath();
54027
- if (!fs3.existsSync(configPath)) return STANDALONE_BIND_HOST_DEFAULT;
54028
- const parsed = JSON.parse(fs3.readFileSync(configPath, "utf8"));
54029
- return parsed?.standaloneBindHost === "0.0.0.0" ? "0.0.0.0" : STANDALONE_BIND_HOST_DEFAULT;
54030
- } catch {
54031
- return STANDALONE_BIND_HOST_DEFAULT;
54032
- }
54333
+ return loadStandalonePreferences(getStandaloneConfigJsonPath()).standaloneBindHost;
54334
+ }
54335
+ function loadStandaloneFontPreferences() {
54336
+ return loadStandalonePreferences(getStandaloneConfigJsonPath()).standaloneFontPreferences;
54033
54337
  }
54034
54338
  function saveStandaloneBindHostPreference(bindHost) {
54035
- const configPath = getStandaloneConfigJsonPath();
54036
- let parsed = {};
54037
- try {
54038
- if (fs3.existsSync(configPath)) {
54039
- const raw = fs3.readFileSync(configPath, "utf8");
54040
- const next = JSON.parse(raw);
54041
- if (next && typeof next === "object" && !Array.isArray(next)) parsed = next;
54042
- }
54043
- } catch {
54044
- parsed = {};
54045
- }
54046
- parsed.standaloneBindHost = bindHost;
54047
- fs3.writeFileSync(configPath, JSON.stringify(parsed, null, 2), { encoding: "utf8", mode: 384 });
54048
- try {
54049
- fs3.chmodSync(configPath, 384);
54050
- } catch {
54051
- }
54052
- return bindHost;
54339
+ return saveStandalonePreferences(getStandaloneConfigJsonPath(), { standaloneBindHost: bindHost }).standaloneBindHost;
54340
+ }
54341
+ function saveStandaloneFontPreferences(fontPreferences) {
54342
+ return saveStandalonePreferences(getStandaloneConfigJsonPath(), { standaloneFontPreferences: fontPreferences }).standaloneFontPreferences;
54053
54343
  }
54054
54344
  function createPasswordRecord(password, salt = (0, import_crypto2.randomBytes)(16).toString("hex")) {
54055
54345
  return {
@@ -54065,9 +54355,9 @@ function verifyPassword(password, config2) {
54065
54355
  return actual.length === expected.length && (0, import_crypto2.timingSafeEqual)(actual, expected);
54066
54356
  }
54067
54357
  function loadStandalonePasswordConfig(filePath = getStandalonePasswordConfigPath()) {
54068
- if (!fs3.existsSync(filePath)) return null;
54358
+ if (!fs4.existsSync(filePath)) return null;
54069
54359
  try {
54070
- const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8"));
54360
+ const parsed = JSON.parse(fs4.readFileSync(filePath, "utf8"));
54071
54361
  if (!parsed || typeof parsed !== "object") return null;
54072
54362
  if (typeof parsed.passwordHash !== "string" || typeof parsed.passwordSalt !== "string") return null;
54073
54363
  return {
@@ -54081,18 +54371,18 @@ function loadStandalonePasswordConfig(filePath = getStandalonePasswordConfigPath
54081
54371
  }
54082
54372
  function saveStandalonePasswordConfig(filePath, config2) {
54083
54373
  const dir = path4.dirname(filePath);
54084
- if (!fs3.existsSync(dir)) {
54085
- fs3.mkdirSync(dir, { recursive: true, mode: 448 });
54374
+ if (!fs4.existsSync(dir)) {
54375
+ fs4.mkdirSync(dir, { recursive: true, mode: 448 });
54086
54376
  }
54087
- fs3.writeFileSync(filePath, JSON.stringify(config2, null, 2), { encoding: "utf8", mode: 384 });
54377
+ fs4.writeFileSync(filePath, JSON.stringify(config2, null, 2), { encoding: "utf8", mode: 384 });
54088
54378
  try {
54089
- fs3.chmodSync(filePath, 384);
54379
+ fs4.chmodSync(filePath, 384);
54090
54380
  } catch {
54091
54381
  }
54092
54382
  }
54093
54383
  function clearStandalonePasswordConfig(filePath = getStandalonePasswordConfigPath()) {
54094
- if (fs3.existsSync(filePath)) {
54095
- fs3.rmSync(filePath, { force: true });
54384
+ if (fs4.existsSync(filePath)) {
54385
+ fs4.rmSync(filePath, { force: true });
54096
54386
  }
54097
54387
  }
54098
54388
  function shouldWarnForPublicUnauthenticatedHost(input) {
@@ -54169,7 +54459,7 @@ if (pkgVersion === "unknown") {
54169
54459
  ];
54170
54460
  for (const candidate of possiblePaths) {
54171
54461
  try {
54172
- const data = JSON.parse(fs3.readFileSync(candidate, "utf-8"));
54462
+ const data = JSON.parse(fs4.readFileSync(candidate, "utf-8"));
54173
54463
  if (data.version) {
54174
54464
  pkgVersion = data.version;
54175
54465
  break;
@@ -54606,10 +54896,12 @@ var StandaloneServer = class {
54606
54896
  }
54607
54897
  if (parsedUrl.pathname === "/api/v1/standalone/preferences" && method === "GET") {
54608
54898
  const configuredBindHost = loadStandaloneBindHostPreference();
54899
+ const standaloneFontPreferences = loadStandaloneFontPreferences();
54609
54900
  res.writeHead(200, { "Content-Type": "application/json" });
54610
54901
  res.end(JSON.stringify({
54611
54902
  standaloneBindHost: configuredBindHost,
54612
54903
  currentBindHost: this.listenHost,
54904
+ standaloneFontPreferences,
54613
54905
  hasPasswordAuth: !!this.passwordConfig,
54614
54906
  hasTokenAuth: !!this.authToken,
54615
54907
  publicHostWarning: shouldWarnForPublicUnauthenticatedHost({
@@ -54633,13 +54925,14 @@ var StandaloneServer = class {
54633
54925
  return;
54634
54926
  }
54635
54927
  const body = await this.readJsonBody(req);
54636
- const nextHost = body?.standaloneBindHost === "0.0.0.0" ? "0.0.0.0" : "127.0.0.1";
54637
- const savedHost = saveStandaloneBindHostPreference(nextHost);
54928
+ const savedHost = Object.prototype.hasOwnProperty.call(body || {}, "standaloneBindHost") ? saveStandaloneBindHostPreference(body?.standaloneBindHost === "0.0.0.0" ? "0.0.0.0" : "127.0.0.1") : loadStandaloneBindHostPreference();
54929
+ const savedFontPreferences = Object.prototype.hasOwnProperty.call(body || {}, "standaloneFontPreferences") ? saveStandaloneFontPreferences(body?.standaloneFontPreferences) : loadStandaloneFontPreferences();
54638
54930
  res.writeHead(200, { "Content-Type": "application/json" });
54639
54931
  res.end(JSON.stringify({
54640
54932
  success: true,
54641
54933
  standaloneBindHost: savedHost,
54642
54934
  currentBindHost: this.listenHost,
54935
+ standaloneFontPreferences: savedFontPreferences,
54643
54936
  hasPasswordAuth: !!this.passwordConfig,
54644
54937
  hasTokenAuth: !!this.authToken,
54645
54938
  publicHostWarning: shouldWarnForPublicUnauthenticatedHost({
@@ -54796,7 +55089,7 @@ var StandaloneServer = class {
54796
55089
  if (publicDir) {
54797
55090
  const filePath = url2 === "/" ? "/index.html" : url2;
54798
55091
  const fullPath = path4.join(publicDir, filePath);
54799
- if (fs3.existsSync(fullPath) && fs3.statSync(fullPath).isFile()) {
55092
+ if (fs4.existsSync(fullPath) && fs4.statSync(fullPath).isFile()) {
54800
55093
  const ext = path4.extname(fullPath);
54801
55094
  const mimeTypes = {
54802
55095
  ".html": "text/html",
@@ -54809,13 +55102,13 @@ var StandaloneServer = class {
54809
55102
  ".woff2": "font/woff2"
54810
55103
  };
54811
55104
  res.writeHead(200, { "Content-Type": mimeTypes[ext] || "application/octet-stream" });
54812
- fs3.createReadStream(fullPath).pipe(res);
55105
+ fs4.createReadStream(fullPath).pipe(res);
54813
55106
  return;
54814
55107
  }
54815
55108
  const indexPath = path4.join(publicDir, "index.html");
54816
- if (fs3.existsSync(indexPath) && !url2.startsWith("/api/")) {
55109
+ if (fs4.existsSync(indexPath) && !url2.startsWith("/api/")) {
54817
55110
  res.writeHead(200, { "Content-Type": "text/html" });
54818
- fs3.createReadStream(indexPath).pipe(res);
55111
+ fs4.createReadStream(indexPath).pipe(res);
54819
55112
  return;
54820
55113
  }
54821
55114
  }
@@ -55607,7 +55900,7 @@ Runtime commands:
55607
55900
  path4.join(process.cwd(), "public")
55608
55901
  ];
55609
55902
  for (const candidate of candidates) {
55610
- if (fs3.existsSync(path4.join(candidate, "index.html"))) {
55903
+ if (fs4.existsSync(path4.join(candidate, "index.html"))) {
55611
55904
  options.publicDir = candidate;
55612
55905
  break;
55613
55906
  }