@moxt-ai/mobius 0.0.170 → 0.0.172

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 (55) 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 +337 -374
  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/index.js +343 -374
  42. package/dist/index.js.map +4 -4
  43. package/dist/relay-connection/session-event-publisher.d.ts +1 -6
  44. package/dist/relay-connection/session-event-publisher.d.ts.map +1 -1
  45. package/dist/relay-connection/session-event-publisher.js +2 -7
  46. package/dist/relay-connection/session-event-publisher.js.map +1 -1
  47. package/dist/run-daemon.js +2 -2
  48. package/dist/run-daemon.js.map +1 -1
  49. package/dist/runtime.js +340 -377
  50. package/dist/runtime.js.map +4 -4
  51. package/dist/session-event-log-v2.d.ts +18 -9
  52. package/dist/session-event-log-v2.d.ts.map +1 -1
  53. package/dist/session-event-log-v2.js +39 -156
  54. package/dist/session-event-log-v2.js.map +1 -1
  55. package/package.json +1 -1
package/dist/runtime.js CHANGED
@@ -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,
@@ -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
  );
@@ -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
 
@@ -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;
28888
28921
  };
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) {
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
+ }
28931
+ };
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,
@@ -34428,21 +34500,9 @@ var DeletedAcpStoredSession = class extends AcpStoredSessionLookup {
34428
34500
  var MemoryAcpSessionStore = class {
34429
34501
  #sessions = /* @__PURE__ */ new Map();
34430
34502
  #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
34503
  close = () => {
34443
34504
  this.#sessions.clear();
34444
34505
  this.#deleted.clear();
34445
- this.#eventsV2.clear();
34446
34506
  };
34447
34507
  findNative = (agentId, nativeSessionId) => [...this.#sessions.values()].filter(
34448
34508
  (session) => session.agentId === agentId && session.nativeSessionId === nativeSessionId
@@ -34453,7 +34513,6 @@ var MemoryAcpSessionStore = class {
34453
34513
  for (const id of ids) {
34454
34514
  this.#sessions.delete(id);
34455
34515
  this.#deleted.add(id);
34456
- this.#eventsV2.delete(id);
34457
34516
  }
34458
34517
  return ids;
34459
34518
  };
@@ -34466,13 +34525,6 @@ var MemoryAcpSessionStore = class {
34466
34525
  };
34467
34526
  remove = (sessionId) => {
34468
34527
  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
34528
  };
34477
34529
  write = (session) => {
34478
34530
  this.#sessions.set(session.sessionId, session);
@@ -34551,30 +34603,6 @@ var SqliteAcpSessionStore = class {
34551
34603
  close = () => {
34552
34604
  this.#sqliteDatabase.close();
34553
34605
  };
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
34606
  findNative = (agentId, nativeSessionId) => this.#database.select().from(acpSession).where(and(eq(acpSession.agentId, agentId), eq(acpSession.nativeSessionId, nativeSessionId))).all().map(decodeStoredSession);
34579
34607
  list = () => this.#database.select().from(acpSession).orderBy(desc(acpSession.updatedAt)).all().map(decodeStoredSession);
34580
34608
  markDeleted = (agentId, nativeSessionId) => {
@@ -34583,7 +34611,6 @@ var SqliteAcpSessionStore = class {
34583
34611
  this.#database.delete(acpSession).where(and(eq(acpSession.agentId, agentId), eq(acpSession.nativeSessionId, nativeSessionId))).run();
34584
34612
  for (const id of ids) {
34585
34613
  this.#database.insert(deletedAcpSession).values({ sessionId: id }).onConflictDoNothing().run();
34586
- this.#database.delete(sessionEventV2).where(eq(sessionEventV2.sessionId, id)).run();
34587
34614
  }
34588
34615
  });
34589
34616
  return ids;
@@ -34597,12 +34624,8 @@ var SqliteAcpSessionStore = class {
34597
34624
  const row = this.#database.select().from(acpSession).where(eq(acpSession.sessionId, sessionId)).get();
34598
34625
  return row === void 0 ? new MissingAcpStoredSession() : new FoundAcpStoredSession(decodeStoredSession(row));
34599
34626
  };
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
34627
  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
- });
34628
+ this.#database.delete(acpSession).where(eq(acpSession.sessionId, sessionId)).run();
34606
34629
  };
34607
34630
  write = (session) => {
34608
34631
  const value = {
@@ -34672,6 +34695,7 @@ var AgentSession = class _AgentSession {
34672
34695
  #sessionTitle = null;
34673
34696
  #sessionUpdatedAt = "";
34674
34697
  #turn = new IdleAcpTurn();
34698
+ #turnHistory = null;
34675
34699
  constructor(agent, cwd, additionalDirectories, mobiusSessionId, getObserver, store, metrics, contentExternalizer) {
34676
34700
  this.#updates = new AgentUpdateStream((notification) => this.#processUpdate(notification));
34677
34701
  this.#additionalDirectories = [...additionalDirectories];
@@ -34689,7 +34713,8 @@ var AgentSession = class _AgentSession {
34689
34713
  sessionId: () => this.#mobiusSessionId,
34690
34714
  commandId: () => this.#turn.commandId,
34691
34715
  assertNativeSession: (sessionId) => this.assertNativeSession(sessionId),
34692
- observer: getObserver
34716
+ observer: getObserver,
34717
+ recordSessionEventV2: this.#recordLifecycleEventV2
34693
34718
  });
34694
34719
  this.#connection = new AgentConnection(agent, cwd, this);
34695
34720
  this.#contentExternalizer = contentExternalizer;
@@ -34785,13 +34810,10 @@ var AgentSession = class _AgentSession {
34785
34810
  }
34786
34811
  };
34787
34812
  }
34788
- const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
34789
- return await embedLocalHistoryImages(await loaded.history.snapshot(), signal);
34813
+ const history = await this.#completedHistory(signal, "ACP agent exited while loading history");
34814
+ return await embedLocalHistoryImages(await history.snapshot(), signal);
34790
34815
  };
34791
34816
  loadHistoryEventsV2 = async (eventLimit, cursor, signal) => {
34792
- if (!this.#prompted && this.#nativeHistoryOwnership.kind === "fresh-session") {
34793
- return new AcpHistoryReplay().eventPage(eventLimit, cursor);
34794
- }
34795
34817
  if (!this.#capabilities.loadSession) {
34796
34818
  throw new AcpExecutionError(
34797
34819
  "This Agent restores context but does not provide message history.",
@@ -34799,9 +34821,20 @@ var AgentSession = class _AgentSession {
34799
34821
  "native_history_unsupported"
34800
34822
  );
34801
34823
  }
34802
- const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
34803
- return loaded.history.eventPage(eventLimit, cursor);
34824
+ const history = await this.#completedHistory(signal, "ACP agent exited while loading history");
34825
+ return history.eventPage(eventLimit, cursor, this.#turnHistory);
34804
34826
  };
34827
+ async #completedHistory(signal, exitMessage) {
34828
+ if (!this.#prompted && this.#nativeHistoryOwnership.kind === "fresh-session") {
34829
+ if (this.#sessionLoad.kind === "not-requested") {
34830
+ this.#sessionLoad = { history: new AcpHistoryReplay(), kind: "loaded", response: {} };
34831
+ }
34832
+ if (this.#sessionLoad.kind === "loaded") {
34833
+ return this.#sessionLoad.history;
34834
+ }
34835
+ }
34836
+ return (await this.#loadSession(signal, exitMessage)).history;
34837
+ }
34805
34838
  async #loadSession(signal, exitMessage) {
34806
34839
  if (this.#sessionLoad.kind === "loaded") {
34807
34840
  return this.#sessionLoad;
@@ -35285,19 +35318,7 @@ var AgentSession = class _AgentSession {
35285
35318
  if (this.#turn.running) {
35286
35319
  throw new AcpExecutionError("Another prompt is already running in this conversation", {}, "session_busy");
35287
35320
  }
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
- }
35321
+ const completedHistory = this.#capabilities.loadSession ? await this.#completedHistory(options.signal, "ACP agent exited while loading history before a prompt") : null;
35301
35322
  const prompt = this.buildPrompt(options);
35302
35323
  if (this.#sessionTitle === null || this.#sessionTitle.length === 0) {
35303
35324
  this.#sessionTitle = truncate(options.prompt, 500);
@@ -35324,6 +35345,23 @@ var AgentSession = class _AgentSession {
35324
35345
  this.prepareAgentContent
35325
35346
  );
35326
35347
  this.#turn = running;
35348
+ this.#turnHistory = completedHistory === null ? null : new AcpHistoryReplay();
35349
+ const lifecycleV2 = options.lifecycleV2;
35350
+ if (lifecycleV2 !== void 0) {
35351
+ await this.#recordLifecycleEventV2({
35352
+ payload: { commandId: options.commandId, content: lifecycleV2.content, kind: "prompt.requested" },
35353
+ type: "lifecycle-metadata"
35354
+ });
35355
+ await this.#recordLifecycleEventV2({
35356
+ payload: {
35357
+ attemptId: lifecycleV2.attemptId,
35358
+ commandId: options.commandId,
35359
+ epoch: lifecycleV2.epoch,
35360
+ kind: "prompt.started"
35361
+ },
35362
+ type: "lifecycle-metadata"
35363
+ });
35364
+ }
35327
35365
  this.#nativePrompt = {
35328
35366
  commandId: options.commandId,
35329
35367
  previousTurnId: this.#connection.inProcessAgent?.nativeTurnId?.() ?? null
@@ -35378,16 +35416,37 @@ var AgentSession = class _AgentSession {
35378
35416
  this.#lastTerminalCommandId
35379
35417
  )
35380
35418
  );
35419
+ if (lifecycleV2 !== void 0) {
35420
+ await this.#recordLifecycleEventV2({
35421
+ payload: { commandId: options.commandId, kind: "prompt.completed", stopReason: result.stopReason },
35422
+ type: "lifecycle-metadata"
35423
+ });
35424
+ }
35381
35425
  return result;
