@adhdev/daemon-standalone 1.0.34 → 1.0.35-rc.2

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
@@ -33319,10 +33319,10 @@ var require_dist3 = __commonJS({
33319
33319
  }
33320
33320
  function getDaemonBuildInfo() {
33321
33321
  if (cached2) return cached2;
33322
- const commit = readInjected(true ? "65e293b631711246fb672d34f817058f4b78ef74" : void 0) ?? "unknown";
33323
- const commitShort = readInjected(true ? "65e293b" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33324
- const version2 = readInjected(true ? "1.0.34" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33325
- const builtAt = readInjected(true ? "2026-08-04T14:54:57.283Z" : void 0);
33322
+ const commit = readInjected(true ? "3875b913f032a9f2012318bcb7904a2c96f6f965" : void 0) ?? "unknown";
33323
+ const commitShort = readInjected(true ? "3875b913" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
33324
+ const version2 = readInjected(true ? "1.0.35-rc.2" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
33325
+ const builtAt = readInjected(true ? "2026-08-05T03:02:23.471Z" : void 0);
33326
33326
  cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
33327
33327
  return cached2;
33328
33328
  }
@@ -35186,11 +35186,11 @@ child.on('exit', () => process.exit(0));
35186
35186
  fs32.writeFileSync(temp, contents, mode === void 0 ? "utf-8" : { encoding: "utf-8", mode });
35187
35187
  fs32.renameSync(temp, file2);
35188
35188
  }
35189
- function installClaudeStatusline(env2 = process.env) {
35189
+ function installClaudeStatusline2(env2 = process.env) {
35190
35190
  const paths = resolveInstallPaths(env2);
35191
35191
  const settingsResult = readJsonFile(paths.settingsFile);
35192
35192
  if (settingsResult.kind === "invalid") {
35193
- throw new StatuslineInstallError(
35193
+ throw new StatuslineInstallError2(
35194
35194
  `${settingsResult.reason}. Fix or move the file, then retry.`
35195
35195
  );
35196
35196
  }
@@ -35258,11 +35258,11 @@ child.on('exit', () => process.exit(0));
35258
35258
  statusLine
35259
35259
  };
35260
35260
  }
35261
- function uninstallClaudeStatusline(env2 = process.env) {
35261
+ function uninstallClaudeStatusline2(env2 = process.env) {
35262
35262
  const paths = resolveInstallPaths(env2);
35263
35263
  const settingsResult = readJsonFile(paths.settingsFile);
35264
35264
  if (settingsResult.kind === "invalid") {
35265
- throw new StatuslineInstallError(
35265
+ throw new StatuslineInstallError2(
35266
35266
  `${settingsResult.reason}. Fix the file by hand, then retry.`
35267
35267
  );
35268
35268
  }
@@ -35303,7 +35303,7 @@ child.on('exit', () => process.exit(0));
35303
35303
  } catch {
35304
35304
  }
35305
35305
  }
35306
- function readStatuslineStatus(env2 = process.env) {
35306
+ function readStatuslineStatus2(env2 = process.env) {
35307
35307
  const paths = resolveInstallPaths(env2);
35308
35308
  const settingsResult = readJsonFile(paths.settingsFile);
35309
35309
  const settings = settingsResult.kind === "ok" ? settingsResult.value : {};
@@ -35322,7 +35322,7 @@ child.on('exit', () => process.exit(0));
35322
35322
  var fs32;
35323
35323
  var path52;
35324
35324
  var WRAPPER_MARKER;
35325
- var StatuslineInstallError;
35325
+ var StatuslineInstallError2;
35326
35326
  var init_install = __esm2({
35327
35327
  "src/quota/statusline/install.ts"() {
35328
35328
  "use strict";
@@ -35332,7 +35332,7 @@ child.on('exit', () => process.exit(0));
35332
35332
  init_paths();
35333
35333
  init_wrapper_source();
35334
35334
  WRAPPER_MARKER = "adhdev-statusline";
35335
- StatuslineInstallError = class extends Error {
35335
+ StatuslineInstallError2 = class extends Error {
35336
35336
  };
35337
35337
  }
35338
35338
  });
@@ -35362,7 +35362,7 @@ child.on('exit', () => process.exit(0));
35362
35362
  }
35363
35363
  return windowFromPercent(record2.usedPercent, windowMinutes2, record2.resetsAt);
35364
35364
  }
35365
- async function fetchClaudeQuota(overrides = {}) {
35365
+ async function fetchClaudeQuota2(overrides = {}) {
35366
35366
  const deps = resolveDeps(overrides);
35367
35367
  const paths = resolveInstallPaths(deps.env);
35368
35368
  let raw;
@@ -35419,7 +35419,7 @@ child.on('exit', () => process.exit(0));
35419
35419
  function missingSnapshotFailure(env2) {
35420
35420
  let installed = false;
35421
35421
  try {
35422
- installed = readStatuslineStatus(env2).installed;
35422
+ installed = readStatuslineStatus2(env2).installed;
35423
35423
  } catch {
35424
35424
  }
35425
35425
  return quotaFailure(
@@ -35538,7 +35538,7 @@ child.on('exit', () => process.exit(0));
35538
35538
  }
35539
35539
  };
35540
35540
  }
35541
- async function fetchCodexQuota(overrides = {}) {
35541
+ async function fetchCodexQuota2(overrides = {}) {
35542
35542
  const deps = resolveDeps(overrides);
35543
35543
  return new Promise((resolve29) => {
35544
35544
  let child;
@@ -35861,7 +35861,7 @@ child.on('exit', () => process.exit(0));
35861
35861
  const at = new Date(header).getTime();
35862
35862
  return Number.isNaN(at) ? void 0 : at;
35863
35863
  }
35864
- async function fetchKimiQuota(overrides = {}) {
35864
+ async function fetchKimiQuota2(overrides = {}) {
35865
35865
  const deps = resolveDeps(overrides);
35866
35866
  const credentialsResult = readCredentials(deps);
35867
35867
  if (credentialsResult.kind === "missing") {
@@ -36009,11 +36009,19 @@ child.on('exit', () => process.exit(0));
36009
36009
  hasRecentCliActivity: () => hasRecentCliActivity(components.instanceManager.collectHotChatSessionStates())
36010
36010
  });
36011
36011
  }
36012
+ function refreshQuotaCacheOnBoot() {
36013
+ if (bootRefreshInFlight || readQuotaCache() !== void 0) return;
36014
+ bootRefreshInFlight = true;
36015
+ void refreshQuotaCacheOnce().catch((e) => LOG2.warn("Quota", `Boot quota refresh failed: ${e?.message || e}`)).finally(() => {
36016
+ bootRefreshInFlight = false;
36017
+ });
36018
+ }
36012
36019
  var QUOTA_REFRESH_INTERVAL_MS;
36013
36020
  var QUOTA_ACTIVITY_WINDOW_MS;
36014
36021
  var REFRESHERS;
36015
36022
  var cache;
36016
36023
  var WORKING_STATUSES;
36024
+ var bootRefreshInFlight;
36017
36025
  var init_refresh = __esm2({
36018
36026
  "src/quota/refresh.ts"() {
36019
36027
  "use strict";
@@ -36024,9 +36032,9 @@ child.on('exit', () => process.exit(0));
36024
36032
  QUOTA_REFRESH_INTERVAL_MS = 15 * 60 * 1e3;
36025
36033
  QUOTA_ACTIVITY_WINDOW_MS = 20 * 60 * 1e3;
36026
36034
  REFRESHERS = [
36027
- { provider: "claude-cli", fetch: () => fetchClaudeQuota() },
36028
- { provider: "codex-cli", fetch: () => fetchCodexQuota() },
36029
- { provider: "kimi", fetch: () => fetchKimiQuota() }
36035
+ { provider: "claude-cli", fetch: () => fetchClaudeQuota2() },
36036
+ { provider: "codex-cli", fetch: () => fetchCodexQuota2() },
36037
+ { provider: "kimi", fetch: () => fetchKimiQuota2() }
36030
36038
  ];
36031
36039
  cache = /* @__PURE__ */ new Map();
36032
36040
  WORKING_STATUSES = /* @__PURE__ */ new Set([
@@ -36039,6 +36047,7 @@ child.on('exit', () => process.exit(0));
36039
36047
  "no_progress",
36040
36048
  "long_generating"
36041
36049
  ]);
36050
+ bootRefreshInFlight = false;
36042
36051
  }
36043
36052
  });
36044
36053
  function buildLocalNodeFacts(deps) {
@@ -39386,6 +39395,10 @@ Next step: ${nextStep}`;
39386
39395
  }
39387
39396
  return { attempt, opened: inserted };
39388
39397
  }
39398
+ function mergeLegacyHint(legacy, sessionId) {
39399
+ if (!legacy) return sessionId ? { sessionId } : void 0;
39400
+ return { ...sessionId ? { sessionId } : {}, ...legacy };
39401
+ }
39389
39402
  function ensureLegacyTurnAttempt(args) {
39390
39403
  const store = MeshRuntimeStore.getInstance();
39391
39404
  const seq2 = typeof args.dispatchNonce === "number" ? args.dispatchNonce : 0;
@@ -39438,7 +39451,7 @@ Next step: ${nextStep}`;
39438
39451
  const nowIso = new Date(nowMs).toISOString();
39439
39452
  const attempt = resolveAttemptForTask(args.meshId, args.taskId, {
39440
39453
  attemptId: args.attemptId,
39441
- legacy: args.legacy ?? (args.sessionId ? { sessionId: args.sessionId } : void 0)
39454
+ legacy: mergeLegacyHint(args.legacy, args.sessionId)
39442
39455
  });
39443
39456
  if (!attempt) return null;
39444
39457
  const current = store.getCurrentTurnAttempt(args.meshId, args.taskId);
@@ -39515,7 +39528,7 @@ Next step: ${nextStep}`;
39515
39528
  const nowIso = new Date(nowMs).toISOString();
39516
39529
  const attempt = resolveAttemptForTask(args.meshId, args.taskId, {
39517
39530
  attemptId: args.attemptId,
39518
- legacy: args.legacy ?? (args.sessionId ? { sessionId: args.sessionId } : void 0)
39531
+ legacy: mergeLegacyHint(args.legacy, args.sessionId)
39519
39532
  });
39520
39533
  if (!attempt) return null;
39521
39534
  const current = store.getCurrentTurnAttempt(args.meshId, args.taskId);
@@ -39803,7 +39816,7 @@ Next step: ${nextStep}`;
39803
39816
  const nowIso = new Date(nowMs).toISOString();
39804
39817
  const attempt = resolveAttemptForTask(proposal.meshId, proposal.taskId, {
39805
39818
  attemptId: proposal.attemptId,
39806
- legacy: proposal.legacy ?? (proposal.sessionId ? { sessionId: proposal.sessionId } : void 0)
39819
+ legacy: mergeLegacyHint(proposal.legacy, proposal.sessionId)
39807
39820
  });
39808
39821
  if (!attempt) {
39809
39822
  noteRejectedProposal("unknown_attempt");
@@ -39995,6 +40008,92 @@ Next step: ${nextStep}`;
39995
40008
  return [];
39996
40009
  }
39997
40010
  }
40011
+ function reclaimOrphanedTurnAttempts(meshId, nowMs = Date.now()) {
40012
+ const result = { closed: 0, skipped: 0 };
40013
+ let rows;
40014
+ try {
40015
+ rows = MeshRuntimeStore.getInstance().listSupersededNonterminalTurnAttempts(meshId);
40016
+ } catch {
40017
+ return result;
40018
+ }
40019
+ if (rows.length === 0) return result;
40020
+ const store = MeshRuntimeStore.getInstance();
40021
+ const nowIso = new Date(nowMs).toISOString();
40022
+ for (const row of rows) {
40023
+ try {
40024
+ const { committed } = store.commitTurnAttemptTerminal(
40025
+ row.attemptId,
40026
+ "cancelled",
40027
+ SUPERSEDED_BY_ATTEMPT_REASON,
40028
+ nowIso
40029
+ );
40030
+ if (committed) {
40031
+ result.closed += 1;
40032
+ store.insertTurnEvent({
40033
+ eventId: (0, import_crypto5.randomUUID)(),
40034
+ meshId,
40035
+ attemptId: row.attemptId,
40036
+ taskId: row.taskId,
40037
+ kind: "cancelled",
40038
+ dedupeKey: SUPERSEDED_BY_ATTEMPT_REASON,
40039
+ occurredAtMs: nowMs,
40040
+ recordedAt: nowIso
40041
+ });
40042
+ } else {
40043
+ result.skipped += 1;
40044
+ }
40045
+ } catch {
40046
+ result.skipped += 1;
40047
+ }
40048
+ }
40049
+ if (result.closed > 0) {
40050
+ LOG2.info("TurnLedger", `Orphan reclaim: closed ${result.closed} superseded nonterminal turn attempt(s) for mesh ${meshId}${result.skipped > 0 ? ` (${result.skipped} skipped \u2014 already terminal)` : ""}`);
40051
+ }
40052
+ return result;
40053
+ }
40054
+ function reclaimQueueTerminatedTurnAttempts(meshId, nowMs = Date.now()) {
40055
+ const result = { closed: 0, skipped: 0 };
40056
+ let rows;
40057
+ try {
40058
+ rows = MeshRuntimeStore.getInstance().listQueueTerminatedNonterminalTurnAttempts(meshId);
40059
+ } catch {
40060
+ return result;
40061
+ }
40062
+ if (rows.length === 0) return result;
40063
+ const store = MeshRuntimeStore.getInstance();
40064
+ const nowIso = new Date(nowMs).toISOString();
40065
+ for (const row of rows) {
40066
+ try {
40067
+ const { committed } = store.commitTurnAttemptTerminal(
40068
+ row.attemptId,
40069
+ "cancelled",
40070
+ SUPERSEDED_BY_QUEUE_TERMINAL_REASON,
40071
+ nowIso
40072
+ );
40073
+ if (committed) {
40074
+ result.closed += 1;
40075
+ store.insertTurnEvent({
40076
+ eventId: (0, import_crypto5.randomUUID)(),
40077
+ meshId,
40078
+ attemptId: row.attemptId,
40079
+ taskId: row.taskId,
40080
+ kind: "cancelled",
40081
+ dedupeKey: SUPERSEDED_BY_QUEUE_TERMINAL_REASON,
40082
+ occurredAtMs: nowMs,
40083
+ recordedAt: nowIso
40084
+ });
40085
+ } else {
40086
+ result.skipped += 1;
40087
+ }
40088
+ } catch {
40089
+ result.skipped += 1;
40090
+ }
40091
+ }
40092
+ if (result.closed > 0) {
40093
+ LOG2.info("TurnLedger", `Queue-terminal reclaim: closed ${result.closed} nonterminal turn attempt(s) whose queue row already finished for mesh ${meshId}${result.skipped > 0 ? ` (${result.skipped} skipped \u2014 already terminal)` : ""}`);
40094
+ }
40095
+ return result;
40096
+ }
39998
40097
  function enqueueTerminalOutbox(args) {
39999
40098
  const nowMs = args.nowMs ?? Date.now();
40000
40099
  const nowIso = new Date(nowMs).toISOString();
@@ -40090,6 +40189,8 @@ Next step: ${nextStep}`;
40090
40189
  var MAX_SUSPENSION_LOG_KEYS;
40091
40190
  var suspensionLogKeys;
40092
40191
  var MAX_REDRIVES_PER_ATTEMPT;
40192
+ var SUPERSEDED_BY_ATTEMPT_REASON;
40193
+ var SUPERSEDED_BY_QUEUE_TERMINAL_REASON;
40093
40194
  var sessionOrderChains;
40094
40195
  var init_mesh_turn_ledger = __esm2({
40095
40196
  "src/mesh/mesh-turn-ledger.ts"() {
@@ -40134,6 +40235,8 @@ Next step: ${nextStep}`;
40134
40235
  MAX_SUSPENSION_LOG_KEYS = 200;
40135
40236
  suspensionLogKeys = /* @__PURE__ */ new Set();
40136
40237
  MAX_REDRIVES_PER_ATTEMPT = 1;
40238
+ SUPERSEDED_BY_ATTEMPT_REASON = "superseded_by_attempt";
40239
+ SUPERSEDED_BY_QUEUE_TERMINAL_REASON = "superseded_by_queue_terminal";
40137
40240
  sessionOrderChains = /* @__PURE__ */ new Map();
40138
40241
  }
40139
40242
  });
@@ -45257,11 +45360,44 @@ Next step: ${nextStep}`;
45257
45360
  * Stage 6's presentation layer resolves sessions (not tasks) — read_chat,
45258
45361
  * session status, dashboard and the restart gate all key on sessionId.
45259
45362
  */
45363
+ /**
45364
+ * The attempt that governs a session's presented execution status.
45365
+ *
45366
+ * A nonterminal attempt is preferred (an in-flight turn outranks a finished
45367
+ * one), but ONLY when it is its task's CURRENT attempt — i.e. no higher
45368
+ * attempt_seq exists for the same task.
45369
+ *
45370
+ * ORPHAN-LEGACY-ATTEMPT (fix ③): without that restriction, a stranded
45371
+ * lower-seq row (classically a `legacy-<taskId>-0` minted mid-turn while the
45372
+ * real dispatch already held seq >= 1) outranks the real, COMPLETED attempt
45373
+ * purely because it is nonterminal. Such a row is unreachable by
45374
+ * construction — every ACK and every completion targets the current attempt,
45375
+ * and the reducer's stale-attempt guard refuses to mutate a non-current row —
45376
+ * so it stays `generating` forever and pins the session's presented status to
45377
+ * `generating` even though its turn finished. Fixes ① (no new orphans) and ②
45378
+ * (close the existing ones) address the rows themselves; this guard is the
45379
+ * read-side safety net for any that still slip through, e.g. mid-flight
45380
+ * before the reclaim sweep runs.
45381
+ *
45382
+ * `attempt_seq DESC` is the final tie-break, not decoration: attempts of one
45383
+ * task are routinely written inside the same millisecond, so `updated_at`
45384
+ * alone leaves ties that SQLite may resolve either way — which would make
45385
+ * the selection (and therefore the presented session status) flap between
45386
+ * runs. Preferring the newer attempt is the correct resolution.
45387
+ */
45260
45388
  getLatestTurnAttemptForSession(sessionId) {
45261
45389
  const row = this.db.prepare(`
45262
- SELECT * FROM mesh_turn_attempts
45263
- WHERE session_id = ?
45264
- ORDER BY (terminal_outcome IS NULL) DESC, updated_at DESC LIMIT 1
45390
+ SELECT a.* FROM mesh_turn_attempts a
45391
+ WHERE a.session_id = ?
45392
+ ORDER BY
45393
+ (a.terminal_outcome IS NULL AND NOT EXISTS (
45394
+ SELECT 1 FROM mesh_turn_attempts b
45395
+ WHERE b.mesh_id = a.mesh_id AND b.task_id = a.task_id
45396
+ AND b.attempt_seq > a.attempt_seq
45397
+ )) DESC,
45398
+ a.updated_at DESC,
45399
+ a.attempt_seq DESC
45400
+ LIMIT 1
45265
45401
  `).get(sessionId);
45266
45402
  return row ? meshTurnAttemptFromRow(row) : null;
45267
45403
  }
@@ -45277,6 +45413,83 @@ Next step: ${nextStep}`;
45277
45413
  `).all(meshId, taskId);
45278
45414
  return rows.map(meshTurnAttemptFromRow);
45279
45415
  }
45416
+ /**
45417
+ * ORPHAN-LEGACY-ATTEMPT (fix ②): nonterminal attempts that a HIGHER-seq
45418
+ * attempt of the same task has superseded.
45419
+ *
45420
+ * Such a row is unreachable by construction: `getCurrentTurnAttempt` returns
45421
+ * the max-seq row, so every ACK and every completion proposal resolves to the
45422
+ * newer attempt and the reducer's stale-attempt guard explicitly refuses to
45423
+ * mutate the older one. Nothing in the system can ever move it to terminal —
45424
+ * it would sit at `generating` indefinitely, and (before fix ③) outrank the
45425
+ * real completed attempt when presenting the session's status.
45426
+ *
45427
+ * Deliberately keyed on seq supersession rather than on the `legacy-` id
45428
+ * prefix: the id form is a symptom of one known minting path, whereas
45429
+ * "a newer attempt exists for this task" is the actual unreachability
45430
+ * condition and covers any future path that strands a row the same way.
45431
+ */
45432
+ listSupersededNonterminalTurnAttempts(meshId) {
45433
+ const rows = this.db.prepare(`
45434
+ SELECT a.* FROM mesh_turn_attempts a
45435
+ WHERE a.mesh_id = ?
45436
+ AND a.terminal_outcome IS NULL
45437
+ AND EXISTS (
45438
+ SELECT 1 FROM mesh_turn_attempts b
45439
+ WHERE b.mesh_id = a.mesh_id AND b.task_id = a.task_id
45440
+ AND b.attempt_seq > a.attempt_seq
45441
+ )
45442
+ ORDER BY a.created_at ASC
45443
+ `).all(meshId);
45444
+ return rows.map(meshTurnAttemptFromRow);
45445
+ }
45446
+ /**
45447
+ * QUEUE-TERMINAL-ATTEMPT: nonterminal attempts whose task's `mesh_queue` row
45448
+ * is ALREADY terminal (`completed` / `failed` / `cancelled`).
45449
+ *
45450
+ * The queue row is an independent writer from the turn-ledger reducer — see
45451
+ * Stage 5's rollout gate (some paths, e.g. mission cascade / requeueTask auto-
45452
+ * fail, flip the queue row through the legacy/shadow path without ever
45453
+ * routing a completion proposal through the reducer). When the queue has
45454
+ * already recorded a terminal outcome for a task, that is independent proof
45455
+ * the work is done, so an attempt row still sitting nonterminal is not a live
45456
+ * turn being protected — it is a finished task that was never told. Closing
45457
+ * it cannot kill a real in-flight turn: a genuinely active turn has its queue
45458
+ * row still `pending`/`assigned`, which this predicate excludes by
45459
+ * construction (only `completed`/`failed`/`cancelled` queue rows qualify).
45460
+ *
45461
+ * `EXISTS` (not a JOIN) so a task_id with NO matching queue row — nothing to
45462
+ * compare against — is excluded rather than treated as a false match; a NULL
45463
+ * comparison in a JOIN would silently drop or wrongly include such rows
45464
+ * depending on the join type, which is exactly the ambiguity this predicate
45465
+ * must not have. Measured on the live ledger (RCA 2b3d260d): 14 of 735
45466
+ * nonterminal attempts match, 2 of 721 `delivered`-stage rows — a live turn
45467
+ * is essentially never caught by this condition.
45468
+ *
45469
+ * Deliberately independent of `attempt_seq` / current-vs-superseded: unlike
45470
+ * listSupersededNonterminalTurnAttempts, this predicate targets the SOLE
45471
+ * (and therefore trivially "current") attempt of a task just as often as a
45472
+ * stale one — a task with only ONE attempt whose queue row is terminal is
45473
+ * exactly the residue class this exists to close (confirmed case: a
45474
+ * `waiting_choice` attempt whose queue row already reads `cancelled`).
45475
+ * `reclaimOrphanedTurnAttempts` (seq supersession) runs first in the same
45476
+ * restart-recovery sweep, so a stale non-current sibling row is already
45477
+ * closed by the time this predicate's SELECT runs.
45478
+ */
45479
+ listQueueTerminatedNonterminalTurnAttempts(meshId) {
45480
+ const rows = this.db.prepare(`
45481
+ SELECT a.* FROM mesh_turn_attempts a
45482
+ WHERE a.mesh_id = ?
45483
+ AND a.terminal_outcome IS NULL
45484
+ AND EXISTS (
45485
+ SELECT 1 FROM mesh_queue q
45486
+ WHERE q.mesh_id = a.mesh_id AND q.id = a.task_id
45487
+ AND q.status IN ('completed', 'failed', 'cancelled')
45488
+ )
45489
+ ORDER BY a.created_at ASC
45490
+ `).all(meshId);
45491
+ return rows.map(meshTurnAttemptFromRow);
45492
+ }
45280
45493
  /** Nonterminal attempts — the restart-recovery reconstruction set. */
45281
45494
  listActiveTurnAttempts(meshId) {
45282
45495
  const rows = this.db.prepare(`
@@ -64516,6 +64729,14 @@ ${cleanBody}`;
64516
64729
  void (async () => {
64517
64730
  try {
64518
64731
  for (const mesh of listMeshes()) {
64732
+ const reclaimed = reclaimOrphanedTurnAttempts(mesh.id);
64733
+ if (reclaimed.closed > 0) {
64734
+ LOG2.info("TurnLedger", `Restart recovery: reclaimed ${reclaimed.closed} orphaned (superseded) turn attempt(s) for mesh ${mesh.id}`);
64735
+ }
64736
+ const queueReclaimed = reclaimQueueTerminatedTurnAttempts(mesh.id);
64737
+ if (queueReclaimed.closed > 0) {
64738
+ LOG2.info("TurnLedger", `Restart recovery: reclaimed ${queueReclaimed.closed} nonterminal turn attempt(s) whose queue row already finished for mesh ${mesh.id}`);
64739
+ }
64519
64740
  const recovered = reconstructActiveAttempts(mesh.id);
64520
64741
  if (recovered.length > 0) {
64521
64742
  LOG2.info("TurnLedger", `Restart recovery: reconstructed ${recovered.length} active turn attempt(s) for mesh ${mesh.id} (${recovered.map((a) => `${a.taskId.slice(0, 8)}@${a.stage}`).join(", ")})`);
@@ -73143,7 +73364,7 @@ ${lastSnapshot}`;
73143
73364
  STALE_TERMINAL_REFINE_WINDOW_MS: () => STALE_TERMINAL_REFINE_WINDOW_MS,
73144
73365
  STANDALONE_CDP_SCAN_INTERVAL_MS: () => STANDALONE_CDP_SCAN_INTERVAL_MS2,
73145
73366
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory2,
73146
- StatuslineInstallError: () => StatuslineInstallError,
73367
+ StatuslineInstallError: () => StatuslineInstallError2,
73147
73368
  TREE_DIGEST_ALGORITHM: () => TREE_DIGEST_ALGORITHM,
73148
73369
  TerminalAdapter: () => TerminalAdapter,
73149
73370
  TurnSnapshotTracker: () => TurnSnapshotTracker,
@@ -73249,9 +73470,9 @@ ${lastSnapshot}`;
73249
73470
  execNpmCommandSync: () => execNpmCommandSync,
73250
73471
  expandDaemonIdForms: () => expandDaemonIdForms,
73251
73472
  fastForwardMeshNode: () => fastForwardMeshNode,
73252
- fetchClaudeQuota: () => fetchClaudeQuota,
73253
- fetchCodexQuota: () => fetchCodexQuota,
73254
- fetchKimiQuota: () => fetchKimiQuota,
73473
+ fetchClaudeQuota: () => fetchClaudeQuota2,
73474
+ fetchCodexQuota: () => fetchCodexQuota2,
73475
+ fetchKimiQuota: () => fetchKimiQuota2,
73255
73476
  filterActivityChatMessages: () => filterActivityChatMessages,
73256
73477
  filterChatMessagesByVisibility: () => filterChatMessagesByVisibility,
73257
73478
  filterInternalChatMessages: () => filterInternalChatMessages,
@@ -73315,7 +73536,7 @@ ${lastSnapshot}`;
73315
73536
  hashSignatureParts: () => hashSignatureParts,
73316
73537
  initDaemonComponents: () => initDaemonComponents2,
73317
73538
  insertDirectDispatch: () => insertDirectDispatch,
73318
- installClaudeStatusline: () => installClaudeStatusline,
73539
+ installClaudeStatusline: () => installClaudeStatusline2,
73319
73540
  installExtensions: () => installExtensions,
73320
73541
  installGlobalInterceptor: () => installGlobalInterceptor,
73321
73542
  interactivePromptFromClaudeAskUserQuestion: () => interactivePromptFromClaudeAskUserQuestion,
@@ -73417,6 +73638,11 @@ ${lastSnapshot}`;
73417
73638
  prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate2,
73418
73639
  prepareSessionModalUpdate: () => prepareSessionModalUpdate2,
73419
73640
  presentationFromAttemptRow: () => presentationFromAttemptRow,
73641
+ printClaudeInstallResult: () => printClaudeInstallResult2,
73642
+ printClaudeStatuslineStatus: () => printClaudeStatuslineStatus2,
73643
+ printClaudeUninstallResult: () => printClaudeUninstallResult2,
73644
+ printQuota: () => printQuota2,
73645
+ printQuotaInstallError: () => printQuotaInstallError2,
73420
73646
  probeCdpPort: () => probeCdpPort,
73421
73647
  pruneOperatingNotes: () => pruneOperatingNotes,
73422
73648
  pruneStaleDirectDispatches: () => pruneStaleDirectDispatches,
@@ -73433,7 +73659,7 @@ ${lastSnapshot}`;
73433
73659
  readMeshCompletionSummary: () => readMeshCompletionSummary,
73434
73660
  readOperatingNotes: () => readOperatingNotes,
73435
73661
  readSessionUsage: () => readSessionUsage,
73436
- readStatuslineStatus: () => readStatuslineStatus,
73662
+ readStatuslineStatus: () => readStatuslineStatus2,
73437
73663
  readTokenCount: () => readTokenCount,
73438
73664
  readV2EnvelopeFromWire: () => readV2EnvelopeFromWire,
73439
73665
  reconcileDirectDispatchCompletionFromTranscript: () => reconcileDirectDispatchCompletionFromTranscript,
@@ -73521,7 +73747,7 @@ ${lastSnapshot}`;
73521
73747
  totalTokens: () => totalTokens,
73522
73748
  triggerMeshQueue: () => triggerMeshQueue,
73523
73749
  turnStageToSurfaceStatus: () => turnStageToSurfaceStatus,
73524
- uninstallClaudeStatusline: () => uninstallClaudeStatusline,
73750
+ uninstallClaudeStatusline: () => uninstallClaudeStatusline2,
73525
73751
  unregisterMeshCoordinator: () => unregisterMeshCoordinator,
73526
73752
  updateConfig: () => updateConfig,
73527
73753
  updateDirectDispatchStatus: () => updateDirectDispatchStatus,
@@ -85693,6 +85919,14 @@ ${formatManifestValidationIssues2(validation.issues)}`,
85693
85919
  init_snapshot2();
85694
85920
  init_build_info();
85695
85921
  init_coordinator_registry();
85922
+ init_types();
85923
+ init_deps();
85924
+ init_refresh();
85925
+ init_kimi();
85926
+ init_codex();
85927
+ init_claude();
85928
+ init_install();
85929
+ init_snapshot();
85696
85930
  var statusMetaHandlers = {
85697
85931
  set_user_name: async (_ctx, args) => {
85698
85932
  const name = args?.userName;
@@ -85713,9 +85947,18 @@ ${formatManifestValidationIssues2(validation.issues)}`,
85713
85947
  return { success: true, status: snapshot, daemonBuild: getDaemonBuildInfo() };
85714
85948
  },
85715
85949
  get_machine_runtime_stats: async (_ctx, _args) => {
85950
+ const quota = readQuotaCache();
85716
85951
  return {
85717
85952
  success: true,
85718
- machine: buildMachineInfo2("full"),
85953
+ machine: {
85954
+ ...buildMachineInfo2("full"),
85955
+ // Omit the key entirely rather than shipping `quota: undefined`
85956
+ // — same "never reported" vs "reported empty" contract as
85957
+ // buildLocalNodeFacts (mesh/node-facts.ts). `'quota' in machine`
85958
+ // must stay false until the refresh loop's first tick.
85959
+ ...quota ? { quota } : {},
85960
+ machineNickname: loadConfig2().machineNickname
85961
+ },
85719
85962
  timestamp: Date.now()
85720
85963
  };
85721
85964
  },
@@ -85737,6 +85980,7 @@ ${formatManifestValidationIssues2(validation.issues)}`,
85737
85980
  const launchInfo = adapter && typeof adapter.getLaunchInfo === "function" ? adapter.getLaunchInfo() : void 0;
85738
85981
  const providerType = target?.providerType || coord?.cliType || "";
85739
85982
  const providerMetaForSession = providerType ? ctx.deps.providerLoader.resolve?.(providerType) || ctx.deps.providerLoader.getMeta(providerType) : void 0;
85983
+ const quota = readQuotaCache();
85740
85984
  return {
85741
85985
  success: true,
85742
85986
  session: {
@@ -85752,6 +85996,14 @@ ${formatManifestValidationIssues2(validation.issues)}`,
85752
85996
  runtimeMetadata: runtimeMeta,
85753
85997
  launch: launchInfo
85754
85998
  },
85999
+ // Machine-scoped, not session-scoped: this daemon is the one the
86000
+ // dialog already talked to (ctx handles the routing), so it can
86001
+ // answer for its own machine's quota with no mesh lookup. Cache
86002
+ // read only — see the import comment above. Key omitted entirely
86003
+ // (not `quota: undefined`) until the refresh loop's first tick —
86004
+ // same never-reported-vs-reported-empty contract as node-facts.ts.
86005
+ ...quota ? { quota } : {},
86006
+ machineNickname: loadConfig2().machineNickname,
85755
86007
  coordinator: coord ? {
85756
86008
  meshId: coord.meshId,
85757
86009
  startedAt: coord.startedAt,
@@ -120316,6 +120568,7 @@ data: ${JSON.stringify(msg.data)}
120316
120568
  setupMeshEventForwarding(components);
120317
120569
  components.meshReconcileLoop = setupMeshReconcileLoop(components);
120318
120570
  components.quotaRefreshLoop = setupQuotaRefreshLoop(components);
120571
+ setImmediate(() => refreshQuotaCacheOnBoot());
120319
120572
  setImmediate(() => void router.resumePendingRefineJobsOnStartup());
120320
120573
  setImmediate(() => router.resumeDeferredRestartsOnStartup());
120321
120574
  return components;
@@ -120638,14 +120891,107 @@ data: ${JSON.stringify(msg.data)}
120638
120891
  Object.values(V1_PRIMITIVE_CATALOG).flat()
120639
120892
  );
120640
120893
  var V1_CONTRACT_VERSION = "1.0.0";
120641
- init_types();
120642
- init_deps();
120643
- init_refresh();
120644
- init_kimi();
120645
- init_codex();
120646
- init_claude();
120647
- init_install();
120648
- init_snapshot();
120894
+ var import_chalk2 = __toESM2((init_source(), __toCommonJS(source_exports)));
120895
+ function formatWindow(label, window) {
120896
+ if (!window) {
120897
+ return ` ${label.padEnd(8)} ${import_chalk2.default.gray("not reported")}`;
120898
+ }
120899
+ const percent = `${window.usedPercent.toFixed(1)}%`;
120900
+ const bar = renderBar(window.usedPercent);
120901
+ const reset = window.resetsAt === null ? "" : import_chalk2.default.gray(` resets ${formatRelative(window.resetsAt)}`);
120902
+ return ` ${label.padEnd(8)} ${bar} ${percent.padStart(6)} used${reset}`;
120903
+ }
120904
+ function renderBar(usedPercent) {
120905
+ const width = 20;
120906
+ const filled = Math.round(Math.min(100, Math.max(0, usedPercent)) / 100 * width);
120907
+ const bar = "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
120908
+ if (usedPercent >= 90) return import_chalk2.default.red(bar);
120909
+ if (usedPercent >= 70) return import_chalk2.default.yellow(bar);
120910
+ return import_chalk2.default.green(bar);
120911
+ }
120912
+ function formatRelative(atMs) {
120913
+ const deltaMs = atMs - Date.now();
120914
+ if (deltaMs <= 0) {
120915
+ return "now";
120916
+ }
120917
+ const minutes = Math.round(deltaMs / 6e4);
120918
+ if (minutes < 60) return `in ${minutes}m`;
120919
+ const hours = Math.floor(minutes / 60);
120920
+ if (hours < 24) return `in ${hours}h ${minutes % 60}m`;
120921
+ return `in ${Math.floor(hours / 24)}d ${hours % 24}h`;
120922
+ }
120923
+ function truncate(value, max) {
120924
+ return value.length <= max ? value : `${value.slice(0, max - 1)}\u2026`;
120925
+ }
120926
+ function printQuota2(name, quota) {
120927
+ console.log();
120928
+ console.log(import_chalk2.default.bold(name));
120929
+ if (quota.status === "ok" || quota.session || quota.weekly) {
120930
+ console.log(formatWindow("5 hour", quota.session));
120931
+ console.log(formatWindow("7 day", quota.weekly));
120932
+ }
120933
+ if (quota.error) {
120934
+ const tone = quota.status === "unavailable" ? import_chalk2.default.gray : import_chalk2.default.yellow;
120935
+ console.log(` ${tone(quota.error)}`);
120936
+ }
120937
+ console.log();
120938
+ }
120939
+ function printClaudeInstallResult2(result) {
120940
+ console.log();
120941
+ console.log(
120942
+ import_chalk2.default.green(
120943
+ result.outcome === "reinstalled" ? "\u2713 Claude Code quota reporting re-installed" : "\u2713 Claude Code quota reporting installed"
120944
+ )
120945
+ );
120946
+ if (result.originalCommand) {
120947
+ console.log(import_chalk2.default.gray(" Your existing statusline is preserved and still runs:"));
120948
+ console.log(import_chalk2.default.gray(` ${truncate(result.originalCommand, 100)}`));
120949
+ console.log(import_chalk2.default.gray(` Backup: ${result.paths.backupFile}`));
120950
+ } else {
120951
+ console.log(import_chalk2.default.gray(" You had no statusline configured; one was not added."));
120952
+ }
120953
+ console.log();
120954
+ console.log(import_chalk2.default.gray(" Open a Claude Code session, then run `adhdev quota claude`."));
120955
+ console.log(import_chalk2.default.gray(" Undo any time with `adhdev quota claude:uninstall`."));
120956
+ console.log();
120957
+ }
120958
+ function printClaudeUninstallResult2(result) {
120959
+ console.log();
120960
+ if (result.outcome === "restored") {
120961
+ console.log(import_chalk2.default.green("\u2713 Your original statusline has been restored"));
120962
+ } else if (result.outcome === "removed") {
120963
+ console.log(import_chalk2.default.green("\u2713 Claude Code quota reporting removed"));
120964
+ console.log(import_chalk2.default.gray(" You had no statusline before install, so none was left behind."));
120965
+ } else {
120966
+ console.log(import_chalk2.default.yellow("\u2022 Claude Code quota reporting was not installed"));
120967
+ console.log(import_chalk2.default.gray(" Your statusLine setting was left untouched."));
120968
+ }
120969
+ console.log();
120970
+ }
120971
+ function printClaudeStatuslineStatus2(status) {
120972
+ console.log();
120973
+ if (status.installed) {
120974
+ console.log(import_chalk2.default.green("\u2713 Installed"));
120975
+ console.log(
120976
+ import_chalk2.default.gray(
120977
+ status.wrappedCommand ? ` Wrapping your statusline: ${truncate(status.wrappedCommand, 100)}` : " You had no statusline before install."
120978
+ )
120979
+ );
120980
+ console.log(import_chalk2.default.gray(` Snapshot: ${status.paths.snapshotFile}`));
120981
+ } else {
120982
+ console.log(import_chalk2.default.yellow("\u2022 Not installed"));
120983
+ if (status.foreignStatusLine) {
120984
+ console.log(import_chalk2.default.gray(" You have your own statusLine configured; install would wrap it."));
120985
+ }
120986
+ console.log(import_chalk2.default.gray(" Set up with `adhdev quota claude:install`."));
120987
+ }
120988
+ console.log();
120989
+ }
120990
+ function printQuotaInstallError2(message) {
120991
+ console.error(import_chalk2.default.red(`
120992
+ \u2717 ${message}
120993
+ `));
120994
+ }
120649
120995
  }
120650
120996
  });
120651
120997
 
@@ -120771,6 +121117,8 @@ var STANDALONE_HELP_TEXT = `
120771
121117
  Usage: adhdev-standalone [options]
120772
121118
  adhdev-standalone list [--all]
120773
121119
  adhdev-standalone attach <sessionId> [--read-only|--takeover]
121120
+ adhdev-standalone quota <claude|codex|kimi>
121121
+ adhdev-standalone quota claude:install | claude:uninstall | claude:status
120774
121122
 
120775
121123
  Options:
120776
121124
  --port, -p <port> Port to run the standalone server on (default: 3847)
@@ -120791,6 +121139,7 @@ Runtime commands:
120791
121139
  list, runtimes Show hosted CLI runtimes
120792
121140
  attach Attach local terminal to a runtime
120793
121141
  open Open a local terminal window running adhmux for a runtime
121142
+ quota Show remaining plan quota for your AI coding agents
120794
121143
  `;
120795
121144
  var PUBLIC_ANY_ADDRESSES = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
120796
121145
  function normalizeStandaloneHostAddress(raw) {
@@ -120889,8 +121238,8 @@ function parseStandaloneCliArgs(args) {
120889
121238
  }
120890
121239
 
120891
121240
  // src/index.ts
120892
- var import_daemon_core2 = __toESM(require_dist3());
120893
121241
  var import_daemon_core3 = __toESM(require_dist3());
121242
+ var import_daemon_core4 = __toESM(require_dist3());
120894
121243
 
120895
121244
  // src/session-host.ts
120896
121245
  var childProcess = __toESM(require("child_process"));
@@ -120970,6 +121319,69 @@ async function proxySessionHostAttach(target, options = {}) {
120970
121319
  return runSessionHostCli(args);
120971
121320
  }
120972
121321
 
121322
+ // src/quota-cli.ts
121323
+ var import_daemon_core2 = __toESM(require_dist3());
121324
+ var QUOTA_HELP_TEXT = `
121325
+ Usage: adhdev quota <provider>
121326
+ adhdev quota claude:install | claude:uninstall | claude:status
121327
+
121328
+ Providers:
121329
+ claude Show Claude Code plan usage (requires \`adhdev quota claude:install\`)
121330
+ codex Show Codex CLI plan usage (queries codex app-server live)
121331
+ kimi Show Kimi Code plan usage (queries the Kimi API live)
121332
+
121333
+ Claude Code setup (codex/kimi need no setup \u2014 they query live):
121334
+ claude:install Set up Claude Code quota reporting by wrapping your statusline
121335
+ claude:uninstall Remove Claude Code quota reporting and restore your original statusline
121336
+ claude:status Show whether Claude Code quota reporting is set up
121337
+ `;
121338
+ async function runQuotaCommand(args) {
121339
+ const sub = args[0];
121340
+ switch (sub) {
121341
+ case "claude":
121342
+ (0, import_daemon_core2.printQuota)("Claude Code", await (0, import_daemon_core2.fetchClaudeQuota)());
121343
+ return 0;
121344
+ case "codex":
121345
+ (0, import_daemon_core2.printQuota)("Codex CLI", await (0, import_daemon_core2.fetchCodexQuota)());
121346
+ return 0;
121347
+ case "kimi":
121348
+ (0, import_daemon_core2.printQuota)("Kimi Code", await (0, import_daemon_core2.fetchKimiQuota)());
121349
+ return 0;
121350
+ case "claude:install":
121351
+ case "claude-install": {
121352
+ try {
121353
+ (0, import_daemon_core2.printClaudeInstallResult)((0, import_daemon_core2.installClaudeStatusline)());
121354
+ return 0;
121355
+ } catch (err) {
121356
+ if (err instanceof import_daemon_core2.StatuslineInstallError) {
121357
+ (0, import_daemon_core2.printQuotaInstallError)(err.message);
121358
+ return 1;
121359
+ }
121360
+ throw err;
121361
+ }
121362
+ }
121363
+ case "claude:uninstall":
121364
+ case "claude-uninstall": {
121365
+ try {
121366
+ (0, import_daemon_core2.printClaudeUninstallResult)((0, import_daemon_core2.uninstallClaudeStatusline)());
121367
+ return 0;
121368
+ } catch (err) {
121369
+ if (err instanceof import_daemon_core2.StatuslineInstallError) {
121370
+ (0, import_daemon_core2.printQuotaInstallError)(err.message);
121371
+ return 1;
121372
+ }
121373
+ throw err;
121374
+ }
121375
+ }
121376
+ case "claude:status":
121377
+ (0, import_daemon_core2.printClaudeStatuslineStatus)((0, import_daemon_core2.readStatuslineStatus)());
121378
+ return 0;
121379
+ default:
121380
+ console.log(QUOTA_HELP_TEXT);
121381
+ return sub === void 0 || sub === "--help" || sub === "-h" ? 0 : 1;
121382
+ }
121383
+ }
121384
+
120973
121385
  // src/startup-restore-policy.ts
120974
121386
  function shouldAutoRestoreHostedSessionsOnStartup(env2 = process.env) {
120975
121387
  const raw = typeof env2.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env2.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";
@@ -121394,7 +121806,7 @@ async function getWorkspaceSocketInfo(workspaceName) {
121394
121806
  }
121395
121807
 
121396
121808
  // src/index.ts
121397
- var import_daemon_core4 = __toESM(require_dist3());
121809
+ var import_daemon_core5 = __toESM(require_dist3());
121398
121810
 
121399
121811
  // src/raw-terminal-http.ts
121400
121812
  function parseRawTerminalPath(pathname) {
@@ -121582,7 +121994,7 @@ async function handleInteractivePromptHttpRequest(options) {
121582
121994
  // src/index.ts
121583
121995
  var DEFAULT_PORT = 3847;
121584
121996
  var STATUS_INTERVAL = 2e3;
121585
- var CHAT_OUTPUT_ACTIVITY_HOT_MS = import_daemon_core4.DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS;
121997
+ var CHAT_OUTPUT_ACTIVITY_HOT_MS = import_daemon_core5.DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS;
121586
121998
  var CHAT_OUTPUT_FLUSH_DEBOUNCE_MS = 700;
121587
121999
  var STANDALONE_AUTH_SESSION_COOKIE = "adhdev_standalone_session";
121588
122000
  var STANDALONE_PASSWORD_CONFIG_FILE = "standalone-auth.json";
@@ -121591,14 +122003,14 @@ var STANDALONE_BIND_HOST_DEFAULT = "127.0.0.1";
121591
122003
  var PASSWORD_KEYLEN = 64;
121592
122004
  var DEFAULT_SESSION_TTL_MS = 1e3 * 60 * 60 * 24 * 30;
121593
122005
  function getStandalonePasswordConfigPath() {
121594
- const dir = (0, import_daemon_core2.getConfigDir)();
122006
+ const dir = (0, import_daemon_core3.getConfigDir)();
121595
122007
  if (!fs3.existsSync(dir)) {
121596
122008
  fs3.mkdirSync(dir, { recursive: true, mode: 448 });
121597
122009
  }
121598
122010
  return path4.join(dir, STANDALONE_PASSWORD_CONFIG_FILE);
121599
122011
  }
121600
122012
  function getStandaloneConfigJsonPath() {
121601
- const dir = (0, import_daemon_core2.getConfigDir)();
122013
+ const dir = (0, import_daemon_core3.getConfigDir)();
121602
122014
  if (!fs3.existsSync(dir)) {
121603
122015
  fs3.mkdirSync(dir, { recursive: true, mode: 448 });
121604
122016
  }
@@ -121787,7 +122199,7 @@ var StandaloneServer = class {
121787
122199
  wsSessionModalSubscriptions = /* @__PURE__ */ new Map();
121788
122200
  wsDaemonMetadataSubscriptions = /* @__PURE__ */ new Map();
121789
122201
  wsGitSubscriptions = /* @__PURE__ */ new Map();
121790
- gitWorkspaceMonitor = (0, import_daemon_core2.createGitWorkspaceMonitor)();
122202
+ gitWorkspaceMonitor = (0, import_daemon_core3.createGitWorkspaceMonitor)();
121791
122203
  authToken = null;
121792
122204
  passwordConfigPath = getStandalonePasswordConfigPath();
121793
122205
  passwordConfig = null;
@@ -121826,19 +122238,19 @@ var StandaloneServer = class {
121826
122238
  rawTerminalService() {
121827
122239
  const endpoint = this.sessionHostEndpoint || void 0;
121828
122240
  return {
121829
- readScreen: (sessionId) => (0, import_daemon_core2.withRawTerminalAttachment)(
122241
+ readScreen: (sessionId) => (0, import_daemon_core3.withRawTerminalAttachment)(
121830
122242
  { endpoint, sessionId, mode: "read" },
121831
122243
  (attachment) => attachment.readScreenText()
121832
122244
  ),
121833
- readState: (sessionId) => (0, import_daemon_core2.withRawTerminalAttachment)(
122245
+ readState: (sessionId) => (0, import_daemon_core3.withRawTerminalAttachment)(
121834
122246
  { endpoint, sessionId, mode: "read" },
121835
122247
  (attachment) => attachment.readState()
121836
122248
  ),
121837
- writeInput: (sessionId, text) => (0, import_daemon_core2.withRawTerminalAttachment)(
122249
+ writeInput: (sessionId, text) => (0, import_daemon_core3.withRawTerminalAttachment)(
121838
122250
  { endpoint, sessionId, mode: "write" },
121839
122251
  (attachment) => attachment.writeInput(text)
121840
122252
  ),
121841
- writeKeys: (sessionId, keys) => (0, import_daemon_core2.withRawTerminalAttachment)(
122253
+ writeKeys: (sessionId, keys) => (0, import_daemon_core3.withRawTerminalAttachment)(
121842
122254
  { endpoint, sessionId, mode: "write" },
121843
122255
  (attachment) => attachment.writeKeys(keys)
121844
122256
  )
@@ -121865,7 +122277,7 @@ var StandaloneServer = class {
121865
122277
  resolvePrompt: async (sessionId, response) => {
121866
122278
  const instanceKey = resolveInstanceKey(sessionId);
121867
122279
  if (!instanceKey) throw new Error(`Unknown session: ${sessionId}`);
121868
- const normalized = (0, import_daemon_core2.normalizeInteractivePromptResponse)(response);
122280
+ const normalized = (0, import_daemon_core3.normalizeInteractivePromptResponse)(response);
121869
122281
  this.components?.instanceManager.sendEvent(instanceKey, "interactive_prompt_response", normalized);
121870
122282
  this.scheduleBroadcastStatus();
121871
122283
  }
@@ -122031,7 +122443,7 @@ var StandaloneServer = class {
122031
122443
  }
122032
122444
  async start(options = {}) {
122033
122445
  const persistedStandaloneBindHost = loadStandaloneBindHostPreference();
122034
- const cfg = (0, import_daemon_core2.loadConfig)();
122446
+ const cfg = (0, import_daemon_core3.loadConfig)();
122035
122447
  if (!options.host && persistedStandaloneBindHost !== STANDALONE_BIND_HOST_DEFAULT) {
122036
122448
  saveStandaloneBindHostPreference(persistedStandaloneBindHost);
122037
122449
  }
@@ -122056,7 +122468,7 @@ var StandaloneServer = class {
122056
122468
  this.authToken = options.token || process.env.ADHDEV_TOKEN || null;
122057
122469
  this.passwordConfig = loadStandalonePasswordConfig(this.passwordConfigPath);
122058
122470
  const statusInstanceId = `standalone_${cfg.machineId || "mach_unknown"}`;
122059
- this.components = await (0, import_daemon_core2.initDaemonComponents)({
122471
+ this.components = await (0, import_daemon_core3.initDaemonComponents)({
122060
122472
  cliManagerDeps: {
122061
122473
  getServerConn: () => null,
122062
122474
  getP2p: () => ({
@@ -122080,7 +122492,7 @@ var StandaloneServer = class {
122080
122492
  removeAgentTracking: () => {
122081
122493
  },
122082
122494
  hostedRuntimeManagerTag: "adhdev-standalone",
122083
- createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, providerSessionId, attachExisting }) => new import_daemon_core2.SessionHostPtyTransportFactory({
122495
+ createPtyTransportFactory: ({ runtimeId, providerType, workspace, cliArgs, providerSessionId, attachExisting }) => new import_daemon_core3.SessionHostPtyTransportFactory({
122084
122496
  endpoint: sessionHostEndpoint,
122085
122497
  ensureReady: async () => {
122086
122498
  const activeEndpoint = await this.ensureActiveSessionHostEndpoint();
@@ -122111,7 +122523,7 @@ var StandaloneServer = class {
122111
122523
  sessionHostControl,
122112
122524
  onStreamsUpdated: (ideType, streams) => {
122113
122525
  if (!this.components) return;
122114
- (0, import_daemon_core2.forwardAgentStreamsToIdeInstance)(this.components.instanceManager, ideType, streams);
122526
+ (0, import_daemon_core3.forwardAgentStreamsToIdeInstance)(this.components.instanceManager, ideType, streams);
122115
122527
  this.scheduleBroadcastStatus();
122116
122528
  },
122117
122529
  tickIntervalMs: 3e3,
@@ -122121,7 +122533,7 @@ var StandaloneServer = class {
122121
122533
  await this.components.cliManager.restoreHostedSessions();
122122
122534
  }
122123
122535
  if (options.dev) {
122124
- this.devServer = await (0, import_daemon_core2.startDaemonDevSupport)({
122536
+ this.devServer = await (0, import_daemon_core3.startDaemonDevSupport)({
122125
122537
  components: this.components,
122126
122538
  logFn: (msg) => console.log(msg)
122127
122539
  });
@@ -122166,11 +122578,11 @@ var StandaloneServer = class {
122166
122578
  });
122167
122579
  if (standaloneIpcEnabled()) {
122168
122580
  try {
122169
- this.ipcServer = await (0, import_daemon_core2.startLocalIpcServer)({
122170
- port: import_daemon_core3.DEFAULT_DAEMON_PORT,
122581
+ this.ipcServer = await (0, import_daemon_core3.startLocalIpcServer)({
122582
+ port: import_daemon_core4.DEFAULT_DAEMON_PORT,
122171
122583
  buildStatusPayload: () => {
122172
122584
  if (!this.components) return null;
122173
- return (0, import_daemon_core2.buildStatusSnapshot)({
122585
+ return (0, import_daemon_core3.buildStatusSnapshot)({
122174
122586
  allStates: this.components.instanceManager.collectAllStates(),
122175
122587
  cdpManagers: this.components.cdpManagers,
122176
122588
  providerLoader: this.components.providerLoader,
@@ -122178,7 +122590,7 @@ var StandaloneServer = class {
122178
122590
  ...ide,
122179
122591
  path: ide.path ?? void 0
122180
122592
  })),
122181
- instanceId: `standalone_${(0, import_daemon_core2.loadConfig)().machineId || "daemon"}`,
122593
+ instanceId: `standalone_${(0, import_daemon_core3.loadConfig)().machineId || "daemon"}`,
122182
122594
  version: pkgVersion,
122183
122595
  profile: "metadata"
122184
122596
  });
@@ -122188,7 +122600,7 @@ var StandaloneServer = class {
122188
122600
  serverConnected: false,
122189
122601
  // standalone never has a cloud server connection
122190
122602
  cdpConnected: (this.components?.cdpManagers.size || 0) > 0,
122191
- localPort: import_daemon_core3.DEFAULT_DAEMON_PORT,
122603
+ localPort: import_daemon_core4.DEFAULT_DAEMON_PORT,
122192
122604
  cliAgents: this.components ? this.components.instanceManager.collectAllStates().filter((state) => state?.category === "cli").map((state) => String(state?.instanceId || "")).filter(Boolean) : [],
122193
122605
  sessionHostConnected: false,
122194
122606
  mode: "standalone"
@@ -122213,8 +122625,8 @@ var StandaloneServer = class {
122213
122625
  }
122214
122626
  });
122215
122627
  } catch (e) {
122216
- const msg = e?.code === "EADDRINUSE" ? `Port ${import_daemon_core3.DEFAULT_DAEMON_PORT} already in use; standalone IPC compatibility mode disabled for this run.` : `Failed to start standalone IPC compatibility server: ${e?.message || e}`;
122217
- import_daemon_core2.LOG.warn("IPC", msg);
122628
+ const msg = e?.code === "EADDRINUSE" ? `Port ${import_daemon_core4.DEFAULT_DAEMON_PORT} already in use; standalone IPC compatibility mode disabled for this run.` : `Failed to start standalone IPC compatibility server: ${e?.message || e}`;
122629
+ import_daemon_core3.LOG.warn("IPC", msg);
122218
122630
  }
122219
122631
  }
122220
122632
  console.log("");
@@ -122234,9 +122646,9 @@ var StandaloneServer = class {
122234
122646
  console.log(" \u{1F510} Password auth: enabled");
122235
122647
  }
122236
122648
  if (this.ipcServer?.isListening()) {
122237
- console.log(` IPC: ws://127.0.0.1:${import_daemon_core3.DEFAULT_DAEMON_PORT}${import_daemon_core3.DAEMON_WS_PATH} (for adhdev mcp --mode ipc)`);
122649
+ console.log(` IPC: ws://127.0.0.1:${import_daemon_core4.DEFAULT_DAEMON_PORT}${import_daemon_core4.DAEMON_WS_PATH} (for adhdev mcp --mode ipc)`);
122238
122650
  } else if (standaloneIpcEnabled()) {
122239
- console.log(` IPC: disabled (port ${import_daemon_core3.DEFAULT_DAEMON_PORT} unavailable)`);
122651
+ console.log(` IPC: disabled (port ${import_daemon_core4.DEFAULT_DAEMON_PORT} unavailable)`);
122240
122652
  }
122241
122653
  if (shouldWarnForPublicUnauthenticatedHost({ host, hasTokenAuth: !!this.authToken, hasPasswordAuth: !!this.passwordConfig })) {
122242
122654
  console.warn(" \u26A0\uFE0F Public host mode is enabled without any auth.");
@@ -122945,7 +123357,7 @@ var StandaloneServer = class {
122945
123357
  if (msg.topic === "workspace.git") {
122946
123358
  const params = msg.params;
122947
123359
  if (!params?.workspace) return;
122948
- const normalized = (0, import_daemon_core2.normalizeGitWorkspaceSubscriptionParams)(params);
123360
+ const normalized = (0, import_daemon_core3.normalizeGitWorkspaceSubscriptionParams)(params);
122949
123361
  const subs = this.wsGitSubscriptions.get(ws) || /* @__PURE__ */ new Map();
122950
123362
  this.wsGitSubscriptions.set(ws, subs);
122951
123363
  subs.get(msg.key)?.subscription.dispose();
@@ -122994,21 +123406,21 @@ var StandaloneServer = class {
122994
123406
  ...request.historySessionId ? { historySessionId: request.historySessionId } : {},
122995
123407
  ...state.cursor.tailLimit > 0 ? { tailLimit: state.cursor.tailLimit } : {}
122996
123408
  });
122997
- if ((0, import_daemon_core2.isMissingLiveSessionResult)(result)) {
123409
+ if ((0, import_daemon_core3.isMissingLiveSessionResult)(result)) {
122998
123410
  const now = Date.now();
122999
- const missing = (0, import_daemon_core2.recordMissingSessionAttempt)(state.missingSession, now);
123411
+ const missing = (0, import_daemon_core3.recordMissingSessionAttempt)(state.missingSession, now);
123000
123412
  state.missingSession = missing;
123001
123413
  const message = `[chat_tail] session ${request.targetSessionId} is not in the live registry`;
123002
- if ((0, import_daemon_core2.shouldWarnForMissingSession)(missing)) {
123414
+ if ((0, import_daemon_core3.shouldWarnForMissingSession)(missing)) {
123003
123415
  missing.warned = true;
123004
- import_daemon_core2.LOG.warn("Standalone", `${message} \u2014 backing off, and dropping the subscription if it stays absent`);
123416
+ import_daemon_core3.LOG.warn("Standalone", `${message} \u2014 backing off, and dropping the subscription if it stays absent`);
123005
123417
  } else {
123006
- import_daemon_core2.LOG.debug("Standalone", `${message} (miss #${missing.consecutiveMisses})`);
123418
+ import_daemon_core3.LOG.debug("Standalone", `${message} (miss #${missing.consecutiveMisses})`);
123007
123419
  }
123008
123420
  return null;
123009
123421
  }
123010
123422
  if (state.missingSession) state.missingSession = void 0;
123011
- const prepared = (0, import_daemon_core2.prepareSessionChatTailUpdate)({
123423
+ const prepared = (0, import_daemon_core3.prepareSessionChatTailUpdate)({
123012
123424
  key,
123013
123425
  sessionId: request.targetSessionId,
123014
123426
  ...request.historySessionId ? { historySessionId: request.historySessionId } : {},
@@ -123072,7 +123484,7 @@ var StandaloneServer = class {
123072
123484
  const now = Date.now();
123073
123485
  const snapshot = this.buildSharedSnapshot("live");
123074
123486
  const underDeliveredSessionIds = this.getUnderDeliveredChatSessionIds();
123075
- const hotSessions = (0, import_daemon_core4.classifyHotChatSessionsForSubscriptionFlush)(
123487
+ const hotSessions = (0, import_daemon_core5.classifyHotChatSessionsForSubscriptionFlush)(
123076
123488
  snapshot.sessions,
123077
123489
  this.hotWsChatSessionIds,
123078
123490
  {
@@ -123132,7 +123544,7 @@ var StandaloneServer = class {
123132
123544
  } catch {
123133
123545
  return /* @__PURE__ */ new Set();
123134
123546
  }
123135
- const { settled, nextStatus } = (0, import_daemon_core4.detectNewlySettledCompletedSessions)(
123547
+ const { settled, nextStatus } = (0, import_daemon_core5.detectNewlySettledCompletedSessions)(
123136
123548
  snapshot.sessions,
123137
123549
  this.lastObservedSessionStatus
123138
123550
  );
@@ -123179,11 +123591,11 @@ var StandaloneServer = class {
123179
123591
  if (!subs || subs.size === 0) continue;
123180
123592
  for (const [key, sub] of subs.entries()) {
123181
123593
  const targetSessionId = sub.request.params.targetSessionId;
123182
- const decision = (0, import_daemon_core2.decideMissingSessionAttempt)(sub.missingSession, now);
123594
+ const decision = (0, import_daemon_core3.decideMissingSessionAttempt)(sub.missingSession, now);
123183
123595
  if (decision.action === "skip") continue;
123184
123596
  if (decision.action === "drop") {
123185
123597
  subs.delete(key);
123186
- import_daemon_core2.LOG.info("Standalone", `[chat_tail] subscription dropped: session=${targetSessionId} key=${key} \u2014 live session absent for ${Math.round((now - (sub.missingSession?.firstMissingAt ?? now)) / 1e3)}s`);
123598
+ import_daemon_core3.LOG.info("Standalone", `[chat_tail] subscription dropped: session=${targetSessionId} key=${key} \u2014 live session absent for ${Math.round((now - (sub.missingSession?.firstMissingAt ?? now)) / 1e3)}s`);
123187
123599
  continue;
123188
123600
  }
123189
123601
  const isForced = forceSessionIds?.has(targetSessionId) === true;
@@ -123193,13 +123605,13 @@ var StandaloneServer = class {
123193
123605
  tasks.push({ ws, key, sub });
123194
123606
  }
123195
123607
  }
123196
- await (0, import_daemon_core2.runAsyncBatch)(tasks, async ({ ws, key, sub }) => {
123608
+ await (0, import_daemon_core3.runAsyncBatch)(tasks, async ({ ws, key, sub }) => {
123197
123609
  try {
123198
123610
  const update = await this.buildChatTailUpdate(sub.request.params, sub, key);
123199
123611
  if (!update || ws.readyState !== import_ws.WebSocket.OPEN) return;
123200
123612
  ws.send(JSON.stringify({ type: "topic_update", update }));
123201
123613
  } catch (error48) {
123202
- import_daemon_core2.LOG.warn("Standalone", `[chat_tail] skipped session=${sub.request.params.targetSessionId} key=${key} error=${error48?.message || error48}`);
123614
+ import_daemon_core3.LOG.warn("Standalone", `[chat_tail] skipped session=${sub.request.params.targetSessionId} key=${key} error=${error48?.message || error48}`);
123203
123615
  }
123204
123616
  }, { concurrency: 4 });
123205
123617
  } finally {
@@ -123228,7 +123640,7 @@ var StandaloneServer = class {
123228
123640
  return {
123229
123641
  topic: "machine.runtime",
123230
123642
  key,
123231
- machine: (0, import_daemon_core2.buildMachineInfo)("full"),
123643
+ machine: (0, import_daemon_core3.buildMachineInfo)("full"),
123232
123644
  seq: state.seq,
123233
123645
  timestamp: now
123234
123646
  };
@@ -123297,7 +123709,7 @@ var StandaloneServer = class {
123297
123709
  const activeModal = modalState.activeModal;
123298
123710
  const status = String(modalState.status || "idle");
123299
123711
  const title = typeof modalState.title === "string" ? modalState.title : void 0;
123300
- const prepared = (0, import_daemon_core2.prepareSessionModalUpdate)({
123712
+ const prepared = (0, import_daemon_core3.prepareSessionModalUpdate)({
123301
123713
  key,
123302
123714
  sessionId: state.request.params.targetSessionId,
123303
123715
  status,
@@ -123332,14 +123744,14 @@ var StandaloneServer = class {
123332
123744
  const now = Date.now();
123333
123745
  state.seq += 1;
123334
123746
  state.lastSentAt = now;
123335
- const cfgSnap = (0, import_daemon_core2.loadConfig)();
123747
+ const cfgSnap = (0, import_daemon_core3.loadConfig)();
123336
123748
  const status = this.buildSharedSnapshot("metadata");
123337
123749
  const includeSessions = state.request.params.includeSessions === true;
123338
123750
  if (includeSessions) {
123339
123751
  if (this.components?.router) {
123340
123752
  const nodes = this.components.router.getCachedInlineMeshNodes();
123341
123753
  for (const node of nodes) {
123342
- const meshSessions = (0, import_daemon_core2.readCachedInlineMeshActiveSessionDetails)(node);
123754
+ const meshSessions = (0, import_daemon_core3.readCachedInlineMeshActiveSessionDetails)(node);
123343
123755
  for (const session of meshSessions) {
123344
123756
  status.sessions.push(session);
123345
123757
  }
@@ -123392,7 +123804,7 @@ var StandaloneServer = class {
123392
123804
  tasks.push({ ws, key, sub });
123393
123805
  });
123394
123806
  }
123395
- await (0, import_daemon_core2.runAsyncBatch)(tasks, async ({ ws, key, sub }) => {
123807
+ await (0, import_daemon_core3.runAsyncBatch)(tasks, async ({ ws, key, sub }) => {
123396
123808
  try {
123397
123809
  const monitorUpdate = await sub.subscription.refresh();
123398
123810
  const current = this.wsGitSubscriptions.get(ws)?.get(key);
@@ -123404,16 +123816,16 @@ var StandaloneServer = class {
123404
123816
  };
123405
123817
  ws.send(JSON.stringify({ type: "topic_update", update }));
123406
123818
  } catch (error48) {
123407
- import_daemon_core2.LOG.warn("Standalone", `[workspace.git] skipped workspace=${sub.request.params.workspace} key=${key} error=${error48?.message || error48}`);
123819
+ import_daemon_core3.LOG.warn("Standalone", `[workspace.git] skipped workspace=${sub.request.params.workspace} key=${key} error=${error48?.message || error48}`);
123408
123820
  }
123409
123821
  }, { concurrency: 2 });
123410
123822
  }
123411
123823
  // ─── Core Logic ───
123412
123824
  buildSharedSnapshot(profile = "full") {
123413
- const cfgSnap = (0, import_daemon_core2.loadConfig)();
123825
+ const cfgSnap = (0, import_daemon_core3.loadConfig)();
123414
123826
  const machineId = cfgSnap.machineId || "mach_unknown";
123415
123827
  const allStates = this.components.instanceManager.collectAllStates();
123416
- return (0, import_daemon_core2.buildStatusSnapshot)({
123828
+ return (0, import_daemon_core3.buildStatusSnapshot)({
123417
123829
  allStates,
123418
123830
  cdpManagers: this.components.cdpManagers,
123419
123831
  providerLoader: this.components.providerLoader,
@@ -123453,8 +123865,8 @@ var StandaloneServer = class {
123453
123865
  }
123454
123866
  }
123455
123867
  getStatus(snapshot = this.buildSharedSnapshot("full")) {
123456
- const cfgSnap = (0, import_daemon_core2.loadConfig)();
123457
- const machineRuntime = (0, import_daemon_core2.buildMachineInfo)("full");
123868
+ const cfgSnap = (0, import_daemon_core3.loadConfig)();
123869
+ const machineRuntime = (0, import_daemon_core3.buildMachineInfo)("full");
123458
123870
  return {
123459
123871
  ...snapshot,
123460
123872
  id: snapshot.instanceId,
@@ -123474,7 +123886,7 @@ var StandaloneServer = class {
123474
123886
  };
123475
123887
  }
123476
123888
  getWsStatus(snapshot = this.buildSharedSnapshot("live")) {
123477
- const availableProviders = this.components?.providerLoader ? (0, import_daemon_core2.buildAvailableProviders)(this.components.providerLoader) : void 0;
123889
+ const availableProviders = this.components?.providerLoader ? (0, import_daemon_core3.buildAvailableProviders)(this.components.providerLoader) : void 0;
123478
123890
  return {
123479
123891
  instanceId: snapshot.instanceId,
123480
123892
  machine: snapshot.machine,
@@ -123575,7 +123987,7 @@ var StandaloneServer = class {
123575
123987
  this.lastStatusBroadcastAt = Date.now();
123576
123988
  const msg = JSON.stringify({ type: "status", data: status });
123577
123989
  const cdpCount = [...this.components.cdpManagers.values()].filter((m) => m.isConnected).length;
123578
- import_daemon_core2.LOG.debug("Broadcast", `status \u2192 ${this.clients.size} client(s), ${status.sessions?.length || 0} session(s), ${cdpCount} CDP`);
123990
+ import_daemon_core3.LOG.debug("Broadcast", `status \u2192 ${this.clients.size} client(s), ${status.sessions?.length || 0} session(s), ${cdpCount} CDP`);
123579
123991
  for (const client of this.clients) {
123580
123992
  if (client.readyState === import_ws.WebSocket.OPEN) {
123581
123993
  client.send(msg);
@@ -123631,7 +124043,7 @@ var StandaloneServer = class {
123631
124043
  this.ipcServer = null;
123632
124044
  }
123633
124045
  if (this.components) {
123634
- await (0, import_daemon_core2.shutdownDaemonComponents)(this.components);
124046
+ await (0, import_daemon_core3.shutdownDaemonComponents)(this.components);
123635
124047
  }
123636
124048
  this.sessionHostControl = null;
123637
124049
  if (this.httpServer) {
@@ -123643,7 +124055,7 @@ var StandaloneServer = class {
123643
124055
  }
123644
124056
  };
123645
124057
  async function main() {
123646
- const helperMode = await (0, import_daemon_core2.maybeRunDaemonUpgradeHelperFromEnv)();
124058
+ const helperMode = await (0, import_daemon_core3.maybeRunDaemonUpgradeHelperFromEnv)();
123647
124059
  if (helperMode) {
123648
124060
  return;
123649
124061
  }
@@ -123665,6 +124077,10 @@ async function main() {
123665
124077
  const exitCode = await proxySessionHostList(showAll);
123666
124078
  process.exit(exitCode);
123667
124079
  }
124080
+ if (primaryCommand === "quota") {
124081
+ const exitCode = await runQuotaCommand(args.slice(1));
124082
+ process.exit(exitCode);
124083
+ }
123668
124084
  let parsed;
123669
124085
  try {
123670
124086
  parsed = parseStandaloneCliArgs(args);