@moxt-ai/mobius 0.0.27 → 0.0.28

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 (36) 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/artifacts/runtime-artifact-uploader.d.ts +12 -0
  13. package/dist/artifacts/runtime-artifact-uploader.d.ts.map +1 -0
  14. package/dist/artifacts/runtime-artifact-uploader.js +157 -0
  15. package/dist/artifacts/runtime-artifact-uploader.js.map +1 -0
  16. package/dist/authorization/local-raster.d.ts +10 -0
  17. package/dist/authorization/local-raster.d.ts.map +1 -0
  18. package/dist/authorization/local-raster.js +134 -0
  19. package/dist/authorization/local-raster.js.map +1 -0
  20. package/dist/cli.js +826 -113
  21. package/dist/cli.js.map +4 -4
  22. package/dist/index.js +849 -137
  23. package/dist/index.js.map +4 -4
  24. package/dist/native-sessions/codex-history.d.ts.map +1 -1
  25. package/dist/native-sessions/codex-history.js +11 -11
  26. package/dist/native-sessions/codex-history.js.map +1 -1
  27. package/dist/native-sessions/history-images.d.ts +3 -0
  28. package/dist/native-sessions/history-images.d.ts.map +1 -0
  29. package/dist/native-sessions/history-images.js +74 -0
  30. package/dist/native-sessions/history-images.js.map +1 -0
  31. package/dist/run-daemon.d.ts.map +1 -1
  32. package/dist/run-daemon.js +30 -7
  33. package/dist/run-daemon.js.map +1 -1
  34. package/dist/runtime.js +845 -133
  35. package/dist/runtime.js.map +4 -4
  36. 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;
@@ -19045,6 +19045,7 @@ var elicitationFieldSchema = external_exports.strictObject({
19045
19045
  type: external_exports.enum(["boolean", "integer", "multiselect", "number", "select", "string"])
19046
19046
  }).readonly();
