@moxt-ai/mobius 0.0.166 → 0.0.167

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 (48) hide show
  1. package/dist/acp/agent-query-processes.d.ts +2 -1
  2. package/dist/acp/agent-query-processes.d.ts.map +1 -1
  3. package/dist/acp/agent-query-processes.js +6 -4
  4. package/dist/acp/agent-query-processes.js.map +1 -1
  5. package/dist/acp/agent-runtime-manager.d.ts +2 -1
  6. package/dist/acp/agent-runtime-manager.d.ts.map +1 -1
  7. package/dist/acp/agent-runtime-manager.js +11 -6
  8. package/dist/acp/agent-runtime-manager.js.map +1 -1
  9. package/dist/acp/agent-session.d.ts +3 -2
  10. package/dist/acp/agent-session.d.ts.map +1 -1
  11. package/dist/acp/agent-session.js +9 -6
  12. package/dist/acp/agent-session.js.map +1 -1
  13. package/dist/artifacts/local-file-streamer.d.ts +2 -1
  14. package/dist/artifacts/local-file-streamer.d.ts.map +1 -1
  15. package/dist/artifacts/local-file-streamer.js +6 -5
  16. package/dist/artifacts/local-file-streamer.js.map +1 -1
  17. package/dist/cli.js +387 -94
  18. package/dist/cli.js.map +4 -4
  19. package/dist/config.d.ts +1 -1
  20. package/dist/config.d.ts.map +1 -1
  21. package/dist/config.js +1 -1
  22. package/dist/config.js.map +1 -1
  23. package/dist/daemon-command-handler.d.ts +3 -1
  24. package/dist/daemon-command-handler.d.ts.map +1 -1
  25. package/dist/daemon-command-handler.js +2 -2
  26. package/dist/daemon-command-handler.js.map +1 -1
  27. package/dist/external-content/acp-content-externalizer.d.ts +8 -0
  28. package/dist/external-content/acp-content-externalizer.d.ts.map +1 -0
  29. package/dist/external-content/acp-content-externalizer.js +131 -0
  30. package/dist/external-content/acp-content-externalizer.js.map +1 -0
  31. package/dist/external-content/local-external-content-store.d.ts +32 -0
  32. package/dist/external-content/local-external-content-store.d.ts.map +1 -0
  33. package/dist/external-content/local-external-content-store.js +88 -0
  34. package/dist/external-content/local-external-content-store.js.map +1 -0
  35. package/dist/index.js +445 -158
  36. package/dist/index.js.map +4 -4
  37. package/dist/relay-connection/run-relay-connection.d.ts +3 -1
  38. package/dist/relay-connection/run-relay-connection.d.ts.map +1 -1
  39. package/dist/relay-connection/run-relay-connection.js +2 -1
  40. package/dist/relay-connection/run-relay-connection.js.map +1 -1
  41. package/dist/run-daemon.d.ts.map +1 -1
  42. package/dist/run-daemon.js +5 -1
  43. package/dist/run-daemon.js.map +1 -1
  44. package/dist/runtime.d.ts +2 -1
  45. package/dist/runtime.d.ts.map +1 -1
  46. package/dist/runtime.js +386 -98
  47. package/dist/runtime.js.map +4 -4
  48. package/package.json +16 -10
