@moxt-ai/mobius 0.0.182 → 0.0.184

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 (34) hide show
  1. package/dist/acp/agent-connection.d.ts.map +1 -1
  2. package/dist/acp/agent-connection.js +14 -2
  3. package/dist/acp/agent-connection.js.map +1 -1
  4. package/dist/acp/agent-runtime-manager.d.ts +2 -1
  5. package/dist/acp/agent-runtime-manager.d.ts.map +1 -1
  6. package/dist/acp/agent-runtime-manager.js +46 -36
  7. package/dist/acp/agent-runtime-manager.js.map +1 -1
  8. package/dist/acp/agent-session.d.ts +4 -3
  9. package/dist/acp/agent-session.d.ts.map +1 -1
  10. package/dist/acp/agent-session.js +15 -3
  11. package/dist/acp/agent-session.js.map +1 -1
  12. package/dist/acp/codex/app-server-protocol.d.ts +4 -0
  13. package/dist/acp/codex/app-server-protocol.d.ts.map +1 -1
  14. package/dist/acp/codex/app-server-protocol.js +2 -0
  15. package/dist/acp/codex/app-server-protocol.js.map +1 -1
  16. package/dist/acp/codex/items.d.ts.map +1 -1
  17. package/dist/acp/codex/items.js +35 -11
  18. package/dist/acp/codex/items.js.map +1 -1
  19. package/dist/acp/session-contracts.d.ts +5 -0
  20. package/dist/acp/session-contracts.d.ts.map +1 -1
  21. package/dist/acp/session-contracts.js.map +1 -1
  22. package/dist/cli.js +177 -83
  23. package/dist/cli.js.map +4 -4
  24. package/dist/daemon-session-commands.d.ts.map +1 -1
  25. package/dist/daemon-session-commands.js +6 -4
  26. package/dist/daemon-session-commands.js.map +1 -1
  27. package/dist/external-content/acp-content-externalizer.d.ts.map +1 -1
  28. package/dist/external-content/acp-content-externalizer.js +13 -0
  29. package/dist/external-content/acp-content-externalizer.js.map +1 -1
  30. package/dist/index.js +171 -79
  31. package/dist/index.js.map +3 -3
  32. package/dist/runtime.js +174 -82
  33. package/dist/runtime.js.map +3 -3
  34. package/package.json +1 -1
