@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/index.js CHANGED
@@ -3380,11 +3380,11 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
3380
3380
  return payload;
3381
3381
  };
3382
3382
  });
3383
- function handleArrayResult(result, final, index2) {
3383
+ function handleArrayResult(result, final, index) {
3384
3384
  if (result.issues.length) {
3385
- final.issues.push(...prefixIssues(index2, result.issues));
3385
+ final.issues.push(...prefixIssues(index, result.issues));
3386
3386
  }
3387
- final.value[index2] = result.value;
3387
+ final.value[index] = result.value;
3388
3388
  }
3389
3389
  var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
3390
3390
  $ZodType.init(inst, def);
@@ -3995,14 +3995,14 @@ function mergeValues(a, b) {
3995
3995
  return { valid: false, mergeErrorPath: [] };
3996
3996
  }
3997
3997
  const newArray = [];
3998
- for (let index2 = 0; index2 < a.length; index2++) {
3999
- const itemA = a[index2];
4000
- const itemB = b[index2];
3998
+ for (let index = 0; index < a.length; index++) {
3999
+ const itemA = a[index];
4000
+ const itemB = b[index];
4001
4001
  const sharedValue = mergeValues(itemA, itemB);
4002
4002
  if (!sharedValue.valid) {
4003
4003
  return {
4004
4004
  valid: false,
4005
- mergeErrorPath: [index2, ...sharedValue.mergeErrorPath]
4005
+ mergeErrorPath: [index, ...sharedValue.mergeErrorPath]
4006
4006
  };
4007
4007
  }
4008
4008
  newArray.push(sharedValue.data);
@@ -4153,11 +4153,11 @@ function getTupleOptStart(items, key) {
4153
4153
  }
4154
4154
  return 0;
4155
4155
  }
4156
- function handleTupleResult(result, final, index2) {
4156
+ function handleTupleResult(result, final, index) {
4157
4157
  if (result.issues.length) {
4158
- final.issues.push(...prefixIssues(index2, result.issues));
4158
+ final.issues.push(...prefixIssues(index, result.issues));
4159
4159
  }
4160
- final.value[index2] = result.value;
4160
+ final.value[index] = result.value;
4161
4161
  }
4162
4162
  function handleTupleResults(itemResults, final, items, input2, optoutStart) {
4163
4163
  for (let i = 0; i < items.length; i++) {
@@ -18838,7 +18838,7 @@ function detectVersion(schema, defaultTarget) {
18838
18838
  return defaultTarget ?? "draft-2020-12";
18839
18839
  }
18840
18840
  function applyMinItems(items, minItems) {
18841
- return items.map((item, index2) => index2 < minItems ? item : item.optional());
18841
+ return items.map((item, index) => index < minItems ? item : item.optional());
18842
18842
  }
18843
18843
  function decodeJSONPointerSegment(segment) {
18844
18844
  return segment.replace(/~1/g, "/").replace(/~0/g, "~");
@@ -20040,12 +20040,12 @@ var DEFAULT_AGENT_EXECUTION_CONFIGURATION = Object.freeze({
20040
20040
  });
20041
20041
  var sessionConfigurationSelectionsSchema = external_exports.array(sessionConfigurationSelectionSchema).max(100).superRefine((selections, context) => {
20042
20042
  const identifiers = /* @__PURE__ */ new Set();
20043
- for (const [index2, selection] of selections.entries()) {
20043
+ for (const [index, selection] of selections.entries()) {
20044
20044
  if (identifiers.has(selection.configId)) {
20045
20045
  context.addIssue({
20046
20046
  code: "custom",
20047
20047
  message: "Session configuration identifiers must be unique",
20048
- path: [index2, "configId"]
20048
+ path: [index, "configId"]
20049
20049
  });
20050
20050
  }
20051
20051
  identifiers.add(selection.configId);
@@ -21520,10 +21520,7 @@ var lifecycleMetadataV2Schema = external_exports.discriminatedUnion("kind", [
21520
21520
  external_exports.object({ kind: external_exports.literal("session.queue.changed") }).readonly(),
21521
21521
  external_exports.object({ event: sessionPermissionRequestedEventSchema, kind: external_exports.literal("session.permission.requested") }).readonly(),
21522
21522
  external_exports.object({ event: sessionPermissionResolvedEventSchema, kind: external_exports.literal("session.permission.resolved") }).readonly(),
21523
- external_exports.object({
21524
- event: sessionElicitationRequestedEventSchema,
21525
- kind: external_exports.literal("session.elicitation.requested")
21526
- }).readonly(),
21523
+ external_exports.object({ event: sessionElicitationRequestedEventSchema, kind: external_exports.literal("session.elicitation.requested") }).readonly(),
21527
21524
  external_exports.object({ event: sessionElicitationResolvedEventSchema, kind: external_exports.literal("session.elicitation.resolved") }).readonly(),
21528
21525
  external_exports.object({
21529
21526
  ...lifecycleBase,
@@ -21592,12 +21589,12 @@ var sessionExportV2Schema = external_exports.object({
21592
21589
  }).readonly().superRefine((session, context) => {
21593
21590
  let previousPosition = 0n;
21594
21591
  const eventIds = /* @__PURE__ */ new Set();
21595
- for (const [index2, event] of session.events.entries()) {
21592
+ for (const [index, event] of session.events.entries()) {
21596
21593
  if (event.sessionId !== session.sessionId) {
21597
21594
  context.addIssue({
21598
21595
  code: "custom",
21599
21596
  message: "Exported event belongs to a different Session",
21600
- path: ["events", index2, "sessionId"]
21597
+ path: ["events", index, "sessionId"]
21601
21598
  });
21602
21599
  }
21603
21600
  const position = BigInt(event.position);
@@ -21605,14 +21602,14 @@ var sessionExportV2Schema = external_exports.object({
21605
21602
  context.addIssue({
21606
21603
  code: "custom",
21607
21604
  message: "Exported events are not in increasing position order",
21608
- path: ["events", index2, "position"]
21605
+ path: ["events", index, "position"]
21609
21606
  });
21610
21607
  }
21611
21608
  if (eventIds.has(event.eventId)) {
21612
21609
  context.addIssue({
21613
21610
  code: "custom",
21614
21611
  message: "Exported event identities are not unique",
21615
- path: ["events", index2, "eventId"]
21612
+ path: ["events", index, "eventId"]
21616
21613
  });
21617
21614
  }
21618
21615
  previousPosition = position;
@@ -21625,6 +21622,7 @@ var mobiusSessionExportV2Schema = external_exports.object({
21625
21622
  }).readonly();
21626
21623
  var sessionEventEnvelopeV2Schema = external_exports.object({ event: sessionEventV2Schema, kind: external_exports.literal(SESSION_EVENT_V2_KIND) }).readonly();
21627
21624
  var sessionEventLogPageV2Schema = external_exports.object({
21625
+ daemonGenerationId: identifierStringSchema,
21628
21626
  events: external_exports.array(sessionEventV2Schema).max(MAX_EVENT_COUNT).readonly(),
21629
21627
  nextCursor: external_exports.string().min(1).max(512).nullable(),
21630
21628
  tailCursor: external_exports.string().max(512),
@@ -21632,17 +21630,13 @@ var sessionEventLogPageV2Schema = external_exports.object({
21632
21630
  version: external_exports.literal(2)
21633
21631
  }).readonly();
21634
21632
  var nativeEventPageRequestV2Schema = external_exports.object({ cursor: external_exports.string().min(1).max(512).nullable(), eventLimit: external_exports.number().int().min(1).max(1e4) }).readonly();
21635
- var executingPromptRequestEventLogV2Schema = external_exports.object({
21636
- attemptId: identifierStringSchema,
21633
+ var queuedPromptRequestEventLogV2Schema = external_exports.object({
21637
21634
  commandId: identifierStringSchema,
21638
- epoch: identifierStringSchema,
21639
- events: external_exports.array(sessionEventV2Schema).max(MAX_EVENT_COUNT).readonly(),
21640
- tailCursor: external_exports.string().max(512),
21641
- truncated: external_exports.boolean()
21635
+ content: external_exports.array(contentBlockV2Schema).min(1).max(100).readonly()
21642
21636
  }).readonly();
21643
21637
  var nativeSessionEventsV2Schema = external_exports.object({
21644
- executingPromptRequest: executingPromptRequestEventLogV2Schema.nullable(),
21645
- history: sessionEventLogPageV2Schema
21638
+ events: sessionEventLogPageV2Schema,
21639
+ queuedPromptRequests: external_exports.array(queuedPromptRequestEventLogV2Schema).max(MAX_COLLECTION_SIZE).readonly()
21646
21640
  }).readonly();
21647
21641
  function inputValue(value) {
21648
21642
  if (typeof value !== "string") {
@@ -21666,7 +21660,6 @@ function decode5(value, schema) {
21666
21660
  function encode4(value, schema) {
21667
21661
  return JSON.stringify(decode5(value, schema));
21668
21662
  }
21669
- var decodeSessionEventV2 = (value) => decode5(value, sessionEventV2Schema);
21670
21663
  var decodeSessionEventEnvelopeV2 = (value) => decode5(value, sessionEventEnvelopeV2Schema);
21671
21664
  var encodeSessionEventEnvelopeV2 = (value) => encode4(value, sessionEventEnvelopeV2Schema);
21672
21665
  var decodeAcpSessionUpdateV2 = (value) => decode5(value, acpSessionUpdateV2Schema);
@@ -23028,7 +23021,7 @@ function startsWith(bytes, signature, offset = 0) {
23028
23021
  if (bytes.byteLength < offset + signature.byteLength) {
23029
23022
  return false;
23030
23023
  }
23031
- return signature.every((value, index2) => bytes[offset + index2] === value);
23024
+ return signature.every((value, index) => bytes[offset + index] === value);
23032
23025
  }
23033
23026
  function sniffRasterMime(bytes) {
23034
23027
  if (startsWith(bytes, PNG_SIGNATURE)) {
@@ -23156,7 +23149,7 @@ function startsWith2(bytes, signature, offset = 0) {
23156
23149
  if (bytes.byteLength < offset + signature.byteLength) {
23157
23150
  return false;
23158
23151
  }
23159
- return signature.every((value, index2) => bytes[offset + index2] === value);
23152
+ return signature.every((value, index) => bytes[offset + index] === value);
23160
23153
  }
23161
23154
  function sniffVideoMime(bytes) {
23162
23155
  if (startsWith2(bytes, MP4_FILE_TYPE, 4)) {
@@ -23285,10 +23278,10 @@ async function replaceImageMarkers(text2, replace) {
23285
23278
  let cursor = 0;
23286
23279
  let rewritten = "";
23287
23280
  for (const match of matches) {
23288
- const index2 = match.index ?? 0;
23289
- rewritten += text2.slice(cursor, index2);
23281
+ const index = match.index ?? 0;
23282
+ rewritten += text2.slice(cursor, index);
23290
23283
  rewritten += await replace(match[1] ?? "");
23291
- cursor = index2 + match[0].length;
23284
+ cursor = index + match[0].length;
23292
23285
  }
23293
23286
  return `${rewritten}${text2.slice(cursor)}`;
23294
23287
  }
@@ -24481,7 +24474,7 @@ function sessionConfigProtocolForAgent(_agentId) {
24481
24474
 
24482
24475
  // src/acp/session-contracts.ts
24483
24476
  var NullAcpSessionObserver = class {
24484
- onAcpUpdate = (_sessionId, _update) => Promise.resolve();
24477
+ onSessionEventV2 = (_sessionId, _event, _position) => Promise.resolve();
24485
24478
  onCommands = () => Promise.resolve();
24486
24479
  onConfig = () => Promise.resolve();
24487
24480
  onContent = () => Promise.resolve();
@@ -24606,7 +24599,8 @@ function historyContentCharacters(messages) {
24606
24599
  var AcpHistoryReplay = class {
24607
24600
  #activities = /* @__PURE__ */ new Map();
24608
24601
  #messages = [];
24609
- #updates = [];
24602
+ #events = [];
24603
+ #records = [];
24610
24604
  #turnActivityIds = /* @__PURE__ */ new Set();
24611
24605
  #activityTracker = new AcpActivityTracker(
24612
24606
  async (activity2) => {
@@ -24628,8 +24622,10 @@ var AcpHistoryReplay = class {
24628
24622
  #firstMessageIndex = 0;
24629
24623
  #characters = 0;
24630
24624
  #truncated = false;
24631
- record = async (update, rawUpdate) => {
24632
- this.#updates.push(rawUpdate);
24625
+ record = async (update, rawUpdate, onRecorded = () => Promise.resolve()) => {
24626
+ this.#records.push({ kind: "acp", rawUpdate, update });
24627
+ this.#events.push({ payload: rawUpdate, type: "acp" });
24628
+ await onRecorded(this.#events.length);
24633
24629
  if (update.sessionUpdate === "agent_thought_chunk") {
24634
24630
  if (update.content.type === "text") {
24635
24631
  await this.#activityTracker.recordNarrative(
@@ -24638,30 +24634,30 @@ var AcpHistoryReplay = class {
24638
24634
  update.content.text
24639
24635
  );
24640
24636
  }
24641
- return;
24637
+ return this.#events.length;
24642
24638
  }
24643
24639
  if (update.sessionUpdate === "tool_call") {
24644
24640
  await this.#activityTracker.recordToolCall(update);
24645
- return;
24641
+ return this.#events.length;
24646
24642
  }
24647
24643
  if (update.sessionUpdate === "tool_call_update") {
24648
24644
  await this.#activityTracker.recordToolCallUpdate(update);
24649
- return;
24645
+ return this.#events.length;
24650
24646
  }
24651
24647
  if (update.sessionUpdate === "plan") {
24652
24648
  await this.#activityTracker.recordPlan(update);
24653
- return;
24649
+ return this.#events.length;
24654
24650
  }
24655
24651
  if (update.sessionUpdate === "plan_update") {
24656
24652
  await this.#activityTracker.recordPlanUpdate(update);
24657
- return;
24653
+ return this.#events.length;
24658
24654
  }
24659
24655
  if (update.sessionUpdate === "plan_removed") {
24660
24656
  await this.#activityTracker.removePlan(update);
24661
- return;
24657
+ return this.#events.length;
24662
24658
  }
24663
24659
  if (update.sessionUpdate !== "user_message_chunk" && update.sessionUpdate !== "agent_message_chunk") {
24664
- return;
24660
+ return this.#events.length;
24665
24661
  }
24666
24662
  if (update.sessionUpdate === "agent_message_chunk" && isProgressMessage(update)) {
24667
24663
  if (update.content.type === "text") {
@@ -24671,18 +24667,18 @@ var AcpHistoryReplay = class {
24671
24667
  update.content.text
24672
24668
  );
24673
24669
  }
24674
- return;
24670
+ return this.#events.length;
24675
24671
  }
24676
24672
  const role = update.sessionUpdate === "user_message_chunk" ? "user" : "assistant";
24677
24673
  const content = update.content;
24678
24674
  if (role === "assistant" && content.type !== "text") {
24679
24675
  await this.#activityTracker.finishNarrative();
24680
24676
  this.recordAssistantContent(update.messageId ?? null, normalizeContentBlock(content));
24681
- return;
24677
+ return this.#events.length;
24682
24678
  }
24683
24679
  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]`;
24684
24680
  if (text2.length === 0) {
24685
- return;
24681
+ return this.#events.length;
24686
24682
  }
24687
24683
  const previous = this.#messages.at(-1);
24688
24684
  const id = update.messageId ?? null;
@@ -24709,10 +24705,30 @@ var AcpHistoryReplay = class {
24709
24705
  this.#characters += bounded2.length;
24710
24706
  this.#lastMessageId = id;
24711
24707
  this.trimMessages();
24708
+ return this.#events.length;
24709
+ };
24710
+ recordLifecycle = (event) => {
24711
+ if (event.type !== "lifecycle-metadata") {
24712
+ throw new Error("Lifecycle history only accepts lifecycle metadata");
24713
+ }
24714
+ this.#records.push({ event, kind: "lifecycle" });
24715
+ this.#events.push(event);
24716
+ return this.#events.length;
24717
+ };
24718
+ eventCount = () => this.#events.length;
24719
+ append = async (replay) => {
24720
+ for (const record2 of replay.#records) {
24721
+ if (record2.kind === "acp") {
24722
+ await this.record(record2.update, record2.rawUpdate);
24723
+ } else {
24724
+ this.recordLifecycle(record2.event);
24725
+ }
24726
+ }
24712
24727
  };
24713
- eventPage = (eventLimit, cursor) => {
24714
- const parsedCursor = cursor === null ? this.#updates.length : Number(cursor);
24715
- if (!Number.isSafeInteger(parsedCursor) || parsedCursor < 0 || parsedCursor > this.#updates.length) {
24728
+ eventPage = (eventLimit, cursor, appended = null) => {
24729
+ const events = appended === null ? this.#events : [...this.#events, ...appended.#events];
24730
+ const parsedCursor = cursor === null ? events.length : Number(cursor);
24731
+ if (!Number.isSafeInteger(parsedCursor) || parsedCursor < 0 || parsedCursor > events.length) {
24716
24732
  throw new Error("The native event cursor is invalid");
24717
24733
  }
24718
24734
  const endUpdate = parsedCursor;
@@ -24721,7 +24737,7 @@ var AcpHistoryReplay = class {
24721
24737
  nextCursor: startUpdate === 0 ? null : startUpdate.toString(),
24722
24738
  startPosition: startUpdate + 1,
24723
24739
  truncated: startUpdate > 0,
24724
- updates: this.#updates.slice(startUpdate, endUpdate)
24740
+ events: events.slice(startUpdate, endUpdate)
24725
24741
  };
24726
24742
  };
24727
24743
  snapshot = async () => {
@@ -25108,6 +25124,34 @@ var AcpSessionInteractions = class {
25108
25124
  constructor(context) {
25109
25125
  this.#context = context;
25110
25126
  }
25127
+ #notifyPermissionRequested = async (event) => {
25128
+ await this.#context.recordSessionEventV2({
25129
+ payload: { event, kind: "session.permission.requested" },
25130
+ type: "lifecycle-metadata"
25131
+ });
25132
+ await this.#context.observer().onPermission(event);
25133
+ };
25134
+ #notifyPermissionResolved = async (event) => {
25135
+ await this.#context.recordSessionEventV2({
25136
+ payload: { event, kind: "session.permission.resolved" },
25137
+ type: "lifecycle-metadata"
25138
+ });
25139
+ await this.#context.observer().onPermissionResolved(event);
25140
+ };
25141
+ #notifyElicitationRequested = async (event) => {
25142
+ await this.#context.recordSessionEventV2({
25143
+ payload: { event, kind: "session.elicitation.requested" },
25144
+ type: "lifecycle-metadata"
25145
+ });
25146
+ await this.#context.observer().onElicitation(event);
25147
+ };
25148
+ #notifyElicitationResolved = async (event) => {
25149
+ await this.#context.recordSessionEventV2({
25150
+ payload: { event, kind: "session.elicitation.resolved" },
25151
+ type: "lifecycle-metadata"
25152
+ });
25153
+ await this.#context.observer().onElicitationResolved(event);
25154
+ };
25111
25155
  respondPermission = async (options) => {
25112
25156
  const pending = this.#pendingPermissions.get(options.interactionId);
25113
25157
  if (pending === void 0) {
@@ -25133,7 +25177,7 @@ var AcpSessionInteractions = class {
25133
25177
  );
25134
25178
  }
25135
25179
  this.#pendingPermissions.delete(options.interactionId);
25136
- await this.#context.observer().onPermissionResolved({
25180
+ await this.#notifyPermissionResolved({
25137
25181
  interactionId: options.interactionId,
25138
25182
  kind: SESSION_PERMISSION_RESOLVED_KIND,
25139
25183
  optionId: options.outcome === "selected" ? options.optionId : "",
@@ -25173,7 +25217,7 @@ var AcpSessionInteractions = class {
25173
25217
  );
25174
25218
  }
25175
25219
  this.#pendingElicitations.delete(options.interactionId);
25176
- await this.#context.observer().onElicitationResolved({
25220
+ await this.#notifyElicitationResolved({
25177
25221
  action: options.action,
25178
25222
  interactionId: options.interactionId,
25179
25223
  kind: SESSION_ELICITATION_RESOLVED_KIND,
@@ -25202,7 +25246,7 @@ var AcpSessionInteractions = class {
25202
25246
  };
25203
25247
  signal.addEventListener("abort", abort, { once: true });
25204
25248
  try {
25205
- await this.#context.observer().onPermission({
25249
+ await this.#notifyPermissionRequested({
25206
25250
  commandId: this.#context.commandId(),
25207
25251
  interactionId,
25208
25252
  kind: SESSION_PERMISSION_REQUESTED_KIND,
@@ -25247,7 +25291,7 @@ var AcpSessionInteractions = class {
25247
25291
  };
25248
25292
  signal.addEventListener("abort", abort, { once: true });
25249
25293
  try {
25250
- await this.#context.observer().onElicitation({
25294
+ await this.#notifyElicitationRequested({
25251
25295
  accepted: false,
25252
25296
  commandId: this.#context.commandId(),
25253
25297
  elicitationId,
@@ -25271,7 +25315,7 @@ var AcpSessionInteractions = class {
25271
25315
  return;
25272
25316
  }
25273
25317
  this.#acceptedUrlElicitations.delete(notification.elicitationId);
25274
- await this.#context.observer().onElicitationResolved({
25318
+ await this.#notifyElicitationResolved({
25275
25319
  action: "complete",
25276
25320
  interactionId,
25277
25321
  kind: SESSION_ELICITATION_RESOLVED_KIND,
@@ -25284,7 +25328,7 @@ var AcpSessionInteractions = class {
25284
25328
  return;
25285
25329
  }
25286
25330
  this.#pendingPermissions.delete(interactionId);
25287
- await this.#context.observer().onPermissionResolved({
25331
+ await this.#notifyPermissionResolved({
25288
25332
  interactionId,
25289
25333
  kind: SESSION_PERMISSION_RESOLVED_KIND,
25290
25334
  optionId: "",
@@ -25298,7 +25342,7 @@ var AcpSessionInteractions = class {
25298
25342
  return;
25299
25343
  }
25300
25344
  this.#pendingElicitations.delete(interactionId);
25301
- await this.#context.observer().onElicitationResolved({
25345
+ await this.#notifyElicitationResolved({
25302
25346
  action: "cancel",
25303
25347
  interactionId,
25304
25348
  kind: SESSION_ELICITATION_RESOLVED_KIND,
@@ -25317,7 +25361,7 @@ var AcpSessionInteractions = class {
25317
25361
  await this.cancelElicitation(interactionId);
25318
25362
  }
25319
25363
  for (const interactionId of acceptedElicitationIds) {
25320
- await this.#context.observer().onElicitationResolved({
25364
+ await this.#notifyElicitationResolved({
25321
25365
  action: "cancel",
25322
25366
  interactionId,
25323
25367
  kind: SESSION_ELICITATION_RESOLVED_KIND,
@@ -26446,7 +26490,7 @@ function haveSameKeys(left, right) {
26446
26490
  const leftKeys = Object.keys(left);
26447
26491
  const rightKeys = Object.keys(right);
26448
26492
  if (leftKeys.length !== rightKeys.length) return false;
26449
- for (const [index2, key] of leftKeys.entries()) if (key !== rightKeys[index2]) return false;
26493
+ for (const [index, key] of leftKeys.entries()) if (key !== rightKeys[index]) return false;
26450
26494
  return true;
26451
26495
  }
26452
26496
  function mapUpdateSet(table, values) {
@@ -27952,60 +27996,6 @@ function sqliteTableWithCasing(casing) {
27952
27996
  }
27953
27997
  var sqliteTable = sqliteTableWithCasing(void 0);
27954
27998
 
27955
- // ../../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
27956
- var IndexBuilderOn = class {
27957
- static [entityKind] = "SQLiteIndexBuilderOn";
27958
- constructor(name2, unique) {
27959
- this.name = name2;
27960
- this.unique = unique;
27961
- }
27962
- on(...columns) {
27963
- return new IndexBuilder(this.name, columns, this.unique);
27964
- }
27965
- };
27966
- var IndexBuilder = class {
27967
- static [entityKind] = "SQLiteIndexBuilder";
27968
- /** @internal */
27969
- config;
27970
- constructor(name2, columns, unique) {
27971
- this.config = {
27972
- name: name2,
27973
- columns,
27974
- unique,
27975
- where: void 0
27976
- };
27977
- }
27978
- /**
27979
- * Condition for partial index.
27980
- */
27981
- where(condition) {
27982
- this.config.where = condition;
27983
- return this;
27984
- }
27985
- /** @internal */
27986
- build(table) {
27987
- return new Index(this.config, table);
27988
- }
27989
- };
27990
- var Index = class {
27991
- static [entityKind] = "SQLiteIndex";
27992
- config;
27993
- isNameExplicit;
27994
- constructor(config2, table) {
27995
- this.config = {
27996
- ...config2,
27997
- table
27998
- };
27999
- this.isNameExplicit = !!config2.name;
28000
- }
28001
- };
28002
- function index(name2) {
28003
- return new IndexBuilderOn(name2, false);
28004
- }
28005
- function uniqueIndex(name2) {
28006
- return new IndexBuilderOn(name2, true);
28007
- }
28008
-
28009
27999
  // ../../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
28010
28000
  function extractUsedTable(table) {
28011
28001
  if (is(table, SQLiteTable)) return [`${table[Table.Symbol.BaseName]}`];
@@ -28830,8 +28820,8 @@ var SQLiteDialect = class {
28830
28820
  buildJoins(joins) {
28831
28821
  if (!joins || joins.length === 0) return;
28832
28822
  const joinsArray = [];
28833
- if (joins) for (const [index2, joinMeta] of joins.entries()) {
28834
- if (index2 === 0) joinsArray.push(sql` `);
28823
+ if (joins) for (const [index, joinMeta] of joins.entries()) {
28824
+ if (index === 0) joinsArray.push(sql` `);
28835
28825
  const table = joinMeta.table;
28836
28826
  const onSql = joinMeta.on ? sql` on ${joinMeta.on}` : void 0;
28837
28827
  if (is(table, SQLiteTable)) {
@@ -28841,7 +28831,7 @@ var SQLiteDialect = class {
28841
28831
  const alias = tableName === origTableName ? void 0 : joinMeta.alias;
28842
28832
  joinsArray.push(sql`${sql.raw(joinMeta.joinType)} join ${tableSchema ? sql`${sql.identifier(tableSchema)}.` : void 0}${sql.identifier(origTableName)}${alias && sql` ${sql.identifier(alias)}`}${onSql}`);
28843
28833
  } else joinsArray.push(sql`${sql.raw(joinMeta.joinType)} join ${table}${onSql}`);
28844
- if (index2 < joins.length - 1) joinsArray.push(sql` `);
28834
+ if (index < joins.length - 1) joinsArray.push(sql` `);
28845
28835
  }
28846
28836
  return sql.join(joinsArray);
28847
28837
  }
@@ -28850,9 +28840,9 @@ var SQLiteDialect = class {
28850
28840
  }
28851
28841
  buildOrderBy(orderBy) {
28852
28842
  const orderByList = [];
28853
- if (orderBy) for (const [index2, orderByValue] of orderBy.entries()) {
28843
+ if (orderBy) for (const [index, orderByValue] of orderBy.entries()) {
28854
28844
  orderByList.push(orderByValue);
28855
- if (index2 < orderBy.length - 1) orderByList.push(sql`, `);
28845
+ if (index < orderBy.length - 1) orderByList.push(sql`, `);
28856
28846
  }
28857
28847
  return orderByList.length > 0 ? sql` order by ${sql.join(orderByList)}` : void 0;
28858
28848
  }
@@ -28880,9 +28870,9 @@ var SQLiteDialect = class {
28880
28870
  const whereSql = where ? sql` where ${where}` : void 0;
28881
28871
  const havingSql = having ? sql` having ${having}` : void 0;
28882
28872
  const groupByList = [];
28883
- if (groupBy) for (const [index2, groupByValue] of groupBy.entries()) {
28873
+ if (groupBy) for (const [index, groupByValue] of groupBy.entries()) {
28884
28874
  groupByList.push(groupByValue);
28885
- if (index2 < groupBy.length - 1) groupByList.push(sql`, `);
28875
+ if (index < groupBy.length - 1) groupByList.push(sql`, `);
28886
28876
  }
28887
28877
  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}`;
28888
28878
  if (setOperators.length > 0) return this.buildSetOperations(finalQuery, setOperators);
@@ -30174,6 +30164,10 @@ var acpSessionStoreMigrations = [
30174
30164
  {
30175
30165
  "name": "0002_equal_black_queen.sql",
30176
30166
  "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`);"
30167
+ },
30168
+ {
30169
+ "name": "0003_silky_ravenous.sql",
30170
+ "sql": "DROP TABLE `session_event_v2`;"
30177
30171
  }
30178
30172
  ];
30179
30173
 
@@ -30195,21 +30189,6 @@ var deletedAcpSession = sqliteTable("deleted_acp_session", {
30195
30189
  sessionId: text("session_id").primaryKey()
30196
30190
  });
30197
30191
 
30198
- // src/schema/acp-session-store/session-event-v2.ts
30199
- var sessionEventV2 = sqliteTable(
30200
- "session_event_v2",
30201
- {
30202
- eventId: text("event_id").primaryKey(),
30203
- eventJson: text("event_json").notNull(),
30204
- position: integer2("position").notNull(),
30205
- sessionId: text("session_id").notNull()
30206
- },
30207
- (table) => [
30208
- uniqueIndex("session_event_v2_session_position_unique").on(table.sessionId, table.position),
30209
- index("session_event_v2_session_position_index").on(table.sessionId, table.position)
30210
- ]
30211
- );
30212
-
30213
30192
  // src/acp/session-store.ts
30214
30193
  var AcpStoredSession = class {
30215
30194
  additionalDirectories;
@@ -30252,21 +30231,9 @@ var DeletedAcpStoredSession = class extends AcpStoredSessionLookup {
30252
30231
  var MemoryAcpSessionStore = class {
30253
30232
  #sessions = /* @__PURE__ */ new Map();
30254
30233
  #deleted = /* @__PURE__ */ new Set();
30255
- #eventsV2 = /* @__PURE__ */ new Map();
30256
- appendExecutingPromptEventV2 = (event) => {
30257
- const events = this.#eventsV2.get(event.sessionId);
30258
- if (events === void 0) {
30259
- throw new Error("The executing prompt event log has not started");
30260
- }
30261
- events.push(event);
30262
- };
30263
- clearExecutingPromptEventsV2 = (sessionId) => {
30264
- this.#eventsV2.delete(sessionId);
30265
- };
30266
30234
  close = () => {
30267
30235
  this.#sessions.clear();
30268
30236
  this.#deleted.clear();
30269
- this.#eventsV2.clear();
30270
30237
  };
30271
30238
  findNative = (agentId, nativeSessionId) => [...this.#sessions.values()].filter(
30272
30239
  (session) => session.agentId === agentId && session.nativeSessionId === nativeSessionId
@@ -30277,7 +30244,6 @@ var MemoryAcpSessionStore = class {
30277
30244
  for (const id of ids) {
30278
30245
  this.#sessions.delete(id);
30279
30246
  this.#deleted.add(id);
30280
- this.#eventsV2.delete(id);
30281
30247
  }
30282
30248
  return ids;
30283
30249
  };
@@ -30290,13 +30256,6 @@ var MemoryAcpSessionStore = class {
30290
30256
  };
30291
30257
  remove = (sessionId) => {
30292
30258
  this.#sessions.delete(sessionId);
30293
- this.#eventsV2.delete(sessionId);
30294
- };
30295
- readExecutingPromptEventsV2 = (sessionId) => [
30296
- ...this.#eventsV2.get(sessionId) ?? []
30297
- ];
30298
- startExecutingPromptEventsV2 = (sessionId, events) => {
30299
- this.#eventsV2.set(sessionId, [...events]);
30300
30259
  };
30301
30260
  write = (session) => {
30302
30261
  this.#sessions.set(session.sessionId, session);
@@ -30346,15 +30305,15 @@ var SqliteAcpSessionStore = class {
30346
30305
  this.#sqliteDatabase.close();
30347
30306
  throw new Error("The ACP Session database was created by a newer Mobius version");
30348
30307
  }
30349
- for (let index2 = version2; index2 < acpSessionStoreMigrations.length; index2 += 1) {
30350
- const migration = acpSessionStoreMigrations[index2];
30308
+ for (let index = version2; index < acpSessionStoreMigrations.length; index += 1) {
30309
+ const migration = acpSessionStoreMigrations[index];
30351
30310
  if (migration === void 0) {
30352
30311
  throw new Error("The ACP Session migration is unavailable");
30353
30312
  }
30354
30313
  this.#sqliteDatabase.exec("BEGIN IMMEDIATE");
30355
30314
  try {
30356
30315
  this.#sqliteDatabase.exec(migration.sql);
30357
- this.#sqliteDatabase.exec(`PRAGMA user_version = ${index2 + 1}`);
30316
+ this.#sqliteDatabase.exec(`PRAGMA user_version = ${index + 1}`);
30358
30317
  this.#sqliteDatabase.exec("COMMIT");
30359
30318
  } catch (error62) {
30360
30319
  this.#sqliteDatabase.exec("ROLLBACK");
@@ -30375,30 +30334,6 @@ var SqliteAcpSessionStore = class {
30375
30334
  close = () => {
30376
30335
  this.#sqliteDatabase.close();
30377
30336
  };
30378
- appendExecutingPromptEventV2 = (event) => {
30379
- this.#database.insert(sessionEventV2).values({
30380
- eventId: event.eventId,
30381
- eventJson: JSON.stringify(event),
30382
- position: Number(event.position),
30383
- sessionId: event.sessionId
30384
- }).run();
30385
- };
30386
- clearExecutingPromptEventsV2 = (sessionId) => {
30387
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, sessionId)).run();
30388
- };
30389
- startExecutingPromptEventsV2 = (sessionId, events) => {
30390
- this.#transaction(() => {
30391
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, sessionId)).run();
30392
- for (const event of events) {
30393
- this.#database.insert(sessionEventV2).values({
30394
- eventId: event.eventId,
30395
- eventJson: JSON.stringify(event),
30396
- position: Number(event.position),
30397
- sessionId: event.sessionId
30398
- }).run();
30399
- }
30400
- });
30401
- };
30402
30337
  findNative = (agentId, nativeSessionId) => this.#database.select().from(acpSession).where(and(eq(acpSession.agentId, agentId), eq(acpSession.nativeSessionId, nativeSessionId))).all().map(decodeStoredSession);
30403
30338
  list = () => this.#database.select().from(acpSession).orderBy(desc(acpSession.updatedAt)).all().map(decodeStoredSession);
30404
30339
  markDeleted = (agentId, nativeSessionId) => {
@@ -30407,7 +30342,6 @@ var SqliteAcpSessionStore = class {
30407
30342
  this.#database.delete(acpSession).where(and(eq(acpSession.agentId, agentId), eq(acpSession.nativeSessionId, nativeSessionId))).run();
30408
30343
  for (const id of ids) {
30409
30344
  this.#database.insert(deletedAcpSession).values({ sessionId: id }).onConflictDoNothing().run();
30410
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, id)).run();
30411
30345
  }
30412
30346
  });
30413
30347
  return ids;
@@ -30421,12 +30355,8 @@ var SqliteAcpSessionStore = class {
30421
30355
  const row = this.#database.select().from(acpSession).where(eq(acpSession.sessionId, sessionId)).get();
30422
30356
  return row === void 0 ? new MissingAcpStoredSession() : new FoundAcpStoredSession(decodeStoredSession(row));
30423
30357
  };
30424
- 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));
30425
30358
  remove = (sessionId) => {
30426
- this.#transaction(() => {
30427
- this.#database.delete(acpSession).where(eq(acpSession.sessionId, sessionId)).run();
30428
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, sessionId)).run();
30429
- });
30359
+ this.#database.delete(acpSession).where(eq(acpSession.sessionId, sessionId)).run();
30430
30360
  };
30431
30361
  write = (session) => {
30432
30362
  const value = {
@@ -30459,7 +30389,7 @@ var RetryableAcpInitializationError = class extends AcpExecutionError {
30459
30389
  }
30460
30390
  };
30461
30391
  function arraysEqual(left, right) {
30462
- return left.length === right.length && left.every((value, index2) => value === right[index2]);
30392
+ return left.length === right.length && left.every((value, index) => value === right[index]);
30463
30393
  }
30464
30394
  function recordsEqual(left, right) {
30465
30395
  const leftEntries = Object.entries(left);
@@ -30496,6 +30426,7 @@ var AgentSession = class _AgentSession {
30496
30426
  #sessionTitle = null;
30497
30427
  #sessionUpdatedAt = "";
30498
30428
  #turn = new IdleAcpTurn();
30429
+ #turnHistory = null;
30499
30430
  constructor(agent, cwd, additionalDirectories, mobiusSessionId, getObserver, store, metrics, contentExternalizer) {
30500
30431
  this.#updates = new AgentUpdateStream((notification) => this.#processUpdate(notification));
30501
30432
  this.#additionalDirectories = [...additionalDirectories];
@@ -30513,7 +30444,8 @@ var AgentSession = class _AgentSession {
30513
30444
  sessionId: () => this.#mobiusSessionId,
30514
30445
  commandId: () => this.#turn.commandId,
30515
30446
  assertNativeSession: (sessionId) => this.assertNativeSession(sessionId),
30516
- observer: getObserver
30447
+ observer: getObserver,
30448
+ recordSessionEventV2: this.#recordLifecycleEventV2
30517
30449
  });
30518
30450
  this.#connection = new AgentConnection(agent, cwd, this);
30519
30451
  this.#contentExternalizer = contentExternalizer;
@@ -30609,13 +30541,10 @@ var AgentSession = class _AgentSession {
30609
30541
  }
30610
30542
  };
30611
30543
  }
30612
- const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
30613
- return await embedLocalHistoryImages(await loaded.history.snapshot(), signal);
30544
+ const history = await this.#completedHistory(signal, "ACP agent exited while loading history");
30545
+ return await embedLocalHistoryImages(await history.snapshot(), signal);
30614
30546
  };
30615
30547
  loadHistoryEventsV2 = async (eventLimit, cursor, signal) => {
30616
- if (!this.#prompted && this.#nativeHistoryOwnership.kind === "fresh-session") {
30617
- return new AcpHistoryReplay().eventPage(eventLimit, cursor);
30618
- }
30619
30548
  if (!this.#capabilities.loadSession) {
30620
30549
  throw new AcpExecutionError(
30621
30550
  "This Agent restores context but does not provide message history.",
@@ -30623,9 +30552,20 @@ var AgentSession = class _AgentSession {
30623
30552
  "native_history_unsupported"
30624
30553
  );
30625
30554
  }
30626
- const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
30627
- return loaded.history.eventPage(eventLimit, cursor);
30555
+ const history = await this.#completedHistory(signal, "ACP agent exited while loading history");
30556
+ return history.eventPage(eventLimit, cursor, this.#turnHistory);
30628
30557
  };
30558
+ async #completedHistory(signal, exitMessage) {
30559
+ if (!this.#prompted && this.#nativeHistoryOwnership.kind === "fresh-session") {
30560
+ if (this.#sessionLoad.kind === "not-requested") {
30561
+ this.#sessionLoad = { history: new AcpHistoryReplay(), kind: "loaded", response: {} };
30562
+ }
30563
+ if (this.#sessionLoad.kind === "loaded") {
30564
+ return this.#sessionLoad.history;
30565
+ }
30566
+ }
30567
+ return (await this.#loadSession(signal, exitMessage)).history;
30568
+ }
30629
30569
  async #loadSession(signal, exitMessage) {
30630
30570
  if (this.#sessionLoad.kind === "loaded") {
30631
30571
  return this.#sessionLoad;
@@ -31109,19 +31049,7 @@ var AgentSession = class _AgentSession {
31109
31049
  if (this.#turn.running) {
31110
31050
  throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
31111
31051
  }
31112
- switch (this.#sessionLoad.kind) {
31113
- case "not-requested":
31114
- break;
31115
- case "loaded":
31116
- this.#sessionLoad = { kind: "not-requested" };
31117
- break;
31118
- case "capturing":
31119
- throw new AcpExecutionError("Session history is still loading", {}, "session_busy");
31120
- default: {
31121
- const unexpected = this.#sessionLoad;
31122
- throw new Error(`Unexpected Session load state: ${JSON.stringify(unexpected)}`);
31123
- }
31124
- }
31052
+ const completedHistory = this.#capabilities.loadSession ? await this.#completedHistory(options.signal, "ACP agent exited while loading history before a prompt") : null;
31125
31053
  const prompt = this.buildPrompt(options);
31126
31054
  if (this.#sessionTitle === null || this.#sessionTitle.length === 0) {
31127
31055
  this.#sessionTitle = truncate2(options.prompt, 500);
@@ -31148,6 +31076,23 @@ var AgentSession = class _AgentSession {
31148
31076
  this.prepareAgentContent
31149
31077
  );
31150
31078
  this.#turn = running;
31079
+ this.#turnHistory = completedHistory === null ? null : new AcpHistoryReplay();
31080
+ const lifecycleV2 = options.lifecycleV2;
31081
+ if (lifecycleV2 !== void 0) {
31082
+ await this.#recordLifecycleEventV2({
31083
+ payload: { commandId: options.commandId, content: lifecycleV2.content, kind: "prompt.requested" },
31084
+ type: "lifecycle-metadata"
31085
+ });
31086
+ await this.#recordLifecycleEventV2({
31087
+ payload: {
31088
+ attemptId: lifecycleV2.attemptId,
31089
+ commandId: options.commandId,
31090
+ epoch: lifecycleV2.epoch,
31091
+ kind: "prompt.started"
31092
+ },
31093
+ type: "lifecycle-metadata"
31094
+ });
31095
+ }
31151
31096
  this.#nativePrompt = {
31152
31097
  commandId: options.commandId,
31153
31098
  previousTurnId: this.#connection.inProcessAgent?.nativeTurnId?.() ?? null
@@ -31202,16 +31147,37 @@ var AgentSession = class _AgentSession {
31202
31147
  this.#lastTerminalCommandId
31203
31148
  )
31204
31149
  );
31150
+ if (lifecycleV2 !== void 0) {
31151
+ await this.#recordLifecycleEventV2({
31152
+ payload: { commandId: options.commandId, kind: "prompt.completed", stopReason: result.stopReason },
31153
+ type: "lifecycle-metadata"
31154
+ });
31155
+ }
31205
31156
  return result;
31206
31157
  } catch (error62) {
31207
31158
  await running.activities.finish();
31159
+ const failure2 = error62 instanceof AcpExecutionError ? error62 : new AcpExecutionError("ACP agent execution failed", { cause: error62 });
31160
+ if (lifecycleV2 !== void 0) {
31161
+ await this.#recordLifecycleEventV2({
31162
+ payload: {
31163
+ attemptId: lifecycleV2.attemptId,
31164
+ code: failure2.code,
31165
+ commandId: options.commandId,
31166
+ kind: "prompt.failed",
31167
+ message: truncate2(failure2.message, 500)
31168
+ },
31169
+ type: "lifecycle-metadata"
31170
+ });
31171
+ }
31208
31172
  if (error62 instanceof AcpExecutionError) {
31209
31173
  throw error62;
31210
31174
  }
31211
- throw new AcpExecutionError("ACP agent execution failed", {
31212
- cause: error62
31213
- });
31175
+ throw failure2;
31214
31176
  } finally {
31177
+ if (completedHistory !== null && this.#turnHistory !== null) {
31178
+ await completedHistory.append(this.#turnHistory);
31179
+ }
31180
+ this.#turnHistory = null;
31215
31181
  this.#turn = new IdleAcpTurn();
31216
31182
  }
31217
31183
  };
@@ -31227,41 +31193,80 @@ var AgentSession = class _AgentSession {
31227
31193
  throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
31228
31194
  }
31229
31195
  const prompt = this.buildPrompt(options);
31230
- const response = await this.race(
31231
- this.#connection.connection.agent.request("_session/steering", {
31232
- _meta: { steering: { idleBehavior: "promptRequired" } },
31233
- prompt,
31234
- sessionId: this.#updates.sessionId()
31235
- }),
31236
- "ACP agent exited during steering",
31237
- options.signal
31238
- );
31239
- if (!isRecord4(response)) {
31196
+ const lifecycleV2 = options.lifecycleV2;
31197
+ if (lifecycleV2 !== void 0) {
31198
+ await this.#recordLifecycleEventV2({
31199
+ payload: { commandId: options.commandId, content: lifecycleV2.content, kind: "prompt.requested" },
31200
+ type: "lifecycle-metadata"
31201
+ });
31202
+ await this.#recordLifecycleEventV2({
31203
+ payload: {
31204
+ attemptId: lifecycleV2.attemptId,
31205
+ commandId: options.commandId,
31206
+ epoch: lifecycleV2.epoch,
31207
+ kind: "prompt.started"
31208
+ },
31209
+ type: "lifecycle-metadata"
31210
+ });
31211
+ }
31212
+ try {
31213
+ const response = await this.race(
31214
+ this.#connection.connection.agent.request("_session/steering", {
31215
+ _meta: { steering: { idleBehavior: "promptRequired" } },
31216
+ prompt,
31217
+ sessionId: this.#updates.sessionId()
31218
+ }),
31219
+ "ACP agent exited during steering",
31220
+ options.signal
31221
+ );
31222
+ if (!isRecord4(response)) {
31223
+ throw new AcpExecutionError(
31224
+ "ACP agent returned an invalid steering response",
31225
+ {},
31226
+ "acp_invalid_steering_response"
31227
+ );
31228
+ }
31229
+ const outcome = response["outcome"];
31230
+ if (outcome === "injected" || outcome === "startedNewTurn") {
31231
+ if (lifecycleV2 !== void 0) {
31232
+ await this.#recordLifecycleEventV2({
31233
+ payload: { commandId: options.commandId, kind: "prompt.completed", stopReason: "steered" },
31234
+ type: "lifecycle-metadata"
31235
+ });
31236
+ }
31237
+ return outcome;
31238
+ }
31239
+ if (outcome === "promptRequired") {
31240
+ throw new AcpExecutionError(
31241
+ "The target turn finished before steering could be injected",
31242
+ {},
31243
+ "steering_target_unavailable"
31244
+ );
31245
+ }
31246
+ if (outcome === "failed") {
31247
+ throw new AcpExecutionError("The Agent could not inject steering", {}, "steering_failed");
31248
+ }
31240
31249
  throw new AcpExecutionError(
31241
31250
  "ACP agent returned an invalid steering response",
31242
31251
  {},
31243
31252
  "acp_invalid_steering_response"
31244
31253
  );
31254
+ } catch (error62) {
31255
+ const failure2 = error62 instanceof AcpExecutionError ? error62 : new AcpExecutionError("ACP agent execution failed", { cause: error62 });
31256
+ if (lifecycleV2 !== void 0) {
31257
+ await this.#recordLifecycleEventV2({
31258
+ payload: {
31259
+ attemptId: lifecycleV2.attemptId,
31260
+ code: failure2.code,
31261
+ commandId: options.commandId,
31262
+ kind: "prompt.failed",
31263
+ message: truncate2(failure2.message, 500)
31264
+ },
31265
+ type: "lifecycle-metadata"
31266
+ });
31267
+ }
31268
+ throw failure2;
31245
31269
  }
31246
- const outcome = response["outcome"];
31247
- if (outcome === "injected" || outcome === "startedNewTurn") {
31248
- return outcome;
31249
- }
31250
- if (outcome === "promptRequired") {
31251
- throw new AcpExecutionError(
31252
- "The target turn finished before steering could be injected",
31253
- {},
31254
- "steering_target_unavailable"
31255
- );
31256
- }
31257
- if (outcome === "failed") {
31258
- throw new AcpExecutionError("The Agent could not inject steering", {}, "steering_failed");
31259
- }
31260
- throw new AcpExecutionError(
31261
- "ACP agent returned an invalid steering response",
31262
- {},
31263
- "acp_invalid_steering_response"
31264
- );
31265
31270
  };
31266
31271
  cancel = async () => {
31267
31272
  const capturedProcesses = await this.#connection.captureProcessTree();
@@ -31282,6 +31287,13 @@ var AgentSession = class _AgentSession {
31282
31287
  onElicitation = (request, signal) => this.#interactions.onElicitation(request, signal);
31283
31288
  onElicitationComplete = (notification) => this.#interactions.onElicitationComplete(notification);
31284
31289
  onUpdate = (notification) => this.#updates.receive(notification);
31290
+ #recordLifecycleEventV2 = async (event) => {
31291
+ if (event.type !== "lifecycle-metadata" || this.#sessionLoad.kind !== "loaded") {
31292
+ return;
31293
+ }
31294
+ const position = this.#turnHistory === null ? this.#sessionLoad.history.recordLifecycle(event) : this.#sessionLoad.history.eventCount() + this.#turnHistory.recordLifecycle(event);
31295
+ await this.#getObserver().onSessionEventV2?.(this.#mobiusSessionId, event, position);
31296
+ };
31285
31297
  selectNativeSession = (sessionId) => {
31286
31298
  this.#updates.select(sessionId);
31287
31299
  this.#nativeHistoryOwnership = { kind: "agent-owned" };
@@ -31298,9 +31310,20 @@ var AgentSession = class _AgentSession {
31298
31310
  if (this.#sessionLoad.kind === "capturing") {
31299
31311
  await this.#sessionLoad.history.record(update, rawUpdate);
31300
31312
  } else {
31301
- const onAcpUpdate = this.#getObserver().onAcpUpdate;
31302
- if (onAcpUpdate !== void 0) {
31303
- await onAcpUpdate(this.#mobiusSessionId, rawUpdate);
31313
+ const onSessionEventV2 = this.#getObserver().onSessionEventV2;
31314
+ if (this.#turnHistory !== null) {
31315
+ const completedEventCount = this.#sessionLoad.kind === "loaded" ? this.#sessionLoad.history.eventCount() : 0;
31316
+ await this.#turnHistory.record(update, rawUpdate, async (turnPosition) => {
31317
+ await onSessionEventV2?.(
31318
+ this.#mobiusSessionId,
31319
+ { payload: rawUpdate, type: "acp" },
31320
+ completedEventCount + turnPosition
31321
+ );
31322
+ });
31323
+ } else if (this.#sessionLoad.kind === "loaded") {
31324
+ await this.#sessionLoad.history.record(update, rawUpdate, async (position) => {
31325
+ await onSessionEventV2?.(this.#mobiusSessionId, { payload: rawUpdate, type: "acp" }, position);
31326
+ });
31304
31327
  }
31305
31328
  }
31306
31329
  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")) {
@@ -32163,9 +32186,9 @@ var AcpProcessCapacityLock = class {
32163
32186
  return await waiter.completion.promise;
32164
32187
  } finally {
32165
32188
  signal.removeEventListener("abort", waiter.cancel);
32166
- const index2 = this.#waiters.indexOf(waiter);
32167
- if (index2 >= 0) {
32168
- this.#waiters.splice(index2, 1);
32189
+ const index = this.#waiters.indexOf(waiter);
32190
+ if (index >= 0) {
32191
+ this.#waiters.splice(index, 1);
32169
32192
  }
32170
32193
  }
32171
32194
  };
@@ -32994,13 +33017,19 @@ var AgentRuntimeManager = class {
32994
33017
  // src/acp/run-prompt.ts
32995
33018
  async function runAcpPrompt(options) {
32996
33019
  const agentRuntime = new AgentRuntimeManager();
33020
+ const commandId = crypto.randomUUID();
32997
33021
  try {
32998
33022
  return await agentRuntime.runPrompt({
32999
33023
  additionalDirectories: [],
33000
33024
  agent: new LocalAgentDefinition("test-agent", "Test agent", options.agentCommand, options.agentArguments),
33001
33025
  cwd: options.cwd,
33002
- commandId: crypto.randomUUID(),
33026
+ commandId,
33003
33027
  images: [],
33028
+ lifecycleV2: {
33029
+ attemptId: crypto.randomUUID(),
33030
+ content: [{ text: options.prompt, type: "text" }],
33031
+ epoch: crypto.randomUUID()
33032
+ },
33004
33033
  onActivity: options.onActivity,
33005
33034
  ...options.onNarration === void 0 ? {} : { onNarration: options.onNarration },
33006
33035
  onText: options.onText,
@@ -34691,8 +34720,8 @@ function promptInput(prompt) {
34691
34720
  function isCompactPrompt(prompt) {
34692
34721
  return prompt.length === 1 && prompt[0]?.type === "text" && prompt[0].text.trim() === "/compact";
34693
34722
  }
34694
- function steeringPromptInput(prompt) {
34695
- const input2 = [];
34723
+ function steeringPrompt(prompt) {
34724
+ const blocks = [];
34696
34725
  for (const block of prompt) {
34697
34726
  if (typeof block !== "object" || block === null) {
34698
34727
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
@@ -34703,7 +34732,7 @@ function steeringPromptInput(prompt) {
34703
34732
  if (typeof text2 !== "string") {
34704
34733
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
34705
34734
  }
34706
- input2.push({ text: text2, text_elements: [], type: "text" });
34735
+ blocks.push({ content: { text: text2, type: "text" }, input: { text: text2, text_elements: [], type: "text" } });
34707
34736
  continue;
34708
34737
  }
34709
34738
  if (type === "image") {
@@ -34712,7 +34741,10 @@ function steeringPromptInput(prompt) {
34712
34741
  if (typeof data !== "string" || typeof mimeType !== "string") {
34713
34742
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
34714
34743
  }
34715
- input2.push({ type: "image", url: `data:${mimeType};base64,${data}` });
34744
+ blocks.push({
34745
+ content: { data, mimeType, type: "image" },
34746
+ input: { type: "image", url: `data:${mimeType};base64,${data}` }
34747
+ });
34716
34748
  continue;
34717
34749
  }
34718
34750
  if (type === "resource") {
@@ -34720,24 +34752,33 @@ function steeringPromptInput(prompt) {
34720
34752
  if (typeof resource !== "object" || resource === null) {
34721
34753
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
34722
34754
  }
34755
+ const uri = Reflect.get(resource, "uri");
34723
34756
  const text2 = Reflect.get(resource, "text");
34724
- if (text2 !== void 0 && typeof text2 !== "string") {
34757
+ const blob2 = Reflect.get(resource, "blob");
34758
+ if (typeof uri !== "string" || typeof text2 !== "string" && typeof blob2 !== "string" || text2 !== void 0 && typeof text2 !== "string" || blob2 !== void 0 && typeof blob2 !== "string") {
34725
34759
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
34726
34760
  }
34727
- input2.push({ text: text2 ?? "", text_elements: [], type: "text" });
34761
+ blocks.push({
34762
+ content: typeof text2 === "string" ? { resource: { text: text2, uri }, type: "resource" } : { resource: { blob: blob2, uri }, type: "resource" },
34763
+ input: { text: text2 ?? "", text_elements: [], type: "text" }
34764
+ });
34728
34765
  continue;
34729
34766
  }
34730
34767
  if (type === "resource_link") {
34768
+ const name2 = Reflect.get(block, "name");
34731
34769
  const uri = Reflect.get(block, "uri");
34732
- if (typeof uri !== "string") {
34770
+ if (typeof name2 !== "string" || typeof uri !== "string") {
34733
34771
  throw new AcpExecutionError("Codex received an invalid steering prompt", {}, "invalid_request");
34734
34772
  }
34735
- input2.push({ text: `Resource: ${uri}`, text_elements: [], type: "text" });
34773
+ blocks.push({
34774
+ content: { name: name2, type: "resource_link", uri },
34775
+ input: { text: `Resource: ${uri}`, text_elements: [], type: "text" }
34776
+ });
34736
34777
  continue;
34737
34778
  }
34738
34779
  throw new AcpExecutionError("Codex received an unsupported steering prompt", {}, "invalid_request");
34739
34780
  }
34740
- return input2;
34781
+ return blocks;
34741
34782
  }
34742
34783
  function agentMessageUpdate(messageId, text2, phase) {
34743
34784
  return {
@@ -34884,6 +34925,14 @@ var CodexAcpAgent = class {
34884
34925
  if (isCompactPrompt(context.params.prompt)) {
34885
34926
  return await this.#compact(context.signal);
34886
34927
  }
34928
+ const messageId = crypto.randomUUID();
34929
+ for (const content of context.params.prompt) {
34930
+ await this.#emit({
34931
+ content,
34932
+ messageId,
34933
+ sessionUpdate: "user_message_chunk"
34934
+ });
34935
+ }
34887
34936
  return await this.#runTurn(promptInput(context.params.prompt), context.signal);
34888
34937
  }).onRequest(
34889
34938
  "_session/steering",
@@ -35365,14 +35414,22 @@ var CodexAcpAgent = class {
35365
35414
  if (sessionId !== this.#nativeSessionId || active === null || active.turn.id.length === 0) {
35366
35415
  return { outcome: "promptRequired", reason: "noRunningTurn" };
35367
35416
  }
35368
- const input2 = steeringPromptInput(prompt);
35369
- if (input2.length === 0) {
35417
+ const steering = steeringPrompt(prompt);
35418
+ if (steering.length === 0) {
35370
35419
  throw new AcpExecutionError("Codex received an empty steering request", {}, "invalid_request");
35371
35420
  }
35421
+ const messageId = crypto.randomUUID();
35422
+ for (const block of steering) {
35423
+ await this.#emit({ content: block.content, messageId, sessionUpdate: "user_message_chunk" });
35424
+ }
35372
35425
  const response = turnSteerResponseSchema.parse(
35373
35426
  await this.#appServer.request(
35374
35427
  "turn/steer",
35375
- { expectedTurnId: active.turn.id, input: input2, threadId: this.#nativeSessionId },
35428
+ {
35429
+ expectedTurnId: active.turn.id,
35430
+ input: steering.map((block) => block.input),
35431
+ threadId: this.#nativeSessionId
35432
+ },
35376
35433
  AbortSignal.any([signal, AbortSignal.timeout(APPROVAL_TIMEOUT_MILLISECONDS2)])
35377
35434
  )
35378
35435
  );
@@ -36768,9 +36825,9 @@ function comparePrerelease(left, right) {
36768
36825
  if (left.length === 0 || right.length === 0) {
36769
36826
  return left.length === right.length ? 0 : left.length === 0 ? 1 : -1;
36770
36827
  }
36771
- for (let index2 = 0; index2 < Math.max(left.length, right.length); index2 += 1) {
36772
- const leftPart = left[index2];
36773
- const rightPart = right[index2];
36828
+ for (let index = 0; index < Math.max(left.length, right.length); index += 1) {
36829
+ const leftPart = left[index];
36830
+ const rightPart = right[index];
36774
36831
  if (leftPart === void 0 || rightPart === void 0) {
36775
36832
  return leftPart === rightPart ? 0 : leftPart === void 0 ? -1 : 1;
36776
36833
  }
@@ -36795,8 +36852,8 @@ function compareAgentVersions(left, right) {
36795
36852
  if (parsedLeft === null || parsedRight === null) {
36796
36853
  return null;
36797
36854
  }
36798
- for (let index2 = 0; index2 < Math.max(parsedLeft.core.length, parsedRight.core.length); index2 += 1) {
36799
- const difference = (parsedLeft.core[index2] ?? 0) - (parsedRight.core[index2] ?? 0);
36855
+ for (let index = 0; index < Math.max(parsedLeft.core.length, parsedRight.core.length); index += 1) {
36856
+ const difference = (parsedLeft.core[index] ?? 0) - (parsedRight.core[index] ?? 0);
36800
36857
  if (difference !== 0) {
36801
36858
  return Math.sign(difference);
36802
36859
  }
@@ -37539,16 +37596,16 @@ var RuntimeInstallationStore = class _RuntimeInstallationStore {
37539
37596
  };
37540
37597
  #readConnectionForChannel = async (channelId, signal) => {
37541
37598
  const normalizedChannelId = validateIdentifier(channelId, "invalid_channel_id");
37542
- const index2 = decodeChannelIndex(
37599
+ const index = decodeChannelIndex(
37543
37600
  await readJsonFile(this.channelIndexPath(normalizedChannelId), signal, "connection_not_found")
37544
37601
  );
37545
- if (index2.applicationId !== this.applicationId || index2.installationId !== this.installationId || index2.channelId !== normalizedChannelId) {
37602
+ if (index.applicationId !== this.applicationId || index.installationId !== this.installationId || index.channelId !== normalizedChannelId) {
37546
37603
  throw new RuntimeInstallationStoreError(
37547
37604
  "connection_owner_mismatch",
37548
37605
  "The saved Runtime connection belongs to another installation"
37549
37606
  );
37550
37607
  }
37551
- return await this.readConnection(index2.connectionId, signal);
37608
+ return await this.readConnection(index.connectionId, signal);
37552
37609
  };
37553
37610
  saveConnection = async (input2, signal) => {
37554
37611
  const stored = new VerifiedRuntimeConnection(
@@ -37743,16 +37800,16 @@ function hasExactKeys2(value, expectedKeys) {
37743
37800
  }
37744
37801
  function readSingleOption(arguments_, option) {
37745
37802
  const values = [];
37746
- for (let index2 = 0; index2 < arguments_.length; index2 += 1) {
37747
- if (arguments_[index2] !== option) {
37803
+ for (let index = 0; index < arguments_.length; index += 1) {
37804
+ if (arguments_[index] !== option) {
37748
37805
  continue;
37749
37806
  }
37750
- const value = arguments_[index2 + 1];
37807
+ const value = arguments_[index + 1];
37751
37808
  if (value === void 0 || value.startsWith("--")) {
37752
37809
  throw new PairingClientError("invalid_arguments", `${option} requires a value`);
37753
37810
  }
37754
37811
  values.push(value);
37755
- index2 += 1;
37812
+ index += 1;
37756
37813
  }
37757
37814
  if (values.length !== 1) {
37758
37815
  throw new PairingClientError("invalid_arguments", `${option} must be provided exactly once`);
@@ -37760,8 +37817,8 @@ function readSingleOption(arguments_, option) {
37760
37817
  return values[0] ?? "";
37761
37818
  }
37762
37819
  function assertKnownArguments(arguments_) {
37763
- for (let index2 = 0; index2 < arguments_.length; index2 += 2) {
37764
- const option = arguments_[index2];
37820
+ for (let index = 0; index < arguments_.length; index += 2) {
37821
+ const option = arguments_[index];
37765
37822
  if (option !== "--url" && option !== "--code" && option !== "--pairing" && option !== "--workspace") {
37766
37823
  throw new PairingClientError("invalid_arguments", `Unknown pairing option: ${option ?? "missing option"}`);
37767
37824
  }
@@ -38052,7 +38109,7 @@ function isRuntimeRelayRevocation(closeCode, closeReason) {
38052
38109
  }
38053
38110
 
38054
38111
  // src/run-daemon.ts
38055
- import { createHash as createHash8, randomUUID as randomUUID8 } from "node:crypto";
38112
+ import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
38056
38113
  import { join as join19 } from "node:path";
38057
38114
  import { styleText } from "node:util";
38058
38115
 
@@ -39133,8 +39190,8 @@ var DaemonAcpObserver = class {
39133
39190
  this.#record = record2;
39134
39191
  this.#recordV2 = recordV2;
39135
39192
  }
39136
- onAcpUpdate = (sessionId, update) => {
39137
- this.#recordV2(sessionId, { payload: update, type: "acp" });
39193
+ onSessionEventV2 = (sessionId, event, position) => {
39194
+ this.#recordV2(sessionId, event, position);
39138
39195
  return Promise.resolve();
39139
39196
  };
39140
39197
  onCommands = (event) => {
@@ -39151,18 +39208,10 @@ var DaemonAcpObserver = class {
39151
39208
  };
39152
39209
  onElicitation = (event) => {
39153
39210
  this.#record(event.sessionId, event);
39154
- this.#recordV2(event.sessionId, {
39155
- payload: { event, kind: "session.elicitation.requested" },
39156
- type: "lifecycle-metadata"
39157
- });
39158
39211
  return Promise.resolve();
39159
39212
  };
39160
39213
  onElicitationResolved = (event) => {
39161
39214
  this.#record(event.sessionId, event);
39162
- this.#recordV2(event.sessionId, {
39163
- payload: { event, kind: "session.elicitation.resolved" },
39164
- type: "lifecycle-metadata"
39165
- });
39166
39215
  return Promise.resolve();
39167
39216
  };
39168
39217
  onInfo = (event) => {
@@ -39171,18 +39220,10 @@ var DaemonAcpObserver = class {
39171
39220
  };
39172
39221
  onPermission = (event) => {
39173
39222
  this.#record(event.sessionId, event);
39174
- this.#recordV2(event.sessionId, {
39175
- payload: { event, kind: "session.permission.requested" },
39176
- type: "lifecycle-metadata"
39177
- });
39178
39223
  return Promise.resolve();
39179
39224
  };
39180
39225
  onPermissionResolved = (event) => {
39181
39226
  this.#record(event.sessionId, event);
39182
- this.#recordV2(event.sessionId, {
39183
- payload: { event, kind: "session.permission.resolved" },
39184
- type: "lifecycle-metadata"
39185
- });
39186
39227
  return Promise.resolve();
39187
39228
  };
39188
39229
  onUsage = (event) => {
@@ -39289,8 +39330,8 @@ var ACTIVE_TURN_TEXT_CHUNK_LIMIT = Math.floor(SESSION_HISTORY_CHARACTER_LIMIT /
39289
39330
  function boundedRecoveryMessages(messages) {
39290
39331
  const selected = [];
39291
39332
  let remainingCharacters = SESSION_HISTORY_CHARACTER_LIMIT;
39292
- for (let index2 = messages.length - 1; index2 >= 0 && selected.length < SESSION_HISTORY_MESSAGE_LIMIT; index2 -= 1) {
39293
- const message = messages[index2];
39333
+ for (let index = messages.length - 1; index >= 0 && selected.length < SESSION_HISTORY_MESSAGE_LIMIT; index -= 1) {
39334
+ const message = messages[index];
39294
39335
  if (message === void 0) {
39295
39336
  break;
39296
39337
  }
@@ -39431,7 +39472,7 @@ var ActiveDaemonTurn = class {
39431
39472
  ];
39432
39473
  } else {
39433
39474
  this.#timeline = this.#timeline.map(
39434
- (entry, index2) => index2 === target && entry.kind === "message" ? { ...entry, content: new Map([...entry.content, [event.contentId, event.content]]) } : entry
39475
+ (entry, index) => index === target && entry.kind === "message" ? { ...entry, content: new Map([...entry.content, [event.contentId, event.content]]) } : entry
39435
39476
  );
39436
39477
  }
39437
39478
  } else if (event.kind === SESSION_PERMISSION_REQUESTED_KIND || event.kind === SESSION_ELICITATION_REQUESTED_KIND) {
@@ -40457,7 +40498,7 @@ async function readAcpHistory(sessions, directories, bindingId, options, nativeS
40457
40498
  async (directory) => await directories.identify(bindingId, directory, options.signal)
40458
40499
  )
40459
40500
  );
40460
- if (primary.path !== options.cwd || additional.length !== options.additionalDirectories.length || additional.some((directory, index2) => directory.path !== options.additionalDirectories[index2])) {
40501
+ if (primary.path !== options.cwd || additional.length !== options.additionalDirectories.length || additional.some((directory, index) => directory.path !== options.additionalDirectories[index])) {
40461
40502
  throw new AcpExecutionError(
40462
40503
  "The native Session belongs to another workspace.",
40463
40504
  {},
@@ -40590,7 +40631,7 @@ var NativeSessionService = class {
40590
40631
  "native_session_not_found"
40591
40632
  );
40592
40633
  }
40593
- if (source.agentId !== command.agentId || source.cwd !== cwd || source.additionalDirectories.length !== additionalDirectories.length || source.additionalDirectories.some((path2, index2) => path2 !== additionalDirectories[index2])) {
40634
+ if (source.agentId !== command.agentId || source.cwd !== cwd || source.additionalDirectories.length !== additionalDirectories.length || source.additionalDirectories.some((path2, index) => path2 !== additionalDirectories[index])) {
40594
40635
  throw new AcpExecutionError(
40595
40636
  "The source conversation execution target does not match the fork request",
40596
40637
  {},
@@ -40611,8 +40652,8 @@ var NativeSessionService = class {
40611
40652
  signal.throwIfAborted();
40612
40653
  const directory = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
40613
40654
  const ready2 = {
40614
- additionalDirectories: additionalDirectories.map((path2, index2) => ({
40615
- directoryId: command.additionalDirectoryIds[index2] ?? command.directoryId,
40655
+ additionalDirectories: additionalDirectories.map((path2, index) => ({
40656
+ directoryId: command.additionalDirectoryIds[index] ?? command.directoryId,
40616
40657
  name: basename5(path2) || path2
40617
40658
  })),
40618
40659
  agentId: command.agentId,
@@ -40945,7 +40986,7 @@ var NativeSessionService = class {
40945
40986
  resolveTarget = async (command, options, selected) => {
40946
40987
  let cursor = null;
40947
40988
  const visited = /* @__PURE__ */ new Set();
40948
- for (let index2 = 0; index2 < 100; index2 += 1) {
40989
+ for (let index = 0; index < 100; index += 1) {
40949
40990
  const page = await this.#sessions.listNativeSessions(options, cursor);
40950
40991
  const info = page.sessions.find((entry) => entry.sessionId === selected.nativeSessionId);
40951
40992
  if (info !== void 0) {
@@ -40953,7 +40994,7 @@ var NativeSessionService = class {
40953
40994
  if (target === null) {
40954
40995
  throw new LocalAuthorizationError("The selected native session is not authorized");
40955
40996
  }
40956
- if (target.cwd !== selected.cwd || target.additionalDirectories.length !== selected.additionalDirectories.length || target.additionalDirectories.some((path2, index3) => path2 !== selected.additionalDirectories[index3])) {
40997
+ if (target.cwd !== selected.cwd || target.additionalDirectories.length !== selected.additionalDirectories.length || target.additionalDirectories.some((path2, index2) => path2 !== selected.additionalDirectories[index2])) {
40957
40998
  throw new AcpExecutionError(
40958
40999
  "This session's directory changed. Refresh the list before continuing.",
40959
41000
  {},
@@ -42042,9 +42083,6 @@ async function streamLocalFile(command, send2, signal, workingDirectory, externa
42042
42083
  });
42043
42084
  }
42044
42085
 
42045
- // src/daemon-history-commands.ts
42046
- import { createHash as createHash7 } from "node:crypto";
42047
-
42048
42086
  // src/authorization/resolve-session-directories.ts
42049
42087
  import { basename as basename7 } from "node:path";
42050
42088
  var ResolvedSessionDirectories = class {
@@ -42144,8 +42182,8 @@ function selectMessagesBefore(messages, endIndex, messageLimit, characterLimit)
42144
42182
  const selected = [];
42145
42183
  let remainingCharacters = characterLimit;
42146
42184
  let startIndex = endIndex;
42147
- for (let index2 = endIndex - 1; index2 >= 0 && selected.length < messageLimit; index2 -= 1) {
42148
- const message = messages[index2];
42185
+ for (let index = endIndex - 1; index >= 0 && selected.length < messageLimit; index -= 1) {
42186
+ const message = messages[index];
42149
42187
  if (message === void 0) {
42150
42188
  break;
42151
42189
  }
@@ -42155,7 +42193,7 @@ function selectMessagesBefore(messages, endIndex, messageLimit, characterLimit)
42155
42193
  }
42156
42194
  selected.unshift(message);
42157
42195
  remainingCharacters -= characters;
42158
- startIndex = index2;
42196
+ startIndex = index;
42159
42197
  }
42160
42198
  if (selected.length === 0 && endIndex > 0) {
42161
42199
  throw new AcpExecutionError(
@@ -42371,20 +42409,7 @@ async function executeSessionLiveHistoryPageLoad(socket, command, config2, direc
42371
42409
  });
42372
42410
  }
42373
42411
  }
42374
- function replayEvent(sessionId, position, update) {
42375
- const encoded = JSON.stringify(update);
42376
- const eventId = `native-${createHash7("sha256").update(sessionId).update(":").update(position.toString()).update(":").update(encoded).digest("hex")}`;
42377
- return {
42378
- eventId,
42379
- payload: update,
42380
- position: position.toString(),
42381
- provenance: { kind: "original" },
42382
- recordedAt: "1970-01-01T00:00:00.000Z",
42383
- sessionId,
42384
- type: "acp"
42385
- };
42386
- }
42387
- async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, directories, audit, diagnostics, sessions, executingPromptRequest, signal) {
42412
+ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, directories, audit, diagnostics, sessions, eventLogV2, signal) {
42388
42413
  try {
42389
42414
  const resolved = await resolveSessionDirectories(
42390
42415
  directories,
@@ -42393,20 +42418,18 @@ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, dir
42393
42418
  command.additionalDirectoryIds,
42394
42419
  signal
42395
42420
  );
42396
- const replay = await sessions.loadSessionEventsV2(
42397
- {
42398
- additionalDirectories: resolved.additionalDirectories,
42399
- agent: config2.catalog.find(command.agentId),
42400
- cwd: resolved.cwd,
42401
- sessionId: command.sessionId,
42402
- signal
42403
- },
42404
- command.eventLimit,
42405
- command.cursor
42406
- );
42421
+ const loadOptions = {
42422
+ additionalDirectories: resolved.additionalDirectories,
42423
+ agent: config2.catalog.find(command.agentId),
42424
+ cwd: resolved.cwd,
42425
+ sessionId: command.sessionId,
42426
+ signal
42427
+ };
42428
+ const recovery = eventLogV2.promptRequestRecovery(command.sessionId);
42429
+ const replay = await sessions.loadSessionEventsV2(loadOptions, command.eventLimit, command.cursor);
42407
42430
  signal.throwIfAborted();
42408
- const events = replay.updates.map(
42409
- (update, index2) => replayEvent(command.sessionId, replay.startPosition + index2, update)
42431
+ const events = replay.events.map(
42432
+ (event, index) => eventLogV2.event(command.sessionId, replay.startPosition + index, event, "1970-01-01T00:00:00.000Z")
42410
42433
  );
42411
42434
  const tailCursor = events.at(-1)?.eventId ?? "";
42412
42435
  audit.record({
@@ -42416,14 +42439,15 @@ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, dir
42416
42439
  });
42417
42440
  send(socket, {
42418
42441
  events: {
42419
- executingPromptRequest: executingPromptRequest(command.sessionId),
42420
- history: {
42442
+ events: {
42443
+ daemonGenerationId: eventLogV2.daemonGenerationId,
42421
42444
  events,
42422
42445
  nextCursor: replay.nextCursor,
42423
42446
  tailCursor,
42424
42447
  truncated: replay.truncated,
42425
42448
  version: 2
42426
- }
42449
+ },
42450
+ queuedPromptRequests: recovery.queuedPromptRequests
42427
42451
  },
42428
42452
  kind: "session.live-history.v2.page.loaded",
42429
42453
  requestId: command.requestId,
@@ -42873,7 +42897,7 @@ async function executePrompt({
42873
42897
  }
42874
42898
  }
42875
42899
  const stream = activateAttempt();
42876
- eventLogV2.started(command.sessionId, command.commandId, attemptId, stream.epoch);
42900
+ const lifecycleV2 = eventLogV2.started(command.sessionId, command.commandId, attemptId, stream.epoch);
42877
42901
  if (!prepared.prompted) {
42878
42902
  const listing = await directories.list(config2.bindingId, command.directoryId, signal);
42879
42903
  publisher.publish(command.sessionId, {
@@ -42910,6 +42934,7 @@ async function executePrompt({
42910
42934
  commandId: command.commandId,
42911
42935
  cwd: resolved.cwd,
42912
42936
  images: attachments.images,
42937
+ lifecycleV2,
42913
42938
  prompt: command.prompt,
42914
42939
  resources: attachments.resources,
42915
42940
  sessionId: command.sessionId,
@@ -42925,6 +42950,7 @@ async function executePrompt({
42925
42950
  cwd: resolved.cwd,
42926
42951
  disposition: availability.disposition,
42927
42952
  images: attachments.images,
42953
+ lifecycleV2,
42928
42954
  onActivity: events.recordActivity,
42929
42955
  onNarration: events.recordNarration,
42930
42956
  onText: events.recordText,
@@ -43339,7 +43365,7 @@ function createDaemonCommandHandler({
43339
43365
  audit,
43340
43366
  diagnostics,
43341
43367
  sessions,
43342
- eventLogV2.executingPromptRequest,
43368
+ eventLogV2,
43343
43369
  signal
43344
43370
  );
43345
43371
  return;
@@ -43992,10 +44018,6 @@ import { WebSocket as WebSocket9 } from "undici";
43992
44018
  var MAX_BUFFERED_BYTES = 32 * 1024 * 1024;
43993
44019
  var DaemonSessionEventPublisher = class {
43994
44020
  #socket = null;
43995
- #store;
43996
- constructor(store) {
43997
- this.#store = store;
43998
- }
43999
44021
  connect = (socket) => {
44000
44022
  this.#socket = socket;
44001
44023
  };
@@ -44047,7 +44069,6 @@ var DaemonSessionEventPublisher = class {
44047
44069
  }
44048
44070
  };
44049
44071
  publishV2 = (event) => {
44050
- this.#store.appendExecutingPromptEventV2(event);
44051
44072
  const socket = this.#socket;
44052
44073
  if (socket === null || socket.readyState !== WebSocket9.OPEN) {
44053
44074
  return;
@@ -44074,7 +44095,7 @@ var SystemDaemonTimer = class {
44074
44095
  var systemDaemonTimer = new SystemDaemonTimer();
44075
44096
 
44076
44097
  // src/session-event-log-v2.ts
44077
- var EXECUTING_PROMPT_EVENT_LIMIT = 1e4;
44098
+ import { createHash as createHash7, randomUUID as randomUUID8 } from "node:crypto";
44078
44099
  function promptContent(command) {
44079
44100
  const content = [];
44080
44101
  if (command.prompt.length > 0) {
@@ -44098,176 +44119,59 @@ function promptContent(command) {
44098
44119
  }
44099
44120
  return content;
44100
44121
  }
44122
+ function sessionEventV2(daemonGenerationId, sessionId, position, event, recordedAt) {
44123
+ const sessionPrefix = createHash7("sha256").update(sessionId).digest("hex").slice(0, 16);
44124
+ return {
44125
+ eventId: `event-${daemonGenerationId}-${sessionPrefix}-${position.toString().padStart(16, "0")}`,
44126
+ ...event,
44127
+ position: position.toString(),
44128
+ provenance: { kind: "original" },
44129
+ recordedAt,
44130
+ sessionId
44131
+ };
44132
+ }
44101
44133
  var DaemonSessionEventLogV2 = class {
44102
- #positions = /* @__PURE__ */ new Map();
44103
- #requests = /* @__PURE__ */ new Map();
44104
- #loadedRequestSessions = /* @__PURE__ */ new Set();
44134
+ daemonGenerationId = randomUUID8();
44105
44135
  #publisher;
44106
- #store;
44107
- constructor(publisher, store) {
44136
+ #queued = /* @__PURE__ */ new Map();
44137
+ constructor(publisher) {
44108
44138
  this.#publisher = publisher;
44109
- this.#store = store;
44110
44139
  }
44111
- #loadStoredEvents = (sessionId) => {
44112
- const stored = this.#store.readExecutingPromptEventsV2(sessionId);
44113
- const lastPosition = stored.at(-1)?.position;
44114
- if (lastPosition !== void 0) {
44115
- this.#positions.set(sessionId, Number(lastPosition));
44116
- }
44117
- return stored;
44118
- };
44119
- #loadRequests = (sessionId) => {
44120
- if (this.#loadedRequestSessions.has(sessionId)) {
44121
- return;
44122
- }
44123
- for (const event of this.#loadStoredEvents(sessionId)) {
44124
- if (event.type === "acp") {
44125
- continue;
44126
- }
44127
- const payload = event.payload;
44128
- if (payload.kind === "prompt.requested") {
44129
- this.#requests.set(payload.commandId, {
44130
- commandId: payload.commandId,
44131
- kind: "requested",
44132
- sessionId
44133
- });
44134
- continue;
44135
- }
44136
- if ("event" in payload) {
44137
- continue;
44138
- }
44139
- if (!("commandId" in payload)) {
44140
- continue;
44141
- }
44142
- const state = this.#requests.get(payload.commandId);
44143
- if (state === void 0) {
44144
- continue;
44145
- }
44146
- if (payload.kind === "prompt.started") {
44147
- this.#requests.set(payload.commandId, {
44148
- attemptId: payload.attemptId,
44149
- commandId: payload.commandId,
44150
- epoch: payload.epoch,
44151
- kind: "executing",
44152
- sessionId
44153
- });
44154
- } else if (payload.kind === "prompt.completed" || payload.kind === "prompt.failed" || payload.kind === "prompt.failed-before-start") {
44155
- this.#requests.delete(payload.commandId);
44156
- }
44157
- }
44158
- this.#loadedRequestSessions.add(sessionId);
44159
- };
44160
- #append = (sessionId, payload) => {
44161
- this.#loadRequests(sessionId);
44162
- const position = (this.#positions.get(sessionId) ?? 0) + 1;
44163
- const event = {
44164
- eventId: `event-${crypto.randomUUID()}`,
44165
- ...payload,
44166
- position: position.toString(),
44167
- provenance: { kind: "original" },
44168
- recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
44169
- sessionId
44170
- };
44171
- this.#publisher.publishV2(event);
44172
- this.#positions.set(sessionId, position);
44173
- return event;
44174
- };
44175
44140
  requested = (command) => {
44176
- const content = promptContent(command);
44177
- this.#append(command.sessionId, {
44178
- payload: { commandId: command.commandId, content, kind: "prompt.requested" },
44179
- type: "lifecycle-metadata"
44180
- });
44181
- this.#requests.set(command.commandId, {
44141
+ this.#queued.set(command.commandId, {
44182
44142
  commandId: command.commandId,
44183
- kind: "requested",
44143
+ content: promptContent(command),
44184
44144
  sessionId: command.sessionId
44185
44145
  });
44186
44146
  };
44187
44147
  started = (sessionId, commandId, attemptId, epoch) => {
44188
- this.#loadRequests(sessionId);
44189
- const request = this.#requests.get(commandId);
44190
- if (request?.sessionId !== sessionId) {
44191
- return;
44148
+ const request = this.#queued.get(commandId);
44149
+ if (request?.sessionId === sessionId) {
44150
+ this.#queued.delete(commandId);
44151
+ return { attemptId, content: request.content, epoch };
44192
44152
  }
44193
- this.#append(sessionId, {
44194
- payload: { attemptId, commandId, epoch, kind: "prompt.started" },
44195
- type: "lifecycle-metadata"
44196
- });
44197
- this.#requests.set(commandId, {
44198
- attemptId,
44199
- commandId,
44200
- epoch,
44201
- kind: "executing",
44202
- sessionId
44203
- });
44153
+ throw new Error("The executing prompt was not registered in the V2 queue");
44204
44154
  };
44205
- record = (sessionId, payload) => {
44206
- this.#loadRequests(sessionId);
44207
- this.#append(sessionId, payload);
44155
+ record = (sessionId, event, position) => {
44156
+ this.#publisher.publishV2(this.event(sessionId, position, event, (/* @__PURE__ */ new Date()).toISOString()));
44208
44157
  };
44209
- #clearCompletedSession = (sessionId) => {
44210
- if (![...this.#requests.values()].some((request) => request.sessionId === sessionId)) {
44211
- this.#store.clearExecutingPromptEventsV2(sessionId);
44158
+ event = (sessionId, position, event, recordedAt) => sessionEventV2(this.daemonGenerationId, sessionId, position, event, recordedAt);
44159
+ queueChanged = (_sessionId) => void 0;
44160
+ completed = (sessionId, commandId, _stopReason) => {
44161
+ const request = this.#queued.get(commandId);
44162
+ if (request?.sessionId === sessionId) {
44163
+ this.#queued.delete(commandId);
44212
44164
  }
44213
44165
  };
44214
- queueChanged = (sessionId) => {
44215
- this.#append(sessionId, {
44216
- payload: { kind: "session.queue.changed" },
44217
- type: "lifecycle-metadata"
44218
- });
44219
- };
44220
- completed = (sessionId, commandId, stopReason) => {
44221
- this.#loadRequests(sessionId);
44222
- this.#append(sessionId, {
44223
- payload: { commandId, kind: "prompt.completed", stopReason },
44224
- type: "lifecycle-metadata"
44225
- });
44226
- this.#requests.delete(commandId);
44227
- this.#clearCompletedSession(sessionId);
44228
- };
44229
- failed = (sessionId, commandId, code, message) => {
44230
- this.#loadRequests(sessionId);
44231
- const request = this.#requests.get(commandId);
44232
- if (request?.kind === "executing" && request.commandId === commandId) {
44233
- this.#append(sessionId, {
44234
- payload: {
44235
- attemptId: request.attemptId,
44236
- code,
44237
- commandId,
44238
- kind: "prompt.failed",
44239
- message
44240
- },
44241
- type: "lifecycle-metadata"
44242
- });
44243
- } else {
44244
- this.#append(sessionId, {
44245
- payload: { code, commandId, kind: "prompt.failed-before-start", message },
44246
- type: "lifecycle-metadata"
44247
- });
44248
- }
44249
- this.#requests.delete(commandId);
44250
- this.#clearCompletedSession(sessionId);
44251
- };
44252
- executingPromptRequest = (sessionId) => {
44253
- this.#loadRequests(sessionId);
44254
- const request = [...this.#requests.values()].find(
44255
- (candidate) => candidate.sessionId === sessionId && candidate.kind === "executing"
44256
- );
44257
- if (request?.kind !== "executing") {
44258
- return null;
44166
+ failed = (sessionId, commandId, _code, _message) => {
44167
+ const request = this.#queued.get(commandId);
44168
+ if (request?.sessionId === sessionId) {
44169
+ this.#queued.delete(commandId);
44259
44170
  }
44260
- const requestEvents = this.#store.readExecutingPromptEventsV2(sessionId);
44261
- const events = requestEvents.slice(-EXECUTING_PROMPT_EVENT_LIMIT);
44262
- return {
44263
- attemptId: request.attemptId,
44264
- commandId: request.commandId,
44265
- epoch: request.epoch,
44266
- events,
44267
- tailCursor: events.at(-1)?.eventId ?? "",
44268
- truncated: events.length < requestEvents.length
44269
- };
44270
44171
  };
44172
+ promptRequestRecovery = (sessionId) => ({
44173
+ queuedPromptRequests: [...this.#queued.values()].filter((request) => request.sessionId === sessionId).map(({ commandId, content }) => ({ commandId, content }))
44174
+ });
44271
44175
  };
44272
44176
 
44273
44177
  // src/run-daemon.ts
@@ -44318,7 +44222,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
44318
44222
  {
44319
44223
  agentId: agent.id,
44320
44224
  kind: AGENT_INSTALL_REQUEST_KIND,
44321
- requestId: `automatic-integration-${randomUUID8()}`
44225
+ requestId: `automatic-integration-${randomUUID9()}`
44322
44226
  },
44323
44227
  signal
44324
44228
  );
@@ -44341,8 +44245,8 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
44341
44245
  );
44342
44246
  await using externalContent = new LocalExternalContentStore(stateDirectory);
44343
44247
  const operations = new DaemonOperationState();
44344
- const publisher = new DaemonSessionEventPublisher(sessionStore);
44345
- const eventLogV2 = new DaemonSessionEventLogV2(publisher, sessionStore);
44248
+ const publisher = new DaemonSessionEventPublisher();
44249
+ const eventLogV2 = new DaemonSessionEventLogV2(publisher);
44346
44250
  const activeTurns = new DaemonTurnRegistry(operations);
44347
44251
  const recordSessionEvent = (sessionId, event) => {
44348
44252
  publisher.publish(sessionId, activeTurns.recordEvent(event));
@@ -44388,7 +44292,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
44388
44292
  options2.signal
44389
44293
  );
44390
44294
  return cwd === options2.cwd && additionalDirectories.length === options2.additionalDirectories.length && additionalDirectories.every(
44391
- (directory, index2) => directory === options2.additionalDirectories[index2]
44295
+ (directory, index) => directory === options2.additionalDirectories[index]
44392
44296
  );
44393
44297
  });
44394
44298
  }