@alan-ai-hq/agent-manager-darwin-arm64 0.1.157 → 0.1.158

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 +353 -177
  2. package/alan-holder.cjs +323 -174
  3. package/package.json +1 -1
package/alan-agent.cjs CHANGED
@@ -23396,6 +23396,7 @@ If a needed tool is not exposed, use the host's tool-discovery mechanism once wh
23396
23396
  Whatever the intent, check your draft before sending: three or more numbers being compared, several items sharing the same attributes, a sequence, or two or more options means it should be visual. Stay in plain text for one-line facts, yes/no answers, clarifying questions, conversation, and short summaries of code you just changed. Lead with one sentence, show one visual (two at most), then stop; the visual carries the detail, so do not repeat it in prose.
23397
23397
  - Examples of plain questions with visual answers: "Which queue should the importer use, BullMQ or SQS?" \u2192 a one-line recommendation, then \`\`\`openui Tabs with a KeyValue of cost, latency and ops effort per option and a Callout with the pick. "Why did last night's deploy fail?" \u2192 a one-sentence cause, then Steps with the failed step and its detail, then Code with the error. "How's the test suite doing?" \u2192 a row of Stat (passed, failed, flaky) and a line \`\`\`chart of failures per day.
23398
23398
  - \`\`\`mermaid renders in chat, documents, plans and artifacts too; \`\`\`openui renders only in your replies in the Alan chat. In Slack or Teams messages, commit messages, pull request bodies and files, use plain Markdown instead.
23399
+ - When you compose a plan, test report, review or document to save as an Alan artifact, use the \`alan-artifact\` skill for its structure and any HTML or interactive block, and \`alan-diagrams\` for its Mermaid diagrams.
23399
23400
  - \`\`\`chart renders in chat, documents, plans and artifacts, and is **strict JSON, nothing else**:
23400
23401
  \`\`\`chart
23401
23402
  { "type": "bar", "title": "Quarterly Revenue", "data": [{ "name": "Q1", "revenue": 4000 }, { "name": "Q2", "revenue": 3000 }] }
@@ -23442,7 +23443,7 @@ Team
23442
23443
  - When a user asks to create a Skill, default to a team-owned Alan platform Skill through \`alan-skill-authoring\`, whether this session runs locally or in a cloud sandbox. Use a repository or filesystem Skill only when the user explicitly requests that scope. Do not infer repository scope from the current checkout or from a procedure that mentions repository files. If repeated work suggests a reusable Skill, offer the platform Skill and its evidence; do not publish it without the approval required by the authoring workflow.
23443
23444
  - Own mistakes. Wrong ID, jumped too fast \u2014 say so and fix it.
23444
23445
  - When writing code, work like a senior engineer: understand the existing design and conventions, make the smallest coherent change that solves the request, and keep related logic together. Reuse an existing abstraction when it fits; remove duplication that the change would otherwise introduce, but do not refactor unrelated code or add speculative abstractions. Keep names, types, error handling, and tests clear enough for the next engineer to maintain. Review the diff for accidental changes before calling the work done.
23445
- - Write for a human reader. Task, subtask and epic descriptions, documents, artifacts and comments are read by people in the app, not parsed by agents. Lead with the outcome in one sentence, then short sections with headings and bullet lists. Spell out internal shorthand, and keep commit hashes, IDs and migration numbers out of sentences \u2014 put them in a trailing "References" list when they matter.
23446
+ - Write for a human reader. Task, subtask and epic descriptions, documents, artifacts and comments are read by people in the app, not parsed by agents. Lead with the outcome in one sentence, then short sections with headings and bullet lists when there is enough to organise. Size it to what is actually known: a task written from someone's request restates that request and never adds repro steps, causes, verification or acceptance criteria nobody stated. Spell out internal shorthand, and keep commit hashes, IDs and migration numbers out of sentences \u2014 put them in a trailing "References" list when they matter.
23446
23447
  ${ALAN_VISUAL_PROMPT}
23447
23448
  - Images you generate or edit appear in the chat automatically, the way ChatGPT shows them. Do not link, embed, or print the generated file's path afterwards, and do not announce "Generated:" or "Edited image:" \u2014 at most one short sentence about the result. Mention a path only when the user asked for the file to be saved into the project.
23448
23449
 
@@ -25871,7 +25872,9 @@ function prepareConversationTurns(transcript, streaming, previousTurns = []) {
25871
25872
  }
25872
25873
  const tail = turn.working.reduce((latest, node2) => !latest || (node2.event.seq ?? node2.event.line) > (latest.event.seq ?? latest.event.line) ? node2 : latest, void 0);
25873
25874
  turn.working = turn.working.filter((node2) => !isThought(node2));
25874
- const final = turn.activity.state === "idle" && (!turn.activity.stopReason || turn.activity.stopReason === "end_turn" || turn.activity.stopReason === "cancelled") && tail?.event.update.sessionUpdate === "agent_message" && hasAnswerContent(tail) ? tail : void 0;
25875
+ const lastStarted = turn.working.at(-1);
25876
+ const answerTail = [tail, lastStarted].find((node2) => node2?.event.update.sessionUpdate === "agent_message" && hasAnswerContent(node2));
25877
+ const final = turn.activity.state === "idle" && (!turn.activity.stopReason || turn.activity.stopReason === "end_turn" || turn.activity.stopReason === "cancelled") ? answerTail : void 0;
25875
25878
  if (final)
25876
25879
  turn.final = final;
25877
25880
  }
@@ -26135,10 +26138,34 @@ function noticeKind(severity, meta3) {
26135
26138
  const kind = meta3?.["alan.dev/noticeKind"];
26136
26139
  return typeof kind === "string" ? kind : severity;
26137
26140
  }
26141
+ function isTextBlock(block2) {
26142
+ return block2.type === "text";
26143
+ }
26144
+ function restatesDispatchFailure(state, update) {
26145
+ if (!isUpdate(update, "agent_message"))
26146
+ return false;
26147
+ if (!update.messageId.endsWith(IMPORTED_CONTENT_SUFFIX))
26148
+ return false;
26149
+ const blocks = Array.isArray(update.content) ? update.content : [];
26150
+ if (blocks.length === 0 || !blocks.every(isTextBlock))
26151
+ return false;
26152
+ const text3 = blocks.map((block2) => block2.text).join("").trim();
26153
+ if (!text3)
26154
+ return false;
26155
+ const index = state.notices.findIndex((notice3) => notice3.kind === "application_problem" && notice3.message.trim() === text3);
26156
+ if (index < 0)
26157
+ return false;
26158
+ const notice2 = state.notices[index];
26159
+ if (notice2.level !== "error")
26160
+ state.notices[index] = { ...notice2, level: "error" };
26161
+ return true;
26162
+ }
26138
26163
  function applyContent(state, index, update) {
26139
26164
  const role = ROLE_BY_KIND[update.sessionUpdate];
26140
26165
  if (!role)
26141
26166
  return;
26167
+ if (restatesDispatchFailure(state, update))
26168
+ return;
26142
26169
  const key = `m:${role}:${update.messageId}`;
26143
26170
  let entry = index.get(key);
26144
26171
  if (!entry) {
@@ -26228,7 +26255,7 @@ function applyTool(state, index, update) {
26228
26255
  function messageText2(entry) {
26229
26256
  return entry.content.filter((b) => b.type === "text").map((b) => b.text).join("");
26230
26257
  }
26231
- var ROLE_BY_KIND, entryIndexes, AWAITING_TOOL_CALLS_META, SETTLED;
26258
+ var ROLE_BY_KIND, entryIndexes, AWAITING_TOOL_CALLS_META, IMPORTED_CONTENT_SUFFIX, SETTLED;
26232
26259
  var init_reduce = __esm({
26233
26260
  "../shared/dist/agent/acp/reduce.js"() {
26234
26261
  "use strict";
@@ -26244,6 +26271,7 @@ var init_reduce = __esm({
26244
26271
  };
26245
26272
  entryIndexes = /* @__PURE__ */ new WeakMap();
26246
26273
  AWAITING_TOOL_CALLS_META = "alan.dev/awaitingToolCallIds";
26274
+ IMPORTED_CONTENT_SUFFIX = ":content";
26247
26275
  SETTLED = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
26248
26276
  }
26249
26277
  });
@@ -26735,6 +26763,13 @@ var init_read = __esm({
26735
26763
  }
26736
26764
  });
26737
26765
 
26766
+ // ../shared/dist/agent/acp/session-activity.js
26767
+ var init_session_activity = __esm({
26768
+ "../shared/dist/agent/acp/session-activity.js"() {
26769
+ "use strict";
26770
+ }
26771
+ });
26772
+
26738
26773
  // ../shared/dist/agent/acp/transcript-byte-decoder.js
26739
26774
  var init_transcript_byte_decoder = __esm({
26740
26775
  "../shared/dist/agent/acp/transcript-byte-decoder.js"() {
@@ -26929,6 +26964,7 @@ var init_acp = __esm({
26929
26964
  init_types3();
26930
26965
  init_read();
26931
26966
  init_reduce();
26967
+ init_session_activity();
26932
26968
  init_transcript_byte_decoder();
26933
26969
  init_transcript_fold();
26934
26970
  init_transcript_http();
@@ -27987,7 +28023,7 @@ var init_chunk_ZCTKXKYY = __esm({
27987
28023
  }
27988
28024
  });
27989
28025
 
27990
- // ../agent-core/dist/chunk-ILZBXGVI.js
28026
+ // ../agent-core/dist/chunk-FYZKVT3E.js
27991
28027
  function detectImageMimeType(buffer) {
27992
28028
  if (buffer.length >= 8 && buffer.subarray(0, 8).equals(PNG_SIGNATURE)) return "image/png";
27993
28029
  if (buffer.length >= 3 && buffer[0] === 255 && buffer[1] === 216 && buffer[2] === 255) {
@@ -28084,21 +28120,38 @@ function imageDimensions(buffer, mimeType) {
28084
28120
  if (mimeType === "image/jpeg") return jpegDimensions(buffer);
28085
28121
  return { width: null, height: null };
28086
28122
  }
28087
- function readMediaFiles(candidates2, cwd, mimeByExt, maxBytes) {
28123
+ function readMediaFiles(query) {
28088
28124
  const seen = /* @__PURE__ */ new Set();
28089
28125
  const files = [];
28090
- for (const candidate of candidates2) {
28091
- const path4 = normalizePath(candidate, cwd);
28126
+ for (const candidate of query.candidates) {
28127
+ const path4 = normalizePath(candidate, query.cwd);
28092
28128
  if (!path4 || seen.has(path4) || !(0, import_fs5.existsSync)(path4)) continue;
28093
28129
  seen.add(path4);
28094
- const mimeType = mimeByExt[(0, import_path4.extname)(path4).toLowerCase()];
28130
+ const mimeType = query.mimeByExt[(0, import_path4.extname)(path4).toLowerCase()];
28095
28131
  if (!mimeType) continue;
28096
28132
  const stat22 = (0, import_fs5.statSync)(path4);
28097
- if (!stat22.isFile() || stat22.size <= 0 || stat22.size > maxBytes) continue;
28133
+ if (!stat22.isFile() || stat22.size <= 0 || stat22.size > query.maxBytes) continue;
28134
+ if (stat22.mtimeMs < query.writtenSince && !query.named.has(path4)) continue;
28098
28135
  files.push({ path: path4, mimeType, buffer: (0, import_fs5.readFileSync)(path4) });
28099
28136
  }
28100
28137
  return files;
28101
28138
  }
28139
+ function isCaptureTool(tool) {
28140
+ return isBrowserScreenshotToolName(tool.name) || isBrowserRecordingToolName(tool.name);
28141
+ }
28142
+ function runsCaptureCommand(tool) {
28143
+ return someString(tool.input, (text3) => AGENT_BROWSER_CAPTURE_COMMAND.test(text3));
28144
+ }
28145
+ function capturePaths(tool, content, extensions, cwd) {
28146
+ const values = isCaptureTool(tool) ? contentStrings(content, tool.input) : runsCaptureCommand(tool) ? contentStrings("", tool.input) : [];
28147
+ return pathCandidates(values, extensions).flatMap((candidate) => {
28148
+ const path4 = normalizePath(candidate, cwd);
28149
+ return path4 ? [path4] : [];
28150
+ });
28151
+ }
28152
+ function base64Length(bytes) {
28153
+ return Math.ceil(bytes / 3) * 4;
28154
+ }
28102
28155
  function resultText2(update) {
28103
28156
  const only2 = isJsonRecord(update._meta) ? update._meta[TOOL_RESULT_ONLY_META] : void 0;
28104
28157
  if (typeof only2 === "string") return only2;
@@ -28389,9 +28442,9 @@ function silentStartError(name, timeoutMs) {
28389
28442
  message: `${name} printed nothing for ${seconds}s after it started and was stopped. Send your message again.`
28390
28443
  };
28391
28444
  }
28392
- 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, AGENT_BROWSER_MENTION, LocalMediaReader, SessionOpenRefusal, JsonRpcError, ACP_PROTOCOL_VERSION, ACP_ERROR, STDERR_TAIL_LINES, RESULT_EXIT_GRACE_MS, PerTurnSession;
28393
- var init_chunk_ILZBXGVI = __esm({
28394
- "../agent-core/dist/chunk-ILZBXGVI.js"() {
28445
+ 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;
28446
+ var init_chunk_FYZKVT3E = __esm({
28447
+ "../agent-core/dist/chunk-FYZKVT3E.js"() {
28395
28448
  "use strict";
28396
28449
  init_chunk_OUEMTEUX();
28397
28450
  init_chunk_ZCTKXKYY();
@@ -28419,12 +28472,16 @@ var init_chunk_ILZBXGVI = __esm({
28419
28472
  VIDEO_EXTENSIONS = "mp4|webm|mov";
28420
28473
  MAX_IMAGE_BYTES = 20 * 1024 * 1024;
28421
28474
  MAX_VIDEO_BYTES = 100 * 1024 * 1024;
28475
+ MAX_TURN_MEDIA_DATA_CHARS = 8 * 1024 * 1024;
28476
+ MTIME_SLACK_MS = 2e3;
28422
28477
  AGENT_BROWSER_MENTION = /agent[-_]browser/i;
28478
+ AGENT_BROWSER_CAPTURE_COMMAND = /(?:^|[\s/])agent[-_]browser(?:@[^\s;&|]+)?(?:\s[^\n;&|]*?)?\s(?:screenshot|record)(?=\s|$)/im;
28423
28479
  LocalMediaReader = class {
28424
28480
  #cwd;
28425
28481
  #clock;
28426
28482
  #tools = /* @__PURE__ */ new Map();
28427
28483
  #pathHints = /* @__PURE__ */ new Set();
28484
+ #mediaDataChars = 0;
28428
28485
  constructor(cwd, clock) {
28429
28486
  this.#cwd = cwd;
28430
28487
  this.#clock = clock;
@@ -28449,7 +28506,11 @@ var init_chunk_ILZBXGVI = __esm({
28449
28506
  /** A recording names its output file when it starts; the stop's result may not repeat it. */
28450
28507
  #announce(toolCallId, name, input2) {
28451
28508
  const known = this.#tools.get(toolCallId);
28452
- const tool = { name: name ?? known?.name ?? "", input: input2 ?? known?.input };
28509
+ const tool = {
28510
+ name: name ?? known?.name ?? "",
28511
+ input: input2 ?? known?.input,
28512
+ startedAt: known?.startedAt ?? this.#clock.now()
28513
+ };
28453
28514
  this.#tools.set(toolCallId, tool);
28454
28515
  if (!isAgentBrowserMedia(tool, "", "video")) return;
28455
28516
  const cwd = toolCwd(this.#cwd, tool.input);
@@ -28458,13 +28519,30 @@ var init_chunk_ILZBXGVI = __esm({
28458
28519
  if (path4) this.#pathHints.add(path4);
28459
28520
  }
28460
28521
  }
28461
- #payloadFields(file2, toolId) {
28522
+ /** Media written before the call started is old, unless its capture command named it. */
28523
+ #toolFiles(tool, content, extensions, limits) {
28524
+ const cwd = toolCwd(this.#cwd, tool.input);
28525
+ return readMediaFiles({
28526
+ ...limits,
28527
+ candidates: [
28528
+ ...pathCandidates(contentStrings(content, tool.input), extensions),
28529
+ ...this.#pathHints
28530
+ ],
28531
+ cwd,
28532
+ writtenSince: tool.startedAt - MTIME_SLACK_MS,
28533
+ named: /* @__PURE__ */ new Set([...capturePaths(tool, content, extensions, cwd), ...this.#pathHints])
28534
+ });
28535
+ }
28536
+ #payloadFields(file2, toolId, explicit) {
28537
+ const dataChars = base64Length(file2.buffer.length);
28538
+ const inline = explicit || this.#mediaDataChars + dataChars <= MAX_TURN_MEDIA_DATA_CHARS;
28539
+ if (inline) this.#mediaDataChars += dataChars;
28462
28540
  return {
28463
28541
  id: (0, import_crypto4.randomUUID)(),
28464
28542
  filename: (0, import_path4.basename)(file2.path),
28465
28543
  mimeType: file2.mimeType,
28466
28544
  size: file2.buffer.length,
28467
- data: file2.buffer.toString("base64"),
28545
+ ...inline ? { data: file2.buffer.toString("base64") } : { inlineDataOmitted: true },
28468
28546
  sourcePath: file2.path,
28469
28547
  sourceHash: (0, import_crypto4.createHash)("sha256").update(file2.buffer).digest("hex"),
28470
28548
  toolId,
@@ -28473,15 +28551,14 @@ var init_chunk_ILZBXGVI = __esm({
28473
28551
  }
28474
28552
  #generatedImages(toolId, tool, content) {
28475
28553
  if (!isGeneratedImageToolName(tool.name)) return [];
28476
- const candidates2 = [
28477
- ...pathCandidates(contentStrings(content, tool.input), IMAGE_EXTENSIONS),
28478
- ...this.#pathHints
28479
- ];
28480
- const cwd = toolCwd(this.#cwd, tool.input);
28481
- return readMediaFiles(candidates2, cwd, IMAGE_MIME_BY_EXT, MAX_IMAGE_BYTES).map((file2) => {
28554
+ const files = this.#toolFiles(tool, content, IMAGE_EXTENSIONS, {
28555
+ mimeByExt: IMAGE_MIME_BY_EXT,
28556
+ maxBytes: MAX_IMAGE_BYTES
28557
+ });
28558
+ return files.map((file2) => {
28482
28559
  const image = {
28483
28560
  type: "generated_image",
28484
- ...this.#payloadFields(file2, toolId),
28561
+ ...this.#payloadFields(file2, toolId, true),
28485
28562
  ...imageDimensions(file2.buffer, file2.mimeType)
28486
28563
  };
28487
28564
  return { sessionUpdate: "_alan/generated_image", image };
@@ -28491,25 +28568,19 @@ var init_chunk_ILZBXGVI = __esm({
28491
28568
  const isVideo = isAgentBrowserMedia(tool, content, "video");
28492
28569
  if (!isVideo && !isAgentBrowserMedia(tool, content, "image")) return [];
28493
28570
  const kind = isVideo ? "video" : "image";
28494
- const candidates2 = [
28495
- ...pathCandidates(
28496
- contentStrings(content, tool.input),
28497
- isVideo ? VIDEO_EXTENSIONS : IMAGE_EXTENSIONS
28498
- ),
28499
- ...this.#pathHints
28500
- ];
28501
- const files = readMediaFiles(
28502
- candidates2,
28503
- toolCwd(this.#cwd, tool.input),
28504
- isVideo ? VIDEO_MIME_BY_EXT : IMAGE_MIME_BY_EXT,
28505
- isVideo ? MAX_VIDEO_BYTES : MAX_IMAGE_BYTES
28571
+ const explicit = isCaptureTool(tool) || runsCaptureCommand(tool);
28572
+ const files = this.#toolFiles(
28573
+ tool,
28574
+ content,
28575
+ isVideo ? VIDEO_EXTENSIONS : IMAGE_EXTENSIONS,
28576
+ isVideo ? { mimeByExt: VIDEO_MIME_BY_EXT, maxBytes: MAX_VIDEO_BYTES } : { mimeByExt: IMAGE_MIME_BY_EXT, maxBytes: MAX_IMAGE_BYTES }
28506
28577
  );
28507
28578
  return files.map((file2) => {
28508
28579
  this.#pathHints.delete(file2.path);
28509
28580
  const media = {
28510
28581
  type: "session_media",
28511
28582
  kind,
28512
- ...this.#payloadFields(file2, toolId),
28583
+ ...this.#payloadFields(file2, toolId, explicit),
28513
28584
  ...kind === "image" ? imageDimensions(file2.buffer, file2.mimeType) : {}
28514
28585
  };
28515
28586
  return { sessionUpdate: "_alan/session_media", media };
@@ -28741,128 +28812,6 @@ var init_chunk_ILZBXGVI = __esm({
28741
28812
  }
28742
28813
  });
28743
28814
 
28744
- // ../agent-core/dist/chunk-J2KTV5FP.js
28745
- function selectExternalMcpServers(spec) {
28746
- const isWorkflow = Boolean(spec.workflowId || spec.workflowExecutionId);
28747
- const filter = isWorkflow ? createWorkflowToolsFilter(spec.workflowTools) : null;
28748
- if (filter && !filter.hasFilter) return {};
28749
- const selected = {};
28750
- for (const [name, server] of Object.entries(spec.externalMcpServers ?? {})) {
28751
- if (!isExternalMcpServerName(name)) continue;
28752
- if (filter && !filter.isMcpServerAllowed(name)) continue;
28753
- selected[name] = server;
28754
- }
28755
- return selected;
28756
- }
28757
- function headerEnvName(server, header) {
28758
- const fingerprint = (0, import_crypto5.createHash)("sha256").update(`${server}\0${header}`).digest("hex").slice(0, 12);
28759
- return `ALAN_MCP_HEADER_${fingerprint.toUpperCase()}`;
28760
- }
28761
- function deliverRemote(name, server, env) {
28762
- const headerEnv = {};
28763
- for (const [header, value2] of Object.entries(server.headers ?? {})) {
28764
- if (!isMcpConfigKey(header)) continue;
28765
- const variable = headerEnvName(name, header);
28766
- env[variable] = value2;
28767
- headerEnv[header] = variable;
28768
- }
28769
- return {
28770
- type: server.type === "sse" ? "sse" : "http",
28771
- url: server.url,
28772
- ...Object.keys(headerEnv).length ? { headerEnv } : {}
28773
- };
28774
- }
28775
- function deliverStdio(server, cliEnv, delivery) {
28776
- const envKeys = [];
28777
- for (const [key, value2] of Object.entries(server.env ?? {})) {
28778
- if (!isMcpConfigKey(key)) continue;
28779
- if (key in cliEnv || key in delivery.env && delivery.env[key] !== value2) {
28780
- delivery.skippedEnvKeys.push(key);
28781
- continue;
28782
- }
28783
- delivery.env[key] = value2;
28784
- envKeys.push(key);
28785
- }
28786
- return {
28787
- type: "stdio",
28788
- command: server.command,
28789
- ...server.args?.length ? { args: server.args } : {},
28790
- ...envKeys.length ? { envKeys } : {}
28791
- };
28792
- }
28793
- function planExternalMcpDelivery(spec, cliEnv) {
28794
- const delivery = { servers: {}, env: {}, skippedEnvKeys: [] };
28795
- for (const [name, server] of Object.entries(selectExternalMcpServers(spec))) {
28796
- const { url: url3, command } = server;
28797
- if (url3 && server.type !== "stdio") {
28798
- delivery.servers[name] = deliverRemote(name, { ...server, url: url3 }, delivery.env);
28799
- } else if (command) {
28800
- delivery.servers[name] = deliverStdio({ ...server, command }, cliEnv, delivery);
28801
- }
28802
- }
28803
- return delivery;
28804
- }
28805
- function envReference(name) {
28806
- return `\${${name}}`;
28807
- }
28808
- function managedMcpHeaders(identity) {
28809
- if (identity.scope === "run") {
28810
- return {
28811
- Authorization: envReference(ALAN_MCP_AUTHORIZATION_ENV),
28812
- [MANAGED_MCP_RUN_HEADER]: envReference(ALAN_RUN_ID_ENV)
28813
- };
28814
- }
28815
- return {
28816
- ...identity.authorization === void 0 ? {} : { Authorization: identity.authorization },
28817
- [MANAGED_MCP_CONVERSATION_HEADER]: identity.conversationId
28818
- };
28819
- }
28820
- function credentialDigest(authorization) {
28821
- if (authorization === void 0) return void 0;
28822
- return (0, import_crypto6.createHash)("sha256").update(authorization).digest("hex").slice(0, 16);
28823
- }
28824
- function canonicalizeManagedMcpServerName(serverName) {
28825
- return RUN_SCOPED_SERVER.test(serverName) ? MANAGED_MCP_SERVER_NAME : serverName;
28826
- }
28827
- function canonicalizeManagedMcpToolName(toolName2) {
28828
- const namespaced = NAMESPACED_RUN_TOOL.exec(toolName2);
28829
- if (namespaced) return `mcp__${MANAGED_MCP_SERVER_NAME}__${namespaced[2]}`;
28830
- const flattened = FLATTENED_RUN_TOOL.exec(toolName2);
28831
- return flattened ? `mcp__${MANAGED_MCP_SERVER_NAME}__${flattened[1]}` : toolName2;
28832
- }
28833
- async function writeSecretFile(name, contents) {
28834
- const dir = await (0, import_promises30.mkdtemp)((0, import_path5.join)((0, import_os2.tmpdir)(), "alan-mcp-"));
28835
- const path4 = (0, import_path5.join)(dir, name);
28836
- const remove = async () => {
28837
- await (0, import_promises30.rm)(dir, { recursive: true, force: true });
28838
- };
28839
- try {
28840
- await (0, import_promises30.writeFile)(path4, contents, { mode: 384, flag: "wx" });
28841
- } catch (error62) {
28842
- await remove();
28843
- throw error62;
28844
- }
28845
- return { path: path4, remove, [Symbol.asyncDispose]: remove };
28846
- }
28847
- var import_crypto5, import_crypto6, import_promises30, import_os2, import_path5, MANAGED_MCP_SERVER_NAME, RUN_SCOPED_SERVER, NAMESPACED_RUN_TOOL, FLATTENED_RUN_TOOL;
28848
- var init_chunk_J2KTV5FP = __esm({
28849
- "../agent-core/dist/chunk-J2KTV5FP.js"() {
28850
- "use strict";
28851
- import_crypto5 = require("crypto");
28852
- init_agent2();
28853
- import_crypto6 = require("crypto");
28854
- init_agent2();
28855
- init_runtime_v2();
28856
- import_promises30 = require("fs/promises");
28857
- import_os2 = require("os");
28858
- import_path5 = require("path");
28859
- MANAGED_MCP_SERVER_NAME = "alan";
28860
- RUN_SCOPED_SERVER = /^alan-run-[a-f0-9]{16}$/;
28861
- NAMESPACED_RUN_TOOL = /^mcp__(alan-run-[a-f0-9]{16})__(.+)$/;
28862
- FLATTENED_RUN_TOOL = /^alan-run-[a-f0-9]{16}_(.+)$/;
28863
- }
28864
- });
28865
-
28866
28815
  // ../agent-core/dist/chunk-DLVRNIY5.js
28867
28816
  function repositories(input2, context) {
28868
28817
  const problems = new Map(input2.problems.map((problem) => [problem.path, problem]));
@@ -29673,6 +29622,131 @@ var init_chunk_DLVRNIY5 = __esm({
29673
29622
  }
29674
29623
  });
29675
29624
 
29625
+ // ../agent-core/dist/chunk-OSECDZA5.js
29626
+ function selectExternalMcpServers(spec) {
29627
+ const isWorkflow = Boolean(spec.workflowId || spec.workflowExecutionId);
29628
+ const filter = isWorkflow ? createWorkflowToolsFilter(spec.workflowTools) : null;
29629
+ if (filter && !filter.hasFilter) return {};
29630
+ const selected = {};
29631
+ for (const [name, server] of Object.entries(spec.externalMcpServers ?? {})) {
29632
+ if (!isExternalMcpServerName(name)) continue;
29633
+ if (filter && !filter.isMcpServerAllowed(name)) continue;
29634
+ selected[name] = server;
29635
+ }
29636
+ return selected;
29637
+ }
29638
+ function headerEnvName(server, header) {
29639
+ const fingerprint = (0, import_crypto5.createHash)("sha256").update(`${server}\0${header}`).digest("hex").slice(0, 12);
29640
+ return `ALAN_MCP_HEADER_${fingerprint.toUpperCase()}`;
29641
+ }
29642
+ function deliverRemote(name, server, env) {
29643
+ const headerEnv = {};
29644
+ for (const [header, value2] of Object.entries(server.headers ?? {})) {
29645
+ if (!isMcpConfigKey(header)) continue;
29646
+ const variable = headerEnvName(name, header);
29647
+ env[variable] = value2;
29648
+ headerEnv[header] = variable;
29649
+ }
29650
+ return {
29651
+ type: server.type === "sse" ? "sse" : "http",
29652
+ url: server.url,
29653
+ ...Object.keys(headerEnv).length ? { headerEnv } : {}
29654
+ };
29655
+ }
29656
+ function deliverStdio(server, cliEnv, delivery) {
29657
+ const envKeys = [];
29658
+ for (const [key, value2] of Object.entries(server.env ?? {})) {
29659
+ if (!isMcpConfigKey(key)) continue;
29660
+ if (key in cliEnv || key in delivery.env && delivery.env[key] !== value2) {
29661
+ delivery.skippedEnvKeys.push(key);
29662
+ continue;
29663
+ }
29664
+ delivery.env[key] = value2;
29665
+ envKeys.push(key);
29666
+ }
29667
+ return {
29668
+ type: "stdio",
29669
+ command: server.command,
29670
+ ...server.args?.length ? { args: server.args } : {},
29671
+ ...envKeys.length ? { envKeys } : {}
29672
+ };
29673
+ }
29674
+ function planExternalMcpDelivery(spec, cliEnv) {
29675
+ const delivery = { servers: {}, env: {}, skippedEnvKeys: [] };
29676
+ for (const [name, server] of Object.entries(selectExternalMcpServers(spec))) {
29677
+ const { url: url3, command } = server;
29678
+ if (url3 && server.type !== "stdio") {
29679
+ delivery.servers[name] = deliverRemote(name, { ...server, url: url3 }, delivery.env);
29680
+ } else if (command) {
29681
+ delivery.servers[name] = deliverStdio({ ...server, command }, cliEnv, delivery);
29682
+ }
29683
+ }
29684
+ return delivery;
29685
+ }
29686
+ function envReference(name) {
29687
+ return `\${${name}}`;
29688
+ }
29689
+ function managedMcpHeaders(identity) {
29690
+ if (identity.scope === "run") {
29691
+ return {
29692
+ Authorization: envReference(ALAN_MCP_AUTHORIZATION_ENV),
29693
+ [MANAGED_MCP_RUN_HEADER]: envReference(ALAN_RUN_ID_ENV)
29694
+ };
29695
+ }
29696
+ return {
29697
+ ...identity.authorization === void 0 ? {} : { Authorization: identity.authorization },
29698
+ [MANAGED_MCP_CONVERSATION_HEADER]: identity.conversationId
29699
+ };
29700
+ }
29701
+ function credentialDigest(authorization) {
29702
+ if (authorization === void 0) return void 0;
29703
+ return (0, import_crypto6.createHash)("sha256").update(authorization).digest("hex").slice(0, 16);
29704
+ }
29705
+ function canonicalizeManagedMcpServerName(serverName) {
29706
+ return RUN_SCOPED_SERVER.test(serverName) ? MANAGED_MCP_SERVER_NAME : serverName;
29707
+ }
29708
+ function canonicalizeManagedMcpToolName(toolName2) {
29709
+ const namespaced = NAMESPACED_RUN_TOOL.exec(toolName2);
29710
+ if (namespaced) return `mcp__${MANAGED_MCP_SERVER_NAME}__${namespaced[2]}`;
29711
+ const flattened = FLATTENED_RUN_TOOL.exec(toolName2);
29712
+ return flattened ? `mcp__${MANAGED_MCP_SERVER_NAME}__${flattened[1]}` : toolName2;
29713
+ }
29714
+ async function writeSecretFile(name, contents) {
29715
+ const dir = await (0, import_promises30.mkdtemp)((0, import_path5.join)((0, import_os2.tmpdir)(), "alan-mcp-"));
29716
+ const path4 = (0, import_path5.join)(dir, name);
29717
+ const remove = async () => {
29718
+ await (0, import_promises30.rm)(dir, { recursive: true, force: true });
29719
+ };
29720
+ try {
29721
+ await (0, import_promises30.writeFile)(path4, contents, { mode: 384, flag: "wx" });
29722
+ } catch (error62) {
29723
+ await remove();
29724
+ throw error62;
29725
+ }
29726
+ return { path: path4, remove, [Symbol.asyncDispose]: remove };
29727
+ }
29728
+ var import_crypto5, import_crypto6, import_promises30, import_os2, import_path5, OPENCODE_CODE_MODE_ENV, OPENCODE_CODE_MODE_TOOL, CODE_MODE_CALLS_META, MANAGED_MCP_SERVER_NAME, RUN_SCOPED_SERVER, NAMESPACED_RUN_TOOL, FLATTENED_RUN_TOOL;
29729
+ var init_chunk_OSECDZA5 = __esm({
29730
+ "../agent-core/dist/chunk-OSECDZA5.js"() {
29731
+ "use strict";
29732
+ import_crypto5 = require("crypto");
29733
+ init_agent2();
29734
+ import_crypto6 = require("crypto");
29735
+ init_agent2();
29736
+ init_runtime_v2();
29737
+ import_promises30 = require("fs/promises");
29738
+ import_os2 = require("os");
29739
+ import_path5 = require("path");
29740
+ OPENCODE_CODE_MODE_ENV = "OPENCODE_EXPERIMENTAL_CODE_MODE";
29741
+ OPENCODE_CODE_MODE_TOOL = "execute";
29742
+ CODE_MODE_CALLS_META = "alanToolCalls";
29743
+ MANAGED_MCP_SERVER_NAME = "alan";
29744
+ RUN_SCOPED_SERVER = /^alan-run-[a-f0-9]{16}$/;
29745
+ NAMESPACED_RUN_TOOL = /^mcp__(alan-run-[a-f0-9]{16})__(.+)$/;
29746
+ FLATTENED_RUN_TOOL = /^alan-run-[a-f0-9]{16}_(.+)$/;
29747
+ }
29748
+ });
29749
+
29676
29750
  // ../agent-core/dist/providers/claude.js
29677
29751
  function trimmed(value2) {
29678
29752
  const text22 = value2?.trim();
@@ -30915,12 +30989,12 @@ var init_claude = __esm({
30915
30989
  "../agent-core/dist/providers/claude.js"() {
30916
30990
  "use strict";
30917
30991
  init_chunk_D4TIXPWZ();
30918
- init_chunk_ILZBXGVI();
30992
+ init_chunk_FYZKVT3E();
30919
30993
  init_chunk_OUEMTEUX();
30920
30994
  init_chunk_ZCTKXKYY();
30921
- init_chunk_J2KTV5FP();
30922
30995
  init_chunk_6VWVDJ2A();
30923
30996
  init_chunk_DLVRNIY5();
30997
+ init_chunk_OSECDZA5();
30924
30998
  init_chunk_YXWJW7I5();
30925
30999
  init_effort();
30926
31000
  import_crypto7 = require("crypto");
@@ -33771,12 +33845,12 @@ var init_codex = __esm({
33771
33845
  "../agent-core/dist/providers/codex.js"() {
33772
33846
  "use strict";
33773
33847
  init_chunk_D4TIXPWZ();
33774
- init_chunk_ILZBXGVI();
33848
+ init_chunk_FYZKVT3E();
33775
33849
  init_chunk_OUEMTEUX();
33776
33850
  init_chunk_ZCTKXKYY();
33777
- init_chunk_J2KTV5FP();
33778
33851
  init_chunk_6VWVDJ2A();
33779
33852
  init_chunk_DLVRNIY5();
33853
+ init_chunk_OSECDZA5();
33780
33854
  init_chunk_YXWJW7I5();
33781
33855
  import_fs7 = require("fs");
33782
33856
  import_path7 = require("path");
@@ -35114,6 +35188,47 @@ const PROVIDER_ID = ${JSON.stringify(ALAN_CODE_ENGINE_PROVIDER_ID)};
35114
35188
  const INCLUDED_RESULTS = 8;
35115
35189
  const MAX_AUTO_RETRIES = 2;
35116
35190
  const MAX_AUTO_RETRY_WAIT_MS = 10_000;
35191
+ const CODE_MODE_TOOL = ${JSON.stringify(OPENCODE_CODE_MODE_TOOL)};
35192
+ const CODE_MODE_CALLS_META = ${JSON.stringify(CODE_MODE_CALLS_META)};
35193
+ const MAX_CHILD_OUTPUT_CHARS = 64 * 1024;
35194
+ const MAX_OPEN_SCRIPTS = 64;
35195
+ const scriptCalls = new Map();
35196
+
35197
+ function mcpResultText(result) {
35198
+ return result.content
35199
+ .flatMap(function (item) {
35200
+ if (item && item.type === "text") return [item.text];
35201
+ if (item && item.type === "resource" && item.resource && item.resource.text) return [item.resource.text];
35202
+ return [];
35203
+ })
35204
+ .join("\\n\\n");
35205
+ }
35206
+
35207
+ function openScript(callID) {
35208
+ if (scriptCalls.size >= MAX_OPEN_SCRIPTS) scriptCalls.delete(scriptCalls.keys().next().value);
35209
+ scriptCalls.set(callID, []);
35210
+ }
35211
+
35212
+ // Code mode names each MCP call "<script callID>/<n>" and hands the hook the raw MCP result.
35213
+ function recordScriptCall(input, result) {
35214
+ const callID = String(input.callID || "");
35215
+ const slash = callID.lastIndexOf("/");
35216
+ const calls = slash > 0 ? scriptCalls.get(callID.slice(0, slash)) : undefined;
35217
+ if (!calls || !result || !Array.isArray(result.content)) return;
35218
+ calls.push({
35219
+ callId: callID,
35220
+ tool: input.tool,
35221
+ input: input.args,
35222
+ output: mcpResultText(result).slice(0, MAX_CHILD_OUTPUT_CHARS),
35223
+ });
35224
+ }
35225
+
35226
+ function closeScript(callID, output) {
35227
+ const calls = scriptCalls.get(callID);
35228
+ scriptCalls.delete(callID);
35229
+ if (!calls || calls.length === 0 || !output || typeof output !== "object") return;
35230
+ output.metadata = Object.assign({}, output.metadata, { [CODE_MODE_CALLS_META]: calls });
35231
+ }
35117
35232
 
35118
35233
  function truncate(text, max) {
35119
35234
  const trimmed = String(text == null ? "" : text).trim();
@@ -35221,6 +35336,13 @@ export const AlanEnginePlugin = async () => ({
35221
35336
  output.headers["x-alan-operation-key"] = Date.now() + "-" + crypto.randomUUID();
35222
35337
  }
35223
35338
  },
35339
+ "tool.execute.before": async (input) => {
35340
+ if (input.tool === CODE_MODE_TOOL) openScript(input.callID);
35341
+ },
35342
+ "tool.execute.after": async (input, output) => {
35343
+ if (input.tool === CODE_MODE_TOOL) closeScript(input.callID, output);
35344
+ else recordScriptCall(input, output);
35345
+ },
35224
35346
  tool: {
35225
35347
  web_search: {
35226
35348
  description: "web_search: Search the public web via Alan's Parallel proxy. Use when you do not already have a URL. Follow up with webfetch on the best result(s).",
@@ -35254,6 +35376,7 @@ function bearerToken(authorization) {
35254
35376
  function alanCodeEngineEnv(input2) {
35255
35377
  return {
35256
35378
  ...alanCodeEngineDirectories(input2.engineRoot),
35379
+ [OPENCODE_CODE_MODE_ENV]: "true",
35257
35380
  [ALAN_CODE_API_KEY_ENV]: input2.apiKey,
35258
35381
  [ALAN_CODE_CONVERSATION_ID_ENV]: input2.conversationId
35259
35382
  };
@@ -35297,6 +35420,7 @@ var import_http9, import_https, import_fs8, import_path8, import_crypto13, impor
35297
35420
  var init_alan_code = __esm({
35298
35421
  "../agent-core/dist/providers/alan-code.js"() {
35299
35422
  "use strict";
35423
+ init_chunk_OSECDZA5();
35300
35424
  init_chunk_YXWJW7I5();
35301
35425
  import_http9 = require("http");
35302
35426
  import_https = require("https");
@@ -35339,10 +35463,15 @@ var init_alan_code = __esm({
35339
35463
  emptyTurn: "Alan Code ended the turn without producing any output. Try again or pick another model."
35340
35464
  };
35341
35465
  WINDOWS_RUNNABLE_EXTENSION = /\.(exe|com|cmd|bat)$/i;
35342
- ALAN_CODE_ENGINE_PLUGIN_VERSION = 2;
35466
+ ALAN_CODE_ENGINE_PLUGIN_VERSION = 3;
35343
35467
  ALAN_CODE_TOOL_NAMING_PROMPT = `## Alan tool names
