@moxt-ai/mobius 0.0.170 → 0.0.173

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 (68) hide show
  1. package/dist/acp/agent-session.d.ts.map +1 -1
  2. package/dist/acp/agent-session.js +141 -42
  3. package/dist/acp/agent-session.js.map +1 -1
  4. package/dist/acp/codex/agent.d.ts.map +1 -1
  5. package/dist/acp/codex/agent.js +45 -12
  6. package/dist/acp/codex/agent.js.map +1 -1
  7. package/dist/acp/run-prompt.d.ts.map +1 -1
  8. package/dist/acp/run-prompt.js +7 -1
  9. package/dist/acp/run-prompt.js.map +1 -1
  10. package/dist/acp/session-contracts.d.ts +9 -4
  11. package/dist/acp/session-contracts.d.ts.map +1 -1
  12. package/dist/acp/session-contracts.js +1 -1
  13. package/dist/acp/session-contracts.js.map +1 -1
  14. package/dist/acp/session-history.d.ts +6 -3
  15. package/dist/acp/session-history.d.ts.map +1 -1
  16. package/dist/acp/session-history.js +41 -17
  17. package/dist/acp/session-history.js.map +1 -1
  18. package/dist/acp/session-interactions.d.ts +2 -0
  19. package/dist/acp/session-interactions.d.ts.map +1 -1
  20. package/dist/acp/session-interactions.js +36 -8
  21. package/dist/acp/session-interactions.js.map +1 -1
  22. package/dist/acp/session-store.d.ts +0 -13
  23. package/dist/acp/session-store.d.ts.map +1 -1
  24. package/dist/acp/session-store.js +3 -65
  25. package/dist/acp/session-store.js.map +1 -1
  26. package/dist/cli.js +419 -521
  27. package/dist/cli.js.map +4 -4
  28. package/dist/daemon-command-handler.js +1 -1
  29. package/dist/daemon-command-handler.js.map +1 -1
  30. package/dist/daemon-history-commands.d.ts +2 -1
  31. package/dist/daemon-history-commands.d.ts.map +1 -1
  32. package/dist/daemon-history-commands.js +9 -20
  33. package/dist/daemon-history-commands.js.map +1 -1
  34. package/dist/daemon-observers.d.ts +3 -3
  35. package/dist/daemon-observers.d.ts.map +1 -1
  36. package/dist/daemon-observers.js +2 -18
  37. package/dist/daemon-observers.js.map +1 -1
  38. package/dist/daemon-prompt-executor.d.ts.map +1 -1
  39. package/dist/daemon-prompt-executor.js +3 -1
  40. package/dist/daemon-prompt-executor.js.map +1 -1
  41. package/dist/daemon-turn-registry.d.ts +13 -13
  42. package/dist/generated/acp-session-store-migrations.d.ts +3 -0
  43. package/dist/generated/acp-session-store-migrations.d.ts.map +1 -1
  44. package/dist/generated/acp-session-store-migrations.js +5 -1
  45. package/dist/generated/acp-session-store-migrations.js.map +1 -1
  46. package/dist/index.js +411 -507
  47. package/dist/index.js.map +4 -4
  48. package/dist/relay-connection/session-event-publisher.d.ts +1 -6
  49. package/dist/relay-connection/session-event-publisher.d.ts.map +1 -1
  50. package/dist/relay-connection/session-event-publisher.js +2 -7
  51. package/dist/relay-connection/session-event-publisher.js.map +1 -1
  52. package/dist/run-daemon.js +2 -2
  53. package/dist/run-daemon.js.map +1 -1
  54. package/dist/runtime.js +402 -504
  55. package/dist/runtime.js.map +4 -4
  56. package/dist/schema/acp-session-store/index.d.ts +0 -1
  57. package/dist/schema/acp-session-store/index.d.ts.map +1 -1
  58. package/dist/schema/acp-session-store/index.js +0 -1
  59. package/dist/schema/acp-session-store/index.js.map +1 -1
  60. package/dist/session-event-log-v2.d.ts +18 -9
  61. package/dist/session-event-log-v2.d.ts.map +1 -1
  62. package/dist/session-event-log-v2.js +39 -156
  63. package/dist/session-event-log-v2.js.map +1 -1
  64. package/package.json +1 -1
  65. package/dist/schema/acp-session-store/session-event-v2.d.ts +0 -72
  66. package/dist/schema/acp-session-store/session-event-v2.d.ts.map +0 -1
  67. package/dist/schema/acp-session-store/session-event-v2.js +0 -11
  68. package/dist/schema/acp-session-store/session-event-v2.js.map +0 -1
package/dist/runtime.js CHANGED
@@ -3354,11 +3354,11 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
3354
3354
  return payload;
3355
3355
  };
3356
3356
  });
