@alan-ai-hq/agent-manager-linux-arm64 0.1.159 → 0.1.161

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/alan-agent.cjs +1072 -338
  2. package/alan-holder.cjs +831 -212
  3. package/package.json +1 -1
package/alan-holder.cjs CHANGED
@@ -637,14 +637,14 @@ function codePointLength(str) {
637
637
  const units = str.length;
638
638
  if (!highSurrogate.test(str))
639
639
  return units;
640
- let count = units;
640
+ let count2 = units;
641
641
  for (let i = 0; i < units - 1; i++) {
642
642
  if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {
643
- count--;
643
+ count2--;
644
644
  i++;
645
645
  }
646
646
  }
647
- return count;
647
+ return count2;
648
648
  }
649
649
  function getLengthableOrigin(input2) {
650
650
  if (Array.isArray(input2))
@@ -5147,8 +5147,8 @@ var init_az = __esm({
5147
5147
  });
5148
5148
 
5149
5149
  // ../../node_modules/zod/v4/locales/be.js
5150
- function getBelarusianPlural(count, one, few, many) {
5151
- const absCount = Math.abs(count);
5150
+ function getBelarusianPlural(count2, one, few, many) {
5151
+ const absCount = Math.abs(count2);
5152
5152
  const lastDigit = absCount % 10;
5153
5153
  const lastTwoDigits = absCount % 100;
5154
5154
  if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
@@ -7942,8 +7942,8 @@ var init_hu = __esm({
7942
7942
  });
7943
7943
 
7944
7944
  // ../../node_modules/zod/v4/locales/hy.js
7945
- function getArmenianPlural(count, one, many) {
7946
- return Math.abs(count) === 1 ? one : many;
7945
+ function getArmenianPlural(count2, one, many) {
7946
+ return Math.abs(count2) === 1 ? one : many;
7947
7947
  }
7948
7948
  function withDefiniteArticle(word) {
7949
7949
  if (!word)
@@ -10841,8 +10841,8 @@ var init_ro = __esm({
10841
10841
  });
10842
10842
 
10843
10843
  // ../../node_modules/zod/v4/locales/ru.js
10844
- function getRussianPlural(count, one, few, many) {
10845
- const absCount = Math.abs(count);
10844
+ function getRussianPlural(count2, one, few, many) {
10845
+ const absCount = Math.abs(count2);
10846
10846
  const lastDigit = absCount % 10;
10847
10847
  const lastTwoDigits = absCount % 100;
10848
10848
  if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
@@ -22443,6 +22443,56 @@ var init_run_log_upload = __esm({
22443
22443
  }
22444
22444
  });
22445
22445
 
22446
+ // ../shared/dist/runtime-v2/run-media.js
22447
+ function runMediaPath(runId) {
22448
+ return `/public/machines/me/runs/${encodeURIComponent(runId)}/media`;
22449
+ }
22450
+ function runMediaCompletePath(runId, mediaId) {
22451
+ return `${runMediaPath(runId)}/${encodeURIComponent(mediaId)}/complete`;
22452
+ }
22453
+ var INT4_MAX, runMediaSourceSchema, runMediaUploadRequestSchema, runMediaUploadTargetSchema, runMediaUploadResponseSchema, runMediaCompleteResponseSchema;
22454
+ var init_run_media = __esm({
22455
+ "../shared/dist/runtime-v2/run-media.js"() {
22456
+ "use strict";
22457
+ init_zod();
22458
+ INT4_MAX = 2147483647;
22459
+ runMediaSourceSchema = external_exports.enum(["generated_image", "session_media"]);
22460
+ runMediaUploadRequestSchema = external_exports.object({
22461
+ /** The `id` the transcript update carries; one upload per id and run. */
22462
+ mediaId: external_exports.string().min(1).max(200),
22463
+ source: runMediaSourceSchema,
22464
+ kind: external_exports.enum(["image", "video"]),
22465
+ mimeType: external_exports.string().min(1).max(200),
22466
+ filename: external_exports.string().min(1).max(500),
22467
+ bytes: external_exports.number().int().positive().max(INT4_MAX),
22468
+ sha256: external_exports.string().regex(/^[0-9a-f]{64}$/),
22469
+ width: external_exports.number().int().min(0).max(INT4_MAX).nullish(),
22470
+ height: external_exports.number().int().min(0).max(INT4_MAX).nullish(),
22471
+ toolId: external_exports.string().max(500).optional(),
22472
+ sourcePath: external_exports.string().max(4096).optional(),
22473
+ ts: external_exports.number().int().positive().optional()
22474
+ });
22475
+ runMediaUploadTargetSchema = external_exports.object({
22476
+ url: external_exports.url(),
22477
+ /** Every header the signed PUT expects, besides the body's `content-length`. */
22478
+ headers: external_exports.record(external_exports.string(), external_exports.string()),
22479
+ expiresAt: external_exports.iso.datetime()
22480
+ });
22481
+ runMediaUploadResponseSchema = external_exports.discriminatedUnion("status", [
22482
+ external_exports.object({
22483
+ status: external_exports.literal("upload"),
22484
+ mediaId: external_exports.string(),
22485
+ upload: runMediaUploadTargetSchema
22486
+ }),
22487
+ external_exports.object({ status: external_exports.literal("ready"), mediaId: external_exports.string() })
22488
+ ]);
22489
+ runMediaCompleteResponseSchema = external_exports.object({
22490
+ status: external_exports.literal("ready"),
22491
+ mediaId: external_exports.string()
22492
+ });
22493
+ }
22494
+ });
22495
+
22446
22496
  // ../shared/dist/runtime-v2/skills.js
22447
22497
  var MAX_MACHINE_SKILLS, installedMachineSkillSchema, MAX_SKILL_UPLOADS, machineSkillScanRepositorySchema, machineSkillScanContextSchema, machineLocalSkillsReportSchema, machineSkillUploadSchema, machineSkillsSyncRequestSchema, desiredMachineSkillSchema, machineSkillDownloadSchema, machineSkillsSyncResponseSchema;
22448
22498
  var init_skills = __esm({
@@ -22565,6 +22615,7 @@ var init_runtime_v2 = __esm({
22565
22615
  init_mcp();
22566
22616
  init_run_log();
22567
22617
  init_run_log_upload();
22618
+ init_run_media();
22568
22619
  init_skills();
22569
22620
  init_workspace();
22570
22621
  }
@@ -25098,11 +25149,15 @@ var init_background_task = __esm({
25098
25149
  function isUpdate(update, kind) {
25099
25150
  return update.sessionUpdate === kind;
25100
25151
  }
25101
- var STEER_ID_META;
25152
+ var STEER_ID_META, MEDIA_SESSION_UPDATE_KINDS;
25102
25153
  var init_types2 = __esm({
25103
25154
  "../shared/dist/agent/acp/types.js"() {
25104
25155
  "use strict";
25105
25156
  STEER_ID_META = "alan.dev/steerId";
25157
+ MEDIA_SESSION_UPDATE_KINDS = /* @__PURE__ */ new Set([
25158
+ "_alan/generated_image",
25159
+ "_alan/session_media"
25160
+ ]);
25106
25161
  }
25107
25162
  });
25108
25163
 
@@ -25210,9 +25265,14 @@ var init_session_activity = __esm({
25210
25265
  });
25211
25266
 
25212
25267
  // ../shared/dist/agent/acp/transcript-byte-decoder.js
25268
+ var MIN_ELIDED_DATA_BYTES, DATA_KEY, MEDIA_MARKERS;
25213
25269
  var init_transcript_byte_decoder = __esm({
25214
25270
  "../shared/dist/agent/acp/transcript-byte-decoder.js"() {
25215
25271
  "use strict";
25272
+ init_types2();
25273
+ MIN_ELIDED_DATA_BYTES = 16 * 1024;
25274
+ DATA_KEY = new TextEncoder().encode('"data":"');
25275
+ MEDIA_MARKERS = [...MEDIA_SESSION_UPDATE_KINDS].map((kind) => new TextEncoder().encode(JSON.stringify(kind)));
25216
25276
  }
25217
25277
  });
25218
25278
 
@@ -25249,7 +25309,7 @@ var init_acp = __esm({
25249
25309
  }
25250
25310
  });
25251
25311
 
25252
- // ../agent-core/dist/chunk-OUEMTEUX.js
25312
+ // ../agent-core/dist/chunk-RBQC7XZH.js
25253
25313
  function textBlock(text2) {
25254
25314
  return { type: "text", text: text2 };
25255
25315
  }
@@ -25384,8 +25444,8 @@ function readPatchHunks(value) {
25384
25444
  return hunk ? [hunk] : [];
25385
25445
  });
25386
25446
  }
25387
- function hunkRange(start, count) {
25388
- return count === 1 ? String(start) : `${start},${count}`;
25447
+ function hunkRange(start, count2) {
25448
+ return count2 === 1 ? String(start) : `${start},${count2}`;
25389
25449
  }
25390
25450
  function hunkHeader(hunk) {
25391
25451
  return `@@ -${hunkRange(hunk.oldStart, hunk.oldLines)} +${hunkRange(hunk.newStart, hunk.newLines)} @@`;
@@ -25396,14 +25456,14 @@ function patchPath(path) {
25396
25456
  function wholeFileHunk(content, deleted) {
25397
25457
  const lines = content === "" ? [] : content.split("\n");
25398
25458
  if (lines.at(-1) === "") lines.pop();
25399
- const count = lines.length;
25459
+ const count2 = lines.length;
25400
25460
  const marked = lines.map((line) => `${deleted ? "-" : "+"}${line}`);
25401
25461
  if (content && !content.endsWith("\n")) marked.push("\");
25402
25462
  return {
25403
- oldStart: deleted && count ? 1 : 0,
25404
- oldLines: deleted ? count : 0,
25405
- newStart: !deleted && count ? 1 : 0,
25406
- newLines: deleted ? 0 : count,
25463
+ oldStart: deleted && count2 ? 1 : 0,
25464
+ oldLines: deleted ? count2 : 0,
25465
+ newStart: !deleted && count2 ? 1 : 0,
25466
+ newLines: deleted ? 0 : count2,
25407
25467
  lines: marked
25408
25468
  };
25409
25469
  }
@@ -25498,8 +25558,8 @@ function planEntries(todos) {
25498
25558
  });
25499
25559
  }
25500
25560
  var PROVIDER_PAYLOAD_META, TOOL_RESULT_ONLY_META, PARENT_TOOL_CALL_META, SUBAGENT_LAUNCHER_META, SUBAGENT_TASK_ID_META, SUBAGENT_OUTPUT_FILE_META, USAGE_META, TODOS_META, NOTICE_KIND_META, ASK_USER_QUESTIONS_META, USER_ANSWER_META, AWAITING_TOOL_CALLS_META, EXIT_PLAN_MODE_INPUT_META, BACKGROUND_TASK_META, TASK_PROGRESS_META, RATE_LIMIT_META, MODEL_META, TOOLS_META, SLASH_COMMANDS_META, TOOL_KIND_RULES, ANSWER_PREFIX, ACCEPT_WORDS, MIN_INLINE_MEDIA_CHARS, DATA_URL_PREFIX, BASE64_BODY, PLAN_ENTRY_STATUSES;
25501
- var init_chunk_OUEMTEUX = __esm({
25502
- "../agent-core/dist/chunk-OUEMTEUX.js"() {
25561
+ var init_chunk_RBQC7XZH = __esm({
25562
+ "../agent-core/dist/chunk-RBQC7XZH.js"() {
25503
25563
  "use strict";
25504
25564
  init_chunk_YXWJW7I5();
25505
25565
  init_constants();
@@ -25555,17 +25615,17 @@ var init_chunk_OUEMTEUX = __esm({
25555
25615
  var init_acp2 = __esm({
25556
25616
  "../agent-core/dist/acp.js"() {
25557
25617
  "use strict";
25558
- init_chunk_OUEMTEUX();
25618
+ init_chunk_RBQC7XZH();
25559
25619
  init_chunk_YXWJW7I5();
25560
25620
  }
25561
25621
  });
25562
25622
 
25563
- // ../agent-core/dist/chunk-D4TIXPWZ.js
25623
+ // ../agent-core/dist/chunk-TFIO37PI.js
25564
25624
  var import_fs4, NEWLINE2, TranscriptCursor, TranscriptLineLookup;
25565
- var init_chunk_D4TIXPWZ = __esm({
25566
- "../agent-core/dist/chunk-D4TIXPWZ.js"() {
25625
+ var init_chunk_TFIO37PI = __esm({
25626
+ "../agent-core/dist/chunk-TFIO37PI.js"() {
25567
25627
  "use strict";
25568
- init_chunk_OUEMTEUX();
25628
+ init_chunk_RBQC7XZH();
25569
25629
  init_chunk_YXWJW7I5();
25570
25630
  import_fs4 = require("fs");
25571
25631
  NEWLINE2 = 10;
@@ -26113,7 +26173,7 @@ var init_chunk_ZCTKXKYY = __esm({
26113
26173
  }
26114
26174
  });
26115
26175
 
26116
- // ../agent-core/dist/chunk-FYZKVT3E.js
26176
+ // ../agent-core/dist/chunk-N2M5D7RS.js
26117
26177
  function detectImageMimeType(buffer) {
26118
26178
  if (buffer.length >= 8 && buffer.subarray(0, 8).equals(PNG_SIGNATURE)) return "image/png";
26119
26179
  if (buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255) {
@@ -26249,6 +26309,27 @@ function resultText(update) {
26249
26309
  if (typeof raw === "string") return raw;
26250
26310
  return raw === void 0 ? "" : JSON.stringify(raw);
26251
26311
  }
26312
+ function mediaUpdate(file2, body) {
26313
+ const fields = {
26314
+ id: file2.mediaId,
26315
+ filename: file2.filename,
26316
+ mimeType: file2.mimeType,
26317
+ size: file2.data.length,
26318
+ ...body,
26319
+ sourcePath: file2.sourcePath,
26320
+ sourceHash: file2.sha256,
26321
+ toolId: file2.toolId,
26322
+ ts: file2.ts,
26323
+ ...file2.width === void 0 ? {} : { width: file2.width },
26324
+ ...file2.height === void 0 ? {} : { height: file2.height }
26325
+ };
26326
+ if (file2.source === "generated_image") {
26327
+ const image = { type: "generated_image", ...fields };
26328
+ return { sessionUpdate: "_alan/generated_image", image };
26329
+ }
26330
+ const media = { type: "session_media", kind: file2.kind, ...fields };
26331
+ return { sessionUpdate: "_alan/session_media", media };
26332
+ }
26252
26333
  function updateRequiredMessage(requirement, found) {
26253
26334
  const { cli, minimumVersion, feature } = requirement;
26254
26335
  const installed = found ? `${cli} ${found}` : `The ${cli} CLI`;
@@ -26533,10 +26614,10 @@ function silentStartError(name, timeoutMs) {
26533
26614
  };
26534
26615
  }
26535
26616
  var import_crypto4, import_fs5, import_path4, PNG_SIGNATURE, IMAGE_MIME_BY_EXT, VIDEO_MIME_BY_EXT, IMAGE_EXTENSIONS, VIDEO_EXTENSIONS, MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, MAX_TURN_MEDIA_DATA_CHARS, MTIME_SLACK_MS, AGENT_BROWSER_MENTION, AGENT_BROWSER_CAPTURE_COMMAND, LocalMediaReader, SessionOpenRefusal, JsonRpcError, ACP_PROTOCOL_VERSION, ACP_ERROR, STDERR_TAIL_LINES, RESULT_EXIT_GRACE_MS, PerTurnSession;
26536
- var init_chunk_FYZKVT3E = __esm({
26537
- "../agent-core/dist/chunk-FYZKVT3E.js"() {
26617
+ var init_chunk_N2M5D7RS = __esm({
26618
+ "../agent-core/dist/chunk-N2M5D7RS.js"() {
26538
26619
  "use strict";
26539
- init_chunk_OUEMTEUX();
26620
+ init_chunk_RBQC7XZH();
26540
26621
  init_chunk_ZCTKXKYY();
26541
26622
  init_chunk_6VWVDJ2A();
26542
26623
  init_chunk_YXWJW7I5();
@@ -26576,8 +26657,12 @@ var init_chunk_FYZKVT3E = __esm({
26576
26657
  this.#cwd = cwd;
26577
26658
  this.#clock = clock;
26578
26659
  }
26579
- /** Updates to record after `update`; nothing for anything but a tool call, which is almost all. */
26660
+ /** Updates to record after `update`, with the bytes inline; nothing for most updates. */
26580
26661
  read(update) {
26662
+ return this.find(update).map((found) => this.inline(found));
26663
+ }
26664
+ /** The media files a completed tool call wrote; nothing for anything but a tool call. */
26665
+ find(update) {
26581
26666
  if (!isUpdate(update, "tool_call_update")) return [];
26582
26667
  const toolCallId = update.toolCallId;
26583
26668
  if (update.name !== void 0 || update.rawInput !== void 0) {
@@ -26623,20 +26708,42 @@ var init_chunk_FYZKVT3E = __esm({
26623
26708
  named: /* @__PURE__ */ new Set([...capturePaths(tool, content, extensions, cwd), ...this.#pathHints])
26624
26709
  });
26625
26710
  }
26626
- #payloadFields(file2, toolId, explicit) {
26627
- const dataChars = base64Length(file2.buffer.length);
26628
- const inline = explicit || this.#mediaDataChars + dataChars <= MAX_TURN_MEDIA_DATA_CHARS;
26711
+ /** The update carrying the file's bytes, unless the turn's budget is spent on media nobody asked for. */
26712
+ inline(found) {
26713
+ const { file: file2 } = found;
26714
+ const dataChars = base64Length(file2.data.length);
26715
+ const inline = found.explicit || this.#mediaDataChars + dataChars <= MAX_TURN_MEDIA_DATA_CHARS;
26629
26716
  if (inline) this.#mediaDataChars += dataChars;
26717
+ return mediaUpdate(
26718
+ file2,
26719
+ inline ? { data: file2.data.toString("base64") } : { inlineDataOmitted: true }
26720
+ );
26721
+ }
26722
+ /** Uploads the file and returns a reference to it; inline as `inline` does when the upload fails. */
26723
+ async publish(found, uploader, signal) {
26724
+ try {
26725
+ await uploader.upload(found.file, signal);
26726
+ return mediaUpdate(found.file, { uploaded: true });
26727
+ } catch {
26728
+ return this.inline(found);
26729
+ }
26730
+ }
26731
+ #found(file2, toolId, source, kind, explicit) {
26630
26732
  return {
26631
- id: (0, import_crypto4.randomUUID)(),
26632
- filename: (0, import_path4.basename)(file2.path),
26633
- mimeType: file2.mimeType,
26634
- size: file2.buffer.length,
26635
- ...inline ? { data: file2.buffer.toString("base64") } : { inlineDataOmitted: true },
26636
- sourcePath: file2.path,
26637
- sourceHash: (0, import_crypto4.createHash)("sha256").update(file2.buffer).digest("hex"),
26638
- toolId,
26639
- ts: this.#clock.now()
26733
+ explicit,
26734
+ file: {
26735
+ mediaId: (0, import_crypto4.randomUUID)(),
26736
+ source,
26737
+ kind,
26738
+ mimeType: file2.mimeType,
26739
+ filename: (0, import_path4.basename)(file2.path),
26740
+ data: file2.buffer,
26741
+ sha256: (0, import_crypto4.createHash)("sha256").update(file2.buffer).digest("hex"),
26742
+ ...kind === "image" ? imageDimensions(file2.buffer, file2.mimeType) : {},
26743
+ toolId,
26744
+ sourcePath: file2.path,
26745
+ ts: this.#clock.now()
26746
+ }
26640
26747
  };
26641
26748
  }
26642
26749
  #generatedImages(toolId, tool, content) {
@@ -26645,14 +26752,7 @@ var init_chunk_FYZKVT3E = __esm({
26645
26752
  mimeByExt: IMAGE_MIME_BY_EXT,
26646
26753
  maxBytes: MAX_IMAGE_BYTES
26647
26754
  });
26648
- return files.map((file2) => {
26649
- const image = {
26650
- type: "generated_image",
26651
- ...this.#payloadFields(file2, toolId, true),
26652
- ...imageDimensions(file2.buffer, file2.mimeType)
26653
- };
26654
- return { sessionUpdate: "_alan/generated_image", image };
26655
- });
26755
+ return files.map((file2) => this.#found(file2, toolId, "generated_image", "image", true));
26656
26756
  }
26657
26757
  #sessionMedia(toolId, tool, content) {
26658
26758
  const isVideo = isAgentBrowserMedia(tool, content, "video");
@@ -26667,13 +26767,7 @@ var init_chunk_FYZKVT3E = __esm({
26667
26767
  );
26668
26768
  return files.map((file2) => {
26669
26769
  this.#pathHints.delete(file2.path);
26670
- const media = {
26671
- type: "session_media",
26672
- kind,
26673
- ...this.#payloadFields(file2, toolId, explicit),
26674
- ...kind === "image" ? imageDimensions(file2.buffer, file2.mimeType) : {}
26675
- };
26676
- return { sessionUpdate: "_alan/session_media", media };
26770
+ return this.#found(file2, toolId, "session_media", kind, explicit);
26677
26771
  });
26678
26772
  }
26679
26773
  };
@@ -28626,9 +28720,29 @@ function backgroundTaskProgress(event, tasks) {
28626
28720
  }
28627
28721
  ];
28628
28722
  }
28723
+ function claudeMessageContextTokens(message) {
28724
+ if (asString(message?.model) === "<synthetic>") return void 0;
28725
+ const usage = asRecord(message?.usage);
28726
+ if (!usage) return void 0;
28727
+ const tokens2 = (asFiniteNumber(usage.input_tokens) ?? 0) + (asFiniteNumber(usage.cache_read_input_tokens) ?? 0) + (asFiniteNumber(usage.cache_creation_input_tokens) ?? 0) + (asFiniteNumber(usage.output_tokens) ?? 0);
28728
+ return tokens2 > 0 ? tokens2 : void 0;
28729
+ }
28730
+ function resultContextWindow(event, model) {
28731
+ const byModel = asRecord(event.modelUsage);
28732
+ if (!byModel) return void 0;
28733
+ const own2 = asFiniteNumber(asRecord(byModel[model])?.contextWindow);
28734
+ if (own2 !== void 0) return own2;
28735
+ let largest;
28736
+ for (const entry of Object.values(byModel)) {
28737
+ const size = asFiniteNumber(asRecord(entry)?.contextWindow);
28738
+ if (size !== void 0 && size > (largest ?? 0)) largest = size;
28739
+ }
28740
+ return largest;
28741
+ }
28629
28742
  function resultUsage(event, context) {
28630
28743
  const usage = asRecord(event.usage);
28631
28744
  const model = asString(event.model).trim() || context.activeModel?.trim() || context.selectedModel?.trim() || "claude";
28745
+ const contextSize = resultContextWindow(event, model);
28632
28746
  return usageUpdate({
28633
28747
  model,
28634
28748
  numTurns: asFiniteNumber(event.num_turns) ?? Math.max(context.iterations, 1),
@@ -28637,7 +28751,9 @@ function resultUsage(event, context) {
28637
28751
  outputTokens: asFiniteNumber(usage?.output_tokens) ?? 0,
28638
28752
  cacheReadTokens: asFiniteNumber(usage?.cache_read_input_tokens) ?? 0,
28639
28753
  cacheCreationTokens: asFiniteNumber(usage?.cache_creation_input_tokens) ?? 0,
28640
- costUsd: asFiniteNumber(event.total_cost_usd) ?? 0
28754
+ costUsd: asFiniteNumber(event.total_cost_usd) ?? 0,
28755
+ ...contextSize === void 0 ? {} : { contextSize },
28756
+ ...context.contextTokens === void 0 ? {} : { contextTokens: context.contextTokens }
28641
28757
  });
28642
28758
  }
28643
28759
  function resultErrorText(event, subtype) {
@@ -28901,9 +29017,9 @@ var import_crypto7, import_fs6, import_path6, import_crypto8, import_promises15,
28901
29017
  var init_claude = __esm({
28902
29018
  "../agent-core/dist/providers/claude.js"() {
28903
29019
  "use strict";
28904
- init_chunk_D4TIXPWZ();
28905
- init_chunk_FYZKVT3E();
28906
- init_chunk_OUEMTEUX();
29020
+ init_chunk_TFIO37PI();
29021
+ init_chunk_N2M5D7RS();
29022
+ init_chunk_RBQC7XZH();
28907
29023
  init_chunk_ZCTKXKYY();
28908
29024
  init_chunk_6VWVDJ2A();
28909
29025
  init_chunk_DLVRNIY5();
@@ -29201,6 +29317,7 @@ var init_claude = __esm({
29201
29317
  #announced = /* @__PURE__ */ new Set();
29202
29318
  #awaitingAskDenialFallback = false;
29203
29319
  #iterations = 0;
29320
+ #contextTokens;
29204
29321
  #providerErrorCode;
29205
29322
  #deferredOnAnswer = false;
29206
29323
  #deferredOnBackground = false;
@@ -29340,6 +29457,7 @@ var init_claude = __esm({
29340
29457
  #handleSystem(event) {
29341
29458
  const subtype = asString(event.subtype);
29342
29459
  if (subtype === "api_retry") this.#noteRetry(event);
29460
+ if (subtype === "compact_boundary") this.#noteCompaction(event);
29343
29461
  if (subtype === "task_started") {
29344
29462
  this.tasks.registerRecord(event, parentToolUseId(event));
29345
29463
  this.taskRecords.track(event, this.tasks.resolveToolUseId(event));
@@ -29424,13 +29542,25 @@ var init_claude = __esm({
29424
29542
  status
29425
29543
  });
29426
29544
  }
29545
+ /** The window was just rewritten; the pre-compaction figure would overstate it until the next call. */
29546
+ #noteCompaction(event) {
29547
+ if (parentToolUseId(event)) return;
29548
+ const after = asFiniteNumber(asRecord(event.compact_metadata)?.post_tokens);
29549
+ this.#contextTokens = after !== void 0 && after > 0 ? after : void 0;
29550
+ }
29551
+ #noteContext(event, message) {
29552
+ if (parentToolUseId(event)) return;
29553
+ this.#contextTokens = claudeMessageContextTokens(message) ?? this.#contextTokens;
29554
+ }
29427
29555
  #handleAssistant(event) {
29428
29556
  if (this.#awaitingAskDenialFallback) {
29429
29557
  this.#awaitingAskDenialFallback = false;
29430
29558
  return;
29431
29559
  }
29432
29560
  this.#iterations += 1;
29433
- for (const raw of asArray(asRecord(event.message)?.content)) {
29561
+ const message = asRecord(event.message);
29562
+ this.#noteContext(event, message);
29563
+ for (const raw of asArray(message?.content)) {
29434
29564
  const block2 = asRecord(raw);
29435
29565
  if (!block2 || asString(block2.type) !== "tool_use") continue;
29436
29566
  const id = asString(block2.id);
@@ -29450,7 +29580,8 @@ var init_claude = __esm({
29450
29580
  resultUsage(event, {
29451
29581
  activeModel: this.grammar.model,
29452
29582
  selectedModel: this.#options.selectedModel,
29453
- iterations: this.#iterations
29583
+ iterations: this.#iterations,
29584
+ ...this.#contextTokens === void 0 ? {} : { contextTokens: this.#contextTokens }
29454
29585
  })
29455
29586
  ];
29456
29587
  if (typeof event.num_turns === "number") this.#iterations = event.num_turns;
@@ -30665,6 +30796,59 @@ function planEntries2(plan2) {
30665
30796
  ];
30666
30797
  });
30667
30798
  }
30799
+ function count(value) {
30800
+ return asFiniteNumber(value) ?? 0;
30801
+ }
30802
+ function withTotal(tokens2, reported) {
30803
+ return { ...tokens2, total: reported || tokens2.input + tokens2.output };
30804
+ }
30805
+ function appServerTokens(record2) {
30806
+ return withTotal(
30807
+ {
30808
+ input: count(record2.inputTokens),
30809
+ cachedInput: count(record2.cachedInputTokens),
30810
+ cacheWrite: count(record2.cacheWriteInputTokens),
30811
+ output: count(record2.outputTokens)
30812
+ },
30813
+ count(record2.totalTokens)
30814
+ );
30815
+ }
30816
+ function rolloutTokens(record2) {
30817
+ return withTotal(
30818
+ {
30819
+ input: count(record2.input_tokens),
30820
+ cachedInput: count(record2.cached_input_tokens),
30821
+ cacheWrite: count(record2.cache_write_input_tokens),
30822
+ output: count(record2.output_tokens)
30823
+ },
30824
+ count(record2.total_tokens)
30825
+ );
30826
+ }
30827
+ function subtractTokens(from, amount2) {
30828
+ const minus = (a, b) => Math.max(a - b, 0);
30829
+ return {
30830
+ input: minus(from.input, amount2.input),
30831
+ cachedInput: minus(from.cachedInput, amount2.cachedInput),
30832
+ cacheWrite: minus(from.cacheWrite, amount2.cacheWrite),
30833
+ output: minus(from.output, amount2.output),
30834
+ total: minus(from.total, amount2.total)
30835
+ };
30836
+ }
30837
+ function codexBreakdown(tokens2) {
30838
+ return {
30839
+ inputTokens: Math.max(tokens2.input - tokens2.cachedInput - tokens2.cacheWrite, 0),
30840
+ outputTokens: tokens2.output,
30841
+ cacheReadTokens: tokens2.cachedInput,
30842
+ cacheCreationTokens: tokens2.cacheWrite
30843
+ };
30844
+ }
30845
+ function codexUsageUpdate(spend, extra, fallbackModel) {
30846
+ const update = usageUpdate({ ...codexBreakdown(spend), ...extra }, fallbackModel);
30847
+ return spend.total > 0 && isUpdate(update, "usage_update") ? { ...update, used: spend.total } : update;
30848
+ }
30849
+ function codexContextTokens(last) {
30850
+ return last.total > 0 ? last.total : void 0;
30851
+ }
30668
30852
  function createCodexSessionMemory() {
30669
30853
  return { shownWarnings: /* @__PURE__ */ new Set(), workers: /* @__PURE__ */ new Map() };
30670
30854
  }
@@ -31116,13 +31300,13 @@ function codexTurnInput(run, context) {
31116
31300
  ...images.length ? { imagePaths: images.map((image) => image.path) } : {}
31117
31301
  };
31118
31302
  }
31119
- var import_fs7, import_path7, import_crypto9, import_crypto10, import_crypto11, import_crypto12, TokenRefresher, MCP_STARTUP_TIMEOUT_SEC, FIELD_TYPES, YES_NO, ACCEPT_DECLINE, MAX_INLINE_GENERATED_IMAGE_BYTES, PNG_SIGNATURE2, JPEG_NON_FRAME_MARKERS, IMAGE_GEN_CALL, PROMPT_LITERAL, RELOCATE_EVERY_MS, CodexImageGenerationFold, CodexRolloutImages, CodexRateLimits, USER_INPUT_METHOD, PERMISSIONS_METHOD, ELICITATION_METHOD, COMMAND_OR_FILE, LEGACY, DECISIONS, COORDINATION_TOOLS, SETTLED_AGENT, STATUS, CHANGE_OPERATIONS, SILENT_ON_START, IGNORED_ITEMS, PLAN_STATUS, CODEX_MCP_STATUS, WORKER_LIFECYCLE, INFO_KINDS, SILENT, CodexTurn, STDERR_TAIL_LINES3, MAX_BETWEEN_UPDATES, UNSUPPORTED_REQUEST, DECLINED_ELICITATION, IMAGE_CATCH_UP_MS, IMAGE_POLL_MS, CodexSession, CODEX_MIN_VERSION, CODEX_REQUIREMENT, CODEX_TESTED_LINE, DEFAULTS2, CLIENT_INFO, STATUS2, EXITED_WITHOUT_RESPONSE, CodexExecTurn, DEFAULTS22, CodexExecSession;
31303
+ var import_fs7, import_path7, import_crypto9, import_crypto10, import_crypto11, import_crypto12, TokenRefresher, MCP_STARTUP_TIMEOUT_SEC, FIELD_TYPES, YES_NO, ACCEPT_DECLINE, MAX_INLINE_GENERATED_IMAGE_BYTES, PNG_SIGNATURE2, JPEG_NON_FRAME_MARKERS, IMAGE_GEN_CALL, PROMPT_LITERAL, RELOCATE_EVERY_MS, CodexImageGenerationFold, CodexRolloutImages, CodexRateLimits, USER_INPUT_METHOD, PERMISSIONS_METHOD, ELICITATION_METHOD, COMMAND_OR_FILE, LEGACY, DECISIONS, COORDINATION_TOOLS, SETTLED_AGENT, STATUS, CHANGE_OPERATIONS, SILENT_ON_START, IGNORED_ITEMS, PLAN_STATUS, CodexTurnTokens, CODEX_MCP_STATUS, WORKER_LIFECYCLE, INFO_KINDS, SILENT, CodexTurn, STDERR_TAIL_LINES3, MAX_BETWEEN_UPDATES, UNSUPPORTED_REQUEST, DECLINED_ELICITATION, IMAGE_CATCH_UP_MS, IMAGE_POLL_MS, CodexSession, CODEX_MIN_VERSION, CODEX_REQUIREMENT, CODEX_TESTED_LINE, DEFAULTS2, CLIENT_INFO, STATUS2, EXITED_WITHOUT_RESPONSE, CodexExecTurn, DEFAULTS22, CodexExecSession;
31120
31304
  var init_codex = __esm({
31121
31305
  "../agent-core/dist/providers/codex.js"() {
31122
31306
  "use strict";
31123
- init_chunk_D4TIXPWZ();
31124
- init_chunk_FYZKVT3E();
31125
- init_chunk_OUEMTEUX();
31307
+ init_chunk_TFIO37PI();
31308
+ init_chunk_N2M5D7RS();
31309
+ init_chunk_RBQC7XZH();
31126
31310
  init_chunk_ZCTKXKYY();
31127
31311
  init_chunk_6VWVDJ2A();
31128
31312
  init_chunk_DLVRNIY5();
@@ -31134,6 +31318,7 @@ var init_codex = __esm({
31134
31318
  import_crypto9 = require("crypto");
31135
31319
  import_crypto10 = require("crypto");
31136
31320
  init_runtime_v2();
31321
+ init_acp();
31137
31322
  init_agent2();
31138
31323
  import_crypto11 = require("crypto");
31139
31324
  init_agent2();
@@ -31267,10 +31452,13 @@ var init_codex = __esm({
31267
31452
  #reported = /* @__PURE__ */ new Set();
31268
31453
  #cursor;
31269
31454
  #lastMiss;
31270
- constructor(locate, clock) {
31455
+ #onTokenCount;
31456
+ /** `onTokenCount` also hears each `token_count` the rollout gains, for the turn's usage. */
31457
+ constructor(locate, clock, onTokenCount) {
31271
31458
  this.#locate = locate;
31272
31459
  this.#clock = clock;
31273
31460
  this.#fold = new CodexImageGenerationFold(clock);
31461
+ this.#onTokenCount = onTokenCount;
31274
31462
  }
31275
31463
  get waiting() {
31276
31464
  return this.#fold.waiting;
@@ -31291,7 +31479,10 @@ var init_codex = __esm({
31291
31479
  }
31292
31480
  /** What the rollout gained since the last drain. */
31293
31481
  drain() {
31294
- for (const line of this.#open()?.read() ?? []) this.#fold.foldLine(line.text);
31482
+ for (const line of this.#open()?.read() ?? []) {
31483
+ this.#fold.foldLine(line.text);
31484
+ if (this.#onTokenCount) this.#readTokenCount(line.text, this.#onTokenCount);
31485
+ }
31295
31486
  return this.admit(this.#fold.take());
31296
31487
  }
31297
31488
  /** The turn is over: what is left, then every call still pending as failed. */
@@ -31308,6 +31499,16 @@ var init_codex = __esm({
31308
31499
  }
31309
31500
  return updates;
31310
31501
  }
31502
+ #readTokenCount(text2, onTokenCount) {
31503
+ if (!text2.includes('"token_count"')) return;
31504
+ try {
31505
+ const payload = asRecord(asRecord(JSON.parse(text2))?.payload);
31506
+ const info = asRecord(payload?.info);
31507
+ if (asString(payload?.type) === "token_count" && info) onTokenCount(info);
31508
+ } catch {
31509
+ return;
31510
+ }
31511
+ }
31311
31512
  #open() {
31312
31513
  if (this.#cursor) return this.#cursor;
31313
31514
  const now = this.#clock.monotonic();
@@ -31409,6 +31610,31 @@ var init_codex = __esm({
31409
31610
  ["inProgress", "in_progress"],
31410
31611
  ["completed", "completed"]
31411
31612
  ]);
31613
+ CodexTurnTokens = class {
31614
+ #baseline;
31615
+ #last;
31616
+ #window;
31617
+ /** Records one report; `total` absent means `last` is the whole turn so far. */
31618
+ note(last, total, window) {
31619
+ if (total) this.#baseline ??= subtractTokens(total, last);
31620
+ this.#last = last;
31621
+ if (window !== void 0 && window > 0) this.#window = window;
31622
+ }
31623
+ get hasBaseline() {
31624
+ return this.#baseline !== void 0;
31625
+ }
31626
+ spend(total) {
31627
+ return this.#baseline ? subtractTokens(total, this.#baseline) : total;
31628
+ }
31629
+ /** The context the turn's last call left, and the window, as far as they are known. */
31630
+ get context() {
31631
+ const contextTokens = this.#last ? codexContextTokens(this.#last) : void 0;
31632
+ return {
31633
+ ...this.#window === void 0 ? {} : { contextSize: this.#window },
31634
+ ...contextTokens === void 0 ? {} : { contextTokens }
31635
+ };
31636
+ }
31637
+ };
31412
31638
  CODEX_MCP_STATUS = {
31413
31639
  starting: "starting",
31414
31640
  ready: "connected",
@@ -31455,6 +31681,7 @@ var init_codex = __esm({
31455
31681
  #end;
31456
31682
  #failFast;
31457
31683
  #lastError;
31684
+ #tokens = new CodexTurnTokens();
31458
31685
  codexTurnId;
31459
31686
  constructor(memory, clock = systemClock2) {
31460
31687
  this.#memory = memory;
@@ -31549,19 +31776,16 @@ var init_codex = __esm({
31549
31776
  }
31550
31777
  #usage(params) {
31551
31778
  const usage = asRecord(params.tokenUsage);
31552
- const last = asRecord(usage?.last);
31553
- if (!last) return [];
31554
- const number4 = (value) => asFiniteNumber(value) ?? 0;
31779
+ const lastRecord = asRecord(usage?.last);
31780
+ if (!lastRecord) return [];
31781
+ const last = appServerTokens(lastRecord);
31782
+ const totalRecord = asRecord(usage?.total);
31783
+ const total = totalRecord ? appServerTokens(totalRecord) : void 0;
31784
+ this.#tokens.note(last, total, asFiniteNumber(usage?.modelContextWindow));
31555
31785
  return [
31556
- usageUpdate(
31557
- {
31558
- inputTokens: number4(last.inputTokens),
31559
- outputTokens: number4(last.outputTokens) + number4(last.reasoningOutputTokens),
31560
- cacheReadTokens: number4(last.cachedInputTokens),
31561
- cacheCreationTokens: number4(last.cacheWriteInputTokens),
31562
- ...asFiniteNumber(usage?.modelContextWindow) === void 0 ? {} : { contextSize: number4(usage?.modelContextWindow) },
31563
- costUsd: 0
31564
- },
31786
+ codexUsageUpdate(
31787
+ total ? this.#tokens.spend(total) : last,
31788
+ { ...this.#tokens.context, costUsd: 0 },
31565
31789
  this.#memory.model ?? "codex"
31566
31790
  )
31567
31791
  ];
@@ -32102,12 +32326,16 @@ var init_codex = __esm({
32102
32326
  #lastError;
32103
32327
  #answered = false;
32104
32328
  #images;
32329
+ #tokens = new CodexTurnTokens();
32330
+ #resumed;
32105
32331
  constructor(resumeId, rollout) {
32106
32332
  this.#threadId = resumeId;
32333
+ this.#resumed = resumeId !== void 0;
32107
32334
  if (!rollout) return;
32108
32335
  this.#images = new CodexRolloutImages(
32109
32336
  () => this.#threadId ? findCodexRollout(rollout.codexHome, this.#threadId) : void 0,
32110
- rollout.clock
32337
+ rollout.clock,
32338
+ (info) => this.#noteTokenCount(info)
32111
32339
  );
32112
32340
  if (resumeId) this.#images.startAtEnd();
32113
32341
  }
@@ -32169,22 +32397,34 @@ var init_codex = __esm({
32169
32397
  if (mapped) return itemUpdates(mapped, completed);
32170
32398
  return [{ sessionUpdate: "_alan/unhandled", kind: `item/${type || "(untyped)"}` }];
32171
32399
  }
32400
+ /** The rollout's per-call counts: exec's own usage is only the thread's running total. */
32401
+ #noteTokenCount(info) {
32402
+ const last = asRecord(info.last_token_usage);
32403
+ const total = asRecord(info.total_token_usage);
32404
+ if (!last) return;
32405
+ this.#tokens.note(
32406
+ rolloutTokens(last),
32407
+ total ? rolloutTokens(total) : void 0,
32408
+ asFiniteNumber(info.model_context_window)
32409
+ );
32410
+ }
32172
32411
  #completed(usage) {
32173
32412
  this.#end = { status: "completed" };
32174
- const number4 = (value) => asFiniteNumber(value) ?? 0;
32413
+ const rolloutUpdates = this.#images?.drain() ?? [];
32175
32414
  return [
32176
- ...usage ? [
32177
- usageUpdate({
32178
- inputTokens: number4(usage.input_tokens),
32179
- outputTokens: number4(usage.output_tokens) + number4(usage.reasoning_output_tokens),
32180
- cacheReadTokens: number4(usage.cached_input_tokens),
32181
- cacheCreationTokens: number4(usage.cache_write_input_tokens),
32182
- costUsd: 0
32183
- })
32184
- ] : [],
32415
+ ...rolloutUpdates,
32416
+ ...usage ? this.#usage(rolloutTokens(usage)) : [],
32185
32417
  { sessionUpdate: "state_update", state: "idle", stopReason: "end_turn" }
32186
32418
  ];
32187
32419
  }
32420
+ /** A resumed turn with no rollout counts cannot separate its spend from earlier turns'. */
32421
+ #usage(threadTotal) {
32422
+ const context = { ...this.#tokens.context, costUsd: 0 };
32423
+ if (this.#resumed && !this.#tokens.hasBaseline) {
32424
+ return context.contextTokens === void 0 ? [] : [usageUpdate(context)];
32425
+ }
32426
+ return [codexUsageUpdate(this.#tokens.spend(threadTotal), context, "")];
32427
+ }
32188
32428
  #failed(error62, fallback) {
32189
32429
  const message = errorText(error62?.message) || errorText(error62?.detail) || fallback.trim();
32190
32430
  const classified = message ? classifyCliError(normalizeCodexCliErrorMessage(message)) : this.#lastError ?? specForErrorKind("provider_error");
@@ -32254,6 +32494,14 @@ function resolveAlanCodeModelId(selectedModel, models) {
32254
32494
  if (requested && models.some((model) => model.id === requested)) return requested;
32255
32495
  return models.find((model) => model.isDefault)?.id ?? firstModel.id;
32256
32496
  }
32497
+ function disabledInheritedMcp(own2, inherited) {
32498
+ const disabled = {};
32499
+ for (const name of inherited ?? []) {
32500
+ if (name in own2) continue;
32501
+ disabled[name] = { enabled: false };
32502
+ }
32503
+ return disabled;
32504
+ }
32257
32505
  function parseExisting(existing) {
32258
32506
  if (!existing?.trim()) return {};
32259
32507
  try {
@@ -32281,6 +32529,8 @@ function alanCodeConfigContent(existing, input2) {
32281
32529
  const prompt = input2.prompt ?? ALAN_CODE_BASELINE_PROMPT;
32282
32530
  const hiddenSkills = { skill: { "customize-opencode": "deny" } };
32283
32531
  const plugins = Array.isArray(config2.plugin) ? config2.plugin : [];
32532
+ const ownMcp = field(config2, "mcp");
32533
+ const mcp = { ...ownMcp, ...disabledInheritedMcp(ownMcp, input2.inheritedMcpServers) };
32284
32534
  return JSON.stringify({
32285
32535
  $schema: "https://opencode.ai/config.json",
32286
32536
  ...config2,
@@ -32289,6 +32539,7 @@ function alanCodeConfigContent(existing, input2) {
32289
32539
  // 3.4 GB of a dev machine's engine database was these patches, against 82 sessions. Alan
32290
32540
  // does not use the engine's undo/revert, so the tracking stays off.
32291
32541
  snapshot: false,
32542
+ ...Object.keys(mcp).length ? { mcp } : {},
32292
32543
  model: `${ALAN_CODE_ENGINE_PROVIDER_ID}/${input2.modelId}`,
32293
32544
  enabled_providers: [ALAN_CODE_ENGINE_PROVIDER_ID],
32294
32545
  provider: {
@@ -32607,6 +32858,77 @@ function alanCodeEngineEnv(input2) {
32607
32858
  [ALAN_CODE_CONVERSATION_ID_ENV]: input2.conversationId
32608
32859
  };
32609
32860
  }
32861
+ function openCodeGlobalConfigDirectory(env, home) {
32862
+ const configHome = env.XDG_CONFIG_HOME?.trim() || (0, import_path9.join)(home, ".config");
32863
+ return (0, import_path9.join)(configHome, "opencode");
32864
+ }
32865
+ function stripJsonc(text2) {
32866
+ let out = "";
32867
+ let index = 0;
32868
+ while (index < text2.length) {
32869
+ const skipTo = commentEnd(text2, index);
32870
+ if (skipTo !== void 0) {
32871
+ index = skipTo;
32872
+ continue;
32873
+ }
32874
+ const char = text2[index];
32875
+ if (char === "}" || char === "]") out = out.replace(/,\s*$/, "");
32876
+ const end = char === '"' ? stringLiteralEnd(text2, index) : index + 1;
32877
+ out += text2.slice(index, end);
32878
+ index = end;
32879
+ }
32880
+ return out;
32881
+ }
32882
+ function commentEnd(text2, index) {
32883
+ const pair = text2.slice(index, index + 2);
32884
+ if (pair === "//") {
32885
+ const newline = text2.indexOf("\n", index);
32886
+ return newline === -1 ? text2.length : newline;
32887
+ }
32888
+ if (pair === "/*") {
32889
+ const close = text2.indexOf("*/", index + 2);
32890
+ return close === -1 ? text2.length : close + 2;
32891
+ }
32892
+ return void 0;
32893
+ }
32894
+ function stringLiteralEnd(text2, start) {
32895
+ let index = start + 1;
32896
+ while (index < text2.length) {
32897
+ const char = text2[index];
32898
+ if (char === "\\") {
32899
+ index += 2;
32900
+ } else if (char === '"') {
32901
+ return index + 1;
32902
+ } else {
32903
+ index += 1;
32904
+ }
32905
+ }
32906
+ return text2.length;
32907
+ }
32908
+ function parseJsonc(text2) {
32909
+ try {
32910
+ return JSON.parse(text2);
32911
+ } catch {
32912
+ try {
32913
+ return JSON.parse(stripJsonc(text2));
32914
+ } catch {
32915
+ return void 0;
32916
+ }
32917
+ }
32918
+ }
32919
+ async function inheritedMcpServerNames(configDirectory) {
32920
+ const names = /* @__PURE__ */ new Set();
32921
+ for (const file2 of ["config.json", "opencode.json", "opencode.jsonc"]) {
32922
+ const text2 = await (0, import_promises16.readFile)((0, import_path9.join)(configDirectory, file2), "utf8").catch(() => null);
32923
+ if (text2 === null) continue;
32924
+ const parsed = parseJsonc(text2);
32925
+ const mcp = parsed !== null && typeof parsed === "object" ? parsed.mcp : void 0;
32926
+ if (mcp !== null && typeof mcp === "object") {
32927
+ for (const name of Object.keys(mcp)) names.add(name);
32928
+ }
32929
+ }
32930
+ return [...names];
32931
+ }
32610
32932
  async function writePlugin(directory, apiOrigin) {
32611
32933
  const origin = (0, import_crypto13.createHash)("sha256").update(apiOrigin).digest("hex").slice(0, 12);
32612
32934
  const target = (0, import_path9.join)(directory, `engine-plugin-v${ALAN_CODE_ENGINE_PLUGIN_VERSION}-${origin}.mjs`);
@@ -32621,9 +32943,10 @@ async function prepareAlanCodeProfile(input2) {
32621
32943
  await Promise.all(
32622
32944
  directories.map((directory) => (0, import_promises16.mkdir)(directory, { recursive: true, mode: 448 }))
32623
32945
  );
32624
- const [pluginUrl, models] = await Promise.all([
32946
+ const [pluginUrl, models, inheritedMcpServers] = await Promise.all([
32625
32947
  writePlugin((0, import_path9.join)(input2.engineRoot, "plugin"), input2.access.apiOrigin),
32626
- (input2.loadModels ?? fetchAlanCodeModels)(input2.access)
32948
+ (input2.loadModels ?? fetchAlanCodeModels)(input2.access),
32949
+ input2.globalConfigDirectory === void 0 ? Promise.resolve([]) : inheritedMcpServerNames(input2.globalConfigDirectory)
32627
32950
  ]);
32628
32951
  const modelId = resolveAlanCodeModelId(input2.requestedModel, models);
32629
32952
  return {
@@ -32631,7 +32954,8 @@ async function prepareAlanCodeProfile(input2) {
32631
32954
  baseURL: `${input2.access.apiOrigin}${ALAN_CODE_PROXY_PATH}`,
32632
32955
  modelId,
32633
32956
  models,
32634
- pluginUrl
32957
+ pluginUrl,
32958
+ inheritedMcpServers
32635
32959
  }),
32636
32960
  model: { providerID: ALAN_CODE_ENGINE_PROVIDER_ID, modelID: modelId }
32637
32961
  };
@@ -33269,8 +33593,8 @@ var require_Node = __commonJS({
33269
33593
  };
33270
33594
  const res = toJS.toJS(this, "", ctx);
33271
33595
  if (typeof onAnchor === "function")
33272
- for (const { count, res: res2 } of ctx.anchors.values())
33273
- onAnchor(res2, count);
33596
+ for (const { count: count2, res: res2 } of ctx.anchors.values())
33597
+ onAnchor(res2, count2);
33274
33598
  return typeof reviver === "function" ? applyReviver.applyReviver(reviver, { "": res }, "", res) : res;
33275
33599
  }
33276
33600
  };
@@ -33376,13 +33700,13 @@ var require_Alias = __commonJS({
33376
33700
  const anchor2 = anchors2 && source && anchors2.get(source);
33377
33701
  return anchor2 ? anchor2.count * anchor2.aliasCount : 0;
33378
33702
  } else if (identity.isCollection(node2)) {
33379
- let count = 0;
33703
+ let count2 = 0;
33380
33704
  for (const item of node2.items) {
33381
33705
  const c = getAliasCount(doc, item, anchors2);
33382
- if (c > count)
33383
- count = c;
33706
+ if (c > count2)
33707
+ count2 = c;
33384
33708
  }
33385
- return count;
33709
+ return count2;
33386
33710
  } else if (identity.isPair(node2)) {
33387
33711
  const kc = getAliasCount(doc, node2.key, anchors2);
33388
33712
  const vc = getAliasCount(doc, node2.value, anchors2);
@@ -36335,8 +36659,8 @@ var require_Document = __commonJS({
36335
36659
  };
36336
36660
  const res = toJS.toJS(this.contents, jsonArg ?? "", ctx);
36337
36661
  if (typeof onAnchor === "function")
36338
- for (const { count, res: res2 } of ctx.anchors.values())
36339
- onAnchor(res2, count);
36662
+ for (const { count: count2, res: res2 } of ctx.anchors.values())
36663
+ onAnchor(res2, count2);
36340
36664
  return typeof reviver === "function" ? applyReviver.applyReviver(reviver, { "": res }, "", res) : res;
36341
36665
  }
36342
36666
  /**
@@ -36413,12 +36737,12 @@ var require_errors = __commonJS({
36413
36737
  lineStr = prev + lineStr;
36414
36738
  }
36415
36739
  if (/[^ ]/.test(lineStr)) {
36416
- let count = 1;
36740
+ let count2 = 1;
36417
36741
  const end = error62.linePos[1];
36418
36742
  if (end?.line === line && end.col > col) {
36419
- count = Math.max(1, Math.min(end.col - col, 80 - ci));
36743
+ count2 = Math.max(1, Math.min(end.col - col, 80 - ci));
36420
36744
  }
36421
- const pointer = " ".repeat(ci) + "^".repeat(count);
36745
+ const pointer = " ".repeat(ci) + "^".repeat(count2);
36422
36746
  error62.message += `:
36423
36747
 
36424
36748
  ${lineStr}
@@ -36660,7 +36984,7 @@ var require_resolve_block_map = __commonJS({
36660
36984
  if (ctx.atRoot)
36661
36985
  ctx.atRoot = false;
36662
36986
  let offset = bm.offset;
36663
- let commentEnd = null;
36987
+ let commentEnd2 = null;
36664
36988
  for (const collItem of bm.items) {
36665
36989
  const { start, key, sep: sep4, value } = collItem;
36666
36990
  const keyProps = resolveProps.resolveProps(start, {
@@ -36680,7 +37004,7 @@ var require_resolve_block_map = __commonJS({
36680
37004
  onError(offset, "BAD_INDENT", startColMsg);
36681
37005
  }
36682
37006
  if (!keyProps.anchor && !keyProps.tag && !sep4) {
36683
- commentEnd = keyProps.end;
37007
+ commentEnd2 = keyProps.end;
36684
37008
  if (keyProps.comment) {
36685
37009
  if (map2.comment)
36686
37010
  map2.comment += "\n" + keyProps.comment;
@@ -36742,9 +37066,9 @@ var require_resolve_block_map = __commonJS({
36742
37066
  map2.items.push(pair);
36743
37067
  }
36744
37068
  }
36745
- if (commentEnd && commentEnd < offset)
36746
- onError(commentEnd, "IMPOSSIBLE", "Map comment with trailing content");
36747
- map2.range = [bm.offset, offset, commentEnd ?? offset];
37069
+ if (commentEnd2 && commentEnd2 < offset)
37070
+ onError(commentEnd2, "IMPOSSIBLE", "Map comment with trailing content");
37071
+ map2.range = [bm.offset, offset, commentEnd2 ?? offset];
36748
37072
  return map2;
36749
37073
  }
36750
37074
  exports2.resolveBlockMap = resolveBlockMap;
@@ -36766,7 +37090,7 @@ var require_resolve_block_seq = __commonJS({
36766
37090
  if (ctx.atKey)
36767
37091
  ctx.atKey = false;
36768
37092
  let offset = bs.offset;
36769
- let commentEnd = null;
37093
+ let commentEnd2 = null;
36770
37094
  for (const { start, value } of bs.items) {
36771
37095
  const props = resolveProps.resolveProps(start, {
36772
37096
  indicator: "seq-item-ind",
@@ -36783,7 +37107,7 @@ var require_resolve_block_seq = __commonJS({
36783
37107
  else
36784
37108
  onError(offset, "MISSING_CHAR", "Sequence item without - indicator");
36785
37109
  } else {
36786
- commentEnd = props.end;
37110
+ commentEnd2 = props.end;
36787
37111
  if (props.comment)
36788
37112
  seq.comment = props.comment;
36789
37113
  continue;
@@ -36795,7 +37119,7 @@ var require_resolve_block_seq = __commonJS({
36795
37119
  offset = node2.range[2];
36796
37120
  seq.items.push(node2);
36797
37121
  }
36798
- seq.range = [bs.offset, offset, commentEnd ?? offset];
37122
+ seq.range = [bs.offset, offset, commentEnd2 ?? offset];
36799
37123
  return seq;
36800
37124
  }
36801
37125
  exports2.resolveBlockSeq = resolveBlockSeq;
@@ -40032,8 +40356,8 @@ var require_dist = __commonJS({
40032
40356
  var init_dist = __esm({
40033
40357
  "../agent-core/dist/index.js"() {
40034
40358
  "use strict";
40035
- init_chunk_FYZKVT3E();
40036
- init_chunk_OUEMTEUX();
40359
+ init_chunk_N2M5D7RS();
40360
+ init_chunk_RBQC7XZH();
40037
40361
  init_chunk_ZCTKXKYY();
40038
40362
  init_chunk_6VWVDJ2A();
40039
40363
  init_chunk_YXWJW7I5();
@@ -40392,24 +40716,30 @@ function tokens(record2, ...keys) {
40392
40716
  }
40393
40717
  return void 0;
40394
40718
  }
40395
- function promptUsage(result, fallbackModel) {
40396
- const usage = asRecord(result.usage) ?? asRecord(result._meta);
40719
+ function contextOf(update) {
40720
+ const used = asFiniteNumber(update.used);
40721
+ const size = asFiniteNumber(update.size);
40722
+ if (used === void 0 || used <= 0) return void 0;
40723
+ return { contextTokens: used, ...size !== void 0 && size > 0 ? { contextSize: size } : {} };
40724
+ }
40725
+ function promptSpend(result, profile) {
40726
+ const meta3 = asRecord(result._meta);
40727
+ const usage = asRecord(result.usage) ?? asRecord(meta3?.usage) ?? meta3;
40397
40728
  const input2 = tokens(usage, "inputTokens", "input_tokens");
40398
40729
  const output2 = tokens(usage, "outputTokens", "output_tokens");
40399
40730
  if (input2 === void 0 && output2 === void 0) return void 0;
40400
40731
  const thoughts = tokens(usage, "thoughtTokens", "reasoningTokens") ?? 0;
40401
- const meta3 = asRecord(result._meta);
40402
- return usageUpdate(
40403
- {
40404
- inputTokens: input2 ?? 0,
40405
- outputTokens: (output2 ?? 0) + thoughts,
40406
- cacheReadTokens: tokens(usage, "cachedReadTokens", "cacheReadTokens") ?? 0,
40407
- cacheCreationTokens: tokens(usage, "cachedWriteTokens", "cacheWriteTokens") ?? 0,
40408
- costUsd: 0,
40409
- ...asString(meta3?.modelId) ? { model: asString(meta3?.modelId) } : {}
40410
- },
40411
- fallbackModel
40412
- );
40732
+ const cacheRead = tokens(usage, "cachedReadTokens", "cacheReadTokens") ?? 0;
40733
+ const cacheWrite = tokens(usage, "cachedWriteTokens", "cacheWriteTokens") ?? 0;
40734
+ const uncached = profile.promptInputIncludesCache ? Math.max((input2 ?? 0) - cacheRead - cacheWrite, 0) : input2 ?? 0;
40735
+ return {
40736
+ inputTokens: uncached,
40737
+ outputTokens: (output2 ?? 0) + thoughts,
40738
+ cacheReadTokens: cacheRead,
40739
+ cacheCreationTokens: cacheWrite,
40740
+ costUsd: 0,
40741
+ ...asString(meta3?.modelId) ? { model: asString(meta3?.modelId) } : {}
40742
+ };
40413
40743
  }
40414
40744
  function pendingAnswer2(pending, answer) {
40415
40745
  switch (pending.kind) {
@@ -40779,8 +41109,8 @@ var import_promises24, import_path10, import_crypto14, import_promises25, CURSOR
40779
41109
  var init_acp3 = __esm({
40780
41110
  "../agent-core/dist/providers/acp.js"() {
40781
41111
  "use strict";
40782
- init_chunk_FYZKVT3E();
40783
- init_chunk_OUEMTEUX();
41112
+ init_chunk_N2M5D7RS();
41113
+ init_chunk_RBQC7XZH();
40784
41114
  init_chunk_ZCTKXKYY();
40785
41115
  init_chunk_6VWVDJ2A();
40786
41116
  init_chunk_DLVRNIY5();
@@ -41010,9 +41340,52 @@ var init_acp3 = __esm({
41010
41340
  #bursts = /* @__PURE__ */ new Map();
41011
41341
  #counter = 0;
41012
41342
  #failure;
41013
- constructor(prefix, profile) {
41343
+ #context;
41344
+ #spend;
41345
+ #onContext;
41346
+ /** `context` is what the session's last turn left, until this turn reports its own. */
41347
+ constructor(prefix, profile, context) {
41014
41348
  this.#prefix = prefix;
41015
41349
  this.#profile = profile;
41350
+ this.#context = context;
41351
+ }
41352
+ get context() {
41353
+ return this.#context;
41354
+ }
41355
+ /** The prompt's answer: what the turn spent, with the context so far, as one update. */
41356
+ settle(result, fallbackModel) {
41357
+ this.#spend = promptSpend(result, this.#profile);
41358
+ return this.#usage(fallbackModel);
41359
+ }
41360
+ /** Resolves on the next `usage_update`, or after `ms`. */
41361
+ async nextContext(ms, sleep) {
41362
+ await Promise.race([
41363
+ new Promise((resolve8) => {
41364
+ this.#onContext = resolve8;
41365
+ }),
41366
+ sleep(ms)
41367
+ ]);
41368
+ this.#onContext = void 0;
41369
+ }
41370
+ /** Ends a `nextContext` wait at once: the turn is being cancelled. */
41371
+ stopWaiting() {
41372
+ this.#onContext?.();
41373
+ }
41374
+ /**
41375
+ * The chat keeps a turn's last usage update, so each one carries both the spend and the
41376
+ * context. An agent's own `usage_update` is context only and must not read as spend.
41377
+ */
41378
+ #noteContext(update) {
41379
+ const context = contextOf(update);
41380
+ if (!context) return [];
41381
+ this.#context = context;
41382
+ this.#onContext?.();
41383
+ const usage = this.#usage(this.#spend?.model ?? "");
41384
+ return usage ? [usage] : [];
41385
+ }
41386
+ #usage(fallbackModel) {
41387
+ if (!this.#spend && !this.#context) return void 0;
41388
+ return usageUpdate({ ...this.#spend, ...this.#context }, fallbackModel);
41016
41389
  }
41017
41390
  /** The first cause a vendor frame named; the prompt's own error is usually generic. */
41018
41391
  get failure() {
@@ -41042,6 +41415,8 @@ var init_acp3 = __esm({
41042
41415
  entries: Array.isArray(update.entries) ? update.entries : []
41043
41416
  }
41044
41417
  ];
41418
+ case "usage_update":
41419
+ return this.#noteContext(update);
41045
41420
  case "current_mode_update":
41046
41421
  return [
41047
41422
  noticeUpdate("info", "mode_changed", asString(update.currentModeId) || "mode changed")
@@ -41167,7 +41542,13 @@ var init_acp3 = __esm({
41167
41542
  return active.done;
41168
41543
  }
41169
41544
  const prompt = this.#promptBlocks(input2);
41170
- this.#rpc.request("session/prompt", { sessionId, prompt }).then((result) => active.finish(this.#promptOutcome(active, asRecord(result) ?? {}))).catch((error62) => {
41545
+ this.#rpc.request("session/prompt", { sessionId, prompt }).then(async (result) => {
41546
+ const record2 = asRecord(result) ?? {};
41547
+ const trailing = this.#profile.trailingUsageMs;
41548
+ if (trailing && !active.cancelRequested)
41549
+ await active.turn.nextContext(trailing, (ms) => this.#options.clock.sleep(ms));
41550
+ active.finish(this.#promptOutcome(active, record2));
41551
+ }).catch((error62) => {
41171
41552
  if (this.#state === "closed") return;
41172
41553
  active.finish(this.#errorOutcome(active, error62));
41173
41554
  });
@@ -41248,7 +41629,7 @@ var init_acp3 = __esm({
41248
41629
  ];
41249
41630
  }
41250
41631
  #promptOutcome(active, result) {
41251
- const usage = promptUsage(result, this.#config?.model ?? this.#profile.backendKind);
41632
+ const usage = active.turn.settle(result, this.#config?.model ?? this.#profile.backendKind);
41252
41633
  if (usage) this.#emit({ type: "update", turnId: active.id, update: usage });
41253
41634
  const stopReason = asString(result.stopReason);
41254
41635
  const failure22 = active.turn.failure;
@@ -41282,6 +41663,7 @@ var init_acp3 = __esm({
41282
41663
  async #stopTurn(active) {
41283
41664
  if (active.cancelRequested) return active.done.then(() => void 0);
41284
41665
  active.cancelRequested = true;
41666
+ active.turn.stopWaiting();
41285
41667
  const rung = await runCancelLadder({
41286
41668
  clock: this.#options.clock,
41287
41669
  graceMs: this.#options.interruptGraceMs,
@@ -41307,14 +41689,14 @@ var init_acp3 = __esm({
41307
41689
  }
41308
41690
  #startTurn(id) {
41309
41691
  this.#turns += 1;
41310
- const turn = new AcpTurn(`acp-${this.#turns}-${id}`, this.#profile);
41692
+ const turn = new AcpTurn(`acp-${this.#turns}-${id}`, this.#profile, this.#idleTurn.context);
41311
41693
  let finish = () => {
41312
41694
  };
41313
41695
  const done = new Promise((resolve8) => {
41314
41696
  finish = (outcome2) => {
41315
41697
  if (this.#current?.id !== id) return;
41316
41698
  this.#current = void 0;
41317
- this.#idleTurn = new AcpTurn(`acp-between-${this.#turns}`, this.#profile);
41699
+ this.#idleTurn = new AcpTurn(`acp-between-${this.#turns}`, this.#profile, turn.context);
41318
41700
  if (this.#state === "busy") this.#state = "idle";
41319
41701
  this.#host.scanDescendants(true);
41320
41702
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
@@ -41553,6 +41935,8 @@ var init_acp3 = __esm({
41553
41935
  }
41554
41936
  };
41555
41937
  grokAcpProfile = {
41938
+ // Grok's ACP `inputTokens` is the full prompt; its own docs say only headless output subtracts cache.
41939
+ promptInputIncludesCache: true,
41556
41940
  backendKind: "grok_cli",
41557
41941
  displayName: "Grok CLI",
41558
41942
  defaultCommand: "grok",
@@ -41583,7 +41967,9 @@ var init_acp3 = __esm({
41583
41967
  requirement: { cli: "kimi", feature: "`kimi acp`" },
41584
41968
  launchArgs: () => ["acp"],
41585
41969
  modelChannel: "session",
41586
- exitsOnStdinEof: true
41970
+ exitsOnStdinEof: true,
41971
+ // Kimi answers the prompt, then reads its context size and pushes `usage_update`.
41972
+ trailingUsageMs: 1e3
41587
41973
  };
41588
41974
  ACP_PROFILES = {
41589
41975
  cursor_agent_cli: cursorAcpProfile,
@@ -41817,9 +42203,19 @@ function createPersistentDriver(provider4, options) {
41817
42203
  }
41818
42204
  };
41819
42205
  const media = new LocalMediaReader(spec.projectPath, clock);
42206
+ const uploader = inputs.media;
42207
+ let uploads = Promise.resolve();
41820
42208
  const recordWithMedia = (update) => {
41821
42209
  record2(update);
41822
- for (const found of media.read(update)) record2(found);
42210
+ const found = media.find(update);
42211
+ if (found.length === 0) return;
42212
+ if (uploader === void 0) {
42213
+ for (const item of found) record2(media.inline(item));
42214
+ return;
42215
+ }
42216
+ uploads = uploads.then(async () => {
42217
+ for (const item of found) record2(await media.publish(item, uploader, signal));
42218
+ });
41823
42219
  };
41824
42220
  const forward = (event) => {
41825
42221
  if (event.type === "session_id") {
@@ -41913,6 +42309,7 @@ function createPersistentDriver(provider4, options) {
41913
42309
  } catch (error62) {
41914
42310
  return { outcome: "failed", message: errorMessage(error62) };
41915
42311
  } finally {
42312
+ await uploads;
41916
42313
  signal.removeEventListener("abort", onAbort);
41917
42314
  if (live.turn === turn) live.turn = void 0;
41918
42315
  }
@@ -42409,8 +42806,22 @@ function codeModeChildUpdates(tool, metadata) {
42409
42806
  };
42410
42807
  });
42411
42808
  }
42809
+ function stepContextTokens(step, total) {
42810
+ const sum = step.inputTokens + step.outputTokens + step.cacheReadTokens + step.cacheCreationTokens;
42811
+ const tokens2 = total !== void 0 && total > 0 ? total : sum;
42812
+ return tokens2 > 0 ? tokens2 : void 0;
42813
+ }
42814
+ function addStepUsage(turn, step) {
42815
+ return {
42816
+ inputTokens: turn.inputTokens + step.inputTokens,
42817
+ outputTokens: turn.outputTokens + step.outputTokens,
42818
+ cacheReadTokens: turn.cacheReadTokens + step.cacheReadTokens,
42819
+ cacheCreationTokens: turn.cacheCreationTokens + step.cacheCreationTokens,
42820
+ costUsd: turn.costUsd === void 0 && step.costUsd === void 0 ? void 0 : (turn.costUsd ?? 0) + (step.costUsd ?? 0)
42821
+ };
42822
+ }
42412
42823
  function createOpenCodeSessionMemory() {
42413
- return { userMessageIds: /* @__PURE__ */ new Set() };
42824
+ return { userMessageIds: /* @__PURE__ */ new Set(), contextWindows: /* @__PURE__ */ new Map() };
42414
42825
  }
42415
42826
  function only(updates) {
42416
42827
  return { updates, actions: [] };
@@ -42743,12 +43154,12 @@ function openCodeTurnInput(run, context) {
42743
43154
  ...images.length ? { imagePaths: images.map((image) => image.path) } : {}
42744
43155
  };
42745
43156
  }
42746
- var import_crypto15, import_http4, import_crypto16, import_promises26, import_path11, import_path12, import_url2, import_crypto17, IDLE_SOCKET_MS2, OpenCodeHttpError, BASE62, messageIdClock, OpenCodeClient, OPENCODE_CONFIG_ENV, OPENCODE_ENGINE, TEXT_PARTS, STEP_PARTS, STOPPED_BY_USER, OpenCodeSubagents, NAMED_KINDS, OPENCODE_ABORTED_ERROR, PROVIDER_EVENT_META, TASK_TOOL_NAME, TASK_RESULT_TAG, TASK_ERROR_TAG, PERMISSION_DENIED, FILE_OPERATIONS, PartReader, NOTHING, NON_INTERACTIVE_PERMISSIONS, CONTENT_FILTER_FINISHES, TRUNCATED_FINISHES, OUTPUT_PARTS, OpenCodeTurn, LISTENING, OUTPUT_TAIL_LINES, IMAGE_TYPES, OpenCodeSession, OPENCODE_MIN_VERSION, OPENCODE_REQUIREMENT, OPENCODE_TESTED_LINE, OPENCODE_SUPPORTED_MAJOR, DEFAULTS4, STORE_LOCKED, NON_INTERACTIVE_RULES, TITLE_LENGTH, MAX_VARIANT_LENGTH;
43157
+ var import_crypto15, import_http4, import_crypto16, import_promises26, import_path11, import_path12, import_url2, import_crypto17, IDLE_SOCKET_MS2, OpenCodeHttpError, BASE62, messageIdClock, OpenCodeClient, OPENCODE_CONFIG_ENV, OPENCODE_ENGINE, TEXT_PARTS, STEP_PARTS, STOPPED_BY_USER, OpenCodeSubagents, NAMED_KINDS, OPENCODE_ABORTED_ERROR, PROVIDER_EVENT_META, TASK_TOOL_NAME, TASK_RESULT_TAG, TASK_ERROR_TAG, PERMISSION_DENIED, FILE_OPERATIONS, NO_USAGE, PartReader, NOTHING, NON_INTERACTIVE_PERMISSIONS, CONTENT_FILTER_FINISHES, TRUNCATED_FINISHES, OUTPUT_PARTS, OpenCodeTurn, LISTENING, OUTPUT_TAIL_LINES, IMAGE_TYPES, OpenCodeSession, OPENCODE_MIN_VERSION, OPENCODE_REQUIREMENT, OPENCODE_TESTED_LINE, OPENCODE_SUPPORTED_MAJOR, DEFAULTS4, STORE_LOCKED, NON_INTERACTIVE_RULES, TITLE_LENGTH, MAX_VARIANT_LENGTH;
42747
43158
  var init_opencode = __esm({
42748
43159
  "../agent-core/dist/providers/opencode.js"() {
42749
43160
  "use strict";
42750
- init_chunk_FYZKVT3E();
42751
- init_chunk_OUEMTEUX();
43161
+ init_chunk_N2M5D7RS();
43162
+ init_chunk_RBQC7XZH();
42752
43163
  init_chunk_ZCTKXKYY();
42753
43164
  init_chunk_6VWVDJ2A();
42754
43165
  init_chunk_DLVRNIY5();
@@ -42930,6 +43341,22 @@ var init_opencode = __esm({
42930
43341
  const providers = Array.isArray(body?.providers) ? body.providers : [];
42931
43342
  return providers.map((provider4) => asString(asRecord(provider4)?.id)).filter(Boolean);
42932
43343
  }
43344
+ /** `provider/model` \u2192 the model's context limit; 0 (a custom model's unknown) is left out. */
43345
+ async modelContextWindows() {
43346
+ const body = asRecord(await this.#call("provider list", "GET", "/config/providers"));
43347
+ const windows = /* @__PURE__ */ new Map();
43348
+ for (const provider4 of Array.isArray(body?.providers) ? body.providers : []) {
43349
+ const record2 = asRecord(provider4);
43350
+ const providerId = asString(record2?.id);
43351
+ for (const [modelId, model] of Object.entries(asRecord(record2?.models) ?? {})) {
43352
+ const limit = asFiniteNumber(asRecord(asRecord(model)?.limit)?.context);
43353
+ if (providerId && limit !== void 0 && limit > 0) {
43354
+ windows.set(`${providerId}/${modelId}`, limit);
43355
+ }
43356
+ }
43357
+ }
43358
+ return windows;
43359
+ }
42933
43360
  /** Asks emitted while disconnected must still get a reply. Older engines may lack these routes. */
42934
43361
  async pendingAsks() {
42935
43362
  const read = async (path, type) => {
@@ -43161,6 +43588,13 @@ var init_opencode = __esm({
43161
43588
  ["delete", "delete"],
43162
43589
  ["update", "modify"]
43163
43590
  ]);
43591
+ NO_USAGE = {
43592
+ inputTokens: 0,
43593
+ outputTokens: 0,
43594
+ cacheReadTokens: 0,
43595
+ cacheCreationTokens: 0,
43596
+ costUsd: void 0
43597
+ };
43164
43598
  PartReader = class {
43165
43599
  /** messageID \u2192 part ids in arrival order, so a multi-part message keeps its order. */
43166
43600
  #order = /* @__PURE__ */ new Map();
@@ -43170,6 +43604,7 @@ var init_opencode = __esm({
43170
43604
  /** To-do calls already sent as a plan; the running and completed frames repeat the input. */
43171
43605
  #planned = /* @__PURE__ */ new Set();
43172
43606
  #steps = /* @__PURE__ */ new Set();
43607
+ #turnUsage = NO_USAGE;
43173
43608
  #partIds = /* @__PURE__ */ new Set();
43174
43609
  #anonymous = 0;
43175
43610
  #retainedChars = 0;
@@ -43184,6 +43619,9 @@ var init_opencode = __esm({
43184
43619
  }
43185
43620
  /** `provider/model` from the assistant message; step-finish frames do not repeat it. */
43186
43621
  model;
43622
+ /** The model's context limit, when the server listed it. */
43623
+ contextWindow;
43624
+ #contextTokens;
43187
43625
  part(part, parentToolCallId) {
43188
43626
  const id = asString(part.id);
43189
43627
  if (id) this.#partIds.add(id);
@@ -43192,7 +43630,7 @@ var init_opencode = __esm({
43192
43630
  "protocol_violation",
43193
43631
  "Alan Code exceeded the retained event limit. Continue in a new turn."
43194
43632
  );
43195
- return withParent(this.#read(part), parentToolCallId);
43633
+ return withParent(this.#read(part, parentToolCallId !== void 0), parentToolCallId);
43196
43634
  }
43197
43635
  /** A delta names only its part; the role and message come from the part's opening snapshot. */
43198
43636
  delta(partId, field2, delta, parentToolCallId) {
@@ -43204,7 +43642,7 @@ var init_opencode = __esm({
43204
43642
  const update = role === "text" ? { sessionUpdate: "agent_message_chunk", messageId, content } : { sessionUpdate: "agent_thought_chunk", messageId: `${messageId}:reasoning`, content };
43205
43643
  return withParent([update], parentToolCallId);
43206
43644
  }
43207
- #read(part) {
43645
+ #read(part, child) {
43208
43646
  const type = asString(part.type);
43209
43647
  switch (type) {
43210
43648
  case "step-start":
@@ -43220,7 +43658,7 @@ var init_opencode = __esm({
43220
43658
  return this.#tool(part);
43221
43659
  case "step-finish":
43222
43660
  case "step_finish":
43223
- return this.#stepFinish(part);
43661
+ return this.#stepFinish(part, child);
43224
43662
  case "snapshot":
43225
43663
  case "patch":
43226
43664
  return [];
@@ -43286,6 +43724,31 @@ var init_opencode = __esm({
43286
43724
  }
43287
43725
  return updates;
43288
43726
  }
43727
+ #stepUsage(part, tokens2, child) {
43728
+ const cache = asRecord(tokens2.cache);
43729
+ const step = {
43730
+ inputTokens: asFiniteNumber(tokens2.input) ?? 0,
43731
+ // OpenCode counts reasoning apart from output, and cache apart from input.
43732
+ outputTokens: (asFiniteNumber(tokens2.output) ?? 0) + (asFiniteNumber(tokens2.reasoning) ?? 0),
43733
+ cacheReadTokens: asFiniteNumber(cache?.read) ?? 0,
43734
+ cacheCreationTokens: asFiniteNumber(cache?.write) ?? 0
43735
+ };
43736
+ if (!child) this.#contextTokens = stepContextTokens(step, asFiniteNumber(tokens2.total));
43737
+ this.#turnUsage = addStepUsage(this.#turnUsage, {
43738
+ ...step,
43739
+ costUsd: asFiniteNumber(part.cost)
43740
+ });
43741
+ const { costUsd, ...turnTokens } = this.#turnUsage;
43742
+ return usageUpdate(
43743
+ {
43744
+ ...turnTokens,
43745
+ ...costUsd === void 0 ? {} : { costUsd },
43746
+ ...this.#contextTokens === void 0 ? {} : { contextTokens: this.#contextTokens },
43747
+ ...this.contextWindow === void 0 ? {} : { contextSize: this.contextWindow }
43748
+ },
43749
+ this.model
43750
+ );
43751
+ }
43289
43752
  /** OpenCode's to-do list is the plan, sent once per call although every frame repeats it. */
43290
43753
  #plan(toolCallId, name, toolState) {
43291
43754
  const todos = asRecord(toolState?.input)?.todos;
@@ -43294,28 +43757,12 @@ var init_opencode = __esm({
43294
43757
  this.#planned.add(toolCallId);
43295
43758
  return [todoPlanUpdate(toolCallId, todos)];
43296
43759
  }
43297
- #stepFinish(part) {
43760
+ #stepFinish(part, child) {
43298
43761
  const id = asString(part.id);
43299
43762
  if (id && this.#steps.has(id)) return [];
43300
43763
  if (id) this.#steps.add(id);
43301
- const updates = [];
43302
43764
  const tokens2 = asRecord(part.tokens);
43303
- if (tokens2) {
43304
- const cache = asRecord(tokens2.cache);
43305
- const cost = asFiniteNumber(part.cost);
43306
- updates.push(
43307
- usageUpdate(
43308
- {
43309
- inputTokens: asFiniteNumber(tokens2.input) ?? 0,
43310
- outputTokens: asFiniteNumber(tokens2.output) ?? 0,
43311
- cacheReadTokens: asFiniteNumber(cache?.read) ?? 0,
43312
- cacheCreationTokens: asFiniteNumber(cache?.write) ?? 0,
43313
- ...cost === void 0 ? {} : { costUsd: cost }
43314
- },
43315
- this.model
43316
- )
43317
- );
43318
- }
43765
+ const updates = tokens2 ? [this.#stepUsage(part, tokens2, child)] : [];
43319
43766
  const reason = asString(part.reason);
43320
43767
  if (reason === "stop") {
43321
43768
  updates.push({ sessionUpdate: "state_update", state: "idle", stopReason: "end_turn" });
@@ -43500,7 +43947,10 @@ var init_opencode = __esm({
43500
43947
  if (finish) this.#finish = finish;
43501
43948
  const provider4 = asString(info.providerID);
43502
43949
  const model = asString(info.modelID);
43503
- if (provider4 && model) this.#parts.model = `${provider4}/${model}`;
43950
+ if (provider4 && model) {
43951
+ this.#parts.model = `${provider4}/${model}`;
43952
+ this.#parts.contextWindow = this.#memory.contextWindows.get(this.#parts.model);
43953
+ }
43504
43954
  const error62 = asRecord(info.error);
43505
43955
  if (!error62 || isAbortError(error62) || this.#error) return [];
43506
43956
  return this.#fail(classifyOpenCodeError(error62, `${this.#engine.label} session error.`));
@@ -43705,6 +44155,9 @@ var init_opencode = __esm({
43705
44155
  /** Subscribes before the session exists, so `session.created` and early asks are seen. */
43706
44156
  async connect(client) {
43707
44157
  this.#client = client;
44158
+ client.modelContextWindows().then((windows) => {
44159
+ this.#memory.contextWindows = windows;
44160
+ }).catch(() => void 0);
43708
44161
  this.#events?.close();
43709
44162
  this.#events = await client.events({
43710
44163
  onEvent: (event) => {
@@ -44113,7 +44566,9 @@ function createAlanCodeHolderDriver(options) {
44113
44566
  });
44114
44567
  const env = options.cliEnvironment;
44115
44568
  const engine = resolveAlanCodeEngine({ env, platform, packaged: [] });
44116
- const engineRoot = alanCodeEngineRoot(env.HOME?.trim() || (0, import_node_os3.homedir)());
44569
+ const home = env.HOME?.trim() || (0, import_node_os3.homedir)();
44570
+ const engineRoot = alanCodeEngineRoot(home);
44571
+ const globalConfigDirectory = openCodeGlobalConfigDirectory(env, home);
44117
44572
  options.log.info("alan_code.engine", { command: engine.command, source: engine.source });
44118
44573
  const open4 = async (planned) => {
44119
44574
  if (planned.profile === void 0) throw refuseWithoutCredential();
@@ -44151,6 +44606,7 @@ function createAlanCodeHolderDriver(options) {
44151
44606
  conversationId: spec.conversationId
44152
44607
  },
44153
44608
  engineRoot,
44609
+ globalConfigDirectory,
44154
44610
  requestedModel: spec.model
44155
44611
  };
44156
44612
  const skills = options.installedSkills?.() ?? null;
@@ -44798,8 +45254,8 @@ var import_crypto18, import_promises27, FACTORY_API_VERSION, FACTORY_PROTOCOL_VE
44798
45254
  var init_droid = __esm({
44799
45255
  "../agent-core/dist/providers/droid.js"() {
44800
45256
  "use strict";
44801
- init_chunk_FYZKVT3E();
44802
- init_chunk_OUEMTEUX();
45257
+ init_chunk_N2M5D7RS();
45258
+ init_chunk_RBQC7XZH();
44803
45259
  init_chunk_ZCTKXKYY();
44804
45260
  init_chunk_6VWVDJ2A();
44805
45261
  init_chunk_DLVRNIY5();
@@ -44844,7 +45300,10 @@ var init_droid = __esm({
44844
45300
  const notification = asRecord(params.notification);
44845
45301
  if (!notification) return [];
44846
45302
  const sessionId = asString(params.sessionId);
44847
- if (!sessionId || sessionId === this.#sessionId) return this.#read(notification);
45303
+ if (!sessionId || sessionId === this.#sessionId) {
45304
+ this.#noteContext(notification);
45305
+ return this.#read(notification);
45306
+ }
44848
45307
  const launcher = this.#memory.childLaunchers.get(sessionId);
44849
45308
  if (!launcher) return [];
44850
45309
  return this.#read(notification).map(
@@ -44854,6 +45313,14 @@ var init_droid = __esm({
44854
45313
  })
44855
45314
  );
44856
45315
  }
45316
+ /** Droid's own context figure: the last call's input, cache reads and output. */
45317
+ #noteContext(notification) {
45318
+ if (asString(notification.type) !== "session_token_usage_changed") return;
45319
+ const last = asRecord(notification.lastCallTokenUsage);
45320
+ if (!last) return;
45321
+ const tokens2 = (asFiniteNumber(last.inputTokens) ?? 0) + (asFiniteNumber(last.cacheReadTokens) ?? 0) + (asFiniteNumber(last.outputTokens) ?? 0);
45322
+ if (tokens2 > 0) this.#memory.contextTokens = tokens2;
45323
+ }
44857
45324
  #read(notification) {
44858
45325
  const type = asString(notification.type);
44859
45326
  if (SILENT2.has(type)) return [];
@@ -44928,6 +45395,7 @@ var init_droid = __esm({
44928
45395
  cacheCreationTokens: number4(usage?.cacheCreationTokens),
44929
45396
  numTurns: 1,
44930
45397
  ...duration3 === void 0 ? {} : { durationMs: duration3 },
45398
+ ...this.#memory.contextTokens === void 0 ? {} : { contextTokens: this.#memory.contextTokens },
44931
45399
  costUsd: 0
44932
45400
  },
44933
45401
  this.#memory.model ?? "droid"
@@ -45736,6 +46204,23 @@ function providerError(_grammar, frame) {
45736
46204
  function spellings(types, handle) {
45737
46205
  return types.map((type) => [type, handle]);
45738
46206
  }
46207
+ function stepTokens(stats) {
46208
+ return {
46209
+ inputTokens: firstNumber2(stats.input_tokens, stats.input),
46210
+ outputTokens: firstNumber2(stats.output_tokens) + firstNumber2(stats.thinking_tokens),
46211
+ cacheReadTokens: firstNumber2(stats.cache_read_tokens, stats.cached_input_tokens, stats.cached),
46212
+ cacheCreationTokens: 0
46213
+ };
46214
+ }
46215
+ function addStepTokens(total, step) {
46216
+ if (!total) return step;
46217
+ return {
46218
+ inputTokens: total.inputTokens + step.inputTokens,
46219
+ outputTokens: total.outputTokens + step.outputTokens,
46220
+ cacheReadTokens: total.cacheReadTokens + step.cacheReadTokens,
46221
+ cacheCreationTokens: total.cacheCreationTokens + step.cacheCreationTokens
46222
+ };
46223
+ }
45739
46224
  function firstNumber2(...values) {
45740
46225
  for (const value of values) {
45741
46226
  const number4 = asFiniteNumber(value);
@@ -45907,9 +46392,9 @@ var import_promises28, import_path13, import_fs9, import_path14, import_path15,
45907
46392
  var init_antigravity = __esm({
45908
46393
  "../agent-core/dist/providers/antigravity.js"() {
45909
46394
  "use strict";
45910
- init_chunk_D4TIXPWZ();
45911
- init_chunk_FYZKVT3E();
45912
- init_chunk_OUEMTEUX();
46395
+ init_chunk_TFIO37PI();
46396
+ init_chunk_N2M5D7RS();
46397
+ init_chunk_RBQC7XZH();
45913
46398
  init_chunk_ZCTKXKYY();
45914
46399
  init_chunk_6VWVDJ2A();
45915
46400
  init_chunk_DLVRNIY5();
@@ -46267,6 +46752,11 @@ var init_antigravity = __esm({
46267
46752
  /** What `--conversation` takes: a frame's `conversation_id` wins over its `session_id`. */
46268
46753
  #conversationId;
46269
46754
  #forkReported = false;
46755
+ /** The conversation this turn runs in; a subagent's steps come under another id. */
46756
+ #rootConversation;
46757
+ /** The sum of this turn's own steps: the result's usage is the whole conversation's. */
46758
+ #stepSpend;
46759
+ #contextTokens;
46270
46760
  constructor(options) {
46271
46761
  this.#options = options;
46272
46762
  this.#conversationId = options.resumeId;
@@ -46313,7 +46803,9 @@ var init_antigravity = __esm({
46313
46803
  const type = asString(frame.type);
46314
46804
  if (!type) return [];
46315
46805
  this.#conversationId = antigravityString(frame, "conversation_id") ?? antigravityString(frame, "session_id") ?? this.#conversationId;
46806
+ this.#rootConversation ??= this.#conversationId;
46316
46807
  this.#track(type, frame);
46808
+ this.#noteStep(type, frame);
46317
46809
  const forked = this.#silentFork();
46318
46810
  if (SESSION_START_TYPES.has(type)) {
46319
46811
  return [
@@ -46328,6 +46820,29 @@ var init_antigravity = __esm({
46328
46820
  if (RESULT_TYPES.has(type)) return [...forked, ...this.#onResult(type, frame)];
46329
46821
  return [...forked, ...this.#transcripts?.read() ?? []];
46330
46822
  }
46823
+ /** A finished answer step of this conversation: one model call, with its own usage. */
46824
+ #noteStep(type, frame) {
46825
+ if (type !== "assistant_message" || asString(frame.state).toUpperCase() !== "DONE") return;
46826
+ const usage = asRecord(frame.usage);
46827
+ if (!usage) return;
46828
+ const conversation = antigravityString(frame, "conversation_id");
46829
+ if (conversation && this.#rootConversation && conversation !== this.#rootConversation) return;
46830
+ const step = stepTokens(usage);
46831
+ this.#stepSpend = addStepTokens(this.#stepSpend, step);
46832
+ const context = step.inputTokens + step.cacheReadTokens + step.outputTokens;
46833
+ if (context > 0) this.#contextTokens = context;
46834
+ }
46835
+ /**
46836
+ * agy's result usage is cumulative over the conversation, so a resumed turn's spend comes
46837
+ * from its steps; a first turn's result is its own.
46838
+ */
46839
+ #turnSpend(frame) {
46840
+ const steps = this.#stepSpend;
46841
+ this.#stepSpend = void 0;
46842
+ if (steps) return steps;
46843
+ if (this.#options.resumeId) return void 0;
46844
+ return stepTokens(asRecord(frame.usage) ?? asRecord(frame.stats) ?? frame);
46845
+ }
46331
46846
  #track(type, frame) {
46332
46847
  const transcripts = this.#transcripts;
46333
46848
  if (!transcripts) return;
@@ -46345,6 +46860,22 @@ var init_antigravity = __esm({
46345
46860
  this.#forkReported = true;
46346
46861
  return [noticeUpdate("warning", "session_resume_failed", RESUME_FORKED)];
46347
46862
  }
46863
+ #resultUsage(frame) {
46864
+ const spend = this.#turnSpend(frame);
46865
+ const contextTokens = this.#contextTokens;
46866
+ if (!spend && contextTokens === void 0) return [];
46867
+ const stats = asRecord(frame.usage) ?? asRecord(frame.stats) ?? frame;
46868
+ return [
46869
+ usageUpdate({
46870
+ model: formatAntigravityModelName(this.#model()),
46871
+ numTurns: Math.max(this.#iterations, 1),
46872
+ durationMs: asFiniteNumber(stats.duration_ms) ?? 0,
46873
+ ...spend,
46874
+ ...contextTokens === void 0 ? {} : { contextTokens },
46875
+ costUsd: 0
46876
+ })
46877
+ ];
46878
+ }
46348
46879
  #onResult(type, frame) {
46349
46880
  const updates = [];
46350
46881
  this.#iterations = Math.max(this.#iterations, asFiniteNumber(frame.num_turns) ?? 1);
@@ -46353,23 +46884,7 @@ var init_antigravity = __esm({
46353
46884
  updates.push(agentText(`antigravity-${this.#conversationId ?? "run"}-result`, resultText2));
46354
46885
  this.#resultShown = true;
46355
46886
  }
46356
- const stats = asRecord(frame.usage) ?? asRecord(frame.stats) ?? frame;
46357
- updates.push(
46358
- usageUpdate({
46359
- model: formatAntigravityModelName(this.#model()),
46360
- numTurns: Math.max(this.#iterations, 1),
46361
- durationMs: asFiniteNumber(stats.duration_ms) ?? 0,
46362
- inputTokens: firstNumber2(stats.input_tokens, stats.input),
46363
- outputTokens: firstNumber2(stats.output_tokens),
46364
- cacheReadTokens: firstNumber2(
46365
- stats.cache_read_tokens,
46366
- stats.cached_input_tokens,
46367
- stats.cached
46368
- ),
46369
- cacheCreationTokens: 0,
46370
- costUsd: 0
46371
- })
46372
- );
46887
+ updates.push(...this.#resultUsage(frame));
46373
46888
  const status = asString(frame.status).toLowerCase();
46374
46889
  const succeeded = !status || SUCCESSFUL_STATUSES.has(status);
46375
46890
  if (succeeded) {
@@ -46612,8 +47127,8 @@ var import_promises29, import_path16, import_crypto20, COMMAND_CODE_GRAMMAR_NAME
46612
47127
  var init_command_code = __esm({
46613
47128
  "../agent-core/dist/providers/command-code.js"() {
46614
47129
  "use strict";
46615
- init_chunk_FYZKVT3E();
46616
- init_chunk_OUEMTEUX();
47130
+ init_chunk_N2M5D7RS();
47131
+ init_chunk_RBQC7XZH();
46617
47132
  init_chunk_ZCTKXKYY();
46618
47133
  init_chunk_6VWVDJ2A();
46619
47134
  init_chunk_DLVRNIY5();
@@ -46978,6 +47493,7 @@ var init_command_code = __esm({
46978
47493
  #streamed = false;
46979
47494
  #totals;
46980
47495
  #result;
47496
+ #contextTokens;
46981
47497
  constructor(options) {
46982
47498
  this.#options = options;
46983
47499
  if (options.resumeId) this.#grammar.sessionId = options.resumeId;
@@ -47020,6 +47536,8 @@ var init_command_code = __esm({
47020
47536
  #onEvent(event) {
47021
47537
  switch (commandCodeString(event.type)) {
47022
47538
  case "model_request_end":
47539
+ this.#noteContext(event.usage);
47540
+ return this.#usage(event.usage);
47023
47541
  case "turn_end":
47024
47542
  return this.#usage(event.usage);
47025
47543
  case "run_end": {
@@ -47071,7 +47589,28 @@ var init_command_code = __esm({
47071
47589
  durationMs: durationMs ?? previous?.durationMs ?? 0
47072
47590
  };
47073
47591
  this.#totals = totals;
47074
- return [usageUpdate({ model: this.#model(), numTurns: 1, ...totals, costUsd: 0 })];
47592
+ return [
47593
+ usageUpdate({
47594
+ model: this.#model(),
47595
+ numTurns: 1,
47596
+ ...totals,
47597
+ // Command Code's own cost estimate takes cache out of inputTokens, which counts it.
47598
+ inputTokens: Math.max(
47599
+ totals.inputTokens - totals.cacheReadTokens - totals.cacheCreationTokens,
47600
+ 0
47601
+ ),
47602
+ ...this.#contextTokens === void 0 ? {} : { contextTokens: this.#contextTokens },
47603
+ costUsd: 0
47604
+ })
47605
+ ];
47606
+ }
47607
+ /** One model call's prompt, cache included, plus its reply: what it left in the window. */
47608
+ #noteContext(usage) {
47609
+ const record2 = asRecord(usage);
47610
+ const input2 = asFiniteNumber(record2?.inputTokens) ?? asFiniteNumber(record2?.input_tokens);
47611
+ if (input2 === void 0 || input2 <= 0) return;
47612
+ const output2 = asFiniteNumber(record2?.outputTokens) ?? asFiniteNumber(record2?.output_tokens);
47613
+ this.#contextTokens = input2 + (output2 ?? 0);
47075
47614
  }
47076
47615
  };
47077
47616
  COMMAND_CODE_MAX_TURNS = 1e4;
@@ -47577,6 +48116,7 @@ function createHttpTransport() {
47577
48116
  init_runtime_v2();
47578
48117
  init_zod();
47579
48118
  var REQUEST_TIMEOUT_MS = 3e4;
48119
+ var MEDIA_PUT_TIMEOUT_MS = 3e5;
47580
48120
  var credentialRefusalSchema = external_exports.object({ message: external_exports.string().trim().min(1) });
47581
48121
  function credentialFailureMessage(response, fallback) {
47582
48122
  if (response.status !== 409) return fallback;
@@ -47645,6 +48185,33 @@ function createHolderApiClient({
47645
48185
  throw new RuntimeFault("io_failed", `MCP credential request failed: ${response.status}`);
47646
48186
  }
47647
48187
  return machineMcpCredentialSchema.parse(jsonBody(response));
48188
+ },
48189
+ uploadRunMedia: async (runId, media, data, signal) => {
48190
+ const reserved = await request2("POST", runMediaPath(runId), signal, media);
48191
+ if (!isOk(reserved)) {
48192
+ throw new RuntimeFault("io_failed", `Media upload request failed: ${reserved.status}`);
48193
+ }
48194
+ const reservation = runMediaUploadResponseSchema.parse(jsonBody(reserved));
48195
+ if (reservation.status === "ready") return;
48196
+ const stored = await transport.send({
48197
+ method: "PUT",
48198
+ url: new URL(reservation.upload.url),
48199
+ headers: {
48200
+ ...reservation.upload.headers,
48201
+ "content-length": String(data.byteLength)
48202
+ },
48203
+ body: data,
48204
+ redirect: "error",
48205
+ signal: AbortSignal.any([signal, AbortSignal.timeout(MEDIA_PUT_TIMEOUT_MS)])
48206
+ });
48207
+ if (!isOk(stored)) {
48208
+ throw new RuntimeFault("io_failed", `Media upload failed: ${stored.status}`);
48209
+ }
48210
+ const completed = await request2("POST", runMediaCompletePath(runId, media.mediaId), signal);
48211
+ if (!isOk(completed)) {
48212
+ throw new RuntimeFault("io_failed", `Media upload completion failed: ${completed.status}`);
48213
+ }
48214
+ runMediaCompleteResponseSchema.parse(jsonBody(completed));
47648
48215
  }
47649
48216
  };
47650
48217
  }
@@ -48317,6 +48884,7 @@ function runtimePaths(stateDir) {
48317
48884
 
48318
48885
  // src/platform/process-memory.ts
48319
48886
  var import_node_child_process4 = require("child_process");
48887
+ var import_node_fs6 = require("fs");
48320
48888
  var import_promises12 = require("fs/promises");
48321
48889
  var import_node_os2 = require("os");
48322
48890
  var import_node_util3 = require("util");
@@ -48356,6 +48924,45 @@ async function readProcessRss(pid) {
48356
48924
  return null;
48357
48925
  }
48358
48926
  }
48927
+ function parseDarwinVmStat(output2) {
48928
+ const pageSize = Number(/page size of (\d+) bytes/.exec(output2)?.[1]);
48929
+ if (!Number.isFinite(pageSize) || pageSize <= 0) return null;
48930
+ const pages = (name) => {
48931
+ const match = new RegExp(`^Pages ${name}:\\s+(\\d+)\\.?$`, "m").exec(output2);
48932
+ return match ? Number(match[1]) : null;
48933
+ };
48934
+ const free = pages("free");
48935
+ if (free === null) return null;
48936
+ return (free + (pages("inactive") ?? 0) + (pages("speculative") ?? 0)) * pageSize;
48937
+ }
48938
+ function parseLinuxMemInfo(output2) {
48939
+ const kilobytes = /^MemAvailable:\s+(\d+)\s+kB$/m.exec(output2)?.[1];
48940
+ return kilobytes === void 0 ? null : Number(kilobytes) * 1024;
48941
+ }
48942
+ var CAPACITY_PROBE_TTL_MS = 2e3;
48943
+ var AvailableMemoryProbe = class {
48944
+ cached = null;
48945
+ read(now) {
48946
+ if (this.cached !== null && now - this.cached.at < CAPACITY_PROBE_TTL_MS) {
48947
+ return this.cached.bytes;
48948
+ }
48949
+ let bytes = null;
48950
+ try {
48951
+ if (process.platform === "darwin") {
48952
+ bytes = parseDarwinVmStat(
48953
+ (0, import_node_child_process4.execFileSync)("vm_stat", { encoding: "utf8", timeout: PROBE_TIMEOUT_MS })
48954
+ );
48955
+ } else if (process.platform === "linux") {
48956
+ bytes = parseLinuxMemInfo((0, import_node_fs6.readFileSync)("/proc/meminfo", "utf8"));
48957
+ }
48958
+ } catch {
48959
+ bytes = null;
48960
+ }
48961
+ this.cached = { at: now, bytes };
48962
+ return bytes;
48963
+ }
48964
+ };
48965
+ var availableMemoryProbe = new AvailableMemoryProbe();
48359
48966
  async function processMemoryRows() {
48360
48967
  if (process.platform === "win32") {
48361
48968
  const { stdout: stdout2 } = await execFileAsync3(
@@ -48456,7 +49063,7 @@ var systemExec = (request2) => new Promise((resolve8) => {
48456
49063
  init_alan_code();
48457
49064
 
48458
49065
  // src/capabilities/providers/commands.ts
48459
- var import_node_fs6 = require("fs");
49066
+ var import_node_fs7 = require("fs");
48460
49067
  var import_promises17 = require("fs/promises");
48461
49068
  var import_node_path9 = require("path");
48462
49069
  var PROVIDER_COMMANDS = [
@@ -48494,7 +49101,7 @@ function pathDelimiter(platform) {
48494
49101
  async function isRunnable(path, platform) {
48495
49102
  try {
48496
49103
  if (!(await (0, import_promises17.stat)(path)).isFile()) return false;
48497
- if (platform !== "win32") await (0, import_promises17.access)(path, import_node_fs6.constants.X_OK);
49104
+ if (platform !== "win32") await (0, import_promises17.access)(path, import_node_fs7.constants.X_OK);
48498
49105
  return true;
48499
49106
  } catch {
48500
49107
  return false;
@@ -49144,7 +49751,7 @@ async function inspectIndexedSkill(directory, contentHash) {
49144
49751
 
49145
49752
  // src/capabilities/skills/native-index.ts
49146
49753
  var import_node_crypto10 = require("crypto");
49147
- var import_node_fs7 = require("fs");
49754
+ var import_node_fs8 = require("fs");
49148
49755
  var import_promises21 = require("fs/promises");
49149
49756
  var import_node_path13 = require("path");
49150
49757
  var ALAN_SKILLS_PLUGIN_NAME = "alan";
@@ -49158,7 +49765,7 @@ var PLUGIN_MANIFEST = `${JSON.stringify(
49158
49765
  )}
49159
49766
  `;
49160
49767
  function installedSkillFolders(layout) {
49161
- return (0, import_node_fs7.existsSync)((0, import_node_path13.join)(layout.pluginDir, ".claude-plugin", "plugin.json")) ? { pluginDir: layout.pluginDir, skillsDir: layout.pluginSkillsDir } : null;
49768
+ return (0, import_node_fs8.existsSync)((0, import_node_path13.join)(layout.pluginDir, ".claude-plugin", "plugin.json")) ? { pluginDir: layout.pluginDir, skillsDir: layout.pluginSkillsDir } : null;
49162
49769
  }
49163
49770
 
49164
49771
  // src/capabilities/workspace/index.ts
@@ -49725,6 +50332,13 @@ function attachmentPath(spec, attachment, index, runDir) {
49725
50332
  }
49726
50333
  return (0, import_node_path19.join)(runDir, `${index}-${safeFilename(attachment.filename)}`);
49727
50334
  }
50335
+ function runMediaUploader(source, runId) {
50336
+ const upload = source.uploadMedia?.bind(source);
50337
+ if (upload === void 0) return void 0;
50338
+ return {
50339
+ upload: ({ data, ...media }, signal) => upload(runId, { ...media, bytes: data.byteLength }, data, signal)
50340
+ };
50341
+ }
49728
50342
  async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
49729
50343
  const dir = (0, import_node_path19.join)(tmpDir, "runs", spec.runId);
49730
50344
  const cleanup = async () => {
@@ -49751,9 +50365,11 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
49751
50365
  ...attachment.height === void 0 ? {} : { height: attachment.height }
49752
50366
  });
49753
50367
  }
50368
+ const media = runMediaUploader(source, spec.runId);
49754
50369
  return {
49755
50370
  attachments,
49756
50371
  providerEnv: credential.env,
50372
+ ...media === void 0 ? {} : { media },
49757
50373
  ...credential.codex === void 0 ? {} : { codex: credential.codex },
49758
50374
  skills,
49759
50375
  [Symbol.asyncDispose]: cleanup
@@ -49766,20 +50382,20 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
49766
50382
 
49767
50383
  // src/holder/serve.ts
49768
50384
  var import_node_crypto15 = require("crypto");
49769
- var import_node_fs11 = require("fs");
50385
+ var import_node_fs12 = require("fs");
49770
50386
  var import_node_net2 = require("net");
49771
50387
  var import_node_path29 = require("path");
49772
50388
  init_runtime_v2();
49773
50389
 
49774
50390
  // src/holder/admission.ts
49775
- var import_node_fs9 = require("fs");
50391
+ var import_node_fs10 = require("fs");
49776
50392
  var import_promises35 = require("fs/promises");
49777
50393
  var import_node_os6 = require("os");
49778
50394
  var import_node_path25 = require("path");
49779
50395
  init_constants();
49780
50396
 
49781
50397
  // ../shared/dist/node/local-workspace.js
49782
- var import_node_fs8 = require("fs");
50398
+ var import_node_fs9 = require("fs");
49783
50399
  var import_node_os5 = require("os");
49784
50400
  var import_node_path20 = require("path");
49785
50401
  function resolveAlanDefaultWorkspacePath(homeDirectory = (0, import_node_os5.homedir)()) {
@@ -50199,7 +50815,7 @@ async function inspectReadiness(path) {
50199
50815
  if (!(await (0, import_promises35.stat)(path)).isDirectory()) {
50200
50816
  return { ready: false, missing: true, message: MESSAGES.missing };
50201
50817
  }
50202
- await (0, import_promises35.access)(path, import_node_fs9.constants.R_OK | import_node_fs9.constants.W_OK | import_node_fs9.constants.X_OK);
50818
+ await (0, import_promises35.access)(path, import_node_fs10.constants.R_OK | import_node_fs10.constants.W_OK | import_node_fs10.constants.X_OK);
50203
50819
  return { ready: true };
50204
50820
  } catch (error62) {
50205
50821
  const code = errnoCode(error62) ?? "";
@@ -50244,7 +50860,7 @@ async function admitDefaultWorkspace(spec, context, skills) {
50244
50860
  const path = resolveAlanDefaultWorkspacePath(env.HOME || env.USERPROFILE || (0, import_node_os6.homedir)());
50245
50861
  try {
50246
50862
  await (0, import_promises35.mkdir)(path, { recursive: true, mode: 448 });
50247
- await (0, import_promises35.access)(path, import_node_fs9.constants.R_OK | import_node_fs9.constants.W_OK | import_node_fs9.constants.X_OK);
50863
+ await (0, import_promises35.access)(path, import_node_fs10.constants.R_OK | import_node_fs10.constants.W_OK | import_node_fs10.constants.X_OK);
50248
50864
  return { kind: "admitted", spec: { ...spec, projectPath: path }, skills };
50249
50865
  } catch (error62) {
50250
50866
  const code = errnoCode(error62);
@@ -50583,13 +51199,13 @@ function runEnded(input2) {
50583
51199
  var decoder = new TextDecoder();
50584
51200
 
50585
51201
  // src/run-log/writer.ts
50586
- var import_node_fs10 = require("fs");
51202
+ var import_node_fs11 = require("fs");
50587
51203
  var import_node_path28 = require("path");
50588
51204
  init_runtime_v2();
50589
51205
  function lastSeq(fd, size) {
50590
51206
  for (const length of tailWindows(size)) {
50591
51207
  const buffer = Buffer.alloc(length);
50592
- (0, import_node_fs10.readSync)(fd, buffer, 0, length, size - length);
51208
+ (0, import_node_fs11.readSync)(fd, buffer, 0, length, size - length);
50593
51209
  const last = lastLine(buffer.toString("utf8").trimEnd(), length === size);
50594
51210
  if (last === void 0) continue;
50595
51211
  if (last.length === 0) return 0;
@@ -50600,13 +51216,13 @@ function lastSeq(fd, size) {
50600
51216
  throw new RuntimeFault("record_too_large", "Run log tail record is larger than any record");
50601
51217
  }
50602
51218
  function openRunLog(path, clock) {
50603
- (0, import_node_fs10.mkdirSync)((0, import_node_path28.dirname)(path), { recursive: true, mode: 448 });
50604
- const fd = (0, import_node_fs10.openSync)(path, "a+", 384);
50605
- let size = (0, import_node_fs10.fstatSync)(fd).size;
51219
+ (0, import_node_fs11.mkdirSync)((0, import_node_path28.dirname)(path), { recursive: true, mode: 448 });
51220
+ const fd = (0, import_node_fs11.openSync)(path, "a+", 384);
51221
+ let size = (0, import_node_fs11.fstatSync)(fd).size;
50606
51222
  let seq = lastSeq(fd, size);
50607
51223
  let dirty = false;
50608
51224
  const sync = () => {
50609
- (0, import_node_fs10.fsyncSync)(fd);
51225
+ (0, import_node_fs11.fsyncSync)(fd);
50610
51226
  dirty = false;
50611
51227
  };
50612
51228
  return {
@@ -50620,7 +51236,7 @@ function openRunLog(path, clock) {
50620
51236
  };
50621
51237
  const line = Buffer.from(`${JSON.stringify(record2)}
50622
51238
  `, "utf8");
50623
- (0, import_node_fs10.writeSync)(fd, line);
51239
+ (0, import_node_fs11.writeSync)(fd, line);
50624
51240
  size += line.length;
50625
51241
  dirty = true;
50626
51242
  if (isRunLifecycleKind(update.sessionUpdate)) sync();
@@ -50632,7 +51248,7 @@ function openRunLog(path, clock) {
50632
51248
  },
50633
51249
  [Symbol.dispose]: () => {
50634
51250
  if (dirty) sync();
50635
- (0, import_node_fs10.closeSync)(fd);
51251
+ (0, import_node_fs11.closeSync)(fd);
50636
51252
  }
50637
51253
  };
50638
51254
  }
@@ -51076,7 +51692,7 @@ async function runHolder({
51076
51692
  for (const client of holder.clients) client.end();
51077
51693
  await new Promise((resolve8) => server.close(() => resolve8()));
51078
51694
  await statusWrites;
51079
- (0, import_node_fs11.rmSync)(launch.statusPath, { force: true });
51695
+ (0, import_node_fs12.rmSync)(launch.statusPath, { force: true });
51080
51696
  log.info("holder.suspended", { conversationId: launch.conversationId });
51081
51697
  } catch (_) {
51082
51698
  var _error = _, _hasError = true;
@@ -51087,6 +51703,7 @@ async function runHolder({
51087
51703
 
51088
51704
  // src/sessions/suspend-policy.ts
51089
51705
  var GIB = 1024 ** 3;
51706
+ var SESSION_MEMORY_CEILING_BYTES = 2.5 * GIB;
51090
51707
  var MEMORY_BUDGET_SHARE = 0.15;
51091
51708
  var MEMORY_BUDGET_MIN_BYTES = GIB;
51092
51709
  var MEMORY_BUDGET_MAX_BYTES = 4 * GIB;
@@ -51115,7 +51732,8 @@ var envSchema = external_exports.object({
51115
51732
  ALAN_RUNTIME_LOG_LEVEL: external_exports.enum(["debug", "info", "warn", "error"]).default("info"),
51116
51733
  ALAN_RUNTIME_SUSPEND_IDLE_MS: external_exports.coerce.number().int().positive().optional(),
51117
51734
  ALAN_RUNTIME_SUSPEND_CHECK_MS: external_exports.coerce.number().int().positive().default(3e4),
51118
- ALAN_RUNTIME_DESIRED_RESYNC_MS: external_exports.coerce.number().int().positive().default(6e5),
51735
+ // A two-minute conditional GET bounds recovery after a lost poke; unchanged state returns 304.
51736
+ ALAN_RUNTIME_DESIRED_RESYNC_MS: external_exports.coerce.number().int().positive().default(12e4),
51119
51737
  ALAN_MAX_ACTIVE_RUNS: external_exports.coerce.number().int().optional(),
51120
51738
  ALAN_RUNTIME_API_URL: external_exports.url().optional(),
51121
51739
  ALAN_RUNTIME_CREDENTIAL_STORE: external_exports.enum(CREDENTIAL_STORE_KINDS).optional(),
@@ -51362,7 +51980,8 @@ async function machineAccess(paths, log, conversationId, transport) {
51362
51980
  fetchProviderCredential: async (runId, signal) => {
51363
51981
  void managedMcp?.authorization(signal);
51364
51982
  return (await api()).fetchProviderCredential(runId, signal);
51365
- }
51983
+ },
51984
+ uploadMedia: async (runId, media, data, signal) => (await api()).uploadRunMedia(runId, media, data, signal)
51366
51985
  };
51367
51986
  const codexCredentials = {
51368
51987
  refresh: async (runId, rejectedAccessTokenSha256) => (await api()).refreshCodexCredential(