35382
35426
  } catch (error62) {
35383
35427
  await running.activities.finish();
35428
+ const failure2 = error62 instanceof AcpExecutionError ? error62 : new AcpExecutionError("ACP agent execution failed", { cause: error62 });
35429
+ if (lifecycleV2 !== void 0) {
35430
+ await this.#recordLifecycleEventV2({
35431
+ payload: {
35432
+ attemptId: lifecycleV2.attemptId,
35433
+ code: failure2.code,
35434
+ commandId: options.commandId,
35435
+ kind: "prompt.failed",
35436
+ message: truncate(failure2.message, 500)
35437
+ },
35438
+ type: "lifecycle-metadata"
35439
+ });
35440
+ }
35384
35441
  if (error62 instanceof AcpExecutionError) {
35385
35442
  throw error62;
35386
35443
  }
35387
- throw new AcpExecutionError("ACP agent execution failed", {
35388
- cause: error62
35389
- });
35444
+ throw failure2;
35390
35445
  } finally {
35446
+ if (completedHistory !== null && this.#turnHistory !== null) {
35447
+ await completedHistory.append(this.#turnHistory);
35448
+ }
35449
+ this.#turnHistory = null;
35391
35450
  this.#turn = new IdleAcpTurn();
35392
35451
  }
35393
35452
  };
