@adhdev/daemon-standalone 0.8.83 → 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,12 +40083,36 @@ ${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();
39868
40090
  init_logger();
39869
40091
  init_chat_message_normalization();
40092
+ function normalizePersistableCliHistoryContent(content) {
40093
+ return flattenContent(content).replace(/\s+/g, " ").trim();
40094
+ }
40095
+ function buildPersistableCliHistorySignature(message) {
40096
+ return [
40097
+ String(message.role || ""),
40098
+ String(message.kind || ""),
40099
+ String(message.senderName || ""),
40100
+ normalizePersistableCliHistoryContent(message.content)
40101
+ ].join("|");
40102
+ }
40103
+ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages) {
40104
+ if (!Array.isArray(currentMessages) || currentMessages.length === 0) return [];
40105
+ if (!Array.isArray(previousMessages) || previousMessages.length === 0) return currentMessages;
40106
+ const previousSignatures = previousMessages.map(buildPersistableCliHistorySignature);
40107
+ const currentSignatures = currentMessages.map(buildPersistableCliHistorySignature);
40108
+ let sharedPrefixLength = 0;
40109
+ while (sharedPrefixLength < previousSignatures.length && sharedPrefixLength < currentSignatures.length && previousSignatures[sharedPrefixLength] === currentSignatures[sharedPrefixLength]) {
40110
+ sharedPrefixLength += 1;
40111
+ }
40112
+ if (sharedPrefixLength === currentSignatures.length) return [];
40113
+ if (sharedPrefixLength === previousSignatures.length) return currentMessages.slice(sharedPrefixLength);
40114
+ return currentMessages;
40115
+ }
39870
40116
  var CachedDatabaseSync = null;
39871
40117
  function getDatabaseSync() {
39872
40118
  if (CachedDatabaseSync) return CachedDatabaseSync;
@@ -39944,6 +40190,7 @@ ${effect.notification.body || ""}`.trim();
39944
40190
  appliedEffectKeys = /* @__PURE__ */ new Set();
39945
40191
  historyWriter;
39946
40192
  runtimeMessages = [];
40193
+ lastPersistedHistoryMessages = [];
39947
40194
  instanceId;
39948
40195
  suppressIdleHistoryReplay = false;
39949
40196
  errorMessage = void 0;
@@ -39984,6 +40231,13 @@ ${effect.notification.body || ""}`.trim();
39984
40231
  this.providerSessionId,
39985
40232
  this.instanceId
39986
40233
  );
40234
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
40235
+ role: message.role,
40236
+ content: message.content,
40237
+ kind: message.kind,
40238
+ senderName: message.senderName,
40239
+ receivedAt: message.receivedAt
40240
+ }));
39987
40241
  this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
39988
40242
  if (restoredHistory.messages.length > 0) {
39989
40243
  this.adapter.seedCommittedMessages(
@@ -40050,7 +40304,7 @@ ${effect.notification.body || ""}`.trim();
40050
40304
  */
40051
40305
  probeSessionIdFromConfig(probe) {
40052
40306
  const resolvedDbPath = probe.dbPath.replace(/^~/, os11.homedir());
40053
- if (!fs5.existsSync(resolvedDbPath)) return null;
40307
+ if (!fs52.existsSync(resolvedDbPath)) return null;
40054
40308
  const directories = this.getProbeDirectories();
40055
40309
  const minCreatedAt = Math.max(0, this.startedAt - 6e4);
40056
40310
  const tsFormat = probe.timestampFormat || "unix_ms";
@@ -40115,15 +40369,24 @@ ${effect.notification.body || ""}`.trim();
40115
40369
  messagesToSave = messagesToSave.slice(0, lastIdx);
40116
40370
  }
40117
40371
  }
40118
- if (!shouldSkipReplayPersist && messagesToSave.length > 0) {
40372
+ const normalizedMessagesToSave = messagesToSave.map((message) => ({
40373
+ role: message.role,
40374
+ content: flattenContent(message.content),
40375
+ kind: typeof message.kind === "string" ? message.kind : void 0,
40376
+ senderName: typeof message.senderName === "string" ? message.senderName : void 0,
40377
+ receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
40378
+ }));
40379
+ if (!shouldSkipReplayPersist && normalizedMessagesToSave.length > 0) {
40380
+ const incrementalMessages = buildIncrementalHistoryAppendMessages(this.lastPersistedHistoryMessages, normalizedMessagesToSave);
40119
40381
  this.historyWriter.appendNewMessages(
40120
40382
  this.type,
40121
- messagesToSave,
40383
+ incrementalMessages,
40122
40384
  parsedStatus?.title || dirName,
40123
40385
  this.instanceId,
40124
40386
  this.providerSessionId
40125
40387
  );
40126
40388
  }
40389
+ this.lastPersistedHistoryMessages = normalizedMessagesToSave;
40127
40390
  }