package/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ var __export = (target, all) => {
7
7
 
8
8
  // src/cli.ts
9
9
  import { constants as constants2 } from "node:fs";
10
- import { mkdir as mkdir6, open as open6 } from "node:fs/promises";
10
+ import { mkdir as mkdir7, open as open6 } from "node:fs/promises";
11
11
  import { resolve as resolve8 } from "node:path";
12
12
 
13
13
  // ../../node_modules/.pnpm/commander@15.0.0/node_modules/commander/lib/error.js
@@ -3381,21 +3381,16 @@ var program = new Command();
3381
3381
  // package.json
3382
3382
  var package_default = {
3383
3383
  name: "@moxt-ai/mobius",
3384
- version: "0.0.166",
3384
+ version: "0.0.167",
3385
3385
  description: "Mobius CLI for pairing and running local AI agent services.",
3386
3386
  type: "module",
3387
3387
  bin: {
3388
3388
  mobius: "dist/cli.js"
3389
3389
  },
3390
+ types: "./src/index.ts",
3390
3391
  exports: {
3391
- ".": {
3392
- types: "./dist/index.d.ts",
3393
- import: "./dist/index.js"
3394
- },
3395
- "./runtime": {
3396
- types: "./dist/runtime.d.ts",
3397
- import: "./dist/runtime.js"
3398
- }
3392
+ ".": "./src/index.ts",
3393
+ "./runtime": "./src/runtime.ts"
3399
3394
  },
3400
3395
  files: [
3401
3396
  "dist"
@@ -3404,7 +3399,18 @@ var package_default = {
3404
3399
  node: ">=22.13.0"
3405
3400
  },
3406
3401
  publishConfig: {
3407
- access: "public"
3402
+ access: "public",
3403
+ types: "./dist/index.d.ts",
3404
+ exports: {
3405
+ ".": {
3406
+ types: "./dist/index.d.ts",
3407
+ import: "./dist/index.js"
3408
+ },
3409
+ "./runtime": {
3410
+ types: "./dist/runtime.d.ts",
3411
+ import: "./dist/runtime.js"
3412
+ }
3413
+ }
3408
3414
  },
3409
3415
  repository: {
3410
3416
  type: "git",
@@ -29799,6 +29805,7 @@ var MAX_JSON_KEYS = 1e3;
29799
29805
  var SESSION_EVENT_V2_KIND = "session.event.v2";
29800
29806
  var boundedString = external_exports.string().max(MAX_CONTENT_LENGTH);
29801
29807
  var shortString = external_exports.string().max(2048);
29808
+ var externalContentKeySchema = external_exports.string().regex(/^[a-f0-9]{64}$/u);
29802
29809
  function boundedJsonIssue(value, depth = 0) {
29803
29810
  if (depth > MAX_JSON_DEPTH) {
29804
29811
  return "JSON nesting exceeds the maximum depth";
@@ -29866,6 +29873,30 @@ var imageContentSchema = external_exports.object({
29866
29873
  uri: boundedString.nullable().optional()
29867
29874
  }).readonly();
29868
29875
  var audioContentSchema = external_exports.object({ ...contentFields, data: boundedString, mimeType: shortString, type: external_exports.literal("audio") }).readonly();
29876
+ var externalImageContentSchema = external_exports.strictObject({
29877
+ ...contentFields,
29878
+ byteLength: external_exports.number().int().positive().safe(),
29879
+ imageKey: externalContentKeySchema,
29880
+ mimeType: shortString,
29881
+ type: external_exports.literal("external_image"),
29882
+ uri: boundedString.nullable().optional()
29883
+ }).readonly();
29884
+ var externalAudioContentSchema = external_exports.strictObject({
29885
+ ...contentFields,
29886
+ audioKey: externalContentKeySchema,
29887
+ byteLength: external_exports.number().int().positive().safe(),
29888
+ mimeType: shortString,
29889
+ type: external_exports.literal("external_audio")
29890
+ }).readonly();
29891
+ var externalResourceContentSchema = external_exports.strictObject({
29892
+ ...contentFields,
29893
+ byteLength: external_exports.number().int().positive().safe(),
29894
+ encoding: external_exports.enum(["binary", "text"]),
29895
+ mimeType: shortString.nullable().optional(),
29896
+ resourceKey: externalContentKeySchema,
29897
+ type: external_exports.literal("external_resource"),
29898
+ uri: boundedString
29899
+ }).readonly();
29869
29900
  var resourceLinkSchema = external_exports.object({
29870
29901
  ...contentFields,
29871
29902
  description: boundedString.nullable().optional(),
@@ -29898,7 +29929,10 @@ var contentBlockV2Schema = external_exports.discriminatedUnion("type", [
29898
29929
  imageContentSchema,
29899
29930
  audioContentSchema,
29900
29931
  resourceLinkSchema,
29901
- embeddedResourceSchema
29932
+ embeddedResourceSchema,
29933
+ externalImageContentSchema,
29934
+ externalAudioContentSchema,
29935
+ externalResourceContentSchema
29902
29936
  ]);
29903
29937
  var toolCallContentSchema = external_exports.discriminatedUnion("type", [
29904
29938
  external_exports.object({ _meta: optionalMetadata, content: contentBlockV2Schema, type: external_exports.literal("content") }).readonly(),
@@ -30710,11 +30744,11 @@ function createDaemonConfig(connection, agents = [], installableAgents = [], loc
30710
30744
 
30711
30745
  // src/daemon-manager.ts
30712
30746
  import { spawn as spawn6 } from "node:child_process";
30713
- import { createHash as createHash8, randomBytes } from "node:crypto";
30714
- import { readFile as readFile3, unlink as unlink2, writeFile as writeFile4 } from "node:fs/promises";
30747
+ import { createHash as createHash9, randomBytes } from "node:crypto";
30748
+ import { readFile as readFile4, unlink as unlink2, writeFile as writeFile5 } from "node:fs/promises";
30715
30749
  import { createConnection, createServer } from "node:net";
30716
30750
  import { tmpdir } from "node:os";
30717
- import { join as join19 } from "node:path";
30751
+ import { join as join20 } from "node:path";
30718
30752
 
30719
30753
  // src/pairing/pair-local-machine.ts
30720
30754
  import { mkdir as mkdir5, realpath as realpath6, stat as stat5 } from "node:fs/promises";
@@ -31544,8 +31578,8 @@ var AuditStore = class {
31544
31578
  };
31545
31579
 
31546
31580
  // src/run-daemon.ts
31547
- import { createHash as createHash7, randomUUID as randomUUID7 } from "node:crypto";
31548
- import { join as join18 } from "node:path";
31581
+ import { createHash as createHash8, randomUUID as randomUUID8 } from "node:crypto";
31582
+ import { join as join19 } from "node:path";
31549
31583
  import { styleText } from "node:util";
31550
31584
 
31551
31585
  // src/acp/active-executions.ts
@@ -34917,7 +34951,7 @@ function sql(strings, ...params) {
34917
34951
  return new SQL([new StringChunk(str)]);
34918
34952
  }
34919
34953
  sql2.raw = raw;
34920
- function join20(chunks, separator) {
34954
+ function join21(chunks, separator) {
34921
34955
  const result = [];
34922
34956
  for (const [i, chunk] of chunks.entries()) {
34923
34957
  if (i > 0 && separator !== void 0) {
@@ -34927,7 +34961,7 @@ function sql(strings, ...params) {
34927
34961
  }
34928
34962
  return new SQL(result);
34929
34963
  }
34930
- sql2.join = join20;
34964
+ sql2.join = join21;
34931
34965
  function identifier(value) {
34932
34966
  return new Name(value);
34933
34967
  }
@@ -37471,7 +37505,7 @@ var SQLiteSelectQueryBuilderBase = class extends TypedQueryBuilder {
37471
37505
  const baseTableName = this.tableName;
37472
37506
  const tableName = getTableLikeName(table);
37473
37507
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
37474
- if (typeof tableName === "string" && this.config.joins?.some((join20) => join20.alias === tableName)) {
37508
+ if (typeof tableName === "string" && this.config.joins?.some((join21) => join21.alias === tableName)) {
37475
37509
  throw new Error(`Alias "${tableName}" is already used in this query`);
37476
37510
  }
37477
37511
  if (!this.isPartialSelect) {
@@ -38330,7 +38364,7 @@ var SQLiteUpdateBase = class extends QueryPromise {
38330
38364
  createJoin(joinType) {
38331
38365
  return (table, on) => {
38332
38366
  const tableName = getTableLikeName(table);
38333
- if (typeof tableName === "string" && this.config.joins.some((join20) => join20.alias === tableName)) {
38367
+ if (typeof tableName === "string" && this.config.joins.some((join21) => join21.alias === tableName)) {
38334
38368
  throw new Error(`Alias "${tableName}" is already used in this query`);
38335
38369
  }
38336
38370
  if (typeof on === "function") {
@@ -39653,6 +39687,7 @@ function recordsEqual(left, right) {
39653
39687
  }
39654
39688
  var AgentSession = class _AgentSession {
39655
39689
  #connection;
39690
+ #contentExternalizer;
39656
39691
  #interactions;
39657
39692
  #additionalDirectories;
39658
39693
  #agentId;
@@ -39680,7 +39715,7 @@ var AgentSession = class _AgentSession {
39680
39715
  #sessionTitle = null;
39681
39716
  #sessionUpdatedAt = "";
39682
39717
  #turn = new IdleAcpTurn();
39683
- constructor(agent, cwd, additionalDirectories, mobiusSessionId, getObserver, store, metrics) {
39718
+ constructor(agent, cwd, additionalDirectories, mobiusSessionId, getObserver, store, metrics, contentExternalizer) {
39684
39719
  this.#updates = new AgentUpdateStream((notification) => this.#processUpdate(notification));
39685
39720
  this.#additionalDirectories = [...additionalDirectories];
39686
39721
  this.#agentId = agent.id;
@@ -39700,8 +39735,9 @@ var AgentSession = class _AgentSession {
39700
39735
  observer: getObserver
39701
39736
  });
39702
39737
  this.#connection = new AgentConnection(agent, cwd, this);
39738
+ this.#contentExternalizer = contentExternalizer;
39703
39739
  }
39704
- static async #start(options, getObserver, store, initialize, metrics) {
39740
+ static async #start(options, getObserver, store, initialize, metrics, contentExternalizer) {
39705
39741
  for (let attempt = 1; attempt <= 2; attempt += 1) {
39706
39742
  options.signal.throwIfAborted();
39707
39743
  const unchanged = await metrics.measure(
@@ -39729,7 +39765,8 @@ var AgentSession = class _AgentSession {
39729
39765
  options.sessionId,
39730
39766
  getObserver,
39731
39767
  store,
39732
- metrics
39768
+ metrics,
39769
+ contentExternalizer
39733
39770
  )
39734
39771
  );
39735
39772
  try {
@@ -39752,19 +39789,21 @@ var AgentSession = class _AgentSession {
39752
39789
  }
39753
39790
  throw new AcpExecutionError("ACP agent initialization failed");
39754
39791
  }
39755
- static start = async (options, getObserver, store, metrics = unmeasuredOperationMetrics) => await _AgentSession.#start(
39792
+ static start = async (options, getObserver, store, metrics, contentExternalizer) => await _AgentSession.#start(
39756
39793
  options,
39757
39794
  getObserver,
39758
39795
  store,
39759
39796
  async (runtime) => await runtime.initialize(options.signal, options.origin),
39760
- metrics
39797
+ metrics,
39798
+ contentExternalizer
39761
39799
  );
39762
- static startNativeSessionBrowser = async (options, getObserver, store) => await _AgentSession.#start(
39800
+ static startNativeSessionBrowser = async (options, getObserver, store, contentExternalizer) => await _AgentSession.#start(
39763
39801
  options,
39764
39802
  getObserver,
39765
39803
  store,
39766
39804
  async (runtime) => await runtime.#initializeAgent(options.signal),
39767
- unmeasuredOperationMetrics
39805
+ unmeasuredOperationMetrics,
39806
+ contentExternalizer
39768
39807
  );
39769
39808
  belongsTo = (agentId, cwd, additionalDirectories) => this.#agentId === agentId && this.#cwd === cwd && arraysEqual(this.#additionalDirectories, additionalDirectories);
39770
39809
  usesEnvironment = (environment) => recordsEqual(this.#environment, environment);
@@ -40469,7 +40508,12 @@ var AgentSession = class _AgentSession {
40469
40508
  #processUpdate = async (notification) => {
40470
40509
  this.assertNativeSession(notification.sessionId);
40471
40510
  const update = notification.update;
40472
- const rawUpdate = decodeAcpSessionUpdateV2(JSON.stringify(update));
40511
+ const externalized = await this.#contentExternalizer.update(
40512
+ this.#mobiusSessionId,
40513
+ update,
40514
+ AbortSignal.timeout(3e4)
40515
+ );
40516
+ const rawUpdate = decodeAcpSessionUpdateV2(JSON.stringify(externalized));
40473
40517
  if (this.#sessionLoad.kind === "capturing") {
40474
40518
  await this.#sessionLoad.history.record(update, rawUpdate);
40475
40519
  } else {
@@ -40756,8 +40800,10 @@ var AgentQueryProcesses = class {
40756
40800
  #processes;
40757
40801
  #observer = new NullAcpSessionObserver();
40758
40802
  #store = new MemoryAcpSessionStore();
40759
- constructor(processes) {
40803
+ #contentExternalizer;
40804
+ constructor(processes, contentExternalizer) {
40760
40805
  this.#processes = processes;
40806
+ this.#contentExternalizer = contentExternalizer;
40761
40807
  this.#processesByQuery = new RetainedAgentProcesses({
40762
40808
  touch: processes.touch,
40763
40809
  changed: processes.notifyChanged
@@ -40773,7 +40819,12 @@ var AgentQueryProcesses = class {
40773
40819
  async #startRetained(options) {
40774
40820
  const runtime = await this.#processes.startRetained(
40775
40821
  options.signal,
40776
- () => AgentSession.startNativeSessionBrowser(options, () => this.#observer, this.#store),
40822
+ () => AgentSession.startNativeSessionBrowser(
40823
+ options,
40824
+ () => this.#observer,
40825
+ this.#store,
40826
+ this.#contentExternalizer
40827
+ ),
40777
40828
  {
40778
40829
  isBusy: () => this.#processesByQuery.isBusy(options.sessionId),
40779
40830
  retire: (runtime2) => this.retire(options.sessionId, runtime2)
@@ -40849,7 +40900,8 @@ var AgentQueryProcesses = class {
40849
40900
  async () => await AgentSession.startNativeSessionBrowser(
40850
40901
  options,
40851
40902
  () => this.#observer,
40852
- new MemoryAcpSessionStore()
40903
+ new MemoryAcpSessionStore(),
40904
+ this.#contentExternalizer
40853
40905
  ),
40854
40906
  async (runtime) => {
40855
40907
  runtime.selectNativeSession(nativeSessionId);
@@ -40864,7 +40916,8 @@ var AgentQueryProcesses = class {
40864
40916
  async () => await AgentSession.startNativeSessionBrowser(
40865
40917
  options,
40866
40918
  () => this.#observer,
40867
- new MemoryAcpSessionStore()
40919
+ new MemoryAcpSessionStore(),
40920
+ this.#contentExternalizer
40868
40921
  ),
40869
40922
  async (runtime) => {
40870
40923
  runtime.selectNativeSession(nativeSessionId);
@@ -40880,6 +40933,220 @@ var AgentQueryProcesses = class {
40880
40933
  };
40881
40934
  };
40882
40935
 
40936
+ // src/external-content/acp-content-externalizer.ts
40937
+ var MAXIMUM_ENCODED_CONTENT_CHARACTERS = 4e6;
40938
+ function decodeBase64(data) {
40939
+ if (data.length > MAXIMUM_ENCODED_CONTENT_CHARACTERS || data.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/u.test(data)) {
40940
+ throw new Error("The ACP embedded content is not valid bounded base64");
40941
+ }
40942
+ return Buffer.from(data, "base64");
40943
+ }
40944
+ var AcpContentExternalizer = class {
40945
+ #store;
40946
+ constructor(store) {
40947
+ this.#store = store;
40948
+ }
40949
+ async #content(sessionId, content, signal) {
40950
+ switch (content.type) {
40951
+ case "text":
40952
+ case "resource_link":
40953
+ return content;
40954
+ case "image": {
40955
+ if (content.data.length === 0) {
40956
+ return content;
40957
+ }
40958
+ const stored = await this.#store.put({
40959
+ bytes: decodeBase64(content.data),
40960
+ kind: "image",
40961
+ mediaType: content.mimeType,
40962
+ name: "image",
40963
+ sessionId,
40964
+ signal
40965
+ });
40966
+ return {
40967
+ _meta: content._meta,
40968
+ annotations: content.annotations,
40969
+ byteLength: stored.byteLength,
40970
+ imageKey: stored.key,
40971
+ mimeType: content.mimeType,
40972
+ type: "external_image",
40973
+ uri: content.uri
40974
+ };
40975
+ }
40976
+ case "audio": {
40977
+ if (content.data.length === 0) {
40978
+ return content;
40979
+ }
40980
+ const stored = await this.#store.put({
40981
+ bytes: decodeBase64(content.data),
40982
+ kind: "audio",
40983
+ mediaType: content.mimeType,
40984
+ name: "audio",
40985
+ sessionId,
40986
+ signal
40987
+ });
40988
+ return {
40989
+ _meta: content._meta,
40990
+ annotations: content.annotations,
40991
+ audioKey: stored.key,
40992
+ byteLength: stored.byteLength,
40993
+ mimeType: content.mimeType,
40994
+ type: "external_audio"
40995
+ };
40996
+ }
40997
+ case "resource": {
40998
+ const embedded = content.resource;
40999
+ const encoding = "text" in embedded ? "text" : "binary";
41000
+ const bytes = "text" in embedded ? Buffer.from(embedded.text, "utf8") : decodeBase64(embedded.blob);
41001
+ if (bytes.byteLength === 0) {
41002
+ return content;
41003
+ }
41004
+ const mediaType = embedded.mimeType ?? "application/octet-stream";
41005
+ const stored = await this.#store.put({
41006
+ bytes,
41007
+ kind: "resource",
41008
+ mediaType,
41009
+ name: "resource",
41010
+ sessionId,
41011
+ signal
41012
+ });
41013
+ return {
41014
+ _meta: content._meta,
41015
+ annotations: content.annotations,
41016
+ byteLength: stored.byteLength,
41017
+ encoding,
41018
+ mimeType: embedded.mimeType,
41019
+ resourceKey: stored.key,
41020
+ type: "external_resource",
41021
+ uri: embedded.uri
41022
+ };
41023
+ }
41024
+ }
41025
+ }
41026
+ async #toolContent(sessionId, item, signal) {
41027
+ return item.type === "content" ? { ...item, content: await this.#content(sessionId, item.content, signal) } : item;
41028
+ }
41029
+ update = async (sessionId, update, signal) => {
41030
+ switch (update.sessionUpdate) {
41031
+ case "user_message_chunk":
41032
+ case "agent_message_chunk":
41033
+ case "agent_thought_chunk":
41034
+ case "compaction_summary_chunk":
41035
+ return { ...update, content: await this.#content(sessionId, update.content, signal) };
41036
+ case "tool_call":
41037
+ case "tool_call_update":
41038
+ return update.content === void 0 || update.content === null ? update : {
41039
+ ...update,
41040
+ content: await Promise.all(
41041
+ update.content.map(async (item) => await this.#toolContent(sessionId, item, signal))
41042
+ )
41043
+ };
41044
+ case "compaction_update":
41045
+ return update.summary === void 0 || update.summary === null ? update : {
41046
+ ...update,
41047
+ summary: await Promise.all(
41048
+ update.summary.map(async (content) => await this.#content(sessionId, content, signal))
41049
+ )
41050
+ };
41051
+ case "plan":
41052
+ case "plan_update":
41053
+ case "plan_removed":
41054
+ case "available_commands_update":
41055
+ case "current_mode_update":
41056
+ case "config_option_update":
41057
+ case "session_info_update":
41058
+ case "usage_update":
41059
+ return update;
41060
+ }
41061
+ };
41062
+ };
41063
+
41064
+ // src/external-content/local-external-content-store.ts
41065
+ import { createHash as createHash3, randomUUID as randomUUID2 } from "node:crypto";
41066
+ import { lstat, mkdir as mkdir6, readFile as readFile3, realpath as realpath8, rename as rename4, rm as rm3, stat as stat7, writeFile as writeFile4 } from "node:fs/promises";
41067
+ import { dirname as dirname5, join as join16 } from "node:path";
41068
+ var contentRequest = /^mobius-content:(image|audio|resource):([a-f0-9]{64})$/u;
41069
+ var metadataSchema2 = external_exports.strictObject({
41070
+ kind: external_exports.enum(["image", "audio", "resource"]),
41071
+ mediaType: external_exports.string().min(1).max(2048).regex(/^[\u0020-\u007e]+$/u),
41072
+ name: external_exports.string().min(1).max(500)
41073
+ });
41074
+ var UnretainedExternalContentStore = class {
41075
+ put = async ({ bytes, signal }) => {
41076
+ signal.throwIfAborted();
41077
+ return { byteLength: bytes.byteLength, key: createHash3("sha256").update(bytes).digest("hex") };
41078
+ };
41079
+ resolve = (_sessionId, _request, signal) => {
41080
+ signal.throwIfAborted();
41081
+ return Promise.resolve(null);
41082
+ };
41083
+ };
41084
+ function sessionScope(sessionId) {
41085
+ return createHash3("sha256").update(sessionId).digest("hex");
41086
+ }
41087
+ async function atomicWrite(path3, bytes, signal) {
41088
+ const temporary = `${path3}.${randomUUID2()}.tmp`;
41089
+ try {
41090
+ await writeFile4(temporary, bytes, { mode: 384, signal });
41091
+ signal.throwIfAborted();
41092
+ await rename4(temporary, path3);
41093
+ } finally {
41094
+ await rm3(temporary, { force: true });
41095
+ }
41096
+ }
41097
+ var LocalExternalContentStore = class {
41098
+ #root;
41099
+ constructor(stateDirectory) {
41100
+ this.#root = join16(stateDirectory, "tmp", "session-content");
41101
+ }
41102
+ put = async ({ bytes, kind, mediaType, name, sessionId, signal }) => {
41103
+ signal.throwIfAborted();
41104
+ const key = createHash3("sha256").update(bytes).digest("hex");
41105
+ const directory = join16(this.#root, sessionScope(sessionId), kind);
41106
+ await mkdir6(directory, { mode: 448, recursive: true });
41107
+ signal.throwIfAborted();
41108
+ const path3 = join16(directory, key);
41109
+ await atomicWrite(path3, bytes, signal);
41110
+ await atomicWrite(
41111
+ `${path3}.json`,
41112
+ Buffer.from(JSON.stringify(metadataSchema2.parse({ kind, mediaType, name })), "utf8"),
41113
+ signal
41114
+ );
41115
+ return { byteLength: bytes.byteLength, key };
41116
+ };
41117
+ resolve = async (sessionId, request, signal) => {
41118
+ const matched = contentRequest.exec(request);
41119
+ if (matched === null) {
41120
+ return null;
41121
+ }
41122
+ const kind = matched[1];
41123
+ const key = matched[2];
41124
+ if (kind !== "image" && kind !== "audio" && kind !== "resource" || key === void 0) {
41125
+ return null;
41126
+ }
41127
+ const directory = join16(this.#root, sessionScope(sessionId), kind);
41128
+ const path3 = join16(directory, key);
41129
+ try {
41130
+ const [resolvedDirectory, resolvedPath, file2, metadata] = await Promise.all([
41131
+ realpath8(directory),
41132
+ realpath8(path3),
41133
+ lstat(path3),
41134
+ readFile3(`${path3}.json`, "utf8").then((value) => metadataSchema2.parse(JSON.parse(value)))
41135
+ ]);
41136
+ signal.throwIfAborted();
41137
+ if (!file2.isFile() || dirname5(resolvedPath) !== resolvedDirectory || metadata.kind !== kind) {
41138
+ return null;
41139
+ }
41140
+ await stat7(resolvedPath);
41141
+ signal.throwIfAborted();
41142
+ return { mediaType: metadata.mediaType, name: metadata.name, path: resolvedPath };
41143
+ } catch {
41144
+ signal.throwIfAborted();
41145
+ return null;
41146
+ }
41147
+ };
41148
+ };
41149
+
40883
41150
  // src/native-sessions/chat-agent.ts
40884
41151
  function supportsNativeChat(agentId) {
40885
41152
  return agentId === "codex" || agentId === "claude" || agentId === "opencode" || agentId === "pi";
@@ -41096,7 +41363,7 @@ var AgentRuntimeManager = class {
41096
41363
  touch: this.#processes.touch,
41097
41364
  changed: this.#processes.notifyChanged
41098
41365
  });
41099
- #queryProcesses = new AgentQueryProcesses(this.#processes);
41366
+ #queryProcesses;
41100
41367
  #executions = new ActiveExecutions();
41101
41368
  #agentSettingsObserver = new NullAcpSessionObserver();
41102
41369
  #nativeOperations = /* @__PURE__ */ new Set();
@@ -41104,13 +41371,16 @@ var AgentRuntimeManager = class {
41104
41371
  #nativeHistoryReader;
41105
41372
  #sessionIdentity;
41106
41373
  #onSessionStatusChanged;
41374
+ #contentExternalizer;
41107
41375
  #observer;
41108
- constructor(observer = new NullAcpSessionObserver(), store = new MemoryAcpSessionStore(), nativeHistoryReader = null, sessionIdentity = "assigned", onSessionStatusChanged = () => void 0) {
41376
+ constructor(observer = new NullAcpSessionObserver(), store = new MemoryAcpSessionStore(), nativeHistoryReader = null, sessionIdentity = "assigned", onSessionStatusChanged = () => void 0, contentExternalizer = new AcpContentExternalizer(new UnretainedExternalContentStore())) {
41109
41377
  this.#observer = observer;
41110
41378
  this.#store = store;
41111
41379
  this.#nativeHistoryReader = nativeHistoryReader;
41112
41380
  this.#sessionIdentity = sessionIdentity;
41113
41381
  this.#onSessionStatusChanged = onSessionStatusChanged;
41382
+ this.#contentExternalizer = contentExternalizer;
41383
+ this.#queryProcesses = new AgentQueryProcesses(this.#processes, contentExternalizer);
41114
41384
  }
41115
41385
  setObserver = (observer) => {
41116
41386
  this.#observer = observer;
@@ -41151,7 +41421,8 @@ var AgentRuntimeManager = class {
41151
41421
  options.origin === void 0 && this.#sessionIdentity === "native" && isNativeChatSessionId(options.agent.id, options.sessionId) && this.#store.read(options.sessionId) instanceof MissingAcpStoredSession ? { ...options, origin: { kind: "import", nativeSessionId: options.sessionId } } : options,
41152
41422
  () => this.#observer,
41153
41423
  this.#store,
41154
- metrics
41424
+ metrics,
41425
+ this.#contentExternalizer
41155
41426
  )
41156
41427
  );
41157
41428
  });
@@ -41166,7 +41437,13 @@ var AgentRuntimeManager = class {
41166
41437
  this.#store.remove(options.sessionId);
41167
41438
  return await this.#startRetainedSessionProcess(
41168
41439
  options,
41169
- async () => await AgentSession.start(options, () => this.#observer, this.#store, metrics)
41440
+ async () => await AgentSession.start(
41441
+ options,
41442
+ () => this.#observer,
41443
+ this.#store,
41444
+ metrics,
41445
+ this.#contentExternalizer
41446
+ )
41170
41447
  );
41171
41448
  });
41172
41449
  }
@@ -41176,7 +41453,13 @@ var AgentRuntimeManager = class {
41176
41453
  await this.#retireSessionProcess(options.sessionId, existing, async () => await existing.close());
41177
41454
  const runtime = await this.#startRetainedSessionProcess(
41178
41455
  options,
41179
- async () => await AgentSession.start(options, () => this.#observer, this.#store)
41456
+ async () => await AgentSession.start(
41457
+ options,
41458
+ () => this.#observer,
41459
+ this.#store,
41460
+ unmeasuredOperationMetrics,
41461
+ this.#contentExternalizer
41462
+ )
41180
41463
  );
41181
41464
  try {
41182
41465
  for (const desired of desiredConfigOptions) {
@@ -41272,7 +41555,9 @@ var AgentRuntimeManager = class {
41272
41555
  sessionId: `agent-settings-${crypto.randomUUID()}`
41273
41556
  },
41274
41557
  () => this.#agentSettingsObserver,
41275
- new MemoryAcpSessionStore()
41558
+ new MemoryAcpSessionStore(),
41559
+ unmeasuredOperationMetrics,
41560
+ this.#contentExternalizer
41276
41561
  ),
41277
41562
  async (runtime) => {
41278
41563
  const prepared = runtime.prepared();
@@ -42325,9 +42610,9 @@ var FixedInstallationExecutor = class {
42325
42610
  };
42326
42611
 
42327
42612
  // src/authorization/workspace-directory.ts
42328
- import { readdir as readdir3, realpath as realpath8, stat as stat7 } from "node:fs/promises";
42613
+ import { readdir as readdir3, realpath as realpath9, stat as stat8 } from "node:fs/promises";
42329
42614
  import { homedir as homedir2 } from "node:os";
42330
- import { basename as basename4, dirname as dirname5, isAbsolute as isAbsolute9, join as join16, normalize as normalize3, relative as relative4 } from "node:path";
42615
+ import { basename as basename4, dirname as dirname6, isAbsolute as isAbsolute9, join as join17, normalize as normalize3, relative as relative4 } from "node:path";
42331
42616
 
42332
42617
  // src/authorization/local-authorization-error.ts
42333
42618
  var LocalAuthorizationError = class extends Error {
@@ -42406,9 +42691,9 @@ var WorkspaceDirectoryService = class {
42406
42691
  throw new LocalAuthorizationError("The local directory path is invalid");
42407
42692
  }
42408
42693
  try {
42409
- const target = await realpath8(requested);
42694
+ const target = await realpath9(requested);
42410
42695
  signal.throwIfAborted();
42411
- const metadata = await stat7(target);
42696
+ const metadata = await stat8(target);
42412
42697
  signal.throwIfAborted();
42413
42698
  if (!isAbsolute9(target) || normalize3(target) !== target || !metadata.isDirectory()) {
42414
42699
  throw new LocalAuthorizationError("The selected location is not a directory");
@@ -42456,7 +42741,7 @@ var WorkspaceDirectoryService = class {
42456
42741
  continue;
42457
42742
  }
42458
42743
  try {
42459
- const path3 = await this.resolvePath(join16(target, child2.name), signal);
42744
+ const path3 = await this.resolvePath(join17(target, child2.name), signal);
42460
42745
  entries.push({ directoryId: encodePath(path3), name: child2.name });
42461
42746
  } catch (cause) {
42462
42747
  signal.throwIfAborted();
@@ -42466,7 +42751,7 @@ var WorkspaceDirectoryService = class {
42466
42751
  }
42467
42752
  }
42468
42753
  entries.sort((a, b) => a.name.localeCompare(b.name));
42469
- const parent = dirname5(target);
42754
+ const parent = dirname6(target);
42470
42755
  return new WorkspaceDirectoryListing(
42471
42756
  id,
42472
42757
  this.label(target),
@@ -42492,15 +42777,15 @@ var WorkspaceDirectoryService = class {
42492
42777
 
42493
42778
  // src/daemon-diagnostic-log.ts
42494
42779
  import { appendFileSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, statSync as statSync3, writeFileSync } from "node:fs";
42495
- import { join as join17 } from "node:path";
42780
+ import { join as join18 } from "node:path";
42496
42781
  var MAXIMUM_DAEMON_LOG_BYTES = 1 * 1024 * 1024;
42497
42782
  var DaemonDiagnosticLog = class {
42498
42783
  #directory;
42499
42784
  #path;
42500
42785
  #maximumBytes;
42501
42786
  constructor(stateDirectory, maximumBytes = MAXIMUM_DAEMON_LOG_BYTES) {
42502
- this.#directory = join17(stateDirectory, "logs");
42503
- this.#path = join17(this.#directory, "daemon.log");
42787
+ this.#directory = join18(stateDirectory, "logs");
42788
+ this.#path = join18(this.#directory, "daemon.log");
42504
42789
  this.#maximumBytes = maximumBytes;
42505
42790
  }
42506
42791
  record = (diagnostic) => {
@@ -42545,7 +42830,7 @@ import { WebSocket as WebSocket2 } from "undici";
42545
42830
  import { WebSocket } from "undici";
42546
42831
 
42547
42832
  // src/prompt-artifact-resolver.ts
42548
- import { createHash as createHash3 } from "node:crypto";
42833
+ import { createHash as createHash4 } from "node:crypto";
42549
42834
  import { fetch as fetch4 } from "undici";
42550
42835
  var ARTIFACT_SCHEME = "mobius-artifact:";
42551
42836
  var ARTIFACT_DOWNLOAD_TIMEOUT_MILLISECONDS = 2e4;
@@ -42683,7 +42968,7 @@ async function download(config2, command, reference, signal) {
42683
42968
  );
42684
42969
  }
42685
42970
  const bytes = await responseBytes(response, reference.byteLength, requestSignal);
42686
- if (createHash3("sha256").update(bytes).digest("hex") !== reference.sha256) {
42971
+ if (createHash4("sha256").update(bytes).digest("hex") !== reference.sha256) {
42687
42972
  throw new PromptArtifactError(
42688
42973
  "artifact_integrity_failed",
42689
42974
  "The prompt artifact failed integrity validation"
@@ -42988,7 +43273,7 @@ var DaemonInstallationObserver = class {
42988
43273
  };
42989
43274
 
42990
43275
  // src/daemon-active-turn.ts
42991
- import { randomUUID as randomUUID2 } from "node:crypto";
43276
+ import { randomUUID as randomUUID3 } from "node:crypto";
42992
43277
  function activeMessageCharacters(message) {
42993
43278
  return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
42994
43279
  }
@@ -43022,7 +43307,7 @@ var ActiveDaemonTurn = class {
43022
43307
  #timeline;
43023
43308
  #sequence = 0;
43024
43309
  #interaction = null;
43025
- #epoch = decodeIdentifier(randomUUID2());
43310
+ #epoch = decodeIdentifier(randomUUID3());
43026
43311
  constructor(command, attemptId) {
43027
43312
  this.attemptId = attemptId;
43028
43313
  this.command = command;
@@ -43084,7 +43369,7 @@ var ActiveDaemonTurn = class {
43084
43369
  if (!this.#activities.has(event.activityId)) {
43085
43370
  this.#timeline = [
43086
43371
  ...this.#timeline,
43087
- { activityId: event.activityId, id: decodeIdentifier(randomUUID2()), kind: "activity" }
43372
+ { activityId: event.activityId, id: decodeIdentifier(randomUUID3()), kind: "activity" }
43088
43373
  ];
43089
43374
  }
43090
43375
  this.#activities.set(event.activityId, {
@@ -43105,7 +43390,7 @@ var ActiveDaemonTurn = class {
43105
43390
  if (previous === void 0) {
43106
43391
  this.#timeline = [
43107
43392
  ...this.#timeline,
43108
- { activityId: event.activityId, id: decodeIdentifier(randomUUID2()), kind: "activity" }
43393
+ { activityId: event.activityId, id: decodeIdentifier(randomUUID3()), kind: "activity" }
43109
43394
  ];
43110
43395
  }
43111
43396
  this.#activities.set(event.activityId, {
@@ -43130,7 +43415,7 @@ var ActiveDaemonTurn = class {
43130
43415
  ...this.#timeline,
43131
43416
  {
43132
43417
  content: /* @__PURE__ */ new Map([[event.contentId, event.content]]),
43133
- id: decodeIdentifier(randomUUID2()),
43418
+ id: decodeIdentifier(randomUUID3()),
43134
43419
  kind: "message",
43135
43420
  sourceMessageId: event.messageId,
43136
43421
  text: ""
@@ -43170,7 +43455,7 @@ var ActiveDaemonTurn = class {
43170
43455
  ...this.#timeline,
43171
43456
  {
43172
43457
  content: /* @__PURE__ */ new Map(),
43173
- id: decodeIdentifier(randomUUID2()),
43458
+ id: decodeIdentifier(randomUUID3()),
43174
43459
  kind: "message",
43175
43460
  sourceMessageId: messageId,
43176
43461
  text: remaining.slice(0, ACTIVE_TURN_TEXT_CHUNK_LIMIT)
@@ -44146,7 +44431,7 @@ var readCodexFullHistory = async (agent, cwd, nativeSessionId, signal, nativeTur
44146
44431
  });
44147
44432
 
44148
44433
  // src/native-sessions/service.ts
44149
- import { randomUUID as randomUUID3 } from "node:crypto";
44434
+ import { randomUUID as randomUUID4 } from "node:crypto";
44150
44435
  import { basename as basename5 } from "node:path";
44151
44436
 
44152
44437
  // src/native-sessions/acp-history.ts
@@ -44361,7 +44646,7 @@ var NativeSessionService = class {
44361
44646
  if (authorized === null) {
44362
44647
  return null;
44363
44648
  }
44364
- const entryId = decodeIdentifier(randomUUID3());
44649
+ const entryId = decodeIdentifier(randomUUID4());
44365
44650
  if (this.#entries.size >= 5e3) {
44366
44651
  this.#entries.clear();
44367
44652
  }
@@ -44417,7 +44702,7 @@ var NativeSessionService = class {
44417
44702
  "invalid_native_session_response"
44418
44703
  );
44419
44704
  }
44420
- nextCursor = decodeIdentifier(randomUUID3());
44705
+ nextCursor = decodeIdentifier(randomUUID4());
44421
44706
  if (this.#cursors.size >= 500) {
44422
44707
  this.#cursors.clear();
44423
44708
  }
@@ -44699,7 +44984,7 @@ var NativeSessionService = class {
44699
44984
  };
44700
44985
 
44701
44986
  // src/relay-connection/daemon-operation-state.ts
44702
- import { createHash as createHash4, randomUUID as randomUUID4 } from "node:crypto";
44987
+ import { createHash as createHash5, randomUUID as randomUUID5 } from "node:crypto";
44703
44988
  var MAX_TERMINAL_RECEIPTS = 1024;
44704
44989
  function isTerminal(state) {
44705
44990
  return state === "succeeded" || state === "failed" || state === "cancelled";
@@ -44708,7 +44993,7 @@ var DaemonOperationState = class {
44708
44993
  #executions = /* @__PURE__ */ new Map();
44709
44994
  #terminalCount = 0;
44710
44995
  claimExecution = (commandId, sessionId, commandJson) => {
44711
- const commandHash = createHash4("sha256").update(commandJson).digest("hex");
44996
+ const commandHash = createHash5("sha256").update(commandJson).digest("hex");
44712
44997
  const existing = this.#executions.get(commandId);
44713
44998
  if (existing !== void 0) {
44714
44999
  if (existing.sessionId !== sessionId || existing.commandHash !== commandHash) {
@@ -44716,7 +45001,7 @@ var DaemonOperationState = class {
44716
45001
  }
44717
45002
  return { attemptId: existing.attemptId, commandId, kind: "duplicate", state: existing.state };
44718
45003
  }
44719
- const attemptId = randomUUID4();
45004
+ const attemptId = randomUUID5();
44720
45005
  this.#executions.set(commandId, { attemptId, commandHash, sessionId, state: "dispatching" });
44721
45006
  return { attemptId, commandId, kind: "accepted", state: "dispatching" };
44722
45007
  };
@@ -45052,7 +45337,7 @@ function createAgentCatalogRefreshHandler(dependencies) {
45052
45337
  import { WebSocket as WebSocket4 } from "undici";
45053
45338
 
45054
45339
  // src/agent-catalog/discover-agent-settings.ts
45055
- import { createHash as createHash5 } from "node:crypto";
45340
+ import { createHash as createHash6 } from "node:crypto";
45056
45341
 
45057
45342
  // src/agent-catalog/agent-settings-base.ts
45058
45343
  var AgentSettingsConfigurationError = class extends Error {
@@ -45516,7 +45801,7 @@ function settingsRevision(agent, reportedAgentVersion, settings, modelEffort) {
45516
45801
  unsupportedModelIds: modelEffort.unsupportedModelIds,
45517
45802
  valuesByModel: {}
45518
45803
  };
45519
- return createHash5("sha256").update(
45804
+ return createHash6("sha256").update(
45520
45805
  JSON.stringify({
45521
45806
  adapterVersion: agent.kind === "acp-adapter-process" ? agent.adapterVersion : agent.agentVersion,
45522
45807
  agentId: agent.id,
@@ -45667,7 +45952,7 @@ function createAgentSettingsDiscoveryHandler(dependencies) {
45667
45952
 
45668
45953
  // src/artifacts/local-file-streamer.ts
45669
45954
  import { createReadStream as createReadStream2 } from "node:fs";
45670
- import { realpath as realpath9, stat as stat8 } from "node:fs/promises";
45955
+ import { realpath as realpath10, stat as stat9 } from "node:fs/promises";
45671
45956
  import { basename as basename6, isAbsolute as isAbsolute10, normalize as normalize4, resolve as resolve7 } from "node:path";
45672
45957
  import { fileURLToPath as fileURLToPath2 } from "node:url";
45673
45958
  var CHUNK_BYTES = 192 * 1024;
@@ -45695,7 +45980,7 @@ async function resolveFile(value, workingDirectory, signal) {
45695
45980
  return null;
45696
45981
  }
45697
45982
  try {
45698
- const target = await realpath9(requested);
45983
+ const target = await realpath10(requested);
45699
45984
  signal.throwIfAborted();
45700
45985
  return isAbsolute10(target) && normalize4(target) === target ? target : null;
45701
45986
  } catch {
@@ -45703,23 +45988,24 @@ async function resolveFile(value, workingDirectory, signal) {
45703
45988
  return null;
45704
45989
  }
45705
45990
  }
45706
- async function streamLocalFile(command, send2, signal, workingDirectory) {
45707
- const target = await resolveFile(command.path, workingDirectory, signal);
45991
+ async function streamLocalFile(command, send2, signal, workingDirectory, externalContent) {
45992
+ const external = await externalContent.resolve(command.sessionId, command.path, signal);
45993
+ const target = external?.path ?? await resolveFile(command.path, workingDirectory, signal);
45708
45994
  if (target === null) {
45709
45995
  throw new Error("The local file is unavailable");
45710
45996
  }
45711
- const before = await stat8(target);
45997
+ const before = await stat9(target);
45712
45998
  signal.throwIfAborted();
45713
45999
  if (!before.isFile() || before.size < 1 || before.size > command.maxBytes) {
45714
46000
  throw new Error("The local file is too large to read");
45715
46001
  }
45716
- const raster = await readLocalRaster(target, signal);
46002
+ const raster = external === null ? await readLocalRaster(target, signal) : null;
45717
46003
  send2({
45718
46004
  byteLength: before.size,
45719
46005
  kind: FILE_BEGIN_KIND,
45720
- mediaType: raster?.mimeType ?? "application/octet-stream",
46006
+ mediaType: external?.mediaType ?? raster?.mimeType ?? "application/octet-stream",
45721
46007
  modifiedAt: before.mtime.toISOString(),
45722
- name: basename6(target) || "file",
46008
+ name: external?.name ?? (basename6(target) || "file"),
45723
46009
  requestId: command.requestId,
45724
46010
  sessionId: command.sessionId
45725
46011
  });
@@ -45736,7 +46022,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
45736
46022
  });
45737
46023
  sequence += 1;
45738
46024
  }
45739
- const after = await stat8(target);
46025
+ const after = await stat9(target);
45740
46026
  signal.throwIfAborted();
45741
46027
  if (after.size !== before.size || after.mtimeMs !== before.mtimeMs) {
45742
46028
  throw new Error("The local file changed during transfer");
@@ -45749,7 +46035,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
45749
46035
  }
45750
46036
 
45751
46037
  // src/daemon-history-commands.ts
45752
- import { createHash as createHash6 } from "node:crypto";
46038
+ import { createHash as createHash7 } from "node:crypto";
45753
46039
 
45754
46040
  // src/authorization/resolve-session-directories.ts
45755
46041
  import { basename as basename7 } from "node:path";
@@ -46143,7 +46429,7 @@ async function executeSessionLiveHistoryPageLoad(socket, command, config2, direc
46143
46429
  }
46144
46430
  function replayEvent(sessionId, position, update) {
46145
46431
  const encoded = JSON.stringify(update);
46146
- const eventId = `native-${createHash6("sha256").update(sessionId).update(":").update(position.toString()).update(":").update(encoded).digest("hex")}`;
46432
+ const eventId = `native-${createHash7("sha256").update(sessionId).update(":").update(position.toString()).update(":").update(encoded).digest("hex")}`;
46147
46433
  return {
46148
46434
  eventId,
46149
46435
  payload: update,
@@ -46226,7 +46512,7 @@ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, dir
46226
46512
  }
46227
46513
 
46228
46514
  // src/acp/session-config/apply-session-configuration.ts
46229
- import { randomUUID as randomUUID5 } from "node:crypto";
46515
+ import { randomUUID as randomUUID6 } from "node:crypto";
46230
46516
  function invalidSessionConfiguration(message) {
46231
46517
  return new AcpExecutionError(message, {}, "invalid_session_configuration");
46232
46518
  }
@@ -46367,7 +46653,7 @@ async function applySessionConfigurationSelection(sessions, audit, options, sele
46367
46653
  booleanValue: selection.booleanValue,
46368
46654
  configId: selection.configId,
46369
46655
  cwd,
46370
- requestId: `cfg_${randomUUID5()}`,
46656
+ requestId: `cfg_${randomUUID6()}`,
46371
46657
  sessionId,
46372
46658
  signal,
46373
46659
  value: selection.value,
@@ -47041,6 +47327,7 @@ function createDaemonCommandHandler({
47041
47327
  operations,
47042
47328
  publisher,
47043
47329
  eventLogV2,
47330
+ externalContent,
47044
47331
  activeTurns,
47045
47332
  diagnostics,
47046
47333
  socket,
@@ -47149,7 +47436,8 @@ function createDaemonCommandHandler({
47149
47436
  command2,
47150
47437
  (message2) => send(socket, message2),
47151
47438
  signal,
47152
- sessions.findSessions([command2.sessionId])[0]?.cwd ?? null
47439
+ sessions.findSessions([command2.sessionId])[0]?.cwd ?? null,
47440
+ externalContent
47153
47441
  ).catch((error62) => {
47154
47442
  if (socket.readyState !== WebSocket6.OPEN || signal.aborted) {
47155
47443
  return;
@@ -47488,7 +47776,7 @@ function connectRelay(url2, signal) {
47488
47776
  }
47489
47777
 
47490
47778
  // src/relay-connection/liveness.ts
47491
- import { randomUUID as randomUUID6 } from "node:crypto";
47779
+ import { randomUUID as randomUUID7 } from "node:crypto";
47492
47780
  var HEARTBEAT_ACK_TIMEOUT_MILLISECONDS = 1e4;
47493
47781
  var HEARTBEAT_INTERVAL_MILLISECONDS = 2e4;
47494
47782
  var RelayLivenessState = class {
@@ -47577,7 +47865,7 @@ var RelayConnectionLiveness = class {
47577
47865
  }
47578
47866
  throw new Error("Heartbeat was scheduled in an invalid state");
47579
47867
  }
47580
- const heartbeatId = randomUUID6();
47868
+ const heartbeatId = randomUUID7();
47581
47869
  this.#state = new AwaitingHeartbeatAckState(
47582
47870
  heartbeatId,
47583
47871
  this.#timer.schedule(this.#handleTimeout, HEARTBEAT_ACK_TIMEOUT_MILLISECONDS)
@@ -47617,6 +47905,7 @@ async function runRelayConnection({
47617
47905
  operations,
47618
47906
  publisher,
47619
47907
  eventLogV2,
47908
+ externalContent,
47620
47909
  activeTurns,
47621
47910
  connectionEpoch,
47622
47911
  diagnostics,
@@ -47640,6 +47929,7 @@ async function runRelayConnection({
47640
47929
  operations,
47641
47930
  publisher,
47642
47931
  eventLogV2,
47932
+ externalContent,
47643
47933
  activeTurns,
47644
47934
  diagnostics,
47645
47935
  socket,
@@ -48118,7 +48408,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
48118
48408
  {
48119
48409
  agentId: agent.id,
48120
48410
  kind: AGENT_INSTALL_REQUEST_KIND,
48121
- requestId: `automatic-integration-${randomUUID7()}`
48411
+ requestId: `automatic-integration-${randomUUID8()}`
48122
48412
  },
48123
48413
  signal
48124
48414
  );
@@ -48137,8 +48427,9 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
48137
48427
  stateDirectory
48138
48428
  });
48139
48429
  const sessionStore = new SqliteAcpSessionStore(
48140
- join18(stateDirectory, "sessions", `${createHash7("sha256").update(config2.channelId).digest("hex")}.sqlite`)
48430
+ join19(stateDirectory, "sessions", `${createHash8("sha256").update(config2.channelId).digest("hex")}.sqlite`)
48141
48431
  );
48432
+ const externalContent = new LocalExternalContentStore(stateDirectory);
48142
48433
  const operations = new DaemonOperationState();
48143
48434
  const publisher = new DaemonSessionEventPublisher(sessionStore);
48144
48435
  const eventLogV2 = new DaemonSessionEventLogV2(publisher, sessionStore);
@@ -48159,7 +48450,8 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
48159
48450
  )).history : null
48160
48451
  },
48161
48452
  "native",
48162
- publisher.publishStatus
48453
+ publisher.publishStatus,
48454
+ new AcpContentExternalizer(externalContent)
48163
48455
  );
48164
48456
  const directories = new WorkspaceDirectoryService(config2.bindingId, config2.defaultWorkspace);
48165
48457
  const installationObserver = new DaemonInstallationObserver();
@@ -48273,6 +48565,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
48273
48565
  operations,
48274
48566
  publisher,
48275
48567
  eventLogV2,
48568
+ externalContent,
48276
48569
  activeTurns,
48277
48570
  connectionEpoch,
48278
48571
  diagnostics,
@@ -48394,17 +48687,17 @@ var START_TIMEOUT_MILLISECONDS = 12e4;
48394
48687
  var MAXIMUM_MESSAGE_BYTES = 64 * 1024;
48395
48688
  var CONNECTION_ID_PATTERN2 = /^mcn_[a-f0-9]{32}$/;
48396
48689
  async function acquireManagerLock(stateDirectory) {
48397
- const path3 = join19(stateDirectory, "manager.lock");
48690
+ const path3 = join20(stateDirectory, "manager.lock");
48398
48691
  for (let attempt = 0; attempt < 2; attempt += 1) {
48399
48692
  try {
48400
- await writeFile4(path3, `${process.pid.toString()}
48693
+ await writeFile5(path3, `${process.pid.toString()}
48401
48694
  `, { flag: "wx", mode: 384 });
48402
48695
  return async () => await unlink2(path3).catch(() => void 0);
48403
48696
  } catch (cause) {
48404
48697
  if (!isNodeError2(cause, "EEXIST")) {
48405
48698
  throw cause;
48406
48699
  }
48407
- const encoded = await readFile3(path3, "utf8").catch(() => "");
48700
+ const encoded = await readFile4(path3, "utf8").catch(() => "");
48408
48701
  const pid = Number(encoded.trim());
48409
48702
  if (Number.isSafeInteger(pid) && pid > 1) {
48410
48703
  try {
@@ -48425,16 +48718,16 @@ function isRecord11(value) {
48425
48718
  return typeof value === "object" && value !== null && !Array.isArray(value);
48426
48719
  }
48427
48720
  function controlSocketPath(stateDirectory) {
48428
- const installationHash = createHash8("sha256").update(stateDirectory).digest("hex").slice(0, 32);
48429
- return process.platform === "win32" ? `\\\\.\\pipe\\mobius-${installationHash}` : join19(tmpdir(), `mobius-${installationHash}.sock`);
48721
+ const installationHash = createHash9("sha256").update(stateDirectory).digest("hex").slice(0, 32);
48722
+ return process.platform === "win32" ? `\\\\.\\pipe\\mobius-${installationHash}` : join20(tmpdir(), `mobius-${installationHash}.sock`);
48430
48723
  }
48431
48724
  function controlTokenPath(stateDirectory) {
48432
- return join19(stateDirectory, "manager.token");
48725
+ return join20(stateDirectory, "manager.token");
48433
48726
  }
48434
48727
  async function readOrCreateControlToken(stateDirectory) {
48435
48728
  const path3 = controlTokenPath(stateDirectory);
48436
48729
  try {
48437
- return (await readFile3(path3, "utf8")).trim();
48730
+ return (await readFile4(path3, "utf8")).trim();
48438
48731
  } catch (cause) {
48439
48732
  if (!isNodeError2(cause, "ENOENT")) {
48440
48733
  throw cause;
@@ -48442,14 +48735,14 @@ async function readOrCreateControlToken(stateDirectory) {
48442
48735
  }
48443
48736
  const token = randomBytes(32).toString("base64url");
48444
48737
  try {
48445
- await writeFile4(path3, `${token}
48738
+ await writeFile5(path3, `${token}
48446
48739
  `, { flag: "wx", mode: 384 });
48447
48740
  return token;
48448
48741
  } catch (cause) {
48449
48742
  if (!isNodeError2(cause, "EEXIST")) {
48450
48743
  throw cause;
48451
48744
  }
48452
- return (await readFile3(path3, "utf8")).trim();
48745
+ return (await readFile4(path3, "utf8")).trim();
48453
48746
  }
48454
48747
  }
48455
48748
  function isNodeError2(error62, code) {
@@ -48761,7 +49054,7 @@ async function waitForManagerExit(stateDirectory, signal) {
48761
49054
  const deadline = AbortSignal.any([signal, AbortSignal.timeout(1e4)]);
48762
49055
  while (!deadline.aborted) {
48763
49056
  try {
48764
- await readFile3(join19(stateDirectory, "manager.lock"), "utf8");
49057
+ await readFile4(join20(stateDirectory, "manager.lock"), "utf8");
48765
49058
  } catch (cause) {
48766
49059
  if (isNodeError2(cause, "ENOENT")) {
48767
49060
  return;
@@ -49039,7 +49332,7 @@ function createProgram() {
49039
49332
  const installation = await openMobiusCliInstallation(shutdown.signal, process.env);
49040
49333
  const localContext = new DaemonLocalContext(installation.stateDirectory, process.env);
49041
49334
  const defaultWorkspace = loadDefaultWorkspace(localContext.environment);
49042
- await mkdir6(defaultWorkspace, { recursive: true, mode: 448 });
49335
+ await mkdir7(defaultWorkspace, { recursive: true, mode: 448 });
49043
49336
  const inventory = await discoverLocalAgentInventory({
49044
49337
  defaultWorkspace,
49045
49338
  environment: localContext.environment,