@adhdev/daemon-core 0.9.82-rc.197 → 0.9.82-rc.198

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.mjs CHANGED
@@ -14689,8 +14689,8 @@ async function detectIDEs(providerLoader) {
14689
14689
  if (existsSync15(bundledCli)) resolvedCli = bundledCli;
14690
14690
  }
14691
14691
  if (!resolvedCli && appPath && os29 === "win32") {
14692
- const { dirname: dirname11 } = await import("path");
14693
- const appDir = dirname11(appPath);
14692
+ const { dirname: dirname12 } = await import("path");
14693
+ const appDir = dirname12(appPath);
14694
14694
  const candidates = [
14695
14695
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
14696
14696
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -27173,7 +27173,15 @@ var SpecDriver = class {
27173
27173
  * explicit wake-up there's nothing to trigger the busy → idle
27174
27174
  * downshift. */
27175
27175
  busyExpiryTimer = null;
27176
+ /** Pending idle-commit timer. Armed when the evaluator first returns idle;
27177
+ * fires after idle_hold_ms if no non-idle reading has cancelled it. */
27178
+ idleHoldTimer = null;
27179
+ /** State snapshot captured when the idle hold was armed — emitted on commit. */
27180
+ pendingIdleState = null;
27176
27181
  specWatcher = null;
27182
+ /** Ring buffer of committed state transitions (max 50). */
27183
+ stateHistory = [];
27184
+ prevStateAt = 0;
27177
27185
  /** Subscribe to outbound events. Returns an unsubscribe fn. */
27178
27186
  subscribe(listener) {
27179
27187
  this.listeners.add(listener);
@@ -27224,9 +27232,40 @@ var SpecDriver = class {
27224
27232
  shutdown() {
27225
27233
  for (const t of this.delegateTimers.values()) clearTimeout(t);
27226
27234
  this.delegateTimers.clear();
27235
+ this.cancelIdleHold();
27236
+ if (this.busyExpiryTimer) {
27237
+ clearTimeout(this.busyExpiryTimer);
27238
+ this.busyExpiryTimer = null;
27239
+ }
27227
27240
  this.specWatcher?.close();
27228
27241
  this.adapter.kill();
27229
27242
  }
27243
+ cancelIdleHold() {
27244
+ if (this.idleHoldTimer) {
27245
+ clearTimeout(this.idleHoldTimer);
27246
+ this.idleHoldTimer = null;
27247
+ }
27248
+ this.pendingIdleState = null;
27249
+ }
27250
+ pushHistory(stateId, label) {
27251
+ const now = Date.now();
27252
+ const durationMs = this.prevStateAt > 0 ? now - this.prevStateAt : 0;
27253
+ this.prevStateAt = now;
27254
+ this.stateHistory.push({ stateId, label, at: now, durationMs });
27255
+ if (this.stateHistory.length > 50) this.stateHistory.shift();
27256
+ }
27257
+ getStateHistory() {
27258
+ return this.stateHistory;
27259
+ }
27260
+ getLastBusyAt() {
27261
+ return this.lastBusyAt;
27262
+ }
27263
+ hasIdleHoldPending() {
27264
+ return this.idleHoldTimer !== null;
27265
+ }
27266
+ getSpecPath() {
27267
+ return this.opts.specPath;
27268
+ }
27230
27269
  // ────────────────────────────────────────────────────────────────────
27231
27270
  // Loading & adapter wiring
27232
27271
  // ────────────────────────────────────────────────────────────────────
@@ -27250,7 +27289,10 @@ var SpecDriver = class {
27250
27289
  }
27251
27290
  armSpecWatcher() {
27252
27291
  try {
27253
- this.specWatcher = fs10.watch(this.opts.specPath, { persistent: false }, () => {
27292
+ const dir = path19.dirname(this.opts.specPath);
27293
+ const base = path19.basename(this.opts.specPath);
27294
+ this.specWatcher = fs10.watch(dir, { persistent: false }, (_event, filename) => {
27295
+ if (filename && filename !== base) return;
27254
27296
  const res = loadSpec(this.opts.specPath);
27255
27297
  if (!res.ok) {
27256
27298
  this.emit({ kind: "spec_error", errors: res.errors });
@@ -27334,7 +27376,46 @@ var SpecDriver = class {
27334
27376
  if (evState.id === "busy") {
27335
27377
  this.lastBusyAt = Date.now();
27336
27378
  this.lastBusyState = evState;
27379
+ this.cancelIdleHold();
27337
27380
  this.scheduleBusyExpiry(busyWakeMs);
27381
+ } else if (evState.id !== this.currentStateId && evState.id !== "busy") {
27382
+ if (evState.id !== (this.spec.default_state ?? "idle")) {
27383
+ this.cancelIdleHold();
27384
+ }
27385
+ }
27386
+ const idleHoldMs = this.spec.debounce?.idle_hold_ms ?? 0;
27387
+ const isIdleState = evState.id === (this.spec.default_state ?? "idle");
27388
+ if (isIdleState && idleHoldMs > 0 && this.currentStateId !== evState.id) {
27389
+ if (!this.idleHoldTimer) {
27390
+ this.pendingIdleState = evState;
27391
+ this.idleHoldTimer = setTimeout(() => {
27392
+ this.idleHoldTimer = null;
27393
+ const committed = this.pendingIdleState;
27394
+ this.pendingIdleState = null;
27395
+ if (!committed) return;
27396
+ LOG.debug("SpecDriver", `[${this.opts.specPath.split("/").slice(-3).join("/")}] idleHold committed after ${idleHoldMs}ms`);
27397
+ this.currentStateId = committed.id;
27398
+ this.currentEval = ev;
27399
+ this.pushHistory(committed.id, committed.label);
27400
+ this.emit({
27401
+ kind: "state_changed",
27402
+ state: committed,
27403
+ modal: null,
27404
+ controls: ev.controls.map((c) => ({ id: c.id, label: c.label, action_type: c.actionType }))
27405
+ });
27406
+ this.armOrCancelDelegateTimers(committed.id);
27407
+ if (this.opts.emitTrace) this.emit({ kind: "spec_trace", entries: ev.trace });
27408
+ }, idleHoldMs);
27409
+ }
27410
+ this.currentEval = ev;
27411
+ const graceMs2 = this.spec.debounce?.startup_grace_ms ?? STARTUP_GRACE_MS;
27412
+ if (!this.idleSeenOnce && Date.now() - this.startedAtMs >= graceMs2) {
27413
+ this.idleSeenOnce = true;
27414
+ const queued = this.pendingSends.splice(0);
27415
+ for (const text of queued) setTimeout(() => this.actuallySendMessage(text), 50);
27416
+ }
27417
+ if (this.pickerInProgress) this.tryAdvancePicker(screen);
27418
+ return;
27338
27419
  }
27339
27420
  const changed = forceEmit || evState.id !== this.currentStateId || !shallowSameModal(ev, this.currentEval) || !shallowSameControls(ev, this.currentEval);
27340
27421
  if (this.pickerInProgress) this.tryAdvancePicker(screen);
@@ -27350,6 +27431,7 @@ var SpecDriver = class {
27350
27431
  }
27351
27432
  if (changed) {
27352
27433
  this.currentStateId = evState.id;
27434
+ this.pushHistory(evState.id, evState.label);
27353
27435
  this.emit({
27354
27436
  kind: "state_changed",
27355
27437
  state: evState,
@@ -27783,7 +27865,11 @@ var SpecCliAdapter = class {
27783
27865
  activeInteractivePrompt: this.activeInteractivePrompt,
27784
27866
  exited: this.exited,
27785
27867
  screen,
27786
- sections
27868
+ sections,
27869
+ stateHistory: this.driver.getStateHistory(),
27870
+ idleHoldPending: this.driver.hasIdleHoldPending(),
27871
+ lastBusyAt: this.driver.getLastBusyAt(),
27872
+ specPath: this.driver.getSpecPath()
27787
27873
  };
27788
27874
  }
27789
27875
  getRuntimeMetadata() {
@@ -33327,17 +33413,17 @@ function parseTranscriptFile(filePath, sessionId, workspaceFallback) {
33327
33413
  }
33328
33414
  function readSession(sessionPath) {
33329
33415
  if (!sessionPath || !path25.isAbsolute(sessionPath)) return null;
33330
- const basename13 = path25.basename(sessionPath, ".jsonl");
33331
- if (!isSafeSessionId(basename13)) return null;
33416
+ const basename14 = path25.basename(sessionPath, ".jsonl");
33417
+ if (!isSafeSessionId(basename14)) return null;
33332
33418
  if (!fs14.existsSync(sessionPath)) return null;
33333
33419
  const sourceMtimeMs = statMtimeMs(sessionPath);
33334
- const messages = parseTranscriptFile(sessionPath, basename13);
33420
+ const messages = parseTranscriptFile(sessionPath, basename14);
33335
33421
  if (messages.length === 0) return null;
33336
33422
  const firstSystem = messages.find((m) => m.kind === "session_start");
33337
33423
  const workspace = firstSystem?.workspace || firstSystem?.content || void 0;
33338
33424
  return {
33339
33425
  messages,
33340
- providerSessionId: basename13,
33426
+ providerSessionId: basename14,
33341
33427
  source: "provider-native",
33342
33428
  sourcePath: sessionPath,
33343
33429
  sourceMtimeMs,
@@ -33539,8 +33625,8 @@ function readSession2(sessionPath) {
33539
33625
  if (!fs15.existsSync(sessionPath)) return null;
33540
33626
  const meta = readSessionMeta(sessionPath);
33541
33627
  const metaId = String(meta?.id ?? "").trim();
33542
- const basename13 = path26.basename(sessionPath, ".jsonl");
33543
- const uuidMatch = basename13.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i);
33628
+ const basename14 = path26.basename(sessionPath, ".jsonl");
33629
+ const uuidMatch = basename14.match(/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/i);
33544
33630
  const filenameUuid2 = uuidMatch ? uuidMatch[1] : "";
33545
33631
  if (metaId && filenameUuid2 && metaId !== filenameUuid2) return null;
33546
33632
  const sessionId = metaId || filenameUuid2;
@@ -40752,6 +40838,21 @@ var DaemonCommandRouter = class {
40752
40838
  } : null
40753
40839
  };
40754
40840
  }
40841
+ case "get_spec_debug": {
40842
+ const sessionId = typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : typeof args?.sessionId === "string" ? args.sessionId.trim() : "";
40843
+ if (!sessionId) return { success: false, error: "targetSessionId required" };
40844
+ const target = this.deps.sessionRegistry.get(sessionId);
40845
+ if (!target) return { success: false, error: "Session not found", sessionId };
40846
+ const adapter = this.deps.cliManager.findAdapter(target.providerType, { instanceKey: sessionId })?.adapter;
40847
+ const snapshot = adapter && typeof adapter.getDebugSnapshot === "function" ? adapter.getDebugSnapshot() : null;
40848
+ return {
40849
+ success: true,
40850
+ sessionId,
40851
+ providerType: target.providerType,
40852
+ isSpecProvider: snapshot !== null,
40853
+ snapshot
40854
+ };
40855
+ }
40755
40856
  // ── User-level coordinator-prompt files (~/.adhdev/coordinator-prompts/).
40756
40857
  // These live on this daemon's filesystem and never sync to the
40757
40858
  // cloud / other daemons — they're per-machine config. The
@@ -42079,7 +42180,7 @@ ${ptyResult.output.slice(-2e3)}`);
42079
42180
  };
42080
42181
  }
42081
42182
  const { existsSync: existsSync39, readFileSync: readFileSync33, writeFileSync: writeFileSync21, copyFileSync: copyFileSync4, mkdirSync: mkdirSync19 } = await import("fs");
42082
- const { dirname: dirname11 } = await import("path");
42183
+ const { dirname: dirname12 } = await import("path");
42083
42184
  const mcpConfigPath = coordinatorSetup.configPath;
42084
42185
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
42085
42186
  let hermesBaseConfig = null;
@@ -42114,7 +42215,7 @@ ${ptyResult.output.slice(-2e3)}`);
42114
42215
  };
42115
42216
  }
42116
42217
  try {
42117
- mkdirSync19(dirname11(mcpConfigPath), { recursive: true });
42218
+ mkdirSync19(dirname12(mcpConfigPath), { recursive: true });
42118
42219
  } catch (error) {
42119
42220
  const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
42120
42221
  LOG.error("MeshCoordinator", message);
@@ -42124,7 +42225,7 @@ ${ptyResult.output.slice(-2e3)}`);
42124
42225
  const hadExistingMcpConfig = existsSync39(mcpConfigPath);
42125
42226
  let existingMcpConfig = hermesBaseConfig?.config || {};
42126
42227
  if (hermesBaseConfig) {
42127
- copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname11(mcpConfigPath));
42228
+ copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname12(mcpConfigPath));
42128
42229
  }
42129
42230
  if (hadExistingMcpConfig) {
42130
42231
  try {
@@ -42162,7 +42263,7 @@ ${ptyResult.output.slice(-2e3)}`);
42162
42263
  const cliArgs = [];
42163
42264
  const launchEnv = {};
42164
42265
  if (configFormat === "hermes_config_yaml") {
42165
- launchEnv.HERMES_HOME = dirname11(mcpConfigPath);
42266
+ launchEnv.HERMES_HOME = dirname12(mcpConfigPath);
42166
42267
  launchEnv.HERMES_IGNORE_USER_CONFIG = "";
42167
42268
  }
42168
42269
  let autoImportContextFilePath;
@@ -51104,11 +51205,11 @@ init_parse_session();
51104
51205
  // src/providers/sdk/v1/fixture-tooling/replay.ts
51105
51206
  init_provider_cli_shared();
51106
51207
  import { readFileSync as readFileSync31 } from "fs";
51107
- import { dirname as dirname9, resolve as resolve21 } from "path";
51208
+ import { dirname as dirname10, resolve as resolve21 } from "path";
51108
51209
 
51109
51210
  // src/providers/sdk/v1/validators/taint.ts
51110
51211
  import { readFileSync as readFileSync32, existsSync as existsSync38 } from "fs";
51111
- import { resolve as resolve22, dirname as dirname10, join as join43 } from "path";
51212
+ import { resolve as resolve22, dirname as dirname11, join as join43 } from "path";
51112
51213
 
51113
51214
  // src/providers/sdk/v1/validators/index.ts
51114
51215
  init_manifest();