3357
- function handleArrayResult(result, final, index2) {
3357
+ function handleArrayResult(result, final, index) {
3358
3358
  if (result.issues.length) {
3359
- final.issues.push(...prefixIssues(index2, result.issues));
3359
+ final.issues.push(...prefixIssues(index, result.issues));
3360
3360
  }
3361
- final.value[index2] = result.value;
3361
+ final.value[index] = result.value;
3362
3362
  }
3363
3363
  var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
3364
3364
  $ZodType.init(inst, def);
@@ -3969,14 +3969,14 @@ function mergeValues(a, b) {
3969
3969
  return { valid: false, mergeErrorPath: [] };
3970
3970
  }
3971
3971
  const newArray = [];
3972
- for (let index2 = 0; index2 < a.length; index2++) {
3973
- const itemA = a[index2];
3974
- const itemB = b[index2];
3972
+ for (let index = 0; index < a.length; index++) {
3973
+ const itemA = a[index];
3974
+ const itemB = b[index];
3975
3975
  const sharedValue = mergeValues(itemA, itemB);
3976
3976
  if (!sharedValue.valid) {
3977
3977
  return {
3978
3978
  valid: false,
3979
- mergeErrorPath: [index2, ...sharedValue.mergeErrorPath]
3979
+ mergeErrorPath: [index, ...sharedValue.mergeErrorPath]
3980
3980
  };
3981
3981
  }
3982
3982
  newArray.push(sharedValue.data);
@@ -4127,11 +4127,11 @@ function getTupleOptStart(items, key) {
4127
4127
  }
4128
4128
  return 0;
4129
4129
  }
4130
- function handleTupleResult(result, final, index2) {
4130
+ function handleTupleResult(result, final, index) {
4131
4131
  if (result.issues.length) {
4132
- final.issues.push(...prefixIssues(index2, result.issues));
4132
+ final.issues.push(...prefixIssues(index, result.issues));
4133
4133
  }
4134
- final.value[index2] = result.value;
4134
+ final.value[index] = result.value;
4135
4135
  }
4136
4136
  function handleTupleResults(itemResults, final, items, input2, optoutStart) {
4137
4137
  for (let i = 0; i < items.length; i++) {
@@ -18812,7 +18812,7 @@ function detectVersion(schema, defaultTarget) {
18812
18812
  return defaultTarget ?? "draft-2020-12";
18813
18813
  }
18814
18814
  function applyMinItems(items, minItems) {
18815
- return items.map((item, index2) => index2 < minItems ? item : item.optional());
18815
+ return items.map((item, index) => index < minItems ? item : item.optional());
18816
18816
  }
18817
18817
  function decodeJSONPointerSegment(segment) {
18818
18818
  return segment.replace(/~1/g, "/").replace(/~0/g, "~");
@@ -20014,12 +20014,12 @@ var DEFAULT_AGENT_EXECUTION_CONFIGURATION = Object.freeze({
20014
20014
  });
20015
20015
  var sessionConfigurationSelectionsSchema = external_exports.array(sessionConfigurationSelectionSchema).max(100).superRefine((selections, context) => {
20016
20016
  const identifiers = /* @__PURE__ */ new Set();
20017
- for (const [index2, selection] of selections.entries()) {
20017
+ for (const [index, selection] of selections.entries()) {
20018
20018
  if (identifiers.has(selection.configId)) {
20019
20019
  context.addIssue({
20020
20020
  code: "custom",
20021
20021
  message: "Session configuration identifiers must be unique",
20022
- path: [index2, "configId"]
20022
+ path: [index, "configId"]
20023
20023
  });
20024
20024
  }
20025
20025
  identifiers.add(selection.configId);
@@ -21494,10 +21494,7 @@ var lifecycleMetadataV2Schema = external_exports.discriminatedUnion("kind", [
21494
21494
  external_exports.object({ kind: external_exports.literal("session.queue.changed") }).readonly(),
21495
21495
  external_exports.object({ event: sessionPermissionRequestedEventSchema, kind: external_exports.literal("session.permission.requested") }).readonly(),
21496
21496
  external_exports.object({ event: sessionPermissionResolvedEventSchema, kind: external_exports.literal("session.permission.resolved") }).readonly(),
21497
- external_exports.object({
21498
- event: sessionElicitationRequestedEventSchema,
21499
- kind: external_exports.literal("session.elicitation.requested")
21500
- }).readonly(),
21497
+ external_exports.object({ event: sessionElicitationRequestedEventSchema, kind: external_exports.literal("session.elicitation.requested") }).readonly(),
21501
21498
  external_exports.object({ event: sessionElicitationResolvedEventSchema, kind: external_exports.literal("session.elicitation.resolved") }).readonly(),
21502
21499
  external_exports.object({
21503
21500
  ...lifecycleBase,
@@ -21566,12 +21563,12 @@ var sessionExportV2Schema = external_exports.object({
21566
21563
  }).readonly().superRefine((session, context) => {
21567
21564
  let previousPosition = 0n;
21568
21565
  const eventIds = /* @__PURE__ */ new Set();
21569
- for (const [index2, event] of session.events.entries()) {
21566
+ for (const [index, event] of session.events.entries()) {
21570
21567
  if (event.sessionId !== session.sessionId) {
21571
21568
  context.addIssue({
21572
21569
  code: "custom",
21573
21570
  message: "Exported event belongs to a different Session",
21574
- path: ["events", index2, "sessionId"]
21571
+ path: ["events", index, "sessionId"]
21575
21572
  });
21576
21573
  }
21577
21574
  const position = BigInt(event.position);
@@ -21579,14 +21576,14 @@ var sessionExportV2Schema = external_exports.object({
21579
21576
  context.addIssue({
21580
21577
  code: "custom",
21581
21578
  message: "Exported events are not in increasing position order",
21582
- path: ["events", index2, "position"]
21579
+ path: ["events", index, "position"]
21583
21580
  });
21584
21581
  }
21585
21582
  if (eventIds.has(event.eventId)) {
21586
21583
  context.addIssue({
21587
21584
  code: "custom",
21588
21585
  message: "Exported event identities are not unique",
21589
- path: ["events", index2, "eventId"]
21586
+ path: ["events", index, "eventId"]
21590
21587
  });
21591
21588
  }
21592
21589
  previousPosition = position;
@@ -21599,6 +21596,7 @@ var mobiusSessionExportV2Schema = external_exports.object({
21599
21596
  }).readonly();
21600
21597
  var sessionEventEnvelopeV2Schema = external_exports.object({ event: sessionEventV2Schema, kind: external_exports.literal(SESSION_EVENT_V2_KIND) }).readonly();
21601
21598
  var sessionEventLogPageV2Schema = external_exports.object({
21599
+ daemonGenerationId: identifierStringSchema,
21602
21600
  events: external_exports.array(sessionEventV2Schema).max(MAX_EVENT_COUNT).readonly(),
21603
21601
  nextCursor: external_exports.string().min(1).max(512).nullable(),
21604
21602
  tailCursor: external_exports.string().max(512),
@@ -21606,17 +21604,13 @@ var sessionEventLogPageV2Schema = external_exports.object({
21606
21604
  version: external_exports.literal(2)
21607
21605
  }).readonly();
21608
21606
  var nativeEventPageRequestV2Schema = external_exports.object({ cursor: external_exports.string().min(1).max(512).nullable(), eventLimit: external_exports.number().int().min(1).max(1e4) }).readonly();
21609
- var executingPromptRequestEventLogV2Schema = external_exports.object({
21610
- attemptId: identifierStringSchema,
21607
+ var queuedPromptRequestEventLogV2Schema = external_exports.object({
21611
21608
  commandId: identifierStringSchema,
21612
- epoch: identifierStringSchema,
21613
- events: external_exports.array(sessionEventV2Schema).max(MAX_EVENT_COUNT).readonly(),
21614
- tailCursor: external_exports.string().max(512),
21615
- truncated: external_exports.boolean()
21609
+ content: external_exports.array(contentBlockV2Schema).min(1).max(100).readonly()
21616
21610
  }).readonly();
21617
21611
  var nativeSessionEventsV2Schema = external_exports.object({
21618
- executingPromptRequest: executingPromptRequestEventLogV2Schema.nullable(),
21619
- history: sessionEventLogPageV2Schema
21612
+ events: sessionEventLogPageV2Schema,
21613
+ queuedPromptRequests: external_exports.array(queuedPromptRequestEventLogV2Schema).max(MAX_COLLECTION_SIZE).readonly()
21620
21614
  }).readonly();
21621
21615
  function inputValue(value) {
21622
21616
  if (typeof value !== "string") {
@@ -21640,7 +21634,6 @@ function decode5(value, schema) {
21640
21634
  function encode4(value, schema) {
21641
21635
  return JSON.stringify(decode5(value, schema));
21642
21636
  }
21643
- var decodeSessionEventV2 = (value) => decode5(value, sessionEventV2Schema);
21644
21637
  var decodeSessionEventEnvelopeV2 = (value) => decode5(value, sessionEventEnvelopeV2Schema);
21645
21638
  var encodeSessionEventEnvelopeV2 = (value) => encode4(value, sessionEventEnvelopeV2Schema);
21646
21639
  var decodeAcpSessionUpdateV2 = (value) => decode5(value, acpSessionUpdateV2Schema);
@@ -24533,8 +24526,8 @@ function promptInput(prompt) {
24533
24526
  function isCompactPrompt(prompt) {
24534
24527
  return prompt.length === 1 && prompt[0]?.type === "text" && prompt[0].text.trim() === "/compact";
24535
24528
  }
24536
- function steeringPromptInput(prompt) {
24537
- const input2 = [];
24529
+ function steeringPrompt(prompt) {
24530
+ const blocks = [];
24538
24531
  for (const block of prompt) {
24539
24532
  if (typeof block !== "object" || block === null) {
24540
24533
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
@@ -24545,7 +24538,7 @@ function steeringPromptInput(prompt) {
24545
24538
  if (typeof text2 !== "string") {
24546
24539
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
24547
24540
  }
24548
- input2.push({ text: text2, text_elements: [], type: "text" });
24541
+ blocks.push({ content: { text: text2, type: "text" }, input: { text: text2, text_elements: [], type: "text" } });
24549
24542
  continue;
24550
24543
  }
24551
24544
  if (type === "image") {
@@ -24554,7 +24547,10 @@ function steeringPromptInput(prompt) {
24554
24547
  if (typeof data !== "string" || typeof mimeType !== "string") {
24555
24548
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
24556
24549
  }
24557
- input2.push({ type: "image", url: `data:${mimeType};base64,${data}` });
24550
+ blocks.push({
24551
+ content: { data, mimeType, type: "image" },
24552
+ input: { type: "image", url: `data:${mimeType};base64,${data}` }
24553
+ });
24558
24554
  continue;
24559
24555
  }
24560
24556
  if (type === "resource") {
@@ -24562,24 +24558,33 @@ function steeringPromptInput(prompt) {
24562
24558
  if (typeof resource !== "object" || resource === null) {
24563
24559
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
24564
24560
  }
24561
+ const uri = Reflect.get(resource, "uri");
24565
24562
  const text2 = Reflect.get(resource, "text");
24566
- if (text2 !== void 0 && typeof text2 !== "string") {
24563
+ const blob2 = Reflect.get(resource, "blob");
24564
+ if (typeof uri !== "string" || typeof text2 !== "string" && typeof blob2 !== "string" || text2 !== void 0 && typeof text2 !== "string" || blob2 !== void 0 && typeof blob2 !== "string") {
24567
24565
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
24568
24566
  }
24569
- input2.push({ text: text2 ?? "", text_elements: [], type: "text" });
24567
+ blocks.push({
24568
+ content: typeof text2 === "string" ? { resource: { text: text2, uri }, type: "resource" } : { resource: { blob: blob2, uri }, type: "resource" },
24569
+ input: { text: text2 ?? "", text_elements: [], type: "text" }
24570
+ });
24570
24571
  continue;
24571
24572
  }
24572
24573
  if (type === "resource_link") {
24574
+ const name2 = Reflect.get(block, "name");
24573
24575
  const uri = Reflect.get(block, "uri");
24574
- if (typeof uri !== "string") {
24576
+ if (typeof name2 !== "string" || typeof uri !== "string") {
24575
24577
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
24576
24578
  }
24577
- input2.push({ text: `Resource: ${uri}`, text_elements: [], type: "text" });
24579
+ blocks.push({
24580
+ content: { name: name2, type: "resource_link", uri },
24581
+ input: { text: `Resource: ${uri}`, text_elements: [], type: "text" }
24582
+ });
24578
24583
  continue;
24579
24584
  }
24580
24585
  throw new AcpExecutionError("Codex received an unsupported steering prompt", {}, "invalid_request");
24581
24586
  }
24582
- return input2;
24587
+ return blocks;
24583
24588
  }
24584
24589
  function agentMessageUpdate(messageId, text2, phase) {
24585
24590
  return {
@@ -24726,6 +24731,14 @@ var CodexAcpAgent = class {
24726
24731
  if (isCompactPrompt(context.params.prompt)) {
24727
24732
  return await this.#compact(context.signal);
24728
24733
  }
24734
+ const messageId = crypto.randomUUID();
24735
+ for (const content of context.params.prompt) {
24736
+ await this.#emit({
24737
+ content,
24738
+ messageId,
24739
+ sessionUpdate: "user_message_chunk"
24740
+ });
24741
+ }
24729
24742
  return await this.#runTurn(promptInput(context.params.prompt), context.signal);
24730
24743
  }).onRequest(
24731
24744
  "_session/steering",
@@ -25207,14 +25220,22 @@ var CodexAcpAgent = class {
25207
25220
  if (sessionId !== this.#nativeSessionId || active === null || active.turn.id.length === 0) {
25208
25221
  return { outcome: "promptRequired", reason: "noRunningTurn" };
25209
25222
  }
25210
- const input2 = steeringPromptInput(prompt);
25211
- if (input2.length === 0) {
25223
+ const steering = steeringPrompt(prompt);
25224
+ if (steering.length === 0) {
25212
25225
  throw new AcpExecutionError("Codex received an empty steering request", {}, "invalid_request");
25213
25226
  }
25227
+ const messageId = crypto.randomUUID();
25228
+ for (const block of steering) {
25229
+ await this.#emit({ content: block.content, messageId, sessionUpdate: "user_message_chunk" });
25230
+ }
25214
25231
  const response = turnSteerResponseSchema.parse(
25215
25232
  await this.#appServer.request(
25216
25233
  "turn/steer",
25217
- { expectedTurnId: active.turn.id, input: input2, threadId: this.#nativeSessionId },
25234
+ {
25235
+ expectedTurnId: active.turn.id,
25236
+ input: steering.map((block) => block.input),
25237
+ threadId: this.#nativeSessionId
25238
+ },
25218
25239
  AbortSignal.any([signal, AbortSignal.timeout(APPROVAL_TIMEOUT_MILLISECONDS2)])
25219
25240
  )
25220
25241
  );
@@ -26650,9 +26671,9 @@ function comparePrerelease(left, right) {
26650
26671
  if (left.length === 0 || right.length === 0) {
26651
26672
  return left.length === right.length ? 0 : left.length === 0 ? 1 : -1;
26652
26673
  }
26653
- for (let index2 = 0; index2 < Math.max(left.length, right.length); index2 += 1) {
26654
- const leftPart = left[index2];
26655
- const rightPart = right[index2];
26674
+ for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
26675
+ const leftPart = left[index];
26676
+ const rightPart = right[index];
26656
26677
  if (leftPart === void 0 || rightPart === void 0) {
26657
26678
  return leftPart === rightPart ? 0 : leftPart === void 0 ? -1 : 1;
26658
26679
  }
@@ -26677,8 +26698,8 @@ function compareAgentVersions(left, right) {
26677
26698
  if (parsedLeft === null || parsedRight === null) {
26678
26699
  return null;
26679
26700
  }
26680
- for (let index2 = 0; index2 < Math.max(parsedLeft.core.length, parsedRight.core.length); index2 += 1) {
26681
- const difference = (parsedLeft.core[index2] ?? 0) - (parsedRight.core[index2] ?? 0);
26701
+ for (let index = 0; index < Math.max(parsedLeft.core.length, parsedRight.core.length); index += 1) {
26702
+ const difference = (parsedLeft.core[index] ?? 0) - (parsedRight.core[index] ?? 0);
26682
26703
  if (difference !== 0) {
26683
26704
  return Math.sign(difference);
26684
26705
  }
@@ -27165,7 +27186,7 @@ function createDaemonConfig(connection, agents = [], installableAgents = [], loc
27165
27186
  }
27166
27187
 
27167
27188
  // src/run-daemon.ts
27168
- import { createHash as createHash7, randomUUID as randomUUID7 } from "node:crypto";
27189
+ import { createHash as createHash7, randomUUID as randomUUID8 } from "node:crypto";
27169
27190
  import { join as join18 } from "node:path";
27170
27191
  import { styleText } from "node:util";
27171
27192
 
@@ -27288,7 +27309,7 @@ function startsWith(bytes, signature, offset = 0) {
27288
27309
  if (bytes.byteLength < offset + signature.byteLength) {
27289
27310
  return false;
27290
27311
  }
27291
- return signature.every((value, index2) => bytes[offset + index2] === value);
27312
+ return signature.every((value, index) => bytes[offset + index] === value);
27292
27313
  }
27293
27314
  function sniffRasterMime(bytes) {
27294
27315
  if (startsWith(bytes, PNG_SIGNATURE)) {
@@ -27416,7 +27437,7 @@ function startsWith2(bytes, signature, offset = 0) {
27416
27437
  if (bytes.byteLength < offset + signature.byteLength) {
27417
27438
  return false;
27418
27439
  }
27419
- return signature.every((value, index2) => bytes[offset + index2] === value);
27440
+ return signature.every((value, index) => bytes[offset + index] === value);
27420
27441
  }
27421
27442
  function sniffVideoMime(bytes) {
27422
27443
  if (startsWith2(bytes, MP4_FILE_TYPE, 4)) {
@@ -27545,10 +27566,10 @@ async function replaceImageMarkers(text2, replace) {
27545
27566
  let cursor = 0;
27546
27567
  let rewritten = "";
27547
27568
  for (const match of matches) {
27548
- const index2 = match.index ?? 0;
27549
- rewritten += text2.slice(cursor, index2);
27569
+ const index = match.index ?? 0;
27570
+ rewritten += text2.slice(cursor, index);
27550
27571
  rewritten += await replace(match[1] ?? "");
27551
- cursor = index2 + match[0].length;
27572
+ cursor = index + match[0].length;
27552
27573
  }
27553
27574
  return `${rewritten}${text2.slice(cursor)}`;
27554
27575
  }
@@ -28714,7 +28735,7 @@ function sessionConfigProtocolForAgent(_agentId) {
28714
28735
 
28715
28736
  // src/acp/session-contracts.ts
28716
28737
  var NullAcpSessionObserver = class {
28717
- onAcpUpdate = (_sessionId, _update) => Promise.resolve();
28738
+ onSessionEventV2 = (_sessionId, _event, _position) => Promise.resolve();
28718
28739
  onCommands = () => Promise.resolve();
28719
28740
  onConfig = () => Promise.resolve();
28720
28741
  onContent = () => Promise.resolve();
@@ -28782,7 +28803,8 @@ function historyContentCharacters(messages) {
28782
28803
  var AcpHistoryReplay = class {
28783
28804
  #activities = /* @__PURE__ */ new Map();
28784
28805
  #messages = [];
28785
- #updates = [];
28806
+ #events = [];
28807
+ #records = [];
28786
28808
  #turnActivityIds = /* @__PURE__ */ new Set();
28787
28809
  #activityTracker = new AcpActivityTracker(
28788
28810
  async (activity2) => {
@@ -28804,8 +28826,10 @@ var AcpHistoryReplay = class {
28804
28826
  #firstMessageIndex = 0;
28805
28827
  #characters = 0;
28806
28828
  #truncated = false;
28807
- record = async (update, rawUpdate) => {
28808
- this.#updates.push(rawUpdate);
28829
+ record = async (update, rawUpdate, onRecorded = () => Promise.resolve()) => {
28830
+ this.#records.push({ kind: "acp", rawUpdate, update });
28831
+ this.#events.push({ payload: rawUpdate, type: "acp" });
28832
+ await onRecorded(this.#events.length);
28809
28833
  if (update.sessionUpdate === "agent_thought_chunk") {
28810
28834
  if (update.content.type === "text") {
28811
28835
  await this.#activityTracker.recordNarrative(
@@ -28814,30 +28838,30 @@ var AcpHistoryReplay = class {
28814
28838
  update.content.text
28815
28839
  );
28816
28840
  }
28817
- return;
28841
+ return this.#events.length;
28818
28842
  }
28819
28843
  if (update.sessionUpdate === "tool_call") {
28820
28844
  await this.#activityTracker.recordToolCall(update);
28821
- return;
28845
+ return this.#events.length;
28822
28846
  }
28823
28847
  if (update.sessionUpdate === "tool_call_update") {
28824
28848
  await this.#activityTracker.recordToolCallUpdate(update);
28825
- return;
28849
+ return this.#events.length;
28826
28850
  }
28827
28851
  if (update.sessionUpdate === "plan") {
28828
28852
  await this.#activityTracker.recordPlan(update);
28829
- return;
28853
+ return this.#events.length;
28830
28854
  }
28831
28855
  if (update.sessionUpdate === "plan_update") {
28832
28856
  await this.#activityTracker.recordPlanUpdate(update);
28833
- return;
28857
+ return this.#events.length;
28834
28858
  }
28835
28859
  if (update.sessionUpdate === "plan_removed") {
28836
28860
  await this.#activityTracker.removePlan(update);
28837
- return;
28861
+ return this.#events.length;
28838
28862
  }
28839
28863
  if (update.sessionUpdate !== "user_message_chunk" && update.sessionUpdate !== "agent_message_chunk") {
28840
- return;
28864
+ return this.#events.length;
28841
28865
  }
28842
28866
  if (update.sessionUpdate === "agent_message_chunk" && isProgressMessage(update)) {
28843
28867
  if (update.content.type === "text") {
@@ -28847,18 +28871,18 @@ var AcpHistoryReplay = class {
28847
28871
  update.content.text
28848
28872
  );
28849
28873
  }
28850
- return;
28874
+ return this.#events.length;
28851
28875
  }
28852
28876
  const role = update.sessionUpdate === "user_message_chunk" ? "user" : "assistant";
28853
28877
  const content = update.content;
28854
28878
  if (role === "assistant" && content.type !== "text") {
28855
28879
  await this.#activityTracker.finishNarrative();
28856
28880
  this.recordAssistantContent(update.messageId ?? null, normalizeContentBlock(content));
28857
- return;
28881
+ return this.#events.length;
28858
28882
  }
28859
28883
  const text2 = content.type === "text" ? content.text : content.type === "image" ? content.data.length > 0 ? `[@image](data:${content.mimeType};base64,${content.data})` : content.uri != null && content.uri.length > 0 ? `[@image](${content.uri})` : "[image attachment]" : `[${content.type} attachment]`;
28860
28884
  if (text2.length === 0) {
28861
- return;
28885
+ return this.#events.length;
28862
28886
  }
28863
28887
  const previous = this.#messages.at(-1);
28864
28888
  const id = update.messageId ?? null;
@@ -28885,10 +28909,30 @@ var AcpHistoryReplay = class {
28885
28909
  this.#characters += bounded2.length;
28886
28910
  this.#lastMessageId = id;
28887
28911
  this.trimMessages();
28912
+ return this.#events.length;
28913
+ };
28914
+ recordLifecycle = (event) => {
28915
+ if (event.type !== "lifecycle-metadata") {
28916
+ throw new Error("Lifecycle history only accepts lifecycle metadata");
28917
+ }
28918
+ this.#records.push({ event, kind: "lifecycle" });
28919
+ this.#events.push(event);
28920
+ return this.#events.length;
28921
+ };
28922
+ eventCount = () => this.#events.length;
28923
+ append = async (replay) => {
28924
+ for (const record2 of replay.#records) {
28925
+ if (record2.kind === "acp") {
28926
+ await this.record(record2.update, record2.rawUpdate);
28927
+ } else {
28928
+ this.recordLifecycle(record2.event);
28929
+ }
28930
+ }
28888
28931
  };
28889
- eventPage = (eventLimit, cursor) => {
28890
- const parsedCursor = cursor === null ? this.#updates.length : Number(cursor);
28891
- if (!Number.isSafeInteger(parsedCursor) || parsedCursor < 0 || parsedCursor > this.#updates.length) {
28932
+ eventPage = (eventLimit, cursor, appended = null) => {
28933
+ const events = appended === null ? this.#events : [...this.#events, ...appended.#events];
28934
+ const parsedCursor = cursor === null ? events.length : Number(cursor);
28935
+ if (!Number.isSafeInteger(parsedCursor) || parsedCursor < 0 || parsedCursor > events.length) {
28892
28936
  throw new Error("The native event cursor is invalid");
28893
28937
  }
28894
28938
  const endUpdate = parsedCursor;
@@ -28897,7 +28941,7 @@ var AcpHistoryReplay = class {
28897
28941
  nextCursor: startUpdate === 0 ? null : startUpdate.toString(),
28898
28942
  startPosition: startUpdate + 1,
28899
28943
  truncated: startUpdate > 0,
28900
- updates: this.#updates.slice(startUpdate, endUpdate)
28944
+ events: events.slice(startUpdate, endUpdate)
28901
28945
  };
28902
28946
  };
28903
28947
  snapshot = async () => {
@@ -29284,6 +29328,34 @@ var AcpSessionInteractions = class {
29284
29328
  constructor(context) {
29285
29329
  this.#context = context;
29286
29330
  }
29331
+ #notifyPermissionRequested = async (event) => {
29332
+ await this.#context.recordSessionEventV2({
29333
+ payload: { event, kind: "session.permission.requested" },
29334
+ type: "lifecycle-metadata"
29335
+ });
29336
+ await this.#context.observer().onPermission(event);
29337
+ };
29338
+ #notifyPermissionResolved = async (event) => {
29339
+ await this.#context.recordSessionEventV2({
29340
+ payload: { event, kind: "session.permission.resolved" },
29341
+ type: "lifecycle-metadata"
29342
+ });
29343
+ await this.#context.observer().onPermissionResolved(event);
29344
+ };
29345
+ #notifyElicitationRequested = async (event) => {
29346
+ await this.#context.recordSessionEventV2({
29347
+ payload: { event, kind: "session.elicitation.requested" },
29348
+ type: "lifecycle-metadata"
29349
+ });
29350
+ await this.#context.observer().onElicitation(event);
29351
+ };
29352
+ #notifyElicitationResolved = async (event) => {
29353
+ await this.#context.recordSessionEventV2({
29354
+ payload: { event, kind: "session.elicitation.resolved" },
29355
+ type: "lifecycle-metadata"
29356
+ });
29357
+ await this.#context.observer().onElicitationResolved(event);
29358
+ };
29287
29359
  respondPermission = async (options) => {
29288
29360
  const pending = this.#pendingPermissions.get(options.interactionId);
29289
29361
  if (pending === void 0) {
@@ -29309,7 +29381,7 @@ var AcpSessionInteractions = class {
29309
29381
  );
29310
29382
  }
29311
29383
  this.#pendingPermissions.delete(options.interactionId);
29312
- await this.#context.observer().onPermissionResolved({
29384
+ await this.#notifyPermissionResolved({
29313
29385
  interactionId: options.interactionId,
29314
29386
  kind: SESSION_PERMISSION_RESOLVED_KIND,
29315
29387
  optionId: options.outcome === "selected" ? options.optionId : "",
@@ -29349,7 +29421,7 @@ var AcpSessionInteractions = class {
29349
29421
  );
29350
29422
  }
29351
29423
  this.#pendingElicitations.delete(options.interactionId);
29352
- await this.#context.observer().onElicitationResolved({
29424
+ await this.#notifyElicitationResolved({
29353
29425
  action: options.action,
29354
29426
  interactionId: options.interactionId,
29355
29427
  kind: SESSION_ELICITATION_RESOLVED_KIND,
@@ -29378,7 +29450,7 @@ var AcpSessionInteractions = class {
29378
29450
  };
29379
29451
  signal.addEventListener("abort", abort, { once: true });
29380
29452
  try {
29381
- await this.#context.observer().onPermission({
29453
+ await this.#notifyPermissionRequested({
29382
29454
  commandId: this.#context.commandId(),
29383
29455
  interactionId,
29384
29456
  kind: SESSION_PERMISSION_REQUESTED_KIND,
@@ -29423,7 +29495,7 @@ var AcpSessionInteractions = class {
29423
29495
  };
29424
29496
  signal.addEventListener("abort", abort, { once: true });
29425
29497
  try {
29426
- await this.#context.observer().onElicitation({
29498
+ await this.#notifyElicitationRequested({
29427
29499
  accepted: false,
29428
29500
  commandId: this.#context.commandId(),
29429
29501
  elicitationId,
@@ -29447,7 +29519,7 @@ var AcpSessionInteractions = class {
29447
29519
  return;
29448
29520
  }
29449
29521
  this.#acceptedUrlElicitations.delete(notification.elicitationId);
29450
- await this.#context.observer().onElicitationResolved({
29522
+ await this.#notifyElicitationResolved({
29451
29523
  action: "complete",
29452
29524
  interactionId,
29453
29525
  kind: SESSION_ELICITATION_RESOLVED_KIND,
@@ -29460,7 +29532,7 @@ var AcpSessionInteractions = class {
29460
29532
  return;
29461
29533
  }
29462
29534
  this.#pendingPermissions.delete(interactionId);
29463
- await this.#context.observer().onPermissionResolved({
29535
+ await this.#notifyPermissionResolved({
29464
29536
  interactionId,
29465
29537
  kind: SESSION_PERMISSION_RESOLVED_KIND,
29466
29538
  optionId: "",
@@ -29474,7 +29546,7 @@ var AcpSessionInteractions = class {
29474
29546
  return;
29475
29547
  }
29476
29548
  this.#pendingElicitations.delete(interactionId);
29477
- await this.#context.observer().onElicitationResolved({
29549
+ await this.#notifyElicitationResolved({
29478
29550
  action: "cancel",
29479
29551
  interactionId,
29480
29552
  kind: SESSION_ELICITATION_RESOLVED_KIND,
@@ -29493,7 +29565,7 @@ var AcpSessionInteractions = class {
29493
29565
  await this.cancelElicitation(interactionId);
29494
29566
  }
29495
29567
  for (const interactionId of acceptedElicitationIds) {
29496
- await this.#context.observer().onElicitationResolved({
29568
+ await this.#notifyElicitationResolved({
29497
29569
  action: "cancel",
29498
29570
  interactionId,
29499
29571
  kind: SESSION_ELICITATION_RESOLVED_KIND,
@@ -30622,7 +30694,7 @@ function haveSameKeys(left, right) {
30622
30694
  const leftKeys = Object.keys(left);
30623
30695
  const rightKeys = Object.keys(right);
30624
30696
  if (leftKeys.length !== rightKeys.length) return false;
30625
- for (const [index2, key] of leftKeys.entries()) if (key !== rightKeys[index2]) return false;
30697
+ for (const [index, key] of leftKeys.entries()) if (key !== rightKeys[index]) return false;
30626
30698
  return true;
30627
30699
  }
30628
30700
  function mapUpdateSet(table, values) {
@@ -32128,60 +32200,6 @@ function sqliteTableWithCasing(casing) {
32128
32200
  }
32129
32201
  var sqliteTable = sqliteTableWithCasing(void 0);
32130
32202
 
32131
- // ../../node_modules/.pnpm/drizzle-orm@1.0.0-rc.4_@cloudflare+workers-types@5.20260918.1_@types+better-sqlite3@7.6_f872c171b7e1945bb1fa42180063dab2/node_modules/drizzle-orm/sqlite-core/indexes.js
32132
- var IndexBuilderOn = class {
32133
- static [entityKind] = "SQLiteIndexBuilderOn";
32134
- constructor(name2, unique) {
32135
- this.name = name2;
32136
- this.unique = unique;
32137
- }
32138
- on(...columns) {
32139
- return new IndexBuilder(this.name, columns, this.unique);
32140
- }
32141
- };
32142
- var IndexBuilder = class {
32143
- static [entityKind] = "SQLiteIndexBuilder";
32144
- /** @internal */
32145
- config;
32146
- constructor(name2, columns, unique) {
32147
- this.config = {
32148
- name: name2,
32149
- columns,
32150
- unique,
32151
- where: void 0
32152
- };
32153
- }
32154
- /**
32155
- * Condition for partial index.
32156
- */
32157
- where(condition) {
32158
- this.config.where = condition;
32159
- return this;
32160
- }
32161
- /** @internal */
32162
- build(table) {
32163
- return new Index(this.config, table);
32164
- }
32165
- };
32166
- var Index = class {
32167
- static [entityKind] = "SQLiteIndex";
32168
- config;
32169
- isNameExplicit;
32170
- constructor(config2, table) {
32171
- this.config = {
32172
- ...config2,
32173
- table
32174
- };
32175
- this.isNameExplicit = !!config2.name;
32176
- }
32177
- };
32178
- function index(name2) {
32179
- return new IndexBuilderOn(name2, false);
32180
- }
32181
- function uniqueIndex(name2) {
32182
- return new IndexBuilderOn(name2, true);
32183
- }
32184
-
32185
32203
  // ../../node_modules/.pnpm/drizzle-orm@1.0.0-rc.4_@cloudflare+workers-types@5.20260918.1_@types+better-sqlite3@7.6_f872c171b7e1945bb1fa42180063dab2/node_modules/drizzle-orm/sqlite-core/utils.js
32186
32204
  function extractUsedTable(table) {
32187
32205
  if (is(table, SQLiteTable)) return [`${table[Table.Symbol.BaseName]}`];
@@ -33006,8 +33024,8 @@ var SQLiteDialect = class {
33006
33024
  buildJoins(joins) {
33007
33025
  if (!joins || joins.length === 0) return;
33008
33026
  const joinsArray = [];
33009
- if (joins) for (const [index2, joinMeta] of joins.entries()) {
33010
- if (index2 === 0) joinsArray.push(sql` `);
33027
+ if (joins) for (const [index, joinMeta] of joins.entries()) {
33028
+ if (index === 0) joinsArray.push(sql` `);
33011
33029
  const table = joinMeta.table;
33012
33030
  const onSql = joinMeta.on ? sql` on ${joinMeta.on}` : void 0;
33013
33031
  if (is(table, SQLiteTable)) {
@@ -33017,7 +33035,7 @@ var SQLiteDialect = class {
33017
33035
  const alias = tableName === origTableName ? void 0 : joinMeta.alias;
33018
33036
  joinsArray.push(sql`${sql.raw(joinMeta.joinType)} join ${tableSchema ? sql`${sql.identifier(tableSchema)}.` : void 0}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`}${onSql}`);
33019
33037
  } else joinsArray.push(sql`${sql.raw(joinMeta.joinType)} join ${table}${onSql}`);
33020
- if (index2 < joins.length - 1) joinsArray.push(sql` `);
33038
+ if (index < joins.length - 1) joinsArray.push(sql` `);
33021
33039
  }
33022
33040
  return sql.join(joinsArray);
33023
33041
  }
@@ -33026,9 +33044,9 @@ var SQLiteDialect = class {
33026
33044
  }
33027
33045
  buildOrderBy(orderBy) {
33028
33046
  const orderByList = [];
33029
- if (orderBy) for (const [index2, orderByValue] of orderBy.entries()) {
33047
+ if (orderBy) for (const [index, orderByValue] of orderBy.entries()) {
33030
33048
  orderByList.push(orderByValue);
33031
- if (index2 < orderBy.length - 1) orderByList.push(sql`, `);
33049
+ if (index < orderBy.length - 1) orderByList.push(sql`, `);
33032
33050
  }
33033
33051
  return orderByList.length > 0 ? sql` order by ${sql.join(orderByList)}` : void 0;
33034
33052
  }
@@ -33056,9 +33074,9 @@ var SQLiteDialect = class {
33056
33074
  const whereSql = where ? sql` where ${where}` : void 0;
33057
33075
  const havingSql = having ? sql` having ${having}` : void 0;
33058
33076
  const groupByList = [];
33059
- if (groupBy) for (const [index2, groupByValue] of groupBy.entries()) {
33077
+ if (groupBy) for (const [index, groupByValue] of groupBy.entries()) {
33060
33078
  groupByList.push(groupByValue);
33061
- if (index2 < groupBy.length - 1) groupByList.push(sql`, `);
33079
+ if (index < groupBy.length - 1) groupByList.push(sql`, `);
33062
33080
  }
33063
33081
  const finalQuery = sql`${withSql}select${distinctSql} ${selection} from ${tableSql}${joinsSql}${whereSql}${groupByList.length > 0 ? sql` group by ${sql.join(groupByList)}` : void 0}${havingSql}${this.buildOrderBy(orderBy)}${this.buildLimit(limit)}${offset ? sql` offset ${offset}` : void 0}`;
33064
33082
  if (setOperators.length > 0) return this.buildSetOperations(finalQuery, setOperators);
@@ -34350,6 +34368,10 @@ var acpSessionStoreMigrations = [
34350
34368
  {
34351
34369
  "name": "0002_equal_black_queen.sql",
34352
34370
  "sql": "CREATE TABLE `session_event_v2` (\n `event_id` text PRIMARY KEY NOT NULL,\n `event_json` text NOT NULL,\n `position` integer NOT NULL,\n `session_id` text NOT NULL\n);\n--> statement-breakpoint\nCREATE UNIQUE INDEX `session_event_v2_session_position_unique` ON `session_event_v2` (`session_id`,`position`);--> statement-breakpoint\nCREATE INDEX `session_event_v2_session_position_index` ON `session_event_v2` (`session_id`,`position`);"
34371
+ },
34372
+ {
34373
+ "name": "0003_silky_ravenous.sql",
34374
+ "sql": "DROP TABLE `session_event_v2`;"
34353
34375
  }
34354
34376
  ];
34355
34377
 
@@ -34371,21 +34393,6 @@ var deletedAcpSession = sqliteTable("deleted_acp_session", {
34371
34393
  sessionId: text("session_id").primaryKey()
34372
34394
  });
34373
34395
 
34374
- // src/schema/acp-session-store/session-event-v2.ts
34375
- var sessionEventV2 = sqliteTable(
34376
- "session_event_v2",
34377
- {
34378
- eventId: text("event_id").primaryKey(),
34379
- eventJson: text("event_json").notNull(),
34380
- position: integer2("position").notNull(),
34381
- sessionId: text("session_id").notNull()
34382
- },
34383
- (table) => [
34384
- uniqueIndex("session_event_v2_session_position_unique").on(table.sessionId, table.position),
34385
- index("session_event_v2_session_position_index").on(table.sessionId, table.position)
34386
- ]
34387
- );
34388
-
34389
34396
  // src/acp/session-store.ts
34390
34397
  var AcpStoredSession = class {
34391
34398
  additionalDirectories;
@@ -34428,21 +34435,9 @@ var DeletedAcpStoredSession = class extends AcpStoredSessionLookup {
34428
34435
  var MemoryAcpSessionStore = class {
34429
34436
  #sessions = /* @__PURE__ */ new Map();
34430
34437
  #deleted = /* @__PURE__ */ new Set();
34431
- #eventsV2 = /* @__PURE__ */ new Map();
34432
- appendExecutingPromptEventV2 = (event) => {
34433
- const events = this.#eventsV2.get(event.sessionId);
34434
- if (events === void 0) {
34435
- throw new Error("The executing prompt event log has not started");
34436
- }
34437
- events.push(event);
34438
- };
34439
- clearExecutingPromptEventsV2 = (sessionId) => {
34440
- this.#eventsV2.delete(sessionId);
34441
- };
34442
34438
  close = () => {
34443
34439
  this.#sessions.clear();
34444
34440
  this.#deleted.clear();
34445
- this.#eventsV2.clear();
34446
34441
  };
34447
34442
  findNative = (agentId, nativeSessionId) => [...this.#sessions.values()].filter(
34448
34443
  (session) => session.agentId === agentId && session.nativeSessionId === nativeSessionId
@@ -34453,7 +34448,6 @@ var MemoryAcpSessionStore = class {
34453
34448
  for (const id of ids) {
34454
34449
  this.#sessions.delete(id);
34455
34450
  this.#deleted.add(id);
34456
- this.#eventsV2.delete(id);
34457
34451
  }
34458
34452
  return ids;
34459
34453
  };
@@ -34466,13 +34460,6 @@ var MemoryAcpSessionStore = class {
34466
34460
  };
34467
34461
  remove = (sessionId) => {
34468
34462
  this.#sessions.delete(sessionId);
34469
- this.#eventsV2.delete(sessionId);
34470
- };
34471
- readExecutingPromptEventsV2 = (sessionId) => [
34472
- ...this.#eventsV2.get(sessionId) ?? []
34473
- ];
34474
- startExecutingPromptEventsV2 = (sessionId, events) => {
34475
- this.#eventsV2.set(sessionId, [...events]);
34476
34463
  };
34477
34464
  write = (session) => {
34478
34465
  this.#sessions.set(session.sessionId, session);
@@ -34522,15 +34509,15 @@ var SqliteAcpSessionStore = class {
34522
34509
  this.#sqliteDatabase.close();
34523
34510
  throw new Error("The ACP Session database was created by a newer Mobius version");
34524
34511
  }
34525
- for (let index2 = version2; index2 < acpSessionStoreMigrations.length; index2 += 1) {
34526
- const migration = acpSessionStoreMigrations[index2];
34512
+ for (let index = version2; index < acpSessionStoreMigrations.length; index += 1) {
34513
+ const migration = acpSessionStoreMigrations[index];
34527
34514
  if (migration === void 0) {
34528
34515
  throw new Error("The ACP Session migration is unavailable");
34529
34516
  }
34530
34517
  this.#sqliteDatabase.exec("BEGIN IMMEDIATE");
34531
34518
  try {
34532
34519
  this.#sqliteDatabase.exec(migration.sql);
34533
- this.#sqliteDatabase.exec(`PRAGMA user_version = ${index2 + 1}`);
34520
+ this.#sqliteDatabase.exec(`PRAGMA user_version = ${index + 1}`);
34534
34521
  this.#sqliteDatabase.exec("COMMIT");
34535
34522
  } catch (error62) {
34536
34523
  this.#sqliteDatabase.exec("ROLLBACK");
@@ -34551,30 +34538,6 @@ var SqliteAcpSessionStore = class {
34551
34538
  close = () => {
34552
34539
  this.#sqliteDatabase.close();
34553
34540
  };
34554
- appendExecutingPromptEventV2 = (event) => {
34555
- this.#database.insert(sessionEventV2).values({
34556
- eventId: event.eventId,
34557
- eventJson: JSON.stringify(event),
34558
- position: Number(event.position),
34559
- sessionId: event.sessionId
34560
- }).run();
34561
- };
34562
- clearExecutingPromptEventsV2 = (sessionId) => {
34563
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, sessionId)).run();
34564
- };
34565
- startExecutingPromptEventsV2 = (sessionId, events) => {
34566
- this.#transaction(() => {
34567
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, sessionId)).run();
34568
- for (const event of events) {
34569
- this.#database.insert(sessionEventV2).values({
34570
- eventId: event.eventId,
34571
- eventJson: JSON.stringify(event),
34572
- position: Number(event.position),
34573
- sessionId: event.sessionId
34574
- }).run();
34575
- }
34576
- });
34577
- };
34578
34541
  findNative = (agentId, nativeSessionId) => this.#database.select().from(acpSession).where(and(eq(acpSession.agentId, agentId), eq(acpSession.nativeSessionId, nativeSessionId))).all().map(decodeStoredSession);
34579
34542
  list = () => this.#database.select().from(acpSession).orderBy(desc(acpSession.updatedAt)).all().map(decodeStoredSession);
34580
34543
  markDeleted = (agentId, nativeSessionId) => {
@@ -34583,7 +34546,6 @@ var SqliteAcpSessionStore = class {
34583
34546
  this.#database.delete(acpSession).where(and(eq(acpSession.agentId, agentId), eq(acpSession.nativeSessionId, nativeSessionId))).run();
34584
34547
  for (const id of ids) {
34585
34548
  this.#database.insert(deletedAcpSession).values({ sessionId: id }).onConflictDoNothing().run();
34586
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, id)).run();
34587
34549
  }
34588
34550
  });
34589
34551
  return ids;
@@ -34597,12 +34559,8 @@ var SqliteAcpSessionStore = class {
34597
34559
  const row = this.#database.select().from(acpSession).where(eq(acpSession.sessionId, sessionId)).get();
34598
34560
  return row === void 0 ? new MissingAcpStoredSession() : new FoundAcpStoredSession(decodeStoredSession(row));
34599
34561
  };
34600
- readExecutingPromptEventsV2 = (sessionId) => this.#database.select({ eventJson: sessionEventV2.eventJson }).from(sessionEventV2).where(eq(sessionEventV2.sessionId, sessionId)).orderBy(asc(sessionEventV2.position)).all().map((row) => decodeSessionEventV2(row.eventJson));
34601
34562
  remove = (sessionId) => {
34602
- this.#transaction(() => {
34603
- this.#database.delete(acpSession).where(eq(acpSession.sessionId, sessionId)).run();
34604
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, sessionId)).run();
34605
- });
34563
+ this.#database.delete(acpSession).where(eq(acpSession.sessionId, sessionId)).run();
34606
34564
  };
34607
34565
  write = (session) => {
34608
34566
  const value = {
@@ -34635,7 +34593,7 @@ var RetryableAcpInitializationError = class extends AcpExecutionError {
34635
34593
  }
34636
34594
  };
34637
34595
  function arraysEqual(left, right) {
34638
- return left.length === right.length && left.every((value, index2) => value === right[index2]);
34596
+ return left.length === right.length && left.every((value, index) => value === right[index]);
34639
34597
  }
34640
34598
  function recordsEqual(left, right) {
34641
34599
  const leftEntries = Object.entries(left);
@@ -34672,6 +34630,7 @@ var AgentSession = class _AgentSession {
34672
34630
  #sessionTitle = null;
34673
34631
  #sessionUpdatedAt = "";
34674
34632
  #turn = new IdleAcpTurn();
34633
+ #turnHistory = null;
34675
34634
  constructor(agent, cwd, additionalDirectories, mobiusSessionId, getObserver, store, metrics, contentExternalizer) {
34676
34635
  this.#updates = new AgentUpdateStream((notification) => this.#processUpdate(notification));
34677
34636
  this.#additionalDirectories = [...additionalDirectories];
@@ -34689,7 +34648,8 @@ var AgentSession = class _AgentSession {
34689
34648
  sessionId: () => this.#mobiusSessionId,
34690
34649
  commandId: () => this.#turn.commandId,
34691
34650
  assertNativeSession: (sessionId) => this.assertNativeSession(sessionId),
34692
- observer: getObserver
34651
+ observer: getObserver,
34652
+ recordSessionEventV2: this.#recordLifecycleEventV2
34693
34653
  });
34694
34654
  this.#connection = new AgentConnection(agent, cwd, this);
34695
34655
  this.#contentExternalizer = contentExternalizer;
@@ -34785,13 +34745,10 @@ var AgentSession = class _AgentSession {
34785
34745
  }
34786
34746
  };
34787
34747
  }
34788
- const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
34789
- return await embedLocalHistoryImages(await loaded.history.snapshot(), signal);
34748
+ const history = await this.#completedHistory(signal, "ACP agent exited while loading history");
34749
+ return await embedLocalHistoryImages(await history.snapshot(), signal);
34790
34750
  };
34791
34751
  loadHistoryEventsV2 = async (eventLimit, cursor, signal) => {
34792
- if (!this.#prompted && this.#nativeHistoryOwnership.kind === "fresh-session") {
34793
- return new AcpHistoryReplay().eventPage(eventLimit, cursor);
34794
- }
34795
34752
  if (!this.#capabilities.loadSession) {
34796
34753
  throw new AcpExecutionError(
34797
34754
  "This Agent restores context but does not provide message history.",
@@ -34799,9 +34756,20 @@ var AgentSession = class _AgentSession {
34799
34756
  "native_history_unsupported"
34800
34757
  );
34801
34758
  }
34802
- const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
34803
- return loaded.history.eventPage(eventLimit, cursor);
34759
+ const history = await this.#completedHistory(signal, "ACP agent exited while loading history");
34760
+ return history.eventPage(eventLimit, cursor, this.#turnHistory);
34804
34761
  };
34762
+ async #completedHistory(signal, exitMessage) {
34763
+ if (!this.#prompted && this.#nativeHistoryOwnership.kind === "fresh-session") {
34764
+ if (this.#sessionLoad.kind === "not-requested") {
34765
+ this.#sessionLoad = { history: new AcpHistoryReplay(), kind: "loaded", response: {} };
34766
+ }
34767
+ if (this.#sessionLoad.kind === "loaded") {
34768
+ return this.#sessionLoad.history;
34769
+ }
34770
+ }
34771
+ return (await this.#loadSession(signal, exitMessage)).history;
34772
+ }
34805
34773
  async #loadSession(signal, exitMessage) {
34806
34774
  if (this.#sessionLoad.kind === "loaded") {
34807
34775
  return this.#sessionLoad;
@@ -35285,19 +35253,7 @@ var AgentSession = class _AgentSession {
35285
35253
  if (this.#turn.running) {
35286
35254
  throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
35287
35255
  }
35288
- switch (this.#sessionLoad.kind) {
35289
- case "not-requested":
35290
- break;
35291
- case "loaded":
35292
- this.#sessionLoad = { kind: "not-requested" };
35293
- break;
35294
- case "capturing":
35295
- throw new AcpExecutionError("Session history is still loading", {}, "session_busy");
35296
- default: {
35297
- const unexpected = this.#sessionLoad;
35298
- throw new Error(`Unexpected Session load state: ${JSON.stringify(unexpected)}`);
35299
- }
35300
- }
35256
+ const completedHistory = this.#capabilities.loadSession ? await this.#completedHistory(options.signal, "ACP agent exited while loading history before a prompt") : null;
35301
35257
  const prompt = this.buildPrompt(options);
35302
35258
  if (this.#sessionTitle === null || this.#sessionTitle.length === 0) {
35303
35259
  this.#sessionTitle = truncate(options.prompt, 500);
@@ -35324,6 +35280,23 @@ var AgentSession = class _AgentSession {
35324
35280
  this.prepareAgentContent
35325
35281
  );
35326
35282
  this.#turn = running;
35283
+ this.#turnHistory = completedHistory === null ? null : new AcpHistoryReplay();
35284
+ const lifecycleV2 = options.lifecycleV2;
35285
+ if (lifecycleV2 !== void 0) {
35286
+ await this.#recordLifecycleEventV2({
35287
+ payload: { commandId: options.commandId, content: lifecycleV2.content, kind: "prompt.requested" },
35288
+ type: "lifecycle-metadata"
35289
+ });
35290
+ await this.#recordLifecycleEventV2({
35291
+ payload: {
35292
+ attemptId: lifecycleV2.attemptId,
35293
+ commandId: options.commandId,
35294
+ epoch: lifecycleV2.epoch,
35295
+ kind: "prompt.started"
35296
+ },
35297
+ type: "lifecycle-metadata"
35298
+ });
35299
+ }
35327
35300
  this.#nativePrompt = {
35328
35301
  commandId: options.commandId,
35329
35302
  previousTurnId: this.#connection.inProcessAgent?.nativeTurnId?.() ?? null
@@ -35378,16 +35351,37 @@ var AgentSession = class _AgentSession {
35378
35351
  this.#lastTerminalCommandId
35379
35352
  )
35380
35353
  );
35354
+ if (lifecycleV2 !== void 0) {
35355
+ await this.#recordLifecycleEventV2({
35356
+ payload: { commandId: options.commandId, kind: "prompt.completed", stopReason: result.stopReason },
35357
+ type: "lifecycle-metadata"
35358
+ });
35359
+ }
35381
35360
  return result;
35382
35361
  } catch (error62) {
35383
35362
  await running.activities.finish();
35363
+ const failure2 = error62 instanceof AcpExecutionError ? error62 : new AcpExecutionError("ACP agent execution failed", { cause: error62 });
35364
+ if (lifecycleV2 !== void 0) {
35365
+ await this.#recordLifecycleEventV2({
35366
+ payload: {
35367
+ attemptId: lifecycleV2.attemptId,
35368
+ code: failure2.code,
35369
+ commandId: options.commandId,
35370
+ kind: "prompt.failed",
35371
+ message: truncate(failure2.message, 500)
35372
+ },
35373
+ type: "lifecycle-metadata"
35374
+ });
35375
+ }
35384
35376
  if (error62 instanceof AcpExecutionError) {
35385
35377
  throw error62;
35386
35378
  }
35387
- throw new AcpExecutionError("ACP agent execution failed", {
35388
- cause: error62
35389
- });
35379
+ throw failure2;
35390
35380
  } finally {
35381
+ if (completedHistory !== null && this.#turnHistory !== null) {
35382
+ await completedHistory.append(this.#turnHistory);
35383
+ }
35384
+ this.#turnHistory = null;
35391
35385
  this.#turn = new IdleAcpTurn();
35392
35386
  }
35393
35387
  };
@@ -35403,41 +35397,80 @@ var AgentSession = class _AgentSession {
35403
35397
  throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
35404
35398
  }
35405
35399
  const prompt = this.buildPrompt(options);
35406
- const response = await this.race(
35407
- this.#connection.connection.agent.request("_session/steering", {
35408
- _meta: { steering: { idleBehavior: "promptRequired" } },
35409
- prompt,
35410
- sessionId: this.#updates.sessionId()
35411
- }),
35412
- "ACP agent exited during steering",
35413
- options.signal
35414
- );
35415
- if (!isRecord4(response)) {
35400
+ const lifecycleV2 = options.lifecycleV2;
35401
+ if (lifecycleV2 !== void 0) {
35402
+ await this.#recordLifecycleEventV2({
35403
+ payload: { commandId: options.commandId, content: lifecycleV2.content, kind: "prompt.requested" },
35404
+ type: "lifecycle-metadata"
35405
+ });
35406
+ await this.#recordLifecycleEventV2({
35407
+ payload: {
35408
+ attemptId: lifecycleV2.attemptId,
35409
+ commandId: options.commandId,
35410
+ epoch: lifecycleV2.epoch,
35411
+ kind: "prompt.started"
35412
+ },
35413
+ type: "lifecycle-metadata"
35414
+ });
35415
+ }
35416
+ try {
35417
+ const response = await this.race(
35418
+ this.#connection.connection.agent.request("_session/steering", {
35419
+ _meta: { steering: { idleBehavior: "promptRequired" } },
35420
+ prompt,
35421
+ sessionId: this.#updates.sessionId()
35422
+ }),
35423
+ "ACP agent exited during steering",
35424
+ options.signal
35425
+ );
35426
+ if (!isRecord4(response)) {
35427
+ throw new AcpExecutionError(
35428
+ "ACP agent returned an invalid steering response",
35429
+ {},
35430
+ "acp_invalid_steering_response"
35431
+ );
35432
+ }
35433
+ const outcome = response["outcome"];
35434
+ if (outcome === "injected" || outcome === "startedNewTurn") {
35435
+ if (lifecycleV2 !== void 0) {
35436
+ await this.#recordLifecycleEventV2({
35437
+ payload: { commandId: options.commandId, kind: "prompt.completed", stopReason: "steered" },
35438
+ type: "lifecycle-metadata"
35439
+ });
35440
+ }
35441
+ return outcome;
35442
+ }
35443
+ if (outcome === "promptRequired") {
35444
+ throw new AcpExecutionError(
35445
+ "The target turn finished before steering could be injected",
35446
+ {},
35447
+ "steering_target_unavailable"
35448
+ );
35449
+ }
35450
+ if (outcome === "failed") {
35451
+ throw new AcpExecutionError("The Agent could not inject steering", {}, "steering_failed");
35452
+ }
35416
35453
  throw new AcpExecutionError(
35417
35454
  "ACP agent returned an invalid steering response",
35418
35455
  {},
35419
35456
  "acp_invalid_steering_response"
35420
35457
  );
35458
+ } catch (error62) {
35459
+ const failure2 = error62 instanceof AcpExecutionError ? error62 : new AcpExecutionError("ACP agent execution failed", { cause: error62 });
35460
+ if (lifecycleV2 !== void 0) {
35461
+ await this.#recordLifecycleEventV2({
35462
+ payload: {
35463
+ attemptId: lifecycleV2.attemptId,
35464
+ code: failure2.code,
35465
+ commandId: options.commandId,
35466
+ kind: "prompt.failed",
35467
+ message: truncate(failure2.message, 500)
35468
+ },
35469
+ type: "lifecycle-metadata"
35470
+ });
35471
+ }
35472
+ throw failure2;
35421
35473
  }
35422
- const outcome = response["outcome"];
35423
- if (outcome === "injected" || outcome === "startedNewTurn") {
35424
- return outcome;
35425
- }
35426
- if (outcome === "promptRequired") {
35427
- throw new AcpExecutionError(
35428
- "The target turn finished before steering could be injected",
35429
- {},
35430
- "steering_target_unavailable"
35431
- );
35432
- }
35433
- if (outcome === "failed") {
35434
- throw new AcpExecutionError("The Agent could not inject steering", {}, "steering_failed");
35435
- }
35436
- throw new AcpExecutionError(
35437
- "ACP agent returned an invalid steering response",
35438
- {},
35439
- "acp_invalid_steering_response"
35440
- );
35441
35474
  };
35442
35475
  cancel = async () => {
35443
35476
  const capturedProcesses = await this.#connection.captureProcessTree();
@@ -35458,6 +35491,13 @@ var AgentSession = class _AgentSession {
35458
35491
  onElicitation = (request, signal) => this.#interactions.onElicitation(request, signal);
35459
35492
  onElicitationComplete = (notification) => this.#interactions.onElicitationComplete(notification);
35460
35493
  onUpdate = (notification) => this.#updates.receive(notification);
35494
+ #recordLifecycleEventV2 = async (event) => {
35495
+ if (event.type !== "lifecycle-metadata" || this.#sessionLoad.kind !== "loaded") {
35496
+ return;
35497
+ }
35498
+ const position = this.#turnHistory === null ? this.#sessionLoad.history.recordLifecycle(event) : this.#sessionLoad.history.eventCount() + this.#turnHistory.recordLifecycle(event);
35499
+ await this.#getObserver().onSessionEventV2?.(this.#mobiusSessionId, event, position);
35500
+ };
35461
35501
  selectNativeSession = (sessionId) => {
35462
35502
  this.#updates.select(sessionId);
35463
35503
  this.#nativeHistoryOwnership = { kind: "agent-owned" };
@@ -35474,9 +35514,20 @@ var AgentSession = class _AgentSession {
35474
35514
  if (this.#sessionLoad.kind === "capturing") {
35475
35515
  await this.#sessionLoad.history.record(update, rawUpdate);
35476
35516
  } else {
35477
- const onAcpUpdate = this.#getObserver().onAcpUpdate;
35478
- if (onAcpUpdate !== void 0) {
35479
- await onAcpUpdate(this.#mobiusSessionId, rawUpdate);
35517
+ const onSessionEventV2 = this.#getObserver().onSessionEventV2;
35518
+ if (this.#turnHistory !== null) {
35519
+ const completedEventCount = this.#sessionLoad.kind === "loaded" ? this.#sessionLoad.history.eventCount() : 0;
35520
+ await this.#turnHistory.record(update, rawUpdate, async (turnPosition) => {
35521
+ await onSessionEventV2?.(
35522
+ this.#mobiusSessionId,
35523
+ { payload: rawUpdate, type: "acp" },
35524
+ completedEventCount + turnPosition
35525
+ );
35526
+ });
35527
+ } else if (this.#sessionLoad.kind === "loaded") {
35528
+ await this.#sessionLoad.history.record(update, rawUpdate, async (position) => {
35529
+ await onSessionEventV2?.(this.#mobiusSessionId, { payload: rawUpdate, type: "acp" }, position);
35530
+ });
35480
35531
  }
35481
35532
  }
35482
35533
  if (this.#sessionLoad.kind === "capturing" && (update.sessionUpdate === "user_message_chunk" || update.sessionUpdate === "agent_message_chunk" || update.sessionUpdate === "agent_thought_chunk" || update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update" || update.sessionUpdate === "plan" || update.sessionUpdate === "plan_update" || update.sessionUpdate === "plan_removed")) {
@@ -36339,9 +36390,9 @@ var AcpProcessCapacityLock = class {
36339
36390
  return await waiter.completion.promise;
36340
36391
  } finally {
36341
36392
  signal.removeEventListener("abort", waiter.cancel);
36342
- const index2 = this.#waiters.indexOf(waiter);
36343
- if (index2 >= 0) {
36344
- this.#waiters.splice(index2, 1);
36393
+ const index = this.#waiters.indexOf(waiter);
36394
+ if (index >= 0) {
36395
+ this.#waiters.splice(index, 1);
36345
36396
  }
36346
36397
  }
36347
36398
  };
@@ -38255,8 +38306,8 @@ var DaemonAcpObserver = class {
38255
38306
  this.#record = record2;
38256
38307
  this.#recordV2 = recordV2;
38257
38308
  }
38258
- onAcpUpdate = (sessionId, update) => {
38259
- this.#recordV2(sessionId, { payload: update, type: "acp" });
38309
+ onSessionEventV2 = (sessionId, event, position) => {
38310
+ this.#recordV2(sessionId, event, position);
38260
38311
  return Promise.resolve();
38261
38312
  };
38262
38313
  onCommands = (event) => {
@@ -38273,18 +38324,10 @@ var DaemonAcpObserver = class {
38273
38324
  };
38274
38325
  onElicitation = (event) => {
38275
38326
  this.#record(event.sessionId, event);
38276
- this.#recordV2(event.sessionId, {
38277
- payload: { event, kind: "session.elicitation.requested" },
38278
- type: "lifecycle-metadata"
38279
- });
38280
38327
  return Promise.resolve();
38281
38328
  };
38282
38329
  onElicitationResolved = (event) => {
38283
38330
  this.#record(event.sessionId, event);
38284
- this.#recordV2(event.sessionId, {
38285
- payload: { event, kind: "session.elicitation.resolved" },
38286
- type: "lifecycle-metadata"
38287
- });
38288
38331
  return Promise.resolve();
38289
38332
  };
38290
38333
  onInfo = (event) => {
@@ -38293,18 +38336,10 @@ var DaemonAcpObserver = class {
38293
38336
  };
38294
38337
  onPermission = (event) => {
38295
38338
  this.#record(event.sessionId, event);
38296
- this.#recordV2(event.sessionId, {
38297
- payload: { event, kind: "session.permission.requested" },
38298
- type: "lifecycle-metadata"
38299
- });
38300
38339
  return Promise.resolve();
38301
38340
  };
38302
38341
  onPermissionResolved = (event) => {
38303
38342
  this.#record(event.sessionId, event);
38304
- this.#recordV2(event.sessionId, {
38305
- payload: { event, kind: "session.permission.resolved" },
38306
- type: "lifecycle-metadata"
38307
- });
38308
38343
  return Promise.resolve();
38309
38344
  };
38310
38345
  onUsage = (event) => {
@@ -38411,8 +38446,8 @@ var ACTIVE_TURN_TEXT_CHUNK_LIMIT = Math.floor(SESSION_HISTORY_CHARACTER_LIMIT /
38411
38446
  function boundedRecoveryMessages(messages) {
38412
38447
  const selected = [];
38413
38448
  let remainingCharacters = SESSION_HISTORY_CHARACTER_LIMIT;
38414
- for (let index2 = messages.length - 1; index2 >= 0 && selected.length < SESSION_HISTORY_MESSAGE_LIMIT; index2 -= 1) {
38415
- const message = messages[index2];
38449
+ for (let index = messages.length - 1; index >= 0 && selected.length < SESSION_HISTORY_MESSAGE_LIMIT; index -= 1) {
38450
+ const message = messages[index];
38416
38451
  if (message === void 0) {
38417
38452
  break;
38418
38453
  }
@@ -38553,7 +38588,7 @@ var ActiveDaemonTurn = class {
38553
38588
  ];
38554
38589
  } else {
38555
38590
  this.#timeline = this.#timeline.map(
38556
- (entry, index2) => index2 === target && entry.kind === "message" ? { ...entry, content: new Map([...entry.content, [event.contentId, event.content]]) } : entry
38591
+ (entry, index) => index === target && entry.kind === "message" ? { ...entry, content: new Map([...entry.content, [event.contentId, event.content]]) } : entry
38557
38592
  );
38558
38593
  }
38559
38594
  } else if (event.kind === SESSION_PERMISSION_REQUESTED_KIND || event.kind === SESSION_ELICITATION_REQUESTED_KIND) {
@@ -39579,7 +39614,7 @@ async function readAcpHistory(sessions, directories, bindingId, options, nativeS
39579
39614
  async (directory) => await directories.identify(bindingId, directory, options.signal)
39580
39615
  )
39581
39616
  );
39582
- if (primary.path !== options.cwd || additional.length !== options.additionalDirectories.length || additional.some((directory, index2) => directory.path !== options.additionalDirectories[index2])) {
39617
+ if (primary.path !== options.cwd || additional.length !== options.additionalDirectories.length || additional.some((directory, index) => directory.path !== options.additionalDirectories[index])) {
39583
39618
  throw new AcpExecutionError(
39584
39619
  "The native Session belongs to another workspace.",
39585
39620
  {},
@@ -39712,7 +39747,7 @@ var NativeSessionService = class {
39712
39747
  "native_session_not_found"
39713
39748
  );
39714
39749
  }
39715
- if (source.agentId !== command.agentId || source.cwd !== cwd || source.additionalDirectories.length !== additionalDirectories.length || source.additionalDirectories.some((path2, index2) => path2 !== additionalDirectories[index2])) {
39750
+ if (source.agentId !== command.agentId || source.cwd !== cwd || source.additionalDirectories.length !== additionalDirectories.length || source.additionalDirectories.some((path2, index) => path2 !== additionalDirectories[index])) {
39716
39751
  throw new AcpExecutionError(
39717
39752
  "The source conversation execution target does not match the fork request",
39718
39753
  {},
@@ -39733,8 +39768,8 @@ var NativeSessionService = class {
39733
39768
  signal.throwIfAborted();
39734
39769
  const directory = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
39735
39770
  const ready2 = {
39736
- additionalDirectories: additionalDirectories.map((path2, index2) => ({
39737
- directoryId: command.additionalDirectoryIds[index2] ?? command.directoryId,
39771
+ additionalDirectories: additionalDirectories.map((path2, index) => ({
39772
+ directoryId: command.additionalDirectoryIds[index] ?? command.directoryId,
39738
39773
  name: basename4(path2) || path2
39739
39774
  })),
39740
39775
  agentId: command.agentId,
@@ -40067,7 +40102,7 @@ var NativeSessionService = class {
40067
40102
  resolveTarget = async (command, options, selected) => {
40068
40103
  let cursor = null;
40069
40104
  const visited = /* @__PURE__ */ new Set();
40070
- for (let index2 = 0; index2 < 100; index2 += 1) {
40105
+ for (let index = 0; index < 100; index += 1) {
40071
40106
  const page = await this.#sessions.listNativeSessions(options, cursor);
40072
40107
  const info = page.sessions.find((entry) => entry.sessionId === selected.nativeSessionId);
40073
40108
  if (info !== void 0) {
@@ -40075,7 +40110,7 @@ var NativeSessionService = class {
40075
40110
  if (target === null) {
40076
40111
  throw new LocalAuthorizationError("The selected native session is not authorized");
40077
40112
  }
40078
- if (target.cwd !== selected.cwd || target.additionalDirectories.length !== selected.additionalDirectories.length || target.additionalDirectories.some((path2, index3) => path2 !== selected.additionalDirectories[index3])) {
40113
+ if (target.cwd !== selected.cwd || target.additionalDirectories.length !== selected.additionalDirectories.length || target.additionalDirectories.some((path2, index2) => path2 !== selected.additionalDirectories[index2])) {
40079
40114
  throw new AcpExecutionError(
40080
40115
  "This session's directory changed. Refresh the list before continuing.",
40081
40116
  {},
@@ -41164,9 +41199,6 @@ async function streamLocalFile(command, send2, signal, workingDirectory, externa
41164
41199
  });
41165
41200
  }
41166
41201
 
41167
- // src/daemon-history-commands.ts
41168
- import { createHash as createHash6 } from "node:crypto";
41169
-
41170
41202
  // src/authorization/resolve-session-directories.ts
41171
41203
  import { basename as basename6 } from "node:path";
41172
41204
  var ResolvedSessionDirectories = class {
@@ -41266,8 +41298,8 @@ function selectMessagesBefore(messages, endIndex, messageLimit, characterLimit)
41266
41298
  const selected = [];
41267
41299
  let remainingCharacters = characterLimit;
41268
41300
  let startIndex = endIndex;
41269
- for (let index2 = endIndex - 1; index2 >= 0 && selected.length < messageLimit; index2 -= 1) {
41270
- const message = messages[index2];
41301
+ for (let index = endIndex - 1; index >= 0 && selected.length < messageLimit; index -= 1) {
41302
+ const message = messages[index];
41271
41303
  if (message === void 0) {
41272
41304
  break;
41273
41305
  }
@@ -41277,7 +41309,7 @@ function selectMessagesBefore(messages, endIndex, messageLimit, characterLimit)
41277
41309
  }
41278
41310
  selected.unshift(message);
41279
41311
  remainingCharacters -= characters;
41280
- startIndex = index2;
41312
+ startIndex = index;
41281
41313
  }
41282
41314
  if (selected.length === 0 && endIndex > 0) {
41283
41315
  throw new AcpExecutionError(
@@ -41493,20 +41525,7 @@ async function executeSessionLiveHistoryPageLoad(socket, command, config2, direc
41493
41525
  });
41494
41526
  }
41495
41527
  }
41496
- function replayEvent(sessionId, position, update) {
41497
- const encoded = JSON.stringify(update);
41498
- const eventId = `native-${createHash6("sha256").update(sessionId).update(":").update(position.toString()).update(":").update(encoded).digest("hex")}`;
41499
- return {
41500
- eventId,
41501
- payload: update,
41502
- position: position.toString(),
41503
- provenance: { kind: "original" },
41504
- recordedAt: "1970-01-01T00:00:00.000Z",
41505
- sessionId,
41506
- type: "acp"
41507
- };
41508
- }
41509
- async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, directories, audit, diagnostics, sessions, executingPromptRequest, signal) {
41528
+ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, directories, audit, diagnostics, sessions, eventLogV2, signal) {
41510
41529
  try {
41511
41530
  const resolved = await resolveSessionDirectories(
41512
41531
  directories,
@@ -41515,20 +41534,18 @@ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, dir
41515
41534
  command.additionalDirectoryIds,
41516
41535
  signal
41517
41536
  );
41518
- const replay = await sessions.loadSessionEventsV2(
41519
- {
41520
- additionalDirectories: resolved.additionalDirectories,
41521
- agent: config2.catalog.find(command.agentId),
41522
- cwd: resolved.cwd,
41523
- sessionId: command.sessionId,
41524
- signal
41525
- },
41526
- command.eventLimit,
41527
- command.cursor
41528
- );
41537
+ const loadOptions = {
41538
+ additionalDirectories: resolved.additionalDirectories,
41539
+ agent: config2.catalog.find(command.agentId),
41540
+ cwd: resolved.cwd,
41541
+ sessionId: command.sessionId,
41542
+ signal
41543
+ };
41544
+ const recovery = eventLogV2.promptRequestRecovery(command.sessionId);
41545
+ const replay = await sessions.loadSessionEventsV2(loadOptions, command.eventLimit, command.cursor);
41529
41546
  signal.throwIfAborted();
41530
- const events = replay.updates.map(
41531
- (update, index2) => replayEvent(command.sessionId, replay.startPosition + index2, update)
41547
+ const events = replay.events.map(
41548
+ (event, index) => eventLogV2.event(command.sessionId, replay.startPosition + index, event, "1970-01-01T00:00:00.000Z")
41532
41549
  );
41533
41550
  const tailCursor = events.at(-1)?.eventId ?? "";
41534
41551
  audit.record({
@@ -41538,14 +41555,15 @@ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, dir
41538
41555
  });
41539
41556
  send(socket, {
41540
41557
  events: {
41541
- executingPromptRequest: executingPromptRequest(command.sessionId),
41542
- history: {
41558
+ events: {
41559
+ daemonGenerationId: eventLogV2.daemonGenerationId,
41543
41560
  events,
41544
41561
  nextCursor: replay.nextCursor,
41545
41562
  tailCursor,
41546
41563
  truncated: replay.truncated,
41547
41564
  version: 2
41548
- }
41565
+ },
41566
+ queuedPromptRequests: recovery.queuedPromptRequests
41549
41567
  },
41550
41568
  kind: "session.live-history.v2.page.loaded",
41551
41569
  requestId: command.requestId,
@@ -41995,7 +42013,7 @@ async function executePrompt({
41995
42013
  }
41996
42014
  }
41997
42015
  const stream = activateAttempt();
41998
- eventLogV2.started(command.sessionId, command.commandId, attemptId, stream.epoch);
42016
+ const lifecycleV2 = eventLogV2.started(command.sessionId, command.commandId, attemptId, stream.epoch);
41999
42017
  if (!prepared.prompted) {
42000
42018
  const listing = await directories.list(config2.bindingId, command.directoryId, signal);
42001
42019
  publisher.publish(command.sessionId, {
@@ -42032,6 +42050,7 @@ async function executePrompt({
42032
42050
  commandId: command.commandId,
42033
42051
  cwd: resolved.cwd,
42034
42052
  images: attachments.images,
42053
+ lifecycleV2,
42035
42054
  prompt: command.prompt,
42036
42055
  resources: attachments.resources,
42037
42056
  sessionId: command.sessionId,
@@ -42047,6 +42066,7 @@ async function executePrompt({
42047
42066
  cwd: resolved.cwd,
42048
42067
  disposition: availability.disposition,
42049
42068
  images: attachments.images,
42069
+ lifecycleV2,
42050
42070
  onActivity: events.recordActivity,
42051
42071
  onNarration: events.recordNarration,
42052
42072
  onText: events.recordText,
@@ -42461,7 +42481,7 @@ function createDaemonCommandHandler({
42461
42481
  audit,
42462
42482
  diagnostics,
42463
42483
  sessions,
42464
- eventLogV2.executingPromptRequest,
42484
+ eventLogV2,
42465
42485
  signal
42466
42486
  );
42467
42487
  return;
@@ -43134,10 +43154,6 @@ import { WebSocket as WebSocket9 } from "undici";
43134
43154
  var MAX_BUFFERED_BYTES = 32 * 1024 * 1024;
43135
43155
  var DaemonSessionEventPublisher = class {
43136
43156
  #socket = null;
43137
- #store;
43138
- constructor(store) {
43139
- this.#store = store;
43140
- }
43141
43157
  connect = (socket) => {
43142
43158
  this.#socket = socket;
43143
43159
  };
@@ -43189,7 +43205,6 @@ var DaemonSessionEventPublisher = class {
43189
43205
  }
43190
43206
  };
43191
43207
  publishV2 = (event) => {
43192
- this.#store.appendExecutingPromptEventV2(event);
43193
43208
  const socket = this.#socket;
43194
43209
  if (socket === null || socket.readyState !== WebSocket9.OPEN) {
43195
43210
  return;
@@ -43216,7 +43231,7 @@ var SystemDaemonTimer = class {
43216
43231
  var systemDaemonTimer = new SystemDaemonTimer();
43217
43232
 
43218
43233
  // src/session-event-log-v2.ts
43219
- var EXECUTING_PROMPT_EVENT_LIMIT = 1e4;
43234
+ import { createHash as createHash6, randomUUID as randomUUID7 } from "node:crypto";
43220
43235
  function promptContent(command) {
43221
43236
  const content = [];
43222
43237
  if (command.prompt.length > 0) {
@@ -43240,176 +43255,59 @@ function promptContent(command) {
43240
43255
  }
43241
43256
  return content;
43242
43257
  }
43258
+ function sessionEventV2(daemonGenerationId, sessionId, position, event, recordedAt) {
43259
+ const sessionPrefix = createHash6("sha256").update(sessionId).digest("hex").slice(0, 16);
43260
+ return {
43261
+ eventId: `event-${daemonGenerationId}-${sessionPrefix}-${position.toString().padStart(16, "0")}`,
43262
+ ...event,
43263
+ position: position.toString(),
43264
+ provenance: { kind: "original" },
43265
+ recordedAt,
43266
+ sessionId
43267
+ };
43268
+ }
43243
43269
  var DaemonSessionEventLogV2 = class {
43244
- #positions = /* @__PURE__ */ new Map();
43245
- #requests = /* @__PURE__ */ new Map();
43246
- #loadedRequestSessions = /* @__PURE__ */ new Set();
43270
+ daemonGenerationId = randomUUID7();
43247
43271
  #publisher;
43248
- #store;
43249
- constructor(publisher, store) {
43272
+ #queued = /* @__PURE__ */ new Map();
43273
+ constructor(publisher) {
43250
43274
  this.#publisher = publisher;
43251
- this.#store = store;
43252
43275
  }
43253
- #loadStoredEvents = (sessionId) => {
43254
- const stored = this.#store.readExecutingPromptEventsV2(sessionId);
43255
- const lastPosition = stored.at(-1)?.position;
43256
- if (lastPosition !== void 0) {
43257
- this.#positions.set(sessionId, Number(lastPosition));
43258
- }
43259
- return stored;
43260
- };
43261
- #loadRequests = (sessionId) => {
43262
- if (this.#loadedRequestSessions.has(sessionId)) {
43263
- return;
43264
- }
43265
- for (const event of this.#loadStoredEvents(sessionId)) {
43266
- if (event.type === "acp") {
43267
- continue;
43268
- }
43269
- const payload = event.payload;
43270
- if (payload.kind === "prompt.requested") {
43271
- this.#requests.set(payload.commandId, {
43272
- commandId: payload.commandId,
43273
- kind: "requested",
43274
- sessionId
43275
- });
43276
- continue;
43277
- }
43278
- if ("event" in payload) {
43279
- continue;
43280
- }
43281
- if (!("commandId" in payload)) {
43282
- continue;
43283
- }
43284
- const state = this.#requests.get(payload.commandId);
43285
- if (state === void 0) {
43286
- continue;
43287
- }
43288
- if (payload.kind === "prompt.started") {
43289
- this.#requests.set(payload.commandId, {
43290
- attemptId: payload.attemptId,
43291
- commandId: payload.commandId,
43292
- epoch: payload.epoch,
43293
- kind: "executing",
43294
- sessionId
43295
- });
43296
- } else if (payload.kind === "prompt.completed" || payload.kind === "prompt.failed" || payload.kind === "prompt.failed-before-start") {
43297
- this.#requests.delete(payload.commandId);
43298
- }
43299
- }
43300
- this.#loadedRequestSessions.add(sessionId);
43301
- };
43302
- #append = (sessionId, payload) => {
43303
- this.#loadRequests(sessionId);
43304
- const position = (this.#positions.get(sessionId) ?? 0) + 1;
43305
- const event = {
43306
- eventId: `event-${crypto.randomUUID()}`,
43307
- ...payload,
43308
- position: position.toString(),
43309
- provenance: { kind: "original" },
43310
- recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
43311
- sessionId
43312
- };
43313
- this.#publisher.publishV2(event);
43314
- this.#positions.set(sessionId, position);
43315
- return event;
43316
- };
43317
43276
  requested = (command) => {
43318
- const content = promptContent(command);
43319
- this.#append(command.sessionId, {
43320
- payload: { commandId: command.commandId, content, kind: "prompt.requested" },
43321
- type: "lifecycle-metadata"
43322
- });
43323
- this.#requests.set(command.commandId, {
43277
+ this.#queued.set(command.commandId, {
43324
43278
  commandId: command.commandId,
43325
- kind: "requested",
43279
+ content: promptContent(command),
43326
43280
  sessionId: command.sessionId
43327
43281
  });
43328
43282
  };
43329
43283
  started = (sessionId, commandId, attemptId, epoch) => {
43330
- this.#loadRequests(sessionId);
43331
- const request = this.#requests.get(commandId);
43332
- if (request?.sessionId !== sessionId) {
43333
- return;
43334
- }
43335
- this.#append(sessionId, {
43336
- payload: { attemptId, commandId, epoch, kind: "prompt.started" },
43337
- type: "lifecycle-metadata"
43338
- });
43339
- this.#requests.set(commandId, {
43340
- attemptId,
43341
- commandId,
43342
- epoch,
43343
- kind: "executing",
43344
- sessionId
43345
- });
43346
- };
43347
- record = (sessionId, payload) => {
43348
- this.#loadRequests(sessionId);
43349
- this.#append(sessionId, payload);
43350
- };
43351
- #clearCompletedSession = (sessionId) => {
43352
- if (![...this.#requests.values()].some((request) => request.sessionId === sessionId)) {
43353
- this.#store.clearExecutingPromptEventsV2(sessionId);
43284
+ const request = this.#queued.get(commandId);
43285
+ if (request?.sessionId === sessionId) {
43286
+ this.#queued.delete(commandId);
43287
+ return { attemptId, content: request.content, epoch };
43354
43288
  }
43289
+ throw new Error("The executing prompt was not registered in the V2 queue");
43355
43290
  };
43356
- queueChanged = (sessionId) => {
43357
- this.#append(sessionId, {
43358
- payload: { kind: "session.queue.changed" },
43359
- type: "lifecycle-metadata"
43360
- });
43291
+ record = (sessionId, event, position) => {
43292
+ this.#publisher.publishV2(this.event(sessionId, position, event, (/* @__PURE__ */ new Date()).toISOString()));
43361
43293
  };
43362
- completed = (sessionId, commandId, stopReason) => {
43363
- this.#loadRequests(sessionId);
43364
- this.#append(sessionId, {
43365
- payload: { commandId, kind: "prompt.completed", stopReason },
43366
- type: "lifecycle-metadata"
43367
- });
43368
- this.#requests.delete(commandId);
43369
- this.#clearCompletedSession(sessionId);
43370
- };
43371
- failed = (sessionId, commandId, code, message) => {
43372
- this.#loadRequests(sessionId);
43373
- const request = this.#requests.get(commandId);
43374
- if (request?.kind === "executing" && request.commandId === commandId) {
43375
- this.#append(sessionId, {
43376
- payload: {
43377
- attemptId: request.attemptId,
43378
- code,
43379
- commandId,
43380
- kind: "prompt.failed",
43381
- message
43382
- },
43383
- type: "lifecycle-metadata"
43384
- });
43385
- } else {
43386
- this.#append(sessionId, {
43387
- payload: { code, commandId, kind: "prompt.failed-before-start", message },
43388
- type: "lifecycle-metadata"
43389
- });
43294
+ event = (sessionId, position, event, recordedAt) => sessionEventV2(this.daemonGenerationId, sessionId, position, event, recordedAt);
43295
+ queueChanged = (_sessionId) => void 0;
43296
+ completed = (sessionId, commandId, _stopReason) => {
43297
+ const request = this.#queued.get(commandId);
43298
+ if (request?.sessionId === sessionId) {
43299
+ this.#queued.delete(commandId);
43390
43300
  }
43391
- this.#requests.delete(commandId);
43392
- this.#clearCompletedSession(sessionId);
43393
43301
  };
43394
- executingPromptRequest = (sessionId) => {
43395
- this.#loadRequests(sessionId);
43396
- const request = [...this.#requests.values()].find(
43397
- (candidate) => candidate.sessionId === sessionId && candidate.kind === "executing"
43398
- );
43399
- if (request?.kind !== "executing") {
43400
- return null;
43302
+ failed = (sessionId, commandId, _code, _message) => {
43303
+ const request = this.#queued.get(commandId);
43304
+ if (request?.sessionId === sessionId) {
43305
+ this.#queued.delete(commandId);
43401
43306
  }
43402
- const requestEvents = this.#store.readExecutingPromptEventsV2(sessionId);
43403
- const events = requestEvents.slice(-EXECUTING_PROMPT_EVENT_LIMIT);
43404
- return {
43405
- attemptId: request.attemptId,
43406
- commandId: request.commandId,
43407
- epoch: request.epoch,
43408
- events,
43409
- tailCursor: events.at(-1)?.eventId ?? "",
43410
- truncated: events.length < requestEvents.length
43411
- };
43412
43307
  };
43308
+ promptRequestRecovery = (sessionId) => ({
43309
+ queuedPromptRequests: [...this.#queued.values()].filter((request) => request.sessionId === sessionId).map(({ commandId, content }) => ({ commandId, content }))
43310
+ });
43413
43311
  };
43414
43312
 
43415
43313
  // src/run-daemon.ts
@@ -43460,7 +43358,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
43460
43358
  {
43461
43359
  agentId: agent.id,
43462
43360
  kind: AGENT_INSTALL_REQUEST_KIND,
43463
- requestId: `automatic-integration-${randomUUID7()}`
43361
+ requestId: `automatic-integration-${randomUUID8()}`
43464
43362
  },
43465
43363
  signal
43466
43364
  );
@@ -43483,8 +43381,8 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
43483
43381
  );
43484
43382
  await using externalContent = new LocalExternalContentStore(stateDirectory);
43485
43383
  const operations = new DaemonOperationState();
43486
- const publisher = new DaemonSessionEventPublisher(sessionStore);
43487
- const eventLogV2 = new DaemonSessionEventLogV2(publisher, sessionStore);
43384
+ const publisher = new DaemonSessionEventPublisher();
43385
+ const eventLogV2 = new DaemonSessionEventLogV2(publisher);
43488
43386
  const activeTurns = new DaemonTurnRegistry(operations);
43489
43387
  const recordSessionEvent = (sessionId, event) => {
43490
43388
  publisher.publish(sessionId, activeTurns.recordEvent(event));
@@ -43530,7 +43428,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
43530
43428
  options2.signal
43531
43429
  );
43532
43430
  return cwd === options2.cwd && additionalDirectories.length === options2.additionalDirectories.length && additionalDirectories.every(
43533
- (directory, index2) => directory === options2.additionalDirectories[index2]
43431
+ (directory, index) => directory === options2.additionalDirectories[index]
43534
43432
  );
43535
43433
  });
43536
43434
  }
@@ -43680,7 +43578,7 @@ import { basename as basename7, resolve as resolve7 } from "node:path";
43680
43578
  import { fetch as fetch4 } from "undici";
43681
43579
 
43682
43580
  // src/storage/runtime-installation-store.ts
43683
- import { createHash as createHash8, randomUUID as randomUUID8 } from "node:crypto";
43581
+ import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
43684
43582
  import { mkdir as mkdir5, open as open5, readdir as readdir4, rename as rename4, unlink, writeFile as writeFile4 } from "node:fs/promises";
43685
43583
  import { dirname as dirname6, join as join19, resolve as resolve6 } from "node:path";
43686
43584
  var APPLICATION_ID_PATTERN = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+){1,31}$/;
@@ -43810,10 +43708,10 @@ function parseRelayOrigin(value) {
43810
43708
  return origin;
43811
43709
  }
43812
43710
  function connectionId() {
43813
- return `mcn_${randomUUID8().replaceAll("-", "")}`;
43711
+ return `mcn_${randomUUID9().replaceAll("-", "")}`;
43814
43712
  }
43815
43713
  function installationId() {
43816
- return `min_${randomUUID8().replaceAll("-", "")}`;
43714
+ return `min_${randomUUID9().replaceAll("-", "")}`;
43817
43715
  }
43818
43716
  function channelIndexFileName(channelId) {
43819
43717
  return `mci_${createHash8("sha256").update(channelId).digest("hex")}.json`;
@@ -43925,7 +43823,7 @@ async function readJsonFile(path2, signal, missingCode) {
43925
43823
  async function writeJsonAtomically(path2, value, signal) {
43926
43824
  signal.throwIfAborted();
43927
43825
  const directory = dirname6(path2);
43928
- const temporaryPath = join19(directory, `.${randomUUID8()}.tmp`);
43826
+ const temporaryPath = join19(directory, `.${randomUUID9()}.tmp`);
43929
43827
  try {
43930
43828
  await mkdir5(directory, { mode: 448, recursive: true });
43931
43829
  signal.throwIfAborted();
@@ -44002,16 +43900,16 @@ var RuntimeInstallationStore = class _RuntimeInstallationStore {
44002
43900
  };
44003
43901
  #readConnectionForChannel = async (channelId, signal) => {
44004
43902
  const normalizedChannelId = validateIdentifier(channelId, "invalid_channel_id");
44005
- const index2 = decodeChannelIndex(
43903
+ const index = decodeChannelIndex(
44006
43904
  await readJsonFile(this.channelIndexPath(normalizedChannelId), signal, "connection_not_found")
44007
43905
  );
44008
- if (index2.applicationId !== this.applicationId || index2.installationId !== this.installationId || index2.channelId !== normalizedChannelId) {
43906
+ if (index.applicationId !== this.applicationId || index.installationId !== this.installationId || index.channelId !== normalizedChannelId) {
44009
43907
  throw new RuntimeInstallationStoreError(
44010
43908
  "connection_owner_mismatch",
44011
43909
  "The saved Runtime connection belongs to another installation"
44012
43910
  );
44013
43911
  }
44014
- return await this.readConnection(index2.connectionId, signal);
43912
+ return await this.readConnection(index.connectionId, signal);
44015
43913
  };
44016
43914
  saveConnection = async (input2, signal) => {
44017
43915
  const stored = new VerifiedRuntimeConnection(