19047
19047
  var displayContentSchema = external_exports.strictObject({
19048
+ artifactId: external_exports.string().max(128).default(""),
19048
19049
  data: external_exports.string().max(4e6),
19049
19050
  mimeType: external_exports.string().max(255),
19050
19051
  name: external_exports.string().max(500),
@@ -19057,6 +19058,7 @@ var displayContentSchema = external_exports.strictObject({
19057
19058
  uri: external_exports.string().max(4096)
19058
19059
  }).readonly();
19059
19060
  var recordedDisplayContentSchema = external_exports.strictObject({
19061
+ artifactId: external_exports.string().max(128).default(""),
19060
19062
  data: external_exports.string().max(4e6),
19061
19063
  mimeType: external_exports.string().max(255),
19062
19064
  name: external_exports.string().max(500),
@@ -21201,6 +21203,212 @@ import {
21201
21203
  RequestError
21202
21204
  } from "@agentclientprotocol/sdk";
21203
21205
 
21206
+ // src/authorization/local-raster.ts
21207
+ import { readFile, realpath as realpath2, stat as stat2 } from "node:fs/promises";
21208
+ import { basename, isAbsolute, normalize, relative, sep } from "node:path";
21209
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
21210
+ var MAX_LOCAL_RASTER_BYTES = 3e6;
21211
+ var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71);
21212
+ var JPEG_SIGNATURE = Uint8Array.of(255, 216, 255);
21213
+ var GIF87_SIGNATURE = new TextEncoder().encode("GIF87a");
21214
+ var GIF89_SIGNATURE = new TextEncoder().encode("GIF89a");
21215
+ var RIFF_SIGNATURE = new TextEncoder().encode("RIFF");
21216
+ var WEBP_SIGNATURE = new TextEncoder().encode("WEBP");
21217
+ var LocalRasterImage = class {
21218
+ bytes;
21219
+ mimeType;
21220
+ name;
21221
+ constructor(name, mimeType, bytes) {
21222
+ this.bytes = bytes;
21223
+ this.mimeType = mimeType;
21224
+ this.name = name;
21225
+ }
21226
+ base64 = () => Buffer.from(this.bytes).toString("base64");
21227
+ };
21228
+ function startsWith(bytes, signature, offset = 0) {
21229
+ if (bytes.byteLength < offset + signature.byteLength) {
21230
+ return false;
21231
+ }
21232
+ return signature.every((value, index) => bytes[offset + index] === value);
21233
+ }
21234
+ function sniffRasterMime(bytes) {
21235
+ if (startsWith(bytes, PNG_SIGNATURE)) {
21236
+ return "image/png";
21237
+ }
21238
+ if (startsWith(bytes, JPEG_SIGNATURE)) {
21239
+ return "image/jpeg";
21240
+ }
21241
+ if (startsWith(bytes, GIF87_SIGNATURE) || startsWith(bytes, GIF89_SIGNATURE)) {
21242
+ return "image/gif";
21243
+ }
21244
+ if (startsWith(bytes, RIFF_SIGNATURE) && startsWith(bytes, WEBP_SIGNATURE, 8)) {
21245
+ return "image/webp";
21246
+ }
21247
+ return null;
21248
+ }
21249
+ function isInsideRoot(root, target) {
21250
+ const relation = relative(root, target);
21251
+ return relation !== ".." && !relation.startsWith(`..${sep}`) && !isAbsolute(relation);
21252
+ }
21253
+ async function resolveCanonicalPath(requested, signal) {
21254
+ signal.throwIfAborted();
21255
+ if (!isAbsolute(requested) || requested.includes("\0") || normalize(requested) !== requested) {
21256
+ return null;
21257
+ }
21258
+ try {
21259
+ const target = await realpath2(requested);
21260
+ signal.throwIfAborted();
21261
+ if (!isAbsolute(target) || normalize(target) !== target) {
21262
+ return null;
21263
+ }
21264
+ return target;
21265
+ } catch (cause) {
21266
+ signal.throwIfAborted();
21267
+ if (cause instanceof Error && cause.name === "AbortError") {
21268
+ throw cause;
21269
+ }
21270
+ return null;
21271
+ }
21272
+ }
21273
+ function parseLocalImageUri(uri) {
21274
+ const trimmed = uri.trim();
21275
+ if (trimmed.length === 0 || trimmed.length > 2048 || trimmed.includes("\0")) {
21276
+ return null;
21277
+ }
21278
+ if (trimmed.startsWith("data:")) {
21279
+ return null;
21280
+ }
21281
+ if (trimmed.startsWith("file:")) {
21282
+ try {
21283
+ const url2 = new URL(trimmed);
21284
+ if (url2.protocol !== "file:" || url2.host.length > 0) {
21285
+ return null;
21286
+ }
21287
+ return fileURLToPath2(url2);
21288
+ } catch {
21289
+ return null;
21290
+ }
21291
+ }
21292
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
21293
+ return null;
21294
+ }
21295
+ return trimmed;
21296
+ }
21297
+ async function readAuthorizedRaster(uri, roots, signal) {
21298
+ signal.throwIfAborted();
21299
+ const requested = parseLocalImageUri(uri);
21300
+ if (requested === null) {
21301
+ return null;
21302
+ }
21303
+ const target = await resolveCanonicalPath(requested, signal);
21304
+ if (target === null) {
21305
+ return null;
21306
+ }
21307
+ const targetMetadata = await stat2(target);
21308
+ signal.throwIfAborted();
21309
+ if (!targetMetadata.isFile() || targetMetadata.size < 1 || targetMetadata.size > MAX_LOCAL_RASTER_BYTES) {
21310
+ return null;
21311
+ }
21312
+ const authorizedRoots = [];
21313
+ for (const root of roots) {
21314
+ const directory = await resolveCanonicalPath(root, signal);
21315
+ if (directory === null) {
21316
+ continue;
21317
+ }
21318
+ const metadata = await stat2(directory);
21319
+ signal.throwIfAborted();
21320
+ if (metadata.isDirectory()) {
21321
+ authorizedRoots.push(directory);
21322
+ }
21323
+ }
21324
+ if (!authorizedRoots.some((root) => isInsideRoot(root, target))) {
21325
+ return null;
21326
+ }
21327
+ const bytes = new Uint8Array(await readFile(target));
21328
+ signal.throwIfAborted();
21329
+ if (bytes.byteLength < 1 || bytes.byteLength > MAX_LOCAL_RASTER_BYTES) {
21330
+ return null;
21331
+ }
21332
+ const mimeType = sniffRasterMime(bytes);
21333
+ if (mimeType === null) {
21334
+ return null;
21335
+ }
21336
+ return new LocalRasterImage(basename(target) || "Image", mimeType, bytes);
21337
+ }
21338
+
21339
+ // src/native-sessions/history-images.ts
21340
+ var IMAGE_MARKER = /\[@image\]\(([^)\r\n]*)(?:\)|$)/g;
21341
+ async function embedLocalHistoryImages(history, roots, signal) {
21342
+ if (history.status !== "available") {
21343
+ return history;
21344
+ }
21345
+ const messages = [];
21346
+ let imageCharacters = 0;
21347
+ for (const message of history.messages) {
21348
+ signal.throwIfAborted();
21349
+ const resolved = await resolveMessageImages(message, roots, imageCharacters, signal);
21350
+ imageCharacters += (resolved.images ?? []).reduce((size, image) => size + image.data.length, 0);
21351
+ messages.push(resolved);
21352
+ }
21353
+ return {
21354
+ ...history,
21355
+ messages
21356
+ };
21357
+ }
21358
+ async function resolveMessageImages(message, roots, usedCharacters, signal) {
21359
+ const images = [...message.images ?? []];
21360
+ let imageCharacters = images.reduce((size, image) => size + image.data.length, 0);
21361
+ const text = await replaceImageMarkers(message.text, async (uri) => {
21362
+ if (images.length >= 8 || usedCharacters + imageCharacters >= SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
21363
+ return "[Image unavailable]";
21364
+ }
21365
+ const embedded = parseNativeHistoryText(`[@image](${uri})`).images[0];
21366
+ if (embedded !== void 0) {
21367
+ if (usedCharacters + imageCharacters + embedded.data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
21368
+ return "[Image unavailable]";
21369
+ }
21370
+ images.push(embedded);
21371
+ imageCharacters += embedded.data.length;
21372
+ return "";
21373
+ }
21374
+ const local = await readAuthorizedRaster(uri, roots, signal);
21375
+ if (local === null) {
21376
+ return "[Image unavailable]";
21377
+ }
21378
+ const data = local.base64();
21379
+ if (usedCharacters + imageCharacters + data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
21380
+ return "[Image unavailable]";
21381
+ }
21382
+ images.push({
21383
+ data,
21384
+ mimeType: local.mimeType,
21385
+ name: local.name
21386
+ });
21387
+ imageCharacters += data.length;
21388
+ return "";
21389
+ });
21390
+ return {
21391
+ ...message,
21392
+ text,
21393
+ ...images.length > 0 ? { images } : {}
21394
+ };
21395
+ }
21396
+ async function replaceImageMarkers(text, replace) {
21397
+ const matches = [...text.matchAll(IMAGE_MARKER)];
21398
+ if (matches.length === 0) {
21399
+ return text;
21400
+ }
21401
+ let cursor = 0;
21402
+ let rewritten = "";
21403
+ for (const match of matches) {
21404
+ const index = match.index ?? 0;
21405
+ rewritten += text.slice(cursor, index);
21406
+ rewritten += await replace(match[1] ?? "");
21407
+ cursor = index + match[0].length;
21408
+ }
21409
+ return `${rewritten}${text.slice(cursor)}`;
21410
+ }
21411
+
21204
21412
  // src/acp/activity.ts
21205
21413
  var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
21206
21414
  function isRecord4(value) {
@@ -21298,6 +21506,7 @@ function readContentOutputDetail(content) {
21298
21506
  function summarizeDisplayContent(content) {
21299
21507
  return {
21300
21508
  ...content,
21509
+ artifactId: truncate(content.artifactId, 128),
21301
21510
  data: truncate(content.data, AGENT_ACTIVITY_DETAIL_LIMIT),
21302
21511
  mimeType: truncate(content.mimeType, 255),
21303
21512
  name: truncate(content.name, 500),
@@ -21310,7 +21519,7 @@ function summarizeDisplayContent(content) {
21310
21519
  };
21311
21520
  }
21312
21521
  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;
21522
+ 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
21523
  }
21315
21524
  function encodedByteLength(value) {
21316
21525
  return new TextEncoder().encode(JSON.stringify(value)).byteLength;
@@ -21336,6 +21545,7 @@ function recordedDetail(activity) {
21336
21545
  }
21337
21546
  function emptyDisplayContent(type) {
21338
21547
  return {
21548
+ artifactId: "",
21339
21549
  data: "",
21340
21550
  mimeType: "",
21341
21551
  name: "",
@@ -21348,6 +21558,16 @@ function emptyDisplayContent(type) {
21348
21558
  uri: ""
21349
21559
  };
21350
21560
  }
21561
+ function imageDisplayContent(mimeType, name, data, artifactId = "", uri = "") {
21562
+ return {
21563
+ ...emptyDisplayContent("image"),
21564
+ artifactId,
21565
+ data,
21566
+ mimeType,
21567
+ name,
21568
+ uri
21569
+ };
21570
+ }
21351
21571
  function normalizeContentBlock(content) {
21352
21572
  if (content.type === "text") {
21353
21573
  return { ...emptyDisplayContent("text"), text: content.text };
@@ -22139,7 +22359,6 @@ var AcpHistoryReplay = class {
22139
22359
  #messages = [];
22140
22360
  #lastMessageId = null;
22141
22361
  #characters = 0;
22142
- #imageCharacters = 0;
22143
22362
  #truncated = false;
22144
22363
  record = (update) => {
22145
22364
  if (update.sessionUpdate !== "user_message_chunk" && update.sessionUpdate !== "agent_message_chunk") {
@@ -22150,40 +22369,30 @@ var AcpHistoryReplay = class {
22150
22369
  }
22151
22370
  const role = update.sessionUpdate === "user_message_chunk" ? "user" : "assistant";
22152
22371
  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) {
22372
+ 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]`;
22373
+ if (text.length === 0) {
22158
22374
  return;
22159
22375
  }
22160
22376
  const previous = this.#messages.at(-1);
22161
22377
  const id = update.messageId ?? null;
22162
22378
  const continuation = previous?.role === role && id === this.#lastMessageId;
22163
22379
  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
22380
  if (continuation) {
22168
22381
  this.#messages.pop();
22169
22382
  this.#characters -= previous.text.length;
22170
- this.#imageCharacters -= (previous.images ?? []).reduce((size, image) => size + image.data.length, 0);
22171
22383
  }
22172
22384
  const bounded = combined.slice(-SESSION_HISTORY_CHARACTER_LIMIT);
22173
22385
  this.#truncated ||= bounded.length < combined.length;
22174
22386
  this.#messages.push({
22175
22387
  role,
22176
- text: bounded,
22177
- ...images.length > 0 ? { images } : {}
22388
+ text: bounded
22178
22389
  });
22179
22390
  this.#characters += bounded.length;
22180
- this.#imageCharacters += images.reduce((size, image) => size + image.data.length, 0);
22181
22391
  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) {
22392
+ while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT) {
22183
22393
  const removed = this.#messages.shift();
22184
22394
  if (removed !== void 0) {
22185
22395
  this.#characters -= removed.text.length;
22186
- this.#imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
22187
22396
  }
22188
22397
  this.#truncated = true;
22189
22398
  }
@@ -22406,6 +22615,10 @@ var MAX_PRE_SESSION_UPDATES = 100;
22406
22615
  var MAX_PRE_SESSION_UPDATE_BYTES = 1024 * 1024;
22407
22616
  var SESSION_CONTROL_COMMAND_ID = "session-control";
22408
22617
  var NullAcpSessionObserver = class {
22618
+ importLocalImage = (_sessionId, _image, signal) => {
22619
+ signal.throwIfAborted();
22620
+ return Promise.resolve("");
22621
+ };
22409
22622
  onCommands = () => Promise.resolve();
22410
22623
  onConfig = () => Promise.resolve();
22411
22624
  onContent = () => Promise.resolve();
@@ -23028,11 +23241,75 @@ var AcpProcessSession = class _AcpProcessSession {
23028
23241
  );
23029
23242
  await this.#updateTail;
23030
23243
  signal.throwIfAborted();
23031
- return history.snapshot();
23244
+ return await embedLocalHistoryImages(
23245
+ history.snapshot(),
23246
+ [this.#cwd, ...this.#additionalDirectories],
23247
+ signal
23248
+ );
23032
23249
  } finally {
23033
23250
  this.#replay = { kind: "idle" };
23034
23251
  }
23035
23252
  };
23253
+ imageRoots = () => [this.#cwd, ...this.#additionalDirectories];
23254
+ emitAgentText = async (text, messageId) => {
23255
+ const signal = AbortSignal.timeout(2e4);
23256
+ const parts = text.split(/(\[@image\]\([^)\r\n]*(?:\)|$))/);
23257
+ let leftover = "";
23258
+ for (const part of parts) {
23259
+ const marker = /^\[@image\]\(([^)\r\n]*)(?:\)|$)/.exec(part);
23260
+ if (marker === null) {
23261
+ leftover += part;
23262
+ continue;
23263
+ }
23264
+ if (leftover.length > 0) {
23265
+ await this.#turn.onText(leftover, messageId);
23266
+ leftover = "";
23267
+ }
23268
+ const raster = await readAuthorizedRaster(marker[1] ?? "", this.imageRoots(), signal);
23269
+ if (raster === null) {
23270
+ leftover += "[Image unavailable]";
23271
+ continue;
23272
+ }
23273
+ await this.emitRaster(raster, messageId, signal);
23274
+ }
23275
+ if (leftover.length > 0) {
23276
+ await this.#turn.onText(leftover, messageId);
23277
+ }
23278
+ };
23279
+ emitAgentContent = async (content, messageId) => {
23280
+ if (content.type === "image" && content.data.length === 0 && content.uri.length > 0) {
23281
+ const signal = AbortSignal.timeout(2e4);
23282
+ const raster = await readAuthorizedRaster(content.uri, this.imageRoots(), signal);
23283
+ if (raster !== null) {
23284
+ await this.emitRaster(raster, messageId, signal);
23285
+ return;
23286
+ }
23287
+ }
23288
+ await this.#getObserver().onContent({
23289
+ commandId: this.#turn.commandId,
23290
+ content,
23291
+ contentId: `content-${crypto.randomUUID()}`,
23292
+ kind: AGENT_CONTENT_KIND,
23293
+ messageId,
23294
+ sessionId: this.#mobiusSessionId
23295
+ });
23296
+ };
23297
+ emitRaster = async (raster, messageId, signal) => {
23298
+ const artifactId = await this.#getObserver().importLocalImage(this.#mobiusSessionId, raster, signal);
23299
+ await this.#getObserver().onContent({
23300
+ commandId: this.#turn.commandId,
23301
+ content: imageDisplayContent(
23302
+ raster.mimeType,
23303
+ raster.name,
23304
+ artifactId.length > 0 ? "" : raster.base64(),
23305
+ artifactId
23306
+ ),
23307
+ contentId: `content-${crypto.randomUUID()}`,
23308
+ kind: AGENT_CONTENT_KIND,
23309
+ messageId,
23310
+ sessionId: this.#mobiusSessionId
23311
+ });
23312
+ };
23036
23313
  async #initializeAgent(signal) {
23037
23314
  const initialized = await this.race(
23038
23315
  this.#connection.agent.request(
@@ -23735,18 +24012,14 @@ var AcpProcessSession = class _AcpProcessSession {
23735
24012
  );
23736
24013
  } else {
23737
24014
  await this.#turn.activities.finishNarrative();
23738
- await this.#turn.onText(update.content.text, truncate3(update.messageId ?? "", 255));
24015
+ await this.emitAgentText(update.content.text, truncate3(update.messageId ?? "", 255));
23739
24016
  }
23740
24017
  } else {
23741
24018
  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
- });
24019
+ await this.emitAgentContent(
24020
+ normalizeContentBlock(update.content),
24021
+ truncate3(update.messageId ?? "", 255)
24022
+ );
23750
24023
  }
23751
24024
  return;
23752
24025
  }
@@ -24612,7 +24885,7 @@ var AuditStore = class {
24612
24885
  this.database.exec("ALTER TABLE audit_events ADD COLUMN details_json TEXT NOT NULL DEFAULT '{}'");
24613
24886
  }
24614
24887
  }
24615
- record(record2) {
24888
+ record(record3) {
24616
24889
  this.database.prepare(
24617
24890
  `
24618
24891
  INSERT INTO audit_events (
@@ -24625,10 +24898,10 @@ var AuditStore = class {
24625
24898
  `
24626
24899
  ).run(
24627
24900
  (/* @__PURE__ */ new Date()).toISOString(),
24628
- record2.event,
24629
- record2.commandId,
24630
- record2.sessionId,
24631
- JSON.stringify(record2.details ?? {})
24901
+ record3.event,
24902
+ record3.commandId,
24903
+ record3.sessionId,
24904
+ JSON.stringify(record3.details ?? {})
24632
24905
  );
24633
24906
  }
24634
24907
  close() {
@@ -24650,7 +24923,7 @@ import { randomBytes } from "node:crypto";
24650
24923
 
24651
24924
  // src/bots/local-bot-grant-store.ts
24652
24925
  import { createHash, randomUUID } from "node:crypto";
24653
- import { stat as stat2 } from "node:fs/promises";
24926
+ import { stat as stat3 } from "node:fs/promises";
24654
24927
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
24655
24928
  var LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS = 90 * 24 * 60 * 60 * 1e3;
24656
24929
  var LocalBotAuthorizationError = class extends Error {
@@ -24708,7 +24981,7 @@ function agentDigest(agent) {
24708
24981
  );
24709
24982
  }
24710
24983
  async function workspaceDigest(path2) {
24711
- const metadata = await stat2(path2);
24984
+ const metadata = await stat3(path2);
24712
24985
  if (!metadata.isDirectory()) {
24713
24986
  throw new LocalBotAuthorizationError("binding_incompatible", "The Bot workspace is not a directory");
24714
24987
  }
@@ -25246,7 +25519,7 @@ async function executeBotMessageCommand(arguments_, environment, signal) {
25246
25519
  // src/bots/bot-outbound-ipc.ts
25247
25520
  import { chmod, mkdir, unlink } from "node:fs/promises";
25248
25521
  import { createServer } from "node:net";
25249
- import { dirname as dirname3, isAbsolute } from "node:path";
25522
+ import { dirname as dirname3, isAbsolute as isAbsolute2 } from "node:path";
25250
25523
  import { fetch } from "undici";
25251
25524
  var BOT_IPC_REQUEST_LIMIT = 32 * 1024;
25252
25525
  var BOT_IPC_TIMEOUT_MILLISECONDS2 = 2e4;
@@ -25344,7 +25617,7 @@ var BotOutboundIpcServer = class {
25344
25617
  #usesFilesystemSocket;
25345
25618
  constructor(socketPath, relayUrl, registry2) {
25346
25619
  const usesFilesystemSocket = !socketPath.startsWith(WINDOWS_NAMED_PIPE_PREFIX);
25347
- if (usesFilesystemSocket && !isAbsolute(socketPath)) {
25620
+ if (usesFilesystemSocket && !isAbsolute2(socketPath)) {
25348
25621
  throw new Error("The Bot IPC path must be absolute");
25349
25622
  }
25350
25623
  this.#registry = registry2;
@@ -25484,9 +25757,9 @@ var BotOutboundIpcServer = class {
25484
25757
 
25485
25758
  // src/pairing/pair-local-machine.ts
25486
25759
  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";
25760
+ import { mkdir as mkdir4, open as open4, realpath as realpath7, rename as rename3, stat as stat7, writeFile as writeFile2 } from "node:fs/promises";
25488
25761
  import { hostname as hostname3 } from "node:os";
25489
- import { basename, join as join14, resolve as resolve3 } from "node:path";
25762
+ import { basename as basename2, join as join14, resolve as resolve3 } from "node:path";
25490
25763
  import { fetch as fetch3 } from "undici";
25491
25764
 
25492
25765
  // src/agent-catalog/agent-discovery.ts
@@ -25595,8 +25868,8 @@ var LocalAgentInventory = class {
25595
25868
  };
25596
25869
 
25597
25870
  // 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";
25871
+ import { mkdir as mkdir2, mkdtemp, open as open2, realpath as realpath3, rename, rm, stat as stat4 } from "node:fs/promises";
25872
+ import { delimiter, dirname as dirname4, isAbsolute as isAbsolute3, join as join4, relative as relative2, sep as sep2 } from "node:path";
25600
25873
  var INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
25601
25874
  var PACKAGE_METADATA_LIMIT_BYTES = 64 * 1024;
25602
25875
  var PACKAGE_LOCK_LIMIT_BYTES = 8 * 1024 * 1024;
@@ -25650,8 +25923,8 @@ function packagePath(root, packageName) {
25650
25923
  return join4(root, "node_modules", ...packageName.split("/"));
25651
25924
  }
25652
25925
  function isContainedPath(root, candidate) {
25653
- const difference = relative(root, candidate);
25654
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep}`) && !isAbsolute2(difference);
25926
+ const difference = relative2(root, candidate);
25927
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute3(difference);
25655
25928
  }
25656
25929
  async function readJsonRecord(path2, maximumBytes) {
25657
25930
  try {
@@ -25752,7 +26025,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
25752
26025
  }
25753
26026
  }
25754
26027
  async function verifyRequiredDependency(rootPath, lock, definition) {
25755
- const dependencyRoot = await realpath2(packagePath(rootPath, definition.packageName));
26028
+ const dependencyRoot = await realpath3(packagePath(rootPath, definition.packageName));
25756
26029
  if (!isContainedPath(rootPath, dependencyRoot)) {
25757
26030
  throw new ManagedNpmPackageError(
25758
26031
  "managed_package_verification_failed",
@@ -25781,8 +26054,8 @@ async function validateManagedNpmPackage(root, definition) {
25781
26054
  }
25782
26055
  }
25783
26056
  async function validateManagedNpmPackageContents(root, definition) {
25784
- const rootPath = await realpath2(root);
25785
- const packageRoot = await realpath2(packagePath(rootPath, definition.packageName));
26057
+ const rootPath = await realpath3(root);
26058
+ const packageRoot = await realpath3(packagePath(rootPath, definition.packageName));
25786
26059
  if (!isContainedPath(rootPath, packageRoot)) {
25787
26060
  throw new ManagedNpmPackageError(
25788
26061
  "managed_package_verification_failed",
@@ -25817,7 +26090,7 @@ var ManagedNpmPackageInstaller = class {
25817
26090
  install = async (root, definition, environment, signal) => {
25818
26091
  signal.throwIfAborted();
25819
26092
  try {
25820
- const metadata = await stat3(root);
26093
+ const metadata = await stat4(root);
25821
26094
  if (metadata.isDirectory()) {
25822
26095
  return await validateManagedNpmPackage(root, definition);
25823
26096
  }
@@ -26084,8 +26357,8 @@ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
26084
26357
  };
26085
26358
 
26086
26359
  // 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";
26360
+ import { realpath as realpath4, stat as stat5 } from "node:fs/promises";
26361
+ import { isAbsolute as isAbsolute4, join as join6, normalize as normalize2 } from "node:path";
26089
26362
 
26090
26363
  // src/agent-installation/deepseek-managed-package.ts
26091
26364
  var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
@@ -26103,12 +26376,12 @@ var DEEPSEEK_HARNESS_PACKAGE = new DeepSeekHarnessManagedPackage(
26103
26376
 
26104
26377
  // src/agent-catalog/agents/deepseek-harness-agent.ts
26105
26378
  async function validateAgentHome(path2) {
26106
- if (!isAbsolute3(path2) || normalize(path2) !== path2) {
26379
+ if (!isAbsolute4(path2) || normalize2(path2) !== path2) {
26107
26380
  throw new AgentProbeError("agent_environment_invalid", "The configured Agent home is invalid");
26108
26381
  }
26109
26382
  try {
26110
- const resolved = await realpath3(path2);
26111
- const metadata = await stat4(resolved);
26383
+ const resolved = await realpath4(path2);
26384
+ const metadata = await stat5(resolved);
26112
26385
  if (!metadata.isDirectory() || typeof process.getuid === "function" && metadata.uid !== process.getuid()) {
26113
26386
  throw new Error("Agent home is not a user-owned directory");
26114
26387
  }
@@ -26190,8 +26463,8 @@ var DeepSeekHarnessAgentSpecification = class extends DirectAcpAgentDefinition {
26190
26463
  };
26191
26464
 
26192
26465
  // 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";
26466
+ import { realpath as realpath5 } from "node:fs/promises";
26467
+ import { isAbsolute as isAbsolute5, join as join7, relative as relative3, sep as sep3 } from "node:path";
26195
26468
 
26196
26469
  // src/agent-installation/grok-managed-package.ts
26197
26470
  var GROK_BUILD_MANAGED_VERSION = "1.0.21";
@@ -26253,8 +26526,8 @@ function grokBuildManagedPackage(platform, architecture) {
26253
26526
 
26254
26527
  // src/agent-catalog/agents/grok-build-agent.ts
26255
26528
  function isContainedPath2(root, candidate) {
26256
- const difference = relative2(root, candidate);
26257
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute4(difference);
26529
+ const difference = relative3(root, candidate);
26530
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute5(difference);
26258
26531
  }
26259
26532
  var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
26260
26533
  adapterVersion = GROK_BUILD_MANAGED_VERSION;
@@ -26281,7 +26554,7 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
26281
26554
  );
26282
26555
  if (managed.path === agent.path) {
26283
26556
  return Object.freeze({
26284
- GROK_HOME: await realpath4(
26557
+ GROK_HOME: await realpath5(
26285
26558
  join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION, "home")
26286
26559
  )
26287
26560
  });
@@ -26293,7 +26566,7 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
26293
26566
  };
26294
26567
  resolveManagedAgent = async (stateDirectory, platform, signal) => {
26295
26568
  signal.throwIfAborted();
26296
- const versionRoot = await realpath4(join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION));
26569
+ const versionRoot = await realpath5(join7(stateDirectory, "agents", this.id, GROK_BUILD_MANAGED_VERSION));
26297
26570
  await validateManagedNpmPackage(join7(versionRoot, "package"), grokBuildManagedPackage(platform, process.arch));
26298
26571
  const executable = await resolveExecutablePath(join7(versionRoot, "home", "bin", "grok"), platform);
26299
26572
  signal.throwIfAborted();
@@ -26318,8 +26591,8 @@ import { join as join9 } from "node:path";
26318
26591
  // src/agent-installation/managed-agent-archive.ts
26319
26592
  import { createHash as createHash2 } from "node:crypto";
26320
26593
  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";
26594
+ 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";
26595
+ import { dirname as dirname5, isAbsolute as isAbsolute6, join as join8, relative as relative4, sep as sep4 } from "node:path";
26323
26596
 
26324
26597
  // src/agent-installation/verified-download.ts
26325
26598
  import { fetch as fetch2 } from "undici";
@@ -26424,8 +26697,8 @@ function isRecord10(value) {
26424
26697
  return typeof value === "object" && value !== null && !Array.isArray(value);
26425
26698
  }
26426
26699
  function isContainedPath3(root, candidate) {
26427
- const difference = relative3(root, candidate);
26428
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute5(difference);
26700
+ const difference = relative4(root, candidate);
26701
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep4}`) && !isAbsolute6(difference);
26429
26702
  }
26430
26703
  async function hashFile(path2, signal) {
26431
26704
  signal.throwIfAborted();
@@ -26499,8 +26772,8 @@ async function readManifest(path2) {
26499
26772
  }
26500
26773
  async function validateManagedAgentArchive(root, definition, signal) {
26501
26774
  try {
26502
- const rootPath = await realpath5(root);
26503
- const rootMetadata = await stat5(rootPath);
26775
+ const rootPath = await realpath6(root);
26776
+ const rootMetadata = await stat6(rootPath);
26504
26777
  if (!rootMetadata.isDirectory() || typeof process.getuid === "function" && rootMetadata.uid !== process.getuid()) {
26505
26778
  throw new Error("Managed Agent root is not user-owned");
26506
26779
  }
@@ -26715,7 +26988,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
26715
26988
  };
26716
26989
 
26717
26990
  // src/agent-catalog/agents/workbuddy-agent.ts
26718
- import { isAbsolute as isAbsolute6, join as join11 } from "node:path";
26991
+ import { isAbsolute as isAbsolute7, join as join11 } from "node:path";
26719
26992
 
26720
26993
  // src/agent-installation/workbuddy-managed-package.ts
26721
26994
  var WORKBUDDY_MANAGED_VERSION = "2.146.0";
@@ -26781,7 +27054,7 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
26781
27054
  }
26782
27055
  const requestedPaths = [join11("/Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH)];
26783
27056
  const homeDirectory = context.environment["HOME"];
26784
- if (homeDirectory !== void 0 && isAbsolute6(homeDirectory)) {
27057
+ if (homeDirectory !== void 0 && isAbsolute7(homeDirectory)) {
26785
27058
  requestedPaths.unshift(join11(homeDirectory, "Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH));
26786
27059
  }
26787
27060
  const executables = [];
@@ -26827,7 +27100,7 @@ import {
26827
27100
  } from "@agentclientprotocol/sdk";
26828
27101
 
26829
27102
  // src/agent-catalog/executable-discovery.ts
26830
- import { isAbsolute as isAbsolute7, join as join13 } from "node:path";
27103
+ import { isAbsolute as isAbsolute8, join as join13 } from "node:path";
26831
27104
 
26832
27105
  // src/agent-installation/managed-adapter-installer.ts
26833
27106
  import { join as join12 } from "node:path";
@@ -26932,7 +27205,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
26932
27205
  async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, resolveManaged, context) {
26933
27206
  const override = context.environment[overrideVariable];
26934
27207
  if (override !== void 0) {
26935
- if (override.length === 0 || !isAbsolute7(override)) {
27208
+ if (override.length === 0 || !isAbsolute8(override)) {
26936
27209
  return [];
26937
27210
  }
26938
27211
  const executable = await resolveExecutablePath(override, context.platform);
@@ -27460,8 +27733,8 @@ async function resolveDefaultWorkspace(path2) {
27460
27733
  const requestedWorkspace = resolve3(path2);
27461
27734
  try {
27462
27735
  await mkdir4(requestedWorkspace, { recursive: true, mode: 448 });
27463
- const defaultWorkspace = await realpath6(requestedWorkspace);
27464
- const metadata = await stat6(defaultWorkspace);
27736
+ const defaultWorkspace = await realpath7(requestedWorkspace);
27737
+ const metadata = await stat7(defaultWorkspace);
27465
27738
  if (!metadata.isDirectory()) {
27466
27739
  throw new PairingClientError("invalid_workspace", "The default workspace is not a directory");
27467
27740
  }
@@ -27531,7 +27804,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
27531
27804
  installableAgents,
27532
27805
  machineName: hostname3(),
27533
27806
  pairingCode: options.code,
27534
- workspaceName: basename(defaultWorkspace) || "Local workspace"
27807
+ workspaceName: basename2(defaultWorkspace) || "Local workspace"
27535
27808
  }),
27536
27809
  dispatcher: environmentProxyDispatcher,
27537
27810
  headers: { "content-type": "application/json" },
@@ -27702,9 +27975,9 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
27702
27975
 
27703
27976
  // src/run-daemon.ts
27704
27977
  import { randomUUID as randomUUID6 } from "node:crypto";
27705
- import { basename as basename4, join as join16 } from "node:path";
27978
+ import { basename as basename5, join as join16 } from "node:path";
27706
27979
  import { styleText } from "node:util";
27707
- import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
27980
+ import { fetch as fetch7, WebSocket as WebSocket2 } from "undici";
27708
27981
 
27709
27982
  // src/agent-catalog/publish-agent-catalog.ts
27710
27983
  import { fetch as fetch4 } from "undici";
@@ -28247,10 +28520,406 @@ var FixedInstallationExecutor = class {
28247
28520
  };
28248
28521
  };
28249
28522
 
28523
+ // src/artifacts/runtime-artifact-uploader.ts
28524
+ import { createHash as createHash3 } from "node:crypto";
28525
+
28526
+ // ../mobius-sdk/src/errors.ts
28527
+ var MobiusError = class extends Error {
28528
+ code;
28529
+ constructor(code, message, options = {}) {
28530
+ super(message, options);
28531
+ this.code = code;
28532
+ this.name = "MobiusError";
28533
+ }
28534
+ };
28535
+ var MobiusProtocolError = class extends MobiusError {
28536
+ constructor(message, options = {}) {
28537
+ super("invalid_service_response", message, options);
28538
+ this.name = "MobiusProtocolError";
28539
+ }
28540
+ };
28541
+ var MobiusValidationError = class extends MobiusError {
28542
+ constructor(message, options = {}) {
28543
+ super("invalid_request", message, options);
28544
+ this.name = "MobiusValidationError";
28545
+ }
28546
+ };
28547
+
28548
+ // ../mobius-sdk/src/resources.ts
28549
+ var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
28550
+ function invalidResponse(message) {
28551
+ return new MobiusProtocolError(message);
28552
+ }
28553
+ function isRecord12(value) {
28554
+ return typeof value === "object" && value !== null && !Array.isArray(value);
28555
+ }
28556
+ function record2(value, name) {
28557
+ if (!isRecord12(value)) {
28558
+ throw invalidResponse(`The service returned an invalid ${name}`);
28559
+ }
28560
+ return value;
28561
+ }
28562
+ function stringField(value, field, maximumLength = 85e5) {
28563
+ const candidate = value[field];
28564
+ if (typeof candidate !== "string" || candidate.length > maximumLength) {
28565
+ throw invalidResponse(`The service returned an invalid ${field}`);
28566
+ }
28567
+ return candidate;
28568
+ }
28569
+ function identifierField(value, field) {
28570
+ const candidate = stringField(value, field, 128);
28571
+ if (!IDENTIFIER_PATTERN7.test(candidate)) {
28572
+ throw invalidResponse(`The service returned an invalid ${field}`);
28573
+ }
28574
+ return candidate;
28575
+ }
28576
+ function integerField(value, field) {
28577
+ const candidate = value[field];
28578
+ if (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0) {
28579
+ throw invalidResponse(`The service returned an invalid ${field}`);
28580
+ }
28581
+ return candidate;
28582
+ }
28583
+ function validateTimestamp(value, field) {
28584
+ if (Number.isNaN(Date.parse(value))) {
28585
+ throw invalidResponse(`The service returned an invalid ${field}`);
28586
+ }
28587
+ return value;
28588
+ }
28589
+ var MobiusArtifactUploadRequest = class {
28590
+ byteLength;
28591
+ mediaType;
28592
+ name;
28593
+ sha256;
28594
+ constructor(name, mediaType, byteLength, sha256) {
28595
+ 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)) {
28596
+ throw new MobiusValidationError("The artifact upload request is invalid");
28597
+ }
28598
+ this.byteLength = byteLength;
28599
+ this.mediaType = mediaType;
28600
+ this.name = name;
28601
+ this.sha256 = sha256;
28602
+ }
28603
+ };
28604
+ var MobiusArtifact = class {
28605
+ artifactId;
28606
+ byteLength;
28607
+ createdAt;
28608
+ mediaType;
28609
+ name;
28610
+ sessionId;
28611
+ sha256;
28612
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt) {
28613
+ this.artifactId = artifactId;
28614
+ this.byteLength = byteLength;
28615
+ this.createdAt = createdAt;
28616
+ this.mediaType = mediaType;
28617
+ this.name = name;
28618
+ this.sessionId = sessionId;
28619
+ this.sha256 = sha256;
28620
+ }
28621
+ };
28622
+ var MobiusUploadingArtifact = class extends MobiusArtifact {
28623
+ expiresAt;
28624
+ state = "uploading";
28625
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiresAt) {
28626
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
28627
+ this.expiresAt = expiresAt;
28628
+ }
28629
+ };
28630
+ var MobiusArtifactUpload = class extends MobiusUploadingArtifact {
28631
+ uploadToken;
28632
+ constructor(artifact, uploadToken) {
28633
+ super(
28634
+ artifact.sessionId,
28635
+ artifact.artifactId,
28636
+ artifact.name,
28637
+ artifact.mediaType,
28638
+ artifact.byteLength,
28639
+ artifact.sha256,
28640
+ artifact.createdAt,
28641
+ artifact.expiresAt
28642
+ );
28643
+ this.uploadToken = uploadToken;
28644
+ }
28645
+ };
28646
+ var MobiusAvailableArtifact = class extends MobiusArtifact {
28647
+ availableAt;
28648
+ state = "available";
28649
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, availableAt) {
28650
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
28651
+ this.availableAt = availableAt;
28652
+ }
28653
+ };
28654
+ var MobiusExpiredArtifact = class extends MobiusArtifact {
28655
+ expiredAt;
28656
+ state = "expired";
28657
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiredAt) {
28658
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
28659
+ this.expiredAt = expiredAt;
28660
+ }
28661
+ };
28662
+ function artifactFields(value) {
28663
+ const sha256 = stringField(value, "sha256", 64);
28664
+ if (!/^[a-f0-9]{64}$/.test(sha256)) {
28665
+ throw invalidResponse("The service returned an invalid artifact digest");
28666
+ }
28667
+ return {
28668
+ artifactId: identifierField(value, "artifactId"),
28669
+ byteLength: integerField(value, "byteLength"),
28670
+ createdAt: validateTimestamp(stringField(value, "createdAt", 128), "createdAt"),
28671
+ mediaType: stringField(value, "mediaType", 255),
28672
+ name: stringField(value, "name", 500),
28673
+ sessionId: identifierField(value, "sessionId"),
28674
+ sha256
28675
+ };
28676
+ }
28677
+ function uploadingArtifact(value) {
28678
+ const fields = artifactFields(value);
28679
+ return new MobiusUploadingArtifact(
28680
+ fields.sessionId,
28681
+ fields.artifactId,
28682
+ fields.name,
28683
+ fields.mediaType,
28684
+ fields.byteLength,
28685
+ fields.sha256,
28686
+ fields.createdAt,
28687
+ validateTimestamp(stringField(value, "expiresAt", 128), "expiresAt")
28688
+ );
28689
+ }
28690
+ function decodeMobiusArtifactUpload(value) {
28691
+ const artifact = record2(value, "artifact upload authorization");
28692
+ return new MobiusArtifactUpload(uploadingArtifact(artifact), stringField(artifact, "uploadToken", 256));
28693
+ }
28694
+ function decodeMobiusArtifact(value) {
28695
+ const artifact = record2(value, "artifact");
28696
+ const state = stringField(artifact, "state", 32);
28697
+ if (state === "uploading") {
28698
+ return uploadingArtifact(artifact);
28699
+ }
28700
+ const fields = artifactFields(artifact);
28701
+ if (state === "available") {
28702
+ return new MobiusAvailableArtifact(
28703
+ fields.sessionId,
28704
+ fields.artifactId,
28705
+ fields.name,
28706
+ fields.mediaType,
28707
+ fields.byteLength,
28708
+ fields.sha256,
28709
+ fields.createdAt,
28710
+ validateTimestamp(stringField(artifact, "availableAt", 128), "availableAt")
28711
+ );
28712
+ }
28713
+ if (state === "expired") {
28714
+ return new MobiusExpiredArtifact(
28715
+ fields.sessionId,
28716
+ fields.artifactId,
28717
+ fields.name,
28718
+ fields.mediaType,
28719
+ fields.byteLength,
28720
+ fields.sha256,
28721
+ fields.createdAt,
28722
+ validateTimestamp(stringField(artifact, "expiredAt", 128), "expiredAt")
28723
+ );
28724
+ }
28725
+ throw invalidResponse("The service returned an invalid artifact state");
28726
+ }
28727
+ function decodeMobiusAvailableArtifact(value) {
28728
+ const artifact = decodeMobiusArtifact(value);
28729
+ if (!(artifact instanceof MobiusAvailableArtifact)) {
28730
+ throw invalidResponse("The service did not make the artifact available");
28731
+ }
28732
+ return artifact;
28733
+ }
28734
+ var MobiusRuntimePairingLifecycle = Object.freeze({
28735
+ Expired: "expired",
28736
+ Paired: "paired",
28737
+ Pending: "pending",
28738
+ Revoked: "revoked"
28739
+ });
28740
+
28741
+ // src/artifacts/runtime-artifact-uploader.ts
28742
+ import { fetch as fetch5 } from "undici";
28743
+ var UPLOAD_TIMEOUT_MILLISECONDS = 2e4;
28744
+ var RuntimeArtifactUploadError = class extends Error {
28745
+ code;
28746
+ constructor(code, message, options = {}) {
28747
+ super(message, options);
28748
+ this.code = code;
28749
+ this.name = "RuntimeArtifactUploadError";
28750
+ }
28751
+ };
28752
+ var UploadedRuntimeArtifact = class {
28753
+ artifactId;
28754
+ byteLength;
28755
+ mimeType;
28756
+ name;
28757
+ sha256;
28758
+ constructor(artifactId, name, mimeType, byteLength, sha256) {
28759
+ this.artifactId = artifactId;
28760
+ this.byteLength = byteLength;
28761
+ this.mimeType = mimeType;
28762
+ this.name = name;
28763
+ this.sha256 = sha256;
28764
+ }
28765
+ };
28766
+ function daemonToken2(config2) {
28767
+ const token = config2.relayUrl.searchParams.get("token");
28768
+ if (token === null || token.length < 32) {
28769
+ throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay daemon token is missing");
28770
+ }
28771
+ return token;
28772
+ }
28773
+ function channelOrigin(config2) {
28774
+ const url2 = new URL(config2.relayUrl);
28775
+ url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
28776
+ let channelPath = "";
28777
+ if (url2.pathname.endsWith("/daemon")) {
28778
+ channelPath = url2.pathname.slice(0, -"/daemon".length);
28779
+ } else {
28780
+ const runtimePath = `${MOBIUS_API_PREFIX}/v1/runtimes/connect`;
28781
+ if (!url2.pathname.endsWith("/v1/runtimes/connect") && !url2.pathname.endsWith(runtimePath)) {
28782
+ throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay artifact endpoint is invalid");
28783
+ }
28784
+ channelPath = `${url2.pathname.replace(/\/v1\/runtimes\/connect$/, "")}/channels/${encodeURIComponent(config2.channelId)}`;
28785
+ }
28786
+ url2.pathname = channelPath;
28787
+ url2.search = "";
28788
+ url2.hash = "";
28789
+ return url2;
28790
+ }
28791
+ function uploadError(code, message, cause) {
28792
+ return new RuntimeArtifactUploadError(code, message, cause === void 0 ? {} : { cause });
28793
+ }
28794
+ function translateSdkError(cause) {
28795
+ if (cause instanceof MobiusValidationError) {
28796
+ throw uploadError("artifact_upload_failed", cause.message, cause);
28797
+ }
28798
+ if (cause instanceof MobiusProtocolError) {
28799
+ throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
28800
+ }
28801
+ throw cause;
28802
+ }
28803
+ async function readJson(response) {
28804
+ try {
28805
+ return await response.json();
28806
+ } catch (cause) {
28807
+ throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
28808
+ }
28809
+ }
28810
+ async function readAuthorization(response) {
28811
+ try {
28812
+ return decodeMobiusArtifactUpload(await readJson(response));
28813
+ } catch (cause) {
28814
+ translateSdkError(cause);
28815
+ }
28816
+ }
28817
+ function sessionArtifactUrl(origin, sessionId, resourcePath, token) {
28818
+ const url2 = new URL(`${origin.pathname}/sessions/${encodeURIComponent(sessionId)}/${resourcePath}`, origin);
28819
+ url2.searchParams.set("token", token);
28820
+ return url2;
28821
+ }
28822
+ async function postLease(url2, request, signal) {
28823
+ return await fetch5(url2, {
28824
+ dispatcher: environmentProxyDispatcher,
28825
+ headers: { "content-type": "application/json" },
28826
+ method: "POST",
28827
+ body: JSON.stringify(request),
28828
+ signal
28829
+ });
28830
+ }
28831
+ async function putContent(url2, authorization, bytes, signal) {
28832
+ return await fetch5(url2, {
28833
+ dispatcher: environmentProxyDispatcher,
28834
+ headers: {
28835
+ "content-type": authorization.mediaType,
28836
+ "x-mobius-upload-token": authorization.uploadToken
28837
+ },
28838
+ method: "PUT",
28839
+ body: bytes,
28840
+ signal
28841
+ });
28842
+ }
28843
+ async function uploadRuntimeArtifact(config2, sessionId, image, signal) {
28844
+ signal.throwIfAborted();
28845
+ let request;
28846
+ try {
28847
+ request = new MobiusArtifactUploadRequest(
28848
+ image.name,
28849
+ image.mimeType,
28850
+ image.bytes.byteLength,
28851
+ createHash3("sha256").update(image.bytes).digest("hex")
28852
+ );
28853
+ } catch (cause) {
28854
+ translateSdkError(cause);
28855
+ }
28856
+ const timeoutSignal = AbortSignal.timeout(UPLOAD_TIMEOUT_MILLISECONDS);
28857
+ const requestSignal = AbortSignal.any([signal, timeoutSignal]);
28858
+ const origin = channelOrigin(config2);
28859
+ const token = daemonToken2(config2);
28860
+ let created;
28861
+ try {
28862
+ created = await postLease(
28863
+ sessionArtifactUrl(origin, sessionId, "artifacts/uploads", token),
28864
+ request,
28865
+ requestSignal
28866
+ );
28867
+ } catch (cause) {
28868
+ signal.throwIfAborted();
28869
+ throw uploadError(
28870
+ timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
28871
+ timeoutSignal.aborted ? "The artifact upload authorization timed out" : "The artifact upload could not start",
28872
+ cause
28873
+ );
28874
+ }
28875
+ if (!created.ok) {
28876
+ await created.body?.cancel();
28877
+ throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact upload");
28878
+ }
28879
+ const authorization = await readAuthorization(created);
28880
+ let uploaded;
28881
+ try {
28882
+ uploaded = await putContent(
28883
+ sessionArtifactUrl(
28884
+ origin,
28885
+ sessionId,
28886
+ `artifacts/${encodeURIComponent(authorization.artifactId)}/content`,
28887
+ token
28888
+ ),
28889
+ authorization,
28890
+ image.bytes,
28891
+ requestSignal
28892
+ );
28893
+ } catch (cause) {
28894
+ signal.throwIfAborted();
28895
+ throw uploadError(
28896
+ timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
28897
+ timeoutSignal.aborted ? "The artifact upload timed out" : "The artifact content could not be uploaded",
28898
+ cause
28899
+ );
28900
+ }
28901
+ if (!uploaded.ok) {
28902
+ await uploaded.body?.cancel();
28903
+ throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact content");
28904
+ }
28905
+ try {
28906
+ const available = decodeMobiusAvailableArtifact(await readJson(uploaded));
28907
+ return new UploadedRuntimeArtifact(
28908
+ available.artifactId,
28909
+ available.name,
28910
+ available.mediaType,
28911
+ available.byteLength,
28912
+ available.sha256
28913
+ );
28914
+ } catch (cause) {
28915
+ translateSdkError(cause);
28916
+ }
28917
+ }
28918
+
28250
28919
  // src/authorization/workspace-directory.ts
28251
- import { readdir, realpath as realpath7, stat as stat7 } from "node:fs/promises";
28920
+ import { readdir, realpath as realpath8, stat as stat8 } from "node:fs/promises";
28252
28921
  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";
28922
+ import { basename as basename3, dirname as dirname6, isAbsolute as isAbsolute9, join as join15, normalize as normalize3, relative as relative5 } from "node:path";
28254
28923
  var WorkspaceDirectoryListing = class {
28255
28924
  directoryId;
28256
28925
  directoryLabel;
@@ -28276,7 +28945,7 @@ function decodePath(value, prefix) {
28276
28945
  throw new LocalAuthorizationError("The directory identifier is invalid");
28277
28946
  }
28278
28947
  const decoded = Buffer.from(encoded, "base64url").toString("utf8");
28279
- if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize2(decoded) !== decoded) {
28948
+ if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize3(decoded) !== decoded) {
28280
28949
  throw new LocalAuthorizationError("The directory identifier is invalid");
28281
28950
  }
28282
28951
  return decoded;
@@ -28302,7 +28971,7 @@ var WorkspaceDirectoryService = class {
28302
28971
  }
28303
28972
  if (id.startsWith("path-")) {
28304
28973
  const path2 = decodePath(id, "path-");
28305
- if (isAbsolute8(path2)) {
28974
+ if (isAbsolute9(path2)) {
28306
28975
  return path2;
28307
28976
  }
28308
28977
  }
@@ -28310,15 +28979,15 @@ var WorkspaceDirectoryService = class {
28310
28979
  };
28311
28980
  resolvePath = async (requested, signal) => {
28312
28981
  signal.throwIfAborted();
28313
- if (!isAbsolute8(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
28982
+ if (!isAbsolute9(requested) || requested.includes("\0") || normalize3(requested) !== requested) {
28314
28983
  throw new LocalAuthorizationError("The local directory path is invalid");
28315
28984
  }
28316
28985
  try {
28317
- const target = await realpath7(requested);
28986
+ const target = await realpath8(requested);
28318
28987
  signal.throwIfAborted();
28319
- const metadata = await stat7(target);
28988
+ const metadata = await stat8(target);
28320
28989
  signal.throwIfAborted();
28321
- if (!isAbsolute8(target) || normalize2(target) !== target || !metadata.isDirectory()) {
28990
+ if (!isAbsolute9(target) || normalize3(target) !== target || !metadata.isDirectory()) {
28322
28991
  throw new LocalAuthorizationError("The selected location is not a directory");
28323
28992
  }
28324
28993
  return target;
@@ -28333,8 +29002,8 @@ var WorkspaceDirectoryService = class {
28333
29002
  }
28334
29003
  };
28335
29004
  label = (path2) => {
28336
- const suffix = relative4(homedir2(), path2);
28337
- return suffix === "" ? "~" : !isAbsolute8(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
29005
+ const suffix = relative5(homedir2(), path2);
29006
+ return suffix === "" ? "~" : !isAbsolute9(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
28338
29007
  };
28339
29008
  identify = async (bindingId, requestedPath, signal) => {
28340
29009
  this.authorizeMachine(bindingId);
@@ -28342,7 +29011,7 @@ var WorkspaceDirectoryService = class {
28342
29011
  return {
28343
29012
  path: path2,
28344
29013
  directoryId: encodePath(path2),
28345
- name: basename2(path2) || path2,
29014
+ name: basename3(path2) || path2,
28346
29015
  label: this.label(path2)
28347
29016
  };
28348
29017
  };
@@ -28436,7 +29105,7 @@ var EmbeddedBotContextApplicator = class {
28436
29105
 
28437
29106
  // src/native-sessions/service.ts
28438
29107
  import { randomUUID as randomUUID4 } from "node:crypto";
28439
- import { basename as basename3 } from "node:path";
29108
+ import { basename as basename4 } from "node:path";
28440
29109
 
28441
29110
  // src/native-sessions/codex-history.ts
28442
29111
  import { spawn as spawn4 } from "node:child_process";
@@ -28469,7 +29138,6 @@ function decodeHistory(thread, value) {
28469
29138
  const page = turnsSchema.parse(value);
28470
29139
  const messages = [];
28471
29140
  let characters = 0;
28472
- let imageCharacters = 0;
28473
29141
  let truncated = page.nextCursor != null;
28474
29142
  for (const turn of page.data.toReversed()) {
28475
29143
  for (const item of turn.items) {
@@ -28477,22 +29145,19 @@ function decodeHistory(thread, value) {
28477
29145
  let message;
28478
29146
  if (type === "userMessage") {
28479
29147
  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
- );
29148
+ const text2 = content.map((block) => {
29149
+ const { type: type2 } = itemTypeSchema.parse(block);
29150
+ if (type2 === "text") {
29151
+ return textSchema.parse(block).text;
29152
+ }
29153
+ if (type2 === "image") {
29154
+ return `[@image](${imageSchema.parse(block).url})`;
29155
+ }
29156
+ return "[Attachment]";
29157
+ }).join("");
28492
29158
  message = {
28493
29159
  role: "user",
28494
- text: parsed.text,
28495
- ...parsed.images.length > 0 ? { images: parsed.images } : {}
29160
+ text: text2
28496
29161
  };
28497
29162
  } else if (type === "agentMessage") {
28498
29163
  const agent = agentMessageSchema.parse(item);
@@ -28510,12 +29175,10 @@ function decodeHistory(thread, value) {
28510
29175
  truncated ||= text.length < message.text.length;
28511
29176
  messages.push({ ...message, text });
28512
29177
  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) {
29178
+ while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT) {
28515
29179
  const removed = messages.shift();
28516
29180
  if (removed !== void 0) {
28517
29181
  characters -= removed.text.length;
28518
- imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
28519
29182
  }
28520
29183
  truncated = true;
28521
29184
  }
@@ -28673,7 +29336,11 @@ async function readCodexHistory(agent, cwd, nativeSessionId, signal) {
28673
29336
  params: { clientInfo: { name: "mobius_history", version: "1.0.0" } }
28674
29337
  });
28675
29338
  }
28676
- return await response.promise;
29339
+ const snapshot = await response.promise;
29340
+ return {
29341
+ ...snapshot,
29342
+ history: await embedLocalHistoryImages(snapshot.history, [cwd, snapshot.cwd], signal)
29343
+ };
28677
29344
  } finally {
28678
29345
  clearTimeout(timeout);
28679
29346
  signal.removeEventListener("abort", abort);
@@ -28927,7 +29594,7 @@ var NativeSessionService = class {
28927
29594
  }
28928
29595
  resolvedPaths.add(path2);
28929
29596
  additionalDirectories.push(path2);
28930
- additionalEntries.push({ directoryId: directoryId2, name: basename3(path2) });
29597
+ additionalEntries.push({ directoryId: directoryId2, name: basename4(path2) });
28931
29598
  }
28932
29599
  const listing = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
28933
29600
  const opened = await this.#sessions.forkSessionAtTurn(
@@ -29066,13 +29733,13 @@ var NativeSessionService = class {
29066
29733
  };
29067
29734
 
29068
29735
  // src/prompt-artifact-resolver.ts
29069
- import { createHash as createHash3 } from "node:crypto";
29070
- import { fetch as fetch5 } from "undici";
29736
+ import { createHash as createHash4 } from "node:crypto";
29737
+ import { fetch as fetch6 } from "undici";
29071
29738
  var ARTIFACT_SCHEME = "mobius-artifact:";
29072
29739
  var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
29073
29740
  var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
29074
29741
  var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
29075
- var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
29742
+ var IDENTIFIER_PATTERN8 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
29076
29743
  var PromptArtifactError = class extends Error {
29077
29744
  code;
29078
29745
  constructor(code, message, options = {}) {
@@ -29115,7 +29782,7 @@ function parseReference(resource) {
29115
29782
  const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
29116
29783
  const sha256 = url2.searchParams.get("sha256") ?? "";
29117
29784
  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)) {
29785
+ 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
29786
  throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
29120
29787
  }
29121
29788
  return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
@@ -29181,7 +29848,7 @@ async function download(config2, command, reference, signal) {
29181
29848
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
29182
29849
  let response;
29183
29850
  try {
29184
- response = await fetch5(downloadUrl(config2, command, reference), {
29851
+ response = await fetch6(downloadUrl(config2, command, reference), {
29185
29852
  dispatcher: environmentProxyDispatcher,
29186
29853
  headers: {
29187
29854
  accept: reference.resource.mimeType,
@@ -29205,7 +29872,7 @@ async function download(config2, command, reference, signal) {
29205
29872
  );
29206
29873
  }
29207
29874
  const bytes = await responseBytes(response, reference.byteLength, requestSignal);
29208
- if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
29875
+ if (createHash4("sha256").update(bytes).digest("hex") !== reference.sha256) {
29209
29876
  throw new PromptArtifactError(
29210
29877
  "artifact_integrity_failed",
29211
29878
  "The prompt artifact failed integrity validation"
@@ -30241,10 +30908,23 @@ function botIpcSocketPath() {
30241
30908
  return join16("/tmp", `mobius-bot-${randomUUID6()}.sock`);
30242
30909
  }
30243
30910
  var DaemonAcpObserver = class {
30911
+ #config;
30244
30912
  #record;
30245
- constructor(record2) {
30246
- this.#record = record2;
30913
+ constructor(config2, record3) {
30914
+ this.#config = config2;
30915
+ this.#record = record3;
30247
30916
  }
30917
+ importLocalImage = async (sessionId, image, signal) => {
30918
+ try {
30919
+ return (await uploadRuntimeArtifact(this.#config, sessionId, image, signal)).artifactId;
30920
+ } catch (cause) {
30921
+ signal.throwIfAborted();
30922
+ if (cause instanceof Error && cause.name === "AbortError") {
30923
+ throw cause;
30924
+ }
30925
+ return "";
30926
+ }
30927
+ };
30248
30928
  onCommands = (event) => {
30249
30929
  this.#record(event.sessionId, encodeSessionCommandsUpdatedEvent(event));
30250
30930
  return Promise.resolve();
@@ -30454,7 +31134,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
30454
31134
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
30455
31135
  let response;
30456
31136
  try {
30457
- response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
31137
+ response = await fetch7(activeTurnReconciliationEndpoint(config2, turn), {
30458
31138
  body: JSON.stringify({ outcome: { kind: "running" } }),
30459
31139
  dispatcher: environmentProxyDispatcher,
30460
31140
  headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
@@ -30770,7 +31450,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
30770
31450
  additionalDirectories.push(directory);
30771
31451
  additionalDirectoryEntries.push({
30772
31452
  directoryId: additionalDirectoryId,
30773
- name: basename4(directory)
31453
+ name: basename5(directory)
30774
31454
  });
30775
31455
  }
30776
31456
  return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
@@ -31281,8 +31961,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
31281
31961
  rejectConnection(failure);
31282
31962
  };
31283
31963
  const processingDeliveryIds = /* @__PURE__ */ new Set();
31284
- const processDeliveredPrompt = async (delivery) => {
31285
- const command = decodeSessionPromptCommand(delivery.payload);
31964
+ const processDeliveredPrompt = async (delivery, command, trackActiveAttempt, execute) => {
31286
31965
  if (command.sessionId !== delivery.sessionId) {
31287
31966
  throw new Error("Runtime delivery Session identity does not match its payload");
31288
31967
  }
@@ -31310,22 +31989,11 @@ async function runRelayConnection(config2, directories, audit, sessions, install
31310
31989
  }
31311
31990
  const turn = new ActiveDaemonTurn(command, receipt.attemptId);
31312
31991
  activeTurns.set(command.commandId, turn);
31313
- if (command.disposition !== SessionPromptDisposition.Steer) {
31992
+ if (trackActiveAttempt) {
31314
31993
  activeAttemptIds.set(command.sessionId, receipt.attemptId);
31315
31994
  }
31316
31995
  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
- );
31996
+ await execute(receipt.attemptId, turn.signal);
31329
31997
  } finally {
31330
31998
  activeTurns.delete(command.commandId);
31331
31999
  if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
@@ -31404,8 +32072,50 @@ async function runRelayConnection(config2, directories, audit, sessions, install
31404
32072
  }
31405
32073
  return;
31406
32074
  }
32075
+ if (kind === BOT_SESSION_PROMPT_KIND) {
32076
+ const command = decodeBotSessionPromptCommand(delivery.payload);
32077
+ await processDeliveredPrompt(
32078
+ delivery,
32079
+ command,
32080
+ true,
32081
+ (attemptId, executionSignal) => executeBotPrompt(
32082
+ outbox,
32083
+ publisher,
32084
+ command,
32085
+ config2,
32086
+ directories,
32087
+ audit,
32088
+ sessions,
32089
+ grants,
32090
+ contexts,
32091
+ applicator,
32092
+ ipc,
32093
+ attemptId,
32094
+ timer,
32095
+ executionSignal
32096
+ )
32097
+ );
32098
+ return;
32099
+ }
31407
32100
  if (kind === SESSION_PROMPT_KIND) {
31408
- await processDeliveredPrompt(delivery);
32101
+ const command = decodeSessionPromptCommand(delivery.payload);
32102
+ await processDeliveredPrompt(
32103
+ delivery,
32104
+ command,
32105
+ command.disposition !== SessionPromptDisposition.Steer,
32106
+ (attemptId, executionSignal) => executePrompt(
32107
+ outbox,
32108
+ publisher,
32109
+ command,
32110
+ config2,
32111
+ directories,
32112
+ audit,
32113
+ sessions,
32114
+ attemptId,
32115
+ timer,
32116
+ executionSignal
32117
+ )
32118
+ );
31409
32119
  return;
31410
32120
  }
31411
32121
  throw new Error("Runtime delivery contains an unsupported protocol message");
@@ -31443,6 +32153,8 @@ async function runRelayConnection(config2, directories, audit, sessions, install
31443
32153
  payloadSessionId = decodeSessionElicitationRespondCommand(delivery.payload).sessionId;
31444
32154
  } else if (payloadKind === SESSION_PROMPT_KIND) {
31445
32155
  payloadSessionId = decodeSessionPromptCommand(delivery.payload).sessionId;
32156
+ } else if (payloadKind === BOT_SESSION_PROMPT_KIND) {
32157
+ payloadSessionId = decodeBotSessionPromptCommand(delivery.payload).sessionId;
31446
32158
  } else {
31447
32159
  throw new Error("Runtime delivery contains an unsupported protocol message");
31448
32160
  }
@@ -32040,7 +32752,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
32040
32752
  }
32041
32753
  publisher.recordAttempt(sessionId, payload, attemptId);
32042
32754
  };
32043
- const sessions = new AcpSessionManager(new DaemonAcpObserver(recordSessionEvent), sessionStore);
32755
+ const sessions = new AcpSessionManager(new DaemonAcpObserver(config2, recordSessionEvent), sessionStore);
32044
32756
  const directories = new WorkspaceDirectoryService(config2.bindingId, config2.defaultWorkspace);
32045
32757
  const installationObserver = new DaemonInstallationObserver();
32046
32758
  const diagnostics = new RelayConnectionDiagnostics(audit, config2.channelId, config2.relayUrl);
@@ -32138,11 +32850,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
32138
32850
  }
32139
32851
 
32140
32852
  // src/runtime.ts
32141
- import { mkdir as mkdir5, realpath as realpath8, stat as stat8 } from "node:fs/promises";
32853
+ import { mkdir as mkdir5, realpath as realpath9, stat as stat9 } from "node:fs/promises";
32142
32854
  import { dirname as dirname8, join as join17, resolve as resolve5 } from "node:path";
32143
32855
  var APP_CREDENTIAL_PATTERN = /^mapp_[a-zA-Z0-9_-]{22}_[a-zA-Z0-9_-]{43}$/;
32144
32856
  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}$/;
32857
+ var IDENTIFIER_PATTERN9 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
32146
32858
  var RUNTIME_CREDENTIAL_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
32147
32859
  var MobiusRuntimeConfigurationError = class extends Error {
32148
32860
  code = "runtime_configuration_invalid";
@@ -32200,7 +32912,7 @@ function relayUrlFromConnection(connection) {
32200
32912
  }
32201
32913
  function loadMobiusRuntimeConnection(environment = process.env) {
32202
32914
  const channelId = requiredEnvironmentValue(environment, "MOBIUS_CHANNEL_ID");
32203
- if (!IDENTIFIER_PATTERN8.test(channelId)) {
32915
+ if (!IDENTIFIER_PATTERN9.test(channelId)) {
32204
32916
  throw new MobiusRuntimeConfigurationError("MOBIUS_CHANNEL_ID is invalid");
32205
32917
  }
32206
32918
  return Object.freeze({
@@ -32215,8 +32927,8 @@ async function resolveWorkspace(path2) {
32215
32927
  const requested = resolve5(path2);
32216
32928
  try {
32217
32929
  await mkdir5(requested, { recursive: true, mode: 448 });
32218
- const resolved = await realpath8(requested);
32219
- const metadata = await stat8(resolved);
32930
+ const resolved = await realpath9(requested);
32931
+ const metadata = await stat9(resolved);
32220
32932
  if (!metadata.isDirectory()) {
32221
32933
  throw new MobiusRuntimeConfigurationError("The Runtime workspace is not a directory");
32222
32934
  }