35344
35468
 
35345
- This engine exposes Alan MCP tools with an \`alan_\` prefix. Where these instructions name an Alan tool, call its prefixed form: \`search_context\` is \`alan_search_context\`, \`search_code_context\` is \`alan_search_code_context\`, and \`find_records\` is \`alan_find_records\`.`;
35469
+ Alan's MCP tools are not separate tools in this engine. Call them inside an \`execute\` script under the \`alan\` namespace: \`search_context\` is \`tools.alan.search_context({ ... })\`, \`search_code_context\` is \`tools.alan.search_code_context({ ... })\`, and \`find_records\` is \`tools.alan.find_records({ ... })\`.
35470
+
35471
+ - Before the first call to a tool whose signature is not shown in the \`execute\` description, read it with \`tools.$codemode.search({ query: "<tool name>" })\` and pass exactly its fields.
35472
+ - Alan tools return JSON as text: \`JSON.parse\` a result before reading its fields or passing it to \`Object.keys\`.
35473
+ - Look up IDs in one script, then make the writes in the next, so a failed lookup never leaves half the writes done.
35474
+ - Pass an \`idempotencyKey\` naming each change (for example \`create-task:<title>\`) on every write that accepts one. If a script fails, check what it already created before running it again, and run only the writes that are missing.`;
35346
35475
  }
