@moxt-ai/mobius 0.0.27 → 0.0.29

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 (77) hide show
  1. package/dist/acp/activity.d.ts +1 -0
  2. package/dist/acp/activity.d.ts.map +1 -1
  3. package/dist/acp/activity.js +14 -1
  4. package/dist/acp/activity.js.map +1 -1
  5. package/dist/acp/session-history.d.ts.map +1 -1
  6. package/dist/acp/session-history.js +10 -16
  7. package/dist/acp/session-history.js.map +1 -1
  8. package/dist/acp/session-manager.d.ts +7 -0
  9. package/dist/acp/session-manager.d.ts.map +1 -1
  10. package/dist/acp/session-manager.js +65 -11
  11. package/dist/acp/session-manager.js.map +1 -1
  12. package/dist/agent-catalog/acp-readiness-probe.d.ts.map +1 -1
  13. package/dist/agent-catalog/acp-readiness-probe.js +2 -2
  14. package/dist/agent-catalog/acp-readiness-probe.js.map +1 -1
  15. package/dist/agent-catalog/agent-specification.d.ts +3 -0
  16. package/dist/agent-catalog/agent-specification.d.ts.map +1 -1
  17. package/dist/agent-catalog/agent-specification.js +3 -0
  18. package/dist/agent-catalog/agent-specification.js.map +1 -1
  19. package/dist/agent-catalog/agents/copilot-cli-agent.d.ts +18 -0
  20. package/dist/agent-catalog/agents/copilot-cli-agent.d.ts.map +1 -0
  21. package/dist/agent-catalog/agents/copilot-cli-agent.js +29 -0
  22. package/dist/agent-catalog/agents/copilot-cli-agent.js.map +1 -0
  23. package/dist/agent-catalog/agents/gemini-cli-agent.d.ts +14 -0
  24. package/dist/agent-catalog/agents/gemini-cli-agent.d.ts.map +1 -0
  25. package/dist/agent-catalog/agents/gemini-cli-agent.js +30 -0
  26. package/dist/agent-catalog/agents/gemini-cli-agent.js.map +1 -0
  27. package/dist/agent-catalog/agents/hermes-agent.d.ts +18 -0
  28. package/dist/agent-catalog/agents/hermes-agent.d.ts.map +1 -0
  29. package/dist/agent-catalog/agents/hermes-agent.js +32 -0
  30. package/dist/agent-catalog/agents/hermes-agent.js.map +1 -0
  31. package/dist/agent-catalog/agents/resolve-user-local-executable.d.ts +4 -0
  32. package/dist/agent-catalog/agents/resolve-user-local-executable.d.ts.map +1 -0
  33. package/dist/agent-catalog/agents/resolve-user-local-executable.js +14 -0
  34. package/dist/agent-catalog/agents/resolve-user-local-executable.js.map +1 -0
  35. package/dist/agent-catalog/agents/supported-agent-specifications.d.ts.map +1 -1
  36. package/dist/agent-catalog/agents/supported-agent-specifications.js +6 -0
  37. package/dist/agent-catalog/agents/supported-agent-specifications.js.map +1 -1
  38. package/dist/agent-catalog/discover-agent.d.ts.map +1 -1
  39. package/dist/agent-catalog/discover-agent.js +2 -2
  40. package/dist/agent-catalog/discover-agent.js.map +1 -1
  41. package/dist/agent-catalog/discover-local-agents.d.ts +3 -0
  42. package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
  43. package/dist/agent-catalog/discover-local-agents.js +3 -0
  44. package/dist/agent-catalog/discover-local-agents.js.map +1 -1
  45. package/dist/agent-catalog/executable-discovery.d.ts +1 -2
  46. package/dist/agent-catalog/executable-discovery.d.ts.map +1 -1
  47. package/dist/agent-catalog/executable-discovery.js +4 -6
  48. package/dist/agent-catalog/executable-discovery.js.map +1 -1
  49. package/dist/agent-catalog/version-output.d.ts +2 -0
  50. package/dist/agent-catalog/version-output.d.ts.map +1 -0
  51. package/dist/agent-catalog/version-output.js +4 -0
  52. package/dist/agent-catalog/version-output.js.map +1 -0
  53. package/dist/artifacts/runtime-artifact-uploader.d.ts +12 -0
  54. package/dist/artifacts/runtime-artifact-uploader.d.ts.map +1 -0
  55. package/dist/artifacts/runtime-artifact-uploader.js +157 -0
  56. package/dist/artifacts/runtime-artifact-uploader.js.map +1 -0
  57. package/dist/authorization/local-raster.d.ts +10 -0
  58. package/dist/authorization/local-raster.d.ts.map +1 -0
  59. package/dist/authorization/local-raster.js +134 -0
  60. package/dist/authorization/local-raster.js.map +1 -0
  61. package/dist/cli.js +1185 -333
  62. package/dist/cli.js.map +4 -4
  63. package/dist/index.js +1245 -396
  64. package/dist/index.js.map +4 -4
  65. package/dist/native-sessions/codex-history.d.ts.map +1 -1
  66. package/dist/native-sessions/codex-history.js +11 -11
  67. package/dist/native-sessions/codex-history.js.map +1 -1
  68. package/dist/native-sessions/history-images.d.ts +3 -0
  69. package/dist/native-sessions/history-images.d.ts.map +1 -0
  70. package/dist/native-sessions/history-images.js +74 -0
  71. package/dist/native-sessions/history-images.js.map +1 -0
  72. package/dist/run-daemon.d.ts.map +1 -1
  73. package/dist/run-daemon.js +30 -7
  74. package/dist/run-daemon.js.map +1 -1
  75. package/dist/runtime.js +1205 -354
  76. package/dist/runtime.js.map +4 -4
  77. package/package.json +2 -1
package/dist/index.js CHANGED
@@ -16087,8 +16087,8 @@ function rewriteKeyNames(ctx) {
16087
16087
  bySchema.set(entry.schema, entry);
16088
16088
  }
16089
16089
  const rewrites = /* @__PURE__ */ new Map();
