@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/index.js CHANGED
@@ -942,8 +942,8 @@ function resolveLaunchFieldsOrDefault(input) {
942
942
  const envVars = Object.fromEntries(Object.entries(normalized.environment ?? {}).filter(([key]) => !controlled.has(key)));
943
943
  const providerEnv = {};
944
944
  const model = normalized.model.kind === "default" ? undefined : normalized.model.name;
945
- if (normalized.model.kind === "custom" && normalized.provider?.kind === "custom_endpoint") {
946
- providerEnv.ANTHROPIC_CUSTOM_MODEL_OPTION = normalized.model.name;
945
+ if (model && normalized.provider?.kind === "custom_endpoint") {
946
+ providerEnv.ANTHROPIC_CUSTOM_MODEL_OPTION = model;
947
947
  }
948
948
  if (normalized.provider?.kind === "custom_endpoint") {
949
949
  providerEnv.ANTHROPIC_BASE_URL = normalized.provider.apiUrl;
@@ -1278,6 +1278,7 @@ import { execFileSync as execFileSync2 } from "child_process";
1278
1278
  import * as fs4 from "fs";
1279
1279
  import * as path4 from "path";
1280
1280
  var PROBE_TIMEOUT_MS = 5000;
1281
+ var PROBE_OUTPUT_MAX_BYTES = 1024 * 1024;
1281
1282
  function resolveCommandOnPath(command, deps = {}) {
1282
1283
  if (deps.which)
1283
1284
  return deps.which(command);
@@ -1328,6 +1329,23 @@ function probeCommandVersion(command, args = [], deps = {}, platform = process.p
1328
1329
  return { ok: false, error: String(code) };
1329
1330
  }
1330
1331
  }
1332
+ function probeCommandOutput(command, args, platform = process.platform) {
1333
+ try {
1334
+ const output = execFileSync2(command, args, {
1335
+ encoding: "utf8",
1336
+ timeout: PROBE_TIMEOUT_MS,
1337
+ maxBuffer: PROBE_OUTPUT_MAX_BYTES,
1338
+ shell: needsWindowsShimShell(command, platform),
1339
+ stdio: ["pipe", "pipe", "ignore"],
1340
+ input: "",
1341
+ env: { ...process.env, CI: "1" }
1342
+ });
1343
+ return { ok: true, output };
1344
+ } catch (err) {
1345
+ const code = err?.code ?? "command_probe_failed";
1346
+ return { ok: false, error: String(code) };
1347
+ }
1348
+ }
1331
1349
  function resolveHomePath(relativePath, deps = {}) {
1332
1350
  return path4.join(deps.homeDir || process.env.HOME || ".", relativePath);
1333
1351
  }
@@ -1434,6 +1452,14 @@ class ClaudeTurnProtocol {
1434
1452
  }
1435
1453
 
1436
1454
  // agent-driver/dist/adapters/claude/index.js
1455
+ var CLAUDE_MODEL_CATALOG = {
1456
+ updateMode: "unsupported",
1457
+ models: ["opus", "sonnet", "haiku"].map((id) => ({
1458
+ id,
1459
+ supportedReasoningEfforts: []
1460
+ }))
1461
+ };
1462
+
1437
1463
  class ClaudeDriver {
1438
1464
  id = "claude";
1439
1465
  instructionDelivery = { kind: "workspace_file", canonical: "AGENTS.md", aliases: ["CLAUDE.md"] };
@@ -1450,10 +1476,11 @@ class ClaudeDriver {
1450
1476
  }
1451
1477
  probe(command) {
1452
1478
  const explicit = command?.trim();
1453
- if (!explicit)
1454
- return probeClaude();
1455
- const result = probeCommandVersion(explicit);
1456
- return result.ok ? { status: "healthy", version: result.version } : { status: "unhealthy", lastError: result.error };
1479
+ const base = explicit ? (() => {
1480
+ const result = probeCommandVersion(explicit);
1481
+ return result.ok ? { status: "healthy", version: result.version } : { status: "unhealthy", lastError: result.error };
1482
+ })() : probeClaude();
1483
+ return base.status === "healthy" ? { ...base, reasoning: CLAUDE_MODEL_CATALOG } : base;
1457
1484
  }
1458
1485
  async openLane(ctx, options) {
1459
1486
  return createProcessLane(this, ctx, { onRawStdoutLine: options?.onRawStdoutLine });
@@ -2020,10 +2047,59 @@ function stableErrorCode(value, fallback) {
2020
2047
  return /^[A-Za-z0-9_.-]{1,100}$/.test(code) ? code : fallback;
2021
2048
  }
2022
2049
 
2050
+ // agent-driver/dist/internal/modelCatalog.js
2051
+ var RUNTIME_MODEL_CATALOG_MAX = 512;
2052
+ var RUNTIME_MODEL_ID_MAX = 100;
2053
+ function normalizeRuntimeModelId(value) {
2054
+ if (typeof value !== "string")
2055
+ return;
2056
+ const id = value.trim();
2057
+ if (!id || id.length > RUNTIME_MODEL_ID_MAX || /\s/.test(id))
2058
+ return;
2059
+ return id;
2060
+ }
2061
+ function catalogFromIds(ids) {
2062
+ const seen = new Set;
2063
+ const models = [];
2064
+ for (const rawId of ids) {
2065
+ const id = normalizeRuntimeModelId(rawId);
2066
+ if (!id || seen.has(id))
2067
+ continue;
2068
+ if (models.length >= RUNTIME_MODEL_CATALOG_MAX)
2069
+ return;
2070
+ seen.add(id);
2071
+ models.push({ id, supportedReasoningEfforts: [] });
2072
+ }
2073
+ if (models.length === 0)
2074
+ return;
2075
+ return { updateMode: "unsupported", models };
2076
+ }
2077
+ function parseOpenCodeModelCatalog(output) {
2078
+ const ids = output.split(/\r?\n/).flatMap((line) => {
2079
+ const id = normalizeRuntimeModelId(line);
2080
+ return id && /^[^/]+\/.+$/.test(id) ? [id] : [];
2081
+ });
2082
+ return catalogFromIds(ids);
2083
+ }
2084
+ function parsePiModelCatalog(values) {
2085
+ if (!Array.isArray(values))
2086
+ return;
2087
+ const ids = values.flatMap((value) => {
2088
+ if (!value || typeof value !== "object")
2089
+ return [];
2090
+ const model = value;
2091
+ const provider = normalizeRuntimeModelId(model.provider);
2092
+ const id = normalizeRuntimeModelId(model.id);
2093
+ return provider && id && !provider.includes("/") ? [`${provider}/${id}`] : [];
2094
+ });
2095
+ return catalogFromIds(ids);
2096
+ }
2097
+
2023
2098
  // agent-driver/dist/adapters/codex/index.js
2024
2099
  var SETTINGS_UPDATE_TIMEOUT_MS = 5000;
2025
2100
  var MODEL_LIST_TIMEOUT_MS = 5000;
2026
- var MODEL_LIST_MAX = 64;
2101
+ var MODEL_LIST_OUTPUT_MAX_BYTES = 1024 * 1024;
2102
+ var MODEL_LIST_MAX = RUNTIME_MODEL_CATALOG_MAX;
2027
2103
  var MODEL_EFFORT_MAX = 16;
2028
2104
  function isCodexMissingRolloutError(message) {
2029
2105
  return /\bno\s+rollout\s+found\b/i.test(message) || /\bmissing\s+rollout\b/i.test(message) || /\brollout\b.*\b(not found|missing)\b/i.test(message) || /\b(not found|missing)\b.*\brollout\b/i.test(message);
@@ -2099,11 +2175,13 @@ class CodexDriver {
2099
2175
  return new Promise((resolve2) => {
2100
2176
  let settled = false;
2101
2177
  let buffer = "";
2178
+ let outputBytes = 0;
2102
2179
  let nextId = 0;
2103
2180
  let initializeId = 0;
2104
2181
  let listId = 0;
2105
2182
  const models = [];
2106
2183
  const seenModels = new Set;
2184
+ let overflow = false;
2107
2185
  let defaultModelId;
2108
2186
  const finish = (catalog) => {
2109
2187
  if (settled)
@@ -2121,12 +2199,16 @@ class CodexDriver {
2121
2199
  `);
2122
2200
  };
2123
2201
  const consumeModel = (value) => {
2124
- if (!value || typeof value !== "object" || models.length >= MODEL_LIST_MAX)
2202
+ if (!value || typeof value !== "object")
2125
2203
  return;
2126
2204
  const model = value;
2127
- const id = typeof model.id === "string" ? model.id.trim() : "";
2128
- if (!id || id.length > 100 || seenModels.has(id))
2205
+ const id = normalizeRuntimeModelId(model.id);
2206
+ if (!id || seenModels.has(id))
2129
2207
  return;
2208
+ if (models.length >= MODEL_LIST_MAX) {
2209
+ overflow = true;
2210
+ return;
2211
+ }
2130
2212
  const rawOptions = Array.isArray(model.supportedReasoningEfforts) ? model.supportedReasoningEfforts : [];
2131
2213
  const seenEfforts = new Set;
2132
2214
  const supportedReasoningEfforts = rawOptions.flatMap((raw) => {
@@ -2170,9 +2252,15 @@ class CodexDriver {
2170
2252
  const result = message.result;
2171
2253
  for (const model of Array.isArray(result.data) ? result.data : [])
2172
2254
  consumeModel(model);
2255
+ if (overflow)
2256
+ return finish();
2173
2257
  const cursor = typeof result.nextCursor === "string" ? result.nextCursor : undefined;
2174
- if (cursor && models.length < MODEL_LIST_MAX)
2258
+ if (cursor && models.length >= MODEL_LIST_MAX)
2259
+ return finish();
2260
+ if (cursor)
2175
2261
  return requestModelPage(cursor);
2262
+ if (models.length === 0)
2263
+ return finish();
2176
2264
  finish({
2177
2265
  updateMode: "live_next_turn",
2178
2266
  ...defaultModelId ? { defaultModelId } : {},
@@ -2182,7 +2270,11 @@ class CodexDriver {
2182
2270
  const timer = setTimeout(() => finish(), MODEL_LIST_TIMEOUT_MS);
2183
2271
  timer.unref?.();
2184
2272
  proc.stdout?.on("data", (chunk) => {
2185
- buffer += chunk.toString();
2273
+ const text = chunk.toString();
2274
+ outputBytes += Buffer.byteLength(text);
2275
+ if (outputBytes > MODEL_LIST_OUTPUT_MAX_BYTES)
2276
+ return finish();
2277
+ buffer += text;
2186
2278
  const lines = buffer.split(`
2187
2279
  `);
2188
2280
  buffer = lines.pop() ?? "";
@@ -2385,9 +2477,189 @@ class CodexDriver {
2385
2477
 
2386
2478
  // agent-driver/dist/adapters/cursor/acp-lane.js
2387
2479
  import { EventEmitter as EventEmitter2 } from "node:events";
2480
+
2481
+ // agent-driver/dist/adapters/cursor/catalog-probe.js
2388
2482
  var ACP_PROTOCOL_VERSION = 1;
2389
- var HANDSHAKE_TIMEOUT_MS = 15000;
2390
2483
  var AUTH_METHOD_ID = "cursor_login";
2484
+ var CATALOG_PROBE_TIMEOUT_MS = 15000;
2485
+ var CATALOG_PROBE_OUTPUT_MAX_BYTES = 1024 * 1024;
2486
+ var MODEL_DISPLAY_NAME_MAX = 256;
2487
+ var MODEL_OPTION_NESTING_MAX = 16;
2488
+ function record(value) {
2489
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
2490
+ }
2491
+ function normalizeDisplayName(value) {
2492
+ if (typeof value !== "string")
2493
+ return;
2494
+ const displayName = value.trim();
2495
+ return displayName && displayName.length <= MODEL_DISPLAY_NAME_MAX ? displayName : undefined;
2496
+ }
2497
+ function flattenCursorAcpSelectOptions(value, depth = 0) {
2498
+ if (!Array.isArray(value) || depth > MODEL_OPTION_NESTING_MAX)
2499
+ return [];
2500
+ const options = [];
2501
+ for (const item of value) {
2502
+ if (Array.isArray(item)) {
2503
+ options.push(...flattenCursorAcpSelectOptions(item, depth + 1));
2504
+ continue;
2505
+ }
2506
+ const candidate = record(item);
2507
+ if (!candidate)
2508
+ continue;
2509
+ const exactValue = normalizeRuntimeModelId(candidate.value);
2510
+ if (exactValue) {
2511
+ const name = normalizeDisplayName(candidate.name);
2512
+ options.push({ value: exactValue, ...name ? { name } : {} });
2513
+ }
2514
+ if (Array.isArray(candidate.options)) {
2515
+ options.push(...flattenCursorAcpSelectOptions(candidate.options, depth + 1));
2516
+ }
2517
+ }
2518
+ return options;
2519
+ }
2520
+ function parseCursorAcpModelCatalog(session) {
2521
+ const payload = record(session);
2522
+ const configOptions = Array.isArray(payload?.configOptions) ? payload.configOptions : [];
2523
+ const modelConfig = configOptions.map(record).find((option) => option?.id === "model") ?? null;
2524
+ if (!modelConfig)
2525
+ return;
2526
+ const seen = new Set;
2527
+ const models = [];
2528
+ for (const option of flattenCursorAcpSelectOptions(modelConfig.options)) {
2529
+ if (option.value === "default[]" || seen.has(option.value))
2530
+ continue;
2531
+ if (models.length >= RUNTIME_MODEL_CATALOG_MAX)
2532
+ return;
2533
+ seen.add(option.value);
2534
+ models.push({
2535
+ id: option.value,
2536
+ ...option.name ? { displayName: option.name } : {},
2537
+ supportedReasoningEfforts: []
2538
+ });
2539
+ }
2540
+ return models.length > 0 ? { updateMode: "unsupported", models } : undefined;
2541
+ }
2542
+ async function cleanupProbeProcess(process2) {
2543
+ if (process2.pid) {
2544
+ await killProcessTree(process2.pid, { graceMs: 250 }).catch(() => {});
2545
+ return;
2546
+ }
2547
+ if (process2.exitCode === null && process2.signalCode === null)
2548
+ process2.kill("SIGTERM");
2549
+ }
2550
+ async function probeCursorAcpCatalog(command, options = {}) {
2551
+ const cwd = options.cwd ?? process.cwd();
2552
+ const spec = resolveSpawnSpec("cursor-agent", ["acp"], command);
2553
+ let processHandle;
2554
+ try {
2555
+ processHandle = (options.spawn ?? spawnAgentProcess)(spec.command, spec.args, {
2556
+ cwd,
2557
+ env: { ...process.env, CI: "1" },
2558
+ shell: spec.shell
2559
+ });
2560
+ } catch {
2561
+ return;
2562
+ }
2563
+ return new Promise((resolve2) => {
2564
+ let settled = false;
2565
+ let buffer = "";
2566
+ let outputBytes = 0;
2567
+ let requestId = 0;
2568
+ let expectedId = 0;
2569
+ let expectedMethod = "";
2570
+ const finish = (catalog) => {
2571
+ if (settled)
2572
+ return;
2573
+ settled = true;
2574
+ clearTimeout(timer);
2575
+ const cleanup = options.cleanup ?? cleanupProbeProcess;
2576
+ Promise.resolve().then(() => cleanup(processHandle)).catch(() => {}).finally(() => resolve2(catalog));
2577
+ };
2578
+ const request = (method, params) => {
2579
+ if (settled)
2580
+ return;
2581
+ const stdin = processHandle.stdin;
2582
+ if (!stdin || stdin.destroyed || stdin.writableEnded || stdin.writable === false)
2583
+ return finish();
2584
+ expectedId = ++requestId;
2585
+ expectedMethod = method;
2586
+ try {
2587
+ stdin.write(`${jsonRpcRequest(method, params, expectedId)}
2588
+ `);
2589
+ } catch {
2590
+ finish();
2591
+ }
2592
+ };
2593
+ const onLine = (line) => {
2594
+ const parsed = tryParseJsonLine(line);
2595
+ const message = record(parsed);
2596
+ if (!message)
2597
+ return finish();
2598
+ if (message.id !== expectedId)
2599
+ return;
2600
+ if (message.error !== undefined)
2601
+ return finish();
2602
+ if (!Object.prototype.hasOwnProperty.call(message, "result"))
2603
+ return finish();
2604
+ if (expectedMethod === "authenticate") {
2605
+ request("session/new", { cwd, mcpServers: [] });
2606
+ return;
2607
+ }
2608
+ const result = record(message.result);
2609
+ if (!result)
2610
+ return finish();
2611
+ if (expectedMethod === "initialize") {
2612
+ const authMethods = Array.isArray(result.authMethods) ? result.authMethods : [];
2613
+ if (result.protocolVersion !== ACP_PROTOCOL_VERSION || !authMethods.some((method) => record(method)?.id === AUTH_METHOD_ID))
2614
+ return finish();
2615
+ request("authenticate", { methodId: AUTH_METHOD_ID });
2616
+ return;
2617
+ }
2618
+ if (expectedMethod !== "session/new" || typeof result.sessionId !== "string" || !result.sessionId.trim())
2619
+ return finish();
2620
+ finish(parseCursorAcpModelCatalog(result));
2621
+ };
2622
+ const timer = setTimeout(() => finish(), options.timeoutMs ?? CATALOG_PROBE_TIMEOUT_MS);
2623
+ timer.unref?.();
2624
+ processHandle.stdout?.on("data", (chunk) => {
2625
+ if (settled)
2626
+ return;
2627
+ const text = chunk.toString();
2628
+ outputBytes += Buffer.byteLength(text);
2629
+ if (outputBytes > (options.outputMaxBytes ?? CATALOG_PROBE_OUTPUT_MAX_BYTES))
2630
+ return finish();
2631
+ buffer += text;
2632
+ const lines = buffer.split(`
2633
+ `);
2634
+ buffer = lines.pop() ?? "";
2635
+ for (const line of lines)
2636
+ if (line.trim())
2637
+ onLine(line);
2638
+ });
2639
+ processHandle.stderr?.on("data", (chunk) => {
2640
+ if (settled)
2641
+ return;
2642
+ outputBytes += Buffer.byteLength(chunk.toString());
2643
+ if (outputBytes > (options.outputMaxBytes ?? CATALOG_PROBE_OUTPUT_MAX_BYTES))
2644
+ finish();
2645
+ });
2646
+ processHandle.on("error", () => finish());
2647
+ processHandle.on("exit", () => finish());
2648
+ request("initialize", {
2649
+ protocolVersion: ACP_PROTOCOL_VERSION,
2650
+ clientCapabilities: {
2651
+ fs: { readTextFile: false, writeTextFile: false },
2652
+ terminal: false
2653
+ },
2654
+ clientInfo: { name: "alook-agent-driver-probe", version: "0.1.25" }
2655
+ });
2656
+ });
2657
+ }
2658
+
2659
+ // agent-driver/dist/adapters/cursor/acp-lane.js
2660
+ var ACP_PROTOCOL_VERSION2 = 1;
2661
+ var HANDSHAKE_TIMEOUT_MS = 15000;
2662
+ var AUTH_METHOD_ID2 = "cursor_login";
2391
2663
  var PROMPT_STOP_REASONS = new Set([
2392
2664
  "end_turn",
2393
2665
  "max_tokens",
@@ -2411,16 +2683,16 @@ class CursorAcpRpcError extends Error {
2411
2683
  this.code = code;
2412
2684
  }
2413
2685
  }
2414
- function record(value) {
2686
+ function record2(value) {
2415
2687
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
2416
2688
  }
2417
2689
  function safeLabel(value) {
2418
2690
  return typeof value === "string" && /^[a-z0-9_-]{1,64}$/i.test(value) ? value : "unknown";
2419
2691
  }
2420
2692
  function rpcErrorMessage(error) {
2421
- const payload = record(error);
2693
+ const payload = record2(error);
2422
2694
  const message = typeof payload?.message === "string" && payload.message.trim() ? payload.message : "Cursor ACP request failed";
2423
- const data = record(payload?.data);
2695
+ const data = record2(payload?.data);
2424
2696
  const detail = typeof data?.message === "string" && data.message.trim() ? data.message : undefined;
2425
2697
  return detail ? `${message}: ${detail}` : message;
2426
2698
  }
@@ -2428,26 +2700,6 @@ function isMissingSessionError(error) {
2428
2700
  const message = error instanceof Error ? error.message : String(error);
2429
2701
  return /\bsession\b.*\b(not found|missing|unknown|invalid)\b/i.test(message) || /\b(not found|missing|unknown|invalid)\b.*\bsession\b/i.test(message);
2430
2702
  }
2431
- function flattenSelectOptions(value) {
2432
- if (!Array.isArray(value))
2433
- return [];
2434
- const out = [];
2435
- for (const item of value) {
2436
- if (Array.isArray(item)) {
2437
- out.push(...flattenSelectOptions(item));
2438
- continue;
2439
- }
2440
- const candidate = record(item);
2441
- if (!candidate)
2442
- continue;
2443
- if (typeof candidate.value === "string") {
2444
- out.push({ value: candidate.value, ...typeof candidate.name === "string" ? { name: candidate.name } : {} });
2445
- }
2446
- if (Array.isArray(candidate.options))
2447
- out.push(...flattenSelectOptions(candidate.options));
2448
- }
2449
- return out;
2450
- }
2451
2703
 
2452
2704
  class CursorAcpLane {
2453
2705
  factory;
@@ -2571,30 +2823,30 @@ class CursorAcpLane {
2571
2823
  }
2572
2824
  }
2573
2825
  async handshake(ctx) {
2574
- const initialize = record(await this.call("initialize", {
2575
- protocolVersion: ACP_PROTOCOL_VERSION,
2826
+ const initialize = record2(await this.call("initialize", {
2827
+ protocolVersion: ACP_PROTOCOL_VERSION2,
2576
2828
  clientCapabilities: {
2577
2829
  fs: { readTextFile: false, writeTextFile: false },
2578
2830
  terminal: false
2579
2831
  },
2580
2832
  clientInfo: { name: "alook-agent-driver", version: "0.1.14" }
2581
2833
  }));
2582
- if (initialize?.protocolVersion !== ACP_PROTOCOL_VERSION) {
2834
+ if (initialize?.protocolVersion !== ACP_PROTOCOL_VERSION2) {
2583
2835
  throw new CursorAcpIncompatibleError("Installed Cursor ACP does not support protocol version 1");
2584
2836
  }
2585
- const capabilities = record(initialize.agentCapabilities);
2837
+ const capabilities = record2(initialize.agentCapabilities);
2586
2838
  if (capabilities?.loadSession !== true) {
2587
2839
  throw new CursorAcpIncompatibleError("Installed Cursor ACP does not support persistent session loading");
2588
2840
  }
2589
2841
  const authMethods = Array.isArray(initialize.authMethods) ? initialize.authMethods : [];
2590
- if (!authMethods.some((method) => record(method)?.id === AUTH_METHOD_ID)) {
2842
+ if (!authMethods.some((method) => record2(method)?.id === AUTH_METHOD_ID2)) {
2591
2843
  throw new CursorAcpIncompatibleError("Installed Cursor ACP does not expose Cursor login authentication");
2592
2844
  }
2593
- await this.call("authenticate", { methodId: AUTH_METHOD_ID });
2845
+ await this.call("authenticate", { methodId: AUTH_METHOD_ID2 });
2594
2846
  let session;
2595
2847
  if (ctx.config.sessionId) {
2596
2848
  try {
2597
- session = record(await this.call("session/load", {
2849
+ session = record2(await this.call("session/load", {
2598
2850
  sessionId: ctx.config.sessionId,
2599
2851
  cwd: ctx.workingDirectory,
2600
2852
  mcpServers: []
@@ -2606,15 +2858,25 @@ class CursorAcpLane {
2606
2858
  throw error;
2607
2859
  }
2608
2860
  } else {
2609
- session = record(await this.call("session/new", { cwd: ctx.workingDirectory, mcpServers: [] }));
2861
+ session = record2(await this.call("session/new", { cwd: ctx.workingDirectory, mcpServers: [] }));
2610
2862
  }
2611
- if (!session || typeof session.sessionId !== "string" || !session.sessionId.trim()) {
2863
+ if (!session)
2864
+ throw new Error("Cursor ACP did not return a valid session response");
2865
+ const returnedSessionId = session.sessionId;
2866
+ if (returnedSessionId !== undefined && (typeof returnedSessionId !== "string" || !returnedSessionId.trim())) {
2612
2867
  throw new Error("Cursor ACP did not return a valid session id");
2613
2868
  }
2614
- if (ctx.config.sessionId && session.sessionId !== ctx.config.sessionId) {
2615
- throw new CursorAcpResetRequiredError("Cursor ACP loaded a different session; reset this agent before continuing");
2869
+ if (ctx.config.sessionId) {
2870
+ if (returnedSessionId !== undefined && returnedSessionId !== ctx.config.sessionId) {
2871
+ throw new CursorAcpResetRequiredError("Cursor ACP loaded a different session; reset this agent before continuing");
2872
+ }
2873
+ this.sessionId = ctx.config.sessionId;
2874
+ } else {
2875
+ if (typeof returnedSessionId !== "string") {
2876
+ throw new Error("Cursor ACP did not return a valid session id");
2877
+ }
2878
+ this.sessionId = returnedSessionId;
2616
2879
  }
2617
- this.sessionId = session.sessionId;
2618
2880
  await this.configureModel(session, ctx);
2619
2881
  }
2620
2882
  async configureModel(session, ctx) {
@@ -2622,24 +2884,30 @@ class CursorAcpLane {
2622
2884
  if (!requestedModel)
2623
2885
  return;
2624
2886
  const configOptions = Array.isArray(session.configOptions) ? session.configOptions : [];
2625
- const modelConfig = configOptions.map(record).find((option) => option?.id === "model") ?? null;
2887
+ const modelConfig = configOptions.map(record2).find((option) => option?.id === "model") ?? null;
2626
2888
  if (!modelConfig) {
2627
2889
  throw new CursorAcpIncompatibleError("Installed Cursor ACP does not support model configuration");
2628
2890
  }
2629
- const options = flattenSelectOptions(modelConfig.options);
2630
- const match = options.find((option) => option.value === requestedModel) ?? options.find((option) => option.name === requestedModel);
2891
+ const options = flattenCursorAcpSelectOptions(modelConfig.options);
2892
+ const match = options.find((option) => option.value === requestedModel);
2631
2893
  if (!match) {
2632
2894
  throw new CursorAcpIncompatibleError(`Configured Cursor model is unavailable through ACP: ${requestedModel}`);
2633
2895
  }
2896
+ let response;
2634
2897
  try {
2635
- await this.call("session/set_config_option", {
2898
+ response = record2(await this.call("session/set_config_option", {
2636
2899
  sessionId: this.sessionId,
2637
2900
  configId: "model",
2638
2901
  value: match.value
2639
- });
2902
+ }));
2640
2903
  } catch {
2641
2904
  throw new CursorAcpIncompatibleError("Installed Cursor ACP rejected model configuration");
2642
2905
  }
2906
+ const confirmedOptions = Array.isArray(response?.configOptions) ? response.configOptions : [];
2907
+ const confirmedModel = confirmedOptions.map(record2).find((option) => option?.id === "model") ?? null;
2908
+ if (confirmedModel?.currentValue !== match.value) {
2909
+ throw new CursorAcpIncompatibleError("Cursor ACP did not confirm the exact configured model");
2910
+ }
2643
2911
  }
2644
2912
  admitPrompt(text) {
2645
2913
  if (!this.sessionId)
@@ -2675,7 +2943,7 @@ class CursorAcpLane {
2675
2943
  completePrompt(active, value) {
2676
2944
  if (this.activePrompt?.requestId !== active.requestId)
2677
2945
  return;
2678
- const result = record(value);
2946
+ const result = record2(value);
2679
2947
  if (!result || typeof result.stopReason !== "string" || !PROMPT_STOP_REASONS.has(result.stopReason)) {
2680
2948
  this.failPrompt(active, new Error("Cursor ACP prompt response did not contain a supported stopReason"));
2681
2949
  return;
@@ -2817,7 +3085,7 @@ class CursorAcpLane {
2817
3085
  });
2818
3086
  }
2819
3087
  handleMessage(value) {
2820
- const message = record(value);
3088
+ const message = record2(value);
2821
3089
  if (!message || message.jsonrpc !== "2.0") {
2822
3090
  this.protocolFailure("Cursor ACP emitted an invalid JSON-RPC message");
2823
3091
  return;
@@ -2845,7 +3113,7 @@ class CursorAcpLane {
2845
3113
  if (pending.kind === "prompt") {
2846
3114
  this.pending.delete(id);
2847
3115
  if (message.error !== undefined) {
2848
- const payload = record(message.error);
3116
+ const payload = record2(message.error);
2849
3117
  this.failPrompt(pending.active, new CursorAcpRpcError(pending.method, typeof payload?.code === "number" ? payload.code : undefined, rpcErrorMessage(message.error)));
2850
3118
  } else if (!("result" in message)) {
2851
3119
  this.failPrompt(pending.active, new Error("Cursor ACP response omitted result"));
@@ -2855,7 +3123,7 @@ class CursorAcpLane {
2855
3123
  return;
2856
3124
  }
2857
3125
  if (message.error !== undefined) {
2858
- const payload = record(message.error);
3126
+ const payload = record2(message.error);
2859
3127
  this.settleRequest(id, false, new CursorAcpRpcError(pending.method, typeof payload?.code === "number" ? payload.code : undefined, rpcErrorMessage(message.error)));
2860
3128
  return;
2861
3129
  }
@@ -2887,9 +3155,9 @@ class CursorAcpLane {
2887
3155
  this.diagnostic("warning", `Unsupported Cursor ACP client request: ${safeLabel(method)}`);
2888
3156
  return;
2889
3157
  }
2890
- const payload = record(params);
3158
+ const payload = record2(params);
2891
3159
  const sameSession = payload?.sessionId === this.sessionId;
2892
- const options = Array.isArray(payload?.options) ? payload.options.map(record).filter(Boolean) : [];
3160
+ const options = Array.isArray(payload?.options) ? payload.options.map(record2).filter(Boolean) : [];
2893
3161
  const allowOnce = options.find((option) => option.kind === "allow_once" && typeof option.optionId === "string" && option.optionId.trim().length > 0);
2894
3162
  if (!this.ready || !this.activePrompt || !sameSession || !allowOnce) {
2895
3163
  this.write({ jsonrpc: "2.0", id, result: { outcome: { outcome: "cancelled" } } });
@@ -2910,7 +3178,7 @@ class CursorAcpLane {
2910
3178
  this.diagnostic("warning", `Unsupported Cursor ACP notification: ${safeLabel(method)}`);
2911
3179
  }
2912
3180
  handleSessionUpdate(params) {
2913
- const payload = record(params);
3181
+ const payload = record2(params);
2914
3182
  if (!payload || payload.sessionId !== this.sessionId) {
2915
3183
  this.diagnostic("warning", "Cursor ACP emitted an update for a different session");
2916
3184
  return;
@@ -2919,18 +3187,18 @@ class CursorAcpLane {
2919
3187
  this.diagnostic("warning", "Cursor ACP emitted a session update without an active prompt");
2920
3188
  return;
2921
3189
  }
2922
- const update = record(payload.update) ?? {};
3190
+ const update = record2(payload.update) ?? {};
2923
3191
  const updateType = update?.sessionUpdate;
2924
3192
  switch (updateType) {
2925
3193
  case "agent_message_chunk": {
2926
- const content = record(update.content);
3194
+ const content = record2(update.content);
2927
3195
  if (content?.type === "text" && typeof content.text === "string") {
2928
3196
  this.events.emit("runtime_event", { kind: "assistant_message_delta", text: content.text });
2929
3197
  }
2930
3198
  return;
2931
3199
  }
2932
3200
  case "agent_thought_chunk": {
2933
- const content = record(update.content);
3201
+ const content = record2(update.content);
2934
3202
  if (content?.type === "text" && typeof content.text === "string") {
2935
3203
  this.events.emit("runtime_event", { kind: "assistant_reasoning_delta", text: content.text });
2936
3204
  }
@@ -3002,6 +3270,7 @@ class CursorAcpLane {
3002
3270
 
3003
3271
  // agent-driver/dist/adapters/cursor/index.js
3004
3272
  class CursorDriver {
3273
+ catalogProbe;
3005
3274
  id = "cursor";
3006
3275
  instructionDelivery = { kind: "workspace_file", canonical: "AGENTS.md", aliases: ["CLAUDE.md"] };
3007
3276
  execution = {
@@ -3010,8 +3279,23 @@ class CursorDriver {
3010
3279
  wakeStart: "immediate",
3011
3280
  terminalOwnership: "transport_request"
3012
3281
  };
3013
- probe(command) {
3014
- return probeCliRuntime("cursor-agent", {}, command);
3282
+ constructor(catalogProbe = probeCursorAcpCatalog) {
3283
+ this.catalogProbe = catalogProbe;
3284
+ }
3285
+ async probe(command) {
3286
+ const result = probeCliRuntime("cursor-agent", {}, command);
3287
+ if (result.status !== "healthy")
3288
+ return result;
3289
+ let reasoning;
3290
+ try {
3291
+ reasoning = await this.catalogProbe(command);
3292
+ } catch {
3293
+ reasoning = undefined;
3294
+ }
3295
+ return {
3296
+ ...result,
3297
+ reasoning
3298
+ };
3015
3299
  }
3016
3300
  async openLane(ctx, options) {
3017
3301
  return new CursorAcpLane(this, ctx, { onRawStdoutLine: options?.onRawStdoutLine });
@@ -3068,7 +3352,7 @@ class OpenCodeHttpError extends Error {
3068
3352
  this.status = status;
3069
3353
  }
3070
3354
  }
3071
- function record2(value) {
3355
+ function record3(value) {
3072
3356
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
3073
3357
  }
3074
3358
  function safeLabel2(value) {
@@ -3115,7 +3399,7 @@ function parseModelRef(model) {
3115
3399
  return { providerID: model.slice(0, slash), id: model.slice(slash + 1) };
3116
3400
  }
3117
3401
  function messageFromError(value) {
3118
- const payload = record2(value);
3402
+ const payload = record3(value);
3119
3403
  const message = typeof payload?.message === "string" && payload.message.trim() ? payload.message : undefined;
3120
3404
  return message ? "OpenCode turn failed" : "OpenCode reported an inconsistent turn outcome";
3121
3405
  }
@@ -3449,7 +3733,7 @@ class OpenCodeServiceLane {
3449
3733
  const healthTimeoutMs = Math.max(1, Math.min(1000, deadline - Date.now(), this.options.requestTimeoutMs ?? REQUEST_TIMEOUT_MS));
3450
3734
  const { response, body } = await this.fetchJsonWithTimeout("/global/health", { method: "GET" }, "health", healthTimeoutMs);
3451
3735
  if (response.ok) {
3452
- const health = record2(body);
3736
+ const health = record3(body);
3453
3737
  if (health?.healthy !== true || health.version !== SUPPORTED_VERSION) {
3454
3738
  throw new OpenCodeIncompatibleError(`Installed OpenCode service must be version ${SUPPORTED_VERSION}`);
3455
3739
  }
@@ -3470,8 +3754,8 @@ class OpenCodeServiceLane {
3470
3754
  const { response, body } = await this.fetchJsonWithTimeout("/doc", { method: "GET" }, "OpenAPI");
3471
3755
  if (!response.ok)
3472
3756
  throw new OpenCodeIncompatibleError("Installed OpenCode service does not expose its OpenAPI document");
3473
- const document = record2(body);
3474
- const paths = record2(document?.paths);
3757
+ const document = record3(body);
3758
+ const paths = record3(document?.paths);
3475
3759
  const required = [
3476
3760
  "/api/session",
3477
3761
  "/api/session/active",
@@ -3484,7 +3768,7 @@ class OpenCodeServiceLane {
3484
3768
  "/api/session/{sessionID}/permission/{requestID}/reply",
3485
3769
  "/api/event"
3486
3770
  ];
3487
- if (!paths || required.some((path6) => !record2(paths[path6]))) {
3771
+ if (!paths || required.some((path6) => !record3(paths[path6]))) {
3488
3772
  throw new OpenCodeIncompatibleError("Installed OpenCode service is missing required v2 session capabilities");
3489
3773
  }
3490
3774
  }
@@ -3497,7 +3781,7 @@ class OpenCodeServiceLane {
3497
3781
  }
3498
3782
  if (!response2.ok)
3499
3783
  throw new OpenCodeHttpError(response2.status, "session resume");
3500
- const session2 = record2(record2(body2)?.data);
3784
+ const session2 = record3(record3(body2)?.data);
3501
3785
  if (session2?.id !== resumeId) {
3502
3786
  throw new OpenCodeResetRequiredError("OpenCode v2 returned a different resumed session; reset this agent before continuing");
3503
3787
  }
@@ -3518,8 +3802,8 @@ class OpenCodeServiceLane {
3518
3802
  }, "session create");
3519
3803
  if (!response.ok)
3520
3804
  throw new OpenCodeHttpError(response.status, "session create");
3521
- const payload = record2(responseBody);
3522
- const session = record2(payload?.data);
3805
+ const payload = record3(responseBody);
3806
+ const session = record3(payload?.data);
3523
3807
  if (typeof session?.id !== "string" || !/^ses/.test(session.id)) {
3524
3808
  throw new Error("OpenCode v2 did not return a valid session id");
3525
3809
  }
@@ -3676,7 +3960,7 @@ class OpenCodeServiceLane {
3676
3960
  const { response, body: responseBody } = await this.fetchJsonWithTimeout(`/api/session/${encodeURIComponent(this.sessionId)}/history?after=${historyCursor}&limit=${HISTORY_PAGE_LIMIT}`, { method: "GET" }, "session history");
3677
3961
  if (!response.ok)
3678
3962
  throw new OpenCodeHttpError(response.status, "session history");
3679
- const body = record2(responseBody);
3963
+ const body = record3(responseBody);
3680
3964
  if (!Array.isArray(body?.data) || typeof body.hasMore !== "boolean") {
3681
3965
  throw new OpenCodeProtocolError("OpenCode session history returned an invalid page");
3682
3966
  }
@@ -3694,9 +3978,9 @@ class OpenCodeServiceLane {
3694
3978
  return run;
3695
3979
  }
3696
3980
  async handleDurableEvent(value, project) {
3697
- const event = record2(value);
3698
- const durable = record2(event?.durable);
3699
- const data = record2(event?.data);
3981
+ const event = record3(value);
3982
+ const durable = record3(event?.durable);
3983
+ const data = record3(event?.data);
3700
3984
  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) {
3701
3985
  throw new OpenCodeProtocolError("OpenCode session stream emitted an invalid durable event");
3702
3986
  }
@@ -3786,9 +4070,9 @@ class OpenCodeServiceLane {
3786
4070
  ...!successful ? { message: "OpenCode reported an unsupported final step outcome" } : {}
3787
4071
  });
3788
4072
  }
3789
- const tokens = record2(data.tokens);
4073
+ const tokens = record3(data.tokens);
3790
4074
  if (tokens && data.finish !== "tool-calls") {
3791
- const cache = record2(tokens.cache);
4075
+ const cache = record3(tokens.cache);
3792
4076
  const metric2 = (value2) => typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= 0 ? value2 : null;
3793
4077
  const cacheParts = [cache?.read, cache?.write].filter((value2) => typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= 0);
3794
4078
  const cacheTotal = cacheParts.reduce((sum, value2) => sum + value2, 0);
@@ -3815,8 +4099,8 @@ class OpenCodeServiceLane {
3815
4099
  return seq;
3816
4100
  }
3817
4101
  async handleLiveEvent(value) {
3818
- const event = record2(value);
3819
- const data = record2(event?.data);
4102
+ const event = record3(value);
4103
+ const data = record3(event?.data);
3820
4104
  if (event?.type !== "permission.v2.asked" || data?.sessionID !== this.sessionId)
3821
4105
  return;
3822
4106
  if (typeof data.id !== "string" || !/^per/.test(data.id)) {
@@ -3830,11 +4114,11 @@ class OpenCodeServiceLane {
3830
4114
  const { response, body: responseBody } = await this.fetchJsonWithTimeout(`/api/session/${encodeURIComponent(this.sessionId)}/permission`, { method: "GET" }, "permission list");
3831
4115
  if (!response.ok)
3832
4116
  throw new OpenCodeHttpError(response.status, "permission list");
3833
- const body = record2(responseBody);
4117
+ const body = record3(responseBody);
3834
4118
  if (!Array.isArray(body?.data))
3835
4119
  throw new OpenCodeProtocolError("OpenCode permission list returned invalid data");
3836
4120
  for (const item of body.data) {
3837
- const permission = record2(item);
4121
+ const permission = record3(item);
3838
4122
  if (permission?.sessionID === this.sessionId && typeof permission.id === "string") {
3839
4123
  await this.replyPermission(permission.id);
3840
4124
  }
@@ -3901,8 +4185,8 @@ class OpenCodeServiceLane {
3901
4185
  }, "prompt admission");
3902
4186
  if (!response.ok)
3903
4187
  throw new OpenCodeHttpError(response.status, "prompt admission");
3904
- const body = record2(responseBody);
3905
- const admitted = record2(body?.data);
4188
+ const body = record3(responseBody);
4189
+ const admitted = record3(body?.data);
3906
4190
  if (admitted?.id !== messageId || admitted.sessionID !== this.sessionId || admitted.delivery !== delivery || !Number.isInteger(admitted.admittedSeq) || Number(admitted.admittedSeq) < 0) {
3907
4191
  throw new OpenCodeProtocolError("OpenCode prompt admission returned an invalid receipt");
3908
4192
  }
@@ -3969,8 +4253,8 @@ class OpenCodeServiceLane {
3969
4253
  const { response, body: responseBody } = await this.fetchJsonWithTimeout("/api/session/active", { method: "GET" }, "active session query");
3970
4254
  if (!response.ok)
3971
4255
  throw new OpenCodeHttpError(response.status, "active session query");
3972
- const body = record2(responseBody);
3973
- const active = record2(body?.data);
4256
+ const body = record3(responseBody);
4257
+ const active = record3(body?.data);
3974
4258
  if (!active)
3975
4259
  throw new OpenCodeProtocolError("OpenCode active session query returned invalid data");
3976
4260
  if (!this.barrierStillCurrent(root, identity, generation))
@@ -4175,6 +4459,7 @@ function createOpenCodeMessageId() {
4175
4459
  }
4176
4460
 
4177
4461
  class OpenCodeDriver {
4462
+ outputProbe;
4178
4463
  id = "opencode";
4179
4464
  instructionDelivery = { kind: "workspace_file", canonical: "AGENTS.md", aliases: ["CLAUDE.md"] };
4180
4465
  execution = {
@@ -4183,8 +4468,19 @@ class OpenCodeDriver {
4183
4468
  wakeStart: "immediate",
4184
4469
  terminalOwnership: "transport_request"
4185
4470
  };
4471
+ constructor(outputProbe = probeCommandOutput) {
4472
+ this.outputProbe = outputProbe;
4473
+ }
4186
4474
  probe(command) {
4187
- return probeCliRuntime("opencode", {}, command);
4475
+ const result = probeCliRuntime("opencode", {}, command);
4476
+ if (result.status !== "healthy")
4477
+ return result;
4478
+ const spec = resolveSpawnSpec("opencode", ["models", "--pure"], command);
4479
+ const output = this.outputProbe(spec.command, spec.args);
4480
+ return {
4481
+ ...result,
4482
+ reasoning: output.ok ? parseOpenCodeModelCatalog(output.output) : undefined
4483
+ };
4188
4484
  }
4189
4485
  beginTurn() {
4190
4486
  return createOpenCodeMessageId();
@@ -4438,6 +4734,7 @@ function createPiSessionDependencies(ctx, loadSdk = loadPiSdkModule) {
4438
4734
 
4439
4735
  // agent-driver/dist/adapters/pi/index.js
4440
4736
  var PI_SDK_PACKAGE_NAME2 = "@earendil-works/pi-coding-agent";
4737
+ var PI_MODEL_PROBE_TIMEOUT_MS = 5000;
4441
4738
  function isPiSdkPackageJson(pkgJsonPath) {
4442
4739
  if (!existsSync3(pkgJsonPath))
4443
4740
  return false;
@@ -4546,6 +4843,8 @@ function mapPiSdkEvent(event, sessionId, state) {
4546
4843
 
4547
4844
  class PiDriver {
4548
4845
  dependenciesFor;
4846
+ loadSdk;
4847
+ readVersion;
4549
4848
  id = "pi";
4550
4849
  instructionDelivery = { kind: "workspace_file", canonical: "AGENTS.md", aliases: ["CLAUDE.md"] };
4551
4850
  execution = {
@@ -4556,15 +4855,36 @@ class PiDriver {
4556
4855
  };
4557
4856
  sessionId = null;
4558
4857
  terminalSequence = 0;
4559
- constructor(dependenciesFor = createPiSessionDependencies) {
4858
+ constructor(dependenciesFor = createPiSessionDependencies, loadSdk = loadPiSdkModule, readVersion = readPiSdkVersion) {
4560
4859
  this.dependenciesFor = dependenciesFor;
4860
+ this.loadSdk = loadSdk;
4861
+ this.readVersion = readVersion;
4561
4862
  }
4562
- probe() {
4563
- const version = readPiSdkVersion();
4863
+ async probe() {
4864
+ const version = this.readVersion();
4564
4865
  if (!version) {
4565
4866
  return { status: "unhealthy", lastError: "sdk_not_installed" };
4566
4867
  }
4567
- return { status: "healthy", version };
4868
+ let timer;
4869
+ try {
4870
+ const reasoning = await Promise.race([
4871
+ this.loadSdk().then(async (sdk) => {
4872
+ const authStorage = sdk.AuthStorage.create();
4873
+ const registry = sdk.ModelRegistry.create(authStorage);
4874
+ return parsePiModelCatalog(await registry.getAvailable());
4875
+ }),
4876
+ new Promise((resolve3) => {
4877
+ timer = setTimeout(() => resolve3(undefined), PI_MODEL_PROBE_TIMEOUT_MS);
4878
+ timer.unref?.();
4879
+ })
4880
+ ]);
4881
+ return { status: "healthy", version, reasoning };
4882
+ } catch {
4883
+ return { status: "healthy", version, reasoning: undefined };
4884
+ } finally {
4885
+ if (timer)
4886
+ clearTimeout(timer);
4887
+ }
4568
4888
  }
4569
4889
  async openLane(ctx) {
4570
4890
  const deps = this.dependenciesFor(ctx);
@@ -6596,8 +6916,8 @@ async function readClaudeQuota(options) {
6596
6916
  if (!body || typeof body !== "object") {
6597
6917
  return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
6598
6918
  }
6599
- const record3 = body;
6600
- const limits = ["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus"].map((key) => claudeLimit(key, record3[key])).filter((limit) => limit !== null);
6919
+ const record4 = body;
6920
+ const limits = ["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus"].map((key) => claudeLimit(key, record4[key])).filter((limit) => limit !== null);
6601
6921
  if (limits.length === 0) {
6602
6922
  return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
6603
6923
  }
@@ -7254,10 +7574,10 @@ function stableNormalizeApmHeldFreshness(value) {
7254
7574
  return value.map((item) => stableNormalizeApmHeldFreshness(item));
7255
7575
  if (!value || typeof value !== "object")
7256
7576
  return value;
7257
- const record3 = value;
7577
+ const record4 = value;
7258
7578
  const normalized = {};
7259
- for (const key of Object.keys(record3).sort()) {
7260
- normalized[key] = stableNormalizeApmHeldFreshness(record3[key]);
7579
+ for (const key of Object.keys(record4).sort()) {
7580
+ normalized[key] = stableNormalizeApmHeldFreshness(record4[key]);
7261
7581
  }
7262
7582
  return normalized;
7263
7583
  }
@@ -7373,13 +7693,13 @@ function reduceManager(state, event) {
7373
7693
  const existing = state.agents[event.agentId];
7374
7694
  if (!existing || existing.execution.sessionInstanceId !== event.sessionInstanceId)
7375
7695
  return { state, effects: [] };
7376
- const record3 = existing.pendingAdmissions.find((entry) => entry.sessionInstanceId === event.sessionInstanceId && entry.commandId === event.commandId);
7377
- if (!record3)
7696
+ const record4 = existing.pendingAdmissions.find((entry) => entry.sessionInstanceId === event.sessionInstanceId && entry.commandId === event.commandId);
7697
+ if (!record4)
7378
7698
  return { state, effects: [] };
7379
7699
  const agent = clone(existing);
7380
7700
  agent.pendingAdmissions = agent.pendingAdmissions.filter((entry) => entry.sessionInstanceId !== event.sessionInstanceId || entry.commandId !== event.commandId);
7381
7701
  syncExecutionProjection(agent);
7382
- return commit(state, agent, event.outcome === "failed" ? recoveryEffects(agent, [record3]) : []);
7702
+ return commit(state, agent, event.outcome === "failed" ? recoveryEffects(agent, [record4]) : []);
7383
7703
  }
7384
7704
  case "admission_acknowledged": {
7385
7705
  const existing = state.agents[event.agentId];
@@ -7897,11 +8217,11 @@ function syncExecutionProjection(agent) {
7897
8217
  agent.lastDeliverAt = agent.pendingAdmissions.length > 0 ? Math.max(...agent.pendingAdmissions.map((entry) => entry.admittedAt)) : null;
7898
8218
  }
7899
8219
  function recoveryEffects(agent, records) {
7900
- return records.filter((record3) => record3.requeueOnFailure).map((record3) => ({
8220
+ return records.filter((record4) => record4.requeueOnFailure).map((record4) => ({
7901
8221
  type: "requeue_delivery",
7902
8222
  agentId: agent.agentId,
7903
- message: record3.exactAgentMsg,
7904
- mode: record3.mode
8223
+ message: record4.exactAgentMsg,
8224
+ mode: record4.mode
7905
8225
  }));
7906
8226
  }
7907
8227
  function commit(state, agent, effects) {
@@ -8312,14 +8632,14 @@ function createLogger(options = {}) {
8312
8632
  `));
8313
8633
  const err = options.err ?? ((line) => process.stderr.write(line + `
8314
8634
  `));
8315
- const record3 = options.record;
8635
+ const record4 = options.record;
8316
8636
  const emit = (level, message, data) => {
8317
8637
  if (LEVEL_RANK[level] < minRank)
8318
8638
  return;
8319
8639
  const time = now();
8320
8640
  const line = `${time} ${header} ${level.toUpperCase().padEnd(5)} ${message}${formatData(data)}`;
8321
8641
  try {
8322
- record3?.({ time, header, level, message, fields: recordFields(data) });
8642
+ record4?.({ time, header, level, message, fields: recordFields(data) });
8323
8643
  } catch {}
8324
8644
  (level === "warn" || level === "error" ? err : out)(line);
8325
8645
  };
@@ -10058,7 +10378,7 @@ __export(exports_external, {
10058
10378
  regexes: () => exports_regexes,
10059
10379
  regex: () => _regex,
10060
10380
  refine: () => refine,
10061
- record: () => record3,
10381
+ record: () => record4,
10062
10382
  readonly: () => readonly,
10063
10383
  property: () => _property,
10064
10384
  promise: () => promise,
@@ -22214,7 +22534,7 @@ __export(exports_schemas2, {
22214
22534
  strictObject: () => strictObject,
22215
22535
  set: () => set,
22216
22536
  refine: () => refine,
22217
- record: () => record3,
22537
+ record: () => record4,
22218
22538
  readonly: () => readonly,
22219
22539
  promise: () => promise,
22220
22540
  preprocess: () => preprocess,
@@ -23291,7 +23611,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
23291
23611
  inst.keyType = def.keyType;
23292
23612
  inst.valueType = def.valueType;
23293
23613
  });
23294
- function record3(keyType, valueType, params) {
23614
+ function record4(keyType, valueType, params) {
23295
23615
  if (!valueType || !valueType._zod) {
23296
23616
  return new ZodRecord({
23297
23617
  type: "record",
@@ -23756,7 +24076,7 @@ var stringbool = (...args) => _stringbool({
23756
24076
  }, ...args);
23757
24077
  function json(params) {
23758
24078
  const jsonSchema = lazy(() => {
23759
- return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema), record3(string2(), jsonSchema)]);
24079
+ return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema), record4(string2(), jsonSchema)]);
23760
24080
  });
23761
24081
  return jsonSchema;
23762
24082
  }
@@ -26955,11 +27275,10 @@ class AgentRouter {
26955
27275
  return;
26956
27276
  if (existing.status === "healthy" && !existing.lastError && !existing.lastErrorAt)
26957
27277
  return;
26958
- this.runtimes.set(id, {
26959
- id: existing.id,
26960
- version: existing.version,
26961
- status: "healthy"
26962
- });
27278
+ const healthy = { ...existing, status: "healthy" };
27279
+ delete healthy.lastError;
27280
+ delete healthy.lastErrorAt;
27281
+ this.runtimes.set(id, healthy);
26963
27282
  this.log.info("runtime marked healthy again", { runtimeId: id });
26964
27283
  this.scheduleReadyFrameResend();
26965
27284
  }
@@ -27379,20 +27698,20 @@ function parseLocalMessageReminderBody(body, agentId) {
27379
27698
  }
27380
27699
  if (!value || typeof value !== "object" || Array.isArray(value))
27381
27700
  return null;
27382
- const record4 = value;
27383
- if (Object.keys(record4).sort().join(",") !== "channel,remindAfterMs,sentSeq")
27701
+ const record5 = value;
27702
+ if (Object.keys(record5).sort().join(",") !== "channel,remindAfterMs,sentSeq")
27384
27703
  return null;
27385
- if (typeof record4.channel !== "string" || !isCanonicalChannelScope(record4.channel))
27704
+ if (typeof record5.channel !== "string" || !isCanonicalChannelScope(record5.channel))
27386
27705
  return null;
27387
- if (!Number.isSafeInteger(record4.sentSeq) || record4.sentSeq < 1)
27706
+ if (!Number.isSafeInteger(record5.sentSeq) || record5.sentSeq < 1)
27388
27707
  return null;
27389
- if (!Number.isSafeInteger(record4.remindAfterMs) || record4.remindAfterMs !== 0 && record4.remindAfterMs < LOCAL_MESSAGE_REMINDER_MIN_MS || record4.remindAfterMs > LOCAL_MESSAGE_REMINDER_MAX_MS)
27708
+ if (!Number.isSafeInteger(record5.remindAfterMs) || record5.remindAfterMs !== 0 && record5.remindAfterMs < LOCAL_MESSAGE_REMINDER_MIN_MS || record5.remindAfterMs > LOCAL_MESSAGE_REMINDER_MAX_MS)
27390
27709
  return null;
27391
27710
  return {
27392
27711
  agentId,
27393
- channel: record4.channel,
27394
- sentSeq: record4.sentSeq,
27395
- remindAfterMs: record4.remindAfterMs
27712
+ channel: record5.channel,
27713
+ sentSeq: record5.sentSeq,
27714
+ remindAfterMs: record5.remindAfterMs
27396
27715
  };
27397
27716
  }
27398
27717
  async function handleLocalMessageReminder(req, res, agentId, onArm) {
@@ -28529,7 +28848,7 @@ var REASONING_EFFORT_RE = /^[A-Za-z0-9._-]+$/;
28529
28848
  var COMMUNITY_REASONING_EFFORT_MAX = 32;
28530
28849
  var COMMUNITY_REASONING_DESCRIPTION_MAX = 256;
28531
28850
  var COMMUNITY_REASONING_OPTIONS_MAX = 16;
28532
- var COMMUNITY_REASONING_MODELS_MAX = 64;
28851
+ var COMMUNITY_REASONING_MODELS_MAX = 512;
28533
28852
  var ReasoningEffortSchema = exports_external.string().min(1).max(COMMUNITY_REASONING_EFFORT_MAX).regex(REASONING_EFFORT_RE, "invalid reasoning effort charset");
28534
28853
  var RuntimeReasoningOptionSchema = exports_external.object({
28535
28854
  value: ReasoningEffortSchema,
@@ -28537,6 +28856,7 @@ var RuntimeReasoningOptionSchema = exports_external.object({
28537
28856
  });
28538
28857
  var RuntimeReasoningModelSchema = exports_external.object({
28539
28858
  id: exports_external.string().min(1).max(100),
28859
+ displayName: exports_external.string().min(1).max(COMMUNITY_REASONING_DESCRIPTION_MAX).optional().catch(undefined),
28540
28860
  supportedReasoningEfforts: exports_external.array(exports_external.unknown()).max(COMMUNITY_REASONING_OPTIONS_MAX).transform((options) => {
28541
28861
  const seen = new Set;
28542
28862
  return options.flatMap((candidate) => {
@@ -32111,15 +32431,15 @@ class MessageReminderScheduler {
32111
32431
  const startedAt = this.now();
32112
32432
  const dueAt = startedAt + input.remindAfterMs;
32113
32433
  const sentRef = `${input.channel}#${input.sentSeq}`;
32114
- const record4 = {
32434
+ const record5 = {
32115
32435
  ...input,
32116
32436
  sentRef,
32117
32437
  startedAt,
32118
32438
  dueAt,
32119
32439
  timer: undefined
32120
32440
  };
32121
- record4.timer = this.setTimer(() => {
32122
- if (this.reminders.get(key) !== record4)
32441
+ record5.timer = this.setTimer(() => {
32442
+ if (this.reminders.get(key) !== record5)
32123
32443
  return;
32124
32444
  this.reminders.delete(key);
32125
32445
  try {
@@ -32130,8 +32450,8 @@ class MessageReminderScheduler {
32130
32450
  Promise.resolve(delivery).catch(() => {});
32131
32451
  } catch {}
32132
32452
  }, input.remindAfterMs);
32133
- record4.timer.unref?.();
32134
- this.reminders.set(key, record4);
32453
+ record5.timer.unref?.();
32454
+ this.reminders.set(key, record5);
32135
32455
  return { armed: true, dueAt };
32136
32456
  }
32137
32457
  observe(agentId, channel2, latestSeq) {