35347
35476
  });
35348
35477
 
@@ -45113,7 +45242,7 @@ var require_tar_stream = __commonJS({
45113
45242
  var init_dist = __esm({
45114
45243
  "../agent-core/dist/index.js"() {
45115
45244
  "use strict";
45116
- init_chunk_ILZBXGVI();
45245
+ init_chunk_FYZKVT3E();
45117
45246
  init_chunk_OUEMTEUX();
45118
45247
  init_chunk_ZCTKXKYY();
45119
45248
  init_chunk_6VWVDJ2A();
@@ -45860,12 +45989,12 @@ var import_promises50, import_path10, import_crypto14, import_promises51, CURSOR
45860
45989
  var init_acp3 = __esm({
45861
45990
  "../agent-core/dist/providers/acp.js"() {
45862
45991
  "use strict";
45863
- init_chunk_ILZBXGVI();
45992
+ init_chunk_FYZKVT3E();
45864
45993
  init_chunk_OUEMTEUX();
45865
45994
  init_chunk_ZCTKXKYY();
45866
- init_chunk_J2KTV5FP();
45867
45995
  init_chunk_6VWVDJ2A();
45868
45996
  init_chunk_DLVRNIY5();
45997
+ init_chunk_OSECDZA5();
45869
45998
  init_chunk_YXWJW7I5();
45870
45999
  import_promises50 = require("fs/promises");
45871
46000
  import_path10 = require("path");
@@ -47366,6 +47495,21 @@ function classifyOpenCodeError(error62, fallback) {
47366
47495
  }
47367
47496
  return classifyCliError(message2 || fallback);
47368
47497
  }
47498
+ function readChildCall(value2) {
47499
+ const record2 = asRecord(value2);
47500
+ const callId = asString(record2?.callId);
47501
+ const tool = asString(record2?.tool);
47502
+ if (!record2 || !callId || !tool) return void 0;
47503
+ return { callId, tool, input: record2.input, output: asString(record2.output) };
47504
+ }
47505
+ function readCodeModeChildCalls(metadata) {
47506
+ return asArray(asRecord(metadata)?.[CODE_MODE_CALLS_META]).flatMap(
47507
+ (entry) => {
47508
+ const call = readChildCall(entry);
47509
+ return call ? [call] : [];
47510
+ }
47511
+ );
47512
+ }
47369
47513
  function withParent(updates, parentToolCallId) {
47370
47514
  if (!parentToolCallId) return updates;
47371
47515
  return updates.map(
@@ -47456,6 +47600,24 @@ function toolContent(tool, toolState) {
47456
47600
  const editing = tool.status === "in_progress" && (tool.name === "edit" || tool.name === "write");
47457
47601
  return editing && path4 ? [fileChangeContent({ path: path4, operation: "modify", hunks: [] })] : void 0;
47458
47602
  }
47603
+ function codeModeChildUpdates(tool, metadata) {
47604
+ if (tool.name !== OPENCODE_CODE_MODE_TOOL || tool.status !== "completed") return [];
47605
+ return readCodeModeChildCalls(metadata).map((call) => {
47606
+ const name = canonicalizeManagedMcpToolName(call.tool);
47607
+ const content = outputContent(call.output);
47608
+ return {
47609
+ sessionUpdate: "tool_call_update",
47610
+ toolCallId: call.callId,
47611
+ name,
47612
+ title: name,
47613
+ kind: toolKindFor(name),
47614
+ status: "completed",
47615
+ ...call.input !== void 0 ? { rawInput: call.input } : {},
47616
+ ...content ? { content } : {},
47617
+ ...call.output ? { rawOutput: call.output } : {}
47618
+ };
47619
+ });
47620
+ }
47459
47621
  function createOpenCodeSessionMemory() {
47460
47622
  return { userMessageIds: /* @__PURE__ */ new Set() };
47461
47623
  }
@@ -47794,12 +47956,12 @@ var import_crypto15, import_http10, import_crypto16, import_promises52, import_p
47794
47956
  var init_opencode = __esm({
47795
47957
  "../agent-core/dist/providers/opencode.js"() {
47796
47958
  "use strict";
47797
- init_chunk_ILZBXGVI();
47959
+ init_chunk_FYZKVT3E();
47798
47960
  init_chunk_OUEMTEUX();
47799
47961
  init_chunk_ZCTKXKYY();
47800
- init_chunk_J2KTV5FP();
47801
47962
  init_chunk_6VWVDJ2A();
47802
47963
  init_chunk_DLVRNIY5();
47964
+ init_chunk_OSECDZA5();
47803
47965
  init_chunk_YXWJW7I5();
47804
47966
  import_crypto15 = require("crypto");
47805
47967
  import_http10 = require("http");
@@ -48325,6 +48487,7 @@ var init_opencode = __esm({
48325
48487
  }
48326
48488
  ];
48327
48489
  updates.push(...this.#plan(toolCallId, tool.name, toolState));
48490
+ updates.push(...codeModeChildUpdates(tool, toolState?.metadata));
48328
48491
  if (tool.status === "failed" && (tool.isTask || PERMISSION_DENIED.test(tool.errorMessage))) {
48329
48492
  updates.push(
48330
48493
  noticeUpdate("error", "tool_failed", tool.errorMessage || "OpenCode tool call failed.")
@@ -49844,12 +50007,12 @@ var import_crypto18, import_promises53, FACTORY_API_VERSION, FACTORY_PROTOCOL_VE
49844
50007
  var init_droid = __esm({
49845
50008
  "../agent-core/dist/providers/droid.js"() {
49846
50009
  "use strict";
49847
- init_chunk_ILZBXGVI();
50010
+ init_chunk_FYZKVT3E();
49848
50011
  init_chunk_OUEMTEUX();
49849
50012
  init_chunk_ZCTKXKYY();
49850
- init_chunk_J2KTV5FP();
49851
50013
  init_chunk_6VWVDJ2A();
49852
50014
  init_chunk_DLVRNIY5();
50015
+ init_chunk_OSECDZA5();
49853
50016
  init_chunk_YXWJW7I5();
49854
50017
  init_runtime_v2();
49855
50018
  import_crypto18 = require("crypto");
@@ -50954,7 +51117,7 @@ var init_antigravity = __esm({
50954
51117
  "../agent-core/dist/providers/antigravity.js"() {
50955
51118
  "use strict";
50956
51119
  init_chunk_D4TIXPWZ();
50957
- init_chunk_ILZBXGVI();
51120
+ init_chunk_FYZKVT3E();
50958
51121
  init_chunk_OUEMTEUX();
50959
51122
  init_chunk_ZCTKXKYY();
50960
51123
  init_chunk_6VWVDJ2A();
@@ -51658,12 +51821,12 @@ var import_promises55, import_path16, import_crypto20, COMMAND_CODE_GRAMMAR_NAME
51658
51821
  var init_command_code = __esm({
51659
51822
  "../agent-core/dist/providers/command-code.js"() {
51660
51823
  "use strict";
51661
- init_chunk_ILZBXGVI();
51824
+ init_chunk_FYZKVT3E();
51662
51825
  init_chunk_OUEMTEUX();
51663
51826
  init_chunk_ZCTKXKYY();
51664
- init_chunk_J2KTV5FP();
51665
51827
  init_chunk_6VWVDJ2A();
51666
51828
  init_chunk_DLVRNIY5();
51829
+ init_chunk_OSECDZA5();
51667
51830
  init_chunk_YXWJW7I5();
51668
51831
  import_promises55 = require("fs/promises");
51669
51832
  import_path16 = require("path");
@@ -57061,7 +57224,7 @@ var require_websocket_server = __commonJS({
57061
57224
  // package.json
57062
57225
  var package_default = {
57063
57226
  name: "@alan-ai-hq/agent-manager",
57064
- version: "0.1.157",
57227
+ version: "0.1.158",
57065
57228
  private: true,
57066
57229
  type: "module",
57067
57230
  description: "Alan machine runtime (alan-agent): identity, link, reconciler, session holders, run log, uploader, local API",
@@ -71985,7 +72148,19 @@ async function runHolder({
71985
72148
  ...machine?.platform === void 0 ? {} : { platform: machine.platform }
71986
72149
  });
71987
72150
  const observed = facts.observe(driver);
71988
- const writeStatus = () => writeJsonFileAtomic(launch.statusPath, {
72151
+ let statusWrites = Promise.resolve();
72152
+ const writeStatus = () => {
72153
+ const next = statusWrites.then(() => writeStatusNow());
72154
+ statusWrites = next.catch(
72155
+ (error62) => log.warn("holder.status_write_failed", { error: error62 })
72156
+ );
72157
+ return next;
72158
+ };
72159
+ const queueStatus = () => {
72160
+ writeStatus().catch(() => {
72161
+ });
72162
+ };
72163
+ const writeStatusNow = () => writeJsonFileAtomic(launch.statusPath, {
71989
72164
  protocol: HOLDER_PROTOCOL,
71990
72165
  conversationId: launch.conversationId,
71991
72166
  pid: identity.pid,
@@ -72004,7 +72179,7 @@ async function runHolder({
72004
72179
  holder.state = "idle";
72005
72180
  holder.runId = null;
72006
72181
  holder.turn = null;
72007
- void writeStatus();
72182
+ queueStatus();
72008
72183
  };
72009
72184
  const startTurn = (id, spec, client) => {
72010
72185
  if (holder.runId === spec.runId) {
@@ -72048,7 +72223,7 @@ async function runHolder({
72048
72223
  return;
72049
72224
  }
72050
72225
  writeMessage(client, { type: "ack", id });
72051
- void writeStatus();
72226
+ queueStatus();
72052
72227
  runClaimedTurn(spec, claimed, context, turn.signal).then((outcome2) => broadcast({ type: "turn_ended", runId: spec.runId, outcome: outcome2 })).catch((error62) => log.error("holder.turn_crashed", { runId: spec.runId, error: error62 })).finally(settle2);
72053
72228
  },
72054
72229
  (error62) => {
@@ -72186,6 +72361,7 @@ async function runHolder({
72186
72361
  await driver.suspend?.().catch((error62) => log.warn("holder.driver_suspend_failed", { error: error62 }));
72187
72362
  for (const client of holder.clients) client.end();
72188
72363
  await new Promise((resolve13) => server.close(() => resolve13()));
72364
+ await statusWrites;
72189
72365
  (0, import_node_fs23.rmSync)(launch.statusPath, { force: true });
72190
72366
  log.info("holder.suspended", { conversationId: launch.conversationId });
72191
72367
  } catch (_) {