16090
- for (const record2 of pendingRecords.get(ctx) ?? []) {
16091
- const seen = ctx.seen.get(record2);
16090
+ for (const record3 of pendingRecords.get(ctx) ?? []) {
16091
+ const seen = ctx.seen.get(record3);
16092
16092
  const names = (seen?.def ?? seen?.schema)?.propertyNames;
16093
16093
  if (!names || names === true || rewrites.has(names))
16094
16094
  continue;
@@ -18903,6 +18903,28 @@ function date4(params) {
18903
18903
 
18904
18904
  // ../protocol/src/prompt-usage.ts
18905
18905
  var TOKEN_COUNT = external_exports.number().int().nonnegative();
18906
+ function normalizeQuotaTokenCount(value) {
18907
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
18908
+ return value;
18909
+ }
18910
+ if (Reflect.has(value, "inputTokens") || Reflect.has(value, "outputTokens") || Reflect.has(value, "totalTokens")) {
18911
+ return value;
18912
+ }
18913
+ if (!Reflect.has(value, "input_tokens") && !Reflect.has(value, "output_tokens")) {
18914
+ return value;
18915
+ }
18916
+ const inputTokens = Reflect.get(value, "input_tokens");
18917
+ const outputTokens = Reflect.get(value, "output_tokens");
18918
+ const reportedTotal = Reflect.get(value, "total_tokens");
18919
+ return {
18920
+ cachedInputTokens: Reflect.get(value, "cached_input_tokens"),
18921
+ cachedWriteTokens: Reflect.get(value, "cached_write_tokens"),
18922
+ inputTokens,
18923
+ outputTokens,
18924
+ reasoningOutputTokens: Reflect.get(value, "reasoning_output_tokens"),
18925
+ totalTokens: reportedTotal === void 0 && typeof inputTokens === "number" && typeof outputTokens === "number" ? inputTokens + outputTokens : reportedTotal
18926
+ };
18927
+ }
18906
18928
  var promptUsageSchema = external_exports.object({
18907
18929
  cachedReadTokens: TOKEN_COUNT.nullish(),
18908
18930
  cachedWriteTokens: TOKEN_COUNT.nullish(),
@@ -18911,14 +18933,17 @@ var promptUsageSchema = external_exports.object({
18911
18933
  thoughtTokens: TOKEN_COUNT.nullish(),
18912
18934
  totalTokens: TOKEN_COUNT
18913
18935
  }).readonly();
18914
- var quotaTokenCountSchema = external_exports.object({
18915
- cachedInputTokens: TOKEN_COUNT,
18916
- cachedWriteTokens: TOKEN_COUNT.optional(),
18917
- inputTokens: TOKEN_COUNT,
18918
- outputTokens: TOKEN_COUNT,
18919
- reasoningOutputTokens: TOKEN_COUNT,
18920
- totalTokens: TOKEN_COUNT
18921
- }).readonly();
18936
+ var quotaTokenCountSchema = external_exports.preprocess(
18937
+ normalizeQuotaTokenCount,
18938
+ external_exports.object({
18939
+ cachedInputTokens: TOKEN_COUNT.optional(),
18940
+ cachedWriteTokens: TOKEN_COUNT.optional(),
18941
+ inputTokens: TOKEN_COUNT,
18942
+ outputTokens: TOKEN_COUNT,
18943
+ reasoningOutputTokens: TOKEN_COUNT.optional(),
18944
+ totalTokens: TOKEN_COUNT
18945
+ }).readonly()
18946
+ );
18922
18947
  var promptMetadataSchema = external_exports.object({
18923
18948
  quota: external_exports.object({
18924
18949
  model_usage: external_exports.array(
@@ -19045,6 +19070,7 @@ var elicitationFieldSchema = external_exports.strictObject({
19045
19070
  type: external_exports.enum(["boolean", "integer", "multiselect", "number", "select", "string"])
19046
19071
  }).readonly();
19047
19072
  var displayContentSchema = external_exports.strictObject({
19073
+ artifactId: external_exports.string().max(128).default(""),
19048
19074
  data: external_exports.string().max(4e6),
19049
19075
  mimeType: external_exports.string().max(255),
19050
19076
  name: external_exports.string().max(500),
@@ -19057,6 +19083,7 @@ var displayContentSchema = external_exports.strictObject({
19057
19083
  uri: external_exports.string().max(4096)
19058
19084
  }).readonly();
19059
19085
  var recordedDisplayContentSchema = external_exports.strictObject({
19086
+ artifactId: external_exports.string().max(128).default(""),
19060
19087
  data: external_exports.string().max(4e6),
19061
19088
  mimeType: external_exports.string().max(255),
19062
19089
  name: external_exports.string().max(500),
@@ -21201,6 +21228,212 @@ import {
21201
21228
  RequestError
21202
21229
  } from "@agentclientprotocol/sdk";
21203
21230
 
21231
+ // src/authorization/local-raster.ts
21232
+ import { readFile, realpath as realpath2, stat as stat2 } from "node:fs/promises";
21233
+ import { basename, isAbsolute, normalize, relative, sep } from "node:path";
21234
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
21235
+ var MAX_LOCAL_RASTER_BYTES = 3e6;
21236
+ var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71);
21237
+ var JPEG_SIGNATURE = Uint8Array.of(255, 216, 255);
21238
+ var GIF87_SIGNATURE = new TextEncoder().encode("GIF87a");
21239
+ var GIF89_SIGNATURE = new TextEncoder().encode("GIF89a");
21240
+ var RIFF_SIGNATURE = new TextEncoder().encode("RIFF");
21241
+ var WEBP_SIGNATURE = new TextEncoder().encode("WEBP");
21242
+ var LocalRasterImage = class {
21243
+ bytes;
21244
+ mimeType;
21245
+ name;
21246
+ constructor(name, mimeType, bytes) {
21247
+ this.bytes = bytes;
21248
+ this.mimeType = mimeType;
21249
+ this.name = name;
21250
+ }
21251
+ base64 = () => Buffer.from(this.bytes).toString("base64");
21252
+ };
21253
+ function startsWith(bytes, signature, offset = 0) {
21254
+ if (bytes.byteLength < offset + signature.byteLength) {
21255
+ return false;
21256
+ }
21257
+ return signature.every((value, index) => bytes[offset + index] === value);
21258
+ }
21259
+ function sniffRasterMime(bytes) {
21260
+ if (startsWith(bytes, PNG_SIGNATURE)) {
21261
+ return "image/png";
21262
+ }
21263
+ if (startsWith(bytes, JPEG_SIGNATURE)) {
21264
+ return "image/jpeg";
21265
+ }
21266
+ if (startsWith(bytes, GIF87_SIGNATURE) || startsWith(bytes, GIF89_SIGNATURE)) {
21267
+ return "image/gif";
21268
+ }
21269
+ if (startsWith(bytes, RIFF_SIGNATURE) && startsWith(bytes, WEBP_SIGNATURE, 8)) {
21270
+ return "image/webp";
21271
+ }
21272
+ return null;
21273
+ }
21274
+ function isInsideRoot(root, target) {
21275
+ const relation = relative(root, target);
21276
+ return relation !== ".." && !relation.startsWith(`..${sep}`) && !isAbsolute(relation);
21277
+ }
21278
+ async function resolveCanonicalPath(requested, signal) {
21279
+ signal.throwIfAborted();
21280
+ if (!isAbsolute(requested) || requested.includes("\0") || normalize(requested) !== requested) {
21281
+ return null;
21282
+ }
21283
+ try {
21284
+ const target = await realpath2(requested);
21285
+ signal.throwIfAborted();
21286
+ if (!isAbsolute(target) || normalize(target) !== target) {
21287
+ return null;
21288
+ }
21289
+ return target;
21290
+ } catch (cause) {
21291
+ signal.throwIfAborted();
21292
+ if (cause instanceof Error && cause.name === "AbortError") {
21293
+ throw cause;
21294
+ }
21295
+ return null;
21296
+ }
21297
+ }
21298
+ function parseLocalImageUri(uri) {
21299
+ const trimmed = uri.trim();
21300
+ if (trimmed.length === 0 || trimmed.length > 2048 || trimmed.includes("\0")) {
21301
+ return null;
21302
+ }
21303
+ if (trimmed.startsWith("data:")) {
21304
+ return null;
21305
+ }
21306
+ if (trimmed.startsWith("file:")) {
21307
+ try {
21308
+ const url2 = new URL(trimmed);
21309
+ if (url2.protocol !== "file:" || url2.host.length > 0) {
21310
+ return null;
21311
+ }
21312
+ return fileURLToPath2(url2);
21313
+ } catch {
21314
+ return null;
21315
+ }
21316
+ }
21317
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
21318
+ return null;
21319
+ }
21320
+ return trimmed;
21321
+ }
21322
+ async function readAuthorizedRaster(uri, roots, signal) {
21323
+ signal.throwIfAborted();
21324
+ const requested = parseLocalImageUri(uri);
21325
+ if (requested === null) {
21326
+ return null;
21327
+ }
21328
+ const target = await resolveCanonicalPath(requested, signal);
21329
+ if (target === null) {
21330
+ return null;
21331
+ }
21332
+ const targetMetadata = await stat2(target);
21333
+ signal.throwIfAborted();
21334
+ if (!targetMetadata.isFile() || targetMetadata.size < 1 || targetMetadata.size > MAX_LOCAL_RASTER_BYTES) {
21335
+ return null;
21336
+ }
21337
+ const authorizedRoots = [];
21338
+ for (const root of roots) {
21339
+ const directory = await resolveCanonicalPath(root, signal);
21340
+ if (directory === null) {
21341
+ continue;
21342
+ }
21343
+ const metadata = await stat2(directory);
21344
+ signal.throwIfAborted();
21345
+ if (metadata.isDirectory()) {
21346
+ authorizedRoots.push(directory);
21347
+ }
21348
+ }
21349
+ if (!authorizedRoots.some((root) => isInsideRoot(root, target))) {
21350
+ return null;
21351
+ }
21352
+ const bytes = new Uint8Array(await readFile(target));
21353
+ signal.throwIfAborted();
21354
+ if (bytes.byteLength < 1 || bytes.byteLength > MAX_LOCAL_RASTER_BYTES) {
21355
+ return null;
21356
+ }
21357
+ const mimeType = sniffRasterMime(bytes);
21358
+ if (mimeType === null) {
21359
+ return null;
21360
+ }
21361
+ return new LocalRasterImage(basename(target) || "Image", mimeType, bytes);
21362
+ }
21363
+
21364
+ // src/native-sessions/history-images.ts
21365
+ var IMAGE_MARKER = /\[@image\]\(([^)\r\n]*)(?:\)|$)/g;
21366
+ async function embedLocalHistoryImages(history, roots, signal) {
21367
+ if (history.status !== "available") {
21368
+ return history;
21369
+ }
21370
+ const messages = [];
21371
+ let imageCharacters = 0;
21372
+ for (const message of history.messages) {
21373
+ signal.throwIfAborted();
21374
+ const resolved = await resolveMessageImages(message, roots, imageCharacters, signal);
21375
+ imageCharacters += (resolved.images ?? []).reduce((size, image) => size + image.data.length, 0);
21376
+ messages.push(resolved);
21377
+ }
21378
+ return {
21379
+ ...history,
21380
+ messages
21381
+ };
21382
+ }
21383
+ async function resolveMessageImages(message, roots, usedCharacters, signal) {
21384
+ const images = [...message.images ?? []];
21385
+ let imageCharacters = images.reduce((size, image) => size + image.data.length, 0);
21386
+ const text = await replaceImageMarkers(message.text, async (uri) => {
21387
+ if (images.length >= 8 || usedCharacters + imageCharacters >= SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
21388
+ return "[Image unavailable]";
21389
+ }
21390
+ const embedded = parseNativeHistoryText(`[@image](${uri})`).images[0];
21391
+ if (embedded !== void 0) {
21392
+ if (usedCharacters + imageCharacters + embedded.data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
21393
+ return "[Image unavailable]";
21394
+ }
21395
+ images.push(embedded);
21396
+ imageCharacters += embedded.data.length;
21397
+ return "";
21398
+ }
21399
+ const local = await readAuthorizedRaster(uri, roots, signal);
21400
+ if (local === null) {
21401
+ return "[Image unavailable]";
21402
+ }
21403
+ const data = local.base64();
21404
+ if (usedCharacters + imageCharacters + data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
21405
+ return "[Image unavailable]";
21406
+ }
21407
+ images.push({
21408
+ data,
21409
+ mimeType: local.mimeType,
21410
+ name: local.name
21411
+ });
21412
+ imageCharacters += data.length;
21413
+ return "";
21414
+ });
21415
+ return {
21416
+ ...message,
21417
+ text,
21418
+ ...images.length > 0 ? { images } : {}
21419
+ };
21420
+ }
21421
+ async function replaceImageMarkers(text, replace) {
21422
+ const matches = [...text.matchAll(IMAGE_MARKER)];
21423
+ if (matches.length === 0) {
21424
+ return text;
21425
+ }
21426
+ let cursor = 0;
21427
+ let rewritten = "";
21428
+ for (const match of matches) {
21429
+ const index = match.index ?? 0;
21430
+ rewritten += text.slice(cursor, index);
21431
+ rewritten += await replace(match[1] ?? "");
21432
+ cursor = index + match[0].length;
21433
+ }
21434
+ return `${rewritten}${text.slice(cursor)}`;
21435
+ }
21436
+
21204
21437
  // src/acp/activity.ts
21205
21438
  var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
21206
21439
  function isRecord4(value) {
@@ -21298,6 +21531,7 @@ function readContentOutputDetail(content) {
21298
21531
  function summarizeDisplayContent(content) {
21299
21532
  return {
21300
21533
  ...content,
21534
+ artifactId: truncate(content.artifactId, 128),
21301
21535
  data: truncate(content.data, AGENT_ACTIVITY_DETAIL_LIMIT),
21302
21536
  mimeType: truncate(content.mimeType, 255),
21303
21537
  name: truncate(content.name, 500),
@@ -21310,7 +21544,7 @@ function summarizeDisplayContent(content) {
21310
21544
  };
21311
21545
  }
21312
21546
  function contentFitsRecordingEnvelope(content) {
21313
- return content.data.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.mimeType.length <= 255 && content.name.length <= 500 && content.newText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.oldText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.path.length <= 2048 && content.terminalId.length <= 255 && content.text.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.uri.length <= 4096;
21547
+ return content.artifactId.length <= 128 && content.data.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.mimeType.length <= 255 && content.name.length <= 500 && content.newText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.oldText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.path.length <= 2048 && content.terminalId.length <= 255 && content.text.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.uri.length <= 4096;
21314
21548
  }
21315
21549
  function encodedByteLength(value) {
21316
21550
  return new TextEncoder().encode(JSON.stringify(value)).byteLength;
@@ -21336,6 +21570,7 @@ function recordedDetail(activity) {
21336
21570
  }
21337
21571
  function emptyDisplayContent(type) {
21338
21572
  return {
21573
+ artifactId: "",
21339
21574
  data: "",
21340
21575
  mimeType: "",
21341
21576
  name: "",
@@ -21348,6 +21583,16 @@ function emptyDisplayContent(type) {
21348
21583
  uri: ""
21349
21584
  };
21350
21585
  }
21586
+ function imageDisplayContent(mimeType, name, data, artifactId = "", uri = "") {
21587
+ return {
21588
+ ...emptyDisplayContent("image"),
21589
+ artifactId,
21590
+ data,
21591
+ mimeType,
21592
+ name,
21593
+ uri
21594
+ };
21595
+ }
21351
21596
  function normalizeContentBlock(content) {
21352
21597
  if (content.type === "text") {
21353
21598
  return { ...emptyDisplayContent("text"), text: content.text };
@@ -22139,7 +22384,6 @@ var AcpHistoryReplay = class {
22139
22384
  #messages = [];
22140
22385
  #lastMessageId = null;
22141
22386
  #characters = 0;
22142
- #imageCharacters = 0;
22143
22387
  #truncated = false;
22144
22388
  record = (update) => {
22145
22389
  if (update.sessionUpdate !== "user_message_chunk" && update.sessionUpdate !== "agent_message_chunk") {
@@ -22150,40 +22394,30 @@ var AcpHistoryReplay = class {
22150
22394
  }
22151
22395
  const role = update.sessionUpdate === "user_message_chunk" ? "user" : "assistant";
22152
22396
  const content = update.content;
22153
- const parsed = parseNativeHistoryText(
22154
- content.type === "text" ? content.text : content.type === "image" ? `[@image](data:${content.mimeType};base64,${content.data})` : `[${content.type} attachment]`
22155
- );
22156
- const text = parsed.text;
22157
- if (text.length === 0 && parsed.images.length === 0) {
22397
+ const text = content.type === "text" ? content.text : content.type === "image" ? content.data.length > 0 ? `[@image](data:${content.mimeType};base64,${content.data})` : content.uri != null && content.uri.length > 0 ? `[@image](${content.uri})` : "[image attachment]" : `[${content.type} attachment]`;
22398
+ if (text.length === 0) {
22158
22399
  return;
22159
22400
  }
22160
22401
  const previous = this.#messages.at(-1);
22161
22402
  const id = update.messageId ?? null;
22162
22403
  const continuation = previous?.role === role && id === this.#lastMessageId;
22163
22404
  const combined = continuation ? `${previous.text}${text}` : text;
22164
- const allImages = continuation ? [...previous.images ?? [], ...parsed.images] : parsed.images;
22165
- const images = allImages.slice(0, 8);
22166
- this.#truncated ||= images.length < allImages.length;
22167
22405
  if (continuation) {
22168
22406
  this.#messages.pop();
22169
22407
  this.#characters -= previous.text.length;
22170
- this.#imageCharacters -= (previous.images ?? []).reduce((size, image) => size + image.data.length, 0);
22171
22408
  }
22172
22409
  const bounded = combined.slice(-SESSION_HISTORY_CHARACTER_LIMIT);
22173
22410
  this.#truncated ||= bounded.length < combined.length;
22174
22411
  this.#messages.push({
22175
22412
  role,
22176
- text: bounded,
22177
- ...images.length > 0 ? { images } : {}
22413
+ text: bounded
22178
22414
  });
22179
22415
  this.#characters += bounded.length;
22180
- this.#imageCharacters += images.reduce((size, image) => size + image.data.length, 0);
22181
22416
  this.#lastMessageId = id;
22182
- while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT || this.#imageCharacters > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
22417
+ while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT) {
22183
22418
  const removed = this.#messages.shift();
22184
22419
  if (removed !== void 0) {
22185
22420
  this.#characters -= removed.text.length;
22186
- this.#imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
22187
22421
  }
22188
22422
  this.#truncated = true;
22189
22423
  }
@@ -22406,6 +22640,10 @@ var MAX_PRE_SESSION_UPDATES = 100;
22406
22640
  var MAX_PRE_SESSION_UPDATE_BYTES = 1024 * 1024;
22407
22641
  var SESSION_CONTROL_COMMAND_ID = "session-control";
22408
22642
  var NullAcpSessionObserver = class {
22643
+ importLocalImage = (_sessionId, _image, signal) => {
22644
+ signal.throwIfAborted();
22645
+ return Promise.resolve("");
22646
+ };
22409
22647
  onCommands = () => Promise.resolve();
22410
22648
  onConfig = () => Promise.resolve();
22411
22649
  onContent = () => Promise.resolve();
@@ -23028,11 +23266,75 @@ var AcpProcessSession = class _AcpProcessSession {
23028
23266
  );
23029
23267
  await this.#updateTail;
23030
23268
  signal.throwIfAborted();
23031
- return history.snapshot();
23269
+ return await embedLocalHistoryImages(
23270
+ history.snapshot(),
23271
+ [this.#cwd, ...this.#additionalDirectories],
23272
+ signal
23273
+ );
23032
23274
  } finally {
23033
23275
  this.#replay = { kind: "idle" };
23034
23276
  }
23035
23277
  };
23278
+ imageRoots = () => [this.#cwd, ...this.#additionalDirectories];
23279
+ emitAgentText = async (text, messageId) => {
23280
+ const signal = AbortSignal.timeout(2e4);
23281
+ const parts = text.split(/(\[@image\]\([^)\r\n]*(?:\)|$))/);
23282
+ let leftover = "";
23283
+ for (const part of parts) {
23284
+ const marker = /^\[@image\]\(([^)\r\n]*)(?:\)|$)/.exec(part);
23285
+ if (marker === null) {
23286
+ leftover += part;
23287
+ continue;
23288
+ }
23289
+ if (leftover.length > 0) {
23290
+ await this.#turn.onText(leftover, messageId);
23291
+ leftover = "";
23292
+ }
23293
+ const raster = await readAuthorizedRaster(marker[1] ?? "", this.imageRoots(), signal);
23294
+ if (raster === null) {
23295
+ leftover += "[Image unavailable]";
23296
+ continue;
23297
+ }
23298
+ await this.emitRaster(raster, messageId, signal);
23299
+ }
23300
+ if (leftover.length > 0) {
23301
+ await this.#turn.onText(leftover, messageId);
23302
+ }
23303
+ };
23304
+ emitAgentContent = async (content, messageId) => {
23305
+ if (content.type === "image" && content.data.length === 0 && content.uri.length > 0) {
23306
+ const signal = AbortSignal.timeout(2e4);
23307
+ const raster = await readAuthorizedRaster(content.uri, this.imageRoots(), signal);
23308
+ if (raster !== null) {
23309
+ await this.emitRaster(raster, messageId, signal);
23310
+ return;
23311
+ }
23312
+ }
23313
+ await this.#getObserver().onContent({
23314
+ commandId: this.#turn.commandId,
23315
+ content,
23316
+ contentId: `content-${crypto.randomUUID()}`,
23317
+ kind: AGENT_CONTENT_KIND,
23318
+ messageId,
23319
+ sessionId: this.#mobiusSessionId
23320
+ });
23321
+ };
23322
+ emitRaster = async (raster, messageId, signal) => {
23323
+ const artifactId = await this.#getObserver().importLocalImage(this.#mobiusSessionId, raster, signal);
23324
+ await this.#getObserver().onContent({
23325
+ commandId: this.#turn.commandId,
23326
+ content: imageDisplayContent(
23327
+ raster.mimeType,
23328
+ raster.name,
23329
+ artifactId.length > 0 ? "" : raster.base64(),
23330
+ artifactId
23331
+ ),
23332
+ contentId: `content-${crypto.randomUUID()}`,
23333
+ kind: AGENT_CONTENT_KIND,
23334
+ messageId,
23335
+ sessionId: this.#mobiusSessionId
23336
+ });
23337
+ };
23036
23338
  async #initializeAgent(signal) {
23037
23339
  const initialized = await this.race(
23038
23340
  this.#connection.agent.request(
@@ -23735,18 +24037,14 @@ var AcpProcessSession = class _AcpProcessSession {
23735
24037
  );
23736
24038
  } else {
23737
24039
  await this.#turn.activities.finishNarrative();
23738
- await this.#turn.onText(update.content.text, truncate3(update.messageId ?? "", 255));
24040
+ await this.emitAgentText(update.content.text, truncate3(update.messageId ?? "", 255));
23739
24041
  }
23740
24042
  } else {
23741
24043
  await this.#turn.activities.finishNarrative();
23742
- await this.#getObserver().onContent({
23743
- commandId: this.#turn.commandId,
23744
- content: normalizeContentBlock(update.content),
23745
- contentId: `content-${crypto.randomUUID()}`,
23746
- kind: AGENT_CONTENT_KIND,
23747
- messageId: truncate3(update.messageId ?? "", 255),
23748
- sessionId: this.#mobiusSessionId
23749
- });
24044
+ await this.emitAgentContent(
24045
+ normalizeContentBlock(update.content),
24046
+ truncate3(update.messageId ?? "", 255)
24047
+ );
23750
24048
  }
23751
24049
  return;
23752
24050
  }
@@ -24612,7 +24910,7 @@ var AuditStore = class {
24612
24910
  this.database.exec("ALTER TABLE audit_events ADD COLUMN details_json TEXT NOT NULL DEFAULT '{}'");
24613
24911
  }
24614
24912
  }
24615
- record(record2) {
24913
+ record(record3) {
24616
24914
  this.database.prepare(
24617
24915
  `
24618
24916
  INSERT INTO audit_events (
@@ -24625,10 +24923,10 @@ var AuditStore = class {
24625
24923
  `
24626
24924
  ).run(
24627
24925
  (/* @__PURE__ */ new Date()).toISOString(),
24628
- record2.event,
24629
- record2.commandId,
24630
- record2.sessionId,
24631
- JSON.stringify(record2.details ?? {})
24926
+ record3.event,
24927
+ record3.commandId,
24928
+ record3.sessionId,
24929
+ JSON.stringify(record3.details ?? {})
24632
24930
  );
24633
24931
  }
24634
24932
  close() {
@@ -24650,7 +24948,7 @@ import { randomBytes } from "node:crypto";
24650
24948
 
24651
24949
  // src/bots/local-bot-grant-store.ts
24652
24950
  import { createHash, randomUUID } from "node:crypto";
24653
- import { stat as stat2 } from "node:fs/promises";
24951
+ import { stat as stat3 } from "node:fs/promises";
24654
24952
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
24655
24953
  var LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS = 90 * 24 * 60 * 60 * 1e3;
24656
24954
  var LocalBotAuthorizationError = class extends Error {
@@ -24708,7 +25006,7 @@ function agentDigest(agent) {
24708
25006
  );
24709
25007
  }
24710
25008
  async function workspaceDigest(path2) {
24711
- const metadata = await stat2(path2);
25009
+ const metadata = await stat3(path2);
24712
25010
  if (!metadata.isDirectory()) {
24713
25011
  throw new LocalBotAuthorizationError("binding_incompatible", "The Bot workspace is not a directory");
24714
25012
  }
@@ -25246,7 +25544,7 @@ async function executeBotMessageCommand(arguments_, environment, signal) {
25246
25544
  // src/bots/bot-outbound-ipc.ts
25247
25545
  import { chmod, mkdir, unlink } from "node:fs/promises";
25248
25546
  import { createServer } from "node:net";
25249
- import { dirname as dirname3, isAbsolute } from "node:path";
25547
+ import { dirname as dirname3, isAbsolute as isAbsolute2 } from "node:path";
25250
25548
  import { fetch } from "undici";
25251
25549
  var BOT_IPC_REQUEST_LIMIT = 32 * 1024;
25252
25550
  var BOT_IPC_TIMEOUT_MILLISECONDS2 = 2e4;
@@ -25344,7 +25642,7 @@ var BotOutboundIpcServer = class {
25344
25642
  #usesFilesystemSocket;
25345
25643
  constructor(socketPath, relayUrl, registry2) {
25346
25644
  const usesFilesystemSocket = !socketPath.startsWith(WINDOWS_NAMED_PIPE_PREFIX);
25347
- if (usesFilesystemSocket && !isAbsolute(socketPath)) {
25645
+ if (usesFilesystemSocket && !isAbsolute2(socketPath)) {
25348
25646
  throw new Error("The Bot IPC path must be absolute");
25349
25647
  }
25350
25648
  this.#registry = registry2;
@@ -25484,9 +25782,9 @@ var BotOutboundIpcServer = class {
25484
25782
 
25485
25783
  // src/pairing/pair-local-machine.ts
25486
25784
  import { randomUUID as randomUUID3 } from "node:crypto";
25487
- import { mkdir as mkdir4, open as open4, realpath as realpath6, rename as rename3, stat as stat6, writeFile as writeFile2 } from "node:fs/promises";
25785
+ import { mkdir as mkdir4, open as open4, realpath as realpath7, rename as rename3, stat as stat7, writeFile as writeFile2 } from "node:fs/promises";
25488
25786
  import { hostname as hostname3 } from "node:os";
25489
- import { basename, join as join14, resolve as resolve3 } from "node:path";
25787
+ import { basename as basename2, join as join15, resolve as resolve3 } from "node:path";
25490
25788
  import { fetch as fetch3 } from "undici";
25491
25789
 
25492
25790
  // src/agent-catalog/agent-discovery.ts
@@ -25595,8 +25893,8 @@ var LocalAgentInventory = class {
25595
25893
  };
25596
25894
 
25597
25895
  // src/agent-installation/managed-npm-package.ts
25598
- import { mkdir as mkdir2, mkdtemp, open as open2, realpath as realpath2, rename, rm, stat as stat3 } from "node:fs/promises";
25599
- import { delimiter, dirname as dirname4, isAbsolute as isAbsolute2, join as join4, relative, sep } from "node:path";
25896
+ import { mkdir as mkdir2, mkdtemp, open as open2, realpath as realpath3, rename, rm, stat as stat4 } from "node:fs/promises";
25897
+ import { delimiter, dirname as dirname4, isAbsolute as isAbsolute3, join as join4, relative as relative2, sep as sep2 } from "node:path";
25600
25898
  var INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
25601
25899
  var PACKAGE_METADATA_LIMIT_BYTES = 64 * 1024;
25602
25900
  var PACKAGE_LOCK_LIMIT_BYTES = 8 * 1024 * 1024;
@@ -25650,8 +25948,8 @@ function packagePath(root, packageName) {
25650
25948
  return join4(root, "node_modules", ...packageName.split("/"));
25651
25949
  }
25652
25950
  function isContainedPath(root, candidate) {
25653
- const difference = relative(root, candidate);
25654
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep}`) && !isAbsolute2(difference);
25951
+ const difference = relative2(root, candidate);
25952
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute3(difference);
25655
25953
  }
25656
25954
  async function readJsonRecord(path2, maximumBytes) {
25657
25955
  try {
@@ -25752,7 +26050,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
25752
26050
  }
25753
26051
  }
25754
26052
  async function verifyRequiredDependency(rootPath, lock, definition) {
25755
- const dependencyRoot = await realpath2(packagePath(rootPath, definition.packageName));
26053
+ const dependencyRoot = await realpath3(packagePath(rootPath, definition.packageName));
25756
26054
  if (!isContainedPath(rootPath, dependencyRoot)) {
25757
26055
  throw new ManagedNpmPackageError(
25758
26056
  "managed_package_verification_failed",
@@ -25781,8 +26079,8 @@ async function validateManagedNpmPackage(root, definition) {
25781
26079
  }
25782
26080
  }
25783
26081
  async function validateManagedNpmPackageContents(root, definition) {
25784
- const rootPath = await realpath2(root);
25785
- const packageRoot = await realpath2(packagePath(rootPath, definition.packageName));
26082
+ const rootPath = await realpath3(root);
26083
+ const packageRoot = await realpath3(packagePath(rootPath, definition.packageName));
25786
26084
  if (!isContainedPath(rootPath, packageRoot)) {
25787
26085
  throw new ManagedNpmPackageError(
25788
26086
  "managed_package_verification_failed",
@@ -25817,7 +26115,7 @@ var ManagedNpmPackageInstaller = class {
25817
26115
  install = async (root, definition, environment, signal) => {
25818
26116
  signal.throwIfAborted();
25819
26117
  try {
25820
- const metadata = await stat3(root);
26118
+ const metadata = await stat4(root);
25821
26119
  if (metadata.isDirectory()) {
25822
26120
  return await validateManagedNpmPackage(root, definition);
25823
26121
  }
@@ -25916,6 +26214,13 @@ var ManagedNpmPackageInstaller = class {
25916
26214
 
25917
26215
  // src/agent-catalog/agent-specification.ts
25918
26216
  import { join as join5 } from "node:path";
26217
+
26218
+ // src/agent-catalog/version-output.ts
26219
+ function normalizeVersionOutput(output2) {
26220
+ return output2.trim().split(/\r?\n/, 1)[0]?.trim().slice(0, 128) ?? "";
26221
+ }
26222
+
26223
+ // src/agent-catalog/agent-specification.ts
25919
26224
  var VERSION_PROBE_TIMEOUT_MILLISECONDS = 3e3;
25920
26225
  var ACP_PROBE_TIMEOUT_MILLISECONDS = 5e3;
25921
26226
  var DEFAULT_PROMPT_TIMEOUT_MILLISECONDS = 30 * 60 * 1e3;
@@ -25924,6 +26229,8 @@ var LocalAgentSpecification = class {
25924
26229
  authenticationCommand = () => "";
25925
26230
  adapterVersionArguments = ["--version"];
25926
26231
  agentVersionArguments = ["--version"];
26232
+ normalizeAdapterVersion = normalizeVersionOutput;
26233
+ normalizeAgentVersion = normalizeVersionOutput;
25927
26234
  promptTimeoutMilliseconds = DEFAULT_PROMPT_TIMEOUT_MILLISECONDS;
25928
26235
  versionProbeTimeoutMilliseconds = VERSION_PROBE_TIMEOUT_MILLISECONDS;
25929
26236
  resolveManagedAgent = async (stateDirectory, platform, signal) => {
@@ -26035,6 +26342,20 @@ var AgentProbeError = class extends Error {
26035
26342
  }
26036
26343
  };
26037
26344
 
26345
+ // src/agent-catalog/agents/resolve-user-local-executable.ts
26346
+ import { isAbsolute as isAbsolute4, join as join6 } from "node:path";
26347
+ async function resolveUserLocalExecutable(executableName, context) {
26348
+ context.signal.throwIfAborted();
26349
+ const platform = context.platform ?? process.platform;
26350
+ const homeDirectory = context.environment["HOME"];
26351
+ if (platform === "win32" || homeDirectory === void 0 || !isAbsolute4(homeDirectory)) {
26352
+ return [];
26353
+ }
26354
+ const executable = await resolveExecutablePath(join6(homeDirectory, ".local", "bin", executableName), platform);
26355
+ context.signal.throwIfAborted();
26356
+ return executable === null ? [] : [executable];
26357
+ }
26358
+
26038
26359
  // src/agent-catalog/agents/verify-session-creation.ts
26039
26360
  import { methods as methods4 } from "@agentclientprotocol/sdk";
26040
26361
  async function verifySessionCreation(connection, capabilities, defaultWorkspace, signal, label) {
@@ -26059,6 +26380,37 @@ async function verifySessionCreation(connection, capabilities, defaultWorkspace,
26059
26380
  }
26060
26381
  }
26061
26382
 
26383
+ // src/agent-catalog/agents/copilot-cli-agent.ts
26384
+ var COPILOT_CLI_TESTED_VERSION = "1.0.83";
26385
+ var CopilotCliAgentSpecification = class extends DirectAcpAgentDefinition {
26386
+ acpProbeTimeoutMilliseconds = 2e4;
26387
+ adapterVersion = COPILOT_CLI_TESTED_VERSION;
26388
+ authenticationCommand = () => "copilot login";
26389
+ agentExecutable = "copilot";
26390
+ id = "github-copilot-cli";
26391
+ label = "GitHub Copilot CLI";
26392
+ versionProbeTimeoutMilliseconds = 1e4;
26393
+ constructor() {
26394
+ super(
26395
+ "MOBIUS_COPILOT_PATH",
26396
+ ["--no-auto-update", "--acp", "--stdio"],
26397
+ ["agents", "github-copilot-cli", COPILOT_CLI_TESTED_VERSION, "bin", "copilot"]
26398
+ );
26399
+ }
26400
+ createLaunchEnvironment = async (_agent, _context) => Object.freeze({ COPILOT_AUTO_UPDATE: "false" });
26401
+ resolveInstalledAgentExecutables = async (context) => await resolveUserLocalExecutable(this.agentExecutable, context);
26402
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
26403
+ const capabilities = initialized.agentCapabilities ?? {};
26404
+ if (capabilities.loadSession !== true || capabilities.sessionCapabilities?.list == null || (initialized.authMethods ?? []).length === 0) {
26405
+ throw new AgentProbeError(
26406
+ "acp_incompatible",
26407
+ "GitHub Copilot CLI reported an unsupported ACP capability set"
26408
+ );
26409
+ }
26410
+ await verifySessionCreation(connection, capabilities, defaultWorkspace, signal, this.label);
26411
+ };
26412
+ };
26413
+
26062
26414
  // src/agent-catalog/agents/cursor-cli-agent.ts
26063
26415
  var CURSOR_CLI_TESTED_VERSION = "2026.09.02-c22c1a3";
26064
26416
  var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
@@ -26084,8 +26436,8 @@ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
26084
26436
  };
26085
26437
 
26086
26438
  // src/agent-catalog/agents/deepseek-harness-agent.ts
26087
- import { realpath as realpath3, stat as stat4 } from "node:fs/promises";
26088
- import { isAbsolute as isAbsolute3, join as join6, normalize } from "node:path";
26439
+ import { realpath as realpath4, stat as stat5 } from "node:fs/promises";
26440
+ import { isAbsolute as isAbsolute5, join as join7, normalize as normalize2 } from "node:path";
26089
26441
 
26090
26442
  // src/agent-installation/deepseek-managed-package.ts
26091
26443
  var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
@@ -26103,12 +26455,12 @@ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
26103
26455
 
26104
26456
  // src/agent-catalog/agents/deepseek-harness-agent.ts
26105
26457
  async function validateAgentHome(path2) {
26106
- if (!isAbsolute3(path2) || normalize(path2) !== path2) {
26458
+ if (!isAbsolute5(path2) || normalize2(path2) !== path2) {
26107
26459
  throw new AgentProbeError("agent_environment_invalid", "The configured Agent home is invalid");
26108
26460
  }
26109
26461
  try {
26110
- const resolved = await realpath3(path2);
26111
- const metadata = await stat4(resolved);
26462
+ const resolved = await realpath4(path2);
26463
+ const metadata = await stat5(resolved);
26112
26464
  if (!metadata.isDirectory() || typeof process.getuid === "function" && metadata.uid !== process.getuid()) {
26113
26465
  throw new Error("Agent home is not a user-owned directory");
26114
26466
  }
@@ -26153,7 +26505,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
26153
26505
  context.signal
26154
26506
  );
26155
26507
  if (managed.path === agent.path) {
26156
- selectedHome = join6(readStateDirectory(context.environment), "agents", this.id, "home");
26508
+ selectedHome = join7(readStateDirectory(context.environment), "agents", this.id, "home");
26157
26509
  }
26158
26510
  } catch {
26159
26511
  context.signal.throwIfAborted();
@@ -26169,7 +26521,7 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
26169
26521
  resolveManagedAgent = async (stateDirectory, _platform, signal) => {
26170
26522
  signal.throwIfAborted();
26171
26523
  const executable = await validateManagedNpmPackage(
26172
- join6(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
26524
+ join7(stateDirectory, "agents", this.id, DEEPSEEK_HARNESS_PACKAGE.version),
26173
26525
  DEEPSEEK_HARNESS_PACKAGE
26174
26526
  );
26175
26527
  signal.throwIfAborted();
@@ -26189,9 +26541,41 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
26189
26541
  };
26190
26542
  };
26191
26543
 
26544
+ // src/agent-catalog/agents/gemini-cli-agent.ts
26545
+ var GEMINI_CLI_TESTED_VERSION = "0.59.0";
26546
+ var GeminiCliAgentSpecification = class extends DirectAcpAgentDefinition {
26547
+ acpProbeTimeoutMilliseconds = 2e4;
26548
+ adapterVersion = GEMINI_CLI_TESTED_VERSION;
26549
+ authenticationCommand = () => "gemini";
26550
+ agentExecutable = "gemini";
26551
+ id = "gemini-cli";
26552
+ label = "Gemini CLI";
26553
+ versionProbeTimeoutMilliseconds = 1e4;
26554
+ constructor() {
26555
+ super(
26556
+ "MOBIUS_GEMINI_PATH",
26557
+ ["--acp"],
26558
+ [
26559
+ "agents",
26560
+ "gemini-cli",
26561
+ GEMINI_CLI_TESTED_VERSION,
26562
+ "bin",
26563
+ process.platform === "win32" ? "gemini.cmd" : "gemini"
26564
+ ]
26565
+ );
26566
+ }
26567
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
26568
+ const capabilities = initialized.agentCapabilities ?? {};
26569
+ if (capabilities.loadSession !== true || (initialized.authMethods ?? []).length === 0) {
26570
+ throw new AgentProbeError("acp_incompatible", "Gemini CLI reported an unsupported ACP capability set");
26571
+ }
26572
+ await verifySessionCreation(connection, capabilities, defaultWorkspace, signal, this.label);
26573
+ };
26574
+ };
26575
+
26192
26576
  // src/agent-catalog/agents/grok-build-agent.ts
26193
- import { realpath as realpath4 } from "node:fs/promises";
26194
- import { isAbsolute as isAbsolute4, join as join7, relative as relative2, sep as sep2 } from "node:path";
26577
+ import { realpath as realpath5 } from "node:fs/promises";
26578
+ import { isAbsolute as isAbsolute6, join as join8, relative as relative3, sep as sep3 } from "node:path";
26195
26579
 
26196
26580
  // src/agent-installation/grok-managed-package.ts
26197
26581
  var GROK_BUILD_MANAGED_VERSION = "1.0.21";
@@ -26253,8 +26637,8 @@ function grokBuildManagedPackage(platform, architecture) {
26253
26637
 
26254
26638
  // src/agent-catalog/agents/grok-build-agent.ts
26255
26639
  function isContainedPath2(root, candidate) {
26256
- const difference = relative2(root, candidate);
26257
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute4(difference);
26640
+ const difference = relative3(root, candidate);
26641
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute6(difference);
26258
26642
  }
26259
26643
  var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
26260
26644
  adapterVersion = GROK_BUILD_MANAGED_VERSION;
@@ -26281,8 +26665,8 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
26281
26665
  );
26282
26666
  if (managed.path === agent.path) {
26283
26667
  return Object.freeze({
26284
- GROK_HOME: await realpath4(
26285
- join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION, "home")
26668
+ GROK_HOME: await realpath5(
26669
+ join8(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION, "home")
26286
26670
  )
26287
26671
  });
26288
26672
  }
@@ -26293,9 +26677,9 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
26293
26677
  };
26294
26678
  resolveManagedAgent = async (stateDirectory, platform, signal) => {
26295
26679
  signal.throwIfAborted();
26296
- const versionRoot = await realpath4(join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION));
26297
- await validateManagedNpmPackage(join7(versionRoot, "package"), grokBuildManagedPackage(platform, process.arch));
26298
- const executable = await resolveExecutablePath(join7(versionRoot, "home", "bin", "grok"), platform);
26680
+ const versionRoot = await realpath5(join8(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION));
26681
+ await validateManagedNpmPackage(join8(versionRoot, "package"), grokBuildManagedPackage(platform, process.arch));
26682
+ const executable = await resolveExecutablePath(join8(versionRoot, "home", "bin", "grok"), platform);
26299
26683
  signal.throwIfAborted();
26300
26684
  if (executable === null || !isContainedPath2(versionRoot, executable.path)) {
26301
26685
  throw new AgentProbeError("managed_agent_invalid", "The managed Grok Build executable is invalid");
@@ -26312,14 +26696,39 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
26312
26696
  };
26313
26697
  };
26314
26698
 
26699
+ // src/agent-catalog/agents/hermes-agent.ts
26700
+ var HERMES_TESTED_VERSION = "0.21.1";
26701
+ var HermesAgentSpecification = class extends DirectAcpAgentDefinition {
26702
+ acpProbeTimeoutMilliseconds = 2e4;
26703
+ adapterVersion = HERMES_TESTED_VERSION;
26704
+ adapterVersionArguments = ["acp", "--version"];
26705
+ authenticationCommand = () => "hermes acp --setup";
26706
+ agentExecutable = "hermes";
26707
+ agentVersionArguments = ["acp", "--version"];
26708
+ id = "hermes";
26709
+ label = "Hermes Agent";
26710
+ constructor() {
26711
+ super("MOBIUS_HERMES_PATH", ["acp"], ["agents", "hermes", HERMES_TESTED_VERSION, "bin", "hermes"]);
26712
+ }
26713
+ resolveInstalledAgentExecutables = async (context) => await resolveUserLocalExecutable(this.agentExecutable, context);
26714
+ verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
26715
+ const capabilities = initialized.agentCapabilities ?? {};
26716
+ const session = capabilities.sessionCapabilities;
26717
+ if (capabilities.loadSession !== true || session?.fork == null || session.list == null || session.resume == null || (initialized.authMethods ?? []).length === 0) {
26718
+ throw new AgentProbeError("acp_incompatible", "Hermes Agent reported an unsupported ACP capability set");
26719
+ }
26720
+ await verifySessionCreation(connection, capabilities, defaultWorkspace, signal, this.label);
26721
+ };
26722
+ };
26723
+
26315
26724
  // src/agent-catalog/agents/opencode-agent.ts
26316
- import { join as join9 } from "node:path";
26725
+ import { join as join10 } from "node:path";
26317
26726
 
26318
26727
  // src/agent-installation/managed-agent-archive.ts
26319
26728
  import { createHash as createHash2 } from "node:crypto";
26320
26729
  import { createReadStream } from "node:fs";
26321
- import { chmod as chmod2, copyFile, mkdir as mkdir3, mkdtemp as mkdtemp2, open as open3, realpath as realpath5, rename as rename2, rm as rm2, stat as stat5, writeFile } from "node:fs/promises";
26322
- import { dirname as dirname5, isAbsolute as isAbsolute5, join as join8, relative as relative3, sep as sep3 } from "node:path";
26730
+ import { chmod as chmod2, copyFile, mkdir as mkdir3, mkdtemp as mkdtemp2, open as open3, realpath as realpath6, rename as rename2, rm as rm2, stat as stat6, writeFile } from "node:fs/promises";
26731
+ import { dirname as dirname5, isAbsolute as isAbsolute7, join as join9, relative as relative4, sep as sep4 } from "node:path";
26323
26732
 
26324
26733
  // src/agent-installation/verified-download.ts
26325
26734
  import { fetch as fetch2 } from "undici";
@@ -26424,8 +26833,8 @@ function isRecord10(value) {
26424
26833
  return typeof value === "object" && value !== null && !Array.isArray(value);
26425
26834
  }
26426
26835
  function isContainedPath3(root, candidate) {
26427
- const difference = relative3(root, candidate);
26428
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute5(difference);
26836
+ const difference = relative4(root, candidate);
26837
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep4}`) && !isAbsolute7(difference);
26429
26838
  }
26430
26839
  async function hashFile(path2, signal) {
26431
26840
  signal.throwIfAborted();
@@ -26499,16 +26908,16 @@ async function readManifest(path2) {
26499
26908
  }
26500
26909
  async function validateManagedAgentArchive(root, definition, signal) {
26501
26910
  try {
26502
- const rootPath = await realpath5(root);
26503
- const rootMetadata = await stat5(rootPath);
26911
+ const rootPath = await realpath6(root);
26912
+ const rootMetadata = await stat6(rootPath);
26504
26913
  if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
26505
26914
  throw new Error("Managed Agent root is not user-owned");
26506
26915
  }
26507
- const manifest = await readManifest(join8(rootPath, "archive.json"));
26916
+ const manifest = await readManifest(join9(rootPath, "archive.json"));
26508
26917
  if (manifest["archiveSha256"] !== definition.archiveSha256 || manifest["archiveUrl"] !== definition.archiveUrl.toString() || manifest["version"] !== definition.version || typeof manifest["executableSha256"] !== "string") {
26509
26918
  throw new Error("Managed Agent archive identity is invalid");
26510
26919
  }
26511
- const executable = await resolveExecutablePath(join8(rootPath, "bin", definition.executableName));
26920
+ const executable = await resolveExecutablePath(join9(rootPath, "bin", definition.executableName));
26512
26921
  if (executable === null || !isContainedPath3(rootPath, executable.path) || await hashFile(executable.path, signal) !== manifest["executableSha256"]) {
26513
26922
  throw new Error("Managed Agent executable is invalid");
26514
26923
  }
@@ -26600,7 +27009,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
26600
27009
  }
26601
27010
  createLaunchEnvironment = async (_agent, _context) => Object.freeze({ OPENCODE_DISABLE_AUTOUPDATE: "1" });
26602
27011
  resolveManagedAgent = async (stateDirectory, platform, signal) => await validateManagedAgentArchive(
26603
- join9(stateDirectory, "agents", this.id, OPENCODE_MANAGED_VERSION),
27012
+ join10(stateDirectory, "agents", this.id, OPENCODE_MANAGED_VERSION),
26604
27013
  openCodeManagedArchive(platform, process.arch),
26605
27014
  signal
26606
27015
  );
@@ -26618,7 +27027,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
26618
27027
  };
26619
27028
 
26620
27029
  // src/agent-catalog/agents/pi-agent.ts
26621
- import { join as join10 } from "node:path";
27030
+ import { join as join11 } from "node:path";
26622
27031
  import {
26623
27032
  methods as methods5
26624
27033
  } from "@agentclientprotocol/sdk";
@@ -26677,7 +27086,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
26677
27086
  resolveManagedAgent = async (stateDirectory, _platform, signal) => {
26678
27087
  signal.throwIfAborted();
26679
27088
  const executable = await validateManagedNpmPackage(
26680
- join10(stateDirectory, "agents", this.id, PI_AGENT_PACKAGE.version),
27089
+ join11(stateDirectory, "agents", this.id, PI_AGENT_PACKAGE.version),
26681
27090
  PI_AGENT_PACKAGE
26682
27091
  );
26683
27092
  signal.throwIfAborted();
@@ -26715,7 +27124,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
26715
27124
  };
26716
27125
 
26717
27126
  // src/agent-catalog/agents/workbuddy-agent.ts
26718
- import { isAbsolute as isAbsolute6, join as join11 } from "node:path";
27127
+ import { isAbsolute as isAbsolute8, join as join12 } from "node:path";
26719
27128
 
26720
27129
  // src/agent-installation/workbuddy-managed-package.ts
26721
27130
  var WORKBUDDY_MANAGED_VERSION = "2.146.0";
@@ -26768,7 +27177,7 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
26768
27177
  resolveManagedAgent = async (stateDirectory, _platform, signal) => {
26769
27178
  signal.throwIfAborted();
26770
27179
  const executable = await validateManagedNpmPackage(
26771
- join11(stateDirectory, "agents", this.id, WORKBUDDY_MANAGED_VERSION),
27180
+ join12(stateDirectory, "agents", this.id, WORKBUDDY_MANAGED_VERSION),
26772
27181
  WORKBUDDY_MANAGED_PACKAGE
26773
27182
  );
26774
27183
  signal.throwIfAborted();
@@ -26779,10 +27188,10 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
26779
27188
  if ((context.platform ?? process.platform) !== "darwin") {
26780
27189
  return [];
26781
27190
  }
26782
- const requestedPaths = [join11("/Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH)];
27191
+ const requestedPaths = [join12("/Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH)];
26783
27192
  const homeDirectory = context.environment["HOME"];
26784
- if (homeDirectory !== void 0 && isAbsolute6(homeDirectory)) {
26785
- requestedPaths.unshift(join11(homeDirectory, "Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH));
27193
+ if (homeDirectory !== void 0 && isAbsolute8(homeDirectory)) {
27194
+ requestedPaths.unshift(join12(homeDirectory, "Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH));
26786
27195
  }
26787
27196
  const executables = [];
26788
27197
  for (const requestedPath of requestedPaths) {
@@ -26808,12 +27217,15 @@ function supportedLocalAgentSpecifications() {
26808
27217
  return Object.freeze([
26809
27218
  new CodexAgentSpecification(),
26810
27219
  new ClaudeCodeAgentSpecification(),
27220
+ new CopilotCliAgentSpecification(),
26811
27221
  new PiAgentSpecification(),
26812
27222
  new DeepSeekHarnessAgentSpecification(),
27223
+ new HermesAgentSpecification(),
26813
27224
  new OpenCodeAgentSpecification(),
26814
27225
  new CursorCliAgentSpecification(),
26815
27226
  new GrokBuildAgentSpecification(),
26816
- new WorkBuddyAgentSpecification()
27227
+ new WorkBuddyAgentSpecification(),
27228
+ new GeminiCliAgentSpecification()
26817
27229
  ]);
26818
27230
  }
26819
27231
 
@@ -26825,223 +27237,13 @@ import {
26825
27237
  PROTOCOL_VERSION as PROTOCOL_VERSION2,
26826
27238
  RequestError as RequestError2
26827
27239
  } from "@agentclientprotocol/sdk";
26828
-
26829
- // src/agent-catalog/executable-discovery.ts
26830
- import { isAbsolute as isAbsolute7, join as join13 } from "node:path";
26831
-
26832
- // src/agent-installation/managed-adapter-installer.ts
26833
- import { join as join12 } from "node:path";
26834
- var ManagedAdapterInstallError = class extends Error {
26835
- code;
26836
- constructor(code, message, options = {}) {
26837
- super(message, options);
26838
- this.code = code;
26839
- this.name = "ManagedAdapterInstallError";
26840
- }
26841
- };
26842
- function translateError(error61) {
26843
- if (error61 instanceof ManagedAdapterInstallError) {
26844
- return error61;
26845
- }
26846
- if (error61 instanceof ManagedNpmPackageError) {
26847
- if (error61.code === "package_manager_not_found") {
26848
- return new ManagedAdapterInstallError(
26849
- error61.code,
26850
- "A supported npm executable is required to install the ACP adapter",
26851
- { cause: error61 }
26852
- );
26853
- }
26854
- if (error61.code === "managed_package_verification_failed") {
26855
- return new ManagedAdapterInstallError(
26856
- "adapter_verification_failed",
26857
- "The managed adapter did not match its pinned artifact",
26858
- { cause: error61 }
26859
- );
26860
- }
26861
- if (error61.code === "managed_package_publish_failed") {
26862
- return new ManagedAdapterInstallError(
26863
- "adapter_publish_failed",
26864
- "The managed adapter could not be published",
26865
- { cause: error61 }
26866
- );
26867
- }
26868
- }
26869
- return new ManagedAdapterInstallError("adapter_install_failed", "The pinned ACP adapter could not be installed", {
26870
- cause: error61
26871
- });
26872
- }
26873
- async function validateManagedAdapter(root, specification) {
26874
- try {
26875
- return await validateManagedNpmPackage(root, specification.adapterPackageDefinition);
26876
- } catch (error61) {
26877
- throw translateError(error61);
26878
- }
26879
- }
26880
- var ManagedAdapterInstaller = class {
26881
- #environment;
26882
- #npmInstaller;
26883
- #stateDirectory;
26884
- constructor(options, npmInstaller = new ManagedNpmPackageInstaller()) {
26885
- this.#environment = options.environment;
26886
- this.#npmInstaller = npmInstaller;
26887
- this.#stateDirectory = options.stateDirectory;
26888
- }
26889
- install = async (specification, signal) => {
26890
- const root = join12(this.#stateDirectory, "adapters", specification.id, specification.adapterVersion);
26891
- try {
26892
- return await this.#npmInstaller.install(
26893
- root,
26894
- specification.adapterPackageDefinition,
26895
- this.#environment,
26896
- signal
26897
- );
26898
- } catch (error61) {
26899
- if (signal.aborted) {
26900
- signal.throwIfAborted();
26901
- }
26902
- throw translateError(error61);
26903
- }
26904
- };
26905
- };
26906
-
26907
- // src/agent-catalog/executable-discovery.ts
26908
- async function resolveManagedExecutable(specification, context) {
26909
- try {
26910
- return await specification.resolveManagedAgent(
26911
- readStateDirectory(context.environment),
26912
- context.platform ?? process.platform,
26913
- context.signal
26914
- );
26915
- } catch {
26916
- context.signal.throwIfAborted();
26917
- return null;
26918
- }
26919
- }
26920
- async function resolveManagedAdapterExecutable(specification, context) {
26921
- let managed;
26922
- try {
26923
- managed = await validateManagedAdapter(
26924
- join13(readStateDirectory(context.environment), "adapters", specification.id, specification.adapterVersion),
26925
- specification
26926
- );
26927
- } catch {
26928
- return null;
26929
- }
26930
- return managed;
26931
- }
26932
- async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, resolveManaged, context) {
26933
- const override = context.environment[overrideVariable];
26934
- if (override !== void 0) {
26935
- if (override.length === 0 || !isAbsolute7(override)) {
26936
- return [];
26937
- }
26938
- const executable = await resolveExecutablePath(override, context.platform);
26939
- return executable === null ? [] : [executable];
26940
- }
26941
- const external = await findExecutableOnPath(executableName, context.environment, context.platform);
26942
- const installed = await resolveInstalled();
26943
- const managed = await resolveManaged();
26944
- const executables = [];
26945
- const paths = /* @__PURE__ */ new Set();
26946
- if (external !== null) {
26947
- executables.push(external);
26948
- paths.add(external.path);
26949
- }
26950
- for (const executable of installed) {
26951
- if (!paths.has(executable.path)) {
26952
- executables.push(executable);
26953
- paths.add(executable.path);
26954
- }
26955
- }
26956
- if (managed !== null && !paths.has(managed.path)) {
26957
- executables.push(managed);
26958
- }
26959
- return executables;
26960
- }
26961
- async function resolveAgentExecutables(specification, context) {
26962
- return await resolveSpecificationExecutables(
26963
- specification.agentExecutable,
26964
- specification.agentOverrideVariable,
26965
- async () => await specification.resolveInstalledAgentExecutables(context),
26966
- async () => await resolveManagedExecutable(specification, context),
26967
- context
26968
- );
26969
- }
26970
- async function resolveAdapterExecutables(specification, context) {
26971
- if (specification instanceof DirectAcpAgentDefinition) {
26972
- return await resolveAgentExecutables(specification, context);
26973
- }
26974
- if (!(specification instanceof BridgedAcpAgentDefinition)) {
26975
- throw new Error("Unsupported local Agent execution topology");
26976
- }
26977
- return await resolveSpecificationExecutables(
26978
- specification.adapterExecutable,
26979
- specification.adapterOverrideVariable,
26980
- () => Promise.resolve([]),
26981
- async () => await resolveManagedAdapterExecutable(specification, context),
26982
- context
26983
- );
26984
- }
26985
- async function resolveAdapterExecutable(specification, context) {
26986
- const executables = await resolveAdapterExecutables(specification, context);
26987
- return executables[0] ?? null;
26988
- }
26989
- function normalizedVersion(output2) {
26990
- return output2.trim().split(/\r?\n/, 1)[0]?.trim().slice(0, 128) ?? "";
26991
- }
26992
- async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal, timeoutMilliseconds) {
26993
- const result = await runBoundedProcess({
26994
- arguments: arguments_,
26995
- command: executable.path,
26996
- cwd: defaultWorkspace,
26997
- environment,
26998
- signal,
26999
- timeoutMilliseconds
27000
- });
27001
- const version2 = normalizedVersion(result.stdout || result.stderr);
27002
- if (version2.length === 0) {
27003
- throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version");
27004
- }
27005
- return version2;
27006
- }
27007
- var VerifiedAgentExecutable = class {
27008
- executable;
27009
- version;
27010
- constructor(executable, version2) {
27011
- this.executable = executable;
27012
- this.version = version2;
27013
- }
27014
- };
27015
- async function findVerifiedAgentExecutable(specification, context) {
27016
- const executables = await resolveAgentExecutables(specification, context);
27017
- for (const executable of executables) {
27018
- try {
27019
- const version2 = await probeVersion(
27020
- executable,
27021
- specification.agentVersionArguments,
27022
- context.environment,
27023
- context.defaultWorkspace,
27024
- context.signal,
27025
- specification.versionProbeTimeoutMilliseconds
27026
- );
27027
- return new VerifiedAgentExecutable(executable, version2);
27028
- } catch {
27029
- if (context.signal.aborted) {
27030
- context.signal.throwIfAborted();
27031
- }
27032
- }
27033
- }
27034
- return null;
27035
- }
27036
-
27037
- // src/agent-catalog/acp-readiness-probe.ts
27038
- var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
27039
- var VerifiedAcpReadiness = class {
27040
- adapterVersion;
27041
- capabilities;
27042
- constructor(adapterVersion, capabilities) {
27043
- this.adapterVersion = adapterVersion;
27044
- this.capabilities = capabilities;
27240
+ var ACP_OUTPUT_LIMIT_BYTES = 1024 * 1024;
27241
+ var VerifiedAcpReadiness = class {
27242
+ adapterVersion;
27243
+ capabilities;
27244
+ constructor(adapterVersion, capabilities) {
27245
+ this.adapterVersion = adapterVersion;
27246
+ this.capabilities = capabilities;
27045
27247
  }
27046
27248
  };
27047
27249
  var DiscoveryAcpHandler = class {
@@ -27169,7 +27371,7 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
27169
27371
  }
27170
27372
  await specification.verifyAcp(connection, initialized, defaultWorkspace, controller.signal);
27171
27373
  return new VerifiedAcpReadiness(
27172
- normalizedVersion(initialized.agentInfo?.version ?? ""),
27374
+ normalizeVersionOutput(initialized.agentInfo?.version ?? ""),
27173
27375
  normalizeAcpCapabilities(initialized)
27174
27376
  );
27175
27377
  } catch (error61) {
@@ -27185,15 +27387,221 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
27185
27387
  if (error61 instanceof RequestError2 && error61.code === -32e3 && specification.authenticationCommand().length > 0) {
27186
27388
  throw new AgentProbeError("authentication_required", "Agent authentication is required", { cause: error61 });
27187
27389
  }
27188
- throw new AgentProbeError("acp_incompatible", "ACP adapter initialization failed", { cause: error61 });
27189
- } finally {
27190
- clearTimeout(timeout);
27191
- signal.removeEventListener("abort", abort);
27192
- connection.close();
27193
- stdin.end();
27194
- stderr.removeListener("data", consumeStderr);
27195
- await stopProcessTree(child);
27390
+ throw new AgentProbeError("acp_incompatible", "ACP adapter initialization failed", { cause: error61 });
27391
+ } finally {
27392
+ clearTimeout(timeout);
27393
+ signal.removeEventListener("abort", abort);
27394
+ connection.close();
27395
+ stdin.end();
27396
+ stderr.removeListener("data", consumeStderr);
27397
+ await stopProcessTree(child);
27398
+ }
27399
+ }
27400
+
27401
+ // src/agent-catalog/executable-discovery.ts
27402
+ import { isAbsolute as isAbsolute9, join as join14 } from "node:path";
27403
+
27404
+ // src/agent-installation/managed-adapter-installer.ts
27405
+ import { join as join13 } from "node:path";
27406
+ var ManagedAdapterInstallError = class extends Error {
27407
+ code;
27408
+ constructor(code, message, options = {}) {
27409
+ super(message, options);
27410
+ this.code = code;
27411
+ this.name = "ManagedAdapterInstallError";
27412
+ }
27413
+ };
27414
+ function translateError(error61) {
27415
+ if (error61 instanceof ManagedAdapterInstallError) {
27416
+ return error61;
27417
+ }
27418
+ if (error61 instanceof ManagedNpmPackageError) {
27419
+ if (error61.code === "package_manager_not_found") {
27420
+ return new ManagedAdapterInstallError(
27421
+ error61.code,
27422
+ "A supported npm executable is required to install the ACP adapter",
27423
+ { cause: error61 }
27424
+ );
27425
+ }
27426
+ if (error61.code === "managed_package_verification_failed") {
27427
+ return new ManagedAdapterInstallError(
27428
+ "adapter_verification_failed",
27429
+ "The managed adapter did not match its pinned artifact",
27430
+ { cause: error61 }
27431
+ );
27432
+ }
27433
+ if (error61.code === "managed_package_publish_failed") {
27434
+ return new ManagedAdapterInstallError(
27435
+ "adapter_publish_failed",
27436
+ "The managed adapter could not be published",
27437
+ { cause: error61 }
27438
+ );
27439
+ }
27440
+ }
27441
+ return new ManagedAdapterInstallError("adapter_install_failed", "The pinned ACP adapter could not be installed", {
27442
+ cause: error61
27443
+ });
27444
+ }
27445
+ async function validateManagedAdapter(root, specification) {
27446
+ try {
27447
+ return await validateManagedNpmPackage(root, specification.adapterPackageDefinition);
27448
+ } catch (error61) {
27449
+ throw translateError(error61);
27450
+ }
27451
+ }
27452
+ var ManagedAdapterInstaller = class {
27453
+ #environment;
27454
+ #npmInstaller;
27455
+ #stateDirectory;
27456
+ constructor(options, npmInstaller = new ManagedNpmPackageInstaller()) {
27457
+ this.#environment = options.environment;
27458
+ this.#npmInstaller = npmInstaller;
27459
+ this.#stateDirectory = options.stateDirectory;
27460
+ }
27461
+ install = async (specification, signal) => {
27462
+ const root = join13(this.#stateDirectory, "adapters", specification.id, specification.adapterVersion);
27463
+ try {
27464
+ return await this.#npmInstaller.install(
27465
+ root,
27466
+ specification.adapterPackageDefinition,
27467
+ this.#environment,
27468
+ signal
27469
+ );
27470
+ } catch (error61) {
27471
+ if (signal.aborted) {
27472
+ signal.throwIfAborted();
27473
+ }
27474
+ throw translateError(error61);
27475
+ }
27476
+ };
27477
+ };
27478
+
27479
+ // src/agent-catalog/executable-discovery.ts
27480
+ async function resolveManagedExecutable(specification, context) {
27481
+ try {
27482
+ return await specification.resolveManagedAgent(
27483
+ readStateDirectory(context.environment),
27484
+ context.platform ?? process.platform,
27485
+ context.signal
27486
+ );
27487
+ } catch {
27488
+ context.signal.throwIfAborted();
27489
+ return null;
27490
+ }
27491
+ }
27492
+ async function resolveManagedAdapterExecutable(specification, context) {
27493
+ let managed;
27494
+ try {
27495
+ managed = await validateManagedAdapter(
27496
+ join14(readStateDirectory(context.environment), "adapters", specification.id, specification.adapterVersion),
27497
+ specification
27498
+ );
27499
+ } catch {
27500
+ return null;
27501
+ }
27502
+ return managed;
27503
+ }
27504
+ async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, resolveManaged, context) {
27505
+ const override = context.environment[overrideVariable];
27506
+ if (override !== void 0) {
27507
+ if (override.length === 0 || !isAbsolute9(override)) {
27508
+ return [];
27509
+ }
27510
+ const executable = await resolveExecutablePath(override, context.platform);
27511
+ return executable === null ? [] : [executable];
27512
+ }
27513
+ const external = await findExecutableOnPath(executableName, context.environment, context.platform);
27514
+ const installed = await resolveInstalled();
27515
+ const managed = await resolveManaged();
27516
+ const executables = [];
27517
+ const paths = /* @__PURE__ */ new Set();
27518
+ if (external !== null) {
27519
+ executables.push(external);
27520
+ paths.add(external.path);
27521
+ }
27522
+ for (const executable of installed) {
27523
+ if (!paths.has(executable.path)) {
27524
+ executables.push(executable);
27525
+ paths.add(executable.path);
27526
+ }
27527
+ }
27528
+ if (managed !== null && !paths.has(managed.path)) {
27529
+ executables.push(managed);
27530
+ }
27531
+ return executables;
27532
+ }
27533
+ async function resolveAgentExecutables(specification, context) {
27534
+ return await resolveSpecificationExecutables(
27535
+ specification.agentExecutable,
27536
+ specification.agentOverrideVariable,
27537
+ async () => await specification.resolveInstalledAgentExecutables(context),
27538
+ async () => await resolveManagedExecutable(specification, context),
27539
+ context
27540
+ );
27541
+ }
27542
+ async function resolveAdapterExecutables(specification, context) {
27543
+ if (specification instanceof DirectAcpAgentDefinition) {
27544
+ return await resolveAgentExecutables(specification, context);
27545
+ }
27546
+ if (!(specification instanceof BridgedAcpAgentDefinition)) {
27547
+ throw new Error("Unsupported local Agent execution topology");
27548
+ }
27549
+ return await resolveSpecificationExecutables(
27550
+ specification.adapterExecutable,
27551
+ specification.adapterOverrideVariable,
27552
+ () => Promise.resolve([]),
27553
+ async () => await resolveManagedAdapterExecutable(specification, context),
27554
+ context
27555
+ );
27556
+ }
27557
+ async function resolveAdapterExecutable(specification, context) {
27558
+ const executables = await resolveAdapterExecutables(specification, context);
27559
+ return executables[0] ?? null;
27560
+ }
27561
+ async function probeVersion(executable, arguments_, environment, defaultWorkspace, signal, timeoutMilliseconds, normalize4 = normalizeVersionOutput) {
27562
+ const result = await runBoundedProcess({
27563
+ arguments: arguments_,
27564
+ command: executable.path,
27565
+ cwd: defaultWorkspace,
27566
+ environment,
27567
+ signal,
27568
+ timeoutMilliseconds
27569
+ });
27570
+ const version2 = normalize4(result.stdout || result.stderr);
27571
+ if (version2.length === 0) {
27572
+ throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version");
27573
+ }
27574
+ return version2;
27575
+ }
27576
+ var VerifiedAgentExecutable = class {
27577
+ executable;
27578
+ version;
27579
+ constructor(executable, version2) {
27580
+ this.executable = executable;
27581
+ this.version = version2;
27582
+ }
27583
+ };
27584
+ async function findVerifiedAgentExecutable(specification, context) {
27585
+ const executables = await resolveAgentExecutables(specification, context);
27586
+ for (const executable of executables) {
27587
+ try {
27588
+ const version2 = await probeVersion(
27589
+ executable,
27590
+ specification.agentVersionArguments,
27591
+ context.environment,
27592
+ context.defaultWorkspace,
27593
+ context.signal,
27594
+ specification.versionProbeTimeoutMilliseconds,
27595
+ specification.normalizeAgentVersion
27596
+ );
27597
+ return new VerifiedAgentExecutable(executable, version2);
27598
+ } catch {
27599
+ if (context.signal.aborted) {
27600
+ context.signal.throwIfAborted();
27601
+ }
27602
+ }
27196
27603
  }
27604
+ return null;
27197
27605
  }
27198
27606
 
27199
27607
  // src/agent-catalog/discover-agent.ts
@@ -27239,7 +27647,8 @@ async function discoverAgent(specification, context) {
27239
27647
  context.environment,
27240
27648
  context.defaultWorkspace,
27241
27649
  context.signal,
27242
- specification.versionProbeTimeoutMilliseconds
27650
+ specification.versionProbeTimeoutMilliseconds,
27651
+ specification.normalizeAgentVersion
27243
27652
  );
27244
27653
  } catch (error61) {
27245
27654
  if (context.signal.aborted) {
@@ -27275,7 +27684,8 @@ async function discoverAgent(specification, context) {
27275
27684
  },
27276
27685
  context.defaultWorkspace,
27277
27686
  context.signal,
27278
- specification.versionProbeTimeoutMilliseconds
27687
+ specification.versionProbeTimeoutMilliseconds,
27688
+ specification.normalizeAdapterVersion
27279
27689
  );
27280
27690
  }
27281
27691
  } catch (error61) {
@@ -27460,8 +27870,8 @@ async function resolveDefaultWorkspace(path2) {
27460
27870
  const requestedWorkspace = resolve3(path2);
27461
27871
  try {
27462
27872
  await mkdir4(requestedWorkspace, { recursive: true, mode: 448 });
27463
- const defaultWorkspace = await realpath6(requestedWorkspace);
27464
- const metadata = await stat6(defaultWorkspace);
27873
+ const defaultWorkspace = await realpath7(requestedWorkspace);
27874
+ const metadata = await stat7(defaultWorkspace);
27465
27875
  if (!metadata.isDirectory()) {
27466
27876
  throw new PairingClientError("invalid_workspace", "The default workspace is not a directory");
27467
27877
  }
@@ -27531,7 +27941,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
27531
27941
  installableAgents,
27532
27942
  machineName: hostname3(),
27533
27943
  pairingCode: options.code,
27534
- workspaceName: basename(defaultWorkspace) || "Local workspace"
27944
+ workspaceName: basename2(defaultWorkspace) || "Local workspace"
27535
27945
  }),
27536
27946
  dispatcher: environmentProxyDispatcher,
27537
27947
  headers: { "content-type": "application/json" },
@@ -27548,10 +27958,10 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
27548
27958
  return options.pairingId.length > 0 ? decodePairingResponse(value, "runtimeCredential", REDEEM_RESPONSE_KEYS) : decodePairingResponse(value, "daemonToken", CLAIM_RESPONSE_KEYS);
27549
27959
  }
27550
27960
  async function persistConnection(channelId, relayOrigin, runtimeCredential2, defaultWorkspace, environment) {
27551
- const connectionsDirectory = join14(readStateDirectory(environment), "connections");
27961
+ const connectionsDirectory = join15(readStateDirectory(environment), "connections");
27552
27962
  await mkdir4(connectionsDirectory, { mode: 448, recursive: true });
27553
- const connectionPath = join14(connectionsDirectory, `${channelId}.json`);
27554
- const temporaryPath = join14(connectionsDirectory, `.${channelId}.${randomUUID3()}.tmp`);
27963
+ const connectionPath = join15(connectionsDirectory, `${channelId}.json`);
27964
+ const temporaryPath = join15(connectionsDirectory, `.${channelId}.${randomUUID3()}.tmp`);
27555
27965
  await writeFile2(
27556
27966
  temporaryPath,
27557
27967
  `${JSON.stringify(
@@ -27589,7 +27999,7 @@ function decodeSavedConnection(value, expectedChannelId) {
27589
27999
  };
27590
28000
  }
27591
28001
  async function readSavedConnection(channelId, environment) {
27592
- const connectionPath = join14(readStateDirectory(environment), "connections", `${channelId}.json`);
28002
+ const connectionPath = join15(readStateDirectory(environment), "connections", `${channelId}.json`);
27593
28003
  let encoded = "";
27594
28004
  const handle = await open4(connectionPath, "r");
27595
28005
  try {
@@ -27625,7 +28035,7 @@ function buildPairedDaemon(connection, connectionPath, inventory, environment) {
27625
28035
  const relayUrl = mobiusApiUrl(connection.relayOrigin, "/v1/runtimes/connect");
27626
28036
  relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
27627
28037
  relayUrl.searchParams.set("token", connection.runtimeCredential);
27628
- const auditDatabasePath = join14(readStateDirectory(environment), "audit", `${connection.channelId}.sqlite`);
28038
+ const auditDatabasePath = join15(readStateDirectory(environment), "audit", `${connection.channelId}.sqlite`);
27629
28039
  return {
27630
28040
  channelUrl: new URL(`/channels/${encodeURIComponent(connection.channelId)}`, connection.relayOrigin).toString(),
27631
28041
  config: createDaemonConfig(
@@ -27687,7 +28097,7 @@ async function pairLocalMachine(arguments_, signal = new AbortController().signa
27687
28097
  }
27688
28098
  async function resumeMobiusRuntime(channelId, signal, environment = process.env) {
27689
28099
  const normalizedChannelId = validatePairingId(channelId);
27690
- const connectionPath = join14(readStateDirectory(environment), "connections", `${normalizedChannelId}.json`);
28100
+ const connectionPath = join15(readStateDirectory(environment), "connections", `${normalizedChannelId}.json`);
27691
28101
  const connection = await readSavedConnection(normalizedChannelId, environment);
27692
28102
  const inventory = await discoverLocalAgentInventory({
27693
28103
  defaultWorkspace: connection.defaultWorkspace,
@@ -27702,9 +28112,9 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
27702
28112
 
27703
28113
  // src/run-daemon.ts
27704
28114
  import { randomUUID as randomUUID6 } from "node:crypto";
27705
- import { basename as basename4, join as join16 } from "node:path";
28115
+ import { basename as basename5, join as join17 } from "node:path";
27706
28116
  import { styleText } from "node:util";
27707
- import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
28117
+ import { fetch as fetch7, WebSocket as WebSocket2 } from "undici";
27708
28118
 
27709
28119
  // src/agent-catalog/publish-agent-catalog.ts
27710
28120
  import { fetch as fetch4 } from "undici";
@@ -28247,10 +28657,406 @@ var FixedInstallationExecutor = class {
28247
28657
  };
28248
28658
  };
28249
28659
 
28660
+ // src/artifacts/runtime-artifact-uploader.ts
28661
+ import { createHash as createHash3 } from "node:crypto";
28662
+
28663
+ // ../mobius-sdk/src/errors.ts
28664
+ var MobiusError = class extends Error {
28665
+ code;
28666
+ constructor(code, message, options = {}) {
28667
+ super(message, options);
28668
+ this.code = code;
28669
+ this.name = "MobiusError";
28670
+ }
28671
+ };
28672
+ var MobiusProtocolError = class extends MobiusError {
28673
+ constructor(message, options = {}) {
28674
+ super("invalid_service_response", message, options);
28675
+ this.name = "MobiusProtocolError";
28676
+ }
28677
+ };
28678
+ var MobiusValidationError = class extends MobiusError {
28679
+ constructor(message, options = {}) {
28680
+ super("invalid_request", message, options);
28681
+ this.name = "MobiusValidationError";
28682
+ }
28683
+ };
28684
+
28685
+ // ../mobius-sdk/src/resources.ts
28686
+ var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
28687
+ function invalidResponse(message) {
28688
+ return new MobiusProtocolError(message);
28689
+ }
28690
+ function isRecord12(value) {
28691
+ return typeof value === "object" && value !== null && !Array.isArray(value);
28692
+ }
28693
+ function record2(value, name) {
28694
+ if (!isRecord12(value)) {
28695
+ throw invalidResponse(`The service returned an invalid ${name}`);
28696
+ }
28697
+ return value;
28698
+ }
28699
+ function stringField(value, field, maximumLength = 85e5) {
28700
+ const candidate = value[field];
28701
+ if (typeof candidate !== "string" || candidate.length > maximumLength) {
28702
+ throw invalidResponse(`The service returned an invalid ${field}`);
28703
+ }
28704
+ return candidate;
28705
+ }
28706
+ function identifierField(value, field) {
28707
+ const candidate = stringField(value, field, 128);
28708
+ if (!IDENTIFIER_PATTERN7.test(candidate)) {
28709
+ throw invalidResponse(`The service returned an invalid ${field}`);
28710
+ }
28711
+ return candidate;
28712
+ }
28713
+ function integerField(value, field) {
28714
+ const candidate = value[field];
28715
+ if (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0) {
28716
+ throw invalidResponse(`The service returned an invalid ${field}`);
28717
+ }
28718
+ return candidate;
28719
+ }
28720
+ function validateTimestamp(value, field) {
28721
+ if (Number.isNaN(Date.parse(value))) {
28722
+ throw invalidResponse(`The service returned an invalid ${field}`);
28723
+ }
28724
+ return value;
28725
+ }
28726
+ var MobiusArtifactUploadRequest = class {
28727
+ byteLength;
28728
+ mediaType;
28729
+ name;
28730
+ sha256;
28731
+ constructor(name, mediaType, byteLength, sha256) {
28732
+ if (name.length < 1 || name.length > 500 || name.includes("\0") || mediaType.length < 1 || mediaType.length > 255 || mediaType.includes("\r") || mediaType.includes("\n") || !Number.isSafeInteger(byteLength) || byteLength < 1 || !/^[a-f0-9]{64}$/.test(sha256)) {
28733
+ throw new MobiusValidationError("The artifact upload request is invalid");
28734
+ }
28735
+ this.byteLength = byteLength;
28736
+ this.mediaType = mediaType;
28737
+ this.name = name;
28738
+ this.sha256 = sha256;
28739
+ }
28740
+ };
28741
+ var MobiusArtifact = class {
28742
+ artifactId;
28743
+ byteLength;
28744
+ createdAt;
28745
+ mediaType;
28746
+ name;
28747
+ sessionId;
28748
+ sha256;
28749
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt) {
28750
+ this.artifactId = artifactId;
28751
+ this.byteLength = byteLength;
28752
+ this.createdAt = createdAt;
28753
+ this.mediaType = mediaType;
28754
+ this.name = name;
28755
+ this.sessionId = sessionId;
28756
+ this.sha256 = sha256;
28757
+ }
28758
+ };
28759
+ var MobiusUploadingArtifact = class extends MobiusArtifact {
28760
+ expiresAt;
28761
+ state = "uploading";
28762
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiresAt) {
28763
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
28764
+ this.expiresAt = expiresAt;
28765
+ }
28766
+ };
28767
+ var MobiusArtifactUpload = class extends MobiusUploadingArtifact {
28768
+ uploadToken;
28769
+ constructor(artifact, uploadToken) {
28770
+ super(
28771
+ artifact.sessionId,
28772
+ artifact.artifactId,
28773
+ artifact.name,
28774
+ artifact.mediaType,
28775
+ artifact.byteLength,
28776
+ artifact.sha256,
28777
+ artifact.createdAt,
28778
+ artifact.expiresAt
28779
+ );
28780
+ this.uploadToken = uploadToken;
28781
+ }
28782
+ };
28783
+ var MobiusAvailableArtifact = class extends MobiusArtifact {
28784
+ availableAt;
28785
+ state = "available";
28786
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, availableAt) {
28787
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
28788
+ this.availableAt = availableAt;
28789
+ }
28790
+ };
28791
+ var MobiusExpiredArtifact = class extends MobiusArtifact {
28792
+ expiredAt;
28793
+ state = "expired";
28794
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiredAt) {
28795
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
28796
+ this.expiredAt = expiredAt;
28797
+ }
28798
+ };
28799
+ function artifactFields(value) {
28800
+ const sha256 = stringField(value, "sha256", 64);
28801
+ if (!/^[a-f0-9]{64}$/.test(sha256)) {
28802
+ throw invalidResponse("The service returned an invalid artifact digest");
28803
+ }
28804
+ return {
28805
+ artifactId: identifierField(value, "artifactId"),
28806
+ byteLength: integerField(value, "byteLength"),
28807
+ createdAt: validateTimestamp(stringField(value, "createdAt", 128), "createdAt"),
28808
+ mediaType: stringField(value, "mediaType", 255),
28809
+ name: stringField(value, "name", 500),
28810
+ sessionId: identifierField(value, "sessionId"),
28811
+ sha256
28812
+ };
28813
+ }
28814
+ function uploadingArtifact(value) {
28815
+ const fields = artifactFields(value);
28816
+ return new MobiusUploadingArtifact(
28817
+ fields.sessionId,
28818
+ fields.artifactId,
28819
+ fields.name,
28820
+ fields.mediaType,
28821
+ fields.byteLength,
28822
+ fields.sha256,
28823
+ fields.createdAt,
28824
+ validateTimestamp(stringField(value, "expiresAt", 128), "expiresAt")
28825
+ );
28826
+ }
28827
+ function decodeMobiusArtifactUpload(value) {
28828
+ const artifact = record2(value, "artifact upload authorization");
28829
+ return new MobiusArtifactUpload(uploadingArtifact(artifact), stringField(artifact, "uploadToken", 256));
28830
+ }
28831
+ function decodeMobiusArtifact(value) {
28832
+ const artifact = record2(value, "artifact");
28833
+ const state = stringField(artifact, "state", 32);
28834
+ if (state === "uploading") {
28835
+ return uploadingArtifact(artifact);
28836
+ }
28837
+ const fields = artifactFields(artifact);
28838
+ if (state === "available") {
28839
+ return new MobiusAvailableArtifact(
28840
+ fields.sessionId,
28841
+ fields.artifactId,
28842
+ fields.name,
28843
+ fields.mediaType,
28844
+ fields.byteLength,
28845
+ fields.sha256,
28846
+ fields.createdAt,
28847
+ validateTimestamp(stringField(artifact, "availableAt", 128), "availableAt")
28848
+ );
28849
+ }
28850
+ if (state === "expired") {
28851
+ return new MobiusExpiredArtifact(
28852
+ fields.sessionId,
28853
+ fields.artifactId,
28854
+ fields.name,
28855
+ fields.mediaType,
28856
+ fields.byteLength,
28857
+ fields.sha256,
28858
+ fields.createdAt,
28859
+ validateTimestamp(stringField(artifact, "expiredAt", 128), "expiredAt")
28860
+ );
28861
+ }
28862
+ throw invalidResponse("The service returned an invalid artifact state");
28863
+ }
28864
+ function decodeMobiusAvailableArtifact(value) {
28865
+ const artifact = decodeMobiusArtifact(value);
28866
+ if (!(artifact instanceof MobiusAvailableArtifact)) {
28867
+ throw invalidResponse("The service did not make the artifact available");
28868
+ }
28869
+ return artifact;
28870
+ }
28871
+ var MobiusRuntimePairingLifecycle = Object.freeze({
28872
+ Expired: "expired",
28873
+ Paired: "paired",
28874
+ Pending: "pending",
28875
+ Revoked: "revoked"
28876
+ });
28877
+
28878
+ // src/artifacts/runtime-artifact-uploader.ts
28879
+ import { fetch as fetch5 } from "undici";
28880
+ var UPLOAD_TIMEOUT_MILLISECONDS = 2e4;
28881
+ var RuntimeArtifactUploadError = class extends Error {
28882
+ code;
28883
+ constructor(code, message, options = {}) {
28884
+ super(message, options);
28885
+ this.code = code;
28886
+ this.name = "RuntimeArtifactUploadError";
28887
+ }
28888
+ };
28889
+ var UploadedRuntimeArtifact = class {
28890
+ artifactId;
28891
+ byteLength;
28892
+ mimeType;
28893
+ name;
28894
+ sha256;
28895
+ constructor(artifactId, name, mimeType, byteLength, sha256) {
28896
+ this.artifactId = artifactId;
28897
+ this.byteLength = byteLength;
28898
+ this.mimeType = mimeType;
28899
+ this.name = name;
28900
+ this.sha256 = sha256;
28901
+ }
28902
+ };
28903
+ function daemonToken2(config2) {
28904
+ const token = config2.relayUrl.searchParams.get("token");
28905
+ if (token === null || token.length < 32) {
28906
+ throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay daemon token is missing");
28907
+ }
28908
+ return token;
28909
+ }
28910
+ function channelOrigin(config2) {
28911
+ const url2 = new URL(config2.relayUrl);
28912
+ url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
28913
+ let channelPath = "";
28914
+ if (url2.pathname.endsWith("/daemon")) {
28915
+ channelPath = url2.pathname.slice(0, -"/daemon".length);
28916
+ } else {
28917
+ const runtimePath = `${MOBIUS_API_PREFIX}/v1/runtimes/connect`;
28918
+ if (!url2.pathname.endsWith("/v1/runtimes/connect") && !url2.pathname.endsWith(runtimePath)) {
28919
+ throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay artifact endpoint is invalid");
28920
+ }
28921
+ channelPath = `${url2.pathname.replace(/\/v1\/runtimes\/connect$/, "")}/channels/${encodeURIComponent(config2.channelId)}`;
28922
+ }
28923
+ url2.pathname = channelPath;
28924
+ url2.search = "";
28925
+ url2.hash = "";
28926
+ return url2;
28927
+ }
28928
+ function uploadError(code, message, cause) {
28929
+ return new RuntimeArtifactUploadError(code, message, cause === void 0 ? {} : { cause });
28930
+ }
28931
+ function translateSdkError(cause) {
28932
+ if (cause instanceof MobiusValidationError) {
28933
+ throw uploadError("artifact_upload_failed", cause.message, cause);
28934
+ }
28935
+ if (cause instanceof MobiusProtocolError) {
28936
+ throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
28937
+ }
28938
+ throw cause;
28939
+ }
28940
+ async function readJson(response) {
28941
+ try {
28942
+ return await response.json();
28943
+ } catch (cause) {
28944
+ throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
28945
+ }
28946
+ }
28947
+ async function readAuthorization(response) {
28948
+ try {
28949
+ return decodeMobiusArtifactUpload(await readJson(response));
28950
+ } catch (cause) {
28951
+ translateSdkError(cause);
28952
+ }
28953
+ }
28954
+ function sessionArtifactUrl(origin, sessionId, resourcePath, token) {
28955
+ const url2 = new URL(`${origin.pathname}/sessions/${encodeURIComponent(sessionId)}/${resourcePath}`, origin);
28956
+ url2.searchParams.set("token", token);
28957
+ return url2;
28958
+ }
28959
+ async function postLease(url2, request, signal) {
28960
+ return await fetch5(url2, {
28961
+ dispatcher: environmentProxyDispatcher,
28962
+ headers: { "content-type": "application/json" },
28963
+ method: "POST",
28964
+ body: JSON.stringify(request),
28965
+ signal
28966
+ });
28967
+ }
28968
+ async function putContent(url2, authorization, bytes, signal) {
28969
+ return await fetch5(url2, {
28970
+ dispatcher: environmentProxyDispatcher,
28971
+ headers: {
28972
+ "content-type": authorization.mediaType,
28973
+ "x-mobius-upload-token": authorization.uploadToken
28974
+ },
28975
+ method: "PUT",
28976
+ body: bytes,
28977
+ signal
28978
+ });
28979
+ }
28980
+ async function uploadRuntimeArtifact(config2, sessionId, image, signal) {
28981
+ signal.throwIfAborted();
28982
+ let request;
28983
+ try {
28984
+ request = new MobiusArtifactUploadRequest(
28985
+ image.name,
28986
+ image.mimeType,
28987
+ image.bytes.byteLength,
28988
+ createHash3("sha256").update(image.bytes).digest("hex")
28989
+ );
28990
+ } catch (cause) {
28991
+ translateSdkError(cause);
28992
+ }
28993
+ const timeoutSignal = AbortSignal.timeout(UPLOAD_TIMEOUT_MILLISECONDS);
28994
+ const requestSignal = AbortSignal.any([signal, timeoutSignal]);
28995
+ const origin = channelOrigin(config2);
28996
+ const token = daemonToken2(config2);
28997
+ let created;
28998
+ try {
28999
+ created = await postLease(
29000
+ sessionArtifactUrl(origin, sessionId, "artifacts/uploads", token),
29001
+ request,
29002
+ requestSignal
29003
+ );
29004
+ } catch (cause) {
29005
+ signal.throwIfAborted();
29006
+ throw uploadError(
29007
+ timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
29008
+ timeoutSignal.aborted ? "The artifact upload authorization timed out" : "The artifact upload could not start",
29009
+ cause
29010
+ );
29011
+ }
29012
+ if (!created.ok) {
29013
+ await created.body?.cancel();
29014
+ throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact upload");
29015
+ }
29016
+ const authorization = await readAuthorization(created);
29017
+ let uploaded;
29018
+ try {
29019
+ uploaded = await putContent(
29020
+ sessionArtifactUrl(
29021
+ origin,
29022
+ sessionId,
29023
+ `artifacts/${encodeURIComponent(authorization.artifactId)}/content`,
29024
+ token
29025
+ ),
29026
+ authorization,
29027
+ image.bytes,
29028
+ requestSignal
29029
+ );
29030
+ } catch (cause) {
29031
+ signal.throwIfAborted();
29032
+ throw uploadError(
29033
+ timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
29034
+ timeoutSignal.aborted ? "The artifact upload timed out" : "The artifact content could not be uploaded",
29035
+ cause
29036
+ );
29037
+ }
29038
+ if (!uploaded.ok) {
29039
+ await uploaded.body?.cancel();
29040
+ throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact content");
29041
+ }
29042
+ try {
29043
+ const available = decodeMobiusAvailableArtifact(await readJson(uploaded));
29044
+ return new UploadedRuntimeArtifact(
29045
+ available.artifactId,
29046
+ available.name,
29047
+ available.mediaType,
29048
+ available.byteLength,
29049
+ available.sha256
29050
+ );
29051
+ } catch (cause) {
29052
+ translateSdkError(cause);
29053
+ }
29054
+ }
29055
+
28250
29056
  // src/authorization/workspace-directory.ts
28251
- import { readdir, realpath as realpath7, stat as stat7 } from "node:fs/promises";
29057
+ import { readdir, realpath as realpath8, stat as stat8 } from "node:fs/promises";
28252
29058
  import { homedir as homedir2 } from "node:os";
28253
- import { basename as basename2, dirname as dirname6, isAbsolute as isAbsolute8, join as join15, normalize as normalize2, relative as relative4 } from "node:path";
29059
+ import { basename as basename3, dirname as dirname6, isAbsolute as isAbsolute10, join as join16, normalize as normalize3, relative as relative5 } from "node:path";
28254
29060
  var WorkspaceDirectoryListing = class {
28255
29061
  directoryId;
28256
29062
  directoryLabel;
@@ -28276,7 +29082,7 @@ function decodePath(value, prefix) {
28276
29082
  throw new LocalAuthorizationError("The directory identifier is invalid");
28277
29083
  }
28278
29084
  const decoded = Buffer.from(encoded, "base64url").toString("utf8");
28279
- if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize2(decoded) !== decoded) {
29085
+ if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize3(decoded) !== decoded) {
28280
29086
  throw new LocalAuthorizationError("The directory identifier is invalid");
28281
29087
  }
28282
29088
  return decoded;
@@ -28302,7 +29108,7 @@ var WorkspaceDirectoryService = class {
28302
29108
  }
28303
29109
  if (id.startsWith("path-")) {
28304
29110
  const path2 = decodePath(id, "path-");
28305
- if (isAbsolute8(path2)) {
29111
+ if (isAbsolute10(path2)) {
28306
29112
  return path2;
28307
29113
  }
28308
29114
  }
@@ -28310,15 +29116,15 @@ var WorkspaceDirectoryService = class {
28310
29116
  };
28311
29117
  resolvePath = async (requested, signal) => {
28312
29118
  signal.throwIfAborted();
28313
- if (!isAbsolute8(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
29119
+ if (!isAbsolute10(requested) || requested.includes("\0") || normalize3(requested) !== requested) {
28314
29120
  throw new LocalAuthorizationError("The local directory path is invalid");
28315
29121
  }
28316
29122
  try {
28317
- const target = await realpath7(requested);
29123
+ const target = await realpath8(requested);
28318
29124
  signal.throwIfAborted();
28319
- const metadata = await stat7(target);
29125
+ const metadata = await stat8(target);
28320
29126
  signal.throwIfAborted();
28321
- if (!isAbsolute8(target) || normalize2(target) !== target || !metadata.isDirectory()) {
29127
+ if (!isAbsolute10(target) || normalize3(target) !== target || !metadata.isDirectory()) {
28322
29128
  throw new LocalAuthorizationError("The selected location is not a directory");
28323
29129
  }
28324
29130
  return target;
@@ -28333,8 +29139,8 @@ var WorkspaceDirectoryService = class {
28333
29139
  }
28334
29140
  };
28335
29141
  label = (path2) => {
28336
- const suffix = relative4(homedir2(), path2);
28337
- return suffix === "" ? "~" : !isAbsolute8(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
29142
+ const suffix = relative5(homedir2(), path2);
29143
+ return suffix === "" ? "~" : !isAbsolute10(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
28338
29144
  };
28339
29145
  identify = async (bindingId, requestedPath, signal) => {
28340
29146
  this.authorizeMachine(bindingId);
@@ -28342,7 +29148,7 @@ var WorkspaceDirectoryService = class {
28342
29148
  return {
28343
29149
  path: path2,
28344
29150
  directoryId: encodePath(path2),
28345
- name: basename2(path2) || path2,
29151
+ name: basename3(path2) || path2,
28346
29152
  label: this.label(path2)
28347
29153
  };
28348
29154
  };
@@ -28364,7 +29170,7 @@ var WorkspaceDirectoryService = class {
28364
29170
  continue;
28365
29171
  }
28366
29172
  try {
28367
- const path2 = await this.resolvePath(join15(target, child.name), signal);
29173
+ const path2 = await this.resolvePath(join16(target, child.name), signal);
28368
29174
  entries.push({ directoryId: encodePath(path2), name: child.name });
28369
29175
  } catch (cause) {
28370
29176
  signal.throwIfAborted();
@@ -28436,7 +29242,7 @@ var EmbeddedBotContextApplicator = class {
28436
29242
 
28437
29243
  // src/native-sessions/service.ts
28438
29244
  import { randomUUID as randomUUID4 } from "node:crypto";
28439
- import { basename as basename3 } from "node:path";
29245
+ import { basename as basename4 } from "node:path";
28440
29246
 
28441
29247
  // src/native-sessions/codex-history.ts
28442
29248
  import { spawn as spawn4 } from "node:child_process";
@@ -28469,7 +29275,6 @@ function decodeHistory(thread, value) {
28469
29275
  const page = turnsSchema.parse(value);
28470
29276
  const messages = [];
28471
29277
  let characters = 0;
28472
- let imageCharacters = 0;
28473
29278
  let truncated = page.nextCursor != null;
28474
29279
  for (const turn of page.data.toReversed()) {
28475
29280
  for (const item of turn.items) {
@@ -28477,22 +29282,19 @@ function decodeHistory(thread, value) {
28477
29282
  let message;
28478
29283
  if (type === "userMessage") {
28479
29284
  const { content } = userMessageSchema.parse(item);
28480
- const parsed = parseNativeHistoryText(
28481
- content.map((block) => {
28482
- const { type: type2 } = itemTypeSchema.parse(block);
28483
- if (type2 === "text") {
28484
- return textSchema.parse(block).text;
28485
- }
28486
- if (type2 === "image") {
28487
- return `[@image](${imageSchema.parse(block).url})`;
28488
- }
28489
- return "[Attachment]";
28490
- }).join("")
28491
- );
29285
+ const text2 = content.map((block) => {
29286
+ const { type: type2 } = itemTypeSchema.parse(block);
29287
+ if (type2 === "text") {
29288
+ return textSchema.parse(block).text;
29289
+ }
29290
+ if (type2 === "image") {
29291
+ return `[@image](${imageSchema.parse(block).url})`;
29292
+ }
29293
+ return "[Attachment]";
29294
+ }).join("");
28492
29295
  message = {
28493
29296
  role: "user",
28494
- text: parsed.text,
28495
- ...parsed.images.length > 0 ? { images: parsed.images } : {}
29297
+ text: text2
28496
29298
  };
28497
29299
  } else if (type === "agentMessage") {
28498
29300
  const agent = agentMessageSchema.parse(item);
@@ -28510,12 +29312,10 @@ function decodeHistory(thread, value) {
28510
29312
  truncated ||= text.length < message.text.length;
28511
29313
  messages.push({ ...message, text });
28512
29314
  characters += text.length;
28513
- imageCharacters += (message.images ?? []).reduce((size, image) => size + image.data.length, 0);
28514
- while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT || imageCharacters > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
29315
+ while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT) {
28515
29316
  const removed = messages.shift();
28516
29317
  if (removed !== void 0) {
28517
29318
  characters -= removed.text.length;
28518
- imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
28519
29319
  }
28520
29320
  truncated = true;
28521
29321
  }
@@ -28673,7 +29473,11 @@ async function readCodexHistory(agent, cwd, nativeSessionId, signal) {
28673
29473
  params: { clientInfo: { name: "mobius_history", version: "1.0.0" } }
28674
29474
  });
28675
29475
  }
28676
- return await response.promise;
29476
+ const snapshot = await response.promise;
29477
+ return {
29478
+ ...snapshot,
29479
+ history: await embedLocalHistoryImages(snapshot.history, [cwd, snapshot.cwd], signal)
29480
+ };
28677
29481
  } finally {
28678
29482
  clearTimeout(timeout);
28679
29483
  signal.removeEventListener("abort", abort);
@@ -28927,7 +29731,7 @@ var NativeSessionService = class {
28927
29731
  }
28928
29732
  resolvedPaths.add(path2);
28929
29733
  additionalDirectories.push(path2);
28930
- additionalEntries.push({ directoryId: directoryId2, name: basename3(path2) });
29734
+ additionalEntries.push({ directoryId: directoryId2, name: basename4(path2) });
28931
29735
  }
28932
29736
  const listing = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
28933
29737
  const opened = await this.#sessions.forkSessionAtTurn(
@@ -29066,13 +29870,13 @@ var NativeSessionService = class {
29066
29870
  };
29067
29871
 
29068
29872
  // src/prompt-artifact-resolver.ts
29069
- import { createHash as createHash3 } from "node:crypto";
29070
- import { fetch as fetch5 } from "undici";
29873
+ import { createHash as createHash4 } from "node:crypto";
29874
+ import { fetch as fetch6 } from "undici";
29071
29875
  var ARTIFACT_SCHEME = "mobius-artifact:";
29072
29876
  var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
29073
29877
  var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
29074
29878
  var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
29075
- var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
29879
+ var IDENTIFIER_PATTERN8 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
29076
29880
  var PromptArtifactError = class extends Error {
29077
29881
  code;
29078
29882
  constructor(code, message, options = {}) {
@@ -29115,7 +29919,7 @@ function parseReference(resource) {
29115
29919
  const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
29116
29920
  const sha256 = url2.searchParams.get("sha256") ?? "";
29117
29921
  const byteLength = Number(encodedByteLength2);
29118
- if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !IDENTIFIER_PATTERN7.test(artifactId) || keys.length !== 2 || keys[0] !== "byteLength" || keys[1] !== "sha256" || !/^[1-9][0-9]*$/.test(encodedByteLength2) || !Number.isSafeInteger(byteLength) || !/^[a-f0-9]{64}$/.test(sha256)) {
29922
+ if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !IDENTIFIER_PATTERN8.test(artifactId) || keys.length !== 2 || keys[0] !== "byteLength" || keys[1] !== "sha256" || !/^[1-9][0-9]*$/.test(encodedByteLength2) || !Number.isSafeInteger(byteLength) || !/^[a-f0-9]{64}$/.test(sha256)) {
29119
29923
  throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
29120
29924
  }
29121
29925
  return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
@@ -29181,7 +29985,7 @@ async function download(config2, command, reference, signal) {
29181
29985
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
29182
29986
  let response;
29183
29987
  try {
29184
- response = await fetch5(downloadUrl(config2, command, reference), {
29988
+ response = await fetch6(downloadUrl(config2, command, reference), {
29185
29989
  dispatcher: environmentProxyDispatcher,
29186
29990
  headers: {
29187
29991
  accept: reference.resource.mimeType,
@@ -29205,7 +30009,7 @@ async function download(config2, command, reference, signal) {
29205
30009
  );
29206
30010
  }
29207
30011
  const bytes = await responseBytes(response, reference.byteLength, requestSignal);
29208
- if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
30012
+ if (createHash4("sha256").update(bytes).digest("hex") !== reference.sha256) {
29209
30013
  throw new PromptArtifactError(
29210
30014
  "artifact_integrity_failed",
29211
30015
  "The prompt artifact failed integrity validation"
@@ -30238,13 +31042,26 @@ function botIpcSocketPath() {
30238
31042
  if (process.platform === "win32") {
30239
31043
  return `\\\\.\\pipe\\mobius-bot-${randomUUID6()}`;
30240
31044
  }
30241
- return join16("/tmp", `mobius-bot-${randomUUID6()}.sock`);
31045
+ return join17("/tmp", `mobius-bot-${randomUUID6()}.sock`);
30242
31046
  }
30243
31047
  var DaemonAcpObserver = class {
31048
+ #config;
30244
31049
  #record;
30245
- constructor(record2) {
30246
- this.#record = record2;
31050
+ constructor(config2, record3) {
31051
+ this.#config = config2;
31052
+ this.#record = record3;
30247
31053
  }
31054
+ importLocalImage = async (sessionId, image, signal) => {
31055
+ try {
31056
+ return (await uploadRuntimeArtifact(this.#config, sessionId, image, signal)).artifactId;
31057
+ } catch (cause) {
31058
+ signal.throwIfAborted();
31059
+ if (cause instanceof Error && cause.name === "AbortError") {
31060
+ throw cause;
31061
+ }
31062
+ return "";
31063
+ }
31064
+ };
30248
31065
  onCommands = (event) => {
30249
31066
  this.#record(event.sessionId, encodeSessionCommandsUpdatedEvent(event));
30250
31067
  return Promise.resolve();
@@ -30454,7 +31271,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
30454
31271
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
30455
31272
  let response;
30456
31273
  try {
30457
- response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
31274
+ response = await fetch7(activeTurnReconciliationEndpoint(config2, turn), {
30458
31275
  body: JSON.stringify({ outcome: { kind: "running" } }),
30459
31276
  dispatcher: environmentProxyDispatcher,
30460
31277
  headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
@@ -30770,7 +31587,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
30770
31587
  additionalDirectories.push(directory);
30771
31588
  additionalDirectoryEntries.push({
30772
31589
  directoryId: additionalDirectoryId,
30773
- name: basename4(directory)
31590
+ name: basename5(directory)
30774
31591
  });
30775
31592
  }
30776
31593
  return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
@@ -31281,8 +32098,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
31281
32098
  rejectConnection(failure);
31282
32099
  };
31283
32100
  const processingDeliveryIds = /* @__PURE__ */ new Set();
31284
- const processDeliveredPrompt = async (delivery) => {
31285
- const command = decodeSessionPromptCommand(delivery.payload);
32101
+ const processDeliveredPrompt = async (delivery, command, trackActiveAttempt, execute) => {
31286
32102
  if (command.sessionId !== delivery.sessionId) {
31287
32103
  throw new Error("Runtime delivery Session identity does not match its payload");
31288
32104
  }
@@ -31310,22 +32126,11 @@ async function runRelayConnection(config2, directories, audit, sessions, install
31310
32126
  }
31311
32127
  const turn = new ActiveDaemonTurn(command, receipt.attemptId);
31312
32128
  activeTurns.set(command.commandId, turn);
31313
- if (command.disposition !== SessionPromptDisposition.Steer) {
32129
+ if (trackActiveAttempt) {
31314
32130
  activeAttemptIds.set(command.sessionId, receipt.attemptId);
31315
32131
  }
31316
32132
  try {
31317
- await executePrompt(
31318
- outbox,
31319
- publisher,
31320
- command,
31321
- config2,
31322
- directories,
31323
- audit,
31324
- sessions,
31325
- receipt.attemptId,
31326
- timer,
31327
- turn.signal
31328
- );
32133
+ await execute(receipt.attemptId, turn.signal);
31329
32134
  } finally {
31330
32135
  activeTurns.delete(command.commandId);
31331
32136
  if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
@@ -31404,8 +32209,50 @@ async function runRelayConnection(config2, directories, audit, sessions, install
31404
32209
  }
31405
32210
  return;
31406
32211
  }
32212
+ if (kind === BOT_SESSION_PROMPT_KIND) {
32213
+ const command = decodeBotSessionPromptCommand(delivery.payload);
32214
+ await processDeliveredPrompt(
32215
+ delivery,
32216
+ command,
32217
+ true,
32218
+ (attemptId, executionSignal) => executeBotPrompt(
32219
+ outbox,
32220
+ publisher,
32221
+ command,
32222
+ config2,
32223
+ directories,
32224
+ audit,
32225
+ sessions,
32226
+ grants,
32227
+ contexts,
32228
+ applicator,
32229
+ ipc,
32230
+ attemptId,
32231
+ timer,
32232
+ executionSignal
32233
+ )
32234
+ );
32235
+ return;
32236
+ }
31407
32237
  if (kind === SESSION_PROMPT_KIND) {
31408
- await processDeliveredPrompt(delivery);
32238
+ const command = decodeSessionPromptCommand(delivery.payload);
32239
+ await processDeliveredPrompt(
32240
+ delivery,
32241
+ command,
32242
+ command.disposition !== SessionPromptDisposition.Steer,
32243
+ (attemptId, executionSignal) => executePrompt(
32244
+ outbox,
32245
+ publisher,
32246
+ command,
32247
+ config2,
32248
+ directories,
32249
+ audit,
32250
+ sessions,
32251
+ attemptId,
32252
+ timer,
32253
+ executionSignal
32254
+ )
32255
+ );
31409
32256
  return;
31410
32257
  }
31411
32258
  throw new Error("Runtime delivery contains an unsupported protocol message");
@@ -31443,6 +32290,8 @@ async function runRelayConnection(config2, directories, audit, sessions, install
31443
32290
  payloadSessionId = decodeSessionElicitationRespondCommand(delivery.payload).sessionId;
31444
32291
  } else if (payloadKind === SESSION_PROMPT_KIND) {
31445
32292
  payloadSessionId = decodeSessionPromptCommand(delivery.payload).sessionId;
32293
+ } else if (payloadKind === BOT_SESSION_PROMPT_KIND) {
32294
+ payloadSessionId = decodeBotSessionPromptCommand(delivery.payload).sessionId;
31446
32295
  } else {
31447
32296
  throw new Error("Runtime delivery contains an unsupported protocol message");
31448
32297
  }
@@ -32040,7 +32889,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
32040
32889
  }
32041
32890
  publisher.recordAttempt(sessionId, payload, attemptId);
32042
32891
  };
32043
- const sessions = new AcpSessionManager(new DaemonAcpObserver(recordSessionEvent), sessionStore);
32892
+ const sessions = new AcpSessionManager(new DaemonAcpObserver(config2, recordSessionEvent), sessionStore);
32044
32893
  const directories = new WorkspaceDirectoryService(config2.bindingId, config2.defaultWorkspace);
32045
32894
  const installationObserver = new DaemonInstallationObserver();
32046
32895
  const diagnostics = new RelayConnectionDiagnostics(audit, config2.channelId, config2.relayUrl);
@@ -32138,11 +32987,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
32138
32987
  }
32139
32988
 
32140
32989
  // src/runtime.ts
32141
- import { mkdir as mkdir5, realpath as realpath8, stat as stat8 } from "node:fs/promises";
32142
- import { dirname as dirname8, join as join17, resolve as resolve5 } from "node:path";
32990
+ import { mkdir as mkdir5, realpath as realpath9, stat as stat9 } from "node:fs/promises";
32991
+ import { dirname as dirname8, join as join18, resolve as resolve5 } from "node:path";
32143
32992
  var APP_CREDENTIAL_PATTERN = /^mapp_[a-zA-Z0-9_-]{22}_[a-zA-Z0-9_-]{43}$/;
32144
32993
  var CONVERSATION_CREDENTIAL_PATTERN = /^mconv_[a-zA-Z0-9_-]{22}_[a-zA-Z0-9_-]{43}$/;
32145
- var IDENTIFIER_PATTERN8 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
32994
+ var IDENTIFIER_PATTERN9 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
32146
32995
  var RUNTIME_CREDENTIAL_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
32147
32996
  var MobiusRuntimeConfigurationError = class extends Error {
32148
32997
  code = "runtime_configuration_invalid";
@@ -32200,11 +33049,11 @@ function relayUrlFromConnection(connection) {
32200
33049
  }
32201
33050
  function loadMobiusRuntimeConnection(environment = process.env) {
32202
33051
  const channelId = requiredEnvironmentValue(environment, "MOBIUS_CHANNEL_ID");
32203
- if (!IDENTIFIER_PATTERN8.test(channelId)) {
33052
+ if (!IDENTIFIER_PATTERN9.test(channelId)) {
32204
33053
  throw new MobiusRuntimeConfigurationError("MOBIUS_CHANNEL_ID is invalid");
32205
33054
  }
32206
33055
  return Object.freeze({
32207
- auditDatabasePath: environment["MOBIUS_AUDIT_DATABASE"]?.trim() || join17(readStateDirectory(environment), "audit", `${channelId}.sqlite`),
33056
+ auditDatabasePath: environment["MOBIUS_AUDIT_DATABASE"]?.trim() || join18(readStateDirectory(environment), "audit", `${channelId}.sqlite`),
32208
33057
  channelId,
32209
33058
  defaultWorkspace: loadDefaultWorkspace(environment),
32210
33059
  relayUrl: requiredEnvironmentValue(environment, "MOBIUS_RELAY_URL"),
@@ -32215,8 +33064,8 @@ async function resolveWorkspace(path2) {
32215
33064
  const requested = resolve5(path2);
32216
33065
  try {
32217
33066
  await mkdir5(requested, { recursive: true, mode: 448 });
32218
- const resolved = await realpath8(requested);
32219
- const metadata = await stat8(resolved);
33067
+ const resolved = await realpath9(requested);
33068
+ const metadata = await stat9(resolved);
32220
33069
  if (!metadata.isDirectory()) {
32221
33070
  throw new MobiusRuntimeConfigurationError("The Runtime workspace is not a directory");
32222
33071
  }