40128
40391
  this.applyProviderResponse(parsedStatus, { phase: "immediate" });
40129
40392
  const surface = resolveProviderStateSurface({
@@ -40139,7 +40402,7 @@ ${effect.notification.body || ""}`.trim();
40139
40402
  activeChat: {
40140
40403
  id: `${this.type}_${this.workingDir}`,
40141
40404
  title: parsedStatus?.title || dirName,
40142
- 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,
40143
40406
  messages: mergedMessages,
40144
40407
  activeModal: autoApproveActive ? null : parsedStatus?.activeModal ?? adapterStatus.activeModal,
40145
40408
  inputContent: ""
@@ -40371,6 +40634,7 @@ ${effect.notification.body || ""}`.trim();
40371
40634
  }
40372
40635
  if (data.sessionEvent === "new_session") {
40373
40636
  this.runtimeMessages = [];
40637
+ this.lastPersistedHistoryMessages = [];
40374
40638
  this.suppressIdleHistoryReplay = false;
40375
40639
  this.adapter.clearHistory();
40376
40640
  }
@@ -40598,7 +40862,7 @@ ${effect.notification.body || ""}`.trim();
40598
40862
  };
40599
40863
  addDir(this.workingDir);
40600
40864
  try {
40601
- addDir(fs5.realpathSync.native(this.workingDir));
40865
+ addDir(fs52.realpathSync.native(this.workingDir));
40602
40866
  } catch {
40603
40867
  }
40604
40868
  return Array.from(dirs);
@@ -52506,6 +52770,13 @@ data: ${JSON.stringify(msg.data)}
52506
52770
  init_pty_transport();
52507
52771
  var import_session_host_core22 = require_dist();
52508
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
+ }
52509
52780
  var SessionHostRuntimeTransport = class {
52510
52781
  constructor(options) {
52511
52782
  this.options = options;
@@ -52679,7 +52950,7 @@ data: ${JSON.stringify(msg.data)}
52679
52950
  payload: {}
52680
52951
  });
52681
52952
  const existingRecord = existingRecords.success && existingRecords.result ? existingRecords.result.find((item) => item.sessionId === this.options.runtimeId) || null : null;
52682
- if (existingRecord?.lifecycle === "interrupted") {
52953
+ if (shouldResumeAttachedSession(existingRecord)) {
52683
52954
  const resumeResponse = await this.client.request({
52684
52955
  type: "resume_session",
52685
52956
  payload: {
@@ -52969,6 +53240,8 @@ data: ${JSON.stringify(msg.data)}
52969
53240
  }
52970
53241
  function shouldAutoRestoreHostedSessionsOnStartup2(env = process.env) {
52971
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;
52972
53245
  return raw === "1" || raw === "true" || raw === "yes";
52973
53246
  }
52974
53247
  var import_child_process10 = require("child_process");
@@ -53447,16 +53720,91 @@ data: ${JSON.stringify(msg.data)}
53447
53720
  var import_http = require("http");
53448
53721
  var import_ws = require("ws");
53449
53722
  var path4 = __toESM(require("path"));
53450
- var fs3 = __toESM(require("fs"));
53723
+ var fs4 = __toESM(require("fs"));
53451
53724
  var os5 = __toESM(require("os"));
53452
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
53453
53801
  var import_daemon_core2 = __toESM(require_dist2());
53454
53802
 
53455
53803
  // src/session-host.ts
53456
53804
  var childProcess = __toESM(require("child_process"));
53457
- var fs2 = __toESM(require("fs"));
53805
+ var fs3 = __toESM(require("fs"));
53458
53806
  var os2 = __toESM(require("os"));
53459
- var path = __toESM(require("path"));
53807
+ var path2 = __toESM(require("path"));
53460
53808
  var import_daemon_core = __toESM(require_dist2());
53461
53809
  var SESSION_HOST_APP_NAME_RESOLUTION = (0, import_daemon_core.resolveSessionHostAppNameResolution)({ standalone: true });
53462
53810
  var SESSION_HOST_APP_NAME = SESSION_HOST_APP_NAME_RESOLUTION.appName;
@@ -53491,18 +53839,18 @@ function buildSessionHostEnv(baseEnv) {
53491
53839
  }
53492
53840
  function resolveSessionHostEntry() {
53493
53841
  const localCandidates = [
53494
- path.resolve(__dirname, "../vendor/session-host-daemon/index.js"),
53495
- 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")
53496
53844
  ];
53497
53845
  for (const candidate of localCandidates) {
53498
- if (fs2.existsSync(candidate)) {
53846
+ if (fs3.existsSync(candidate)) {
53499
53847
  return candidate;
53500
53848
  }
53501
53849
  }
53502
53850
  return require.resolve("@adhdev/session-host-daemon");
53503
53851
  }
53504
53852
  function getSessionHostPidFile() {
53505
- 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`);
53506
53854
  }
