@alook/daemon 0.1.25 → 0.1.26

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.
Files changed (3) hide show
  1. package/dist/cli/index.js +461 -141
  2. package/dist/index.js +449 -129
  3. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -17536,7 +17536,7 @@ var REASONING_EFFORT_RE = /^[A-Za-z0-9._-]+$/;
17536
17536
  var COMMUNITY_REASONING_EFFORT_MAX = 32;
17537
17537
  var COMMUNITY_REASONING_DESCRIPTION_MAX = 256;
17538
17538
  var COMMUNITY_REASONING_OPTIONS_MAX = 16;
17539
- var COMMUNITY_REASONING_MODELS_MAX = 64;
17539
+ var COMMUNITY_REASONING_MODELS_MAX = 512;
17540
17540
  var ReasoningEffortSchema = exports_external.string().min(1).max(COMMUNITY_REASONING_EFFORT_MAX).regex(REASONING_EFFORT_RE, "invalid reasoning effort charset");
17541
17541
  var RuntimeReasoningOptionSchema = exports_external.object({
17542
17542
  value: ReasoningEffortSchema,
@@ -17544,6 +17544,7 @@ var RuntimeReasoningOptionSchema = exports_external.object({
17544
17544
  });
17545
17545
  var RuntimeReasoningModelSchema = exports_external.object({
17546
17546
  id: exports_external.string().min(1).max(100),
17547
+ displayName: exports_external.string().min(1).max(COMMUNITY_REASONING_DESCRIPTION_MAX).optional().catch(undefined),
17547
17548
  supportedReasoningEfforts: exports_external.array(exports_external.unknown()).max(COMMUNITY_REASONING_OPTIONS_MAX).transform((options) => {
17548
17549
  const seen = new Set;
17549
17550
  return options.flatMap((candidate) => {
@@ -20338,8 +20339,8 @@ function resolveLaunchFieldsOrDefault(input) {
20338
20339
  const envVars = Object.fromEntries(Object.entries(normalized.environment ?? {}).filter(([key]) => !controlled.has(key)));
20339
20340
  const providerEnv = {};
20340
20341
  const model = normalized.model.kind === "default" ? undefined : normalized.model.name;
20341
- if (normalized.model.kind === "custom" && normalized.provider?.kind === "custom_endpoint") {
20342
- providerEnv.ANTHROPIC_CUSTOM_MODEL_OPTION = normalized.model.name;
20342
+ if (model && normalized.provider?.kind === "custom_endpoint") {
20343
+ providerEnv.ANTHROPIC_CUSTOM_MODEL_OPTION = model;
20343
20344
  }
20344
20345
  if (normalized.provider?.kind === "custom_endpoint") {
20345
20346
  providerEnv.ANTHROPIC_BASE_URL = normalized.provider.apiUrl;
@@ -20674,6 +20675,7 @@ import { execFileSync as execFileSync2 } from "child_process";
20674
20675
  import * as fs5 from "fs";
20675
20676
  import * as path5 from "path";
20676
20677
  var PROBE_TIMEOUT_MS = 5000;
20678
+ var PROBE_OUTPUT_MAX_BYTES = 1024 * 1024;
20677
20679
  function resolveCommandOnPath(command, deps = {}) {
20678
20680
  if (deps.which)
20679
20681
  return deps.which(command);
@@ -20724,6 +20726,23 @@ function probeCommandVersion(command, args = [], deps = {}, platform = process.p
20724
20726
  return { ok: false, error: String(code) };
20725
20727
  }
20726
20728
  }
20729
+ function probeCommandOutput(command, args, platform = process.platform) {
20730
+ try {
20731
+ const output = execFileSync2(command, args, {
20732
+ encoding: "utf8",
20733
+ timeout: PROBE_TIMEOUT_MS,
20734
+ maxBuffer: PROBE_OUTPUT_MAX_BYTES,
20735
+ shell: needsWindowsShimShell(command, platform),
20736
+ stdio: ["pipe", "pipe", "ignore"],
20737
+ input: "",
20738
+ env: { ...process.env, CI: "1" }
20739
+ });
20740
+ return { ok: true, output };
20741
+ } catch (err) {
20742
+ const code = err?.code ?? "command_probe_failed";
20743
+ return { ok: false, error: String(code) };
20744
+ }
20745
+ }
20727
20746
  function resolveHomePath(relativePath, deps = {}) {
20728
20747
  return path5.join(deps.homeDir || process.env.HOME || ".", relativePath);
20729
20748
  }
@@ -20830,6 +20849,14 @@ class ClaudeTurnProtocol {
20830
20849
  }
20831
20850
 
20832
20851
  // agent-driver/dist/adapters/claude/index.js
20852
+ var CLAUDE_MODEL_CATALOG = {
20853
+ updateMode: "unsupported",
20854
+ models: ["opus", "sonnet", "haiku"].map((id) => ({
20855
+ id,
20856
+ supportedReasoningEfforts: []
20857
+ }))
20858
+ };
20859
+
20833
20860
  class ClaudeDriver {
20834
20861
  id = "claude";
20835
20862
  instructionDelivery = { kind: "workspace_file", canonical: "AGENTS.md", aliases: ["CLAUDE.md"] };
@@ -20846,10 +20873,11 @@ class ClaudeDriver {
20846
20873
  }
20847
20874
  probe(command) {
20848
20875
  const explicit = command?.trim();
20849
- if (!explicit)
20850
- return probeClaude();
20851
- const result = probeCommandVersion(explicit);
20852
- return result.ok ? { status: "healthy", version: result.version } : { status: "unhealthy", lastError: result.error };
20876
+ const base = explicit ? (() => {
20877
+ const result = probeCommandVersion(explicit);
20878
+ return result.ok ? { status: "healthy", version: result.version } : { status: "unhealthy", lastError: result.error };
20879
+ })() : probeClaude();
20880
+ return base.status === "healthy" ? { ...base, reasoning: CLAUDE_MODEL_CATALOG } : base;
20853
20881
  }
20854
20882
  async openLane(ctx, options) {
20855
20883
  return createProcessLane(this, ctx, { onRawStdoutLine: options?.onRawStdoutLine });
@@ -21416,10 +21444,59 @@ function stableErrorCode(value, fallback) {
21416
21444
  return /^[A-Za-z0-9_.-]{1,100}$/.test(code) ? code : fallback;
21417
21445
  }
21418
21446
 
21447
+ // agent-driver/dist/internal/modelCatalog.js
21448
+ var RUNTIME_MODEL_CATALOG_MAX = 512;
21449
+ var RUNTIME_MODEL_ID_MAX = 100;
21450
+ function normalizeRuntimeModelId(value) {
21451
+ if (typeof value !== "string")
21452
+ return;
21453
+ const id = value.trim();
21454
+ if (!id || id.length > RUNTIME_MODEL_ID_MAX || /\s/.test(id))
21455
+ return;
21456
+ return id;
21457
+ }
21458
+ function catalogFromIds(ids) {
21459
+ const seen = new Set;
21460
+ const models = [];
21461
+ for (const rawId of ids) {
21462
+ const id = normalizeRuntimeModelId(rawId);
21463
+ if (!id || seen.has(id))
21464
+ continue;
21465
+ if (models.length >= RUNTIME_MODEL_CATALOG_MAX)
21466
+ return;
21467
+ seen.add(id);
21468
+ models.push({ id, supportedReasoningEfforts: [] });
21469
+ }
21470
+ if (models.length === 0)
21471
+ return;
21472
+ return { updateMode: "unsupported", models };
21473
+ }
21474
+ function parseOpenCodeModelCatalog(output) {
21475
+ const ids = output.split(/\r?\n/).flatMap((line) => {
21476
+ const id = normalizeRuntimeModelId(line);
21477
+ return id && /^[^/]+\/.+$/.test(id) ? [id] : [];
21478
+ });
21479
+ return catalogFromIds(ids);
21480
+ }
21481
+ function parsePiModelCatalog(values) {
21482
+ if (!Array.isArray(values))
21483
+ return;
21484
+ const ids = values.flatMap((value) => {
21485
+ if (!value || typeof value !== "object")
21486
+ return [];
21487
+ const model = value;
21488
+ const provider = normalizeRuntimeModelId(model.provider);
21489
+ const id = normalizeRuntimeModelId(model.id);
21490
+ return provider && id && !provider.includes("/") ? [`${provider}/${id}`] : [];
21491
+ });
21492
+ return catalogFromIds(ids);
21493
+ }
21494
+
21419
21495
  // agent-driver/dist/adapters/codex/index.js
21420
21496
  var SETTINGS_UPDATE_TIMEOUT_MS = 5000;
21421
21497
  var MODEL_LIST_TIMEOUT_MS = 5000;
21422
- var MODEL_LIST_MAX = 64;
21498
+ var MODEL_LIST_OUTPUT_MAX_BYTES = 1024 * 1024;
21499
+ var MODEL_LIST_MAX = RUNTIME_MODEL_CATALOG_MAX;
21423
21500
  var MODEL_EFFORT_MAX = 16;
21424
21501
  function isCodexMissingRolloutError(message2) {
21425
21502
  return /\bno\s+rollout\s+found\b/i.test(message2) || /\bmissing\s+rollout\b/i.test(message2) || /\brollout\b.*\b(not found|missing)\b/i.test(message2) || /\b(not found|missing)\b.*\brollout\b/i.test(message2);
@@ -21495,11 +21572,13 @@ class CodexDriver {
21495
21572
  return new Promise((resolve2) => {
21496
21573
  let settled = false;
21497
21574
  let buffer = "";
21575
+ let outputBytes = 0;
21498
21576
  let nextId = 0;
21499
21577
  let initializeId = 0;
21500
21578
  let listId = 0;
21501
21579
  const models = [];
21502
21580
  const seenModels = new Set;
21581
+ let overflow = false;
21503
21582
  let defaultModelId;
21504
21583
  const finish = (catalog) => {
21505
21584
  if (settled)
@@ -21517,12 +21596,16 @@ class CodexDriver {
21517
21596
  `);
21518
21597
  };
21519
21598
  const consumeModel = (value) => {
21520
- if (!value || typeof value !== "object" || models.length >= MODEL_LIST_MAX)
21599
+ if (!value || typeof value !== "object")
21521
21600
  return;
21522
21601
  const model = value;
21523
- const id = typeof model.id === "string" ? model.id.trim() : "";
21524
- if (!id || id.length > 100 || seenModels.has(id))
21602
+ const id = normalizeRuntimeModelId(model.id);
21603
+ if (!id || seenModels.has(id))
21525
21604
  return;
21605
+ if (models.length >= MODEL_LIST_MAX) {
21606
+ overflow = true;
21607
+ return;
21608
+ }
21526
21609
  const rawOptions = Array.isArray(model.supportedReasoningEfforts) ? model.supportedReasoningEfforts : [];
21527
21610
  const seenEfforts = new Set;
21528
21611
  const supportedReasoningEfforts = rawOptions.flatMap((raw) => {
@@ -21566,9 +21649,15 @@ class CodexDriver {
21566
21649
  const result = message2.result;
21567
21650
  for (const model of Array.isArray(result.data) ? result.data : [])
21568
21651
  consumeModel(model);
21652
+ if (overflow)
21653
+ return finish();
21569
21654
  const cursor = typeof result.nextCursor === "string" ? result.nextCursor : undefined;
21570
- if (cursor && models.length < MODEL_LIST_MAX)
21655
+ if (cursor && models.length >= MODEL_LIST_MAX)
21656
+ return finish();
21657
+ if (cursor)
21571
21658
  return requestModelPage(cursor);
21659
+ if (models.length === 0)
21660
+ return finish();
21572
21661
  finish({
21573
21662
  updateMode: "live_next_turn",
21574
21663
  ...defaultModelId ? { defaultModelId } : {},
@@ -21578,7 +21667,11 @@ class CodexDriver {
21578
21667
  const timer = setTimeout(() => finish(), MODEL_LIST_TIMEOUT_MS);
21579
21668
  timer.unref?.();
21580
21669
  proc.stdout?.on("data", (chunk2) => {
21581
- buffer += chunk2.toString();
21670
+ const text2 = chunk2.toString();
21671
+ outputBytes += Buffer.byteLength(text2);
21672
+ if (outputBytes > MODEL_LIST_OUTPUT_MAX_BYTES)
21673
+ return finish();
21674
+ buffer += text2;
21582
21675
  const lines = buffer.split(`
21583
21676
  `);
21584
21677
  buffer = lines.pop() ?? "";
@@ -21781,9 +21874,189 @@ class CodexDriver {
21781
21874
 
21782
21875
  // agent-driver/dist/adapters/cursor/acp-lane.js
21783
21876
  import { EventEmitter as EventEmitter2 } from "node:events";
21877
+
21878
+ // agent-driver/dist/adapters/cursor/catalog-probe.js
21784
21879
  var ACP_PROTOCOL_VERSION = 1;
21785
- var HANDSHAKE_TIMEOUT_MS = 15000;
21786
21880
  var AUTH_METHOD_ID = "cursor_login";
21881
+ var CATALOG_PROBE_TIMEOUT_MS = 15000;
21882
+ var CATALOG_PROBE_OUTPUT_MAX_BYTES = 1024 * 1024;
21883
+ var MODEL_DISPLAY_NAME_MAX = 256;
21884
+ var MODEL_OPTION_NESTING_MAX = 16;
21885
+ function record2(value) {
21886
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
21887
+ }
21888
+ function normalizeDisplayName(value) {
21889
+ if (typeof value !== "string")
21890
+ return;
21891
+ const displayName = value.trim();
21892
+ return displayName && displayName.length <= MODEL_DISPLAY_NAME_MAX ? displayName : undefined;
21893
+ }
21894
+ function flattenCursorAcpSelectOptions(value, depth = 0) {
21895
+ if (!Array.isArray(value) || depth > MODEL_OPTION_NESTING_MAX)
21896
+ return [];
21897
+ const options = [];
21898
+ for (const item of value) {
21899
+ if (Array.isArray(item)) {
21900
+ options.push(...flattenCursorAcpSelectOptions(item, depth + 1));
21901
+ continue;
21902
+ }
21903
+ const candidate = record2(item);
21904
+ if (!candidate)
21905
+ continue;
21906
+ const exactValue = normalizeRuntimeModelId(candidate.value);
21907
+ if (exactValue) {
21908
+ const name = normalizeDisplayName(candidate.name);
21909
+ options.push({ value: exactValue, ...name ? { name } : {} });
21910
+ }
21911
+ if (Array.isArray(candidate.options)) {
21912
+ options.push(...flattenCursorAcpSelectOptions(candidate.options, depth + 1));
21913
+ }
21914
+ }
21915
+ return options;
21916
+ }
21917
+ function parseCursorAcpModelCatalog(session2) {
21918
+ const payload = record2(session2);
21919
+ const configOptions = Array.isArray(payload?.configOptions) ? payload.configOptions : [];
21920
+ const modelConfig = configOptions.map(record2).find((option) => option?.id === "model") ?? null;
21921
+ if (!modelConfig)
21922
+ return;
21923
+ const seen = new Set;
21924
+ const models = [];
21925
+ for (const option of flattenCursorAcpSelectOptions(modelConfig.options)) {
21926
+ if (option.value === "default[]" || seen.has(option.value))
21927
+ continue;
21928
+ if (models.length >= RUNTIME_MODEL_CATALOG_MAX)
21929
+ return;
21930
+ seen.add(option.value);
21931
+ models.push({
21932
+ id: option.value,
21933
+ ...option.name ? { displayName: option.name } : {},
21934
+ supportedReasoningEfforts: []
21935
+ });
21936
+ }
21937
+ return models.length > 0 ? { updateMode: "unsupported", models } : undefined;
21938
+ }
21939
+ async function cleanupProbeProcess(process3) {
21940
+ if (process3.pid) {
21941
+ await killProcessTree(process3.pid, { graceMs: 250 }).catch(() => {});
21942
+ return;
21943
+ }
21944
+ if (process3.exitCode === null && process3.signalCode === null)
21945
+ process3.kill("SIGTERM");
21946
+ }
21947
+ async function probeCursorAcpCatalog(command, options = {}) {
21948
+ const cwd = options.cwd ?? process.cwd();
21949
+ const spec = resolveSpawnSpec("cursor-agent", ["acp"], command);
21950
+ let processHandle;
21951
+ try {
21952
+ processHandle = (options.spawn ?? spawnAgentProcess)(spec.command, spec.args, {
21953
+ cwd,
21954
+ env: { ...process.env, CI: "1" },
21955
+ shell: spec.shell
21956
+ });
21957
+ } catch {
21958
+ return;
21959
+ }
21960
+ return new Promise((resolve2) => {
21961
+ let settled = false;
21962
+ let buffer = "";
21963
+ let outputBytes = 0;
21964
+ let requestId = 0;
21965
+ let expectedId = 0;
21966
+ let expectedMethod = "";
21967
+ const finish = (catalog) => {
21968
+ if (settled)
21969
+ return;
21970
+ settled = true;
21971
+ clearTimeout(timer);
21972
+ const cleanup = options.cleanup ?? cleanupProbeProcess;
21973
+ Promise.resolve().then(() => cleanup(processHandle)).catch(() => {}).finally(() => resolve2(catalog));
21974
+ };
21975
+ const request = (method, params) => {
21976
+ if (settled)
21977
+ return;
21978
+ const stdin = processHandle.stdin;
21979
+ if (!stdin || stdin.destroyed || stdin.writableEnded || stdin.writable === false)
21980
+ return finish();
21981
+ expectedId = ++requestId;
21982
+ expectedMethod = method;
21983
+ try {
21984
+ stdin.write(`${jsonRpcRequest(method, params, expectedId)}
21985
+ `);
21986
+ } catch {
21987
+ finish();
21988
+ }
21989
+ };
21990
+ const onLine = (line) => {
21991
+ const parsed = tryParseJsonLine(line);
21992
+ const message2 = record2(parsed);
21993
+ if (!message2)
21994
+ return finish();
21995
+ if (message2.id !== expectedId)
21996
+ return;
21997
+ if (message2.error !== undefined)
21998
+ return finish();
21999
+ if (!Object.prototype.hasOwnProperty.call(message2, "result"))
22000
+ return finish();
22001
+ if (expectedMethod === "authenticate") {
22002
+ request("session/new", { cwd, mcpServers: [] });
22003
+ return;
22004
+ }
22005
+ const result = record2(message2.result);
22006
+ if (!result)
22007
+ return finish();
22008
+ if (expectedMethod === "initialize") {
22009
+ const authMethods = Array.isArray(result.authMethods) ? result.authMethods : [];
22010
+ if (result.protocolVersion !== ACP_PROTOCOL_VERSION || !authMethods.some((method) => record2(method)?.id === AUTH_METHOD_ID))
22011
+ return finish();
22012
+ request("authenticate", { methodId: AUTH_METHOD_ID });
22013
+ return;
22014
+ }
22015
+ if (expectedMethod !== "session/new" || typeof result.sessionId !== "string" || !result.sessionId.trim())
22016
+ return finish();
22017
+ finish(parseCursorAcpModelCatalog(result));
22018
+ };
22019
+ const timer = setTimeout(() => finish(), options.timeoutMs ?? CATALOG_PROBE_TIMEOUT_MS);
22020
+ timer.unref?.();
22021
+ processHandle.stdout?.on("data", (chunk2) => {
22022
+ if (settled)
22023
+ return;
22024
+ const text2 = chunk2.toString();
22025
+ outputBytes += Buffer.byteLength(text2);
22026
+ if (outputBytes > (options.outputMaxBytes ?? CATALOG_PROBE_OUTPUT_MAX_BYTES))
22027
+ return finish();
22028
+ buffer += text2;
22029
+ const lines = buffer.split(`
22030
+ `);
22031
+ buffer = lines.pop() ?? "";
22032
+ for (const line of lines)
22033
+ if (line.trim())
22034
+ onLine(line);
22035
+ });
22036
+ processHandle.stderr?.on("data", (chunk2) => {
22037
+ if (settled)
22038
+ return;
22039
+ outputBytes += Buffer.byteLength(chunk2.toString());
22040
+ if (outputBytes > (options.outputMaxBytes ?? CATALOG_PROBE_OUTPUT_MAX_BYTES))
22041
+ finish();
22042
+ });
22043
+ processHandle.on("error", () => finish());
22044
+ processHandle.on("exit", () => finish());
22045
+ request("initialize", {
22046
+ protocolVersion: ACP_PROTOCOL_VERSION,
22047
+ clientCapabilities: {
22048
+ fs: { readTextFile: false, writeTextFile: false },
22049
+ terminal: false
22050
+ },
22051
+ clientInfo: { name: "alook-agent-driver-probe", version: "0.1.25" }
22052
+ });
22053
+ });
22054
+ }
22055
+
22056
+ // agent-driver/dist/adapters/cursor/acp-lane.js
22057
+ var ACP_PROTOCOL_VERSION2 = 1;
22058
+ var HANDSHAKE_TIMEOUT_MS = 15000;
22059
+ var AUTH_METHOD_ID2 = "cursor_login";
21787
22060
  var PROMPT_STOP_REASONS = new Set([
21788
22061
  "end_turn",
21789
22062
  "max_tokens",
@@ -21807,16 +22080,16 @@ class CursorAcpRpcError extends Error {
21807
22080
  this.code = code;
21808
22081
  }
21809
22082
  }
21810
- function record2(value) {
22083
+ function record3(value) {
21811
22084
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
21812
22085
  }
21813
22086
  function safeLabel(value) {
21814
22087
  return typeof value === "string" && /^[a-z0-9_-]{1,64}$/i.test(value) ? value : "unknown";
21815
22088
  }
21816
22089
  function rpcErrorMessage(error51) {
21817
- const payload = record2(error51);
22090
+ const payload = record3(error51);
21818
22091
  const message2 = typeof payload?.message === "string" && payload.message.trim() ? payload.message : "Cursor ACP request failed";
21819
- const data = record2(payload?.data);
22092
+ const data = record3(payload?.data);
21820
22093
  const detail = typeof data?.message === "string" && data.message.trim() ? data.message : undefined;
21821
22094
  return detail ? `${message2}: ${detail}` : message2;
21822
22095
  }
@@ -21824,26 +22097,6 @@ function isMissingSessionError(error51) {
21824
22097
  const message2 = error51 instanceof Error ? error51.message : String(error51);
21825
22098
  return /\bsession\b.*\b(not found|missing|unknown|invalid)\b/i.test(message2) || /\b(not found|missing|unknown|invalid)\b.*\bsession\b/i.test(message2);
21826
22099
  }
21827
- function flattenSelectOptions(value) {
21828
- if (!Array.isArray(value))
21829
- return [];
21830
- const out = [];
21831
- for (const item of value) {
21832
- if (Array.isArray(item)) {
21833
- out.push(...flattenSelectOptions(item));
21834
- continue;
21835
- }
21836
- const candidate = record2(item);
21837
- if (!candidate)
21838
- continue;
21839
- if (typeof candidate.value === "string") {
21840
- out.push({ value: candidate.value, ...typeof candidate.name === "string" ? { name: candidate.name } : {} });
21841
- }
21842
- if (Array.isArray(candidate.options))
21843
- out.push(...flattenSelectOptions(candidate.options));
21844
- }
21845
- return out;
21846
- }
21847
22100
 
21848
22101
  class CursorAcpLane {
21849
22102
  factory;
@@ -21967,30 +22220,30 @@ class CursorAcpLane {
21967
22220
  }
21968
22221
  }
21969
22222
  async handshake(ctx) {
21970
- const initialize = record2(await this.call("initialize", {
21971
- protocolVersion: ACP_PROTOCOL_VERSION,
22223
+ const initialize = record3(await this.call("initialize", {
22224
+ protocolVersion: ACP_PROTOCOL_VERSION2,
21972
22225
  clientCapabilities: {
21973
22226
  fs: { readTextFile: false, writeTextFile: false },
21974
22227
  terminal: false
21975
22228
  },
21976
22229
  clientInfo: { name: "alook-agent-driver", version: "0.1.14" }
21977
22230
  }));
21978
- if (initialize?.protocolVersion !== ACP_PROTOCOL_VERSION) {
22231
+ if (initialize?.protocolVersion !== ACP_PROTOCOL_VERSION2) {
21979
22232
  throw new CursorAcpIncompatibleError("Installed Cursor ACP does not support protocol version 1");
21980
22233
  }
21981
- const capabilities = record2(initialize.agentCapabilities);
22234
+ const capabilities = record3(initialize.agentCapabilities);
21982
22235
  if (capabilities?.loadSession !== true) {
21983
22236
  throw new CursorAcpIncompatibleError("Installed Cursor ACP does not support persistent session loading");
21984
22237
  }
21985
22238
  const authMethods = Array.isArray(initialize.authMethods) ? initialize.authMethods : [];
21986
- if (!authMethods.some((method) => record2(method)?.id === AUTH_METHOD_ID)) {
22239
+ if (!authMethods.some((method) => record3(method)?.id === AUTH_METHOD_ID2)) {
21987
22240
  throw new CursorAcpIncompatibleError("Installed Cursor ACP does not expose Cursor login authentication");
21988
22241
  }
21989
- await this.call("authenticate", { methodId: AUTH_METHOD_ID });
22242
+ await this.call("authenticate", { methodId: AUTH_METHOD_ID2 });
21990
22243
  let session2;
21991
22244
  if (ctx.config.sessionId) {
21992
22245
  try {
21993
- session2 = record2(await this.call("session/load", {
22246
+ session2 = record3(await this.call("session/load", {
21994
22247
  sessionId: ctx.config.sessionId,
21995
22248
  cwd: ctx.workingDirectory,
21996
22249
  mcpServers: []
@@ -22002,15 +22255,25 @@ class CursorAcpLane {
22002
22255
  throw error51;
22003
22256
  }
22004
22257
  } else {
22005
- session2 = record2(await this.call("session/new", { cwd: ctx.workingDirectory, mcpServers: [] }));
22258
+ session2 = record3(await this.call("session/new", { cwd: ctx.workingDirectory, mcpServers: [] }));
22006
22259
  }
22007
- if (!session2 || typeof session2.sessionId !== "string" || !session2.sessionId.trim()) {
22260
+ if (!session2)
22261
+ throw new Error("Cursor ACP did not return a valid session response");
22262
+ const returnedSessionId = session2.sessionId;
22263
+ if (returnedSessionId !== undefined && (typeof returnedSessionId !== "string" || !returnedSessionId.trim())) {
22008
22264
  throw new Error("Cursor ACP did not return a valid session id");
22009
22265
  }
22010
- if (ctx.config.sessionId && session2.sessionId !== ctx.config.sessionId) {
22011
- throw new CursorAcpResetRequiredError("Cursor ACP loaded a different session; reset this agent before continuing");
22266
+ if (ctx.config.sessionId) {
22267
+ if (returnedSessionId !== undefined && returnedSessionId !== ctx.config.sessionId) {
22268
+ throw new CursorAcpResetRequiredError("Cursor ACP loaded a different session; reset this agent before continuing");
22269
+ }
22270
+ this.sessionId = ctx.config.sessionId;
22271
+ } else {
22272
+ if (typeof returnedSessionId !== "string") {
22273
+ throw new Error("Cursor ACP did not return a valid session id");
22274
+ }
22275
+ this.sessionId = returnedSessionId;
22012
22276
  }
22013
- this.sessionId = session2.sessionId;
22014
22277
  await this.configureModel(session2, ctx);
22015
22278
  }
22016
22279
  async configureModel(session2, ctx) {
@@ -22018,24 +22281,30 @@ class CursorAcpLane {
22018
22281
  if (!requestedModel)
22019
22282
  return;
22020
22283
  const configOptions = Array.isArray(session2.configOptions) ? session2.configOptions : [];
22021
- const modelConfig = configOptions.map(record2).find((option) => option?.id === "model") ?? null;
22284
+ const modelConfig = configOptions.map(record3).find((option) => option?.id === "model") ?? null;
22022
22285
  if (!modelConfig) {
22023
22286
  throw new CursorAcpIncompatibleError("Installed Cursor ACP does not support model configuration");
22024
22287
  }
22025
- const options = flattenSelectOptions(modelConfig.options);
22026
- const match = options.find((option) => option.value === requestedModel) ?? options.find((option) => option.name === requestedModel);
22288
+ const options = flattenCursorAcpSelectOptions(modelConfig.options);
22289
+ const match = options.find((option) => option.value === requestedModel);
22027
22290
  if (!match) {
22028
22291
  throw new CursorAcpIncompatibleError(`Configured Cursor model is unavailable through ACP: ${requestedModel}`);
22029
22292
  }
22293
+ let response;
22030
22294
  try {
22031
- await this.call("session/set_config_option", {
22295
+ response = record3(await this.call("session/set_config_option", {
22032
22296
  sessionId: this.sessionId,
22033
22297
  configId: "model",
22034
22298
  value: match.value
22035
- });
22299
+ }));
22036
22300
  } catch {
22037
22301
  throw new CursorAcpIncompatibleError("Installed Cursor ACP rejected model configuration");
22038
22302
  }
22303
+ const confirmedOptions = Array.isArray(response?.configOptions) ? response.configOptions : [];
22304
+ const confirmedModel = confirmedOptions.map(record3).find((option) => option?.id === "model") ?? null;
22305
+ if (confirmedModel?.currentValue !== match.value) {
22306
+ throw new CursorAcpIncompatibleError("Cursor ACP did not confirm the exact configured model");
22307
+ }
22039
22308
  }
22040
22309
  admitPrompt(text2) {
22041
22310
  if (!this.sessionId)
@@ -22071,7 +22340,7 @@ class CursorAcpLane {
22071
22340
  completePrompt(active, value) {
22072
22341
  if (this.activePrompt?.requestId !== active.requestId)
22073
22342
  return;
22074
- const result = record2(value);
22343
+ const result = record3(value);
22075
22344
  if (!result || typeof result.stopReason !== "string" || !PROMPT_STOP_REASONS.has(result.stopReason)) {
22076
22345
  this.failPrompt(active, new Error("Cursor ACP prompt response did not contain a supported stopReason"));
22077
22346
  return;
@@ -22213,7 +22482,7 @@ class CursorAcpLane {
22213
22482
  });
22214
22483
  }
22215
22484
  handleMessage(value) {
22216
- const message2 = record2(value);
22485
+ const message2 = record3(value);
22217
22486
  if (!message2 || message2.jsonrpc !== "2.0") {
22218
22487
  this.protocolFailure("Cursor ACP emitted an invalid JSON-RPC message");
22219
22488
  return;
@@ -22241,7 +22510,7 @@ class CursorAcpLane {
22241
22510
  if (pending.kind === "prompt") {
22242
22511
  this.pending.delete(id);
22243
22512
  if (message2.error !== undefined) {
22244
- const payload = record2(message2.error);
22513
+ const payload = record3(message2.error);
22245
22514
  this.failPrompt(pending.active, new CursorAcpRpcError(pending.method, typeof payload?.code === "number" ? payload.code : undefined, rpcErrorMessage(message2.error)));
22246
22515
  } else if (!("result" in message2)) {
22247
22516
  this.failPrompt(pending.active, new Error("Cursor ACP response omitted result"));
@@ -22251,7 +22520,7 @@ class CursorAcpLane {
22251
22520
  return;
22252
22521
  }
22253
22522
  if (message2.error !== undefined) {
22254
- const payload = record2(message2.error);
22523
+ const payload = record3(message2.error);
22255
22524
  this.settleRequest(id, false, new CursorAcpRpcError(pending.method, typeof payload?.code === "number" ? payload.code : undefined, rpcErrorMessage(message2.error)));
22256
22525
  return;
22257
22526
  }
@@ -22283,9 +22552,9 @@ class CursorAcpLane {
22283
22552
  this.diagnostic("warning", `Unsupported Cursor ACP client request: ${safeLabel(method)}`);
22284
22553
  return;
22285
22554
  }
22286
- const payload = record2(params);
22555
+ const payload = record3(params);
22287
22556
  const sameSession = payload?.sessionId === this.sessionId;
22288
- const options = Array.isArray(payload?.options) ? payload.options.map(record2).filter(Boolean) : [];
22557
+ const options = Array.isArray(payload?.options) ? payload.options.map(record3).filter(Boolean) : [];
22289
22558
  const allowOnce = options.find((option) => option.kind === "allow_once" && typeof option.optionId === "string" && option.optionId.trim().length > 0);
22290
22559
  if (!this.ready || !this.activePrompt || !sameSession || !allowOnce) {
22291
22560
  this.write({ jsonrpc: "2.0", id, result: { outcome: { outcome: "cancelled" } } });
@@ -22306,7 +22575,7 @@ class CursorAcpLane {
22306
22575
  this.diagnostic("warning", `Unsupported Cursor ACP notification: ${safeLabel(method)}`);
22307
22576
  }
22308
22577
  handleSessionUpdate(params) {
22309
- const payload = record2(params);
22578
+ const payload = record3(params);
22310
22579
  if (!payload || payload.sessionId !== this.sessionId) {
22311
22580
  this.diagnostic("warning", "Cursor ACP emitted an update for a different session");
22312
22581
  return;
@@ -22315,18 +22584,18 @@ class CursorAcpLane {
22315
22584
  this.diagnostic("warning", "Cursor ACP emitted a session update without an active prompt");
22316
22585
  return;
22317
22586
  }
22318
- const update = record2(payload.update) ?? {};
22587
+ const update = record3(payload.update) ?? {};
22319
22588
  const updateType = update?.sessionUpdate;
22320
22589
  switch (updateType) {
22321
22590
  case "agent_message_chunk": {
22322
- const content = record2(update.content);
22591
+ const content = record3(update.content);
22323
22592
  if (content?.type === "text" && typeof content.text === "string") {
22324
22593
  this.events.emit("runtime_event", { kind: "assistant_message_delta", text: content.text });
22325
22594
  }
22326
22595
  return;
22327
22596
  }
22328
22597
  case "agent_thought_chunk": {
22329
- const content = record2(update.content);
22598
+ const content = record3(update.content);
22330
22599
  if (content?.type === "text" && typeof content.text === "string") {
22331
22600
  this.events.emit("runtime_event", { kind: "assistant_reasoning_delta", text: content.text });
22332
22601
  }
@@ -22398,6 +22667,7 @@ class CursorAcpLane {
22398
22667
 
22399
22668
  // agent-driver/dist/adapters/cursor/index.js
22400
22669
  class CursorDriver {
22670
+ catalogProbe;
22401
22671
  id = "cursor";
22402
22672
  instructionDelivery = { kind: "workspace_file", canonical: "AGENTS.md", aliases: ["CLAUDE.md"] };
22403
22673
  execution = {
@@ -22406,8 +22676,23 @@ class CursorDriver {
22406
22676
  wakeStart: "immediate",
22407
22677
  terminalOwnership: "transport_request"
22408
22678
  };
22409
- probe(command) {
22410
- return probeCliRuntime("cursor-agent", {}, command);
22679
+ constructor(catalogProbe = probeCursorAcpCatalog) {
22680
+ this.catalogProbe = catalogProbe;
22681
+ }
22682
+ async probe(command) {
22683
+ const result = probeCliRuntime("cursor-agent", {}, command);
22684
+ if (result.status !== "healthy")
22685
+ return result;
22686
+ let reasoning;
22687
+ try {
22688
+ reasoning = await this.catalogProbe(command);
22689
+ } catch {
22690
+ reasoning = undefined;
22691
+ }
22692
+ return {
22693
+ ...result,
22694
+ reasoning
22695
+ };
22411
22696
  }
22412
22697
  async openLane(ctx, options) {
22413
22698
  return new CursorAcpLane(this, ctx, { onRawStdoutLine: options?.onRawStdoutLine });
@@ -22464,7 +22749,7 @@ class OpenCodeHttpError extends Error {
22464
22749
  this.status = status;
22465
22750
  }
22466
22751
  }
22467
- function record3(value) {
22752
+ function record4(value) {
22468
22753
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
22469
22754
  }
22470
22755
  function safeLabel2(value) {
@@ -22511,7 +22796,7 @@ function parseModelRef(model) {
22511
22796
  return { providerID: model.slice(0, slash), id: model.slice(slash + 1) };
22512
22797
  }
22513
22798
  function messageFromError(value) {
22514
- const payload = record3(value);
22799
+ const payload = record4(value);
22515
22800
  const message2 = typeof payload?.message === "string" && payload.message.trim() ? payload.message : undefined;
22516
22801
  return message2 ? "OpenCode turn failed" : "OpenCode reported an inconsistent turn outcome";
22517
22802
  }
@@ -22845,7 +23130,7 @@ class OpenCodeServiceLane {
22845
23130
  const healthTimeoutMs = Math.max(1, Math.min(1000, deadline - Date.now(), this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS));
22846
23131
  const { response, body } = await this.fetchJsonWithTimeout("/global/health", { method: "GET" }, "health", healthTimeoutMs);
22847
23132
  if (response.ok) {
22848
- const health = record3(body);
23133
+ const health = record4(body);
22849
23134
  if (health?.healthy !== true || health.version !== SUPPORTED_VERSION) {
22850
23135
  throw new OpenCodeIncompatibleError(`Installed OpenCode service must be version ${SUPPORTED_VERSION}`);
22851
23136
  }
@@ -22866,8 +23151,8 @@ class OpenCodeServiceLane {
22866
23151
  const { response, body } = await this.fetchJsonWithTimeout("/doc", { method: "GET" }, "OpenAPI");
22867
23152
  if (!response.ok)
22868
23153
  throw new OpenCodeIncompatibleError("Installed OpenCode service does not expose its OpenAPI document");
22869
- const document = record3(body);
22870
- const paths = record3(document?.paths);
23154
+ const document = record4(body);
23155
+ const paths = record4(document?.paths);
22871
23156
  const required2 = [
22872
23157
  "/api/session",
22873
23158
  "/api/session/active",
@@ -22880,7 +23165,7 @@ class OpenCodeServiceLane {
22880
23165
  "/api/session/{sessionID}/permission/{requestID}/reply",
22881
23166
  "/api/event"
22882
23167
  ];
22883
- if (!paths || required2.some((path7) => !record3(paths[path7]))) {
23168
+ if (!paths || required2.some((path7) => !record4(paths[path7]))) {
22884
23169
  throw new OpenCodeIncompatibleError("Installed OpenCode service is missing required v2 session capabilities");
22885
23170
  }
22886
23171
  }
@@ -22893,7 +23178,7 @@ class OpenCodeServiceLane {
22893
23178
  }
22894
23179
  if (!response2.ok)
22895
23180
  throw new OpenCodeHttpError(response2.status, "session resume");
22896
- const session3 = record3(record3(body2)?.data);
23181
+ const session3 = record4(record4(body2)?.data);
22897
23182
  if (session3?.id !== resumeId) {
22898
23183
  throw new OpenCodeResetRequiredError("OpenCode v2 returned a different resumed session; reset this agent before continuing");
22899
23184
  }
@@ -22914,8 +23199,8 @@ class OpenCodeServiceLane {
22914
23199
  }, "session create");
22915
23200
  if (!response.ok)
22916
23201
  throw new OpenCodeHttpError(response.status, "session create");
22917
- const payload = record3(responseBody);
22918
- const session2 = record3(payload?.data);
23202
+ const payload = record4(responseBody);
23203
+ const session2 = record4(payload?.data);
22919
23204
  if (typeof session2?.id !== "string" || !/^ses/.test(session2.id)) {
22920
23205
  throw new Error("OpenCode v2 did not return a valid session id");
22921
23206
  }
@@ -23072,7 +23357,7 @@ class OpenCodeServiceLane {
23072
23357
  const { response, body: responseBody } = await this.fetchJsonWithTimeout(`/api/session/${encodeURIComponent(this.sessionId)}/history?after=${historyCursor}&limit=${HISTORY_PAGE_LIMIT}`, { method: "GET" }, "session history");
23073
23358
  if (!response.ok)
23074
23359
  throw new OpenCodeHttpError(response.status, "session history");
23075
- const body = record3(responseBody);
23360
+ const body = record4(responseBody);
23076
23361
  if (!Array.isArray(body?.data) || typeof body.hasMore !== "boolean") {
23077
23362
  throw new OpenCodeProtocolError("OpenCode session history returned an invalid page");
23078
23363
  }
@@ -23090,9 +23375,9 @@ class OpenCodeServiceLane {
23090
23375
  return run;
23091
23376
  }
23092
23377
  async handleDurableEvent(value, project) {
23093
- const event = record3(value);
23094
- const durable = record3(event?.durable);
23095
- const data = record3(event?.data);
23378
+ const event = record4(value);
23379
+ const durable = record4(event?.durable);
23380
+ const data = record4(event?.data);
23096
23381
  if (!event || typeof event.id !== "string" || typeof event.type !== "string" || !durable || durable.aggregateID !== this.sessionId || !Number.isInteger(durable.seq) || Number(durable.seq) < 0 || data?.sessionID !== this.sessionId) {
23097
23382
  throw new OpenCodeProtocolError("OpenCode session stream emitted an invalid durable event");
23098
23383
  }
@@ -23182,9 +23467,9 @@ class OpenCodeServiceLane {
23182
23467
  ...!successful ? { message: "OpenCode reported an unsupported final step outcome" } : {}
23183
23468
  });
23184
23469
  }
23185
- const tokens = record3(data.tokens);
23470
+ const tokens = record4(data.tokens);
23186
23471
  if (tokens && data.finish !== "tool-calls") {
23187
- const cache = record3(tokens.cache);
23472
+ const cache = record4(tokens.cache);
23188
23473
  const metric2 = (value2) => typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= 0 ? value2 : null;
23189
23474
  const cacheParts = [cache?.read, cache?.write].filter((value2) => typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= 0);
23190
23475
  const cacheTotal = cacheParts.reduce((sum, value2) => sum + value2, 0);
@@ -23211,8 +23496,8 @@ class OpenCodeServiceLane {
23211
23496
  return seq;
23212
23497
  }
23213
23498
  async handleLiveEvent(value) {
23214
- const event = record3(value);
23215
- const data = record3(event?.data);
23499
+ const event = record4(value);
23500
+ const data = record4(event?.data);
23216
23501
  if (event?.type !== "permission.v2.asked" || data?.sessionID !== this.sessionId)
23217
23502
  return;
23218
23503
  if (typeof data.id !== "string" || !/^per/.test(data.id)) {
@@ -23226,11 +23511,11 @@ class OpenCodeServiceLane {
23226
23511
  const { response, body: responseBody } = await this.fetchJsonWithTimeout(`/api/session/${encodeURIComponent(this.sessionId)}/permission`, { method: "GET" }, "permission list");
23227
23512
  if (!response.ok)
23228
23513
  throw new OpenCodeHttpError(response.status, "permission list");
23229
- const body = record3(responseBody);
23514
+ const body = record4(responseBody);
23230
23515
  if (!Array.isArray(body?.data))
23231
23516
  throw new OpenCodeProtocolError("OpenCode permission list returned invalid data");
23232
23517
  for (const item of body.data) {
23233
- const permission = record3(item);
23518
+ const permission = record4(item);
23234
23519
  if (permission?.sessionID === this.sessionId && typeof permission.id === "string") {
23235
23520
  await this.replyPermission(permission.id);
23236
23521
  }
@@ -23297,8 +23582,8 @@ class OpenCodeServiceLane {
23297
23582
  }, "prompt admission");
23298
23583
  if (!response.ok)
23299
23584
  throw new OpenCodeHttpError(response.status, "prompt admission");
23300
- const body = record3(responseBody);
23301
- const admitted = record3(body?.data);
23585
+ const body = record4(responseBody);
23586
+ const admitted = record4(body?.data);
23302
23587
  if (admitted?.id !== messageId || admitted.sessionID !== this.sessionId || admitted.delivery !== delivery || !Number.isInteger(admitted.admittedSeq) || Number(admitted.admittedSeq) < 0) {
23303
23588
  throw new OpenCodeProtocolError("OpenCode prompt admission returned an invalid receipt");
23304
23589
  }
@@ -23365,8 +23650,8 @@ class OpenCodeServiceLane {
23365
23650
  const { response, body: responseBody } = await this.fetchJsonWithTimeout("/api/session/active", { method: "GET" }, "active session query");
23366
23651
  if (!response.ok)
23367
23652
  throw new OpenCodeHttpError(response.status, "active session query");
23368
- const body = record3(responseBody);
23369
- const active = record3(body?.data);
23653
+ const body = record4(responseBody);
23654
+ const active = record4(body?.data);
23370
23655
  if (!active)
23371
23656
  throw new OpenCodeProtocolError("OpenCode active session query returned invalid data");
23372
23657
  if (!this.barrierStillCurrent(root, identity, generation))
@@ -23571,6 +23856,7 @@ function createOpenCodeMessageId() {
23571
23856
  }
23572
23857
 
23573
23858
  class OpenCodeDriver {
23859
+ outputProbe;
23574
23860
  id = "opencode";
23575
23861
  instructionDelivery = { kind: "workspace_file", canonical: "AGENTS.md", aliases: ["CLAUDE.md"] };
23576
23862
  execution = {
@@ -23579,8 +23865,19 @@ class OpenCodeDriver {
23579
23865
  wakeStart: "immediate",
23580
23866
  terminalOwnership: "transport_request"
23581
23867
  };
23868
+ constructor(outputProbe = probeCommandOutput) {
23869
+ this.outputProbe = outputProbe;
23870
+ }
23582
23871
  probe(command) {
23583
- return probeCliRuntime("opencode", {}, command);
23872
+ const result = probeCliRuntime("opencode", {}, command);
23873
+ if (result.status !== "healthy")
23874
+ return result;
23875
+ const spec = resolveSpawnSpec("opencode", ["models", "--pure"], command);
23876
+ const output = this.outputProbe(spec.command, spec.args);
23877
+ return {
23878
+ ...result,
23879
+ reasoning: output.ok ? parseOpenCodeModelCatalog(output.output) : undefined
23880
+ };
23584
23881
  }
23585
23882
  beginTurn() {
23586
23883
  return createOpenCodeMessageId();
@@ -23834,6 +24131,7 @@ function createPiSessionDependencies(ctx, loadSdk = loadPiSdkModule) {
23834
24131
 
23835
24132
  // agent-driver/dist/adapters/pi/index.js
23836
24133
  var PI_SDK_PACKAGE_NAME2 = "@earendil-works/pi-coding-agent";
24134
+ var PI_MODEL_PROBE_TIMEOUT_MS = 5000;
23837
24135
  function isPiSdkPackageJson(pkgJsonPath) {
23838
24136
  if (!existsSync3(pkgJsonPath))
23839
24137
  return false;
@@ -23942,6 +24240,8 @@ function mapPiSdkEvent(event, sessionId, state) {
23942
24240
 
23943
24241
  class PiDriver {
23944
24242
  dependenciesFor;
24243
+ loadSdk;
24244
+ readVersion;
23945
24245
  id = "pi";
23946
24246
  instructionDelivery = { kind: "workspace_file", canonical: "AGENTS.md", aliases: ["CLAUDE.md"] };
23947
24247
  execution = {
@@ -23952,15 +24252,36 @@ class PiDriver {
23952
24252
  };
23953
24253
  sessionId = null;
23954
24254
  terminalSequence = 0;
23955
- constructor(dependenciesFor = createPiSessionDependencies) {
24255
+ constructor(dependenciesFor = createPiSessionDependencies, loadSdk = loadPiSdkModule, readVersion = readPiSdkVersion) {
23956
24256
  this.dependenciesFor = dependenciesFor;
24257
+ this.loadSdk = loadSdk;
24258
+ this.readVersion = readVersion;
23957
24259
  }
23958
- probe() {
23959
- const version3 = readPiSdkVersion();
24260
+ async probe() {
24261
+ const version3 = this.readVersion();
23960
24262
  if (!version3) {
23961
24263
  return { status: "unhealthy", lastError: "sdk_not_installed" };
23962
24264
  }
23963
- return { status: "healthy", version: version3 };
24265
+ let timer;
24266
+ try {
24267
+ const reasoning = await Promise.race([
24268
+ this.loadSdk().then(async (sdk) => {
24269
+ const authStorage = sdk.AuthStorage.create();
24270
+ const registry2 = sdk.ModelRegistry.create(authStorage);
24271
+ return parsePiModelCatalog(await registry2.getAvailable());
24272
+ }),
24273
+ new Promise((resolve3) => {
24274
+ timer = setTimeout(() => resolve3(undefined), PI_MODEL_PROBE_TIMEOUT_MS);
24275
+ timer.unref?.();
24276
+ })
24277
+ ]);
24278
+ return { status: "healthy", version: version3, reasoning };
24279
+ } catch {
24280
+ return { status: "healthy", version: version3, reasoning: undefined };
24281
+ } finally {
24282
+ if (timer)
24283
+ clearTimeout(timer);
24284
+ }
23964
24285
  }
23965
24286
  async openLane(ctx) {
23966
24287
  const deps = this.dependenciesFor(ctx);
@@ -25868,14 +26189,14 @@ function createLogger2(options = {}) {
25868
26189
  `));
25869
26190
  const err = options.err ?? ((line) => process.stderr.write(line + `
25870
26191
  `));
25871
- const record4 = options.record;
26192
+ const record5 = options.record;
25872
26193
  const emit = (level, message2, data) => {
25873
26194
  if (LEVEL_RANK[level] < minRank)
25874
26195
  return;
25875
26196
  const time3 = now();
25876
26197
  const line = `${time3} ${header} ${level.toUpperCase().padEnd(5)} ${message2}${formatData(data)}`;
25877
26198
  try {
25878
- record4?.({ time: time3, header, level, message: message2, fields: recordFields(data) });
26199
+ record5?.({ time: time3, header, level, message: message2, fields: recordFields(data) });
25879
26200
  } catch {}
25880
26201
  (level === "warn" || level === "error" ? err : out)(line);
25881
26202
  };
@@ -27019,20 +27340,20 @@ function parseLocalMessageReminderBody(body, agentId) {
27019
27340
  }
27020
27341
  if (!value || typeof value !== "object" || Array.isArray(value))
27021
27342
  return null;
27022
- const record4 = value;
27023
- if (Object.keys(record4).sort().join(",") !== "channel,remindAfterMs,sentSeq")
27343
+ const record5 = value;
27344
+ if (Object.keys(record5).sort().join(",") !== "channel,remindAfterMs,sentSeq")
27024
27345
  return null;
27025
- if (typeof record4.channel !== "string" || !isCanonicalChannelScope(record4.channel))
27346
+ if (typeof record5.channel !== "string" || !isCanonicalChannelScope(record5.channel))
27026
27347
  return null;
27027
- if (!Number.isSafeInteger(record4.sentSeq) || record4.sentSeq < 1)
27348
+ if (!Number.isSafeInteger(record5.sentSeq) || record5.sentSeq < 1)
27028
27349
  return null;
27029
- if (!Number.isSafeInteger(record4.remindAfterMs) || record4.remindAfterMs !== 0 && record4.remindAfterMs < LOCAL_MESSAGE_REMINDER_MIN_MS || record4.remindAfterMs > LOCAL_MESSAGE_REMINDER_MAX_MS)
27350
+ if (!Number.isSafeInteger(record5.remindAfterMs) || record5.remindAfterMs !== 0 && record5.remindAfterMs < LOCAL_MESSAGE_REMINDER_MIN_MS || record5.remindAfterMs > LOCAL_MESSAGE_REMINDER_MAX_MS)
27030
27351
  return null;
27031
27352
  return {
27032
27353
  agentId,
27033
- channel: record4.channel,
27034
- sentSeq: record4.sentSeq,
27035
- remindAfterMs: record4.remindAfterMs
27354
+ channel: record5.channel,
27355
+ sentSeq: record5.sentSeq,
27356
+ remindAfterMs: record5.remindAfterMs
27036
27357
  };
27037
27358
  }
27038
27359
  async function handleLocalMessageReminder(req, res, agentId, onArm) {
@@ -27378,13 +27699,13 @@ function reduceManager(state, event) {
27378
27699
  const existing = state.agents[event.agentId];
27379
27700
  if (!existing || existing.execution.sessionInstanceId !== event.sessionInstanceId)
27380
27701
  return { state, effects: [] };
27381
- const record4 = existing.pendingAdmissions.find((entry) => entry.sessionInstanceId === event.sessionInstanceId && entry.commandId === event.commandId);
27382
- if (!record4)
27702
+ const record5 = existing.pendingAdmissions.find((entry) => entry.sessionInstanceId === event.sessionInstanceId && entry.commandId === event.commandId);
27703
+ if (!record5)
27383
27704
  return { state, effects: [] };
27384
27705
  const agent2 = clone2(existing);
27385
27706
  agent2.pendingAdmissions = agent2.pendingAdmissions.filter((entry) => entry.sessionInstanceId !== event.sessionInstanceId || entry.commandId !== event.commandId);
27386
27707
  syncExecutionProjection(agent2);
27387
- return commit(state, agent2, event.outcome === "failed" ? recoveryEffects(agent2, [record4]) : []);
27708
+ return commit(state, agent2, event.outcome === "failed" ? recoveryEffects(agent2, [record5]) : []);
27388
27709
  }
27389
27710
  case "admission_acknowledged": {
27390
27711
  const existing = state.agents[event.agentId];
@@ -27902,11 +28223,11 @@ function syncExecutionProjection(agent2) {
27902
28223
  agent2.lastDeliverAt = agent2.pendingAdmissions.length > 0 ? Math.max(...agent2.pendingAdmissions.map((entry) => entry.admittedAt)) : null;
27903
28224
  }
27904
28225
  function recoveryEffects(agent2, records) {
27905
- return records.filter((record4) => record4.requeueOnFailure).map((record4) => ({
28226
+ return records.filter((record5) => record5.requeueOnFailure).map((record5) => ({
27906
28227
  type: "requeue_delivery",
27907
28228
  agentId: agent2.agentId,
27908
- message: record4.exactAgentMsg,
27909
- mode: record4.mode
28229
+ message: record5.exactAgentMsg,
28230
+ mode: record5.mode
27910
28231
  }));
27911
28232
  }
27912
28233
  function commit(state, agent2, effects) {
@@ -28052,8 +28373,8 @@ async function readClaudeQuota(options) {
28052
28373
  if (!body || typeof body !== "object") {
28053
28374
  return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
28054
28375
  }
28055
- const record4 = body;
28056
- const limits = ["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus"].map((key) => claudeLimit(key, record4[key])).filter((limit) => limit !== null);
28376
+ const record5 = body;
28377
+ const limits = ["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus"].map((key) => claudeLimit(key, record5[key])).filter((limit) => limit !== null);
28057
28378
  if (limits.length === 0) {
28058
28379
  return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
28059
28380
  }
@@ -30228,11 +30549,10 @@ class AgentRouter {
30228
30549
  return;
30229
30550
  if (existing.status === "healthy" && !existing.lastError && !existing.lastErrorAt)
30230
30551
  return;
30231
- this.runtimes.set(id, {
30232
- id: existing.id,
30233
- version: existing.version,
30234
- status: "healthy"
30235
- });
30552
+ const healthy = { ...existing, status: "healthy" };
30553
+ delete healthy.lastError;
30554
+ delete healthy.lastErrorAt;
30555
+ this.runtimes.set(id, healthy);
30236
30556
  this.log.info("runtime marked healthy again", { runtimeId: id });
30237
30557
  this.scheduleReadyFrameResend();
30238
30558
  }
@@ -31813,15 +32133,15 @@ class MessageReminderScheduler {
31813
32133
  const startedAt = this.now();
31814
32134
  const dueAt = startedAt + input.remindAfterMs;
31815
32135
  const sentRef = `${input.channel}#${input.sentSeq}`;
31816
- const record4 = {
32136
+ const record5 = {
31817
32137
  ...input,
31818
32138
  sentRef,
31819
32139
  startedAt,
31820
32140
  dueAt,
31821
32141
  timer: undefined
31822
32142
  };
31823
- record4.timer = this.setTimer(() => {
31824
- if (this.reminders.get(key) !== record4)
32143
+ record5.timer = this.setTimer(() => {
32144
+ if (this.reminders.get(key) !== record5)
31825
32145
  return;
31826
32146
  this.reminders.delete(key);
31827
32147
  try {
@@ -31832,8 +32152,8 @@ class MessageReminderScheduler {
31832
32152
  Promise.resolve(delivery).catch(() => {});
31833
32153
  } catch {}
31834
32154
  }, input.remindAfterMs);
31835
- record4.timer.unref?.();
31836
- this.reminders.set(key, record4);
32155
+ record5.timer.unref?.();
32156
+ this.reminders.set(key, record5);
31837
32157
  return { armed: true, dueAt };
31838
32158
  }
31839
32159
  observe(agentId, channel2, latestSeq) {
@@ -34128,11 +34448,11 @@ async function strictOutcome(response, allowed) {
34128
34448
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
34129
34449
  return { kind: "retryable" };
34130
34450
  }
34131
- const record4 = value;
34132
- if (Object.keys(record4).length !== 2 || record4.kind !== "terminal") {
34451
+ const record5 = value;
34452
+ if (Object.keys(record5).length !== 2 || record5.kind !== "terminal") {
34133
34453
  return { kind: "retryable" };
34134
34454
  }
34135
- const status = record4.status;
34455
+ const status = record5.status;
34136
34456
  if (status !== "uploaded" && status !== "failed" || allowed[status] !== response.status) {
34137
34457
  return { kind: "retryable" };
34138
34458
  }
@@ -34626,7 +34946,7 @@ function createDaemonProcessLogger(daemonDir, foreground) {
34626
34946
  `) : quiet,
34627
34947
  err: foreground ? (line2) => process.stderr.write(line2 + `
34628
34948
  `) : quiet,
34629
- record: (record4) => sink.write(JSON.stringify(record4))
34949
+ record: (record5) => sink.write(JSON.stringify(record5))
34630
34950
  });
34631
34951
  return { logger, logPath, sink };
34632
34952
  }
@@ -35369,18 +35689,18 @@ function readCredentialFile(filePath) {
35369
35689
  } catch {}
35370
35690
  return null;
35371
35691
  }
35372
- function writeCredentialFile(filePath, record4) {
35373
- writePrivateJsonAtomic2(filePath, record4);
35692
+ function writeCredentialFile(filePath, record5) {
35693
+ writePrivateJsonAtomic2(filePath, record5);
35374
35694
  }
35375
35695
  function readDaemonLaunchRecord(baseDir, machineId) {
35376
- const record4 = readCredentialFile(credentialFilePathByMachineId(baseDir, machineId));
35377
- if (!record4 || !("schemaVersion" in record4) || record4.schemaVersion !== 1 || !parseReleaseVersion(record4.daemonVersion)) {
35696
+ const record5 = readCredentialFile(credentialFilePathByMachineId(baseDir, machineId));
35697
+ if (!record5 || !("schemaVersion" in record5) || record5.schemaVersion !== 1 || !parseReleaseVersion(record5.daemonVersion)) {
35378
35698
  throw new Error("daemon launch record is missing or requires a manual start upgrade");
35379
35699
  }
35380
- validateMachineId(record4.machineId);
35381
- if (record4.machineId !== machineId)
35700
+ validateMachineId(record5.machineId);
35701
+ if (record5.machineId !== machineId)
35382
35702
  throw new Error("daemon launch record machine mismatch");
35383
- return record4;
35703
+ return record5;
35384
35704
  }
35385
35705
  function findExistingCredentialForBearer(baseDir, bearer) {
35386
35706
  const dir = daemonsDir(baseDir);
@@ -35545,23 +35865,23 @@ async function daemonResume(opts) {
35545
35865
  if (!/^[A-Za-z0-9_-]{16,128}$/.test(opts.requestId))
35546
35866
  throw new Error("invalid replacement request id");
35547
35867
  const baseDir = opts.baseDir || process.env.ALOOK_DATA_DIR || DEFAULT_BASE_DIR;
35548
- const record4 = readDaemonLaunchRecord(baseDir, opts.id);
35868
+ const record5 = readDaemonLaunchRecord(baseDir, opts.id);
35549
35869
  if (false) {}
35550
35870
  await daemonStart({
35551
- machineKey: record4.credential,
35552
- serverUrl: record4.serverUrl,
35553
- wsUrl: record4.wsUrl,
35871
+ machineKey: record5.credential,
35872
+ serverUrl: record5.serverUrl,
35873
+ wsUrl: record5.wsUrl,
35554
35874
  baseDir,
35555
35875
  resumeRequestId: opts.requestId
35556
35876
  });
35557
35877
  }
35558
35878
  async function daemonStartById(opts) {
35559
35879
  const baseDir = opts.baseDir || process.env.ALOOK_DATA_DIR || DEFAULT_BASE_DIR;
35560
- const record4 = readDaemonLaunchRecord(baseDir, opts.id);
35880
+ const record5 = readDaemonLaunchRecord(baseDir, opts.id);
35561
35881
  await daemonStart({
35562
- machineKey: record4.credential,
35563
- serverUrl: record4.serverUrl,
35564
- wsUrl: record4.wsUrl,
35882
+ machineKey: record5.credential,
35883
+ serverUrl: record5.serverUrl,
35884
+ wsUrl: record5.wsUrl,
35565
35885
  baseDir,
35566
35886
  foreground: opts.foreground
35567
35887
  });