@@ -35403,41 +35462,80 @@ var AgentSession = class _AgentSession {
35403
35462
  throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
35404
35463
  }
35405
35464
  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)) {
35465
+ const lifecycleV2 = options.lifecycleV2;
35466
+ if (lifecycleV2 !== void 0) {
35467
+ await this.#recordLifecycleEventV2({
35468
+ payload: { commandId: options.commandId, content: lifecycleV2.content, kind: "prompt.requested" },
35469
+ type: "lifecycle-metadata"
35470
+ });
35471
+ await this.#recordLifecycleEventV2({
35472
+ payload: {
35473
+ attemptId: lifecycleV2.attemptId,
35474
+ commandId: options.commandId,
35475
+ epoch: lifecycleV2.epoch,
35476
+ kind: "prompt.started"
35477
+ },
35478
+ type: "lifecycle-metadata"
35479
+ });
35480
+ }
35481
+ try {
35482
+ const response = await this.race(
35483
+ this.#connection.connection.agent.request("_session/steering", {
35484
+ _meta: { steering: { idleBehavior: "promptRequired" } },
35485
+ prompt,
35486
+ sessionId: this.#updates.sessionId()
35487
+ }),
35488
+ "ACP agent exited during steering",
35489
+ options.signal
35490
+ );
35491
+ if (!isRecord4(response)) {
35492
+ throw new AcpExecutionError(
35493
+ "ACP agent returned an invalid steering response",
35494
+ {},
35495
+ "acp_invalid_steering_response"
35496
+ );
35497
+ }
35498
+ const outcome = response["outcome"];
35499
+ if (outcome === "injected" || outcome === "startedNewTurn") {
35500
+ if (lifecycleV2 !== void 0) {
35501
+ await this.#recordLifecycleEventV2({
35502
+ payload: { commandId: options.commandId, kind: "prompt.completed", stopReason: "steered" },
35503
+ type: "lifecycle-metadata"
35504
+ });
35505
+ }
35506
+ return outcome;
35507
+ }
35508
+ if (outcome === "promptRequired") {
35509
+ throw new AcpExecutionError(
35510
+ "The target turn finished before steering could be injected",
35511
+ {},
35512
+ "steering_target_unavailable"
35513
+ );
35514
+ }
35515
+ if (outcome === "failed") {
35516
+ throw new AcpExecutionError("The Agent could not inject steering", {}, "steering_failed");
35517
+ }
35416
35518
  throw new AcpExecutionError(
35417
35519
  "ACP agent returned an invalid steering response",
35418
35520
  {},
35419
35521
  "acp_invalid_steering_response"
35420
35522
  );
