@adhdev/daemon-core 0.9.82-rc.216 → 0.9.82-rc.217

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
@@ -27948,8 +27948,9 @@ function evaluateCondition(cond, sections, fullScreen, cursor, prevLines, trace,
27948
27948
  const endRow = cursor.row;
27949
27949
  const currentSlice = curLines.slice(startRow, endRow).join("\n");
27950
27950
  const prevSlice = prevLines.slice(startRow, endRow).join("\n");
27951
- const result = currentSlice !== prevSlice;
27952
- trace.push({ kind: "section", text: `state[${stateId}] changed cond cursor_above=${cond.cursor_above} rows[${startRow},${endRow}) changed=${result}` });
27951
+ const didChange = currentSlice !== prevSlice;
27952
+ const result = cond.changed ? didChange : !didChange;
27953
+ trace.push({ kind: "section", text: `state[${stateId}] changed cond cursor_above=${cond.cursor_above} rows[${startRow},${endRow}) changed=${didChange} expected=${cond.changed} result=${result}` });
27953
27954
  return result;
27954
27955
  }
27955
27956
  if (isRegexCondition(cond)) {
@@ -28672,7 +28673,8 @@ var SCHEMA_V3 = {
28672
28673
  "required": ["cursor_above", "changed"],
28673
28674
  "properties": {
28674
28675
  "cursor_above": { "type": "integer", "minimum": 1 },
28675
- "changed": { "type": "boolean", "const": true }
28676
+ "changed": { "type": "boolean" },
28677
+ "stable_ms": { "type": "integer", "minimum": 0 }
28676
28678
  }
28677
28679
  },
28678
28680
  "allCondition": {
@@ -29148,6 +29150,13 @@ init_logger();
29148
29150
  var STARTUP_GRACE_MS = 2500;
29149
29151
  var BUSY_HOLD_MS = 6e3;
29150
29152
  var SUBMIT_DELAY_FLOOR_MS = 200;
29153
+ function collectChangedConditions(when) {
29154
+ if (!when) return [];
29155
+ if ("cursor_above" in when && "changed" in when) return [when];
29156
+ if ("all" in when) return when.all.flatMap((c) => collectChangedConditions(c));
29157
+ if ("any" in when) return when.any.flatMap((c) => collectChangedConditions(c));
29158
+ return [];
29159
+ }
29151
29160
  function countNewlines(s) {
29152
29161
  let n = 0;
29153
29162
  for (let i = 0; i < s.length; i += 1) if (s.charCodeAt(i) === 10) n += 1;
@@ -29253,6 +29262,9 @@ var SpecDriver = class {
29253
29262
  * Used by screen_active_hold_ms to suppress idle downshifts while
29254
29263
  * the terminal is still actively updating. */
29255
29264
  lastScreenChangedAt = 0;
29265
+ /** Per-cursor_above region last-changed timestamps for stable_ms tracking.
29266
+ * Key: cursor_above value. Value: last time that region changed. */
29267
+ regionLastChangedAt = /* @__PURE__ */ new Map();
29256
29268
  /** Timer that re-runs evaluate() once the hold window expires. Needed
29257
29269
  * because the PTY stops emitting once the agent finishes; without an
29258
29270
  * explicit wake-up there's nothing to trigger the busy → idle
@@ -29457,18 +29469,47 @@ var SpecDriver = class {
29457
29469
  const cursor = this.adapter.getCursorPosition();
29458
29470
  const currentLines = screen.split("\n").map((l) => l.endsWith("\r") ? l.slice(0, -1) : l);
29459
29471
  const ev = evaluate(this.spec, screen, cursor, this.prevScreenLines.length > 0 ? this.prevScreenLines : void 0);
29472
+ const now = Date.now();
29460
29473
  if (this.prevScreenLines.length > 0 && currentLines.join("\n") !== this.prevScreenLines.join("\n")) {
29461
- this.lastScreenChangedAt = Date.now();
29474
+ this.lastScreenChangedAt = now;
29475
+ }
29476
+ if (cursor && this.prevScreenLines.length > 0) {
29477
+ for (const state of this.spec.states) {
29478
+ const conditions = collectChangedConditions(state.when);
29479
+ for (const cond of conditions) {
29480
+ if (cond.stable_ms == null) continue;
29481
+ const startRow = Math.max(0, cursor.row - cond.cursor_above);
29482
+ const endRow = cursor.row;
29483
+ const cur = currentLines.slice(startRow, endRow).join("\n");
29484
+ const prev = this.prevScreenLines.slice(startRow, endRow).join("\n");
29485
+ if (cur !== prev) this.regionLastChangedAt.set(cond.cursor_above, now);
29486
+ }
29487
+ }
29462
29488
  }
29463
29489
  this.prevScreenLines = currentLines;
29464
29490
  let evState = ev.state;
29465
29491
  const busyHoldMs = this.spec.debounce?.busy_hold_ms ?? BUSY_HOLD_MS;
29466
29492
  if (this.currentStateId === "busy" && evState.id === "idle") {
29467
- const ageMs = Date.now() - this.lastBusyAt;
29493
+ const ageMs = now - this.lastBusyAt;
29468
29494
  if (ageMs < busyHoldMs) {
29469
29495
  evState = this.lastBusyState ?? evState;
29470
29496
  }
29471
29497
  }
29498
+ if (evState.id === (this.spec.default_state ?? "idle") && cursor) {
29499
+ const stableConditions = collectChangedConditions(
29500
+ this.spec.states.find((s) => s.id === evState.id)?.when
29501
+ ).filter((c) => c.changed === false && c.stable_ms != null);
29502
+ for (const cond of stableConditions) {
29503
+ const lastChanged = this.regionLastChangedAt.get(cond.cursor_above) ?? 0;
29504
+ const stableMs = cond.stable_ms;
29505
+ const stableAge = lastChanged > 0 ? now - lastChanged : Infinity;
29506
+ if (stableAge < stableMs) {
29507
+ evState = this.lastBusyState ?? { id: "busy", label: "Generating", title: null };
29508
+ this.scheduleBusyExpiry(stableMs - stableAge + 50);
29509
+ break;
29510
+ }
29511
+ }
29512
+ }
29472
29513
  const idleStateId = this.spec.default_state ?? "idle";
29473
29514
  const isModalState = (id) => id !== null && id !== "busy" && id !== idleStateId;
29474
29515
  if (isModalState(this.currentStateId) && evState.id === "busy") {
@@ -29481,7 +29522,6 @@ var SpecDriver = class {
29481
29522
  const screenActiveHoldMs = this.spec.debounce?.screen_active_hold_ms;
29482
29523
  let busyWakeMs = busyHoldMs;
29483
29524
  const postModalGraceMs = busyHoldMs;
29484
- const now = Date.now();
29485
29525
  const recentlyInModal = isModalState(this.currentStateId) || this.lastModalAt > 0 && now - this.lastModalAt < postModalGraceMs;
29486
29526
  const recentlyLeftModal = !recentlyInModal && this.lastModalExitAt > 0 && now - this.lastModalExitAt < postModalGraceMs;
29487
29527
  const screenActiveMs = screenActiveHoldMs ?? 0;
@@ -29493,15 +29533,14 @@ var SpecDriver = class {
29493
29533
  if (evState.id === "busy" && completionIdleRule && !recentlyInModal && !recentlyLeftModal && !screenIsActive) {
29494
29534
  const completionKey = matchesCompletionIdleRule(this.spec, ev, screen);
29495
29535
  if (completionKey) {
29496
- const now2 = Date.now();
29497
29536
  if (completionKey !== this.completionIdleKey) {
29498
29537
  this.completionIdleKey = completionKey;
29499
- this.completionIdleFirstSeenAt = now2;
29538
+ this.completionIdleFirstSeenAt = now;
29500
29539
  LOG.debug("SpecDriver", `[${this.opts.specPath.split("/").slice(-3).join("/")}] completion_idle_after matched: key="${completionKey}"`);
29501
29540
  }
29502
29541
  const holdMs = Math.max(0, completionIdleRule.hold_ms || 0);
29503
29542
  const forceAfterMs = typeof completionIdleRule.force_after_ms === "number" ? completionIdleRule.force_after_ms : null;
29504
- const ageMs = now2 - this.completionIdleFirstSeenAt;
29543
+ const ageMs = now - this.completionIdleFirstSeenAt;
29505
29544
  if (ageMs >= holdMs) {
29506
29545
  const targetMatches = matchesCompletionIdleTargetState(this.spec, ev, screen, cursor);
29507
29546
  const forced = !targetMatches && forceAfterMs !== null && ageMs >= holdMs + forceAfterMs;