@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/runtime.js CHANGED
@@ -5,7 +5,7 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // src/runtime.ts
8
- import { mkdir as mkdir5, realpath as realpath8, stat as stat8 } from "node:fs/promises";
8
+ import { mkdir as mkdir5, realpath as realpath9, stat as stat9 } from "node:fs/promises";
9
9
  import { dirname as dirname8, join as join17, resolve as resolve5 } from "node:path";
10
10
 
11
11
  // src/agent-catalog/local-agent.ts
@@ -2524,7 +2524,7 @@ var AuditStore = class {
2524
2524
  this.database.exec("ALTER TABLE audit_events ADD COLUMN details_json TEXT NOT NULL DEFAULT '{}'");
2525
2525
  }
2526
2526
  }
2527
- record(record2) {
2527
+ record(record3) {
2528
2528
  this.database.prepare(
2529
2529
  `
2530
2530
  INSERT INTO audit_events (
@@ -2537,10 +2537,10 @@ var AuditStore = class {
2537
2537
  `
2538
2538
  ).run(
2539
2539
  (/* @__PURE__ */ new Date()).toISOString(),
2540
- record2.event,
2541
- record2.commandId,
2542
- record2.sessionId,
2543
- JSON.stringify(record2.details ?? {})
2540
+ record3.event,
2541
+ record3.commandId,
2542
+ record3.sessionId,
2543
+ JSON.stringify(record3.details ?? {})
2544
2544
  );
2545
2545
  }
2546
2546
  close() {
@@ -18603,8 +18603,8 @@ function rewriteKeyNames(ctx) {
18603
18603
  bySchema.set(entry.schema, entry);
18604
18604
  }
18605
18605
  const rewrites = /* @__PURE__ */ new Map();
18606
- for (const record2 of pendingRecords.get(ctx) ?? []) {
18607
- const seen = ctx.seen.get(record2);
18606
+ for (const record3 of pendingRecords.get(ctx) ?? []) {
18607
+ const seen = ctx.seen.get(record3);
18608
18608
  const names = (seen?.def ?? seen?.schema)?.propertyNames;
18609
18609
  if (!names || names === true || rewrites.has(names))
18610
18610
  continue;
@@ -21561,6 +21561,7 @@ var elicitationFieldSchema = external_exports.strictObject({
21561
21561
  type: external_exports.enum(["boolean", "integer", "multiselect", "number", "select", "string"])
21562
21562
  }).readonly();
21563
21563
  var displayContentSchema = external_exports.strictObject({
21564
+ artifactId: external_exports.string().max(128).default(""),
21564
21565
  data: external_exports.string().max(4e6),
21565
21566
  mimeType: external_exports.string().max(255),
21566
21567
  name: external_exports.string().max(500),
@@ -21573,6 +21574,7 @@ var displayContentSchema = external_exports.strictObject({
21573
21574
  uri: external_exports.string().max(4096)
21574
21575
  }).readonly();
21575
21576
  var recordedDisplayContentSchema = external_exports.strictObject({
21577
+ artifactId: external_exports.string().max(128).default(""),
21576
21578
  data: external_exports.string().max(4e6),
21577
21579
  mimeType: external_exports.string().max(255),
21578
21580
  name: external_exports.string().max(500),
@@ -23077,9 +23079,9 @@ function createDaemonConfig(connection, agents = [], installableAgents = []) {
23077
23079
 
23078
23080
  // src/run-daemon.ts
23079
23081
  import { randomUUID as randomUUID4 } from "node:crypto";
23080
- import { basename as basename3, join as join15 } from "node:path";
23082
+ import { basename as basename4, join as join15 } from "node:path";
23081
23083
  import { styleText } from "node:util";
23082
- import { fetch as fetch5, WebSocket as WebSocket2 } from "undici";
23084
+ import { fetch as fetch6, WebSocket as WebSocket2 } from "undici";
23083
23085
 
23084
23086
  // src/acp/session-manager.ts
23085
23087
  import { spawn as spawn3 } from "node:child_process";
@@ -23090,6 +23092,212 @@ import {
23090
23092
  RequestError as RequestError2
23091
23093
  } from "@agentclientprotocol/sdk";
23092
23094
 
23095
+ // src/authorization/local-raster.ts
23096
+ import { readFile, realpath as realpath6, stat as stat5 } from "node:fs/promises";
23097
+ import { basename, isAbsolute as isAbsolute7, normalize as normalize2, relative as relative4, sep as sep4 } from "node:path";
23098
+ import { fileURLToPath } from "node:url";
23099
+ var MAX_LOCAL_RASTER_BYTES = 3e6;
23100
+ var PNG_SIGNATURE = Uint8Array.of(137, 80, 78, 71);
23101
+ var JPEG_SIGNATURE = Uint8Array.of(255, 216, 255);
23102
+ var GIF87_SIGNATURE = new TextEncoder().encode("GIF87a");
23103
+ var GIF89_SIGNATURE = new TextEncoder().encode("GIF89a");
23104
+ var RIFF_SIGNATURE = new TextEncoder().encode("RIFF");
23105
+ var WEBP_SIGNATURE = new TextEncoder().encode("WEBP");
23106
+ var LocalRasterImage = class {
23107
+ bytes;
23108
+ mimeType;
23109
+ name;
23110
+ constructor(name, mimeType, bytes) {
23111
+ this.bytes = bytes;
23112
+ this.mimeType = mimeType;
23113
+ this.name = name;
23114
+ }
23115
+ base64 = () => Buffer.from(this.bytes).toString("base64");
23116
+ };
23117
+ function startsWith(bytes, signature, offset = 0) {
23118
+ if (bytes.byteLength < offset + signature.byteLength) {
23119
+ return false;
23120
+ }
23121
+ return signature.every((value, index) => bytes[offset + index] === value);
23122
+ }
23123
+ function sniffRasterMime(bytes) {
23124
+ if (startsWith(bytes, PNG_SIGNATURE)) {
23125
+ return "image/png";
23126
+ }
23127
+ if (startsWith(bytes, JPEG_SIGNATURE)) {
23128
+ return "image/jpeg";
23129
+ }
23130
+ if (startsWith(bytes, GIF87_SIGNATURE) || startsWith(bytes, GIF89_SIGNATURE)) {
23131
+ return "image/gif";
23132
+ }
23133
+ if (startsWith(bytes, RIFF_SIGNATURE) && startsWith(bytes, WEBP_SIGNATURE, 8)) {
23134
+ return "image/webp";
23135
+ }
23136
+ return null;
23137
+ }
23138
+ function isInsideRoot(root, target) {
23139
+ const relation = relative4(root, target);
23140
+ return relation !== ".." && !relation.startsWith(`..${sep4}`) && !isAbsolute7(relation);
23141
+ }
23142
+ async function resolveCanonicalPath(requested, signal) {
23143
+ signal.throwIfAborted();
23144
+ if (!isAbsolute7(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
23145
+ return null;
23146
+ }
23147
+ try {
23148
+ const target = await realpath6(requested);
23149
+ signal.throwIfAborted();
23150
+ if (!isAbsolute7(target) || normalize2(target) !== target) {
23151
+ return null;
23152
+ }
23153
+ return target;
23154
+ } catch (cause) {
23155
+ signal.throwIfAborted();
23156
+ if (cause instanceof Error && cause.name === "AbortError") {
23157
+ throw cause;
23158
+ }
23159
+ return null;
23160
+ }
23161
+ }
23162
+ function parseLocalImageUri(uri) {
23163
+ const trimmed = uri.trim();
23164
+ if (trimmed.length === 0 || trimmed.length > 2048 || trimmed.includes("\0")) {
23165
+ return null;
23166
+ }
23167
+ if (trimmed.startsWith("data:")) {
23168
+ return null;
23169
+ }
23170
+ if (trimmed.startsWith("file:")) {
23171
+ try {
23172
+ const url2 = new URL(trimmed);
23173
+ if (url2.protocol !== "file:" || url2.host.length > 0) {
23174
+ return null;
23175
+ }
23176
+ return fileURLToPath(url2);
23177
+ } catch {
23178
+ return null;
23179
+ }
23180
+ }
23181
+ if (/^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(trimmed)) {
23182
+ return null;
23183
+ }
23184
+ return trimmed;
23185
+ }
23186
+ async function readAuthorizedRaster(uri, roots, signal) {
23187
+ signal.throwIfAborted();
23188
+ const requested = parseLocalImageUri(uri);
23189
+ if (requested === null) {
23190
+ return null;
23191
+ }
23192
+ const target = await resolveCanonicalPath(requested, signal);
23193
+ if (target === null) {
23194
+ return null;
23195
+ }
23196
+ const targetMetadata = await stat5(target);
23197
+ signal.throwIfAborted();
23198
+ if (!targetMetadata.isFile() || targetMetadata.size < 1 || targetMetadata.size > MAX_LOCAL_RASTER_BYTES) {
23199
+ return null;
23200
+ }
23201
+ const authorizedRoots = [];
23202
+ for (const root of roots) {
23203
+ const directory = await resolveCanonicalPath(root, signal);
23204
+ if (directory === null) {
23205
+ continue;
23206
+ }
23207
+ const metadata = await stat5(directory);
23208
+ signal.throwIfAborted();
23209
+ if (metadata.isDirectory()) {
23210
+ authorizedRoots.push(directory);
23211
+ }
23212
+ }
23213
+ if (!authorizedRoots.some((root) => isInsideRoot(root, target))) {
23214
+ return null;
23215
+ }
23216
+ const bytes = new Uint8Array(await readFile(target));
23217
+ signal.throwIfAborted();
23218
+ if (bytes.byteLength < 1 || bytes.byteLength > MAX_LOCAL_RASTER_BYTES) {
23219
+ return null;
23220
+ }
23221
+ const mimeType = sniffRasterMime(bytes);
23222
+ if (mimeType === null) {
23223
+ return null;
23224
+ }
23225
+ return new LocalRasterImage(basename(target) || "Image", mimeType, bytes);
23226
+ }
23227
+
23228
+ // src/native-sessions/history-images.ts
23229
+ var IMAGE_MARKER = /\[@image\]\(([^)\r\n]*)(?:\)|$)/g;
23230
+ async function embedLocalHistoryImages(history, roots, signal) {
23231
+ if (history.status !== "available") {
23232
+ return history;
23233
+ }
23234
+ const messages = [];
23235
+ let imageCharacters = 0;
23236
+ for (const message of history.messages) {
23237
+ signal.throwIfAborted();
23238
+ const resolved = await resolveMessageImages(message, roots, imageCharacters, signal);
23239
+ imageCharacters += (resolved.images ?? []).reduce((size, image) => size + image.data.length, 0);
23240
+ messages.push(resolved);
23241
+ }
23242
+ return {
23243
+ ...history,
23244
+ messages
23245
+ };
23246
+ }
23247
+ async function resolveMessageImages(message, roots, usedCharacters, signal) {
23248
+ const images = [...message.images ?? []];
23249
+ let imageCharacters = images.reduce((size, image) => size + image.data.length, 0);
23250
+ const text = await replaceImageMarkers(message.text, async (uri) => {
23251
+ if (images.length >= 8 || usedCharacters + imageCharacters >= SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
23252
+ return "[Image unavailable]";
23253
+ }
23254
+ const embedded = parseNativeHistoryText(`[@image](${uri})`).images[0];
23255
+ if (embedded !== void 0) {
23256
+ if (usedCharacters + imageCharacters + embedded.data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
23257
+ return "[Image unavailable]";
23258
+ }
23259
+ images.push(embedded);
23260
+ imageCharacters += embedded.data.length;
23261
+ return "";
23262
+ }
23263
+ const local = await readAuthorizedRaster(uri, roots, signal);
23264
+ if (local === null) {
23265
+ return "[Image unavailable]";
23266
+ }
23267
+ const data = local.base64();
23268
+ if (usedCharacters + imageCharacters + data.length > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
23269
+ return "[Image unavailable]";
23270
+ }
23271
+ images.push({
23272
+ data,
23273
+ mimeType: local.mimeType,
23274
+ name: local.name
23275
+ });
23276
+ imageCharacters += data.length;
23277
+ return "";
23278
+ });
23279
+ return {
23280
+ ...message,
23281
+ text,
23282
+ ...images.length > 0 ? { images } : {}
23283
+ };
23284
+ }
23285
+ async function replaceImageMarkers(text, replace) {
23286
+ const matches = [...text.matchAll(IMAGE_MARKER)];
23287
+ if (matches.length === 0) {
23288
+ return text;
23289
+ }
23290
+ let cursor = 0;
23291
+ let rewritten = "";
23292
+ for (const match of matches) {
23293
+ const index = match.index ?? 0;
23294
+ rewritten += text.slice(cursor, index);
23295
+ rewritten += await replace(match[1] ?? "");
23296
+ cursor = index + match[0].length;
23297
+ }
23298
+ return `${rewritten}${text.slice(cursor)}`;
23299
+ }
23300
+
23093
23301
  // src/acp/activity.ts
23094
23302
  var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
23095
23303
  function isRecord6(value) {
@@ -23187,6 +23395,7 @@ function readContentOutputDetail(content) {
23187
23395
  function summarizeDisplayContent(content) {
23188
23396
  return {
23189
23397
  ...content,
23398
+ artifactId: truncate(content.artifactId, 128),
23190
23399
  data: truncate(content.data, AGENT_ACTIVITY_DETAIL_LIMIT),
23191
23400
  mimeType: truncate(content.mimeType, 255),
23192
23401
  name: truncate(content.name, 500),
@@ -23199,7 +23408,7 @@ function summarizeDisplayContent(content) {
23199
23408
  };
23200
23409
  }
23201
23410
  function contentFitsRecordingEnvelope(content) {
23202
- 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;
23411
+ 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;
23203
23412
  }
23204
23413
  function encodedByteLength(value) {
23205
23414
  return new TextEncoder().encode(JSON.stringify(value)).byteLength;
@@ -23225,6 +23434,7 @@ function recordedDetail(activity) {
23225
23434
  }
23226
23435
  function emptyDisplayContent(type) {
23227
23436
  return {
23437
+ artifactId: "",
23228
23438
  data: "",
23229
23439
  mimeType: "",
23230
23440
  name: "",
@@ -23237,6 +23447,16 @@ function emptyDisplayContent(type) {
23237
23447
  uri: ""
23238
23448
  };
23239
23449
  }
23450
+ function imageDisplayContent(mimeType, name, data, artifactId = "", uri = "") {
23451
+ return {
23452
+ ...emptyDisplayContent("image"),
23453
+ artifactId,
23454
+ data,
23455
+ mimeType,
23456
+ name,
23457
+ uri
23458
+ };
23459
+ }
23240
23460
  function normalizeContentBlock(content) {
23241
23461
  if (content.type === "text") {
23242
23462
  return { ...emptyDisplayContent("text"), text: content.text };
@@ -24028,7 +24248,6 @@ var AcpHistoryReplay = class {
24028
24248
  #messages = [];
24029
24249
  #lastMessageId = null;
24030
24250
  #characters = 0;
24031
- #imageCharacters = 0;
24032
24251
  #truncated = false;
24033
24252
  record = (update) => {
24034
24253
  if (update.sessionUpdate !== "user_message_chunk" && update.sessionUpdate !== "agent_message_chunk") {
@@ -24039,40 +24258,30 @@ var AcpHistoryReplay = class {
24039
24258
  }
24040
24259
  const role = update.sessionUpdate === "user_message_chunk" ? "user" : "assistant";
24041
24260
  const content = update.content;
24042
- const parsed = parseNativeHistoryText(
24043
- content.type === "text" ? content.text : content.type === "image" ? `[@image](data:${content.mimeType};base64,${content.data})` : `[${content.type} attachment]`
24044
- );
24045
- const text = parsed.text;
24046
- if (text.length === 0 && parsed.images.length === 0) {
24261
+ 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]`;
24262
+ if (text.length === 0) {
24047
24263
  return;
24048
24264
  }
24049
24265
  const previous = this.#messages.at(-1);
24050
24266
  const id = update.messageId ?? null;
24051
24267
  const continuation = previous?.role === role && id === this.#lastMessageId;
24052
24268
  const combined = continuation ? `${previous.text}${text}` : text;
24053
- const allImages = continuation ? [...previous.images ?? [], ...parsed.images] : parsed.images;
24054
- const images = allImages.slice(0, 8);
24055
- this.#truncated ||= images.length < allImages.length;
24056
24269
  if (continuation) {
24057
24270
  this.#messages.pop();
24058
24271
  this.#characters -= previous.text.length;
24059
- this.#imageCharacters -= (previous.images ?? []).reduce((size, image) => size + image.data.length, 0);
24060
24272
  }
24061
24273
  const bounded = combined.slice(-SESSION_HISTORY_CHARACTER_LIMIT);
24062
24274
  this.#truncated ||= bounded.length < combined.length;
24063
24275
  this.#messages.push({
24064
24276
  role,
24065
- text: bounded,
24066
- ...images.length > 0 ? { images } : {}
24277
+ text: bounded
24067
24278
  });
24068
24279
  this.#characters += bounded.length;
24069
- this.#imageCharacters += images.reduce((size, image) => size + image.data.length, 0);
24070
24280
  this.#lastMessageId = id;
24071
- while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT || this.#imageCharacters > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
24281
+ while (this.#messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || this.#characters > SESSION_HISTORY_CHARACTER_LIMIT) {
24072
24282
  const removed = this.#messages.shift();
24073
24283
  if (removed !== void 0) {
24074
24284
  this.#characters -= removed.text.length;
24075
- this.#imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
24076
24285
  }
24077
24286
  this.#truncated = true;
24078
24287
  }
@@ -24295,6 +24504,10 @@ var MAX_PRE_SESSION_UPDATES = 100;
24295
24504
  var MAX_PRE_SESSION_UPDATE_BYTES = 1024 * 1024;
24296
24505
  var SESSION_CONTROL_COMMAND_ID = "session-control";
24297
24506
  var NullAcpSessionObserver = class {
24507
+ importLocalImage = (_sessionId, _image, signal) => {
24508
+ signal.throwIfAborted();
24509
+ return Promise.resolve("");
24510
+ };
24298
24511
  onCommands = () => Promise.resolve();
24299
24512
  onConfig = () => Promise.resolve();
24300
24513
  onContent = () => Promise.resolve();
@@ -24917,11 +25130,75 @@ var AcpProcessSession = class _AcpProcessSession {
24917
25130
  );
24918
25131
  await this.#updateTail;
24919
25132
  signal.throwIfAborted();
24920
- return history.snapshot();
25133
+ return await embedLocalHistoryImages(
25134
+ history.snapshot(),
25135
+ [this.#cwd, ...this.#additionalDirectories],
25136
+ signal
25137
+ );
24921
25138
  } finally {
24922
25139
  this.#replay = { kind: "idle" };
24923
25140
  }
24924
25141
  };
25142
+ imageRoots = () => [this.#cwd, ...this.#additionalDirectories];
25143
+ emitAgentText = async (text, messageId) => {
25144
+ const signal = AbortSignal.timeout(2e4);
25145
+ const parts = text.split(/(\[@image\]\([^)\r\n]*(?:\)|$))/);
25146
+ let leftover = "";
25147
+ for (const part of parts) {
25148
+ const marker = /^\[@image\]\(([^)\r\n]*)(?:\)|$)/.exec(part);
25149
+ if (marker === null) {
25150
+ leftover += part;
25151
+ continue;
25152
+ }
25153
+ if (leftover.length > 0) {
25154
+ await this.#turn.onText(leftover, messageId);
25155
+ leftover = "";
25156
+ }
25157
+ const raster = await readAuthorizedRaster(marker[1] ?? "", this.imageRoots(), signal);
25158
+ if (raster === null) {
25159
+ leftover += "[Image unavailable]";
25160
+ continue;
25161
+ }
25162
+ await this.emitRaster(raster, messageId, signal);
25163
+ }
25164
+ if (leftover.length > 0) {
25165
+ await this.#turn.onText(leftover, messageId);
25166
+ }
25167
+ };
25168
+ emitAgentContent = async (content, messageId) => {
25169
+ if (content.type === "image" && content.data.length === 0 && content.uri.length > 0) {
25170
+ const signal = AbortSignal.timeout(2e4);
25171
+ const raster = await readAuthorizedRaster(content.uri, this.imageRoots(), signal);
25172
+ if (raster !== null) {
25173
+ await this.emitRaster(raster, messageId, signal);
25174
+ return;
25175
+ }
25176
+ }
25177
+ await this.#getObserver().onContent({
25178
+ commandId: this.#turn.commandId,
25179
+ content,
25180
+ contentId: `content-${crypto.randomUUID()}`,
25181
+ kind: AGENT_CONTENT_KIND,
25182
+ messageId,
25183
+ sessionId: this.#mobiusSessionId
25184
+ });
25185
+ };
25186
+ emitRaster = async (raster, messageId, signal) => {
25187
+ const artifactId = await this.#getObserver().importLocalImage(this.#mobiusSessionId, raster, signal);
25188
+ await this.#getObserver().onContent({
25189
+ commandId: this.#turn.commandId,
25190
+ content: imageDisplayContent(
25191
+ raster.mimeType,
25192
+ raster.name,
25193
+ artifactId.length > 0 ? "" : raster.base64(),
25194
+ artifactId
25195
+ ),
25196
+ contentId: `content-${crypto.randomUUID()}`,
25197
+ kind: AGENT_CONTENT_KIND,
25198
+ messageId,
25199
+ sessionId: this.#mobiusSessionId
25200
+ });
25201
+ };
24925
25202
  async #initializeAgent(signal) {
24926
25203
  const initialized = await this.race(
24927
25204
  this.#connection.agent.request(
@@ -25624,18 +25901,14 @@ var AcpProcessSession = class _AcpProcessSession {
25624
25901
  );
25625
25902
  } else {
25626
25903
  await this.#turn.activities.finishNarrative();
25627
- await this.#turn.onText(update.content.text, truncate3(update.messageId ?? "", 255));
25904
+ await this.emitAgentText(update.content.text, truncate3(update.messageId ?? "", 255));
25628
25905
  }
25629
25906
  } else {
25630
25907
  await this.#turn.activities.finishNarrative();
25631
- await this.#getObserver().onContent({
25632
- commandId: this.#turn.commandId,
25633
- content: normalizeContentBlock(update.content),
25634
- contentId: `content-${crypto.randomUUID()}`,
25635
- kind: AGENT_CONTENT_KIND,
25636
- messageId: truncate3(update.messageId ?? "", 255),
25637
- sessionId: this.#mobiusSessionId
25638
- });
25908
+ await this.emitAgentContent(
25909
+ normalizeContentBlock(update.content),
25910
+ truncate3(update.messageId ?? "", 255)
25911
+ );
25639
25912
  }
25640
25913
  return;
25641
25914
  }
@@ -26996,6 +27269,402 @@ var FixedInstallationExecutor = class {
26996
27269
  };
26997
27270
  };
26998
27271
 
27272
+ // src/artifacts/runtime-artifact-uploader.ts
27273
+ import { createHash as createHash2 } from "node:crypto";
27274
+
27275
+ // ../mobius-sdk/src/errors.ts
27276
+ var MobiusError = class extends Error {
27277
+ code;
27278
+ constructor(code, message, options = {}) {
27279
+ super(message, options);
27280
+ this.code = code;
27281
+ this.name = "MobiusError";
27282
+ }
27283
+ };
27284
+ var MobiusProtocolError = class extends MobiusError {
27285
+ constructor(message, options = {}) {
27286
+ super("invalid_service_response", message, options);
27287
+ this.name = "MobiusProtocolError";
27288
+ }
27289
+ };
27290
+ var MobiusValidationError = class extends MobiusError {
27291
+ constructor(message, options = {}) {
27292
+ super("invalid_request", message, options);
27293
+ this.name = "MobiusValidationError";
27294
+ }
27295
+ };
27296
+
27297
+ // ../mobius-sdk/src/resources.ts
27298
+ var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
27299
+ function invalidResponse(message) {
27300
+ return new MobiusProtocolError(message);
27301
+ }
27302
+ function isRecord9(value) {
27303
+ return typeof value === "object" && value !== null && !Array.isArray(value);
27304
+ }
27305
+ function record2(value, name) {
27306
+ if (!isRecord9(value)) {
27307
+ throw invalidResponse(`The service returned an invalid ${name}`);
27308
+ }
27309
+ return value;
27310
+ }
27311
+ function stringField(value, field, maximumLength = 85e5) {
27312
+ const candidate = value[field];
27313
+ if (typeof candidate !== "string" || candidate.length > maximumLength) {
27314
+ throw invalidResponse(`The service returned an invalid ${field}`);
27315
+ }
27316
+ return candidate;
27317
+ }
27318
+ function identifierField(value, field) {
27319
+ const candidate = stringField(value, field, 128);
27320
+ if (!IDENTIFIER_PATTERN5.test(candidate)) {
27321
+ throw invalidResponse(`The service returned an invalid ${field}`);
27322
+ }
27323
+ return candidate;
27324
+ }
27325
+ function integerField(value, field) {
27326
+ const candidate = value[field];
27327
+ if (typeof candidate !== "number" || !Number.isSafeInteger(candidate) || candidate < 0) {
27328
+ throw invalidResponse(`The service returned an invalid ${field}`);
27329
+ }
27330
+ return candidate;
27331
+ }
27332
+ function validateTimestamp(value, field) {
27333
+ if (Number.isNaN(Date.parse(value))) {
27334
+ throw invalidResponse(`The service returned an invalid ${field}`);
27335
+ }
27336
+ return value;
27337
+ }
27338
+ var MobiusArtifactUploadRequest = class {
27339
+ byteLength;
27340
+ mediaType;
27341
+ name;
27342
+ sha256;
27343
+ constructor(name, mediaType, byteLength, sha256) {
27344
+ 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)) {
27345
+ throw new MobiusValidationError("The artifact upload request is invalid");
27346
+ }
27347
+ this.byteLength = byteLength;
27348
+ this.mediaType = mediaType;
27349
+ this.name = name;
27350
+ this.sha256 = sha256;
27351
+ }
27352
+ };
27353
+ var MobiusArtifact = class {
27354
+ artifactId;
27355
+ byteLength;
27356
+ createdAt;
27357
+ mediaType;
27358
+ name;
27359
+ sessionId;
27360
+ sha256;
27361
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt) {
27362
+ this.artifactId = artifactId;
27363
+ this.byteLength = byteLength;
27364
+ this.createdAt = createdAt;
27365
+ this.mediaType = mediaType;
27366
+ this.name = name;
27367
+ this.sessionId = sessionId;
27368
+ this.sha256 = sha256;
27369
+ }
27370
+ };
27371
+ var MobiusUploadingArtifact = class extends MobiusArtifact {
27372
+ expiresAt;
27373
+ state = "uploading";
27374
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiresAt) {
27375
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
27376
+ this.expiresAt = expiresAt;
27377
+ }
27378
+ };
27379
+ var MobiusArtifactUpload = class extends MobiusUploadingArtifact {
27380
+ uploadToken;
27381
+ constructor(artifact, uploadToken) {
27382
+ super(
27383
+ artifact.sessionId,
27384
+ artifact.artifactId,
27385
+ artifact.name,
27386
+ artifact.mediaType,
27387
+ artifact.byteLength,
27388
+ artifact.sha256,
27389
+ artifact.createdAt,
27390
+ artifact.expiresAt
27391
+ );
27392
+ this.uploadToken = uploadToken;
27393
+ }
27394
+ };
27395
+ var MobiusAvailableArtifact = class extends MobiusArtifact {
27396
+ availableAt;
27397
+ state = "available";
27398
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, availableAt) {
27399
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
27400
+ this.availableAt = availableAt;
27401
+ }
27402
+ };
27403
+ var MobiusExpiredArtifact = class extends MobiusArtifact {
27404
+ expiredAt;
27405
+ state = "expired";
27406
+ constructor(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt, expiredAt) {
27407
+ super(sessionId, artifactId, name, mediaType, byteLength, sha256, createdAt);
27408
+ this.expiredAt = expiredAt;
27409
+ }
27410
+ };
27411
+ function artifactFields(value) {
27412
+ const sha256 = stringField(value, "sha256", 64);
27413
+ if (!/^[a-f0-9]{64}$/.test(sha256)) {
27414
+ throw invalidResponse("The service returned an invalid artifact digest");
27415
+ }
27416
+ return {
27417
+ artifactId: identifierField(value, "artifactId"),
27418
+ byteLength: integerField(value, "byteLength"),
27419
+ createdAt: validateTimestamp(stringField(value, "createdAt", 128), "createdAt"),
27420
+ mediaType: stringField(value, "mediaType", 255),
27421
+ name: stringField(value, "name", 500),
27422
+ sessionId: identifierField(value, "sessionId"),
27423
+ sha256
27424
+ };
27425
+ }
27426
+ function uploadingArtifact(value) {
27427
+ const fields = artifactFields(value);
27428
+ return new MobiusUploadingArtifact(
27429
+ fields.sessionId,
27430
+ fields.artifactId,
27431
+ fields.name,
27432
+ fields.mediaType,
27433
+ fields.byteLength,
27434
+ fields.sha256,
27435
+ fields.createdAt,
27436
+ validateTimestamp(stringField(value, "expiresAt", 128), "expiresAt")
27437
+ );
27438
+ }
27439
+ function decodeMobiusArtifactUpload(value) {
27440
+ const artifact = record2(value, "artifact upload authorization");
27441
+ return new MobiusArtifactUpload(uploadingArtifact(artifact), stringField(artifact, "uploadToken", 256));
27442
+ }
27443
+ function decodeMobiusArtifact(value) {
27444
+ const artifact = record2(value, "artifact");
27445
+ const state = stringField(artifact, "state", 32);
27446
+ if (state === "uploading") {
27447
+ return uploadingArtifact(artifact);
27448
+ }
27449
+ const fields = artifactFields(artifact);
27450
+ if (state === "available") {
27451
+ return new MobiusAvailableArtifact(
27452
+ fields.sessionId,
27453
+ fields.artifactId,
27454
+ fields.name,
27455
+ fields.mediaType,
27456
+ fields.byteLength,
27457
+ fields.sha256,
27458
+ fields.createdAt,
27459
+ validateTimestamp(stringField(artifact, "availableAt", 128), "availableAt")
27460
+ );
27461
+ }
27462
+ if (state === "expired") {
27463
+ return new MobiusExpiredArtifact(
27464
+ fields.sessionId,
27465
+ fields.artifactId,
27466
+ fields.name,
27467
+ fields.mediaType,
27468
+ fields.byteLength,
27469
+ fields.sha256,
27470
+ fields.createdAt,
27471
+ validateTimestamp(stringField(artifact, "expiredAt", 128), "expiredAt")
27472
+ );
27473
+ }
27474
+ throw invalidResponse("The service returned an invalid artifact state");
27475
+ }
27476
+ function decodeMobiusAvailableArtifact(value) {
27477
+ const artifact = decodeMobiusArtifact(value);
27478
+ if (!(artifact instanceof MobiusAvailableArtifact)) {
27479
+ throw invalidResponse("The service did not make the artifact available");
27480
+ }
27481
+ return artifact;
27482
+ }
27483
+ var MobiusRuntimePairingLifecycle = Object.freeze({
27484
+ Expired: "expired",
27485
+ Paired: "paired",
27486
+ Pending: "pending",
27487
+ Revoked: "revoked"
27488
+ });
27489
+
27490
+ // src/artifacts/runtime-artifact-uploader.ts
27491
+ import { fetch as fetch3 } from "undici";
27492
+ var UPLOAD_TIMEOUT_MILLISECONDS = 2e4;
27493
+ var RuntimeArtifactUploadError = class extends Error {
27494
+ code;
27495
+ constructor(code, message, options = {}) {
27496
+ super(message, options);
27497
+ this.code = code;
27498
+ this.name = "RuntimeArtifactUploadError";
27499
+ }
27500
+ };
27501
+ var UploadedRuntimeArtifact = class {
27502
+ artifactId;
27503
+ byteLength;
27504
+ mimeType;
27505
+ name;
27506
+ sha256;
27507
+ constructor(artifactId, name, mimeType, byteLength, sha256) {
27508
+ this.artifactId = artifactId;
27509
+ this.byteLength = byteLength;
27510
+ this.mimeType = mimeType;
27511
+ this.name = name;
27512
+ this.sha256 = sha256;
27513
+ }
27514
+ };
27515
+ function daemonToken(config2) {
27516
+ const token = config2.relayUrl.searchParams.get("token");
27517
+ if (token === null || token.length < 32) {
27518
+ throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay daemon token is missing");
27519
+ }
27520
+ return token;
27521
+ }
27522
+ function channelOrigin(config2) {
27523
+ const url2 = new URL(config2.relayUrl);
27524
+ url2.protocol = url2.protocol === "wss:" ? "https:" : "http:";
27525
+ let channelPath = "";
27526
+ if (url2.pathname.endsWith("/daemon")) {
27527
+ channelPath = url2.pathname.slice(0, -"/daemon".length);
27528
+ } else {
27529
+ const runtimePath = `${MOBIUS_API_PREFIX}/v1/runtimes/connect`;
27530
+ if (!url2.pathname.endsWith("/v1/runtimes/connect") && !url2.pathname.endsWith(runtimePath)) {
27531
+ throw new RuntimeArtifactUploadError("artifact_endpoint_invalid", "The Relay artifact endpoint is invalid");
27532
+ }
27533
+ channelPath = `${url2.pathname.replace(/\/v1\/runtimes\/connect$/, "")}/channels/${encodeURIComponent(config2.channelId)}`;
27534
+ }
27535
+ url2.pathname = channelPath;
27536
+ url2.search = "";
27537
+ url2.hash = "";
27538
+ return url2;
27539
+ }
27540
+ function uploadError(code, message, cause) {
27541
+ return new RuntimeArtifactUploadError(code, message, cause === void 0 ? {} : { cause });
27542
+ }
27543
+ function translateSdkError(cause) {
27544
+ if (cause instanceof MobiusValidationError) {
27545
+ throw uploadError("artifact_upload_failed", cause.message, cause);
27546
+ }
27547
+ if (cause instanceof MobiusProtocolError) {
27548
+ throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
27549
+ }
27550
+ throw cause;
27551
+ }
27552
+ async function readJson(response) {
27553
+ try {
27554
+ return await response.json();
27555
+ } catch (cause) {
27556
+ throw uploadError("artifact_upload_failed", "The Relay returned an invalid upload response", cause);
27557
+ }
27558
+ }
27559
+ async function readAuthorization(response) {
27560
+ try {
27561
+ return decodeMobiusArtifactUpload(await readJson(response));
27562
+ } catch (cause) {
27563
+ translateSdkError(cause);
27564
+ }
27565
+ }
27566
+ function sessionArtifactUrl(origin, sessionId, resourcePath, token) {
27567
+ const url2 = new URL(`${origin.pathname}/sessions/${encodeURIComponent(sessionId)}/${resourcePath}`, origin);
27568
+ url2.searchParams.set("token", token);
27569
+ return url2;
27570
+ }
27571
+ async function postLease(url2, request, signal) {
27572
+ return await fetch3(url2, {
27573
+ dispatcher: environmentProxyDispatcher,
27574
+ headers: { "content-type": "application/json" },
27575
+ method: "POST",
27576
+ body: JSON.stringify(request),
27577
+ signal
27578
+ });
27579
+ }
27580
+ async function putContent(url2, authorization, bytes, signal) {
27581
+ return await fetch3(url2, {
27582
+ dispatcher: environmentProxyDispatcher,
27583
+ headers: {
27584
+ "content-type": authorization.mediaType,
27585
+ "x-mobius-upload-token": authorization.uploadToken
27586
+ },
27587
+ method: "PUT",
27588
+ body: bytes,
27589
+ signal
27590
+ });
27591
+ }
27592
+ async function uploadRuntimeArtifact(config2, sessionId, image, signal) {
27593
+ signal.throwIfAborted();
27594
+ let request;
27595
+ try {
27596
+ request = new MobiusArtifactUploadRequest(
27597
+ image.name,
27598
+ image.mimeType,
27599
+ image.bytes.byteLength,
27600
+ createHash2("sha256").update(image.bytes).digest("hex")
27601
+ );
27602
+ } catch (cause) {
27603
+ translateSdkError(cause);
27604
+ }
27605
+ const timeoutSignal = AbortSignal.timeout(UPLOAD_TIMEOUT_MILLISECONDS);
27606
+ const requestSignal = AbortSignal.any([signal, timeoutSignal]);
27607
+ const origin = channelOrigin(config2);
27608
+ const token = daemonToken(config2);
27609
+ let created;
27610
+ try {
27611
+ created = await postLease(
27612
+ sessionArtifactUrl(origin, sessionId, "artifacts/uploads", token),
27613
+ request,
27614
+ requestSignal
27615
+ );
27616
+ } catch (cause) {
27617
+ signal.throwIfAborted();
27618
+ throw uploadError(
27619
+ timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
27620
+ timeoutSignal.aborted ? "The artifact upload authorization timed out" : "The artifact upload could not start",
27621
+ cause
27622
+ );
27623
+ }
27624
+ if (!created.ok) {
27625
+ await created.body?.cancel();
27626
+ throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact upload");
27627
+ }
27628
+ const authorization = await readAuthorization(created);
27629
+ let uploaded;
27630
+ try {
27631
+ uploaded = await putContent(
27632
+ sessionArtifactUrl(
27633
+ origin,
27634
+ sessionId,
27635
+ `artifacts/${encodeURIComponent(authorization.artifactId)}/content`,
27636
+ token
27637
+ ),
27638
+ authorization,
27639
+ image.bytes,
27640
+ requestSignal
27641
+ );
27642
+ } catch (cause) {
27643
+ signal.throwIfAborted();
27644
+ throw uploadError(
27645
+ timeoutSignal.aborted ? "artifact_upload_timeout" : "artifact_upload_failed",
27646
+ timeoutSignal.aborted ? "The artifact upload timed out" : "The artifact content could not be uploaded",
27647
+ cause
27648
+ );
27649
+ }
27650
+ if (!uploaded.ok) {
27651
+ await uploaded.body?.cancel();
27652
+ throw uploadError("artifact_upload_rejected", "The Relay rejected the artifact content");
27653
+ }
27654
+ try {
27655
+ const available = decodeMobiusAvailableArtifact(await readJson(uploaded));
27656
+ return new UploadedRuntimeArtifact(
27657
+ available.artifactId,
27658
+ available.name,
27659
+ available.mediaType,
27660
+ available.byteLength,
27661
+ available.sha256
27662
+ );
27663
+ } catch (cause) {
27664
+ translateSdkError(cause);
27665
+ }
27666
+ }
27667
+
26999
27668
  // src/authorization/local-authorization-error.ts
27000
27669
  var LocalAuthorizationError = class extends Error {
27001
27670
  code = "local_authorization_failed";
@@ -27006,9 +27675,9 @@ var LocalAuthorizationError = class extends Error {
27006
27675
  };
27007
27676
 
27008
27677
  // src/authorization/workspace-directory.ts
27009
- import { readdir, realpath as realpath6, stat as stat5 } from "node:fs/promises";
27678
+ import { readdir, realpath as realpath7, stat as stat6 } from "node:fs/promises";
27010
27679
  import { homedir as homedir2 } from "node:os";
27011
- import { basename, dirname as dirname5, isAbsolute as isAbsolute7, join as join14, normalize as normalize2, relative as relative4 } from "node:path";
27680
+ import { basename as basename2, dirname as dirname5, isAbsolute as isAbsolute8, join as join14, normalize as normalize3, relative as relative5 } from "node:path";
27012
27681
  var WorkspaceDirectoryListing = class {
27013
27682
  directoryId;
27014
27683
  directoryLabel;
@@ -27034,7 +27703,7 @@ function decodePath(value, prefix) {
27034
27703
  throw new LocalAuthorizationError("The directory identifier is invalid");
27035
27704
  }
27036
27705
  const decoded = Buffer.from(encoded, "base64url").toString("utf8");
27037
- if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize2(decoded) !== decoded) {
27706
+ if (Buffer.from(decoded, "utf8").toString("base64url") !== encoded || decoded.includes("\0") || normalize3(decoded) !== decoded) {
27038
27707
  throw new LocalAuthorizationError("The directory identifier is invalid");
27039
27708
  }
27040
27709
  return decoded;
@@ -27060,7 +27729,7 @@ var WorkspaceDirectoryService = class {
27060
27729
  }
27061
27730
  if (id.startsWith("path-")) {
27062
27731
  const path2 = decodePath(id, "path-");
27063
- if (isAbsolute7(path2)) {
27732
+ if (isAbsolute8(path2)) {
27064
27733
  return path2;
27065
27734
  }
27066
27735
  }
@@ -27068,15 +27737,15 @@ var WorkspaceDirectoryService = class {
27068
27737
  };
27069
27738
  resolvePath = async (requested, signal) => {
27070
27739
  signal.throwIfAborted();
27071
- if (!isAbsolute7(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
27740
+ if (!isAbsolute8(requested) || requested.includes("\0") || normalize3(requested) !== requested) {
27072
27741
  throw new LocalAuthorizationError("The local directory path is invalid");
27073
27742
  }
27074
27743
  try {
27075
- const target = await realpath6(requested);
27744
+ const target = await realpath7(requested);
27076
27745
  signal.throwIfAborted();
27077
- const metadata = await stat5(target);
27746
+ const metadata = await stat6(target);
27078
27747
  signal.throwIfAborted();
27079
- if (!isAbsolute7(target) || normalize2(target) !== target || !metadata.isDirectory()) {
27748
+ if (!isAbsolute8(target) || normalize3(target) !== target || !metadata.isDirectory()) {
27080
27749
  throw new LocalAuthorizationError("The selected location is not a directory");
27081
27750
  }
27082
27751
  return target;
@@ -27091,8 +27760,8 @@ var WorkspaceDirectoryService = class {
27091
27760
  }
27092
27761
  };
27093
27762
  label = (path2) => {
27094
- const suffix = relative4(homedir2(), path2);
27095
- return suffix === "" ? "~" : !isAbsolute7(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
27763
+ const suffix = relative5(homedir2(), path2);
27764
+ return suffix === "" ? "~" : !isAbsolute8(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
27096
27765
  };
27097
27766
  identify = async (bindingId, requestedPath, signal) => {
27098
27767
  this.authorizeMachine(bindingId);
@@ -27100,7 +27769,7 @@ var WorkspaceDirectoryService = class {
27100
27769
  return {
27101
27770
  path: path2,
27102
27771
  directoryId: encodePath(path2),
27103
- name: basename(path2) || path2,
27772
+ name: basename2(path2) || path2,
27104
27773
  label: this.label(path2)
27105
27774
  };
27106
27775
  };
@@ -27157,8 +27826,8 @@ var WorkspaceDirectoryService = class {
27157
27826
  };
27158
27827
 
27159
27828
  // src/bots/local-bot-grant-store.ts
27160
- import { createHash as createHash2, randomUUID } from "node:crypto";
27161
- import { stat as stat6 } from "node:fs/promises";
27829
+ import { createHash as createHash3, randomUUID } from "node:crypto";
27830
+ import { stat as stat7 } from "node:fs/promises";
27162
27831
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
27163
27832
  var LOCAL_BOT_GRANT_LIFETIME_MILLISECONDS = 90 * 24 * 60 * 60 * 1e3;
27164
27833
  var LocalBotAuthorizationError = class extends Error {
@@ -27202,7 +27871,7 @@ var LocalBotGrant = class {
27202
27871
  }
27203
27872
  };
27204
27873
  function digest(value) {
27205
- return createHash2("sha256").update(value, "utf8").digest("hex");
27874
+ return createHash3("sha256").update(value, "utf8").digest("hex");
27206
27875
  }
27207
27876
  function agentDigest(agent) {
27208
27877
  return digest(
@@ -27216,7 +27885,7 @@ function agentDigest(agent) {
27216
27885
  );
27217
27886
  }
27218
27887
  async function workspaceDigest(path2) {
27219
- const metadata = await stat6(path2);
27888
+ const metadata = await stat7(path2);
27220
27889
  if (!metadata.isDirectory()) {
27221
27890
  throw new LocalBotAuthorizationError("binding_incompatible", "The Bot workspace is not a directory");
27222
27891
  }
@@ -27633,12 +28302,12 @@ var BotExecutionContextRegistry = class {
27633
28302
  // src/bots/bot-outbound-ipc.ts
27634
28303
  import { chmod as chmod2, mkdir as mkdir3, unlink } from "node:fs/promises";
27635
28304
  import { createServer } from "node:net";
27636
- import { dirname as dirname6, isAbsolute as isAbsolute8 } from "node:path";
27637
- import { fetch as fetch3 } from "undici";
28305
+ import { dirname as dirname6, isAbsolute as isAbsolute9 } from "node:path";
28306
+ import { fetch as fetch4 } from "undici";
27638
28307
  var BOT_IPC_REQUEST_LIMIT = 32 * 1024;
27639
28308
  var BOT_IPC_TIMEOUT_MILLISECONDS = 2e4;
27640
28309
  var BOT_RELAY_TIMEOUT_MILLISECONDS = 2e4;
27641
- var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
28310
+ var IDENTIFIER_PATTERN6 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
27642
28311
  var WINDOWS_NAMED_PIPE_PREFIX = "\\\\.\\pipe\\";
27643
28312
  var BotOutboundIpcRequest = class {
27644
28313
  contextHandle;
@@ -27652,7 +28321,7 @@ var BotOutboundIpcRequest = class {
27652
28321
  this.text = text;
27653
28322
  }
27654
28323
  };
27655
- function isRecord9(value) {
28324
+ function isRecord10(value) {
27656
28325
  return typeof value === "object" && value !== null && !Array.isArray(value);
27657
28326
  }
27658
28327
  function decodeRequest(encoded) {
@@ -27662,7 +28331,7 @@ function decodeRequest(encoded) {
27662
28331
  } catch (cause) {
27663
28332
  throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid", { cause });
27664
28333
  }
27665
- if (!isRecord9(value)) {
28334
+ if (!isRecord10(value)) {
27666
28335
  throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
27667
28336
  }
27668
28337
  const keys = Object.keys(value);
@@ -27673,7 +28342,7 @@ function decodeRequest(encoded) {
27673
28342
  const idempotencyKey = value["idempotencyKey"];
27674
28343
  const target = value["target"];
27675
28344
  const text = value["text"];
27676
- if (typeof contextHandle !== "string" || !/^ctx_[a-zA-Z0-9_-]{43}$/.test(contextHandle) || typeof idempotencyKey !== "string" || !IDENTIFIER_PATTERN5.test(idempotencyKey) || typeof target !== "string" || !IDENTIFIER_PATTERN5.test(target) || typeof text !== "string" || text.trim().length === 0 || text.length > 1e4) {
28345
+ if (typeof contextHandle !== "string" || !/^ctx_[a-zA-Z0-9_-]{43}$/.test(contextHandle) || typeof idempotencyKey !== "string" || !IDENTIFIER_PATTERN6.test(idempotencyKey) || typeof target !== "string" || !IDENTIFIER_PATTERN6.test(target) || typeof text !== "string" || text.trim().length === 0 || text.length > 1e4) {
27677
28346
  throw new LocalBotAuthorizationError("invalid_request", "The local Bot request is invalid");
27678
28347
  }
27679
28348
  return new BotOutboundIpcRequest(contextHandle, idempotencyKey, target, text);
@@ -27695,7 +28364,7 @@ function relayEndpoint(relayUrl, context, target) {
27695
28364
  endpoint.pathname = `${MOBIUS_API_PREFIX}/v1/bot-executions/${execution}/delivery-targets/${encodeURIComponent(deliveryTargetId)}/messages`;
27696
28365
  return endpoint;
27697
28366
  }
27698
- function daemonToken(relayUrl) {
28367
+ function daemonToken2(relayUrl) {
27699
28368
  const token = relayUrl.searchParams.get("token") ?? "";
27700
28369
  if (!/^[a-zA-Z0-9_-]{32,256}$/.test(token)) {
27701
28370
  throw new LocalBotAuthorizationError("bot_service_unavailable", "The Runtime credential is unavailable");
@@ -27712,10 +28381,10 @@ async function decodeRelayResponse(response) {
27712
28381
  cause
27713
28382
  });
27714
28383
  }
27715
- if (response.status === 202 && isRecord9(value) && typeof value["outboundMessageId"] === "string") {
28384
+ if (response.status === 202 && isRecord10(value) && typeof value["outboundMessageId"] === "string") {
27716
28385
  return value["outboundMessageId"];
27717
28386
  }
27718
- if (isRecord9(value) && isRecord9(value["error"])) {
28387
+ if (isRecord10(value) && isRecord10(value["error"])) {
27719
28388
  const error61 = value["error"];
27720
28389
  if (typeof error61["code"] === "string" && typeof error61["message"] === "string") {
27721
28390
  throw new LocalBotAuthorizationError(error61["code"], error61["message"]);
@@ -27731,7 +28400,7 @@ var BotOutboundIpcServer = class {
27731
28400
  #usesFilesystemSocket;
27732
28401
  constructor(socketPath, relayUrl, registry2) {
27733
28402
  const usesFilesystemSocket = !socketPath.startsWith(WINDOWS_NAMED_PIPE_PREFIX);
27734
- if (usesFilesystemSocket && !isAbsolute8(socketPath)) {
28403
+ if (usesFilesystemSocket && !isAbsolute9(socketPath)) {
27735
28404
  throw new Error("The Bot IPC path must be absolute");
27736
28405
  }
27737
28406
  this.#registry = registry2;
@@ -27748,7 +28417,7 @@ var BotOutboundIpcServer = class {
27748
28417
  if (this.#usesFilesystemSocket) {
27749
28418
  await mkdir3(dirname6(this.#socketPath), { mode: 448, recursive: true });
27750
28419
  await unlink(this.#socketPath).catch((error61) => {
27751
- if (!isRecord9(error61) || error61["code"] !== "ENOENT") {
28420
+ if (!isRecord10(error61) || error61["code"] !== "ENOENT") {
27752
28421
  throw error61;
27753
28422
  }
27754
28423
  });
@@ -27783,7 +28452,7 @@ var BotOutboundIpcServer = class {
27783
28452
  }
27784
28453
  if (this.#usesFilesystemSocket) {
27785
28454
  await unlink(this.#socketPath).catch((error61) => {
27786
- if (!isRecord9(error61) || error61["code"] !== "ENOENT") {
28455
+ if (!isRecord10(error61) || error61["code"] !== "ENOENT") {
27787
28456
  throw error61;
27788
28457
  }
27789
28458
  });
@@ -27847,10 +28516,10 @@ var BotOutboundIpcServer = class {
27847
28516
  const requestSignal = AbortSignal.any([signal, timeout]);
27848
28517
  let response;
27849
28518
  try {
27850
- response = await fetch3(relayEndpoint(this.#relayUrl, context, request.target), {
28519
+ response = await fetch4(relayEndpoint(this.#relayUrl, context, request.target), {
27851
28520
  body: JSON.stringify({ idempotencyKey: request.idempotencyKey, text: request.text }),
27852
28521
  headers: {
27853
- authorization: `Bearer ${daemonToken(this.#relayUrl)}`,
28522
+ authorization: `Bearer ${daemonToken2(this.#relayUrl)}`,
27854
28523
  "content-type": "application/json",
27855
28524
  "x-mobius-bot-execution-capability": context.command.executionCapabilitySecret
27856
28525
  },
@@ -27871,7 +28540,7 @@ var BotOutboundIpcServer = class {
27871
28540
 
27872
28541
  // src/native-sessions/service.ts
27873
28542
  import { randomUUID as randomUUID2 } from "node:crypto";
27874
- import { basename as basename2 } from "node:path";
28543
+ import { basename as basename3 } from "node:path";
27875
28544
 
27876
28545
  // src/native-sessions/codex-history.ts
27877
28546
  import { spawn as spawn4 } from "node:child_process";
@@ -27904,7 +28573,6 @@ function decodeHistory(thread, value) {
27904
28573
  const page = turnsSchema.parse(value);
27905
28574
  const messages = [];
27906
28575
  let characters = 0;
27907
- let imageCharacters = 0;
27908
28576
  let truncated = page.nextCursor != null;
27909
28577
  for (const turn of page.data.toReversed()) {
27910
28578
  for (const item of turn.items) {
@@ -27912,22 +28580,19 @@ function decodeHistory(thread, value) {
27912
28580
  let message;
27913
28581
  if (type === "userMessage") {
27914
28582
  const { content } = userMessageSchema.parse(item);
27915
- const parsed = parseNativeHistoryText(
27916
- content.map((block) => {
27917
- const { type: type2 } = itemTypeSchema.parse(block);
27918
- if (type2 === "text") {
27919
- return textSchema.parse(block).text;
27920
- }
27921
- if (type2 === "image") {
27922
- return `[@image](${imageSchema.parse(block).url})`;
27923
- }
27924
- return "[Attachment]";
27925
- }).join("")
27926
- );
28583
+ const text2 = content.map((block) => {
28584
+ const { type: type2 } = itemTypeSchema.parse(block);
28585
+ if (type2 === "text") {
28586
+ return textSchema.parse(block).text;
28587
+ }
28588
+ if (type2 === "image") {
28589
+ return `[@image](${imageSchema.parse(block).url})`;
28590
+ }
28591
+ return "[Attachment]";
28592
+ }).join("");
27927
28593
  message = {
27928
28594
  role: "user",
27929
- text: parsed.text,
27930
- ...parsed.images.length > 0 ? { images: parsed.images } : {}
28595
+ text: text2
27931
28596
  };
27932
28597
  } else if (type === "agentMessage") {
27933
28598
  const agent = agentMessageSchema.parse(item);
@@ -27945,12 +28610,10 @@ function decodeHistory(thread, value) {
27945
28610
  truncated ||= text.length < message.text.length;
27946
28611
  messages.push({ ...message, text });
27947
28612
  characters += text.length;
27948
- imageCharacters += (message.images ?? []).reduce((size, image) => size + image.data.length, 0);
27949
- while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT || imageCharacters > SESSION_HISTORY_IMAGE_CHARACTER_LIMIT) {
28613
+ while (messages.length > SESSION_HISTORY_PREVIEW_MESSAGE_LIMIT || characters > SESSION_HISTORY_CHARACTER_LIMIT) {
27950
28614
  const removed = messages.shift();
27951
28615
  if (removed !== void 0) {
27952
28616
  characters -= removed.text.length;
27953
- imageCharacters -= (removed.images ?? []).reduce((size, image) => size + image.data.length, 0);
27954
28617
  }
27955
28618
  truncated = true;
27956
28619
  }
@@ -28108,7 +28771,11 @@ async function readCodexHistory(agent, cwd, nativeSessionId, signal) {
28108
28771
  params: { clientInfo: { name: "mobius_history", version: "1.0.0" } }
28109
28772
  });
28110
28773
  }
28111
- return await response.promise;
28774
+ const snapshot = await response.promise;
28775
+ return {
28776
+ ...snapshot,
28777
+ history: await embedLocalHistoryImages(snapshot.history, [cwd, snapshot.cwd], signal)
28778
+ };
28112
28779
  } finally {
28113
28780
  clearTimeout(timeout);
28114
28781
  signal.removeEventListener("abort", abort);
@@ -28362,7 +29029,7 @@ var NativeSessionService = class {
28362
29029
  }
28363
29030
  resolvedPaths.add(path2);
28364
29031
  additionalDirectories.push(path2);
28365
- additionalEntries.push({ directoryId: directoryId2, name: basename2(path2) });
29032
+ additionalEntries.push({ directoryId: directoryId2, name: basename3(path2) });
28366
29033
  }
28367
29034
  const listing = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
28368
29035
  const opened = await this.#sessions.forkSessionAtTurn(
@@ -28501,13 +29168,13 @@ var NativeSessionService = class {
28501
29168
  };
28502
29169
 
28503
29170
  // src/prompt-artifact-resolver.ts
28504
- import { createHash as createHash3 } from "node:crypto";
28505
- import { fetch as fetch4 } from "undici";
29171
+ import { createHash as createHash4 } from "node:crypto";
29172
+ import { fetch as fetch5 } from "undici";
28506
29173
  var ARTIFACT_SCHEME = "mobius-artifact:";
28507
29174
  var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
28508
29175
  var MAX_AGENT_IMAGE_BASE64_LENGTH = 4e6;
28509
29176
  var MAX_AGENT_RESOURCE_BYTE_LENGTH = 1e6;
28510
- var IDENTIFIER_PATTERN6 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
29177
+ var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
28511
29178
  var PromptArtifactError = class extends Error {
28512
29179
  code;
28513
29180
  constructor(code, message, options = {}) {
@@ -28550,7 +29217,7 @@ function parseReference(resource) {
28550
29217
  const encodedByteLength2 = url2.searchParams.get("byteLength") ?? "";
28551
29218
  const sha256 = url2.searchParams.get("sha256") ?? "";
28552
29219
  const byteLength = Number(encodedByteLength2);
28553
- if (url2.protocol !== ARTIFACT_SCHEME || url2.hash.length > 0 || resource.type !== "link" || resource.text.length > 0 || !IDENTIFIER_PATTERN6.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)) {
29220
+ 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)) {
28554
29221
  throw new PromptArtifactError("artifact_reference_invalid", "The prompt artifact reference is invalid");
28555
29222
  }
28556
29223
  return new PromptArtifactReference(artifactId, byteLength, sha256, resource);
@@ -28616,7 +29283,7 @@ async function download(config2, command, reference, signal) {
28616
29283
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
28617
29284
  let response;
28618
29285
  try {
28619
- response = await fetch4(downloadUrl(config2, command, reference), {
29286
+ response = await fetch5(downloadUrl(config2, command, reference), {
28620
29287
  dispatcher: environmentProxyDispatcher,
28621
29288
  headers: {
28622
29289
  accept: reference.resource.mimeType,
@@ -28640,7 +29307,7 @@ async function download(config2, command, reference, signal) {
28640
29307
  );
28641
29308
  }
28642
29309
  const bytes = await responseBytes(response, reference.byteLength, requestSignal);
28643
- if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
29310
+ if (createHash4("sha256").update(bytes).digest("hex") !== reference.sha256) {
28644
29311
  throw new PromptArtifactError(
28645
29312
  "artifact_integrity_failed",
28646
29313
  "The prompt artifact failed integrity validation"
@@ -29676,10 +30343,23 @@ function botIpcSocketPath() {
29676
30343
  return join15("/tmp", `mobius-bot-${randomUUID4()}.sock`);
29677
30344
  }
29678
30345
  var DaemonAcpObserver = class {
30346
+ #config;
29679
30347
  #record;
29680
- constructor(record2) {
29681
- this.#record = record2;
30348
+ constructor(config2, record3) {
30349
+ this.#config = config2;
30350
+ this.#record = record3;
29682
30351
  }
30352
+ importLocalImage = async (sessionId, image, signal) => {
30353
+ try {
30354
+ return (await uploadRuntimeArtifact(this.#config, sessionId, image, signal)).artifactId;
30355
+ } catch (cause) {
30356
+ signal.throwIfAborted();
30357
+ if (cause instanceof Error && cause.name === "AbortError") {
30358
+ throw cause;
30359
+ }
30360
+ return "";
30361
+ }
30362
+ };
29683
30363
  onCommands = (event) => {
29684
30364
  this.#record(event.sessionId, encodeSessionCommandsUpdatedEvent(event));
29685
30365
  return Promise.resolve();
@@ -29889,7 +30569,7 @@ async function reconcileActiveTurn(config2, turn, signal) {
29889
30569
  const requestSignal = AbortSignal.any([signal, timeoutSignal]);
29890
30570
  let response;
29891
30571
  try {
29892
- response = await fetch5(activeTurnReconciliationEndpoint(config2, turn), {
30572
+ response = await fetch6(activeTurnReconciliationEndpoint(config2, turn), {
29893
30573
  body: JSON.stringify({ outcome: { kind: "running" } }),
29894
30574
  dispatcher: environmentProxyDispatcher,
29895
30575
  headers: { ...runtimeAuthorization(config2.relayUrl), "content-type": "application/json" },
@@ -30205,7 +30885,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
30205
30885
  additionalDirectories.push(directory);
30206
30886
  additionalDirectoryEntries.push({
30207
30887
  directoryId: additionalDirectoryId,
30208
- name: basename3(directory)
30888
+ name: basename4(directory)
30209
30889
  });
30210
30890
  }
30211
30891
  return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
@@ -30716,8 +31396,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30716
31396
  rejectConnection(failure);
30717
31397
  };
30718
31398
  const processingDeliveryIds = /* @__PURE__ */ new Set();
30719
- const processDeliveredPrompt = async (delivery) => {
30720
- const command = decodeSessionPromptCommand(delivery.payload);
31399
+ const processDeliveredPrompt = async (delivery, command, trackActiveAttempt, execute) => {
30721
31400
  if (command.sessionId !== delivery.sessionId) {
30722
31401
  throw new Error("Runtime delivery Session identity does not match its payload");
30723
31402
  }
@@ -30745,22 +31424,11 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30745
31424
  }
30746
31425
  const turn = new ActiveDaemonTurn(command, receipt.attemptId);
30747
31426
  activeTurns.set(command.commandId, turn);
30748
- if (command.disposition !== SessionPromptDisposition.Steer) {
31427
+ if (trackActiveAttempt) {
30749
31428
  activeAttemptIds.set(command.sessionId, receipt.attemptId);
30750
31429
  }
30751
31430
  try {
30752
- await executePrompt(
30753
- outbox,
30754
- publisher,
30755
- command,
30756
- config2,
30757
- directories,
30758
- audit,
30759
- sessions,
30760
- receipt.attemptId,
30761
- timer,
30762
- turn.signal
30763
- );
31431
+ await execute(receipt.attemptId, turn.signal);
30764
31432
  } finally {
30765
31433
  activeTurns.delete(command.commandId);
30766
31434
  if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
@@ -30839,8 +31507,50 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30839
31507
  }
30840
31508
  return;
30841
31509
  }
31510
+ if (kind === BOT_SESSION_PROMPT_KIND) {
31511
+ const command = decodeBotSessionPromptCommand(delivery.payload);
31512
+ await processDeliveredPrompt(
31513
+ delivery,
31514
+ command,
31515
+ true,
31516
+ (attemptId, executionSignal) => executeBotPrompt(
31517
+ outbox,
31518
+ publisher,
31519
+ command,
31520
+ config2,
31521
+ directories,
31522
+ audit,
31523
+ sessions,
31524
+ grants,
31525
+ contexts,
31526
+ applicator,
31527
+ ipc,
31528
+ attemptId,
31529
+ timer,
31530
+ executionSignal
31531
+ )
31532
+ );
31533
+ return;
31534
+ }
30842
31535
  if (kind === SESSION_PROMPT_KIND) {
30843
- await processDeliveredPrompt(delivery);
31536
+ const command = decodeSessionPromptCommand(delivery.payload);
31537
+ await processDeliveredPrompt(
31538
+ delivery,
31539
+ command,
31540
+ command.disposition !== SessionPromptDisposition.Steer,
31541
+ (attemptId, executionSignal) => executePrompt(
31542
+ outbox,
31543
+ publisher,
31544
+ command,
31545
+ config2,
31546
+ directories,
31547
+ audit,
31548
+ sessions,
31549
+ attemptId,
31550
+ timer,
31551
+ executionSignal
31552
+ )
31553
+ );
30844
31554
  return;
30845
31555
  }
30846
31556
  throw new Error("Runtime delivery contains an unsupported protocol message");
@@ -30878,6 +31588,8 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30878
31588
  payloadSessionId = decodeSessionElicitationRespondCommand(delivery.payload).sessionId;
30879
31589
  } else if (payloadKind === SESSION_PROMPT_KIND) {
30880
31590
  payloadSessionId = decodeSessionPromptCommand(delivery.payload).sessionId;
31591
+ } else if (payloadKind === BOT_SESSION_PROMPT_KIND) {
31592
+ payloadSessionId = decodeBotSessionPromptCommand(delivery.payload).sessionId;
30881
31593
  } else {
30882
31594
  throw new Error("Runtime delivery contains an unsupported protocol message");
30883
31595
  }
@@ -31475,7 +32187,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
31475
32187
  }
31476
32188
  publisher.recordAttempt(sessionId, payload, attemptId);
31477
32189
  };
31478
- const sessions = new AcpSessionManager(new DaemonAcpObserver(recordSessionEvent), sessionStore);
32190
+ const sessions = new AcpSessionManager(new DaemonAcpObserver(config2, recordSessionEvent), sessionStore);
31479
32191
  const directories = new WorkspaceDirectoryService(config2.bindingId, config2.defaultWorkspace);
31480
32192
  const installationObserver = new DaemonInstallationObserver();
31481
32193
  const diagnostics = new RelayConnectionDiagnostics(audit, config2.channelId, config2.relayUrl);
@@ -31574,13 +32286,13 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
31574
32286
 
31575
32287
  // src/pairing/pair-local-machine.ts
31576
32288
  import { randomUUID as randomUUID5 } from "node:crypto";
31577
- import { mkdir as mkdir4, open as open4, realpath as realpath7, rename as rename3, stat as stat7, writeFile as writeFile2 } from "node:fs/promises";
32289
+ import { mkdir as mkdir4, open as open4, realpath as realpath8, rename as rename3, stat as stat8, writeFile as writeFile2 } from "node:fs/promises";
31578
32290
  import { hostname as hostname3 } from "node:os";
31579
- import { basename as basename4, join as join16, resolve as resolve4 } from "node:path";
31580
- import { fetch as fetch6 } from "undici";
32291
+ import { basename as basename5, join as join16, resolve as resolve4 } from "node:path";
32292
+ import { fetch as fetch7 } from "undici";
31581
32293
  var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
31582
32294
  var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
31583
- var IDENTIFIER_PATTERN7 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
32295
+ var IDENTIFIER_PATTERN8 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
31584
32296
  var TOKEN_PATTERN2 = /^[a-zA-Z0-9_-]{32,256}$/;
31585
32297
  var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
31586
32298
  var CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken", "runtimeId"];
@@ -31595,7 +32307,7 @@ var PairingClientError = class extends Error {
31595
32307
  this.name = "PairingClientError";
31596
32308
  }
31597
32309
  };
31598
- function isRecord10(value) {
32310
+ function isRecord11(value) {
31599
32311
  return typeof value === "object" && value !== null && !Array.isArray(value);
31600
32312
  }
31601
32313
  function hasExactKeys(value, expectedKeys) {
@@ -31634,7 +32346,7 @@ function parsePairingCode(value) {
31634
32346
  return code;
31635
32347
  }
31636
32348
  function validatePairingId(value) {
31637
- if (!IDENTIFIER_PATTERN7.test(value)) {
32349
+ if (!IDENTIFIER_PATTERN8.test(value)) {
31638
32350
  throw new PairingClientError("invalid_pairing_id", "The Runtime pairing ID is invalid");
31639
32351
  }
31640
32352
  return value;
@@ -31643,8 +32355,8 @@ async function resolveDefaultWorkspace2(path2) {
31643
32355
  const requestedWorkspace = resolve4(path2);
31644
32356
  try {
31645
32357
  await mkdir4(requestedWorkspace, { recursive: true, mode: 448 });
31646
- const defaultWorkspace = await realpath7(requestedWorkspace);
31647
- const metadata = await stat7(defaultWorkspace);
32358
+ const defaultWorkspace = await realpath8(requestedWorkspace);
32359
+ const metadata = await stat8(defaultWorkspace);
31648
32360
  if (!metadata.isDirectory()) {
31649
32361
  throw new PairingClientError("invalid_workspace", "The default workspace is not a directory");
31650
32362
  }
@@ -31673,9 +32385,9 @@ async function readJsonResponse(response) {
31673
32385
  }
31674
32386
  }
31675
32387
  function readRelayError(value) {
31676
- if (isRecord10(value)) {
32388
+ if (isRecord11(value)) {
31677
32389
  const error61 = value["error"];
31678
- if (isRecord10(error61)) {
32390
+ if (isRecord11(error61)) {
31679
32391
  const code = error61["code"];
31680
32392
  const message = error61["message"];
31681
32393
  if (typeof code === "string" && typeof message === "string") {
@@ -31686,13 +32398,13 @@ function readRelayError(value) {
31686
32398
  return new PairingClientError("pairing_failed", "The relay could not pair this machine");
31687
32399
  }
31688
32400
  function decodePairingResponse(value, credentialField, expectedKeys) {
31689
- if (!isRecord10(value) || !hasExactKeys(value, expectedKeys)) {
32401
+ if (!isRecord11(value) || !hasExactKeys(value, expectedKeys)) {
31690
32402
  throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
31691
32403
  }
31692
32404
  const channelId = value["channelId"];
31693
32405
  const runtimeCredential2 = value[credentialField];
31694
32406
  const runtimeId = value["runtimeId"];
31695
- if (typeof channelId !== "string" || !IDENTIFIER_PATTERN7.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN7.test(runtimeId)) {
32407
+ if (typeof channelId !== "string" || !IDENTIFIER_PATTERN8.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN8.test(runtimeId)) {
31696
32408
  throw new PairingClientError("invalid_relay_response", "The relay returned an invalid pairing response");
31697
32409
  }
31698
32410
  return { channelId, runtimeCredential: runtimeCredential2, runtimeId };
@@ -31708,13 +32420,13 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
31708
32420
  const endpoint = options.pairingId.length > 0 ? mobiusApiUrl(options.relayOrigin, `/v1/runtime-pairings/${encodeURIComponent(options.pairingId)}/redeem`) : mobiusApiUrl(options.relayOrigin, "/pairings/claim");
31709
32421
  let response;
31710
32422
  try {
31711
- response = await fetch6(endpoint, {
32423
+ response = await fetch7(endpoint, {
31712
32424
  body: JSON.stringify({
31713
32425
  agents,
31714
32426
  installableAgents,
31715
32427
  machineName: hostname3(),
31716
32428
  pairingCode: options.code,
31717
- workspaceName: basename4(defaultWorkspace) || "Local workspace"
32429
+ workspaceName: basename5(defaultWorkspace) || "Local workspace"
31718
32430
  }),
31719
32431
  dispatcher: environmentProxyDispatcher,
31720
32432
  headers: { "content-type": "application/json" },
@@ -31754,14 +32466,14 @@ async function persistConnection(channelId, relayOrigin, runtimeCredential2, def
31754
32466
  return connectionPath;
31755
32467
  }
31756
32468
  function decodeSavedConnection(value, expectedChannelId) {
31757
- if (!isRecord10(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS) && !hasExactKeys(value, LEGACY_SAVED_CONNECTION_KEYS)) {
32469
+ if (!isRecord11(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS) && !hasExactKeys(value, LEGACY_SAVED_CONNECTION_KEYS)) {
31758
32470
  throw new PairingClientError("invalid_connection", "The saved connection is invalid");
31759
32471
  }
31760
32472
  const defaultWorkspace = value["defaultWorkspace"];
31761
32473
  const channelId = value["channelId"];
31762
32474
  const runtimeCredential2 = value["runtimeCredential"] ?? value["daemonToken"];
31763
32475
  const relayOrigin = value["relayOrigin"];
31764
- if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN7.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof relayOrigin !== "string") {
32476
+ if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN8.test(channelId) || typeof runtimeCredential2 !== "string" || !TOKEN_PATTERN2.test(runtimeCredential2) || typeof relayOrigin !== "string") {
31765
32477
  throw new PairingClientError("invalid_connection", "The saved connection is invalid");
31766
32478
  }
31767
32479
  return {
@@ -31880,7 +32592,7 @@ async function resumeMobiusRuntime(channelId, signal, environment = process.env)
31880
32592
  // src/runtime.ts
31881
32593
  var APP_CREDENTIAL_PATTERN = /^mapp_[a-zA-Z0-9_-]{22}_[a-zA-Z0-9_-]{43}$/;
31882
32594
  var CONVERSATION_CREDENTIAL_PATTERN = /^mconv_[a-zA-Z0-9_-]{22}_[a-zA-Z0-9_-]{43}$/;
31883
- var IDENTIFIER_PATTERN8 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
32595
+ var IDENTIFIER_PATTERN9 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
31884
32596
  var RUNTIME_CREDENTIAL_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
31885
32597
  var MobiusRuntimeConfigurationError = class extends Error {
31886
32598
  code = "runtime_configuration_invalid";
@@ -31938,7 +32650,7 @@ function relayUrlFromConnection(connection) {
31938
32650
  }
31939
32651
  function loadMobiusRuntimeConnection(environment = process.env) {
31940
32652
  const channelId = requiredEnvironmentValue(environment, "MOBIUS_CHANNEL_ID");
31941
- if (!IDENTIFIER_PATTERN8.test(channelId)) {
32653
+ if (!IDENTIFIER_PATTERN9.test(channelId)) {
31942
32654
  throw new MobiusRuntimeConfigurationError("MOBIUS_CHANNEL_ID is invalid");
31943
32655
  }
31944
32656
  return Object.freeze({
@@ -31953,8 +32665,8 @@ async function resolveWorkspace(path2) {
31953
32665
  const requested = resolve5(path2);
31954
32666
  try {
31955
32667
  await mkdir5(requested, { recursive: true, mode: 448 });
31956
- const resolved = await realpath8(requested);
31957
- const metadata = await stat8(resolved);
32668
+ const resolved = await realpath9(requested);
32669
+ const metadata = await stat9(resolved);
31958
32670
  if (!metadata.isDirectory()) {
31959
32671
  throw new MobiusRuntimeConfigurationError("The Runtime workspace is not a directory");
31960
32672
  }