35523
+ } catch (error62) {
35524
+ const failure2 = error62 instanceof AcpExecutionError ? error62 : new AcpExecutionError("ACP agent execution failed", { cause: error62 });
35525
+ if (lifecycleV2 !== void 0) {
35526
+ await this.#recordLifecycleEventV2({
35527
+ payload: {
35528
+ attemptId: lifecycleV2.attemptId,
35529
+ code: failure2.code,
35530
+ commandId: options.commandId,
35531
+ kind: "prompt.failed",
35532
+ message: truncate(failure2.message, 500)
35533
+ },
35534
+ type: "lifecycle-metadata"
35535
+ });
35536
+ }
35537
+ throw failure2;
35421
35538
  }
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
35539
  };
35442
35540
  cancel = async () => {
35443
35541
  const capturedProcesses = await this.#connection.captureProcessTree();
@@ -35458,6 +35556,13 @@ var AgentSession = class _AgentSession {
35458
35556
  onElicitation = (request, signal) => this.#interactions.onElicitation(request, signal);
35459
35557
  onElicitationComplete = (notification) => this.#interactions.onElicitationComplete(notification);
35460
35558
  onUpdate = (notification) => this.#updates.receive(notification);
35559
+ #recordLifecycleEventV2 = async (event) => {
35560
+ if (event.type !== "lifecycle-metadata" || this.#sessionLoad.kind !== "loaded") {
35561
+ return;
35562
+ }
35563
+ const position = this.#turnHistory === null ? this.#sessionLoad.history.recordLifecycle(event) : this.#sessionLoad.history.eventCount() + this.#turnHistory.recordLifecycle(event);
35564
+ await this.#getObserver().onSessionEventV2?.(this.#mobiusSessionId, event, position);
35565
+ };
35461
35566
  selectNativeSession = (sessionId) => {
35462
35567
  this.#updates.select(sessionId);
35463
35568
  this.#nativeHistoryOwnership = { kind: "agent-owned" };
@@ -35474,9 +35579,20 @@ var AgentSession = class _AgentSession {
35474
35579
  if (this.#sessionLoad.kind === "capturing") {
35475
35580
  await this.#sessionLoad.history.record(update, rawUpdate);
35476
35581
  } else {
35477
- const onAcpUpdate = this.#getObserver().onAcpUpdate;
35478
- if (onAcpUpdate !== void 0) {
35479
- await onAcpUpdate(this.#mobiusSessionId, rawUpdate);
35582
+ const onSessionEventV2 = this.#getObserver().onSessionEventV2;
35583
+ if (this.#turnHistory !== null) {
35584
+ const completedEventCount = this.#sessionLoad.kind === "loaded" ? this.#sessionLoad.history.eventCount() : 0;
35585
+ await this.#turnHistory.record(update, rawUpdate, async (turnPosition) => {
35586
+ await onSessionEventV2?.(
35587
+ this.#mobiusSessionId,
35588
+ { payload: rawUpdate, type: "acp" },
35589
+ completedEventCount + turnPosition
35590
+ );
35591
+ });
35592
+ } else if (this.#sessionLoad.kind === "loaded") {
35593
+ await this.#sessionLoad.history.record(update, rawUpdate, async (position) => {
35594
+ await onSessionEventV2?.(this.#mobiusSessionId, { payload: rawUpdate, type: "acp" }, position);
35595
+ });
35480
35596
  }
35481
35597
  }
35482
35598
  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")) {
@@ -38255,8 +38371,8 @@ var DaemonAcpObserver = class {
38255
38371
  this.#record = record2;
38256
38372
  this.#recordV2 = recordV2;
38257
38373
  }
38258
- onAcpUpdate = (sessionId, update) => {
38259
- this.#recordV2(sessionId, { payload: update, type: "acp" });
38374
+ onSessionEventV2 = (sessionId, event, position) => {
38375
+ this.#recordV2(sessionId, event, position);
38260
38376
  return Promise.resolve();
38261
38377
  };
38262
38378
  onCommands = (event) => {
@@ -38273,18 +38389,10 @@ var DaemonAcpObserver = class {
38273
38389
  };
38274
38390
  onElicitation = (event) => {
38275
38391
  this.#record(event.sessionId, event);
38276
- this.#recordV2(event.sessionId, {
38277
- payload: { event, kind: "session.elicitation.requested" },
38278
- type: "lifecycle-metadata"
38279
- });
38280
38392
  return Promise.resolve();
38281
38393
  };
38282
38394
  onElicitationResolved = (event) => {
38283
38395
  this.#record(event.sessionId, event);
38284
- this.#recordV2(event.sessionId, {
38285
- payload: { event, kind: "session.elicitation.resolved" },
38286
- type: "lifecycle-metadata"
38287
- });
38288
38396
  return Promise.resolve();
38289
38397
  };
