@moxt-ai/mobius 0.0.354 → 0.0.356

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 (59) hide show
  1. package/dist/cli.js +613 -490
  2. package/dist/cli.js.map +4 -4
  3. package/dist/engine/agent/discovery/agent-discovery-context.d.ts +10 -0
  4. package/dist/engine/agent/discovery/agent-discovery-context.d.ts.map +1 -1
  5. package/dist/engine/agent/discovery/discover-agent.d.ts.map +1 -1
  6. package/dist/engine/agent/discovery/discover-agent.js +27 -6
  7. package/dist/engine/agent/discovery/discover-agent.js.map +1 -1
  8. package/dist/engine/agent/discovery/executable-discovery.d.ts.map +1 -1
  9. package/dist/engine/agent/discovery/executable-discovery.js +8 -1
  10. package/dist/engine/agent/discovery/executable-discovery.js.map +1 -1
  11. package/dist/engine/runtime/catalog/discover-agent-catalog.d.ts +4 -0
  12. package/dist/engine/runtime/catalog/discover-agent-catalog.d.ts.map +1 -0
  13. package/dist/engine/runtime/catalog/discover-agent-catalog.js +54 -0
  14. package/dist/engine/runtime/catalog/discover-agent-catalog.js.map +1 -0
  15. package/dist/engine/runtime/command/registry/interactions.d.ts.map +1 -1
  16. package/dist/engine/runtime/command/registry/interactions.js +7 -1
  17. package/dist/engine/runtime/command/registry/interactions.js.map +1 -1
  18. package/dist/engine/runtime/observability/diagnostic-log.d.ts.map +1 -1
  19. package/dist/engine/runtime/observability/diagnostic-log.js +6 -0
  20. package/dist/engine/runtime/observability/diagnostic-log.js.map +1 -1
  21. package/dist/engine/runtime/pairing.d.ts.map +1 -1
  22. package/dist/engine/runtime/pairing.js +6 -5
  23. package/dist/engine/runtime/pairing.js.map +1 -1
  24. package/dist/engine/runtime/runtime-loop.d.ts.map +1 -1
  25. package/dist/engine/runtime/runtime-loop.js +4 -3
  26. package/dist/engine/runtime/runtime-loop.js.map +1 -1
  27. package/dist/engine/session/live/agent-session-restore.d.ts +1 -1
  28. package/dist/engine/session/live/agent-session-restore.d.ts.map +1 -1
  29. package/dist/engine/session/live/agent-session.d.ts +1 -1
  30. package/dist/engine/session/live/agent-session.d.ts.map +1 -1
  31. package/dist/engine/session/live/agent-session.js +23 -2
  32. package/dist/engine/session/live/agent-session.js.map +1 -1
  33. package/dist/engine/session/live/session-configurations.d.ts +1 -1
  34. package/dist/engine/session/live/session-configurations.d.ts.map +1 -1
  35. package/dist/engine/session/live/session-configurations.js +1 -1
  36. package/dist/engine/session/live/session-configurations.js.map +1 -1
  37. package/dist/engine/session/live/session-restore.d.ts.map +1 -1
  38. package/dist/engine/session/live/session-restore.js +7 -1
  39. package/dist/engine/session/live/session-restore.js.map +1 -1
  40. package/dist/engine/session/native/native-session-browser.d.ts.map +1 -1
  41. package/dist/engine/session/native/native-session-browser.js +1 -0
  42. package/dist/engine/session/native/native-session-browser.js.map +1 -1
  43. package/dist/engine/session/prompt/execute-prompt.d.ts.map +1 -1
  44. package/dist/engine/session/prompt/execute-prompt.js +1 -0
  45. package/dist/engine/session/prompt/execute-prompt.js.map +1 -1
  46. package/dist/engine/session/turn/execution-receipts.d.ts +2 -0
  47. package/dist/engine/session/turn/execution-receipts.d.ts.map +1 -1
  48. package/dist/engine/session/turn/execution-receipts.js +7 -0
  49. package/dist/engine/session/turn/execution-receipts.js.map +1 -1
  50. package/dist/engine/util/process/executable.d.ts.map +1 -1
  51. package/dist/engine/util/process/executable.js +26 -8
  52. package/dist/engine/util/process/executable.js.map +1 -1
  53. package/dist/engine/util/process/process-error.d.ts +6 -1
  54. package/dist/engine/util/process/process-error.d.ts.map +1 -1
  55. package/dist/engine/util/process/process-error.js +2 -0
  56. package/dist/engine/util/process/process-error.js.map +1 -1
  57. package/dist/engine.js +572 -470
  58. package/dist/engine.js.map +4 -4
  59. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -2086,7 +2086,7 @@ var init_package = __esm({
2086
2086
  "package.json"() {
2087
2087
  package_default = {
2088
2088
  name: "@moxt-ai/mobius",
2089
- version: "0.0.354",
2089
+ version: "0.0.356",
2090
2090
  description: "Mobius CLI for pairing and running local AI agent services.",
2091
2091
  type: "module",
2092
2092
  bin: {
@@ -26964,7 +26964,7 @@ function sanitizeConsumableNativeSessionEvents(value) {
26964
26964
  )
26965
26965
  };
26966
26966
  }
26967
- var MAX_EVENT_COUNT, MAX_COLLECTION_SIZE2, MAX_CONTENT_LENGTH2, SESSION_EVENT_KIND, SESSION_EVENT_BATCH_MAX_SIZE, boundedString2, shortString, externalContentKeySchema, annotationsSchema, contentFields, textContentSchema, imageContentSchema, audioContentSchema, externalImageContentSchema, externalAudioContentSchema, externalResourceContentSchema, resourceLinkSchema, textResourceSchema, blobResourceSchema, embeddedResourceSchema, contentBlockSchema, toolCallContentSchema, toolKindSchema, toolStatusSchema, backgroundTaskSchema, toolPatchFields, planEntrySchema, planContentSchema, commandSchema, configSelectOptionSchema, configSelectGroupSchema, configBaseFields, sessionConfigOptionSchema2, contentChunkFields, acpSessionUpdateSchema, lifecycleBase, promptExecutionContextSchema, lifecycleMetadataSchema, sessionEventPayloadSchema, positionSchema, sharedSessionEventFields, sessionLiveEventFields, sessionEventSchema, sessionLiveEventSchema, wireLifecyclePayloadSchema, wireEventFields, sessionWireEventSchema, sessionWireEnvelopeSchema, sessionEventBatchSchema, sessionLiveEventBatchSchema, sessionExportSchema, mobiusSessionExportSchema, sessionEventEnvelopeSchema, sessionEventLogPageSchema, sessionEventOmissionSchema, nativeEventPageRequestSchema, queuedPromptRequestEventLogSchema, nativeSessionEventsSchema, knownSessionLiveEventBatchSchema, decodeSessionEvent, decodeKnownSessionEventPayload, decodeSessionEventEnvelope, encodeSessionEventEnvelope, decodeAcpSessionUpdate, decodeKnownNativeSessionEvents;
26967
+ var MAX_EVENT_COUNT, MAX_COLLECTION_SIZE2, MAX_CONTENT_LENGTH2, SESSION_EVENT_KIND, SESSION_EVENT_BATCH_MAX_SIZE, boundedString2, shortString, externalContentKeySchema, annotationsSchema, contentFields, textContentSchema, imageContentSchema, audioContentSchema, externalImageContentSchema, externalAudioContentSchema, externalResourceContentSchema, resourceLinkSchema, textResourceSchema, blobResourceSchema, embeddedResourceSchema, contentBlockSchema, toolCallContentSchema, toolKindSchema, toolStatusSchema, backgroundTaskSchema, toolPatchFields, planEntrySchema, planContentSchema, commandSchema, configSelectOptionSchema, configSelectGroupSchema, configBaseFields, sessionConfigOptionSchema2, contentChunkFields, acpSessionUpdateSchema, lifecycleBase, promptExecutionContextSchema, lifecycleMetadataSchema, sessionEventPayloadSchema, positionSchema, sharedSessionEventFields, sessionLiveEventFields, sessionEventSchema, sessionLiveEventSchema, wireLifecyclePayloadSchema, wireEventFields, sessionWireEventSchema, sessionWireEnvelopeSchema, sessionEventBatchSchema, sessionLiveEventBatchSchema, sessionEventEnvelopeSchema, sessionEventLogPageSchema, nativeEventPageRequestSchema, queuedPromptRequestEventLogSchema, nativeSessionEventsSchema, knownSessionLiveEventBatchSchema, decodeSessionEvent, decodeKnownSessionEventPayload, decodeSessionEventEnvelope, encodeSessionEventEnvelope, decodeAcpSessionUpdate, decodeKnownNativeSessionEvents;
26968
26968
  var init_events = __esm({
26969
26969
  "../mobius-sdk/src/protocol/session/events/index.ts"() {
26970
26970
  "use strict";
@@ -27308,38 +27308,6 @@ var init_events = __esm({
27308
27308
  }).passthrough().readonly();
27309
27309
  sessionEventBatchSchema = external_exports.array(sessionEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly();
27310
27310
  sessionLiveEventBatchSchema = external_exports.array(sessionLiveEventSchema).min(1).max(SESSION_EVENT_BATCH_MAX_SIZE).readonly();
27311
- sessionExportSchema = external_exports.object({
27312
- binding: external_exports.object({
27313
- bindingId: identifierStringSchema,
27314
- runtimeId: identifierStringSchema
27315
- }).readonly(),
27316
- events: external_exports.array(sessionEventSchema).max(MAX_EVENT_COUNT).readonly(),
27317
- sessionId: identifierStringSchema,
27318
- truncated: external_exports.boolean()
27319
- }).readonly().superRefine((session, context) => {
27320
- const eventIds = /* @__PURE__ */ new Set();
27321
- for (const [index2, event] of session.events.entries()) {
27322
- if (event.sessionId !== session.sessionId) {
27323
- context.addIssue({
27324
- code: "custom",
27325
- message: "Exported event belongs to a different Session",
27326
- path: ["events", index2, "sessionId"]
27327
- });
27328
- }
27329
- if (eventIds.has(event.eventId)) {
27330
- context.addIssue({
27331
- code: "custom",
27332
- message: "Exported event identities are not unique",
27333
- path: ["events", index2, "eventId"]
27334
- });
27335
- }
27336
- eventIds.add(event.eventId);
27337
- }
27338
- });
27339
- mobiusSessionExportSchema = external_exports.object({
27340
- formatVersion: external_exports.literal("2"),
27341
- session: sessionExportSchema
27342
- }).readonly();
27343
27311
  sessionEventEnvelopeSchema = external_exports.object({ events: sessionLiveEventBatchSchema, kind: external_exports.literal(SESSION_EVENT_KIND) }).readonly();
27344
27312
  sessionEventLogPageSchema = external_exports.object({
27345
27313
  events: external_exports.array(sessionEventSchema).max(MAX_EVENT_COUNT).readonly(),
@@ -27352,12 +27320,9 @@ var init_events = __esm({
27352
27320
  truncated: external_exports.boolean(),
27353
27321
  version: external_exports.literal(2)
27354
27322
  }).readonly();
27355
- sessionEventOmissionSchema = external_exports.literal("agent-reasoning");
27356
27323
  nativeEventPageRequestSchema = external_exports.object({
27357
27324
  cursor: external_exports.string().min(1).max(512).nullable(),
27358
- eventLimit: external_exports.number().int().min(1).max(1e4),
27359
- // Legacy callers may still send this option; readers must ignore it.
27360
- omit: external_exports.array(sessionEventOmissionSchema).max(1).readonly().optional()
27325
+ eventLimit: external_exports.number().int().min(1).max(1e4)
27361
27326
  }).readonly();
27362
27327
  queuedPromptRequestEventLogSchema = external_exports.object({
27363
27328
  commandId: identifierStringSchema,
@@ -27998,7 +27963,9 @@ var init_native = __esm({
27998
27963
  // unrecognized delivery from a newer peer reads as absent instead of failing the snapshot.
27999
27964
  command: commandDeliverySchema.optional().catch(void 0),
28000
27965
  // Absent from older Runtimes and while the last started command is still running.
28001
- lastTurn: lastTurnOutcomeSchema.optional().catch(void 0)
27966
+ lastTurn: lastTurnOutcomeSchema.optional().catch(void 0),
27967
+ // Runtime-owned support; older Relays strip this field before exposing the snapshot.
27968
+ queuedCancellation: external_exports.literal("before-start").optional().catch(void 0)
28002
27969
  }).readonly(),
28003
27970
  external_exports.object({
28004
27971
  ...resultEnvelope,
@@ -28066,8 +28033,6 @@ var init_history = __esm({
28066
28033
  pageRequestFields = {
28067
28034
  cursor: external_exports.string().min(1).max(512).nullable(),
28068
28035
  eventLimit: external_exports.number().int().min(1).max(1e4),
28069
- // Decode old clients without rejecting their request; omission has no effect.
28070
- omit: external_exports.array(sessionEventOmissionSchema).max(1).readonly().optional(),
28071
28036
  requestId: identifierStringSchema,
28072
28037
  sessionId: identifierStringSchema
28073
28038
  };
@@ -65844,7 +65809,6 @@ var init_background_task_notifications = __esm({
65844
65809
  });
65845
65810
 
65846
65811
  // src/engine/acp/harness/claude/upstream/dist/context-resources.js
65847
- import { extname } from "node:path";
65848
65812
  function formatUriAsLink(uri) {
65849
65813
  if (uri.startsWith("file://")) {
65850
65814
  const path8 = uri.slice(7);
@@ -65855,91 +65819,6 @@ function formatUriAsLink(uri) {
65855
65819
  }
65856
65820
  return uri;
65857
65821
  }
65858
- function parseContextBlock(block) {
65859
- if (block.type !== "text" || typeof block.text !== "string") {
65860
- return null;
65861
- }
65862
- const match = /^\n<context ref="([^"\r\n]+)">\n([\s\S]*)\n<\/context>$/u.exec(block.text);
65863
- const uri = match?.[1];
65864
- const text2 = match?.[2];
65865
- if (uri === void 0 || text2 === void 0 || formatContextBlock(uri, text2) !== block.text) {
65866
- return null;
65867
- }
65868
- return { uri, text: text2 };
65869
- }
65870
- function contextMimeType(uri) {
65871
- let pathname = uri;
65872
- try {
65873
- pathname = new URL(uri).pathname;
65874
- } catch {
65875
- }
65876
- switch (extname(pathname).toLowerCase()) {
65877
- case ".html":
65878
- case ".htm":
65879
- return "text/html";
65880
- case ".js":
65881
- case ".mjs":
65882
- case ".cjs":
65883
- return "text/javascript";
65884
- case ".css":
65885
- return "text/css";
65886
- case ".json":
65887
- return "application/json";
65888
- case ".md":
65889
- case ".markdown":
65890
- return "text/markdown";
65891
- case ".xml":
65892
- return "application/xml";
65893
- case ".svg":
65894
- return "image/svg+xml";
65895
- case ".csv":
65896
- return "text/csv";
65897
- default:
65898
- return "text/plain";
65899
- }
65900
- }
65901
- function replayContextResources(content) {
65902
- const contexts = [];
65903
- let contextStart = content.length;
65904
- for (let index2 = content.length - 1; index2 >= 0; index2 -= 1) {
65905
- const block = content[index2];
65906
- const parsed = block === void 0 ? null : parseContextBlock(block);
65907
- if (parsed === null) {
65908
- break;
65909
- }
65910
- contexts.push(parsed);
65911
- contextStart = index2;
65912
- }
65913
- if (contexts.length === 0) {
65914
- return null;
65915
- }
65916
- contexts.reverse();
65917
- const links = new Set(contexts.map(({ uri }) => formatUriAsLink(uri)));
65918
- const resources = /* @__PURE__ */ new Map();
65919
- let nextContext = 0;
65920
- for (let index2 = 0; index2 < contextStart; index2 += 1) {
65921
- const block = content[index2];
65922
- if (block?.type !== "text" || typeof block.text !== "string") {
65923
- continue;
65924
- }
65925
- if (block.text.startsWith('\n<context ref="')) {
65926
- return null;
65927
- }
65928
- if (!links.has(block.text)) {
65929
- continue;
65930
- }
65931
- const context = contexts[nextContext];
65932
- if (context === void 0 || block.text !== formatUriAsLink(context.uri)) {
65933
- return null;
65934
- }
65935
- resources.set(index2, {
65936
- type: "resource",
65937
- resource: { ...context, mimeType: contextMimeType(context.uri) }
65938
- });
65939
- nextContext += 1;
65940
- }
65941
- return nextContext === contexts.length ? { contextStart, resources } : null;
65942
- }
65943
65822
  var formatContextBlock;
65944
65823
  var init_context_resources = __esm({
65945
65824
  "src/engine/acp/harness/claude/upstream/dist/context-resources.js"() {
@@ -70302,13 +70181,8 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, client2, log
70302
70181
  const toolUseResult = options?.toolUseResult !== void 0 && content.filter((c) => typeof c === "object" && c !== null && c.type === "tool_result").length === 1 ? options.toolUseResult : void 0;
70303
70182
  const toolResultMeta = parseToolResultMeta(options?.toolResultMeta);
70304
70183
  const output2 = [];
70305
- const replayedResources = role === "user" && options.historical === true ? replayContextResources(content) : null;
70306
- for (const [index2, chunk] of content.entries()) {
70307
- if (replayedResources !== null && index2 >= replayedResources.contextStart) {
70308
- break;
70309
- }
70184
+ for (const chunk of content) {
70310
70185
  let update = null;
70311
- const resource = replayedResources?.resources.get(index2);
70312
70186
  switch (chunk.type) {
70313
70187
  case "text":
70314
70188
  case "text_delta": {
@@ -70317,7 +70191,7 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, client2, log
70317
70191
  update = {
70318
70192
  sessionUpdate: role === "assistant" ? "agent_message_chunk" : "user_message_chunk",
70319
70193
  messageId,
70320
- content: resource ?? {
70194
+ content: {
70321
70195
  type: "text",
70322
70196
  text: chunk.text
70323
70197
  }
@@ -74294,9 +74168,11 @@ var init_process_error = __esm({
74294
74168
  "use strict";
74295
74169
  ProcessExecutionError = class extends Error {
74296
74170
  code;
74171
+ diagnosticDetails;
74297
74172
  constructor(code, message, options = {}) {
74298
74173
  super(message, options);
74299
74174
  this.code = code;
74175
+ this.diagnosticDetails = options.diagnosticDetails ?? {};
74300
74176
  this.name = "ProcessExecutionError";
74301
74177
  }
74302
74178
  };
@@ -74306,7 +74182,7 @@ var init_process_error = __esm({
74306
74182
  // src/engine/util/process/platform/windows.ts
74307
74183
  import { execFile as execFile4 } from "node:child_process";
74308
74184
  import { readFile as readFile6, realpath as realpath6 } from "node:fs/promises";
74309
- import { dirname as dirname7, extname as extname2, join as join16, resolve as resolve9 } from "node:path";
74185
+ import { dirname as dirname7, extname, join as join16, resolve as resolve9 } from "node:path";
74310
74186
  function environmentValue2(environment, name2) {
74311
74187
  return Object.entries(environment).find(([key]) => key.toUpperCase() === name2.toUpperCase())?.[1];
74312
74188
  }
@@ -74321,14 +74197,14 @@ function executableExtensions(executableName, environment) {
74321
74197
  async function resolveExecutableTarget(path8) {
74322
74198
  let resolvedPath;
74323
74199
  try {
74324
- resolvedPath = await realpath6(extname2(path8) === "" ? `${path8}.cmd` : path8);
74200
+ resolvedPath = await realpath6(extname(path8) === "" ? `${path8}.cmd` : path8);
74325
74201
  } catch (cause) {
74326
- if (extname2(path8) !== "" || !(cause instanceof Error) || !("code" in cause) || cause.code !== "ENOENT") {
74202
+ if (extname(path8) !== "" || !(cause instanceof Error) || !("code" in cause) || cause.code !== "ENOENT") {
74327
74203
  throw cause;
74328
74204
  }
74329
74205
  resolvedPath = await realpath6(path8);
74330
74206
  }
74331
- if (extname2(resolvedPath).toLowerCase() === ".cmd") {
74207
+ if (extname(resolvedPath).toLowerCase() === ".cmd") {
74332
74208
  const shim = await readFile6(resolvedPath, "utf8");
74333
74209
  if (shim.includes('SET "NPM_CLI_JS=%~dp0\\node_modules\\npm\\bin\\npm-cli.js"') && shim.includes('"%NODE_EXE%" "%NPM_CLI_JS%" %*')) {
74334
74210
  return await realpath6(resolve9(dirname7(resolvedPath), "node_modules/npm/bin/npm-cli.js"));
@@ -74693,11 +74569,16 @@ async function runBoundedProcess(options) {
74693
74569
  abort();
74694
74570
  }
74695
74571
  try {
74696
- const exit = new Promise((resolveExit, rejectExit) => {
74697
- child.once("error", rejectExit);
74698
- child.once("exit", (code) => resolveExit(code ?? 1));
74572
+ const completion = new Promise((resolveCompletion, rejectCompletion) => {
74573
+ child.once("error", rejectCompletion);
74574
+ child.once("exit", (code) => {
74575
+ if (code !== 0) {
74576
+ resolveCompletion(code ?? 1);
74577
+ }
74578
+ });
74579
+ child.once("close", (code) => resolveCompletion(code ?? 1));
74699
74580
  });
74700
- const exitCode = await Promise.race([exit, interrupted.promise.then(() => -1)]);
74581
+ const exitCode = await Promise.race([completion, interrupted.promise.then(() => -1)]);
74701
74582
  if (interruptionCleanupFailure !== null) {
74702
74583
  throw interruptionCleanupFailure;
74703
74584
  }
@@ -74709,12 +74590,19 @@ async function runBoundedProcess(options) {
74709
74590
  }
74710
74591
  return new ProcessResult(Buffer.concat(stdout).toString("utf8"), Buffer.concat(stderr).toString("utf8"));
74711
74592
  } catch (error62) {
74712
- if (error62 instanceof ProcessExecutionError) {
74713
- throw error62;
74714
- }
74715
- throw new ProcessExecutionError("process_spawn_failed", "The executable could not be started", {
74593
+ const failure2 = error62 instanceof ProcessExecutionError ? error62 : new ProcessExecutionError("process_spawn_failed", "The executable could not be started", {
74716
74594
  cause: error62
74717
74595
  });
74596
+ throw new ProcessExecutionError(failure2.code, failure2.message, {
74597
+ cause: error62,
74598
+ diagnosticDetails: {
74599
+ stdoutBytes: stdoutBytes.toString(),
74600
+ stderrBytes: stderrBytes.toString(),
74601
+ outputLimitBytes: outputLimitBytes.toString(),
74602
+ ...child.exitCode === null ? {} : { exitCode: child.exitCode.toString() },
74603
+ ...child.signalCode === null ? {} : { signal: child.signalCode }
74604
+ }
74605
+ });
74718
74606
  } finally {
74719
74607
  clearTimeout(timeout);
74720
74608
  options.signal.removeEventListener("abort", abort);
@@ -78463,8 +78351,69 @@ var init_pi_commands = __esm({
78463
78351
  }
78464
78352
  });
78465
78353
 
78354
+ // src/engine/acp/harness/pi/upstream/dist/acp/pi-history.js
78355
+ import { readFileSync as readFileSync3 } from "node:fs";
78356
+ import { RequestError as RequestError8 } from "@agentclientprotocol/sdk";
78357
+ function readPiHistory(sessionFile) {
78358
+ try {
78359
+ const entries = /* @__PURE__ */ new Map();
78360
+ let leaf = null;
78361
+ for (const line of readFileSync3(sessionFile, "utf8").split(/\r?\n/u)) {
78362
+ if (!line.trim()) {
78363
+ continue;
78364
+ }
78365
+ const value = JSON.parse(line);
78366
+ if (external_exports.object({ type: external_exports.literal("session") }).safeParse(value).success) {
78367
+ continue;
78368
+ }
78369
+ const entry = entrySchema.parse(value);
78370
+ entries.set(entry.id, entry);
78371
+ leaf = entry.id;
78372
+ }
78373
+ const history = [];
78374
+ const visited = /* @__PURE__ */ new Set();
78375
+ while (leaf !== null) {
78376
+ const entry = entries.get(leaf);
78377
+ if (entry === void 0 || visited.has(leaf)) {
78378
+ throw new Error("Invalid Pi history branch");
78379
+ }
78380
+ visited.add(leaf);
78381
+ if (entry.type === "message") {
78382
+ const { role } = external_exports.object({ role: external_exports.string() }).parse(entry.message);
78383
+ if (role === "user" || role === "assistant" || role === "toolResult") {
78384
+ history.push({ type: "message", message: messageSchema.parse(entry.message) });
78385
+ }
78386
+ } else if (entry.type === "compaction") {
78387
+ history.push({ type: "compaction", id: entry.id, summary: external_exports.string().parse(entry.summary) });
78388
+ }
78389
+ leaf = entry.parentId;
78390
+ }
78391
+ return history.reverse();
78392
+ } catch (cause) {
78393
+ const error62 = RequestError8.internalError({ code: "PI_HISTORY_READ_FAILED" }, "Unable to read Pi history");
78394
+ error62.cause = cause;
78395
+ throw error62;
78396
+ }
78397
+ }
78398
+ var entrySchema, messageSchema;
78399
+ var init_pi_history = __esm({
78400
+ "src/engine/acp/harness/pi/upstream/dist/acp/pi-history.js"() {
78401
+ "use strict";
78402
+ init_zod();
78403
+ entrySchema = external_exports.object({
78404
+ type: external_exports.string(),
78405
+ id: external_exports.string(),
78406
+ parentId: external_exports.string().nullable()
78407
+ }).passthrough();
78408
+ messageSchema = external_exports.object({
78409
+ role: external_exports.enum(["user", "assistant", "toolResult"]),
78410
+ content: external_exports.unknown()
78411
+ }).passthrough();
78412
+ }
78413
+ });
78414
+
78466
78415
  // src/engine/acp/harness/pi/upstream/dist/acp/pi-sessions.js
78467
- import { closeSync as closeSync2, existsSync as existsSync4, openSync as openSync2, readdirSync as readdirSync4, readFileSync as readFileSync3, readSync as readSync2, statSync as statSync2 } from "node:fs";
78416
+ import { closeSync as closeSync2, existsSync as existsSync4, openSync as openSync2, readdirSync as readdirSync4, readFileSync as readFileSync4, readSync as readSync2, statSync as statSync2 } from "node:fs";
78468
78417
  import { isAbsolute as isAbsolute10, join as join19, resolve as resolve11 } from "node:path";
78469
78418
  function getPiAgentDir(environment) {
78470
78419
  const configured = environment["PI_CODING_AGENT_DIR"];
@@ -78476,7 +78425,7 @@ function readSessionDirFromSettings(agentDir) {
78476
78425
  if (!existsSync4(settingsPath)) {
78477
78426
  return null;
78478
78427
  }
78479
- const raw = readFileSync3(settingsPath, "utf8");
78428
+ const raw = readFileSync4(settingsPath, "utf8");
78480
78429
  const data = JSON.parse(raw);
78481
78430
  if (!data || typeof data !== "object" || Array.isArray(data)) {
78482
78431
  return null;
@@ -78692,7 +78641,7 @@ function pickUpdatedAtFromTail(tail) {
78692
78641
  }
78693
78642
  function pickFallbackTitleFromHead(path8) {
78694
78643
  try {
78695
- const raw = readFileSync3(path8, { encoding: "utf8" });
78644
+ const raw = readFileSync4(path8, { encoding: "utf8" });
78696
78645
  const lines = raw.split(/\r?\n/);
78697
78646
  for (const line0 of lines) {
78698
78647
  const line = line0.trim();
@@ -78797,7 +78746,7 @@ var init_pi_sessions = __esm({
78797
78746
  });
78798
78747
 
78799
78748
  // src/engine/acp/harness/pi/upstream/dist/acp/pi-settings.js
78800
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
78749
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "node:fs";
78801
78750
  import { join as join20, resolve as resolve12 } from "node:path";
78802
78751
  function isObject2(x) {
78803
78752
  return Boolean(x) && typeof x === "object" && !Array.isArray(x);
@@ -78819,7 +78768,7 @@ function readJsonFile2(path8) {
78819
78768
  if (!existsSync5(path8)) {
78820
78769
  return {};
78821
78770
  }
78822
- const raw = readFileSync4(path8, "utf-8");
78771
+ const raw = readFileSync5(path8, "utf-8");
78823
78772
  const data = JSON.parse(raw);
78824
78773
  return isObject2(data) ? data : {};
78825
78774
  } catch {
@@ -78869,7 +78818,7 @@ var init_pi_settings = __esm({
78869
78818
  });
78870
78819
 
78871
78820
  // src/engine/acp/harness/pi/upstream/dist/acp/extension-questions.js
78872
- import { RequestError as RequestError8 } from "@agentclientprotocol/sdk";
78821
+ import { RequestError as RequestError9 } from "@agentclientprotocol/sdk";
78873
78822
  function questionField(question) {
78874
78823
  const title2 = question.title || "Answer";
78875
78824
  switch (question.method) {
@@ -78917,7 +78866,7 @@ var init_extension_questions = __esm({
78917
78866
  external_exports.object({ ...questionBase, method: external_exports.literal("editor"), prefill: external_exports.string().max(1e4).optional() })
78918
78867
  ]).readonly();
78919
78868
  QUESTION_TIMEOUT_MS = 36e5;
78920
- PiQuestionError = class extends RequestError8 {
78869
+ PiQuestionError = class extends RequestError9 {
78921
78870
  constructor(kind, cause) {
78922
78871
  const messages = {
78923
78872
  request_failed: "Pi could not request an answer.",
@@ -79029,7 +78978,7 @@ var init_extension_questions = __esm({
79029
78978
  throw new PiQuestionError("invalid_response");
79030
78979
  }
79031
78980
  } catch (cause) {
79032
- if (!signal.aborted && !(cause instanceof RequestError8 && cause.code === -32800)) {
78981
+ if (!signal.aborted && !(cause instanceof RequestError9 && cause.code === -32800)) {
79033
78982
  turn.controller.abort(cause instanceof PiQuestionError ? cause : new PiQuestionError("request_failed", cause));
79034
78983
  }
79035
78984
  } finally {
@@ -79045,14 +78994,14 @@ var init_extension_questions = __esm({
79045
78994
  });
79046
78995
 
79047
78996
  // src/engine/acp/harness/pi/upstream/dist/acp/session-store.js
79048
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync } from "node:fs";
78997
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync } from "node:fs";
79049
78998
  import { dirname as dirname8 } from "node:path";
79050
78999
  function ensureParentDir(path8) {
79051
79000
  mkdirSync2(dirname8(path8), { recursive: true });
79052
79001
  }
79053
79002
  function loadFile(path8) {
79054
79003
  try {
79055
- const raw = readFileSync5(path8, "utf-8");
79004
+ const raw = readFileSync6(path8, "utf-8");
79056
79005
  const parsed = JSON.parse(raw);
79057
79006
  if (parsed?.version !== 1 || typeof parsed.sessions !== "object" || !parsed.sessions) {
79058
79007
  return { version: 1, sessions: {} };
@@ -79104,7 +79053,7 @@ var init_session_store = __esm({
79104
79053
  });
79105
79054
 
79106
79055
  // src/engine/acp/harness/pi/upstream/dist/acp/slash-commands.js
79107
- import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync6 } from "node:fs";
79056
+ import { existsSync as existsSync6, readdirSync as readdirSync5, readFileSync as readFileSync7 } from "node:fs";
79108
79057
  import { join as join21, resolve as resolve13 } from "node:path";
79109
79058
  function parseFrontmatter(content) {
79110
79059
  const frontmatter = {};
@@ -79143,7 +79092,7 @@ function loadCommandsFromDir(dir, source, subdir = "") {
79143
79092
  continue;
79144
79093
  }
79145
79094
  try {
79146
- const rawContent = readFileSync6(fullPath, "utf-8");
79095
+ const rawContent = readFileSync7(fullPath, "utf-8");
79147
79096
  const { frontmatter, content } = parseFrontmatter(rawContent);
79148
79097
  const name2 = entry.name.slice(0, -3);
79149
79098
  const sourceStr = source === "user" ? subdir ? `(user:${subdir})` : "(user)" : subdir ? `(project:${subdir})` : "(project)";
@@ -79335,9 +79284,9 @@ var init_pi_tools = __esm({
79335
79284
 
79336
79285
  // src/engine/acp/harness/pi/upstream/dist/acp/session.js
79337
79286
  import { randomUUID as randomUUID10 } from "node:crypto";
79338
- import { readFileSync as readFileSync7 } from "node:fs";
79287
+ import { readFileSync as readFileSync8 } from "node:fs";
79339
79288
  import { isAbsolute as isAbsolute11, resolve as resolvePath } from "node:path";
79340
- import { RequestError as RequestError9 } from "@agentclientprotocol/sdk";
79289
+ import { RequestError as RequestError10 } from "@agentclientprotocol/sdk";
79341
79290
  function toUsageUpdate(stats) {
79342
79291
  const used = stats?.contextUsage?.tokens;
79343
79292
  const size = stats?.contextUsage?.contextWindow;
@@ -79452,10 +79401,11 @@ function toToolKind(toolName) {
79452
79401
  return "other";
79453
79402
  }
79454
79403
  }
79455
- var SessionManager, PiAcpSession;
79404
+ var nativeUserMessageSchema, SessionManager, PiAcpSession;
79456
79405
  var init_session = __esm({
79457
79406
  "src/engine/acp/harness/pi/upstream/dist/acp/session.js"() {
79458
79407
  "use strict";
79408
+ init_zod();
79459
79409
  init_process();
79460
79410
  init_auth_required();
79461
79411
  init_extension_questions();
@@ -79463,6 +79413,16 @@ var init_session = __esm({
79463
79413
  init_slash_commands();
79464
79414
  init_bash();
79465
79415
  init_pi_tools();
79416
+ nativeUserMessageSchema = external_exports.object({
79417
+ role: external_exports.literal("user"),
79418
+ content: external_exports.union([
79419
+ external_exports.string().transform((text2) => [{ type: "text", text: text2 }]),
79420
+ external_exports.array(external_exports.discriminatedUnion("type", [
79421
+ external_exports.object({ type: external_exports.literal("text"), text: external_exports.string() }),
79422
+ external_exports.object({ type: external_exports.literal("image"), data: external_exports.string(), mimeType: external_exports.string() })
79423
+ ]))
79424
+ ])
79425
+ });
79466
79426
  SessionManager = class {
79467
79427
  sessions = /* @__PURE__ */ new Map();
79468
79428
  store = new SessionStore();
@@ -79511,7 +79471,7 @@ var init_session = __esm({
79511
79471
  });
79512
79472
  } catch (e) {
79513
79473
  if (e instanceof PiRpcSpawnError) {
79514
- throw RequestError9.internalError({ code: e.code }, e.message);
79474
+ throw RequestError10.internalError({ code: e.code }, e.message);
79515
79475
  }
79516
79476
  throw e;
79517
79477
  }
@@ -79540,7 +79500,7 @@ var init_session = __esm({
79540
79500
  get(sessionId) {
79541
79501
  const s = this.sessions.get(sessionId);
79542
79502
  if (!s) {
79543
- throw RequestError9.invalidParams(`Unknown sessionId: ${sessionId}`);
79503
+ throw RequestError10.invalidParams(`Unknown sessionId: ${sessionId}`);
79544
79504
  }
79545
79505
  return s;
79546
79506
  }
@@ -79640,8 +79600,8 @@ var init_session = __esm({
79640
79600
  if (cause instanceof PiRpcProcessError) {
79641
79601
  const pending = this.pendingTurn;
79642
79602
  const reason = pending?.questionSignal.reason;
79643
- const error62 = reason instanceof RequestError9 ? reason : RequestError9.internalError({ code: cause.code, details: cause.message });
79644
- if (!(reason instanceof RequestError9)) {
79603
+ const error62 = reason instanceof RequestError10 ? reason : RequestError10.internalError({ code: cause.code, details: cause.message });
79604
+ if (!(reason instanceof RequestError10)) {
79645
79605
  error62.cause = cause;
79646
79606
  }
79647
79607
  this.extensionQuestions.endTurn(error62);
@@ -79709,12 +79669,12 @@ var init_session = __esm({
79709
79669
  const signal = this.extensionQuestions.startTurn();
79710
79670
  try {
79711
79671
  const result = await this.proc.compact(customInstructions, { signal, timeoutMs });
79712
- if (signal.aborted && signal.reason instanceof RequestError9) {
79672
+ if (signal.aborted && signal.reason instanceof RequestError10) {
79713
79673
  throw signal.reason;
79714
79674
  }
79715
79675
  return result;
79716
79676
  } catch (cause) {
79717
- if (signal.aborted && signal.reason instanceof RequestError9) {
79677
+ if (signal.aborted && signal.reason instanceof RequestError10) {
79718
79678
  try {
79719
79679
  await this.proc.abort({ signal: this.proc.signal, timeoutMs });
79720
79680
  } catch (abortCause) {
@@ -79807,14 +79767,14 @@ var init_session = __esm({
79807
79767
  await this.publishContextUsage();
79808
79768
  const retryFailure = this.turnRetryFailure;
79809
79769
  this.turnRetryFailure = null;
79810
- if (questionSignal?.aborted && questionSignal.reason instanceof RequestError9 && !this.cancelRequested) {
79770
+ if (questionSignal?.aborted && questionSignal.reason instanceof RequestError10 && !this.cancelRequested) {
79811
79771
  this.pendingTurn?.reject(questionSignal.reason);
79812
79772
  } else if (retryFailure !== null && !this.cancelRequested) {
79813
79773
  this.pendingTurn?.reject(
79814
79774
  // The message rides in `data.details` so clients that unwrap the
79815
79775
  // JSON-RPC internal-error envelope (like Mobius) surface the real
79816
79776
  // model error; `code` keeps the failure machine-readable.
79817
- RequestError9.internalError({
79777
+ RequestError10.internalError({
79818
79778
  code: "pi_retries_exhausted",
79819
79779
  details: `Pi retries exhausted: ${retryFailure}`
79820
79780
  })
@@ -79898,6 +79858,17 @@ var init_session = __esm({
79898
79858
  handlePiEvent(ev2) {
79899
79859
  const type = String(ev2.type ?? "");
79900
79860
  switch (type) {
79861
+ case "message_start": {
79862
+ const message = nativeUserMessageSchema.safeParse(ev2.message);
79863
+ if (!message.success) {
79864
+ break;
79865
+ }
79866
+ this.lastEmit = this.lastEmit.then(() => this.conn.startUserMessage());
79867
+ for (const content of message.data.content) {
79868
+ this.emit({ sessionUpdate: "user_message_chunk", content });
79869
+ }
79870
+ break;
79871
+ }
79901
79872
  case "message_update": {
79902
79873
  const ame2 = ev2.assistantMessageEvent;
79903
79874
  if (this.turnRetryFailure !== null && (ame2?.type === "text_delta" || ame2?.type === "thinking_delta" || ame2?.type === "toolcall_start")) {
@@ -80004,7 +79975,7 @@ var init_session = __esm({
80004
79975
  if (p) {
80005
79976
  try {
80006
79977
  const abs = isAbsolute11(p) ? p : resolvePath(this.cwd, p);
80007
- snapshotOldText = readFileSync7(abs, "utf8");
79978
+ snapshotOldText = readFileSync8(abs, "utf8");
80008
79979
  this.fileSnapshots.set(toolCallId, { path: p, oldText: snapshotOldText });
80009
79980
  if (toolName === "edit") {
80010
79981
  for (const needle of getEditOldTexts(args)) {
@@ -80087,7 +80058,7 @@ var init_session = __esm({
80087
80058
  if (!isError && snapshot) {
80088
80059
  try {
80089
80060
  const abs = isAbsolute11(snapshot.path) ? snapshot.path : resolvePath(this.cwd, snapshot.path);
80090
- const newText = readFileSync7(abs, "utf8");
80061
+ const newText = readFileSync8(abs, "utf8");
80091
80062
  if (snapshot.oldText === null || newText !== snapshot.oldText) {
80092
80063
  hasStructuredDiff = true;
80093
80064
  content = [
@@ -80264,9 +80235,9 @@ var init_prompt = __esm({
80264
80235
  // src/engine/acp/harness/pi/upstream/dist/acp/agent.js
80265
80236
  import { spawnSync } from "node:child_process";
80266
80237
  import { randomUUID as randomUUID11 } from "node:crypto";
80267
- import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync8, realpathSync as realpathSync3, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
80238
+ import { existsSync as existsSync7, readdirSync as readdirSync6, readFileSync as readFileSync9, realpathSync as realpathSync3, statSync as statSync3, unlinkSync as unlinkSync2 } from "node:fs";
80268
80239
  import { basename as basename6, dirname as dirname9, isAbsolute as isAbsolute12, join as join22 } from "node:path";
80269
- import { RequestError as RequestError10 } from "@agentclientprotocol/sdk";
80240
+ import { RequestError as RequestError11 } from "@agentclientprotocol/sdk";
80270
80241
  function thinkingLevelName(id) {
80271
80242
  return id.split(/[_-]/u).map((part) => part.length === 0 ? part : `${part[0]?.toUpperCase() ?? ""}${part.slice(1)}`).join(" ");
80272
80243
  }
@@ -80470,7 +80441,7 @@ async function setSessionModel(proc, requestedModelId) {
80470
80441
  }
80471
80442
  }
80472
80443
  if (!provider || !modelId) {
80473
- throw RequestError10.invalidParams(`Unknown modelId: ${requestedModelId}`);
80444
+ throw RequestError11.invalidParams(`Unknown modelId: ${requestedModelId}`);
80474
80445
  }
80475
80446
  await proc.setModel(provider, modelId);
80476
80447
  }
@@ -80624,7 +80595,7 @@ function buildStartupInfo(opts) {
80624
80595
  ];
80625
80596
  for (const settingsPath of settingsPaths) {
80626
80597
  try {
80627
- const settings = JSON.parse(readFileSync8(settingsPath, "utf-8"));
80598
+ const settings = JSON.parse(readFileSync9(settingsPath, "utf-8"));
80628
80599
  const pkgs = Array.isArray(settings?.packages) ? settings.packages : [];
80629
80600
  for (const pkg of pkgs) {
80630
80601
  const s = String(pkg);
@@ -80657,6 +80628,7 @@ var init_agent2 = __esm({
80657
80628
  init_auth_required();
80658
80629
  init_paths();
80659
80630
  init_pi_commands();
80631
+ init_pi_history();
80660
80632
  init_pi_sessions();
80661
80633
  init_pi_settings();
80662
80634
  init_session();
@@ -80752,7 +80724,7 @@ var init_agent2 = __esm({
80752
80724
  const restorePromise = (async () => {
80753
80725
  const stored = this.findStoredSession(sessionId);
80754
80726
  if (!stored) {
80755
- throw RequestError10.invalidParams(`Unknown sessionId: ${sessionId}`);
80727
+ throw RequestError11.invalidParams(`Unknown sessionId: ${sessionId}`);
80756
80728
  }
80757
80729
  const cwd = opts?.cwd ?? stored.cwd;
80758
80730
  let proc;
@@ -80765,7 +80737,7 @@ var init_agent2 = __esm({
80765
80737
  });
80766
80738
  } catch (e) {
80767
80739
  if (e?.name === "PiRpcSpawnError") {
80768
- throw RequestError10.internalError({ code: e?.code }, String(e?.message ?? e));
80740
+ throw RequestError11.internalError({ code: e?.code }, String(e?.message ?? e));
80769
80741
  }
80770
80742
  throw e;
80771
80743
  }
@@ -80825,7 +80797,7 @@ var init_agent2 = __esm({
80825
80797
  }
80826
80798
  async newSession(params) {
80827
80799
  if (!isAbsolute12(params.cwd)) {
80828
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
80800
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
80829
80801
  }
80830
80802
  this.lastSessionCwd = params.cwd;
80831
80803
  const fileCommands = loadSlashCommands(params.cwd, this.environment);
@@ -80864,16 +80836,16 @@ var init_agent2 = __esm({
80864
80836
  }
80865
80837
  if (availableModelsErr) {
80866
80838
  this.cleanupFailedNewSession(session.sessionId, state);
80867
- throw RequestError10.internalError({}, String(availableModelsErr?.message ?? availableModelsErr));
80839
+ throw RequestError11.internalError({}, String(availableModelsErr?.message ?? availableModelsErr));
80868
80840
  }
80869
80841
  const rawModelsCount = Array.isArray(availableModels?.models) ? availableModels.models.length : 0;
80870
80842
  if (rawModelsCount === 0) {
80871
80843
  this.cleanupFailedNewSession(session.sessionId, state);
80872
- throw RequestError10.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
80844
+ throw RequestError11.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
80873
80845
  }
80874
80846
  if (stateErr && maybeAuthRequiredError(stateErr)) {
80875
80847
  this.cleanupFailedNewSession(session.sessionId, state);
80876
- throw RequestError10.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
80848
+ throw RequestError11.authRequired({ authMethods: getAuthMethods() }, "Configure an API key or log in with an OAuth provider.");
80877
80849
  }
80878
80850
  let configuration;
80879
80851
  try {
@@ -80883,7 +80855,7 @@ var init_agent2 = __esm({
80883
80855
  configuration = await getSessionConfiguration(session.proc, { state, availableModels });
80884
80856
  } catch (err) {
80885
80857
  this.cleanupFailedNewSession(session.sessionId, state);
80886
- throw maybeAuthRequiredError(err) ?? RequestError10.internalError({}, String(err?.message ?? err));
80858
+ throw maybeAuthRequiredError(err) ?? RequestError11.internalError({}, String(err?.message ?? err));
80887
80859
  }
80888
80860
  const { configOptions, models, modes } = configuration;
80889
80861
  const quietStartup = getQuietStartup(params.cwd, this.environment);
@@ -80963,16 +80935,6 @@ var init_agent2 = __esm({
80963
80935
  }
80964
80936
  async promptSubmission(params, submission) {
80965
80937
  const session = await this.restoreSession(params.sessionId);
80966
- this.conn.startUserMessage();
80967
- for (const content of params.prompt) {
80968
- if (submission.aborted) {
80969
- return { stopReason: "cancelled" };
80970
- }
80971
- await this.conn.sessionUpdate({
80972
- sessionId: params.sessionId,
80973
- update: { sessionUpdate: "user_message_chunk", content }
80974
- });
80975
- }
80976
80938
  if (submission.aborted) {
80977
80939
  return { stopReason: "cancelled" };
80978
80940
  }
@@ -80983,6 +80945,9 @@ var init_agent2 = __esm({
80983
80945
  const cmd = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space);
80984
80946
  const argsString = space === -1 ? "" : trimmed.slice(space + 1);
80985
80947
  const args = parseCommandArgs(argsString);
80948
+ if (builtinAvailableCommands().some((command) => command.name === cmd)) {
80949
+ this.conn.startUserMessage();
80950
+ }
80986
80951
  if (cmd === "compact") {
80987
80952
  const customInstructions = args.join(" ").trim() || void 0;
80988
80953
  const compactionId = randomUUID11();
@@ -81244,7 +81209,7 @@ ${JSON.stringify(stats, null, 2)}`;
81244
81209
  }
81245
81210
  let text2 = "";
81246
81211
  try {
81247
- text2 = readFileSync8(changelogPath, "utf-8");
81212
+ text2 = readFileSync9(changelogPath, "utf-8");
81248
81213
  } catch (e) {
81249
81214
  await this.conn.sessionUpdate({
81250
81215
  sessionId: session.sessionId,
@@ -81288,7 +81253,7 @@ ${JSON.stringify(stats, null, 2)}`;
81288
81253
  return { stopReason: "end_turn" };
81289
81254
  }
81290
81255
  try {
81291
- const raw = readFileSync8(sessionFile, "utf-8");
81256
+ const raw = readFileSync9(sessionFile, "utf-8");
81292
81257
  if (raw.trim().length === 0) {
81293
81258
  await this.conn.sessionUpdate({
81294
81259
  sessionId: session.sessionId,
@@ -81411,7 +81376,7 @@ ${JSON.stringify(stats, null, 2)}`;
81411
81376
  signal.throwIfAborted();
81412
81377
  const parsed = steerRequestSchema.safeParse(params);
81413
81378
  if (!parsed.success) {
81414
- throw RequestError10.invalidParams("Invalid steering request");
81379
+ throw RequestError11.invalidParams("Invalid steering request");
81415
81380
  }
81416
81381
  const session = this.sessions.maybeGet(parsed.data.sessionId);
81417
81382
  if (session === void 0) {
@@ -81423,14 +81388,6 @@ ${JSON.stringify(stats, null, 2)}`;
81423
81388
  case "idle":
81424
81389
  return { outcome: "promptRequired", reason: "noRunningTurn" };
81425
81390
  case "injected": {
81426
- this.conn.startUserMessage();
81427
- for (const content of parsed.data.prompt) {
81428
- signal.throwIfAborted();
81429
- await this.conn.sessionUpdate({
81430
- sessionId: parsed.data.sessionId,
81431
- update: { sessionUpdate: "user_message_chunk", content }
81432
- });
81433
- }
81434
81391
  return { outcome: "injected" };
81435
81392
  }
81436
81393
  }
@@ -81464,11 +81421,11 @@ ${JSON.stringify(stats, null, 2)}`;
81464
81421
  }
81465
81422
  async forkSession(params) {
81466
81423
  if (!isAbsolute12(params.cwd)) {
81467
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81424
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81468
81425
  }
81469
81426
  const source = this.findStoredSession(params.sessionId);
81470
81427
  if (!source) {
81471
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81428
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81472
81429
  }
81473
81430
  this.lastSessionCwd = params.cwd;
81474
81431
  const fileCommands = loadSlashCommands(params.cwd, this.environment);
@@ -81530,13 +81487,13 @@ ${JSON.stringify(stats, null, 2)}`;
81530
81487
  }
81531
81488
  async resumeSession(params) {
81532
81489
  if (!isAbsolute12(params.cwd)) {
81533
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81490
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81534
81491
  }
81535
81492
  this.sessions.close(params.sessionId);
81536
81493
  this.lastSessionCwd = params.cwd;
81537
81494
  const stored = this.findStoredSession(params.sessionId);
81538
81495
  if (!stored) {
81539
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81496
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81540
81497
  }
81541
81498
  const session = await this.restoreSession(params.sessionId, {
81542
81499
  cwd: params.cwd,
@@ -81601,13 +81558,13 @@ ${JSON.stringify(stats, null, 2)}`;
81601
81558
  }
81602
81559
  async loadSession(params) {
81603
81560
  if (!isAbsolute12(params.cwd)) {
81604
- throw RequestError10.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81561
+ throw RequestError11.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
81605
81562
  }
81606
81563
  this.sessions.close(params.sessionId);
81607
81564
  this.lastSessionCwd = params.cwd;
81608
81565
  const stored = this.findStoredSession(params.sessionId);
81609
81566
  if (!stored) {
81610
- throw RequestError10.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81567
+ throw RequestError11.invalidParams(`Unknown sessionId: ${params.sessionId}`);
81611
81568
  }
81612
81569
  const enableSkillCommands = getEnableSkillCommands(params.cwd, this.environment);
81613
81570
  const session = await this.restoreSession(params.sessionId, {
@@ -81630,9 +81587,29 @@ ${JSON.stringify(stats, null, 2)}`;
81630
81587
  cwd: params.cwd,
81631
81588
  sessionFile: stored.sessionFile
81632
81589
  });
81633
- const data = await proc.getMessages();
81634
- const messages = Array.isArray(data?.messages) ? data.messages : [];
81635
- for (const m of messages) {
81590
+ for (const entry of readPiHistory(stored.sessionFile)) {
81591
+ if (entry.type === "compaction") {
81592
+ await this.conn.sessionUpdate({
81593
+ sessionId: session.sessionId,
81594
+ update: {
81595
+ sessionUpdate: "compaction_update",
81596
+ compactionId: entry.id,
81597
+ status: "completed"
81598
+ }
81599
+ });
81600
+ if (entry.summary) {
81601
+ await this.conn.sessionUpdate({
81602
+ sessionId: session.sessionId,
81603
+ update: {
81604
+ sessionUpdate: "compaction_summary_chunk",
81605
+ compactionId: entry.id,
81606
+ content: { type: "text", text: entry.summary }
81607
+ }
81608
+ });
81609
+ }
81610
+ continue;
81611
+ }
81612
+ const m = entry.message;
81636
81613
  const role = String(m?.role ?? "");
81637
81614
  if (role === "user") {
81638
81615
  const text2 = normalizePiMessageText(m?.content);
@@ -81782,7 +81759,7 @@ ${JSON.stringify(stats, null, 2)}`;
81782
81759
  const session = await this.restoreSession(params.sessionId);
81783
81760
  const mode = params.modeId;
81784
81761
  if (typeof mode !== "string" || mode.length === 0) {
81785
- throw RequestError10.invalidParams("Expected nonempty string modeId");
81762
+ throw RequestError11.invalidParams("Expected nonempty string modeId");
81786
81763
  }
81787
81764
  await session.proc.setThinkingLevel(mode);
81788
81765
  await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
@@ -81793,18 +81770,18 @@ ${JSON.stringify(stats, null, 2)}`;
81793
81770
  const configId = String(params.configId);
81794
81771
  let modelChanged = false;
81795
81772
  if (typeof params.value !== "string") {
81796
- throw RequestError10.invalidParams(`Expected string value for config option: ${configId}`);
81773
+ throw RequestError11.invalidParams(`Expected string value for config option: ${configId}`);
81797
81774
  }
81798
81775
  if (configId === MODEL_CONFIG_ID2) {
81799
81776
  await setSessionModel(session.proc, params.value);
81800
81777
  modelChanged = true;
81801
81778
  } else if (configId === THOUGHT_LEVEL_CONFIG_ID) {
81802
81779
  if (params.value.length === 0) {
81803
- throw RequestError10.invalidParams("Expected nonempty thinking level");
81780
+ throw RequestError11.invalidParams("Expected nonempty thinking level");
81804
81781
  }
81805
81782
  await session.proc.setThinkingLevel(params.value);
81806
81783
  } else {
81807
- throw RequestError10.invalidParams(`Unknown config option: ${configId}`);
81784
+ throw RequestError11.invalidParams(`Unknown config option: ${configId}`);
81808
81785
  }
81809
81786
  const configOptions = await emitConfigOptionsUpdate(this.conn, session.sessionId, session.proc);
81810
81787
  if (modelChanged) {
@@ -82580,7 +82557,14 @@ async function probeVersion(executable, arguments_, environment, defaultWorkspac
82580
82557
  });
82581
82558
  const version2 = normalize4(result.stdout || result.stderr);
82582
82559
  if (version2.length === 0) {
82583
- throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version");
82560
+ throw new ProcessExecutionError("process_exit_failed", "The executable did not report a version", {
82561
+ diagnosticDetails: {
82562
+ probeReason: "empty_version_output",
82563
+ exitCode: "0",
82564
+ stdoutBytes: Buffer.byteLength(result.stdout).toString(),
82565
+ stderrBytes: Buffer.byteLength(result.stderr).toString()
82566
+ }
82567
+ });
82584
82568
  }
82585
82569
  return version2;
82586
82570
  }
@@ -82609,9 +82593,27 @@ function isRetryableProbeFailure(error62) {
82609
82593
  }
82610
82594
  return error62 instanceof AgentProbeError && error62.code === "adapter_probe_timeout";
82611
82595
  }
82612
- async function probeWithRetry(signal, probe) {
82596
+ async function probeWithRetry(context, specification, source, probe) {
82597
+ const signal = context.signal;
82598
+ const run = async (attempt) => {
82599
+ const startedAt = performance.now();
82600
+ try {
82601
+ return await probe();
82602
+ } catch (failure2) {
82603
+ context.onProbeDiagnostic?.({
82604
+ agentId: specification.id,
82605
+ source,
82606
+ event: signal.aborted ? "agent_probe_cancelled" : "agent_probe_failed",
82607
+ attempt,
82608
+ elapsedMilliseconds: Math.round(performance.now() - startedAt),
82609
+ timeoutMilliseconds: source === "acp_readiness" ? specification.acpProbeTimeoutMilliseconds : specification.versionProbeTimeoutMilliseconds,
82610
+ failure: failure2
82611
+ });
82612
+ throw failure2;
82613
+ }
82614
+ };
82613
82615
  try {
82614
- return await probe();
82616
+ return await run(1);
82615
82617
  } catch (error62) {
82616
82618
  if (signal.aborted) {
82617
82619
  signal.throwIfAborted();
@@ -82619,7 +82621,7 @@ async function probeWithRetry(signal, probe) {
82619
82621
  if (!isRetryableProbeFailure(error62)) {
82620
82622
  throw error62;
82621
82623
  }
82622
- return await probe();
82624
+ return await run(2);
82623
82625
  }
82624
82626
  }
82625
82627
  function integrationProbeFailure(specification, error62) {
@@ -82649,7 +82651,9 @@ async function discoverAgent(specification, context) {
82649
82651
  let agentVersion = "";
82650
82652
  try {
82651
82653
  agentVersion = await probeWithRetry(
82652
- context.signal,
82654
+ context,
82655
+ specification,
82656
+ "agent_version",
82653
82657
  async () => await probeVersion(
82654
82658
  agent,
82655
82659
  specification.agentVersionArguments,
@@ -82697,7 +82701,9 @@ async function discoverAgent(specification, context) {
82697
82701
  launchEnvironment = await specification.createLaunchEnvironment(agent, context);
82698
82702
  if (specification.adapterVersionArguments.length > 0) {
82699
82703
  adapterVersion = await probeWithRetry(
82700
- context.signal,
82704
+ context,
82705
+ specification,
82706
+ "adapter_version",
82701
82707
  async () => await probeVersion(
82702
82708
  adapter,
82703
82709
  specification.adapterVersionArguments,
@@ -82732,7 +82738,9 @@ async function discoverAgent(specification, context) {
82732
82738
  );
82733
82739
  try {
82734
82740
  const readiness = await probeWithRetry(
82735
- context.signal,
82741
+ context,
82742
+ specification,
82743
+ "acp_readiness",
82736
82744
  async () => await probeAcpReadiness(
82737
82745
  specification,
82738
82746
  buildDefinition(adapterVersion, unsupportedSessionCapabilities()),
@@ -91272,6 +91280,294 @@ var init_environment_proxy = __esm({
91272
91280
  }
91273
91281
  });
91274
91282
 
91283
+ // src/engine/storage/logs/bounded-log.ts
91284
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
91285
+ import { join as join26 } from "node:path";
91286
+ var BoundedLineLog;
91287
+ var init_bounded_log = __esm({
91288
+ "src/engine/storage/logs/bounded-log.ts"() {
91289
+ "use strict";
91290
+ BoundedLineLog = class {
91291
+ #path;
91292
+ #maximumBytes;
91293
+ #directory;
91294
+ #reportedFailure = false;
91295
+ #onWriteFailure;
91296
+ constructor(directory, filename, maximumBytes, onWriteFailure = () => void 0) {
91297
+ this.#directory = directory;
91298
+ this.#path = join26(directory, filename);
91299
+ this.#maximumBytes = maximumBytes;
91300
+ this.#onWriteFailure = onWriteFailure;
91301
+ }
91302
+ record = (line) => {
91303
+ try {
91304
+ mkdirSync4(this.#directory, { mode: 448, recursive: true });
91305
+ this.#append(line);
91306
+ } catch (cause) {
91307
+ if (!this.#reportedFailure) {
91308
+ this.#reportedFailure = true;
91309
+ this.#onWriteFailure(cause);
91310
+ }
91311
+ }
91312
+ };
91313
+ #append = (line) => {
91314
+ const encoded = `${line.replace(/[\r\n]+/gu, " ").trim()}
91315
+ `;
91316
+ const encodedBytes = Buffer.byteLength(encoded);
91317
+ let existingBytes = 0;
91318
+ try {
91319
+ existingBytes = statSync5(this.#path).size;
91320
+ } catch (cause) {
91321
+ if (!(cause instanceof Error && Reflect.get(cause, "code") === "ENOENT")) {
91322
+ throw cause;
91323
+ }
91324
+ }
91325
+ if (existingBytes + encodedBytes <= this.#maximumBytes) {
91326
+ appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
91327
+ return;
91328
+ }
91329
+ const lines = `${existingBytes === 0 ? "" : readFileSync10(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
91330
+ let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
91331
+ while (totalBytes > this.#maximumBytes && lines.length > 0) {
91332
+ const oldest = lines.shift();
91333
+ if (oldest !== void 0) {
91334
+ totalBytes -= Buffer.byteLength(oldest) + 1;
91335
+ }
91336
+ }
91337
+ const temporaryPath = `${this.#path}.tmp`;
91338
+ writeFileSync2(temporaryPath, lines.length === 0 ? "" : `${lines.join("\n")}
91339
+ `, {
91340
+ encoding: "utf8",
91341
+ mode: 384
91342
+ });
91343
+ renameSync2(temporaryPath, this.#path);
91344
+ };
91345
+ };
91346
+ }
91347
+ });
91348
+
91349
+ // src/engine/storage/logs/log-files.ts
91350
+ import { readFileSync as readFileSync11 } from "node:fs";
91351
+ import { join as join27 } from "node:path";
91352
+ function unhandledRejectionLogFilename(role) {
91353
+ return `unhandled-rejections-${role}.log`;
91354
+ }
91355
+ function logDirectory(dataDirectory) {
91356
+ return join27(dataDirectory, "logs");
91357
+ }
91358
+ function processLogPaths(dataDirectory) {
91359
+ return [
91360
+ WORKER_LIFECYCLE_LOG_FILENAME,
91361
+ unhandledRejectionLogFilename("manager"),
91362
+ unhandledRejectionLogFilename("worker")
91363
+ ].map((filename) => join27(logDirectory(dataDirectory), filename));
91364
+ }
91365
+ function readLogText(path8) {
91366
+ try {
91367
+ return readFileSync11(path8, "utf8");
91368
+ } catch {
91369
+ return null;
91370
+ }
91371
+ }
91372
+ var DAEMON_LOG_FILENAME, WORKER_LIFECYCLE_LOG_FILENAME;
91373
+ var init_log_files = __esm({
91374
+ "src/engine/storage/logs/log-files.ts"() {
91375
+ "use strict";
91376
+ DAEMON_LOG_FILENAME = "daemon.log";
91377
+ WORKER_LIFECYCLE_LOG_FILENAME = "worker-lifecycle.log";
91378
+ }
91379
+ });
91380
+
91381
+ // src/engine/runtime/observability/diagnostic-log.ts
91382
+ import { join as join28 } from "node:path";
91383
+ function exportedFields(value) {
91384
+ const entry = {};
91385
+ for (const field of REMOTE_DIAGNOSTIC_FIELDS) {
91386
+ const item = Reflect.get(value, field);
91387
+ if (typeof item === "string" && FIELD_VALUE_PATTERN.test(item)) {
91388
+ entry[field] = item;
91389
+ } else if (typeof item === "number" && Number.isFinite(item)) {
91390
+ entry[field] = String(item);
91391
+ }
91392
+ }
91393
+ return entry;
91394
+ }
91395
+ function compareTimestamp(left, right) {
91396
+ const leftAt = left["timestamp"] ?? "";
91397
+ const rightAt = right["timestamp"] ?? "";
91398
+ return leftAt < rightAt ? -1 : leftAt > rightAt ? 1 : 0;
91399
+ }
91400
+ var MAXIMUM_RUNTIME_LOG_BYTES, MAXIMUM_ENTRIES, MAXIMUM_REPORT_BYTES, REMOTE_DIAGNOSTIC_FIELDS, FIELD_VALUE_PATTERN, RuntimeDiagnosticLog;
91401
+ var init_diagnostic_log = __esm({
91402
+ "src/engine/runtime/observability/diagnostic-log.ts"() {
91403
+ "use strict";
91404
+ init_bounded_log();
91405
+ init_log_files();
91406
+ MAXIMUM_RUNTIME_LOG_BYTES = 1 * 1024 * 1024;
91407
+ MAXIMUM_ENTRIES = 200;
91408
+ MAXIMUM_REPORT_BYTES = 6e4;
91409
+ REMOTE_DIAGNOSTIC_FIELDS = [
91410
+ "agentId",
91411
+ "operation",
91412
+ "runtimeId",
91413
+ "closeCode",
91414
+ "timeoutMilliseconds",
91415
+ "attempt",
91416
+ "elapsedMilliseconds",
91417
+ "stdoutBytes",
91418
+ "stderrBytes",
91419
+ "outputLimitBytes",
91420
+ "probeReason",
91421
+ "proxyRoute",
91422
+ "timestamp",
91423
+ "event",
91424
+ "channelId",
91425
+ "requestId",
91426
+ "commandId",
91427
+ "sessionId",
91428
+ "turnId",
91429
+ "connectionEpoch",
91430
+ "code",
91431
+ "source",
91432
+ "kind",
91433
+ "pid",
91434
+ "version",
91435
+ "exitCode",
91436
+ "signal",
91437
+ "failureName",
91438
+ "failureCode",
91439
+ "failureStatusCode",
91440
+ "cause1Name",
91441
+ "cause1Code",
91442
+ "cause2Name",
91443
+ "cause2Code"
91444
+ ];
91445
+ FIELD_VALUE_PATTERN = /^[a-zA-Z0-9_.: -]{1,256}$/u;
91446
+ RuntimeDiagnosticLog = class {
91447
+ #log;
91448
+ #maximumBytes;
91449
+ #sources;
91450
+ constructor(stateDirectory, options = {}) {
91451
+ const maximumBytes = options.maximumBytes ?? MAXIMUM_RUNTIME_LOG_BYTES;
91452
+ const directory = logDirectory(stateDirectory);
91453
+ this.#log = new BoundedLineLog(directory, DAEMON_LOG_FILENAME, maximumBytes);
91454
+ this.#maximumBytes = maximumBytes;
91455
+ const processLogsDirectory = options.processLogsDirectory;
91456
+ this.#sources = [
91457
+ { maximumBytes, path: join28(directory, DAEMON_LOG_FILENAME) },
91458
+ // The process logs a Runtime does not own, but must read to explain its own deaths.
91459
+ ...processLogsDirectory === void 0 ? [] : processLogPaths(processLogsDirectory).map((path8) => ({ maximumBytes: null, path: path8 }))
91460
+ ];
91461
+ }
91462
+ // Export only correlation and failure metadata. Local messages and paths stay local.
91463
+ snapshot = () => {
91464
+ const merged = [];
91465
+ let truncated = false;
91466
+ for (const source of this.#sources) {
91467
+ const collected = this.#read(source);
91468
+ merged.push(...collected.entries);
91469
+ truncated ||= collected.truncated;
91470
+ }
91471
+ merged.sort(compareTimestamp);
91472
+ const entries = merged.slice(-MAXIMUM_ENTRIES);
91473
+ truncated ||= entries.length < merged.length;
91474
+ while (JSON.stringify(entries).length > MAXIMUM_REPORT_BYTES && entries.length > 0) {
91475
+ entries.shift();
91476
+ truncated = true;
91477
+ }
91478
+ return { entries, truncated };
91479
+ };
91480
+ record = (diagnostic) => {
91481
+ this.#log.record(diagnostic);
91482
+ };
91483
+ #read = (source) => {
91484
+ const content = readLogText(source.path);
91485
+ if (content === null) {
91486
+ return { entries: [], truncated: false };
91487
+ }
91488
+ const lines = content.split("\n").filter((line) => line.length > 0);
91489
+ const entries = [];
91490
+ for (const line of lines.slice(-MAXIMUM_ENTRIES)) {
91491
+ const start = line.indexOf("{");
91492
+ if (start < 0) {
91493
+ continue;
91494
+ }
91495
+ let value;
91496
+ try {
91497
+ value = JSON.parse(line.slice(start));
91498
+ } catch {
91499
+ continue;
91500
+ }
91501
+ if (typeof value !== "object" || value === null) {
91502
+ continue;
91503
+ }
91504
+ entries.push(exportedFields(value));
91505
+ }
91506
+ const nearRotation = source.maximumBytes !== null && Buffer.byteLength(content) >= source.maximumBytes - 4096;
91507
+ return { entries, truncated: lines.length > MAXIMUM_ENTRIES || nearRotation };
91508
+ };
91509
+ };
91510
+ }
91511
+ });
91512
+
91513
+ // src/engine/runtime/catalog/discover-agent-catalog.ts
91514
+ function failureDetails(failure2) {
91515
+ const fields = {};
91516
+ let current = failure2;
91517
+ for (let depth = 0; depth < 3 && current instanceof Error; depth += 1) {
91518
+ const prefix = depth === 0 ? "failure" : `cause${depth.toString()}`;
91519
+ if (current instanceof ProcessExecutionError || current instanceof AgentProbeError) {
91520
+ fields[`${prefix}Name`] = current instanceof ProcessExecutionError ? "ProcessExecutionError" : "AgentProbeError";
91521
+ fields[`${prefix}Code`] = current.code;
91522
+ } else {
91523
+ fields[`${prefix}Name`] = "Error";
91524
+ }
91525
+ if (depth === 0 && current instanceof ProcessExecutionError) {
91526
+ Object.assign(fields, current.diagnosticDetails);
91527
+ }
91528
+ current = current.cause;
91529
+ }
91530
+ return fields;
91531
+ }
91532
+ async function discoverRuntimeAgentInventory(options, channelId) {
91533
+ const log = new RuntimeDiagnosticLog(options.dataDirectory);
91534
+ const record2 = (details) => {
91535
+ log.record(
91536
+ `Mobius agent discovery diagnostic ${JSON.stringify({
91537
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
91538
+ channelId,
91539
+ ...details
91540
+ })}`
91541
+ );
91542
+ };
91543
+ const inventory = await discoverLocalAgentInventory({
91544
+ ...options,
91545
+ onProbeDiagnostic: ({ failure: failure2, ...diagnostic }) => {
91546
+ record2({ ...diagnostic, ...failureDetails(failure2) });
91547
+ }
91548
+ });
91549
+ for (const { discovery, detectionMilliseconds } of inventory.results) {
91550
+ record2({
91551
+ event: "agent_discovery_result",
91552
+ agentId: discovery.specification.id,
91553
+ code: discovery instanceof UnavailableAgent ? discovery.code : "ready",
91554
+ source: discovery.status,
91555
+ elapsedMilliseconds: detectionMilliseconds
91556
+ });
91557
+ }
91558
+ return inventory;
91559
+ }
91560
+ var init_discover_agent_catalog = __esm({
91561
+ "src/engine/runtime/catalog/discover-agent-catalog.ts"() {
91562
+ "use strict";
91563
+ init_agent_discovery();
91564
+ init_agent_probe_error();
91565
+ init_discover_local_agents();
91566
+ init_process_error();
91567
+ init_diagnostic_log();
91568
+ }
91569
+ });
91570
+
91275
91571
  // src/engine/runtime/relay/relay-authentication.ts
91276
91572
  function runtimeCredential(relayUrl) {
91277
91573
  return relayUrl.searchParams.get("token") ?? "";
@@ -91746,21 +92042,27 @@ function buildSavedRuntimeConfig(connection, defaultWorkspace, inventory, localC
91746
92042
  localContext,
91747
92043
  new OpaqueRuntimeReconnectTarget(connection.connectionId),
91748
92044
  createCatalogAgentResolver(
91749
- (refreshSignal) => discoverLocalAgentInventory({
92045
+ (refreshSignal) => discoverRuntimeAgentInventory(
92046
+ {
92047
+ defaultWorkspace,
92048
+ dataDirectory: localContext.stateDirectory,
92049
+ environment: localContext.agentLaunchEnvironment,
92050
+ signal: refreshSignal
92051
+ },
92052
+ connection.channelId
92053
+ ),
92054
+ () => config2,
92055
+ publishAgentCatalog
92056
+ ),
92057
+ (refreshSignal) => discoverRuntimeAgentInventory(
92058
+ {
91750
92059
  defaultWorkspace,
91751
92060
  dataDirectory: localContext.stateDirectory,
91752
92061
  environment: localContext.agentLaunchEnvironment,
91753
92062
  signal: refreshSignal
91754
- }),
91755
- () => config2,
91756
- publishAgentCatalog
91757
- ),
91758
- (refreshSignal) => discoverLocalAgentInventory({
91759
- defaultWorkspace,
91760
- dataDirectory: localContext.stateDirectory,
91761
- environment: localContext.agentLaunchEnvironment,
91762
- signal: refreshSignal
91763
- }).then((inventory2) => inventory2.readyAgents())
92063
+ },
92064
+ connection.channelId
92065
+ ).then((inventory2) => inventory2.readyAgents())
91764
92066
  );
91765
92067
  return config2;
91766
92068
  }
@@ -91804,12 +92106,15 @@ async function pairRuntimeConnection(installation, options, signal, environment)
91804
92106
  async function prepareRuntimeConnection(installation, connection, signal, environment, maxAcpProcesses) {
91805
92107
  const localContext = new RuntimeLocalContext(installation.stateDirectory, environment, maxAcpProcesses);
91806
92108
  const defaultWorkspace = await resolveDefaultWorkspace(connection.defaultWorkspace);
91807
- const inventory = await discoverLocalAgentInventory({
91808
- defaultWorkspace,
91809
- dataDirectory: localContext.stateDirectory,
91810
- environment: localContext.agentLaunchEnvironment,
91811
- signal
91812
- });
92109
+ const inventory = await discoverRuntimeAgentInventory(
92110
+ {
92111
+ defaultWorkspace,
92112
+ dataDirectory: localContext.stateDirectory,
92113
+ environment: localContext.agentLaunchEnvironment,
92114
+ signal
92115
+ },
92116
+ connection.channelId
92117
+ );
91813
92118
  return buildSavedRuntimeConfig(connection, defaultWorkspace, inventory, localContext);
91814
92119
  }
91815
92120
  var PAIRING_TIMEOUT_MILLISECONDS, PAIRING_CODE_PATTERN, TOKEN_PATTERN, CLAIM_RESPONSE_KEYS, REDEEM_RESPONSE_KEYS, PairingClientError;
@@ -91822,6 +92127,7 @@ var init_pairing = __esm({
91822
92127
  init_local_files();
91823
92128
  init_environment_proxy();
91824
92129
  init_value_utils();
92130
+ init_discover_agent_catalog();
91825
92131
  init_publish_agent_catalog();
91826
92132
  init_resolve_catalog_agent();
91827
92133
  init_config();
@@ -92990,7 +93296,7 @@ var init_session_configurations = __esm({
92990
93296
  restore = async (stored, options, apply, signal) => {
92991
93297
  this.#selected = stored;
92992
93298
  for (const selection of this.#selected) {
92993
- const current = options.find(
93299
+ const current = options().find(
92994
93300
  (option) => option.id === selection.configId && option.type === selection.type
92995
93301
  );
92996
93302
  if (current === void 0) {
@@ -93199,6 +93505,7 @@ async function restoreSession(session, signal, recovery, origin) {
93199
93505
  session.store.remove(session.sessionId);
93200
93506
  stored = session.metrics.measureSync("session-state-read", () => session.store.read(session.sessionId));
93201
93507
  }
93508
+ const forkSource = origin?.kind === "fork" ? session.store.findNative(session.agentId, origin.nativeSessionId)[0] : void 0;
93202
93509
  let lifecycleResponse2;
93203
93510
  if (origin?.kind === "fork") {
93204
93511
  if (!session.capabilities.unstableForkSession) {
@@ -93360,7 +93667,9 @@ async function restoreSession(session, signal, recovery, origin) {
93360
93667
  }
93361
93668
  session.restrictSessionCapabilities(lifecycleResponse2);
93362
93669
  session.setConfigOptions(session.sessionConfigProtocol.normalizeLifecycle(lifecycleResponse2));
93363
- if (stored instanceof FoundStoredSession && session.restored) {
93670
+ if (forkSource !== void 0) {
93671
+ await session.restoreStoredConfigurations(forkSource, signal, "fork");
93672
+ } else if (stored instanceof FoundStoredSession && session.restored) {
93364
93673
  await session.restoreStoredConfigurations(stored.session, signal);
93365
93674
  }
93366
93675
  await session.drained();
@@ -93604,13 +93913,31 @@ var init_agent_session = __esm({
93604
93913
  this.writeStoredSession((/* @__PURE__ */ new Date()).toISOString());
93605
93914
  }
93606
93915
  };
93607
- restoreStoredConfigurations = async (session, signal) => {
93916
+ restoreStoredConfigurations = async (session, signal, intent = "restore") => {
93917
+ const configurations = intent === "fork" ? session.configurations.toSorted(
93918
+ (left, right) => Number(right.configId === "model") - Number(left.configId === "model")
93919
+ ) : session.configurations;
93608
93920
  await this.#sessionConfigurations.restore(
93609
- session.configurations,
93610
- this.#configOptions,
93921
+ configurations,
93922
+ () => this.#configOptions,
93611
93923
  this.#applyConfiguration,
93612
93924
  signal
93613
93925
  );
93926
+ if (intent === "fork") {
93927
+ for (const selection of session.configurations) {
93928
+ if (selection.configId !== "mode") {
93929
+ continue;
93930
+ }
93931
+ const current = this.#configOptions.find((option) => option.id === selection.configId);
93932
+ if (current?.type !== selection.type || (selection.type === "select" ? current.currentValue !== selection.value : current.booleanValue !== selection.booleanValue)) {
93933
+ throw new AcpExecutionError(
93934
+ "The Agent could not preserve the source Session mode for this Fork",
93935
+ {},
93936
+ "invalid_session_configuration"
93937
+ );
93938
+ }
93939
+ }
93940
+ }
93614
93941
  };
93615
93942
  restrictSessionCapabilities = (response) => {
93616
93943
  this.#capabilities = restrictAcpSessionCapabilities(this.#capabilities, response);
@@ -95096,7 +95423,8 @@ var init_native_session_browser = __esm({
95096
95423
  requestId: command.requestId,
95097
95424
  sessionId: command.sessionId,
95098
95425
  targetSessionId: command.targetSessionId,
95099
- ...await this.#activeTurn(command, options)
95426
+ ...await this.#activeTurn(command, options),
95427
+ queuedCancellation: "before-start"
95100
95428
  };
95101
95429
  }
95102
95430
  const capabilities = await options.adapter.getCapabilities(options);
@@ -95730,6 +96058,11 @@ var init_execution_receipts = __esm({
95730
96058
  return void 0;
95731
96059
  }
95732
96060
  };
96061
+ /** Started identities remain authoritative after their detailed receipt is evicted. */
96062
+ hasStarted = (commandId, sessionId) => {
96063
+ const receipt = this.#executions.get(commandId);
96064
+ return receipt === void 0 ? this.#table.identity(commandId)?.sessionId === sessionId : receipt.sessionId === sessionId && receipt.started;
96065
+ };
95733
96066
  /** Reserves an unseen command for cancellation before a delayed prompt can claim its identity. */
95734
96067
  recordCancellationBeforeAdmission = (commandId, sessionId) => {
95735
96068
  const existing = this.#executions.get(commandId);
@@ -96282,7 +96615,7 @@ var init_session_turns = __esm({
96282
96615
 
96283
96616
  // src/engine/session/workspace/workspace-directory.ts
96284
96617
  import { homedir as homedir4 } from "node:os";
96285
- import { basename as basename8, dirname as dirname11, isAbsolute as isAbsolute15, join as join26, normalize as normalize2, relative as relative2 } from "node:path";
96618
+ import { basename as basename8, dirname as dirname11, isAbsolute as isAbsolute15, join as join29, normalize as normalize2, relative as relative2 } from "node:path";
96286
96619
  function encodePath(path8) {
96287
96620
  const encoded = Buffer.from(path8, "utf8").toString("base64url");
96288
96621
  if (path8.length === 0 || path8.length > MAX_WORKSPACE_PATH_LENGTH || encoded.length + "path-".length > MAX_DIRECTORY_IDENTIFIER_LENGTH) {
@@ -96412,7 +96745,7 @@ var init_workspace_directory = __esm({
96412
96745
  continue;
96413
96746
  }
96414
96747
  try {
96415
- const path8 = await this.resolvePath(join26(target, child.name), signal);
96748
+ const path8 = await this.resolvePath(join29(target, child.name), signal);
96416
96749
  entries.push({ directoryId: encodePath(path8), name: child.name });
96417
96750
  } catch (cause) {
96418
96751
  signal.throwIfAborted();
@@ -96592,7 +96925,7 @@ var init_session_layer = __esm({
96592
96925
  // src/engine/storage/files/scratch-directory.ts
96593
96926
  import { randomUUID as randomUUID17 } from "node:crypto";
96594
96927
  import { lstat as lstat4, mkdir as mkdir5, readdir as readdir6, readFile as readFile7, realpath as realpath8, rename as rename4, rm as rm3, stat as stat8, utimes, writeFile as writeFile2 } from "node:fs/promises";
96595
- import { dirname as dirname12, join as join27 } from "node:path";
96928
+ import { dirname as dirname12, join as join30 } from "node:path";
96596
96929
  async function atomicWrite(path8, bytes, signal) {
96597
96930
  const temporary = `${path8}.${randomUUID17()}.tmp`;
96598
96931
  try {
@@ -96610,7 +96943,7 @@ var init_scratch_directory = __esm({
96610
96943
  ScratchDirectory = class {
96611
96944
  #root;
96612
96945
  constructor(parent) {
96613
- this.#root = join27(parent, randomUUID17());
96946
+ this.#root = join30(parent, randomUUID17());
96614
96947
  }
96615
96948
  /** Refreshes this directory's lease and removes sibling directories whose lease is older than `leaseMilliseconds`. */
96616
96949
  refreshLease = async (leaseMilliseconds) => {
@@ -96621,7 +96954,7 @@ var init_scratch_directory = __esm({
96621
96954
  if (!directory.isDirectory() || !/^[a-f0-9-]{36}$/u.test(directory.name)) {
96622
96955
  continue;
96623
96956
  }
96624
- const path8 = join27(dirname12(this.#root), directory.name);
96957
+ const path8 = join30(dirname12(this.#root), directory.name);
96625
96958
  if (path8 === this.#root) {
96626
96959
  continue;
96627
96960
  }
@@ -96636,10 +96969,10 @@ var init_scratch_directory = __esm({
96636
96969
  };
96637
96970
  /** Writes `bytes` atomically to `<group>/<name>` with owner-only permissions and returns the path. */
96638
96971
  write = async (group, name2, bytes, signal) => {
96639
- const directory = join27(this.#root, group);
96972
+ const directory = join30(this.#root, group);
96640
96973
  await mkdir5(directory, { mode: 448, recursive: true });
96641
96974
  signal.throwIfAborted();
96642
- const path8 = join27(directory, name2);
96975
+ const path8 = join30(directory, name2);
96643
96976
  await atomicWrite(path8, bytes, signal);
96644
96977
  return path8;
96645
96978
  };
@@ -96674,9 +97007,9 @@ var init_scratch_directory = __esm({
96674
97007
 
96675
97008
  // src/engine/session/content/external-content-store.ts
96676
97009
  import { createHash as createHash8 } from "node:crypto";
96677
- import { extname as extname3, join as join28 } from "node:path";
97010
+ import { extname as extname2, join as join31 } from "node:path";
96678
97011
  function contentFileName(key, name2) {
96679
- const extension = extname3(name2).toLowerCase();
97012
+ const extension = extname2(name2).toLowerCase();
96680
97013
  return /^\.[a-z0-9]{1,16}$/u.test(extension) ? `${key}${extension}` : key;
96681
97014
  }
96682
97015
  var contentRequest, CONTENT_LIFETIME_MILLISECONDS, metadataSchema, LocalExternalContentStore;
@@ -96700,7 +97033,7 @@ var init_external_content_store = __esm({
96700
97033
  #expirationTimer;
96701
97034
  #cleanup = Promise.resolve();
96702
97035
  constructor(stateDirectory) {
96703
- this.#scratch = new ScratchDirectory(join28(stateDirectory, "tmp", "session-content"));
97036
+ this.#scratch = new ScratchDirectory(join31(stateDirectory, "tmp", "session-content"));
96704
97037
  this.#expirationTimer = setInterval(() => {
96705
97038
  void this.#expire().catch(() => void 0);
96706
97039
  }, 6e4);
@@ -97096,230 +97429,6 @@ var init_agent_process_pool = __esm({
97096
97429
  }
97097
97430
  });
97098
97431
 
97099
- // src/engine/storage/logs/bounded-log.ts
97100
- import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, statSync as statSync5, writeFileSync as writeFileSync2 } from "node:fs";
97101
- import { join as join29 } from "node:path";
97102
- var BoundedLineLog;
97103
- var init_bounded_log = __esm({
97104
- "src/engine/storage/logs/bounded-log.ts"() {
97105
- "use strict";
97106
- BoundedLineLog = class {
97107
- #path;
97108
- #maximumBytes;
97109
- #directory;
97110
- #reportedFailure = false;
97111
- #onWriteFailure;
97112
- constructor(directory, filename, maximumBytes, onWriteFailure = () => void 0) {
97113
- this.#directory = directory;
97114
- this.#path = join29(directory, filename);
97115
- this.#maximumBytes = maximumBytes;
97116
- this.#onWriteFailure = onWriteFailure;
97117
- }
97118
- record = (line) => {
97119
- try {
97120
- mkdirSync4(this.#directory, { mode: 448, recursive: true });
97121
- this.#append(line);
97122
- } catch (cause) {
97123
- if (!this.#reportedFailure) {
97124
- this.#reportedFailure = true;
97125
- this.#onWriteFailure(cause);
97126
- }
97127
- }
97128
- };
97129
- #append = (line) => {
97130
- const encoded = `${line.replace(/[\r\n]+/gu, " ").trim()}
97131
- `;
97132
- const encodedBytes = Buffer.byteLength(encoded);
97133
- let existingBytes = 0;
97134
- try {
97135
- existingBytes = statSync5(this.#path).size;
97136
- } catch (cause) {
97137
- if (!(cause instanceof Error && Reflect.get(cause, "code") === "ENOENT")) {
97138
- throw cause;
97139
- }
97140
- }
97141
- if (existingBytes + encodedBytes <= this.#maximumBytes) {
97142
- appendFileSync2(this.#path, encoded, { encoding: "utf8", mode: 384 });
97143
- return;
97144
- }
97145
- const lines = `${existingBytes === 0 ? "" : readFileSync9(this.#path, "utf8")}${encoded}`.split("\n").filter((candidate) => candidate.length > 0);
97146
- let totalBytes = lines.reduce((total, candidate) => total + Buffer.byteLength(candidate) + 1, 0);
97147
- while (totalBytes > this.#maximumBytes && lines.length > 0) {
97148
- const oldest = lines.shift();
97149
- if (oldest !== void 0) {
97150
- totalBytes -= Buffer.byteLength(oldest) + 1;
97151
- }
97152
- }
97153
- const temporaryPath = `${this.#path}.tmp`;
97154
- writeFileSync2(temporaryPath, lines.length === 0 ? "" : `${lines.join("\n")}
97155
- `, {
97156
- encoding: "utf8",
97157
- mode: 384
97158
- });
97159
- renameSync2(temporaryPath, this.#path);
97160
- };
97161
- };
97162
- }
97163
- });
97164
-
97165
- // src/engine/storage/logs/log-files.ts
97166
- import { readFileSync as readFileSync10 } from "node:fs";
97167
- import { join as join30 } from "node:path";
97168
- function unhandledRejectionLogFilename(role) {
97169
- return `unhandled-rejections-${role}.log`;
97170
- }
97171
- function logDirectory(dataDirectory) {
97172
- return join30(dataDirectory, "logs");
97173
- }
97174
- function processLogPaths(dataDirectory) {
97175
- return [
97176
- WORKER_LIFECYCLE_LOG_FILENAME,
97177
- unhandledRejectionLogFilename("manager"),
97178
- unhandledRejectionLogFilename("worker")
97179
- ].map((filename) => join30(logDirectory(dataDirectory), filename));
97180
- }
97181
- function readLogText(path8) {
97182
- try {
97183
- return readFileSync10(path8, "utf8");
97184
- } catch {
97185
- return null;
97186
- }
97187
- }
97188
- var DAEMON_LOG_FILENAME, WORKER_LIFECYCLE_LOG_FILENAME;
97189
- var init_log_files = __esm({
97190
- "src/engine/storage/logs/log-files.ts"() {
97191
- "use strict";
97192
- DAEMON_LOG_FILENAME = "daemon.log";
97193
- WORKER_LIFECYCLE_LOG_FILENAME = "worker-lifecycle.log";
97194
- }
97195
- });
97196
-
97197
- // src/engine/runtime/observability/diagnostic-log.ts
97198
- import { join as join31 } from "node:path";
97199
- function exportedFields(value) {
97200
- const entry = {};
97201
- for (const field of REMOTE_DIAGNOSTIC_FIELDS) {
97202
- const item = Reflect.get(value, field);
97203
- if (typeof item === "string" && FIELD_VALUE_PATTERN.test(item)) {
97204
- entry[field] = item;
97205
- } else if (typeof item === "number" && Number.isFinite(item)) {
97206
- entry[field] = String(item);
97207
- }
97208
- }
97209
- return entry;
97210
- }
97211
- function compareTimestamp(left, right) {
97212
- const leftAt = left["timestamp"] ?? "";
97213
- const rightAt = right["timestamp"] ?? "";
97214
- return leftAt < rightAt ? -1 : leftAt > rightAt ? 1 : 0;
97215
- }
97216
- var MAXIMUM_RUNTIME_LOG_BYTES, MAXIMUM_ENTRIES, MAXIMUM_REPORT_BYTES, REMOTE_DIAGNOSTIC_FIELDS, FIELD_VALUE_PATTERN, RuntimeDiagnosticLog;
97217
- var init_diagnostic_log = __esm({
97218
- "src/engine/runtime/observability/diagnostic-log.ts"() {
97219
- "use strict";
97220
- init_bounded_log();
97221
- init_log_files();
97222
- MAXIMUM_RUNTIME_LOG_BYTES = 1 * 1024 * 1024;
97223
- MAXIMUM_ENTRIES = 200;
97224
- MAXIMUM_REPORT_BYTES = 6e4;
97225
- REMOTE_DIAGNOSTIC_FIELDS = [
97226
- "agentId",
97227
- "operation",
97228
- "runtimeId",
97229
- "closeCode",
97230
- "timeoutMilliseconds",
97231
- "proxyRoute",
97232
- "timestamp",
97233
- "event",
97234
- "channelId",
97235
- "requestId",
97236
- "commandId",
97237
- "sessionId",
97238
- "turnId",
97239
- "connectionEpoch",
97240
- "code",
97241
- "source",
97242
- "kind",
97243
- "pid",
97244
- "version",
97245
- "exitCode",
97246
- "signal",
97247
- "failureName",
97248
- "failureCode",
97249
- "failureStatusCode",
97250
- "cause1Name",
97251
- "cause1Code",
97252
- "cause2Name",
97253
- "cause2Code"
97254
- ];
97255
- FIELD_VALUE_PATTERN = /^[a-zA-Z0-9_.: -]{1,256}$/u;
97256
- RuntimeDiagnosticLog = class {
97257
- #log;
97258
- #maximumBytes;
97259
- #sources;
97260
- constructor(stateDirectory, options = {}) {
97261
- const maximumBytes = options.maximumBytes ?? MAXIMUM_RUNTIME_LOG_BYTES;
97262
- const directory = logDirectory(stateDirectory);
97263
- this.#log = new BoundedLineLog(directory, DAEMON_LOG_FILENAME, maximumBytes);
97264
- this.#maximumBytes = maximumBytes;
97265
- const processLogsDirectory = options.processLogsDirectory;
97266
- this.#sources = [
97267
- { maximumBytes, path: join31(directory, DAEMON_LOG_FILENAME) },
97268
- // The process logs a Runtime does not own, but must read to explain its own deaths.
97269
- ...processLogsDirectory === void 0 ? [] : processLogPaths(processLogsDirectory).map((path8) => ({ maximumBytes: null, path: path8 }))
97270
- ];
97271
- }
97272
- // Export only correlation and failure metadata. Local messages and paths stay local.
97273
- snapshot = () => {
97274
- const merged = [];
97275
- let truncated = false;
97276
- for (const source of this.#sources) {
97277
- const collected = this.#read(source);
97278
- merged.push(...collected.entries);
97279
- truncated ||= collected.truncated;
97280
- }
97281
- merged.sort(compareTimestamp);
97282
- const entries = merged.slice(-MAXIMUM_ENTRIES);
97283
- truncated ||= entries.length < merged.length;
97284
- while (JSON.stringify(entries).length > MAXIMUM_REPORT_BYTES && entries.length > 0) {
97285
- entries.shift();
97286
- truncated = true;
97287
- }
97288
- return { entries, truncated };
97289
- };
97290
- record = (diagnostic) => {
97291
- this.#log.record(diagnostic);
97292
- };
97293
- #read = (source) => {
97294
- const content = readLogText(source.path);
97295
- if (content === null) {
97296
- return { entries: [], truncated: false };
97297
- }
97298
- const lines = content.split("\n").filter((line) => line.length > 0);
97299
- const entries = [];
97300
- for (const line of lines.slice(-MAXIMUM_ENTRIES)) {
97301
- const start = line.indexOf("{");
97302
- if (start < 0) {
97303
- continue;
97304
- }
97305
- let value;
97306
- try {
97307
- value = JSON.parse(line.slice(start));
97308
- } catch {
97309
- continue;
97310
- }
97311
- if (typeof value !== "object" || value === null) {
97312
- continue;
97313
- }
97314
- entries.push(exportedFields(value));
97315
- }
97316
- const nearRotation = source.maximumBytes !== null && Buffer.byteLength(content) >= source.maximumBytes - 4096;
97317
- return { entries, truncated: lines.length > MAXIMUM_ENTRIES || nearRotation };
97318
- };
97319
- };
97320
- }
97321
- });
97322
-
97323
97432
  // src/engine/runtime/relay/diagnostics.ts
97324
97433
  function sanitizeDiagnosticText(value) {
97325
97434
  const printable = Array.from(value, (character) => {
@@ -98334,7 +98443,7 @@ var init_content_write = __esm({
98334
98443
  });
98335
98444
 
98336
98445
  // src/engine/session/content/session-files.ts
98337
- import { basename as basename9, extname as extname4, isAbsolute as isAbsolute16, join as join32, normalize as normalize3, resolve as resolve17 } from "node:path";
98446
+ import { basename as basename9, extname as extname3, isAbsolute as isAbsolute16, join as join32, normalize as normalize3, resolve as resolve17 } from "node:path";
98338
98447
  import { fileURLToPath as fileURLToPath2 } from "node:url";
98339
98448
  function requestedPath(value) {
98340
98449
  if (value.includes("\0")) {
@@ -98390,7 +98499,7 @@ async function streamLocalFile(command, send2, sendChunk, signal, workingDirecto
98390
98499
  send2({
98391
98500
  byteLength: before.size,
98392
98501
  kind: FILE_BEGIN_KIND,
98393
- mediaType: external?.mediaType ?? raster?.mimeType ?? (extname4(target).toLowerCase() === ".svg" ? "image/svg+xml" : "application/octet-stream"),
98502
+ mediaType: external?.mediaType ?? raster?.mimeType ?? (extname3(target).toLowerCase() === ".svg" ? "image/svg+xml" : "application/octet-stream"),
98394
98503
  modifiedAt: before.modifiedAt.toISOString(),
98395
98504
  name: external?.name ?? (basename9(target) || "file"),
98396
98505
  requestId: command.requestId,
@@ -98739,10 +98848,19 @@ var init_interactions2 = __esm({
98739
98848
  if (message.kind !== SESSION_CANCEL_BEFORE_START_KIND) {
98740
98849
  throw new Error("Command kind mismatch");
98741
98850
  }
98851
+ if (operations.hasStarted(message.commandId, message.sessionId)) {
98852
+ reportOperationFailure(
98853
+ socket,
98854
+ message.commandId,
98855
+ message.sessionId,
98856
+ new SessionError("turn_already_started", "The message already started and could not be withdrawn")
98857
+ );
98858
+ return;
98859
+ }
98742
98860
  const turn = sessionTurns.get(message.commandId, message.sessionId);
98743
98861
  if (turn === void 0) {
98744
98862
  const outcome = operations.recordCancellationBeforeAdmission(message.commandId, message.sessionId);
98745
- if (outcome !== void 0) {
98863
+ if (outcome?.type === "lifecycle-metadata" && outcome.payload.kind === "prompt.completed" && outcome.payload.stopReason === "cancelled") {
98746
98864
  void eventProjection.replayOutcome(message.sessionId, outcome).catch((error62) => {
98747
98865
  reportOperationFailure(socket, message.commandId, message.sessionId, error62);
98748
98866
  });
@@ -99239,6 +99357,7 @@ async function executePrompt({
99239
99357
  );
99240
99358
  prepared = await sessions.prepareExecutionSession(preparation);
99241
99359
  }
99360
+ signal.throwIfAborted();
99242
99361
  operations.markExecutionStarted(command.commandId);
99243
99362
  if (availability.disposition === SessionPromptDisposition.Steer) {
99244
99363
  if (!recordSteeringPrompt()) {
@@ -100907,13 +101026,16 @@ async function prepareProvidedRuntime({
100907
101026
  const defaultWorkspace = await resolveWorkspace(connection.defaultWorkspace);
100908
101027
  const specifications = supportedLocalAgentSpecifications();
100909
101028
  const discoveryEnvironment = localContext.agentLaunchEnvironment;
100910
- const discover = async (refreshSignal) => await discoverLocalAgentInventory({
100911
- defaultWorkspace,
100912
- dataDirectory: localContext.stateDirectory,
100913
- environment: discoveryEnvironment,
100914
- signal: refreshSignal,
100915
- specifications
100916
- });
101029
+ const discover = async (refreshSignal) => await discoverRuntimeAgentInventory(
101030
+ {
101031
+ defaultWorkspace,
101032
+ dataDirectory: localContext.stateDirectory,
101033
+ environment: discoveryEnvironment,
101034
+ signal: refreshSignal,
101035
+ specifications
101036
+ },
101037
+ connection.channelId
101038
+ );
100917
101039
  const inventory = await discover(signal);
100918
101040
  const config2 = createRuntimeConfig(
100919
101041
  {
@@ -100940,6 +101062,7 @@ var init_runtime_loop = __esm({
100940
101062
  init_discover_local_agents();
100941
101063
  init_runtime_agents();
100942
101064
  init_local_files();
101065
+ init_discover_agent_catalog();
100943
101066
  init_publish_agent_catalog();
100944
101067
  init_resolve_catalog_agent();
100945
101068
  init_config();