@adhdev/daemon-standalone 1.0.42-rc.1 → 1.0.42

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
@@ -31423,9 +31423,9 @@ var require_streamx = __commonJS({
31423
31423
  }
31424
31424
  });
31425
31425
 
31426
- // ../../node_modules/tar-stream/node_modules/b4a/index.js
31426
+ // ../daemon-core/node_modules/b4a/index.js
31427
31427
  var require_b4a2 = __commonJS({
31428
- "../../node_modules/tar-stream/node_modules/b4a/index.js"(exports2, module2) {
31428
+ "../daemon-core/node_modules/b4a/index.js"(exports2, module2) {
31429
31429
  "use strict";
31430
31430
  function isBuffer(value) {
31431
31431
  return Buffer.isBuffer(value) || value instanceof Uint8Array;
@@ -31581,9 +31581,9 @@ var require_b4a2 = __commonJS({
31581
31581
  }
31582
31582
  });
31583
31583
 
31584
- // ../../node_modules/tar-stream/headers.js
31584
+ // ../daemon-core/node_modules/tar-stream/headers.js
31585
31585
  var require_headers = __commonJS({
31586
- "../../node_modules/tar-stream/headers.js"(exports2) {
31586
+ "../daemon-core/node_modules/tar-stream/headers.js"(exports2) {
31587
31587
  "use strict";
31588
31588
  var b4a = require_b4a2();
31589
31589
  var ZEROS = "0000000000000000000";
@@ -31844,9 +31844,9 @@ var require_headers = __commonJS({
31844
31844
  }
31845
31845
  });
31846
31846
 
31847
- // ../../node_modules/tar-stream/extract.js
31847
+ // ../daemon-core/node_modules/tar-stream/extract.js
31848
31848
  var require_extract = __commonJS({
31849
- "../../node_modules/tar-stream/extract.js"(exports2, module2) {
31849
+ "../daemon-core/node_modules/tar-stream/extract.js"(exports2, module2) {
31850
31850
  "use strict";
31851
31851
  var { Writable, Readable, getStreamError } = require_streamx();
31852
31852
  var FIFO = require_fast_fifo();
@@ -32189,9 +32189,9 @@ var require_extract = __commonJS({
32189
32189
  }
32190
32190
  });
32191
32191
 
32192
- // ../../node_modules/tar-stream/constants.js
32192
+ // ../daemon-core/node_modules/tar-stream/constants.js
32193
32193
  var require_constants = __commonJS({
32194
- "../../node_modules/tar-stream/constants.js"(exports2, module2) {
32194
+ "../daemon-core/node_modules/tar-stream/constants.js"(exports2, module2) {
32195
32195
  "use strict";
32196
32196
  var constants = {
32197
32197
  // just for envs without fs
@@ -32210,9 +32210,9 @@ var require_constants = __commonJS({
32210
32210
  }
32211
32211
  });
32212
32212
 
32213
- // ../../node_modules/tar-stream/pack.js
32213
+ // ../daemon-core/node_modules/tar-stream/pack.js
32214
32214
  var require_pack = __commonJS({
32215
- "../../node_modules/tar-stream/pack.js"(exports2, module2) {
32215
+ "../daemon-core/node_modules/tar-stream/pack.js"(exports2, module2) {
32216
32216
  "use strict";
32217
32217
  var { Readable, Writable, getStreamError } = require_streamx();
32218
32218
  var b4a = require_b4a2();
@@ -32445,9 +32445,9 @@ var require_pack = __commonJS({
32445
32445
  }
32446
32446
  });
32447
32447
 
32448
- // ../../node_modules/tar-stream/index.js
32448
+ // ../daemon-core/node_modules/tar-stream/index.js
32449
32449
  var require_tar_stream = __commonJS({
32450
- "../../node_modules/tar-stream/index.js"(exports2) {
32450
+ "../daemon-core/node_modules/tar-stream/index.js"(exports2) {
32451
32451
  "use strict";
32452
32452
  exports2.extract = require_extract();
32453
32453
  exports2.pack = require_pack();
@@ -32690,9 +32690,9 @@ var require_pump = __commonJS({
32690
32690
  }
32691
32691
  });
32692
32692
 
32693
- // ../../node_modules/tar-fs/index.js
32693
+ // ../daemon-core/node_modules/tar-fs/index.js
32694
32694
  var require_tar_fs = __commonJS({
32695
- "../../node_modules/tar-fs/index.js"(exports2) {
32695
+ "../daemon-core/node_modules/tar-fs/index.js"(exports2) {
32696
32696
  "use strict";
32697
32697
  var tar = require_tar_stream();
32698
32698
  var pump = require_pump();
@@ -36556,10 +36556,10 @@ var require_dist3 = __commonJS({
36556
36556
  }
36557
36557
  function getDaemonBuildInfo() {
36558
36558
  if (cached2) return cached2;
36559
- const commit = readInjected(true ? "d424e843d3ebe663ebdd8ca6c46cd47355f45eba" : void 0) ?? "unknown";
36560
- const commitShort = readInjected(true ? "d424e843" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36561
- const version2 = readInjected(true ? "1.0.42-rc.1" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36562
- const builtAt = readInjected(true ? "2026-08-10T14:31:55.387Z" : void 0);
36559
+ const commit = readInjected(true ? "9d57fb32f38be14867c8897aac6af379a1027624" : void 0) ?? "unknown";
36560
+ const commitShort = readInjected(true ? "9d57fb3" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
36561
+ const version2 = readInjected(true ? "1.0.42" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
36562
+ const builtAt = readInjected(true ? "2026-08-10T23:11:18.240Z" : void 0);
36563
36563
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
36564
36564
  return cached2;
36565
36565
  }
@@ -37817,7 +37817,7 @@ var require_dist3 = __commonJS({
37817
37817
  }
37818
37818
  });
37819
37819
  function resolveBuildTrack(env2 = process.env) {
37820
- const injected = true ? "preview" : void 0;
37820
+ const injected = true ? "" : void 0;
37821
37821
  const stamped = typeof injected === "string" ? injected.trim() : "";
37822
37822
  const raw = (stamped || (env2[BUILD_CHANNEL_ENV_VAR] ?? "").trim()).toLowerCase();
37823
37823
  return raw === "preview" || raw === "next" ? "preview" : "stable";
@@ -93131,6 +93131,13 @@ ${marker}`,
93131
93131
  return n;
93132
93132
  }
93133
93133
  var SUBMIT_DELAY_FLOOR_MS = 200;
93134
+ var SEND_IN_FLIGHT_MAX_MS = 3e4;
93135
+ var DUPLICATE_RESEND_WINDOW_MS = 6e4;
93136
+ function hashSendText(text) {
93137
+ let h = 5381;
93138
+ for (let i = 0; i < text.length; i += 1) h = ((h << 5) + h ^ text.charCodeAt(i)) >>> 0;
93139
+ return `${h.toString(36)}:${text.length}`;
93140
+ }
93134
93141
  var fsmDriverSeq = 0;
93135
93142
  var WIN32_SUBMIT_RESEND_GAP_MS = 350;
93136
93143
  var WIN32_SUBMIT_MAX_RESENDS = 14;
@@ -93237,6 +93244,19 @@ ${marker}`,
93237
93244
  // non-busy ("ready") state — same contract as v3's idleSeenOnce.
93238
93245
  readySeenOnce = false;
93239
93246
  pendingSends = [];
93247
+ /** True while a send is written but the FSM has not yet left idle, i.e. the
93248
+ * composer is mid-submit. Blocks a second send from overwriting the first
93249
+ * before the CLI has consumed it (see handleSendMessage). */
93250
+ sendInFlight = false;
93251
+ /** Wall-clock (ms) the in-flight send was written. Bounds sendInFlight so a
93252
+ * send the CLI never visibly consumed cannot wedge the queue forever. */
93253
+ sendInFlightAt = 0;
93254
+ /** Content hash → wall-clock of the last PTY write, for the pre-write
93255
+ * duplicate gate (see isDuplicateResend). */
93256
+ recentSendHashes = /* @__PURE__ */ new Map();
93257
+ /** Pending queued-send drain timer, tracked so shutdown() can cancel it and
93258
+ * a torn-down driver never writes a queued body into a dead PTY. */
93259
+ pendingSendDrainTimer = null;
93240
93260
  pickerInProgress = null;
93241
93261
  delegateTimers = /* @__PURE__ */ new Map();
93242
93262
  specWatcher = null;
@@ -93389,6 +93409,11 @@ ${marker}`,
93389
93409
  clearTimeout(this.win32ModalConfirmTimer);
93390
93410
  this.win32ModalConfirmTimer = null;
93391
93411
  }
93412
+ if (this.pendingSendDrainTimer) {
93413
+ clearTimeout(this.pendingSendDrainTimer);
93414
+ this.pendingSendDrainTimer = null;
93415
+ }
93416
+ this.pendingSends.length = 0;
93392
93417
  this.specWatcher?.close();
93393
93418
  this.adapter.kill();
93394
93419
  }
@@ -93580,12 +93605,14 @@ ${marker}`,
93580
93605
  this.scheduleWakeForState();
93581
93606
  this.scheduleStallWatchdog();
93582
93607
  this.maybeMarkReady();
93608
+ this.drainPendingSends();
93583
93609
  return;
93584
93610
  }
93585
93611
  this.emitStateChanged(forceEmit);
93586
93612
  this.scheduleWakeForState();
93587
93613
  this.scheduleStallWatchdog();
93588
93614
  this.maybeMarkReady();
93615
+ this.drainPendingSends();
93589
93616
  }
93590
93617
  commitTransition(fired, now, ev) {
93591
93618
  const from = this.currentStateId;
@@ -93855,8 +93882,7 @@ ${marker}`,
93855
93882
  if (!st) return;
93856
93883
  if (!st.initial && statusForState(st) === "idle") {
93857
93884
  this.readySeenOnce = true;
93858
- const queued = this.pendingSends.splice(0);
93859
- for (const text of queued) setTimeout(() => this.actuallySendMessage(text), 50);
93885
+ this.drainPendingSends();
93860
93886
  }
93861
93887
  }
93862
93888
  // ────────────────────────────────────────────────────────────────────
@@ -93894,13 +93920,109 @@ ${marker}`,
93894
93920
  // ────────────────────────────────────────────────────────────────────
93895
93921
  // Dashboard commands (identical semantics to v3)
93896
93922
  // ────────────────────────────────────────────────────────────────────
93923
+ /**
93924
+ * SEND-OVERLAP gate. A send may only go straight to the PTY when the machine
93925
+ * is genuinely able to accept one: it has been ready at least once, it is
93926
+ * sitting at an idle prompt right now, and no earlier send is still in flight.
93927
+ * Anything else is queued and drained by drainPendingSends() when the machine
93928
+ * next returns to idle.
93929
+ *
93930
+ * Before the fix this consulted ONLY `readySeenOnce` — a one-shot latch — so
93931
+ * every send after the first ignored the live FSM state and could be written
93932
+ * on top of a still-generating turn, braiding the two bodies in the composer
93933
+ * (see the SEND-OVERLAP note above the constants).
93934
+ */
93897
93935
  handleSendMessage(text) {
93898
- if (!this.readySeenOnce) {
93936
+ if (this.isDuplicateResend(text)) {
93937
+ LOG2.info("FsmDriver", `[${this.specTag()}] send suppressed \u2014 duplicate resend within ${DUPLICATE_RESEND_WINDOW_MS}ms (len=${text.length})`);
93938
+ return;
93939
+ }
93940
+ if (!this.canSendNow()) {
93899
93941
  this.pendingSends.push(text);
93942
+ LOG2.info(
93943
+ "FsmDriver",
93944
+ `[${this.specTag()}] send queued \u2014 ${this.sendBlockedReason()} (len=${text.length}, queued=${this.pendingSends.length})`
93945
+ );
93900
93946
  return;
93901
93947
  }
93948
+ this.beginSend(text);
93949
+ }
93950
+ /** True when a send can be written to the PTY right now. */
93951
+ canSendNow() {
93952
+ if (!this.readySeenOnce) return false;
93953
+ if (this.isSendInFlight()) return false;
93954
+ return this.currentStatus() === "idle";
93955
+ }
93956
+ /** Human-readable reason a send was queued — logged, never used for control flow. */
93957
+ sendBlockedReason() {
93958
+ if (!this.readySeenOnce) return "machine not ready yet";
93959
+ if (this.isSendInFlight()) return `previous send still in flight (${Date.now() - this.sendInFlightAt}ms)`;
93960
+ return `machine is ${this.currentStatus()}`;
93961
+ }
93962
+ /** In-flight latch with its self-expiry applied, so a send the CLI never
93963
+ * visibly consumed cannot wedge the queue permanently. */
93964
+ isSendInFlight() {
93965
+ if (!this.sendInFlight) return false;
93966
+ if (Date.now() - this.sendInFlightAt > SEND_IN_FLIGHT_MAX_MS) {
93967
+ LOG2.warn("FsmDriver", `[${this.specTag()}] in-flight send latch expired after ${SEND_IN_FLIGHT_MAX_MS}ms \u2014 releasing`);
93968
+ this.sendInFlight = false;
93969
+ return false;
93970
+ }
93971
+ return true;
93972
+ }
93973
+ /**
93974
+ * Pre-write duplicate gate. Suppresses a repeat of text that was written to
93975
+ * the PTY within DUPLICATE_RESEND_WINDOW_MS *while that text is still being
93976
+ * processed* — i.e. a send is in flight or the machine has not returned to
93977
+ * idle. A genuine repeat typed at an idle prompt is NOT suppressed: sending
93978
+ * "continue" twice in a row is ordinary use, and silently swallowing the
93979
+ * second one would be a worse defect than the one being fixed.
93980
+ */
93981
+ isDuplicateResend(text) {
93982
+ const now = Date.now();
93983
+ const key2 = hashSendText(text);
93984
+ for (const [candidate, at] of this.recentSendHashes) {
93985
+ if (now - at > DUPLICATE_RESEND_WINDOW_MS) this.recentSendHashes.delete(candidate);
93986
+ }
93987
+ const previous = this.recentSendHashes.get(key2);
93988
+ if (previous === void 0) return false;
93989
+ if (now - previous > DUPLICATE_RESEND_WINDOW_MS) return false;
93990
+ const stillProcessing = this.isSendInFlight() || this.currentStatus() !== "idle" || this.pendingSends.length > 0;
93991
+ return stillProcessing;
93992
+ }
93993
+ /** Mark a send as in flight, record it for the duplicate gate, and write it. */
93994
+ beginSend(text) {
93995
+ this.sendInFlight = true;
93996
+ this.sendInFlightAt = Date.now();
93997
+ this.recentSendHashes.set(hashSendText(text), this.sendInFlightAt);
93902
93998
  this.actuallySendMessage(text);
93903
93999
  }
94000
+ /**
94001
+ * Release the in-flight latch and write the next queued send, if the machine
94002
+ * can take one. Called from the FSM evaluation loop, so it runs on the same
94003
+ * frame the machine reaches idle — the queue never waits for an extra PTY
94004
+ * frame that a quiet CLI would never produce (the same hazard maybeMarkReady
94005
+ * documents for the very first message).
94006
+ */
94007
+ drainPendingSends() {
94008
+ if (!this.readySeenOnce) return;
94009
+ const status = this.currentStatus();
94010
+ if (this.sendInFlight && status !== "idle") {
94011
+ this.sendInFlight = false;
94012
+ }
94013
+ if (status !== "idle") return;
94014
+ if (this.isSendInFlight()) return;
94015
+ if (this.pendingSends.length === 0) return;
94016
+ const next = this.pendingSends.shift();
94017
+ LOG2.info("FsmDriver", `[${this.specTag()}] draining queued send (len=${next.length}, remaining=${this.pendingSends.length})`);
94018
+ if (this.pendingSendDrainTimer) clearTimeout(this.pendingSendDrainTimer);
94019
+ this.pendingSendDrainTimer = setTimeout(() => {
94020
+ this.pendingSendDrainTimer = null;
94021
+ this.beginSend(next);
94022
+ }, 50);
94023
+ this.sendInFlight = true;
94024
+ this.sendInFlightAt = Date.now();
94025
+ }
93904
94026
  actuallySendMessage(text) {
93905
94027
  const sm = this.spec.send_message;
93906
94028
  const perChar = sm.delay_ms_per_char ?? 0;