38290
38398
  onInfo = (event) => {
@@ -38293,18 +38401,10 @@ var DaemonAcpObserver = class {
38293
38401
  };
38294
38402
  onPermission = (event) => {
38295
38403
  this.#record(event.sessionId, event);
38296
- this.#recordV2(event.sessionId, {
38297
- payload: { event, kind: "session.permission.requested" },
38298
- type: "lifecycle-metadata"
38299
- });
38300
38404
  return Promise.resolve();
38301
38405
  };
38302
38406
  onPermissionResolved = (event) => {
38303
38407
  this.#record(event.sessionId, event);
38304
- this.#recordV2(event.sessionId, {
38305
- payload: { event, kind: "session.permission.resolved" },
38306
- type: "lifecycle-metadata"
38307
- });
38308
38408
  return Promise.resolve();
38309
38409
  };
38310
38410
  onUsage = (event) => {
@@ -41164,9 +41264,6 @@ async function streamLocalFile(command, send2, signal, workingDirectory, externa
41164
41264
  });
41165
41265
  }
41166
41266
 
41167
- // src/daemon-history-commands.ts
41168
- import { createHash as createHash6 } from "node:crypto";
41169
-
41170
41267
  // src/authorization/resolve-session-directories.ts
41171
41268
  import { basename as basename6 } from "node:path";
41172
41269
  var ResolvedSessionDirectories = class {
@@ -41493,20 +41590,7 @@ async function executeSessionLiveHistoryPageLoad(socket, command, config2, direc
41493
41590
  });
41494
41591
  }