53507
53855
  function killPid(pid) {
53508
53856
  try {
@@ -53520,8 +53868,8 @@ function stopManagedSessionHostProcess() {
53520
53868
  let stopped = false;
53521
53869
  const pidFile = getSessionHostPidFile();
53522
53870
  try {
53523
- if (fs2.existsSync(pidFile)) {
53524
- 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);
53525
53873
  if (Number.isFinite(pid) && pid !== process.pid) {
53526
53874
  stopped = killPid(pid) || stopped;
53527
53875
  }
@@ -53529,7 +53877,7 @@ function stopManagedSessionHostProcess() {
53529
53877
  } catch {
53530
53878
  } finally {
53531
53879
  try {
53532
- fs2.unlinkSync(pidFile);
53880
+ fs3.unlinkSync(pidFile);
53533
53881
  } catch {
53534
53882
  }
53535
53883
  }
@@ -53597,12 +53945,14 @@ async function proxySessionHostAttach(target, options = {}) {
53597
53945
  // src/startup-restore-policy.ts
53598
53946
  function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
53599
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;
53600
53950
  return raw === "1" || raw === "true" || raw === "yes";
53601
53951
  }
53602
53952
 
53603
53953
  // ../session-host-core/dist/index.mjs
53604
53954
  var os3 = __toESM(require("os"), 1);
53605
- var path2 = __toESM(require("path"), 1);
53955
+ var path22 = __toESM(require("path"), 1);
53606
53956
  var net = __toESM(require("net"), 1);
53607
53957
  var import_crypto = require("crypto");
53608
53958
  function getDefaultSessionHostEndpoint(appName = "adhdev") {
@@ -53614,7 +53964,7 @@ function getDefaultSessionHostEndpoint(appName = "adhdev") {
53614
53964
  }
53615
53965
  return {
53616
53966
  kind: "unix",
53617
- path: path2.join(os3.tmpdir(), `${appName}-session-host.sock`)
53967
+ path: path22.join(os3.tmpdir(), `${appName}-session-host.sock`)
53618
53968
  };
53619
53969
  }
53620
53970
  function serializeEnvelope(envelope) {
@@ -53961,53 +54311,35 @@ var DEFAULT_PORT = 3847;
53961
54311
  var STATUS_INTERVAL = 2e3;
53962
54312
  var STANDALONE_AUTH_SESSION_COOKIE = "adhdev_standalone_session";
53963
54313
  var STANDALONE_PASSWORD_CONFIG_FILE = "standalone-auth.json";
53964
- var STANDALONE_BIND_HOST_CONFIG_FILE = "standalone-network.json";
54314
+ var STANDALONE_PREFERENCES_CONFIG_FILE = "standalone-network.json";
53965
54315
  var STANDALONE_BIND_HOST_DEFAULT = "127.0.0.1";
53966
54316
  var PASSWORD_KEYLEN = 64;
53967
54317
  var DEFAULT_SESSION_TTL_MS = 1e3 * 60 * 60 * 24 * 30;
53968
54318
  function getStandalonePasswordConfigPath() {
53969
54319
  const dir = path4.join(os5.homedir(), ".adhdev");
53970
- if (!fs3.existsSync(dir)) {
53971
- fs3.mkdirSync(dir, { recursive: true, mode: 448 });
54320
+ if (!fs4.existsSync(dir)) {
54321
+ fs4.mkdirSync(dir, { recursive: true, mode: 448 });
53972
54322
  }
53973
54323
  return path4.join(dir, STANDALONE_PASSWORD_CONFIG_FILE);
53974
54324
  }
53975
54325
  function getStandaloneConfigJsonPath() {
53976
54326
  const dir = path4.join(os5.homedir(), ".adhdev");
53977
- if (!fs3.existsSync(dir)) {
53978
- fs3.mkdirSync(dir, { recursive: true, mode: 448 });
54327
+ if (!fs4.existsSync(dir)) {
54328
+ fs4.mkdirSync(dir, { recursive: true, mode: 448 });
53979
54329
  }
53980
- return path4.join(dir, STANDALONE_BIND_HOST_CONFIG_FILE);
54330
+ return path4.join(dir, STANDALONE_PREFERENCES_CONFIG_FILE);
53981
54331
  }
53982
54332
  function loadStandaloneBindHostPreference() {
53983
- try {
53984
- const configPath = getStandaloneConfigJsonPath();
53985
- if (!fs3.existsSync(configPath)) return STANDALONE_BIND_HOST_DEFAULT;
53986
- const parsed = JSON.parse(fs3.readFileSync(configPath, "utf8"));
53987
- return parsed?.standaloneBindHost === "0.0.0.0" ? "0.0.0.0" : STANDALONE_BIND_HOST_DEFAULT;
53988
- } catch {
53989
- return STANDALONE_BIND_HOST_DEFAULT;
53990
- }
54333
+ return loadStandalonePreferences(getStandaloneConfigJsonPath()).standaloneBindHost;
54334
+ }
54335
+ function loadStandaloneFontPreferences() {
54336
+ return loadStandalonePreferences(getStandaloneConfigJsonPath()).standaloneFontPreferences;
53991
54337
  }
53992
54338
  function saveStandaloneBindHostPreference(bindHost) {
53993
- const configPath = getStandaloneConfigJsonPath();
53994
- let parsed = {};
53995
- try {
53996
- if (fs3.existsSync(configPath)) {
53997
- const raw = fs3.readFileSync(configPath, "utf8");
53998
- const next = JSON.parse(raw);
53999
- if (next && typeof next === "object" && !Array.isArray(next)) parsed = next;
54000
- }
54001
- } catch {
54002
- parsed = {};
54003
- }
54004
- parsed.standaloneBindHost = bindHost;
54005
- fs3.writeFileSync(configPath, JSON.stringify(parsed, null, 2), { encoding: "utf8", mode: 384 });
54006
- try {
54007
- fs3.chmodSync(configPath, 384);
54008
- } catch {
54009
- }
54010
- return bindHost;
54339
+ return saveStandalonePreferences(getStandaloneConfigJsonPath(), { standaloneBindHost: bindHost }).standaloneBindHost;
54340
+ }
54341
+ function saveStandaloneFontPreferences(fontPreferences) {
54342
+ return saveStandalonePreferences(getStandaloneConfigJsonPath(), { standaloneFontPreferences: fontPreferences }).standaloneFontPreferences;
54011
54343
  }
54012
54344
  function createPasswordRecord(password, salt = (0, import_crypto2.randomBytes)(16).toString("hex")) {
54013
54345
  return {
@@ -54023,9 +54355,9 @@ function verifyPassword(password, config2) {
54023
54355
  return actual.length === expected.length && (0, import_crypto2.timingSafeEqual)(actual, expected);
54024
54356
  }
54025
54357
  function loadStandalonePasswordConfig(filePath = getStandalonePasswordConfigPath()) {
54026
- if (!fs3.existsSync(filePath)) return null;
54358
+ if (!fs4.existsSync(filePath)) return null;
54027
54359
  try {
54028
- const parsed = JSON.parse(fs3.readFileSync(filePath, "utf8"));
54360
+ const parsed = JSON.parse(fs4.readFileSync(filePath, "utf8"));
54029
54361
  if (!parsed || typeof parsed !== "object") return null;
54030
54362
  if (typeof parsed.passwordHash !== "string" || typeof parsed.passwordSalt !== "string") return null;
54031
54363
  return {
@@ -54039,18 +54371,18 @@ function loadStandalonePasswordConfig(filePath = getStandalonePasswordConfigPath
54039
54371
  }
54040
54372
  function saveStandalonePasswordConfig(filePath, config2) {
54041
54373
  const dir = path4.dirname(filePath);
54042
- if (!fs3.existsSync(dir)) {
54043
- fs3.mkdirSync(dir, { recursive: true, mode: 448 });
54374
+ if (!fs4.existsSync(dir)) {
54375
+ fs4.mkdirSync(dir, { recursive: true, mode: 448 });
54044
54376
  }
54045
- 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 });
54046
54378
  try {
54047
- fs3.chmodSync(filePath, 384);
54379
+ fs4.chmodSync(filePath, 384);
54048
54380
  } catch {
54049
54381
  }
54050
54382
  }
54051
54383
  function clearStandalonePasswordConfig(filePath = getStandalonePasswordConfigPath()) {
54052
- if (fs3.existsSync(filePath)) {
54053
- fs3.rmSync(filePath, { force: true });
54384
+ if (fs4.existsSync(filePath)) {
54385
+ fs4.rmSync(filePath, { force: true });
54054
54386
  }
54055
54387
  }
54056
54388
  function shouldWarnForPublicUnauthenticatedHost(input) {
@@ -54127,7 +54459,7 @@ if (pkgVersion === "unknown") {
54127
54459
  ];
54128
54460
  for (const candidate of possiblePaths) {
54129
54461
  try {
54130
- const data = JSON.parse(fs3.readFileSync(candidate, "utf-8"));
54462
+ const data = JSON.parse(fs4.readFileSync(candidate, "utf-8"));
54131
54463
  if (data.version) {
54132
54464
  pkgVersion = data.version;
54133
54465
  break;
@@ -54564,10 +54896,12 @@ var StandaloneServer = class {
54564
54896
  }
54565
54897
  if (parsedUrl.pathname === "/api/v1/standalone/preferences" && method === "GET") {
54566
54898
  const configuredBindHost = loadStandaloneBindHostPreference();
54899
+ const standaloneFontPreferences = loadStandaloneFontPreferences();
54567
54900
  res.writeHead(200, { "Content-Type": "application/json" });
54568
54901
  res.end(JSON.stringify({
54569
54902
  standaloneBindHost: configuredBindHost,
54570
54903
  currentBindHost: this.listenHost,
54904
+ standaloneFontPreferences,
54571
54905
  hasPasswordAuth: !!this.passwordConfig,
54572
54906
  hasTokenAuth: !!this.authToken,
54573
54907
  publicHostWarning: shouldWarnForPublicUnauthenticatedHost({
@@ -54591,13 +54925,14 @@ var StandaloneServer = class {
54591
54925
  return;
54592
54926
  }
54593
54927
  const body = await this.readJsonBody(req);
54594
- const nextHost = body?.standaloneBindHost === "0.0.0.0" ? "0.0.0.0" : "127.0.0.1";
54595
- 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();
54596
54930
  res.writeHead(200, { "Content-Type": "application/json" });
54597
54931
  res.end(JSON.stringify({
54598
54932
  success: true,
54599
54933
  standaloneBindHost: savedHost,
54600
54934
  currentBindHost: this.listenHost,
54935
+ standaloneFontPreferences: savedFontPreferences,
54601
54936
  hasPasswordAuth: !!this.passwordConfig,
54602
54937
  hasTokenAuth: !!this.authToken,
54603
54938
  publicHostWarning: shouldWarnForPublicUnauthenticatedHost({
@@ -54754,7 +55089,7 @@ var StandaloneServer = class {
54754
55089
  if (publicDir) {
54755
55090
  const filePath = url2 === "/" ? "/index.html" : url2;
54756
55091
  const fullPath = path4.join(publicDir, filePath);
54757
- if (fs3.existsSync(fullPath) && fs3.statSync(fullPath).isFile()) {
55092
+ if (fs4.existsSync(fullPath) && fs4.statSync(fullPath).isFile()) {
54758
55093
  const ext = path4.extname(fullPath);
54759
55094
  const mimeTypes = {
54760
55095
  ".html": "text/html",
@@ -54767,13 +55102,13 @@ var StandaloneServer = class {
54767
55102
  ".woff2": "font/woff2"
54768
55103
  };
54769
55104
  res.writeHead(200, { "Content-Type": mimeTypes[ext] || "application/octet-stream" });
54770
- fs3.createReadStream(fullPath).pipe(res);
55105
+ fs4.createReadStream(fullPath).pipe(res);
54771
55106
  return;
54772
55107
  }
54773
55108
  const indexPath = path4.join(publicDir, "index.html");
54774
- if (fs3.existsSync(indexPath) && !url2.startsWith("/api/")) {
55109
+ if (fs4.existsSync(indexPath) && !url2.startsWith("/api/")) {
54775
55110
  res.writeHead(200, { "Content-Type": "text/html" });
54776
- fs3.createReadStream(indexPath).pipe(res);
55111
+ fs4.createReadStream(indexPath).pipe(res);
54777
55112
  return;
54778
55113
  }
54779
55114
  }
@@ -55565,7 +55900,7 @@ Runtime commands:
55565
55900
  path4.join(process.cwd(), "public")
55566
55901
  ];
55567
55902
  for (const candidate of candidates) {
55568
- if (fs3.existsSync(path4.join(candidate, "index.html"))) {
55903
+ if (fs4.existsSync(path4.join(candidate, "index.html"))) {
55569
55904
  options.publicDir = candidate;
55570
55905
  break;
55571
55906
  }