package/dist/runtime.js CHANGED
@@ -23106,6 +23106,7 @@ function sessionFailureMeta(failure2) {
23106
23106
  import { spawn as spawn2 } from "node:child_process";
23107
23107
 
23108
23108
  // src/acp/codex/app-server-protocol.ts
23109
+ import { isAbsolute as isAbsolute2 } from "node:path";
23109
23110
  var boundedText = (maximum) => external_exports.string().max(maximum);
23110
23111
  var jsonValue = external_exports.lazy(() => external_exports.unknown());
23111
23112
  var requestIdSchema = external_exports.union([external_exports.number(), external_exports.string()]).refine((value) => typeof value === "number" || value.length <= 256);
@@ -23176,6 +23177,7 @@ var imageGenerationItemSchema = external_exports.object({
23176
23177
  });
23177
23178
  var threadItemSchema = external_exports.discriminatedUnion("type", [
23178
23179
  imageGenerationItemSchema,
23180
+ external_exports.object({ type: external_exports.literal("imageView"), id: boundedText(256), path: boundedText(32768).refine(isAbsolute2) }),
23179
23181
  external_exports.object({
23180
23182
  id: boundedText(256),
23181
23183
  text: boundedText(1e6),
@@ -23600,6 +23602,7 @@ var CodexAppServerClient = class {
23600
23602
  };
23601
23603
 
23602
23604
  // src/acp/codex/items.ts
23605
+ import { pathToFileURL } from "node:url";
23603
23606
  var TOOL_OUTPUT_CHARACTER_LIMIT = 32768;
23604
23607
  var TITLE_CHARACTER_LIMIT = 500;
23605
23608
  function truncate2(value, limit) {
@@ -23621,6 +23624,14 @@ function textContent(text2) {
23621
23624
  const block = { text: truncate2(text2, TOOL_OUTPUT_CHARACTER_LIMIT), type: "text" };
23622
23625
  return { content: block, type: "content" };
23623
23626
  }
23627
+ function structuredToolText(value) {
23628
+ const result = external_exports.object({ content: external_exports.array(external_exports.unknown()) }).safeParse(value);
23629
+ const items = Array.isArray(value) ? value : result.success ? result.data.content : [];
23630
+ return items.flatMap((item) => {
23631
+ const text2 = external_exports.object({ type: external_exports.enum(["text", "inputText"]), text: external_exports.string() }).safeParse(item);
23632
+ return text2.success ? [textContent(text2.data.text)] : [];
23633
+ });
23634
+ }
23624
23635
  function firstLine(value) {
23625
23636
  const line = value.split("\n", 1)[0] ?? "";
23626
23637
  return line.trim().length > 0 ? line.trim() : value.trim();
@@ -23641,6 +23652,22 @@ function mcpStatus(status) {
23641
23652
  return status === "inProgress" ? "in_progress" : status === "completed" ? "completed" : "failed";
23642
23653
  }
23643
23654
  function presentToolItem(item) {
23655
+ if (item.type === "imageView") {
23656
+ return {
23657
+ content: [
23658
+ {
23659
+ type: "content",
23660
+ content: { type: "image", data: "", mimeType: "", uri: pathToFileURL(item.path).href }
23661
+ }
23662
+ ],
23663
+ kind: "read",
23664
+ locations: [{ path: item.path }],
23665
+ rawInput: { path: item.path },
23666
+ rawOutput: null,
23667
+ status: "completed",
23668
+ title: "View image"
23669
+ };
23670
+ }
23644
23671
  if (item.type === "imageGeneration") {
23645
23672
  const failed = item.failure != null || item.status === "failed";
23646
23673
  const content = [];
@@ -23705,13 +23732,7 @@ function presentToolItem(item) {
23705
23732
  }
23706
23733
  if (item.type === "mcpToolCall") {
23707
23734
  const label = `${item.server}/${item.tool}`;
23708
- const content = [];
23709
- if (item.result != null) {
23710
- content.push(textContent(JSON.stringify(item.result)));
23711
- }
23712
- if (item.error != null) {
23713
- content.push(textContent(JSON.stringify(item.error)));
23714
- }
23735
+ const content = structuredToolText(item.error ?? item.result);
23715
23736
  return {
23716
23737
  content,
23717
23738
  kind: "other",
@@ -23724,13 +23745,13 @@ function presentToolItem(item) {
23724
23745
  }
23725
23746
  if (item.type === "dynamicToolCall") {
23726
23747
  const label = item.namespace == null ? item.tool : `${item.namespace}/${item.tool}`;
23727
- const content = (item.contentItems ?? []).map((entry) => textContent(JSON.stringify(entry)));
23748
+ const content = structuredToolText(item.contentItems);
23728
23749
  return {
23729
23750
  content,
23730
23751
  kind: "other",
23731
23752
  locations: [],
23732
23753
  rawInput: item.arguments ?? null,
23733
- rawOutput: item.success === true ? null : item.contentItems ?? null,
23754
+ rawOutput: item.contentItems ?? null,
23734
23755
  status: mcpStatus(item.status),
23735
23756
  title: truncate2(label, TITLE_CHARACTER_LIMIT)
23736
23757
  };
@@ -23743,12 +23764,12 @@ function toolCallUpdate(item, lifecycle) {
23743
23764
  return null;
23744
23765
  }
23745
23766
  return {
23746
- content: [...presentation.content],
23767
+ content: item.type === "imageView" && lifecycle === "started" ? [] : [...presentation.content],
23747
23768
  kind: presentation.kind,
23748
23769
  locations: [...presentation.locations],
23749
23770
  rawInput: presentation.rawInput,
23750
23771
  rawOutput: presentation.rawOutput,
23751
- status: lifecycle === "completed" && presentation.status === "in_progress" ? "completed" : presentation.status,
23772
+ status: item.type === "imageView" && lifecycle === "started" ? "in_progress" : lifecycle === "completed" && presentation.status === "in_progress" ? "completed" : presentation.status,
23752
23773
  title: presentation.title,
23753
23774
  toolCallId: item.id
23754
23775
  };
@@ -24972,12 +24993,12 @@ var AgentProbeError = class extends Error {
24972
24993
  };
24973
24994
 
24974
24995
  // src/agent-catalog/agents/resolve-user-local-executable.ts
24975
- import { isAbsolute as isAbsolute2, join as join4 } from "node:path";
24996
+ import { isAbsolute as isAbsolute3, join as join4 } from "node:path";
24976
24997
  async function resolveUserLocalExecutable(executableName, context) {
24977
24998
  context.signal.throwIfAborted();
24978
24999
  const platform = context.platform ?? process.platform;
24979
25000
  const homeDirectory = context.environment["HOME"];
24980
- if (platform === "win32" || homeDirectory === void 0 || !isAbsolute2(homeDirectory)) {
25001
+ if (platform === "win32" || homeDirectory === void 0 || !isAbsolute3(homeDirectory)) {
24981
25002
  return [];
24982
25003
  }
24983
25004
  const executable = await resolveExecutablePath(join4(homeDirectory, ".local", "bin", executableName), platform);
@@ -25070,7 +25091,7 @@ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
25070
25091
 
25071
25092
  // src/agent-catalog/agents/deepseek-harness-agent.ts
25072
25093
  import { mkdir as mkdir2, realpath as realpath3, stat as stat3, writeFile } from "node:fs/promises";
25073
- import { isAbsolute as isAbsolute3, join as join6, normalize } from "node:path";
25094
+ import { isAbsolute as isAbsolute4, join as join6, normalize } from "node:path";
25074
25095
 
25075
25096
  // src/agent-installation/deepseek-managed-package.ts
25076
25097
  var DeepSeekHarnessManagedPackage = class extends SriManagedNpmPackageDefinition {
@@ -25105,7 +25126,7 @@ var DEEPSEEK_HARNESS_IMAGE_PROMPT_PATCH = `# Managed by Mobius: pin the ACP brid
25105
25126
  model: deepseek-v4-flash-vision-exp
25106
25127
  `;
25107
25128
  async function prepareAgentHome(path2, imagePrompts) {
25108
- if (!isAbsolute3(path2) || normalize(path2) !== path2) {
25129
+ if (!isAbsolute4(path2) || normalize(path2) !== path2) {
25109
25130
  throw new AgentProbeError("agent_environment_invalid", "The configured Agent home is invalid");
25110
25131
  }
25111
25132
  try {
@@ -25237,7 +25258,7 @@ var GeminiCliAgentSpecification = class extends DirectAcpAgentDefinition {
25237
25258
 
25238
25259
  // src/agent-catalog/agents/grok-build-agent.ts
25239
25260
  import { realpath as realpath4 } from "node:fs/promises";
25240
- import { isAbsolute as isAbsolute4, join as join7, relative as relative2, sep as sep2 } from "node:path";
25261
+ import { isAbsolute as isAbsolute5, join as join7, relative as relative2, sep as sep2 } from "node:path";
25241
25262
  import {
25242
25263
  RequestError
25243
25264
  } from "@agentclientprotocol/sdk";
@@ -25303,7 +25324,7 @@ function grokBuildManagedPackage(platform, architecture) {
25303
25324
  // src/agent-catalog/agents/grok-build-agent.ts
25304
25325
  function isContainedPath2(root, candidate) {
25305
25326
  const difference = relative2(root, candidate);
25306
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute4(difference);
25327
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep2}`) && !isAbsolute5(difference);
25307
25328
  }
25308
25329
  var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
25309
25330
  adapterVersion = GROK_BUILD_MANAGED_VERSION;
@@ -25452,7 +25473,7 @@ import { join as join9 } from "node:path";
25452
25473
  import { createHash } from "node:crypto";
25453
25474
  import { createReadStream } from "node:fs";
25454
25475
  import { chmod, copyFile, mkdir as mkdir3, mkdtemp as mkdtemp2, open as open3, realpath as realpath5, rename as rename2, rm as rm2, stat as stat4, writeFile as writeFile2 } from "node:fs/promises";
25455
- import { delimiter as delimiter2, dirname as dirname2, isAbsolute as isAbsolute5, join as join8, relative as relative3, sep as sep3 } from "node:path";
25476
+ import { delimiter as delimiter2, dirname as dirname2, isAbsolute as isAbsolute6, join as join8, relative as relative3, sep as sep3 } from "node:path";
25456
25477
 
25457
25478
  // src/agent-installation/verified-download.ts
25458
25479
  import { fetch } from "undici";
@@ -25558,7 +25579,7 @@ function isRecord5(value) {
25558
25579
  }
25559
25580
  function isContainedPath3(root, candidate) {
25560
25581
  const difference = relative3(root, candidate);
25561
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute5(difference);
25582
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute6(difference);
25562
25583
  }
25563
25584
  async function hashFile(path2, signal) {
25564
25585
  signal.throwIfAborted();
@@ -25948,7 +25969,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
25948
25969
  };
25949
25970
 
25950
25971
  // src/agent-catalog/agents/workbuddy-agent.ts
25951
- import { isAbsolute as isAbsolute6, join as join11 } from "node:path";
25972
+ import { isAbsolute as isAbsolute7, join as join11 } from "node:path";
25952
25973
 
25953
25974
  // src/agent-installation/workbuddy-managed-package.ts
25954
25975
  var WORKBUDDY_MANAGED_VERSION = "2.146.0";
@@ -26016,7 +26037,7 @@ var WorkBuddyAgentSpecification = class extends DirectAcpAgentDefinition {
26016
26037
  }
26017
26038
  const requestedPaths = [join11("/Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH)];
26018
26039
  const homeDirectory = context.environment["HOME"];
26019
- if (homeDirectory !== void 0 && isAbsolute6(homeDirectory)) {
26040
+ if (homeDirectory !== void 0 && isAbsolute7(homeDirectory)) {
26020
26041
  requestedPaths.unshift(join11(homeDirectory, "Applications", ...WORKBUDDY_MACOS_EXECUTABLE_PATH));
26021
26042
  }
26022
26043
  const executables = [];
@@ -26381,7 +26402,7 @@ function isAgentVersionSupported(reportedVersion, minimumSupportedVersion) {
26381
26402
  }
26382
26403
 
26383
26404
  // src/agent-catalog/executable-discovery.ts
26384
- import { isAbsolute as isAbsolute7, join as join13 } from "node:path";
26405
+ import { isAbsolute as isAbsolute8, join as join13 } from "node:path";
26385
26406
 
26386
26407
  // src/agent-installation/managed-adapter-installer.ts
26387
26408
  import { join as join12 } from "node:path";
@@ -26486,7 +26507,7 @@ async function resolveManagedAdapterExecutable(specification, context) {
26486
26507
  async function resolveSpecificationExecutables(executableName, overrideVariable, resolveInstalled, resolveManaged, context) {
26487
26508
  const override = context.environment[overrideVariable];
26488
26509
  if (override !== void 0) {
26489
- if (override.length === 0 || !isAbsolute7(override)) {
26510
+ if (override.length === 0 || !isAbsolute8(override)) {
26490
26511
  return [];
26491
26512
  }
26492
26513
  const executable = await resolveExecutablePath(override, context.platform);
@@ -26948,7 +26969,7 @@ import {
26948
26969
 
26949
26970
  // src/authorization/local-raster.ts
26950
26971
  import { open as open4, readFile as readFile2, realpath as realpath6, stat as stat5 } from "node:fs/promises";
26951
- import { basename, isAbsolute as isAbsolute8, normalize as normalize2 } from "node:path";
26972
+ import { basename, isAbsolute as isAbsolute9, normalize as normalize2 } from "node:path";
26952
26973
  import { fileURLToPath } from "node:url";
26953
26974
  var MAX_LOCAL_RASTER_BYTES = 128 * 1024 * 1024;
26954
26975
  var MAX_INLINE_RASTER_BYTES = 3e6;
@@ -27014,13 +27035,13 @@ function readInlineRaster(data, name2 = "Image") {
27014
27035
  }
27015
27036
  async function resolveCanonicalPath(requested, signal) {
27016
27037
  signal.throwIfAborted();
27017
- if (!isAbsolute8(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
27038
+ if (!isAbsolute9(requested) || requested.includes("\0") || normalize2(requested) !== requested) {
27018
27039
  return null;
27019
27040
  }
27020
27041
  try {
27021
27042
  const target = await realpath6(requested);
27022
27043
  signal.throwIfAborted();
27023
- if (!isAbsolute8(target) || normalize2(target) !== target) {
27044
+ if (!isAbsolute9(target) || normalize2(target) !== target) {
27024
27045
  return null;
27025
27046
  }
27026
27047
  return target;
@@ -27528,6 +27549,18 @@ function isProgressMessage(content) {
27528
27549
  // src/acp/agent-connection.ts
27529
27550
  import { spawn as spawn4 } from "node:child_process";
27530
27551
  import { ndJsonStream as ndJsonStream2, RequestError as RequestError3 } from "@agentclientprotocol/sdk";
27552
+ function requestErrorMessage(error62) {
27553
+ const fallback = truncate(error62.message, 500);
27554
+ if (error62.message !== "Internal error" || !isRecord4(error62.data)) {
27555
+ return fallback;
27556
+ }
27557
+ const agentError = error62.data["error"];
27558
+ if (!isRecord4(agentError) || agentError["code"] !== "invalid_prompt") {
27559
+ return fallback;
27560
+ }
27561
+ const message = agentError["message"];
27562
+ return typeof message === "string" && message.length > 0 ? truncate(message, 500) : fallback;
27563
+ }
27531
27564
  function readableWebStream(input2) {
27532
27565
  let streamOpen = true;
27533
27566
  return new ReadableStream({
@@ -27699,7 +27732,7 @@ var AgentConnection = class {
27699
27732
  );
27700
27733
  }
27701
27734
  if (error62 instanceof RequestError3) {
27702
- throw new AcpExecutionError(truncate(error62.message, 500), { cause: error62 }, "acp_agent_error");
27735
+ throw new AcpExecutionError(requestErrorMessage(error62), { cause: error62 }, "acp_agent_error");
27703
27736
  }
27704
27737
  throw error62;
27705
27738
  }
@@ -34507,11 +34540,11 @@ var AgentSession = class _AgentSession {
34507
34540
  }
34508
34541
  throw new AcpExecutionError("ACP agent initialization failed");
34509
34542
  }
34510
- static start = async (options, getObserver, store, metrics, contentExternalizer) => await _AgentSession.#start(
34543
+ static start = async (options, recovery, getObserver, store, metrics, contentExternalizer) => await _AgentSession.#start(
34511
34544
  options,
34512
34545
  getObserver,
34513
34546
  store,
34514
- async (runtime) => await runtime.initialize(options.signal, options.origin),
34547
+ async (runtime) => await runtime.initialize(options.signal, recovery, options.origin),
34515
34548
  metrics,
34516
34549
  contentExternalizer
34517
34550
  );
@@ -34549,6 +34582,16 @@ var AgentSession = class _AgentSession {
34549
34582
  const history = await this.#completedHistory(signal, "ACP agent exited while loading history");
34550
34583
  return await embedLocalHistoryImages(await history.snapshot(), signal);
34551
34584
  };
34585
+ ensureHistoryLoaded = async (signal) => {
34586
+ if (!this.#capabilities.loadSession) {
34587
+ throw new AcpExecutionError(
34588
+ "This Agent restores context but does not provide message history.",
34589
+ {},
34590
+ "native_history_unsupported"
34591
+ );
34592
+ }
34593
+ await this.#completedHistory(signal, "ACP agent exited while loading history");
34594
+ };
34552
34595
  loadHistoryEventsV2 = async (eventLimit, cursor, signal) => {
34553
34596
  if (!this.#capabilities.loadSession) {
34554
34597
  throw new AcpExecutionError(
@@ -34721,7 +34764,7 @@ var AgentSession = class _AgentSession {
34721
34764
  128
34722
34765
  );
34723
34766
  }
34724
- initialize = async (signal, origin) => {
34767
+ initialize = async (signal, recovery, origin) => {
34725
34768
  await this.#initializeAgent(signal);
34726
34769
  let stored = this.#metrics.measureSync(
34727
34770
  "session-state-read",
@@ -34790,7 +34833,19 @@ var AgentSession = class _AgentSession {
34790
34833
  this.#prompted = stored.session.prompted;
34791
34834
  this.#sessionTitle = stored.session.title;
34792
34835
  this.#restored = true;
34793
- if (this.#capabilities.resumeSession) {
34836
+ if (recovery.kind === "history-required") {
34837
+ if (!this.#capabilities.loadSession) {
34838
+ throw new AcpExecutionError(
34839
+ "This Agent restores context but does not provide message history.",
34840
+ {},
34841
+ "native_history_unsupported"
34842
+ );
34843
+ }
34844
+ lifecycleResponse = await this.#metrics.measure(
34845
+ "session-load",
34846
+ async () => (await this.#loadSession(signal, "ACP agent exited while loading a session")).response
34847
+ );
34848
+ } else if (this.#capabilities.resumeSession) {
34794
34849
  lifecycleResponse = await this.#metrics.measure(
34795
34850
  "session-resume",
34796
34851
  async () => await this.race(
@@ -35748,8 +35803,15 @@ var embeddedImageSchema = external_exports.looseObject({
35748
35803
  data: external_exports.string(),
35749
35804
  mimeType: external_exports.string()
35750
35805
  });
35806
+ var inlineImageUrlSchema = external_exports.string().regex(/^data:image\/(?:png|jpeg|gif|webp);base64,/u).transform((url2) => ({
35807
+ type: "image",
35808
+ data: url2.slice(url2.indexOf(",") + 1),
35809
+ mimeType: url2.slice(5, url2.indexOf(";"))
35810
+ }));
35751
35811
  var toolImageSchema = external_exports.union([
35752
35812
  embeddedImageSchema,
35813
+ external_exports.object({ type: external_exports.literal("file"), mime: external_exports.string(), url: inlineImageUrlSchema }).refine(({ mime, url: url2 }) => mime === url2.mimeType).transform(({ url: url2 }) => url2),
35814
+ external_exports.object({ type: external_exports.literal("inputImage"), imageUrl: inlineImageUrlSchema }).transform(({ imageUrl }) => imageUrl),
35753
35815
  external_exports.object({
35754
35816
  type: external_exports.literal("image"),
35755
35817
  source: external_exports.object({ type: external_exports.literal("base64"), data: external_exports.string(), media_type: external_exports.string() })
@@ -36401,12 +36463,13 @@ var AgentRuntimeManager = class {
36401
36463
  this.#executionProcesses.retain(options.sessionId, runtime);
36402
36464
  return runtime;
36403
36465
  }
36404
- async #startPreparation(options, metrics = unmeasuredOperationMetrics) {
36466
+ async #startPreparation(options, recovery, metrics = unmeasuredOperationMetrics) {
36405
36467
  return await this.#executionProcesses.prepare(options.sessionId, async () => {
36406
36468
  return await this.#startRetainedSessionProcess(
36407
36469
  options,
36408
36470
  async () => await AgentSession.start(
36409
36471
  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,
36472
+ recovery,
36410
36473
  () => this.#observer,
36411
36474
  this.#store,
36412
36475
  metrics,
@@ -36415,7 +36478,7 @@ var AgentRuntimeManager = class {
36415
36478
  );
36416
36479
  });
36417
36480
  }
36418
- async #replacePreparation(existing, options, metrics) {
36481
+ async #replacePreparation(existing, options, recovery, metrics) {
36419
36482
  return await this.#executionProcesses.prepare(options.sessionId, async () => {
36420
36483
  await this.#retireSessionProcess(
36421
36484
  options.sessionId,
@@ -36427,6 +36490,7 @@ var AgentRuntimeManager = class {
36427
36490
  options,
36428
36491
  async () => await AgentSession.start(
36429
36492
  options,
36493
+ recovery,
36430
36494
  () => this.#observer,
36431
36495
  this.#store,
36432
36496
  metrics,
@@ -36443,6 +36507,7 @@ var AgentRuntimeManager = class {
36443
36507
  options,
36444
36508
  async () => await AgentSession.start(
36445
36509
  options,
36510
+ { kind: "interactive-only" },
36446
36511
  () => this.#observer,
36447
36512
  this.#store,
36448
36513
  unmeasuredOperationMetrics,
@@ -36486,42 +36551,58 @@ var AgentRuntimeManager = class {
36486
36551
  return runtime;
36487
36552
  });
36488
36553
  }
36489
- prepareSession = async (options, metrics = unmeasuredOperationMetrics) => this.#operations.run(options, async (options2) => {
36490
- const stored = metrics.measureSync("session-state-read", () => this.#store.read(options2.sessionId));
36491
- if (stored instanceof FoundAcpStoredSession && this.#nativeOperations.has(`${stored.session.agentId}:${stored.session.nativeSessionId}`)) {
36492
- throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
36493
- }
36494
- const pending = this.#executionProcesses.pending(options2.sessionId);
36495
- if (pending !== void 0) {
36496
- const runtime2 = await metrics.measure(
36497
- "session-preparation-wait",
36498
- async () => await waitForSharedOperation(pending, options2.signal)
36499
- );
36500
- if (runtime2.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
36501
- this.#executionProcesses.touch(options2.sessionId, runtime2);
36502
- return runtime2.prepared();
36503
- }
36504
- return await this.prepareSession(options2, metrics);
36505
- }
36506
- const existing = this.#executionProcesses.get(options2.sessionId);
36507
- if (existing !== void 0) {
36508
- if (existing.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
36509
- this.#executionProcesses.touch(options2.sessionId, existing);
36510
- return existing.prepared();
36554
+ async #prepareSession(options, recovery, metrics = unmeasuredOperationMetrics) {
36555
+ return await this.#operations.run(options, async (options2) => {
36556
+ const stored = metrics.measureSync("session-state-read", () => this.#store.read(options2.sessionId));
36557
+ if (stored instanceof FoundAcpStoredSession && this.#nativeOperations.has(`${stored.session.agentId}:${stored.session.nativeSessionId}`)) {
36558
+ throw new AcpExecutionError("The native session is being managed", {}, "session_busy");
36511
36559
  }
36512
- if (!existing.canRebind()) {
36513
- throw new AcpExecutionError(
36514
- "The agent or workspace cannot change after a conversation has started",
36515
- {},
36516
- "session_identity_mismatch"
36560
+ const pending = this.#executionProcesses.pending(options2.sessionId);
36561
+ if (pending !== void 0) {
36562
+ const runtime2 = await metrics.measure(
36563
+ "session-preparation-wait",
36564
+ async () => await waitForSharedOperation(pending, options2.signal)
36517
36565
  );
36566
+ if (runtime2.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
36567
+ this.#executionProcesses.touch(options2.sessionId, runtime2);
36568
+ if (recovery.kind === "history-required") {
36569
+ await metrics.measure(
36570
+ "session-load",
36571
+ async () => await runtime2.ensureHistoryLoaded(options2.signal)
36572
+ );
36573
+ }
36574
+ return runtime2.prepared();
36575
+ }
36576
+ return await this.#prepareSession(options2, recovery, metrics);
36577
+ }
36578
+ const existing = this.#executionProcesses.get(options2.sessionId);
36579
+ if (existing !== void 0) {
36580
+ if (existing.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
36581
+ this.#executionProcesses.touch(options2.sessionId, existing);
36582
+ if (recovery.kind === "history-required") {
36583
+ await metrics.measure(
36584
+ "session-load",
36585
+ async () => await existing.ensureHistoryLoaded(options2.signal)
36586
+ );
36587
+ }
36588
+ return existing.prepared();
36589
+ }
36590
+ if (!existing.canRebind()) {
36591
+ throw new AcpExecutionError(
36592
+ "The agent or workspace cannot change after a conversation has started",
36593
+ {},
36594
+ "session_identity_mismatch"
36595
+ );
36596
+ }
36597
+ const runtime2 = await this.#replacePreparation(existing, options2, recovery, metrics);
36598
+ return runtime2.prepared();
36518
36599
  }
36519
- const runtime2 = await this.#replacePreparation(existing, options2, metrics);
36520
- return runtime2.prepared();
36521
- }
36522
- const runtime = await this.#startPreparation(options2, metrics);
36523
- return runtime.prepared();
36524
- });
36600
+ const runtime = await this.#startPreparation(options2, recovery, metrics);
36601
+ return runtime.prepared();
36602
+ });
36603
+ }
36604
+ prepareSession = async (options, metrics = unmeasuredOperationMetrics) => await this.#prepareSession(options, { kind: "interactive-only" }, metrics);
36605
+ restoreSession = async (options, metrics = unmeasuredOperationMetrics) => await this.#prepareSession(options, { kind: "history-required" }, metrics);
36525
36606
  /**
36526
36607
  * Opens a short-lived native ACP session only to read the local Agent's
36527
36608
  * authoritative settings. Its identity and store are private to this
@@ -36535,6 +36616,7 @@ var AgentRuntimeManager = class {
36535
36616
  ...options2,
36536
36617
  sessionId: `agent-settings-${crypto.randomUUID()}`
36537
36618
  },
36619
+ { kind: "interactive-only" },
36538
36620
  () => this.#agentSettingsObserver,
36539
36621
  new MemoryAcpSessionStore(),
36540
36622
  unmeasuredOperationMetrics,
@@ -36572,7 +36654,7 @@ var AgentRuntimeManager = class {
36572
36654
  );
36573
36655
  }
36574
36656
  return await this.#executionProcesses.use(options2.sessionId, async () => {
36575
- const runtime = await this.#startPreparation(options2, metrics);
36657
+ const runtime = await this.#startPreparation(options2, { kind: "interactive-only" }, metrics);
36576
36658
  try {
36577
36659
  return runtime.prepared();
36578
36660
  } finally {
@@ -36592,7 +36674,7 @@ var AgentRuntimeManager = class {
36592
36674
  }
36593
36675
  const existing = this.#executionProcesses.get(options2.sessionId);
36594
36676
  if (existing === void 0) {
36595
- return (await this.#startPreparation(options2)).prepared();
36677
+ return (await this.#startPreparation(options2, { kind: "interactive-only" })).prepared();
36596
36678
  }
36597
36679
  if (!existing.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
36598
36680
  throw new AcpExecutionError(
@@ -36777,7 +36859,7 @@ var AgentRuntimeManager = class {
36777
36859
  const temporaryOptions = { ...options2, sessionId: temporarySessionId };
36778
36860
  return await this.#executionProcesses.use(temporarySessionId, async () => {
36779
36861
  try {
36780
- const runtime = await this.#startPreparation(temporaryOptions);
36862
+ const runtime = await this.#startPreparation(temporaryOptions, { kind: "interactive-only" });
36781
36863
  let adopted = false;
36782
36864
  try {
36783
36865
  const nativeSessionId = runtime.nativeSessionId();
@@ -36943,7 +37025,7 @@ var AgentRuntimeManager = class {
36943
37025
  return await this.#executionProcesses.use(options2.sessionId, async () => {
36944
37026
  this.#nativeOperations.add(key);
36945
37027
  try {
36946
- const runtime = await this.#startPreparation({ ...options2, origin });
37028
+ const runtime = await this.#startPreparation({ ...options2, origin }, { kind: "interactive-only" });
36947
37029
  const openedKey = `${options2.agent.id}:${runtime.nativeSessionId()}`;
36948
37030
  this.#nativeOperations.add(openedKey);
36949
37031
  try {
@@ -37556,7 +37638,7 @@ var FixedInstallationExecutor = class {
37556
37638
  // src/authorization/workspace-directory.ts
37557
37639
  import { readdir as readdir3, realpath as realpath8, stat as stat7 } from "node:fs/promises";
37558
37640
  import { homedir as homedir2 } from "node:os";
37559
- import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute9, join as join16, normalize as normalize3, relative as relative4 } from "node:path";
37641
+ import { basename as basename3, dirname as dirname4, isAbsolute as isAbsolute10, join as join16, normalize as normalize3, relative as relative4 } from "node:path";
37560
37642
 
37561
37643
  // src/authorization/local-authorization-error.ts
37562
37644
  var LocalAuthorizationError = class extends Error {
@@ -37623,7 +37705,7 @@ var WorkspaceDirectoryService = class {
37623
37705
  }
37624
37706
  if (id.startsWith("path-")) {
37625
37707
  const path2 = expandCurrentUserHome(decodePath(id, "path-"));
37626
- if (isAbsolute9(path2)) {
37708
+ if (isAbsolute10(path2)) {
37627
37709
  return path2;
37628
37710
  }
37629
37711
  }
@@ -37631,7 +37713,7 @@ var WorkspaceDirectoryService = class {
37631
37713
  };
37632
37714
  resolvePath = async (requested, signal) => {
37633
37715
  signal.throwIfAborted();
37634
- if (!isAbsolute9(requested) || requested.includes("\0") || normalize3(requested) !== requested) {
37716
+ if (!isAbsolute10(requested) || requested.includes("\0") || normalize3(requested) !== requested) {
37635
37717
  throw new LocalAuthorizationError("The local directory path is invalid");
37636
37718
  }
37637
37719
  try {
@@ -37639,7 +37721,7 @@ var WorkspaceDirectoryService = class {
37639
37721
  signal.throwIfAborted();
37640
37722
  const metadata = await stat7(target);
37641
37723
  signal.throwIfAborted();
37642
- if (!isAbsolute9(target) || normalize3(target) !== target || !metadata.isDirectory()) {
37724
+ if (!isAbsolute10(target) || normalize3(target) !== target || !metadata.isDirectory()) {
37643
37725
  throw new LocalAuthorizationError("The selected location is not a directory");
37644
37726
  }
37645
37727
  return target;
@@ -37655,7 +37737,7 @@ var WorkspaceDirectoryService = class {
37655
37737
  };
37656
37738
  label = (path2) => {
37657
37739
  const suffix = relative4(homedir2(), path2);
37658
- return suffix === "" ? "~" : !isAbsolute9(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
37740
+ return suffix === "" ? "~" : !isAbsolute10(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
37659
37741
  };
37660
37742
  identify = async (bindingId, requestedPath2, signal) => {
37661
37743
  this.authorizeMachine(bindingId);
@@ -40733,7 +40815,7 @@ function createAgentSettingsDiscoveryHandler(dependencies) {
40733
40815
  // src/artifacts/local-file-streamer.ts
40734
40816
  import { createReadStream as createReadStream2 } from "node:fs";
40735
40817
  import { realpath as realpath9, stat as stat8 } from "node:fs/promises";
40736
- import { basename as basename4, isAbsolute as isAbsolute10, normalize as normalize4, resolve as resolve5 } from "node:path";
40818
+ import { basename as basename4, isAbsolute as isAbsolute11, normalize as normalize4, resolve as resolve5 } from "node:path";
40737
40819
  import { fileURLToPath as fileURLToPath2 } from "node:url";
40738
40820
  var CHUNK_BYTES = 192 * 1024;
40739
40821
  function requestedPath(value) {
@@ -40752,17 +40834,17 @@ function requestedPath(value) {
40752
40834
  }
40753
40835
  async function resolveFile(value, workingDirectory, signal) {
40754
40836
  const path2 = requestedPath(value);
40755
- if (path2 === null || !isAbsolute10(path2) && workingDirectory === null) {
40837
+ if (path2 === null || !isAbsolute11(path2) && workingDirectory === null) {
40756
40838
  return null;
40757
40839
  }
40758
40840
  const requested = workingDirectory === null ? path2 : resolve5(workingDirectory, path2);
40759
- if (!isAbsolute10(requested) || isAbsolute10(path2) && normalize4(path2) !== path2) {
40841
+ if (!isAbsolute11(requested) || isAbsolute11(path2) && normalize4(path2) !== path2) {
40760
40842
  return null;
40761
40843
  }
40762
40844
  try {
40763
40845
  const target = await realpath9(requested);
40764
40846
  signal.throwIfAborted();
40765
- return isAbsolute10(target) && normalize4(target) === target ? target : null;
40847
+ return isAbsolute11(target) && normalize4(target) === target ? target : null;
40766
40848
  } catch {
40767
40849
  signal.throwIfAborted();
40768
40850
  return null;
@@ -41291,7 +41373,7 @@ async function executePrompt({
41291
41373
  }
41292
41374
 
41293
41375
  // src/daemon-session-commands.ts
41294
- async function prepareSession(command, config2, directories, audit, sessions, metrics, signal) {
41376
+ async function prepareSession(command, recovery, config2, directories, audit, sessions, metrics, signal) {
41295
41377
  return await metrics.measure("prepare-total", async () => {
41296
41378
  const resolved = await metrics.measure(
41297
41379
  "workspace-resolve",
@@ -41311,7 +41393,7 @@ async function prepareSession(command, config2, directories, audit, sessions, me
41311
41393
  sessionId: command.sessionId,
41312
41394
  signal
41313
41395
  };
41314
- const prepared = command.transient === true ? await sessions.inspectSession(preparation, metrics) : await sessions.prepareSession(preparation, metrics);
41396
+ const prepared = command.transient === true ? await sessions.inspectSession(preparation, metrics) : recovery.kind === "history-required" ? await sessions.restoreSession(preparation, metrics) : await sessions.prepareSession(preparation, metrics);
41315
41397
  const configuration = command.configuration;
41316
41398
  const configOptions = configuration === void 0 ? prepared.configOptions : await metrics.measure(
41317
41399
  "configuration",
@@ -41381,7 +41463,16 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
41381
41463
  async function executeSessionPrepare(socket, command, config2, directories, audit, sessions, diagnostics, signal) {
41382
41464
  const metrics = new AccumulatingOperationMetrics();
41383
41465
  try {
41384
- const readyEvent = await prepareSession(command, config2, directories, audit, sessions, metrics, signal);
41466
+ const readyEvent = await prepareSession(
41467
+ command,
41468
+ { kind: "interactive-only" },
41469
+ config2,
41470
+ directories,
41471
+ audit,
41472
+ sessions,
41473
+ metrics,
41474
+ signal
41475
+ );
41385
41476
  send(socket, {
41386
41477
  ...readyEvent,
41387
41478
  runtimeTimings: metrics.snapshot()
@@ -41430,6 +41521,7 @@ async function executeSessionRestore(socket, command, config2, directories, audi
41430
41521
  sessionId: command.sessionId,
41431
41522
  sessionState: "provisioned"
41432
41523
  },
41524
+ { kind: "history-required" },
41433
41525
  config2,
41434
41526
  directories,
41435
41527
  audit,