41495
41592
  }
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) {
41593
+ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, directories, audit, diagnostics, sessions, eventLogV2, signal) {
41510
41594
  try {
41511
41595
  const resolved = await resolveSessionDirectories(
41512
41596
  directories,
@@ -41515,20 +41599,18 @@ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, dir
41515
41599
  command.additionalDirectoryIds,
41516
41600
  signal
41517
41601
  );
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
- );
41602
+ const loadOptions = {
41603
+ additionalDirectories: resolved.additionalDirectories,
41604
+ agent: config2.catalog.find(command.agentId),
41605
+ cwd: resolved.cwd,
41606
+ sessionId: command.sessionId,
41607
+ signal
41608
+ };
41609
+ const recovery = eventLogV2.promptRequestRecovery(command.sessionId);
41610
+ const replay = await sessions.loadSessionEventsV2(loadOptions, command.eventLimit, command.cursor);
41529
41611
  signal.throwIfAborted();
41530
- const events = replay.updates.map(
41531
- (update, index2) => replayEvent(command.sessionId, replay.startPosition + index2, update)
41612
+ const events = replay.events.map(
41613
+ (event, index2) => eventLogV2.event(command.sessionId, replay.startPosition + index2, event, "1970-01-01T00:00:00.000Z")
41532
41614
  );
41533
41615
  const tailCursor = events.at(-1)?.eventId ?? "";
41534
41616
  audit.record({
@@ -41538,14 +41620,15 @@ async function executeSessionLiveHistoryV2PageLoad(socket, command, config2, dir
41538
41620
  });
41539
41621
  send(socket, {
41540
41622
  events: {
41541
- executingPromptRequest: executingPromptRequest(command.sessionId),
41542
- history: {
41623
+ events: {
41624
+ daemonGenerationId: eventLogV2.daemonGenerationId,
41543
41625
  events,
41544
41626
  nextCursor: replay.nextCursor,
41545
41627
  tailCursor,
41546
41628
  truncated: replay.truncated,
41547
41629
  version: 2
41548
- }
41630
+ },
41631
+ queuedPromptRequests: recovery.queuedPromptRequests
41549
41632
  },
41550
41633
  kind: "session.live-history.v2.page.loaded",
41551
41634
  requestId: command.requestId,
@@ -41995,7 +42078,7 @@ async function executePrompt({
41995
42078
  }
41996
42079
  }
41997
42080
  const stream = activateAttempt();
41998
- eventLogV2.started(command.sessionId, command.commandId, attemptId, stream.epoch);
42081
+ const lifecycleV2 = eventLogV2.started(command.sessionId, command.commandId, attemptId, stream.epoch);
41999
42082
  if (!prepared.prompted) {
42000
42083
  const listing = await directories.list(config2.bindingId, command.directoryId, signal);
42001
42084
  publisher.publish(command.sessionId, {
@@ -42032,6 +42115,7 @@ async function executePrompt({
42032
42115
  commandId: command.commandId,
42033
42116
  cwd: resolved.cwd,
42034
42117
  images: attachments.images,
42118
+ lifecycleV2,
42035
42119
  prompt: command.prompt,
42036
42120
  resources: attachments.resources,
42037
42121
  sessionId: command.sessionId,
@@ -42047,6 +42131,7 @@ async function executePrompt({
42047
42131
  cwd: resolved.cwd,
42048
42132
  disposition: availability.disposition,
42049
42133
  images: attachments.images,
42134
+ lifecycleV2,
42050
42135
  onActivity: events.recordActivity,
42051
42136
  onNarration: events.recordNarration,
42052
42137
  onText: events.recordText,
@@ -42461,7 +42546,7 @@ function createDaemonCommandHandler({
42461
42546
  audit,
42462
42547
  diagnostics,
42463
42548
  sessions,
42464
- eventLogV2.executingPromptRequest,
42549
+ eventLogV2,
42465
42550
  signal
42466
42551
  );
42467
42552
  return;
@@ -43134,10 +43219,6 @@ import { WebSocket as WebSocket9 } from "undici";
43134
43219
  var MAX_BUFFERED_BYTES = 32 * 1024 * 1024;
43135
43220
  var DaemonSessionEventPublisher = class {
43136
43221
  #socket = null;
43137
- #store;
43138
- constructor(store) {
43139
- this.#store = store;
43140
- }
43141
43222
  connect = (socket) => {
43142
43223
  this.#socket = socket;
43143
43224
  };
@@ -43189,7 +43270,6 @@ var DaemonSessionEventPublisher = class {
43189
43270
  }
43190
43271
  };
43191
43272
  publishV2 = (event) => {
43192
- this.#store.appendExecutingPromptEventV2(event);
43193
43273
  const socket = this.#socket;
43194
43274
  if (socket === null || socket.readyState !== WebSocket9.OPEN) {
43195
43275
  return;
@@ -43216,7 +43296,7 @@ var SystemDaemonTimer = class {
43216
43296
  var systemDaemonTimer = new SystemDaemonTimer();
43217
43297
 
43218
43298
  // src/session-event-log-v2.ts
43219
- var EXECUTING_PROMPT_EVENT_LIMIT = 1e4;
43299
+ import { createHash as createHash6, randomUUID as randomUUID7 } from "node:crypto";
43220
43300
  function promptContent(command) {
43221
43301
  const content = [];
43222
43302
  if (command.prompt.length > 0) {
@@ -43240,176 +43320,59 @@ function promptContent(command) {
43240
43320
  }
43241
43321
  return content;
43242
43322
  }
43323
+ function sessionEventV22(daemonGenerationId, sessionId, position, event, recordedAt) {
43324
+ const sessionPrefix = createHash6("sha256").update(sessionId).digest("hex").slice(0, 16);
43325
+ return {
43326
+ eventId: `event-${daemonGenerationId}-${sessionPrefix}-${position.toString().padStart(16, "0")}`,
43327
+ ...event,
43328
+ position: position.toString(),
43329
+ provenance: { kind: "original" },
43330
+ recordedAt,
43331
+ sessionId
43332
+ };
43333
+ }
43243
43334
  var DaemonSessionEventLogV2 = class {
43244
- #positions = /* @__PURE__ */ new Map();
43245
- #requests = /* @__PURE__ */ new Map();
43246
- #loadedRequestSessions = /* @__PURE__ */ new Set();
43335
+ daemonGenerationId = randomUUID7();
43247
43336
  #publisher;
43248
- #store;
43249
- constructor(publisher, store) {
43337
+ #queued = /* @__PURE__ */ new Map();
43338
+ constructor(publisher) {
43250
43339
  this.#publisher = publisher;
43251
- this.#store = store;
43252
43340
  }
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
43341
  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, {
43342
+ this.#queued.set(command.commandId, {
43324
43343
  commandId: command.commandId,
43325
- kind: "requested",
43344
+ content: promptContent(command),
43326
43345
  sessionId: command.sessionId
43327
43346
  });
43328
43347
  };
43329
43348
  started = (sessionId, commandId, attemptId, epoch) => {
43330
- this.#loadRequests(sessionId);
43331
- const request = this.#requests.get(commandId);
43332
- if (request?.sessionId !== sessionId) {
43333
- return;
43349
+ const request = this.#queued.get(commandId);
43350
+ if (request?.sessionId === sessionId) {
43351
+ this.#queued.delete(commandId);
43352
+ return { attemptId, content: request.content, epoch };
43334
43353
  }
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
- });
43354
+ throw new Error("The executing prompt was not registered in the V2 queue");
43346
43355
  };
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);
43354
- }
43355
- };
43356
- queueChanged = (sessionId) => {
43357
- this.#append(sessionId, {
43358
- payload: { kind: "session.queue.changed" },
43359
- type: "lifecycle-metadata"
43360
- });
43356
+ record = (sessionId, event, position) => {
43357
+ this.#publisher.publishV2(this.event(sessionId, position, event, (/* @__PURE__ */ new Date()).toISOString()));
43361
43358
  };
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
- });
43359
+ event = (sessionId, position, event, recordedAt) => sessionEventV22(this.daemonGenerationId, sessionId, position, event, recordedAt);
43360
+ queueChanged = (_sessionId) => void 0;
43361
+ completed = (sessionId, commandId, _stopReason) => {
43362
+ const request = this.#queued.get(commandId);
43363
+ if (request?.sessionId === sessionId) {
43364
+ this.#queued.delete(commandId);
43390
43365
  }
43391
- this.#requests.delete(commandId);
43392
- this.#clearCompletedSession(sessionId);
43393
43366
  };
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;
43367
+ failed = (sessionId, commandId, _code, _message) => {
43368
+ const request = this.#queued.get(commandId);
43369
+ if (request?.sessionId === sessionId) {
43370
+ this.#queued.delete(commandId);
43401
43371
  }
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
43372
  };
43373
+ promptRequestRecovery = (sessionId) => ({
43374
+ queuedPromptRequests: [...this.#queued.values()].filter((request) => request.sessionId === sessionId).map(({ commandId, content }) => ({ commandId, content }))
43375
+ });
43413
43376
  };
43414
43377
 
43415
43378
  // src/run-daemon.ts
@@ -43460,7 +43423,7 @@ async function installDetectedAgentIntegrations(config2, installations, signal)
43460
43423
  {
43461
43424
  agentId: agent.id,
43462
43425
  kind: AGENT_INSTALL_REQUEST_KIND,
43463
- requestId: `automatic-integration-${randomUUID7()}`
43426
+ requestId: `automatic-integration-${randomUUID8()}`
43464
43427
  },
43465
43428
  signal
43466
43429
  );
@@ -43483,8 +43446,8 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer, opti
43483
43446
  );
43484
43447
  await using externalContent = new LocalExternalContentStore(stateDirectory);
43485
43448
  const operations = new DaemonOperationState();
43486
- const publisher = new DaemonSessionEventPublisher(sessionStore);
43487
- const eventLogV2 = new DaemonSessionEventLogV2(publisher, sessionStore);
43449
+ const publisher = new DaemonSessionEventPublisher();
43450
+ const eventLogV2 = new DaemonSessionEventLogV2(publisher);
43488
43451
  const activeTurns = new DaemonTurnRegistry(operations);
43489
43452
  const recordSessionEvent = (sessionId, event) => {
43490
43453
  publisher.publish(sessionId, activeTurns.recordEvent(event));
@@ -43680,7 +43643,7 @@ import { basename as basename7, resolve as resolve7 } from "node:path";
43680
43643
  import { fetch as fetch4 } from "undici";
43681
43644
 
43682
43645
  // src/storage/runtime-installation-store.ts
43683
- import { createHash as createHash8, randomUUID as randomUUID8 } from "node:crypto";
43646
+ import { createHash as createHash8, randomUUID as randomUUID9 } from "node:crypto";
43684
43647
  import { mkdir as mkdir5, open as open5, readdir as readdir4, rename as rename4, unlink, writeFile as writeFile4 } from "node:fs/promises";
43685
43648
  import { dirname as dirname6, join as join19, resolve as resolve6 } from "node:path";
43686
43649
  var APPLICATION_ID_PATTERN = /^[a-z][a-z0-9]*(?:[.-][a-z0-9]+){1,31}$/;
@@ -43810,10 +43773,10 @@ function parseRelayOrigin(value) {
43810
43773
  return origin;
43811
43774
  }
43812
43775
  function connectionId() {
43813
- return `mcn_${randomUUID8().replaceAll("-", "")}`;
43776
+ return `mcn_${randomUUID9().replaceAll("-", "")}`;
43814
43777
  }
43815
43778
  function installationId() {
43816
- return `min_${randomUUID8().replaceAll("-", "")}`;
43779
+ return `min_${randomUUID9().replaceAll("-", "")}`;
43817
43780
  }
43818
43781
  function channelIndexFileName(channelId) {
43819
43782
  return `mci_${createHash8("sha256").update(channelId).digest("hex")}.json`;
@@ -43925,7 +43888,7 @@ async function readJsonFile(path2, signal, missingCode) {
43925
43888
  async function writeJsonAtomically(path2, value, signal) {
43926
43889
  signal.throwIfAborted();
43927
43890
  const directory = dirname6(path2);
43928
- const temporaryPath = join19(directory, `.${randomUUID8()}.tmp`);
43891
+ const temporaryPath = join19(directory, `.${randomUUID9()}.tmp`);
43929
43892
  try {
43930
43893
  await mkdir5(directory, { mode: 448, recursive: true });
43931
43894
  signal.throwIfAborted();