@moxt-ai/mobius 0.0.142 → 0.0.144

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 (49) hide show
  1. package/dist/acp/agent-query-processes.js +2 -2
  2. package/dist/acp/agent-query-processes.js.map +1 -1
  3. package/dist/acp/agent-runtime-manager.js +4 -4
  4. package/dist/acp/agent-runtime-manager.js.map +1 -1
  5. package/dist/acp/agent-session.d.ts.map +1 -1
  6. package/dist/acp/agent-session.js +37 -34
  7. package/dist/acp/agent-session.js.map +1 -1
  8. package/dist/acp/runtime-operations.d.ts +2 -2
  9. package/dist/acp/runtime-operations.d.ts.map +1 -1
  10. package/dist/acp/runtime-operations.js +2 -2
  11. package/dist/acp/runtime-operations.js.map +1 -1
  12. package/dist/cli.js +594 -419
  13. package/dist/cli.js.map +4 -4
  14. package/dist/daemon-active-turn.d.ts +2 -0
  15. package/dist/daemon-active-turn.d.ts.map +1 -1
  16. package/dist/daemon-active-turn.js +80 -6
  17. package/dist/daemon-active-turn.js.map +1 -1
  18. package/dist/daemon-prompt-executor.d.ts.map +1 -1
  19. package/dist/daemon-prompt-executor.js +25 -41
  20. package/dist/daemon-prompt-executor.js.map +1 -1
  21. package/dist/daemon-turn-registry.d.ts +48 -0
  22. package/dist/daemon-turn-registry.d.ts.map +1 -1
  23. package/dist/index.js +593 -418
  24. package/dist/index.js.map +4 -4
  25. package/dist/native-sessions/codex-history.d.ts.map +1 -1
  26. package/dist/native-sessions/codex-history.js +254 -94
  27. package/dist/native-sessions/codex-history.js.map +1 -1
  28. package/dist/native-sessions/live-history-page.d.ts.map +1 -1
  29. package/dist/native-sessions/live-history-page.js +40 -24
  30. package/dist/native-sessions/live-history-page.js.map +1 -1
  31. package/dist/relay-connection/coalescing-agent-event-publisher.d.ts +32 -0
  32. package/dist/relay-connection/coalescing-agent-event-publisher.d.ts.map +1 -0
  33. package/dist/relay-connection/coalescing-agent-event-publisher.js +116 -0
  34. package/dist/relay-connection/coalescing-agent-event-publisher.js.map +1 -0
  35. package/dist/runtime.js +593 -418
  36. package/dist/runtime.js.map +4 -4
  37. package/package.json +1 -1
  38. package/dist/relay-connection/coalescing-activity-publisher.d.ts +0 -10
  39. package/dist/relay-connection/coalescing-activity-publisher.d.ts.map +0 -1
  40. package/dist/relay-connection/coalescing-activity-publisher.js +0 -54
  41. package/dist/relay-connection/coalescing-activity-publisher.js.map +0 -1
  42. package/dist/relay-connection/coalescing-narration-publisher.d.ts +0 -31
  43. package/dist/relay-connection/coalescing-narration-publisher.d.ts.map +0 -1
  44. package/dist/relay-connection/coalescing-narration-publisher.js +0 -61
  45. package/dist/relay-connection/coalescing-narration-publisher.js.map +0 -1
  46. package/dist/relay-connection/coalescing-text-publisher.d.ts +0 -26
  47. package/dist/relay-connection/coalescing-text-publisher.d.ts.map +0 -1
  48. package/dist/relay-connection/coalescing-text-publisher.js +0 -57
  49. package/dist/relay-connection/coalescing-text-publisher.js.map +0 -1
package/dist/runtime.js CHANGED
@@ -20929,7 +20929,7 @@ var userHistoryMessage = external_exports.strictObject({
20929
20929
  text: external_exports.string().max(SESSION_HISTORY_CHARACTER_LIMIT),
20930
20930
  images: external_exports.array(historyImage).max(8).readonly().optional()
20931
20931
  }).readonly();
20932
- var assistantHistoryMessage = external_exports.strictObject({
20932
+ var assistantHistoryMessageSchema = external_exports.strictObject({
20933
20933
  activities: external_exports.array(nativeMessageActivitySchema).max(100).readonly().default([]),
20934
20934
  content: external_exports.array(displayContentSchema).max(100).readonly().default([]),
20935
20935
  role: external_exports.literal("assistant"),
@@ -20938,7 +20938,7 @@ var assistantHistoryMessage = external_exports.strictObject({
20938
20938
  text: external_exports.string().max(SESSION_HISTORY_CHARACTER_LIMIT),
20939
20939
  images: external_exports.array(historyImage).max(8).readonly().optional()
20940
20940
  }).readonly();
20941
- var historyMessage = external_exports.discriminatedUnion("role", [userHistoryMessage, assistantHistoryMessage]);
20941
+ var historyMessage = external_exports.discriminatedUnion("role", [userHistoryMessage, assistantHistoryMessageSchema]);
20942
20942
  var availableSessionHistoryObjectSchema = external_exports.strictObject({
20943
20943
  status: external_exports.literal("available"),
20944
20944
  messages: external_exports.array(historyMessage).max(SESSION_HISTORY_MESSAGE_LIMIT).readonly(),
@@ -21009,6 +21009,7 @@ var activeTurnSnapshotSchema = external_exports.strictObject({
21009
21009
  truncated: external_exports.boolean(),
21010
21010
  epoch: identifierStringSchema,
21011
21011
  interaction: external_exports.discriminatedUnion("kind", [sessionPermissionRequestedEventSchema, sessionElicitationRequestedEventSchema]).nullable(),
21012
+ messages: external_exports.array(assistantHistoryMessageSchema).max(SESSION_HISTORY_MESSAGE_LIMIT).readonly(),
21012
21013
  sequence: external_exports.number().int().nonnegative(),
21013
21014
  state: external_exports.literal("running")
21014
21015
  }).readonly();
@@ -27921,6 +27922,48 @@ var AgentUpdateStream = class {
27921
27922
  };
27922
27923
  };
27923
27924
 
27925
+ // src/acp/runtime-operations.ts
27926
+ var RuntimeOperations = class {
27927
+ #shutdown = new AbortController();
27928
+ #pending = /* @__PURE__ */ new Set();
27929
+ #closing = null;
27930
+ run = async (options, operation) => {
27931
+ const signal = AbortSignal.any([options.signal, this.#shutdown.signal]);
27932
+ signal.throwIfAborted();
27933
+ const pending = Promise.resolve().then(() => operation({ ...options, signal }));
27934
+ this.#pending.add(pending);
27935
+ try {
27936
+ const result = await pending;
27937
+ signal.throwIfAborted();
27938
+ return result;
27939
+ } finally {
27940
+ this.#pending.delete(pending);
27941
+ }
27942
+ };
27943
+ close = (release) => {
27944
+ if (this.#closing !== null) {
27945
+ return this.#closing;
27946
+ }
27947
+ this.#shutdown.abort();
27948
+ this.#closing = (async () => {
27949
+ await Promise.allSettled([...this.#pending]);
27950
+ await release();
27951
+ })();
27952
+ return this.#closing;
27953
+ };
27954
+ };
27955
+ async function waitForSharedOperation(pending, signal) {
27956
+ signal.throwIfAborted();
27957
+ const cancelled = Promise.withResolvers();
27958
+ const abort = () => cancelled.reject(signal.reason);
27959
+ signal.addEventListener("abort", abort, { once: true });
27960
+ try {
27961
+ return await Promise.race([pending, cancelled.promise]);
27962
+ } finally {
27963
+ signal.removeEventListener("abort", abort);
27964
+ }
27965
+ }
27966
+
27924
27967
  // src/acp/session-config/session-config-protocol.ts
27925
27968
  import { methods as methods7 } from "@agentclientprotocol/sdk";
27926
27969
  var MAXIMUM_CONFIG_OPTIONS = 100;
@@ -34560,9 +34603,7 @@ var AgentSession = class _AgentSession {
34560
34603
  #configOptions = [];
34561
34604
  #prompted = false;
34562
34605
  #nativePrompt = null;
34563
- #replay = {
34564
- kind: "idle"
34565
- };
34606
+ #sessionLoad = { kind: "not-requested" };
34566
34607
  #restored = false;
34567
34608
  #sessionTitle = null;
34568
34609
  #sessionUpdatedAt = "";
@@ -34675,30 +34716,46 @@ var AgentSession = class _AgentSession {
34675
34716
  }
34676
34717
  };
34677
34718
  }
34678
- const history = new AcpHistoryReplay();
34679
- this.#replay = { kind: "capture", history };
34680
- try {
34681
- await this.race(
34682
- this.#connection.connection.agent.request(
34683
- methods8.agent.session.load,
34684
- {
34685
- additionalDirectories: [...this.#additionalDirectories],
34686
- cwd: this.#cwd,
34687
- mcpServers: [],
34688
- sessionId: this.#updates.sessionId()
34689
- },
34690
- { cancellationSignal: signal }
34691
- ),
34692
- "ACP agent exited while loading history",
34693
- signal
34694
- );
34695
- await this.#updates.drained();
34696
- signal.throwIfAborted();
34697
- return await embedLocalHistoryImages(await history.snapshot(), signal);
34698
- } finally {
34699
- this.#replay = { kind: "idle" };
34700
- }
34719
+ const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
34720
+ return await embedLocalHistoryImages(await loaded.history.snapshot(), signal);
34701
34721
  };
34722
+ async #loadSession(signal, exitMessage) {
34723
+ if (this.#sessionLoad.kind === "loaded") {
34724
+ return this.#sessionLoad;
34725
+ }
34726
+ if (this.#sessionLoad.kind === "capturing") {
34727
+ return await waitForSharedOperation(this.#sessionLoad.completion, signal);
34728
+ }
34729
+ const history = new AcpHistoryReplay();
34730
+ const completion = Promise.resolve().then(async () => {
34731
+ try {
34732
+ const response = await this.race(
34733
+ this.#connection.connection.agent.request(
34734
+ methods8.agent.session.load,
34735
+ {
34736
+ additionalDirectories: [...this.#additionalDirectories],
34737
+ cwd: this.#cwd,
34738
+ mcpServers: [],
34739
+ sessionId: this.#updates.sessionId()
34740
+ },
34741
+ { cancellationSignal: signal }
34742
+ ),
34743
+ exitMessage,
34744
+ signal
34745
+ );
34746
+ await this.#updates.drained();
34747
+ signal.throwIfAborted();
34748
+ const loaded = { history, kind: "loaded", response };
34749
+ this.#sessionLoad = loaded;
34750
+ return loaded;
34751
+ } catch (cause) {
34752
+ this.#sessionLoad = { kind: "not-requested" };
34753
+ throw cause;
34754
+ }
34755
+ });
34756
+ this.#sessionLoad = { completion, history, kind: "capturing" };
34757
+ return await completion;
34758
+ }
34702
34759
  prepareAgentContent = async (content) => {
34703
34760
  if (content.type === "image" && content.uri.length > 0) {
34704
34761
  const signal = AbortSignal.timeout(2e4);
@@ -34901,29 +34958,10 @@ var AgentSession = class _AgentSession {
34901
34958
  )
34902
34959
  );
34903
34960
  } else if (this.#capabilities.loadSession) {
34904
- this.#replay = { kind: "discard" };
34905
- try {
34906
- lifecycleResponse = await this.#metrics.measure(
34907
- "session-load",
34908
- async () => await this.race(
34909
- this.#connection.connection.agent.request(
34910
- methods8.agent.session.load,
34911
- {
34912
- additionalDirectories: [...this.#additionalDirectories],
34913
- cwd: this.#cwd,
34914
- mcpServers: [],
34915
- sessionId: this.#updates.sessionId()
34916
- },
34917
- { cancellationSignal: signal }
34918
- ),
34919
- "ACP agent exited while loading a session",
34920
- signal
34921
- )
34922
- );
34923
- } finally {
34924
- await this.#updates.drained();
34925
- this.#replay = { kind: "idle" };
34926
- }
34961
+ lifecycleResponse = await this.#metrics.measure(
34962
+ "session-load",
34963
+ async () => (await this.#loadSession(signal, "ACP agent exited while loading a session")).response
34964
+ );
34927
34965
  } else {
34928
34966
  throw new AcpExecutionError(
34929
34967
  "The ACP agent cannot restore its persisted session",
@@ -35308,10 +35346,10 @@ var AgentSession = class _AgentSession {
35308
35346
  #processUpdate = async (notification) => {
35309
35347
  this.assertNativeSession(notification.sessionId);
35310
35348
  const update = notification.update;
35311
- if (this.#replay.kind === "capture") {
35312
- await this.#replay.history.record(update);
35349
+ if (this.#sessionLoad.kind !== "not-requested") {
35350
+ await this.#sessionLoad.history.record(update);
35313
35351
  }
35314
- if (this.#replay.kind !== "idle" && (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")) {
35352
+ 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")) {
35315
35353
  return;
35316
35354
  }
35317
35355
  if (update.sessionUpdate === "agent_message_chunk") {
@@ -35581,48 +35619,6 @@ var RetainedAgentProcesses = class {
35581
35619
  };
35582
35620
  };
35583
35621
 
35584
- // src/acp/runtime-operations.ts
35585
- var RuntimeOperations = class {
35586
- #shutdown = new AbortController();
35587
- #pending = /* @__PURE__ */ new Set();
35588
- #closing = null;
35589
- run = async (options, operation) => {
35590
- const signal = AbortSignal.any([options.signal, this.#shutdown.signal]);
35591
- signal.throwIfAborted();
35592
- const pending = Promise.resolve().then(() => operation({ ...options, signal }));
35593
- this.#pending.add(pending);
35594
- try {
35595
- const result = await pending;
35596
- signal.throwIfAborted();
35597
- return result;
35598
- } finally {
35599
- this.#pending.delete(pending);
35600
- }
35601
- };
35602
- close = (release) => {
35603
- if (this.#closing !== null) {
35604
- return this.#closing;
35605
- }
35606
- this.#shutdown.abort();
35607
- this.#closing = (async () => {
35608
- await Promise.allSettled([...this.#pending]);
35609
- await release();
35610
- })();
35611
- return this.#closing;
35612
- };
35613
- };
35614
- async function waitForPreparation(pending, signal) {
35615
- signal.throwIfAborted();
35616
- const cancelled = Promise.withResolvers();
35617
- const abort = () => cancelled.reject(signal.reason);
35618
- signal.addEventListener("abort", abort, { once: true });
35619
- try {
35620
- return await Promise.race([pending, cancelled.promise]);
35621
- } finally {
35622
- signal.removeEventListener("abort", abort);
35623
- }
35624
- }
35625
-
35626
35622
  // src/acp/agent-query-processes.ts
35627
35623
  var AgentQueryProcesses = class {
35628
35624
  #processesByQuery;
@@ -35669,7 +35665,7 @@ var AgentQueryProcesses = class {
35669
35665
  prepare = async (options) => {
35670
35666
  const pending = this.#processesByQuery.pending(options.sessionId);
35671
35667
  if (pending !== void 0) {
35672
- const runtime2 = await waitForPreparation(pending, options.signal);
35668
+ const runtime2 = await waitForSharedOperation(pending, options.signal);
35673
35669
  if (runtime2.belongsTo(options.agent.id, options.cwd, options.additionalDirectories)) {
35674
35670
  this.#processesByQuery.touch(options.sessionId, runtime2);
35675
35671
  return runtime2.prepared();
@@ -36087,7 +36083,7 @@ var AgentRuntimeManager = class {
36087
36083
  if (pending !== void 0) {
36088
36084
  const runtime2 = await metrics.measure(
36089
36085
  "session-preparation-wait",
36090
- async () => await waitForPreparation(pending, options2.signal)
36086
+ async () => await waitForSharedOperation(pending, options2.signal)
36091
36087
  );
36092
36088
  if (runtime2.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
36093
36089
  this.#executionProcesses.touch(options2.sessionId, runtime2);
@@ -36177,7 +36173,7 @@ var AgentRuntimeManager = class {
36177
36173
  prepareExecutionSession = async (options) => this.#operations.run(options, async (options2) => {
36178
36174
  const pending = this.#executionProcesses.pending(options2.sessionId);
36179
36175
  if (pending !== void 0) {
36180
- await waitForPreparation(pending, options2.signal);
36176
+ await waitForSharedOperation(pending, options2.signal);
36181
36177
  return await this.prepareExecutionSession(options2);
36182
36178
  }
36183
36179
  const existing = this.#executionProcesses.get(options2.sessionId);
@@ -36231,7 +36227,7 @@ var AgentRuntimeManager = class {
36231
36227
  }
36232
36228
  const pending = this.#executionProcesses.pending(options2.sessionId);
36233
36229
  if (pending !== void 0) {
36234
- await waitForPreparation(pending, options2.signal);
36230
+ await waitForSharedOperation(pending, options2.signal);
36235
36231
  }
36236
36232
  if (this.#executions.command(options2.sessionId) !== options2.targetCommandId) {
36237
36233
  throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
@@ -37784,6 +37780,7 @@ var ActiveDaemonTurn = class {
37784
37780
  #text = "";
37785
37781
  #activities = /* @__PURE__ */ new Map();
37786
37782
  #content = /* @__PURE__ */ new Map();
37783
+ #timeline = [];
37787
37784
  #sequence = 0;
37788
37785
  #interaction = null;
37789
37786
  #epoch = decodeIdentifier(randomUUID());
@@ -37827,12 +37824,16 @@ var ActiveDaemonTurn = class {
37827
37824
  recordEvent = (event) => {
37828
37825
  if (event.kind === AGENT_MESSAGE_DELTA_KIND) {
37829
37826
  this.#text += event.text;
37827
+ this.appendMessageText(event.messageId, event.text);
37830
37828
  return this.updated();
37831
37829
  }
37832
37830
  if (event.sessionId !== this.command.sessionId || "commandId" in event && event.commandId !== this.command.commandId) {
37833
37831
  return event;
37834
37832
  }
37835
37833
  if (event.kind === AGENT_ACTIVITY_KIND) {
37834
+ if (!this.#activities.has(event.activityId)) {
37835
+ this.#timeline = [...this.#timeline, { activityId: event.activityId, kind: "activity" }];
37836
+ }
37836
37837
  this.#activities.set(event.activityId, {
37837
37838
  activityId: event.activityId,
37838
37839
  activityType: event.activityType,
@@ -37848,6 +37849,9 @@ var ActiveDaemonTurn = class {
37848
37849
  });
37849
37850
  } else if (event.kind === AGENT_ACTIVITY_NARRATION_KIND) {
37850
37851
  const previous = this.#activities.get(event.activityId);
37852
+ if (previous === void 0) {
37853
+ this.#timeline = [...this.#timeline, { activityId: event.activityId, kind: "activity" }];
37854
+ }
37851
37855
  this.#activities.set(event.activityId, {
37852
37856
  activityId: event.activityId,
37853
37857
  activityType: event.activityType,
@@ -37863,6 +37867,24 @@ var ActiveDaemonTurn = class {
37863
37867
  });
37864
37868
  } else if (event.kind === AGENT_CONTENT_KIND) {
37865
37869
  this.#content.set(event.contentId, event.content);
37870
+ const target = this.#timeline.findLastIndex(
37871
+ (entry) => entry.kind === "message" && entry.messageId === event.messageId
37872
+ );
37873
+ if (target < 0) {
37874
+ this.#timeline = [
37875
+ ...this.#timeline,
37876
+ {
37877
+ content: /* @__PURE__ */ new Map([[event.contentId, event.content]]),
37878
+ kind: "message",
37879
+ messageId: event.messageId,
37880
+ text: ""
37881
+ }
37882
+ ];
37883
+ } else {
37884
+ this.#timeline = this.#timeline.map(
37885
+ (entry, index) => index === target && entry.kind === "message" ? { ...entry, content: new Map([...entry.content, [event.contentId, event.content]]) } : entry
37886
+ );
37887
+ }
37866
37888
  } else if (event.kind === SESSION_PERMISSION_REQUESTED_KIND || event.kind === SESSION_ELICITATION_REQUESTED_KIND) {
37867
37889
  this.#interaction = event;
37868
37890
  } else if ((event.kind === SESSION_PERMISSION_RESOLVED_KIND || event.kind === SESSION_ELICITATION_RESOLVED_KIND) && this.#interaction?.interactionId === event.interactionId) {
@@ -37873,6 +37895,49 @@ var ActiveDaemonTurn = class {
37873
37895
  }
37874
37896
  return event;
37875
37897
  };
37898
+ appendMessageText(messageId, text2) {
37899
+ let remaining = text2;
37900
+ while (remaining.length > 0) {
37901
+ const latest = this.#timeline.at(-1);
37902
+ if (latest?.kind === "message" && latest.messageId === messageId) {
37903
+ const available = SESSION_HISTORY_CHARACTER_LIMIT - latest.text.length;
37904
+ if (available > 0) {
37905
+ this.#timeline = [
37906
+ ...this.#timeline.slice(0, -1),
37907
+ { ...latest, text: `${latest.text}${remaining.slice(0, available)}` }
37908
+ ];
37909
+ remaining = remaining.slice(available);
37910
+ continue;
37911
+ }
37912
+ }
37913
+ this.#timeline = [
37914
+ ...this.#timeline,
37915
+ {
37916
+ content: /* @__PURE__ */ new Map(),
37917
+ kind: "message",
37918
+ messageId,
37919
+ text: remaining.slice(0, SESSION_HISTORY_CHARACTER_LIMIT)
37920
+ }
37921
+ ];
37922
+ remaining = remaining.slice(SESSION_HISTORY_CHARACTER_LIMIT);
37923
+ }
37924
+ }
37925
+ timelineMessages() {
37926
+ return this.#timeline.flatMap((entry) => {
37927
+ if (entry.kind === "message") {
37928
+ return [
37929
+ {
37930
+ activities: [],
37931
+ content: [...entry.content.values()],
37932
+ role: "assistant",
37933
+ text: entry.text
37934
+ }
37935
+ ];
37936
+ }
37937
+ const activity2 = this.#activities.get(entry.activityId);
37938
+ return activity2 === void 0 ? [] : [{ activities: [activity2], content: [], role: "assistant", text: "" }];
37939
+ });
37940
+ }
37876
37941
  updated = () => {
37877
37942
  this.#sequence += 1;
37878
37943
  const turn = this.snapshot();
@@ -37881,18 +37946,26 @@ var ActiveDaemonTurn = class {
37881
37946
  }
37882
37947
  return { kind: "session.turn.updated", sessionId: this.command.sessionId, turn };
37883
37948
  };
37884
- snapshot = () => this.#dispatch.kind === "running" ? {
37885
- activities: [...this.#activities.values()].sort((left, right) => left.sequence - right.sequence),
37886
- commandId: decodeIdentifier(this.command.commandId),
37887
- content: [...this.#content.values()],
37888
- prompt: this.command.prompt,
37889
- text: this.#text,
37890
- truncated: false,
37891
- epoch: this.#epoch,
37892
- interaction: this.#interaction,
37893
- sequence: this.#sequence,
37894
- state: "running"
37895
- } : null;
37949
+ snapshot = () => {
37950
+ if (this.#dispatch.kind !== "running") {
37951
+ return null;
37952
+ }
37953
+ const completeMessages = this.timelineMessages();
37954
+ const messages = completeMessages.slice(-SESSION_HISTORY_MESSAGE_LIMIT);
37955
+ return {
37956
+ activities: [...this.#activities.values()].sort((left, right) => left.sequence - right.sequence),
37957
+ commandId: decodeIdentifier(this.command.commandId),
37958
+ content: [...this.#content.values()],
37959
+ prompt: this.command.prompt,
37960
+ text: this.#text,
37961
+ truncated: messages.length !== completeMessages.length,
37962
+ epoch: this.#epoch,
37963
+ interaction: this.#interaction,
37964
+ messages,
37965
+ sequence: this.#sequence,
37966
+ state: "running"
37967
+ };
37968
+ };
37896
37969
  matches = (cancellation) => cancellation.commandId === this.command.commandId && cancellation.sessionId === this.command.sessionId;
37897
37970
  matchesInteraction = (interactionId, sessionId) => this.command.sessionId === sessionId && this.#interaction?.interactionId === interactionId;
37898
37971
  requestCancellation = () => {
@@ -38078,15 +38151,21 @@ var turnsSchema = external_exports.object({
38078
38151
  });
38079
38152
  var itemTypeSchema = external_exports.object({ type: external_exports.string().min(1).max(80) });
38080
38153
  var userMessageSchema = external_exports.object({
38081
- content: external_exports.array(external_exports.unknown()).max(1e4)
38154
+ content: external_exports.array(external_exports.unknown()).max(1e4),
38155
+ type: external_exports.literal("userMessage")
38082
38156
  });
38083
38157
  var textSchema = external_exports.object({ text: external_exports.string() });
38084
38158
  var imageSchema = external_exports.object({ url: external_exports.string() });
38085
- var agentMessageSchema = textSchema.extend({ phase: external_exports.string().nullish() });
38159
+ var agentMessageSchema = textSchema.extend({
38160
+ id: external_exports.string().optional(),
38161
+ phase: external_exports.string().nullish(),
38162
+ type: external_exports.literal("agentMessage")
38163
+ });
38086
38164
  var reasoningSchema = external_exports.object({
38087
38165
  id: external_exports.string(),
38088
38166
  summary: external_exports.array(external_exports.string()).max(1e4),
38089
- content: external_exports.array(external_exports.string()).max(1e4)
38167
+ content: external_exports.array(external_exports.string()).max(1e4),
38168
+ type: external_exports.literal("reasoning")
38090
38169
  });
38091
38170
  var commandExecutionSchema = external_exports.object({
38092
38171
  id: external_exports.string(),
@@ -38095,8 +38174,45 @@ var commandExecutionSchema = external_exports.object({
38095
38174
  status: external_exports.string(),
38096
38175
  commandActions: external_exports.array(external_exports.object({ type: external_exports.string() }).passthrough()).max(100),
38097
38176
  aggregatedOutput: external_exports.string().nullish(),
38098
- exitCode: external_exports.number().int().nullish()
38177
+ exitCode: external_exports.number().int().nullish(),
38178
+ type: external_exports.literal("commandExecution")
38179
+ });
38180
+ var fileChangeSchema = external_exports.object({
38181
+ changes: external_exports.array(external_exports.object({ diff: external_exports.string(), path: external_exports.string() })).max(1e4),
38182
+ id: external_exports.string(),
38183
+ status: external_exports.string(),
38184
+ type: external_exports.literal("fileChange")
38185
+ });
38186
+ var mcpToolCallSchema = external_exports.object({
38187
+ arguments: external_exports.unknown().optional(),
38188
+ error: external_exports.unknown().nullish(),
38189
+ id: external_exports.string(),
38190
+ result: external_exports.unknown().nullish(),
38191
+ server: external_exports.string(),
38192
+ status: external_exports.string(),
38193
+ tool: external_exports.string(),
38194
+ type: external_exports.literal("mcpToolCall")
38195
+ });
38196
+ var dynamicToolCallSchema = external_exports.object({
38197
+ arguments: external_exports.unknown().optional(),
38198
+ contentItems: external_exports.array(external_exports.unknown()).max(1e4).nullish(),
38199
+ id: external_exports.string(),
38200
+ namespace: external_exports.string().nullish(),
38201
+ status: external_exports.string(),
38202
+ tool: external_exports.string(),
38203
+ type: external_exports.literal("dynamicToolCall")
38099
38204
  });
38205
+ var planSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), type: external_exports.literal("plan") });
38206
+ var historyItemSchema = external_exports.discriminatedUnion("type", [
38207
+ userMessageSchema,
38208
+ agentMessageSchema,
38209
+ reasoningSchema,
38210
+ commandExecutionSchema,
38211
+ fileChangeSchema,
38212
+ mcpToolCallSchema,
38213
+ dynamicToolCallSchema,
38214
+ planSchema
38215
+ ]);
38100
38216
  function bounded(value, maximum) {
38101
38217
  return value.slice(0, maximum);
38102
38218
  }
@@ -38127,6 +38243,33 @@ function errorMessage(value) {
38127
38243
  }
38128
38244
  return JSON.stringify(value) ?? "Codex stopped before completing this turn.";
38129
38245
  }
38246
+ function formatted(value) {
38247
+ if (value === void 0) {
38248
+ return "";
38249
+ }
38250
+ if (typeof value === "string") {
38251
+ return value;
38252
+ }
38253
+ return JSON.stringify(value) ?? "";
38254
+ }
38255
+ function toolStatus(status) {
38256
+ return status === "inProgress" ? "running" : status === "completed" ? "completed" : "failed";
38257
+ }
38258
+ function diffDisplayContent(path2, newText) {
38259
+ return {
38260
+ artifactId: "",
38261
+ data: "",
38262
+ mimeType: "",
38263
+ name: "",
38264
+ newText,
38265
+ oldText: "",
38266
+ path: path2,
38267
+ terminalId: "",
38268
+ text: "",
38269
+ type: "diff",
38270
+ uri: ""
38271
+ };
38272
+ }
38130
38273
  function messageSize(message) {
38131
38274
  return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
38132
38275
  }
@@ -38164,8 +38307,8 @@ function fitActivities(activities, maximumCharacters) {
38164
38307
  const maximumActivityCharacters = Math.floor(Math.max(0, maximumCharacters - arrayCharacters) / activities.length);
38165
38308
  return activities.map((activity2) => fitActivity(activity2, maximumActivityCharacters));
38166
38309
  }
38167
- function fitHistoryMessage(message) {
38168
- const text2 = message.text.slice(-SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT);
38310
+ function fitHistoryMessage(message, maximumCharacters = SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT) {
38311
+ const text2 = message.text.slice(-maximumCharacters);
38169
38312
  if (message.role === "user") {
38170
38313
  return {
38171
38314
  message: { ...message, text: text2 },
@@ -38175,12 +38318,12 @@ function fitHistoryMessage(message) {
38175
38318
  let activities = message.activities;
38176
38319
  const content = message.content;
38177
38320
  let fitted = { ...message, activities, content, text: text2 };
38178
- if (messageSize(fitted) > SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT && activities.length > 0) {
38179
- const maximumCharacters = SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT - text2.length - JSON.stringify(content).length;
38180
- activities = fitActivities(activities, maximumCharacters);
38321
+ if (messageSize(fitted) > maximumCharacters && activities.length > 0) {
38322
+ const maximumActivityCharacters = maximumCharacters - text2.length - JSON.stringify(content).length;
38323
+ activities = fitActivities(activities, maximumActivityCharacters);
38181
38324
  fitted = { ...fitted, activities };
38182
38325
  }
38183
- const excess = Math.max(0, messageSize(fitted) - SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT);
38326
+ const excess = Math.max(0, messageSize(fitted) - maximumCharacters);
38184
38327
  if (excess > 0) {
38185
38328
  const maximumTextLength = Math.max(0, fitted.text.length - excess);
38186
38329
  fitted = {
@@ -38218,128 +38361,209 @@ function decodeHistory(thread, value, options) {
38218
38361
  let truncated = page.nextCursor != null;
38219
38362
  for (const turn of page.data.toReversed()) {
38220
38363
  const outcome = turnOutcome(turn.status);
38221
- const activities = [];
38222
- let assignedActivityCount = 0;
38364
+ const turnMessageCharacterLimit = Math.max(
38365
+ 1,
38366
+ Math.floor(SESSION_HISTORY_CHARACTER_LIMIT / Math.max(1, turn.items.length + (turn.error == null ? 0 : 1)))
38367
+ );
38223
38368
  let sequence = 0;
38224
38369
  let assistantMessageIndex = null;
38225
- const activitySlice = () => {
38226
- const assigned = activities.slice(assignedActivityCount).slice(-100);
38227
- assignedActivityCount = activities.length;
38228
- return assigned;
38370
+ const append = (message) => {
38371
+ const fitted = fitHistoryMessage(message, turnMessageCharacterLimit);
38372
+ if (fitted.message.text.length === 0 && (fitted.message.images?.length ?? 0) === 0 && (fitted.message.role === "user" || fitted.message.activities.length === 0 && fitted.message.content.length === 0)) {
38373
+ return;
38374
+ }
38375
+ truncated ||= fitted.truncated;
38376
+ messages.push(fitted.message);
38377
+ if (fitted.message.role === "assistant") {
38378
+ assistantMessageIndex = messages.length - 1;
38379
+ }
38380
+ characters += messageSize(fitted.message);
38229
38381
  };
38230
38382
  for (const item of turn.items) {
38231
- const { type } = itemTypeSchema.parse(item);
38232
- let message;
38233
- if (type === "userMessage") {
38234
- const { content } = userMessageSchema.parse(item);
38235
- const text2 = content.map((block) => {
38236
- const { type: type2 } = itemTypeSchema.parse(block);
38237
- if (type2 === "text") {
38383
+ const decoded = historyItemSchema.safeParse(item);
38384
+ if (!decoded.success) {
38385
+ continue;
38386
+ }
38387
+ const historyItem = decoded.data;
38388
+ if (historyItem.type === "userMessage") {
38389
+ const text2 = historyItem.content.map((block) => {
38390
+ const { type } = itemTypeSchema.parse(block);
38391
+ if (type === "text") {
38238
38392
  return textSchema.parse(block).text;
38239
38393
  }
38240
- if (type2 === "image") {
38394
+ if (type === "image") {
38241
38395
  return `[@image](${imageSchema.parse(block).url})`;
38242
38396
  }
38243
38397
  return "[Attachment]";
38244
38398
  }).join("");
38245
- message = {
38399
+ append({
38246
38400
  role: "user",
38247
38401
  text: text2
38248
- };
38249
- } else if (type === "agentMessage") {
38250
- const agent = agentMessageSchema.parse(item);
38251
- if (agent.phase === "commentary") {
38252
- if (options.detail === "rich" && agent.text.length > 0) {
38253
- activities.push(
38254
- activity(`progress-${sequence.toString()}`, "progress", sequence, {
38402
+ });
38403
+ } else if (historyItem.type === "agentMessage") {
38404
+ if (historyItem.phase === "commentary") {
38405
+ if (options.detail === "rich" && historyItem.text.length > 0) {
38406
+ append({
38407
+ activities: [
38408
+ activity(historyItem.id ?? `progress-${sequence.toString()}`, "progress", sequence, {
38409
+ input: "",
38410
+ locations: [],
38411
+ name: "",
38412
+ output: historyItem.text,
38413
+ status: "completed",
38414
+ title: "Progress",
38415
+ toolKind: ""
38416
+ })
38417
+ ],
38418
+ content: [],
38419
+ role: "assistant",
38420
+ text: ""
38421
+ });
38422
+ sequence += 1;
38423
+ }
38424
+ continue;
38425
+ }
38426
+ append({ activities: [], content: [], role: "assistant", text: historyItem.text });
38427
+ } else if (historyItem.type === "reasoning" && options.detail === "rich") {
38428
+ const output2 = (historyItem.summary.length > 0 ? historyItem.summary : historyItem.content).join(
38429
+ "\n\n"
38430
+ );
38431
+ if (output2.length > 0) {
38432
+ append({
38433
+ activities: [
38434
+ activity(historyItem.id, "reasoning", sequence, {
38255
38435
  input: "",
38256
38436
  locations: [],
38257
38437
  name: "",
38258
- output: agent.text,
38438
+ output: output2,
38259
38439
  status: "completed",
38260
- title: "Progress",
38440
+ title: "Reasoning",
38261
38441
  toolKind: ""
38262
38442
  })
38263
- );
38264
- sequence += 1;
38265
- }
38266
- continue;
38443
+ ],
38444
+ content: [],
38445
+ role: "assistant",
38446
+ text: ""
38447
+ });
38448
+ sequence += 1;
38267
38449
  }
38268
- message = { activities: activitySlice(), content: [], role: "assistant", text: agent.text };
38269
- } else if (type === "reasoning" && options.detail === "rich") {
38270
- const reasoning = reasoningSchema.parse(item);
38271
- const output2 = (reasoning.summary.length > 0 ? reasoning.summary : reasoning.content).join("\n\n");
38272
- if (output2.length > 0) {
38273
- activities.push(
38274
- activity(reasoning.id, "reasoning", sequence, {
38450
+ } else if (historyItem.type === "commandExecution" && options.detail === "rich") {
38451
+ const action = historyItem.commandActions[0]?.type ?? "execute";
38452
+ append({
38453
+ activities: [
38454
+ activity(historyItem.id, "tool", sequence, {
38455
+ input: JSON.stringify({ command: historyItem.command, cwd: historyItem.cwd }),
38456
+ locations: [historyItem.cwd],
38457
+ name: "",
38458
+ output: JSON.stringify({
38459
+ formatted_output: historyItem.aggregatedOutput ?? "",
38460
+ ...historyItem.exitCode == null ? {} : { exit_code: historyItem.exitCode }
38461
+ }),
38462
+ status: toolStatus(historyItem.status),
38463
+ title: historyItem.command,
38464
+ toolKind: action
38465
+ })
38466
+ ],
38467
+ content: [],
38468
+ role: "assistant",
38469
+ text: ""
38470
+ });
38471
+ sequence += 1;
38472
+ } else if (historyItem.type === "fileChange" && options.detail === "rich") {
38473
+ const paths = historyItem.changes.map((change) => change.path);
38474
+ const content = historyItem.changes.map(
38475
+ (change) => diffDisplayContent(change.path, change.diff)
38476
+ );
38477
+ append({
38478
+ activities: [
38479
+ activity(historyItem.id, "tool", sequence, {
38480
+ input: JSON.stringify({ changes: paths }),
38481
+ locations: paths,
38482
+ name: "",
38483
+ output: "",
38484
+ status: toolStatus(historyItem.status),
38485
+ title: paths.join(", "),
38486
+ toolKind: "edit"
38487
+ })
38488
+ ].map((entry) => ({ ...entry, content })),
38489
+ content: [],
38490
+ role: "assistant",
38491
+ text: ""
38492
+ });
38493
+ sequence += 1;
38494
+ } else if (historyItem.type === "mcpToolCall" && options.detail === "rich") {
38495
+ append({
38496
+ activities: [
38497
+ activity(historyItem.id, "tool", sequence, {
38498
+ input: formatted(historyItem.arguments),
38499
+ locations: [],
38500
+ name: historyItem.tool,
38501
+ output: formatted(historyItem.error ?? historyItem.result),
38502
+ status: toolStatus(historyItem.status),
38503
+ title: `${historyItem.server}/${historyItem.tool}`,
38504
+ toolKind: "other"
38505
+ })
38506
+ ],
38507
+ content: [],
38508
+ role: "assistant",
38509
+ text: ""
38510
+ });
38511
+ sequence += 1;
38512
+ } else if (historyItem.type === "dynamicToolCall" && options.detail === "rich") {
38513
+ append({
38514
+ activities: [
38515
+ activity(historyItem.id, "tool", sequence, {
38516
+ input: formatted(historyItem.arguments),
38517
+ locations: [],
38518
+ name: historyItem.tool,
38519
+ output: formatted(historyItem.contentItems),
38520
+ status: toolStatus(historyItem.status),
38521
+ title: historyItem.namespace == null ? historyItem.tool : `${historyItem.namespace}/${historyItem.tool}`,
38522
+ toolKind: "other"
38523
+ })
38524
+ ],
38525
+ content: [],
38526
+ role: "assistant",
38527
+ text: ""
38528
+ });
38529
+ sequence += 1;
38530
+ } else if (historyItem.type === "plan" && options.detail === "rich") {
38531
+ append({
38532
+ activities: [
38533
+ activity(historyItem.id, "plan", sequence, {
38275
38534
  input: "",
38276
38535
  locations: [],
38277
38536
  name: "",
38278
- output: output2,
38537
+ output: historyItem.text,
38279
38538
  status: "completed",
38280
- title: "Reasoning",
38539
+ title: "Plan",
38281
38540
  toolKind: ""
38282
38541
  })
38283
- );
38284
- sequence += 1;
38285
- }
38286
- continue;
38287
- } else if (type === "commandExecution" && options.detail === "rich") {
38288
- const command = commandExecutionSchema.parse(item);
38289
- const action = command.commandActions[0]?.type ?? "execute";
38290
- activities.push(
38291
- activity(command.id, "tool", sequence, {
38292
- input: JSON.stringify({ command: command.command, cwd: command.cwd }),
38293
- locations: [command.cwd],
38294
- name: "",
38295
- output: JSON.stringify({
38296
- formatted_output: command.aggregatedOutput ?? "",
38297
- ...command.exitCode == null ? {} : { exit_code: command.exitCode }
38298
- }),
38299
- status: command.status === "completed" ? "completed" : "failed",
38300
- title: command.command,
38301
- toolKind: action
38302
- })
38303
- );
38542
+ ],
38543
+ content: [],
38544
+ role: "assistant",
38545
+ text: ""
38546
+ });
38304
38547
  sequence += 1;
38305
- continue;
38306
- } else {
38307
- continue;
38308
38548
  }
38309
- const fitted = fitHistoryMessage(message);
38310
- if (fitted.message.text.length === 0 && (fitted.message.images?.length ?? 0) === 0) {
38311
- continue;
38312
- }
38313
- truncated ||= fitted.truncated;
38314
- messages.push(fitted.message);
38315
- if (message.role === "assistant") {
38316
- assistantMessageIndex = messages.length - 1;
38317
- }
38318
- characters += messageSize(fitted.message);
38319
38549
  }
38320
38550
  if (options.detail === "rich" && turn.error != null) {
38321
- activities.push(
38322
- activity(`agent-error-${sequence.toString()}`, "tool", sequence, {
38323
- input: "",
38324
- locations: [],
38325
- name: "",
38326
- output: errorMessage(turn.error),
38327
- status: "failed",
38328
- title: "Agent error",
38329
- toolKind: "other"
38330
- })
38331
- );
38332
- }
38333
- if (options.detail === "rich" && activities.length > assignedActivityCount) {
38334
- const message = {
38335
- activities: activitySlice(),
38551
+ append({
38552
+ activities: [
38553
+ activity(`agent-error-${sequence.toString()}`, "tool", sequence, {
38554
+ input: "",
38555
+ locations: [],
38556
+ name: "",
38557
+ output: errorMessage(turn.error),
38558
+ status: "failed",
38559
+ title: "Agent error",
38560
+ toolKind: "other"
38561
+ })
38562
+ ],
38336
38563
  content: [],
38337
38564
  role: "assistant",
38338
38565
  text: ""
38339
- };
38340
- messages.push(message);
38341
- assistantMessageIndex = messages.length - 1;
38342
- characters += messageSize(message);
38566
+ });
38343
38567
  }
38344
38568
  if (assistantMessageIndex !== null) {
38345
38569
  const assistant = messages[assistantMessageIndex];
@@ -38349,20 +38573,20 @@ function decodeHistory(thread, value, options) {
38349
38573
  ...assistant,
38350
38574
  ...outcome === void 0 ? {} : { outcome }
38351
38575
  };
38352
- const fitted = fitHistoryMessage(updated);
38576
+ const fitted = fitHistoryMessage(updated, turnMessageCharacterLimit);
38353
38577
  truncated ||= fitted.truncated;
38354
38578
  messages[assistantMessageIndex] = fitted.message;
38355
38579
  characters += messageSize(fitted.message);
38356
38580
  }
38357
- } else if (activities.length > 0 || outcome !== void 0) {
38581
+ } else if (outcome !== void 0) {
38358
38582
  const message = {
38359
- activities: activities.slice(-100),
38583
+ activities: [],
38360
38584
  content: [],
38361
38585
  role: "assistant",
38362
38586
  ...outcome === void 0 ? {} : { outcome },
38363
38587
  text: ""
38364
38588
  };
38365
- const fitted = fitHistoryMessage(message);
38589
+ const fitted = fitHistoryMessage(message, turnMessageCharacterLimit);
38366
38590
  truncated ||= fitted.truncated;
38367
38591
  messages.push(fitted.message);
38368
38592
  characters += messageSize(fitted.message);
@@ -40202,6 +40426,34 @@ function liveHistoryCoveredTurnRanges(history) {
40202
40426
  function historyMessageCharacters(message) {
40203
40427
  return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
40204
40428
  }
40429
+ function boundedActiveMessages(messages, messageLimit, characterLimit) {
40430
+ const selected = [];
40431
+ let remainingCharacters = characterLimit;
40432
+ for (let index = messages.length - 1; index >= 0 && selected.length < messageLimit; index -= 1) {
40433
+ const message = messages[index];
40434
+ if (message === void 0) {
40435
+ break;
40436
+ }
40437
+ const characters = historyMessageCharacters(message);
40438
+ if (characters <= remainingCharacters) {
40439
+ selected.unshift(message);
40440
+ remainingCharacters -= characters;
40441
+ continue;
40442
+ }
40443
+ const structuredCharacters = characters - message.text.length;
40444
+ if (selected.length === 0 && structuredCharacters <= remainingCharacters) {
40445
+ const textCharacters = remainingCharacters - structuredCharacters;
40446
+ selected.unshift({ ...message, text: textCharacters === 0 ? "" : message.text.slice(-textCharacters) });
40447
+ remainingCharacters = 0;
40448
+ }
40449
+ break;
40450
+ }
40451
+ return {
40452
+ characters: characterLimit - remainingCharacters,
40453
+ messages: selected,
40454
+ truncated: selected.length !== messages.length
40455
+ };
40456
+ }
40205
40457
  function paginateAcpSessionHistory(history, sessionId, cursor, limit) {
40206
40458
  if (history.status === "unavailable") {
40207
40459
  if (cursor !== null) {
@@ -40232,30 +40484,19 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
40232
40484
  if (activeTurn === null || cursor !== null) {
40233
40485
  return paginateAcpSessionHistory(history, sessionId, cursor, limit);
40234
40486
  }
40235
- const activeMessageOverhead = 4;
40236
- const activeStructuredCharacters = JSON.stringify(activeTurn.activities).length + JSON.stringify(activeTurn.content).length;
40237
- const maximumActiveTextLength = Math.max(
40238
- 0,
40239
- SESSION_HISTORY_CHARACTER_LIMIT - activeTurn.prompt.length - activeStructuredCharacters - activeMessageOverhead
40240
- );
40241
- const activeText = activeTurn.text.slice(-maximumActiveTextLength);
40242
- const completeActiveMessages = [
40243
- { role: "user", text: activeTurn.prompt },
40244
- {
40245
- activities: activeTurn.activities,
40246
- content: activeTurn.content,
40247
- role: "assistant",
40248
- text: activeText
40249
- }
40250
- ];
40251
40487
  if (history.status === "unavailable") {
40488
+ const bounded3 = boundedActiveMessages(
40489
+ activeTurn.messages,
40490
+ Math.max(0, limit - 1),
40491
+ Math.max(0, SESSION_HISTORY_CHARACTER_LIMIT - activeTurn.prompt.length)
40492
+ );
40252
40493
  return {
40253
40494
  coveredCommandIds: [],
40254
40495
  coveredMessageIds: [],
40255
- messages: completeActiveMessages,
40496
+ messages: [{ role: "user", text: activeTurn.prompt }, ...bounded3.messages],
40256
40497
  nextCursor: null,
40257
40498
  status: "available",
40258
- truncated: activeTurn.truncated || activeText.length !== activeTurn.text.length
40499
+ truncated: activeTurn.truncated || bounded3.truncated
40259
40500
  };
40260
40501
  }
40261
40502
  const activeUserIndex = history.coveredCommandIds.includes(activeTurn.commandId) ? history.messages.findLastIndex((message) => message.role === "user") : -1;
@@ -40270,9 +40511,18 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
40270
40511
  };
40271
40512
  }
40272
40513
  const latestNativeMessage = history.messages.at(-1);
40273
- const activeMessages = activeUserIndex >= 0 || latestNativeMessage?.role === "user" && latestNativeMessage.text === activeTurn.prompt ? completeActiveMessages.slice(1) : completeActiveMessages;
40514
+ const includeActivePrompt = activeUserIndex < 0 && !(latestNativeMessage?.role === "user" && latestNativeMessage.text === activeTurn.prompt);
40515
+ const bounded2 = boundedActiveMessages(
40516
+ activeTurn.messages,
40517
+ Math.max(0, limit - (includeActivePrompt ? 1 : 0)),
40518
+ Math.max(0, SESSION_HISTORY_CHARACTER_LIMIT - (includeActivePrompt ? activeTurn.prompt.length : 0))
40519
+ );
40520
+ const activeMessages = [
40521
+ ...includeActivePrompt ? [{ role: "user", text: activeTurn.prompt }] : [],
40522
+ ...bounded2.messages
40523
+ ];
40274
40524
  let historicalMessageCount = 0;
40275
- let remainingCharacters = SESSION_HISTORY_CHARACTER_LIMIT - activeText.length - activeMessageOverhead - activeStructuredCharacters - (activeMessages.length === completeActiveMessages.length ? activeTurn.prompt.length : 0);
40525
+ let remainingCharacters = SESSION_HISTORY_CHARACTER_LIMIT - bounded2.characters - (includeActivePrompt ? activeTurn.prompt.length : 0);
40276
40526
  const historicalMessageLimit = Math.max(0, limit - activeMessages.length);
40277
40527
  for (let index = history.messages.length - 1; index >= 0 && historicalMessageCount < historicalMessageLimit; index -= 1) {
40278
40528
  const message = history.messages[index];
@@ -40297,7 +40547,7 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
40297
40547
  return {
40298
40548
  ...page,
40299
40549
  messages: [...page.messages, ...activeMessages],
40300
- truncated: page.truncated || activeTurn.truncated || activeText.length !== activeTurn.text.length
40550
+ truncated: page.truncated || activeTurn.truncated || bounded2.truncated
40301
40551
  };
40302
40552
  }
40303
40553
  function mergeLiveSessionHistory(history, activeTurn, sessionId) {
@@ -40607,167 +40857,113 @@ function warnIgnoredSetting(audit, event, commandId, sessionId, agentId, selecti
40607
40857
  `);
40608
40858
  }
40609
40859
 
40610
- // src/relay-connection/coalescing-activity-publisher.ts
40611
- var AGENT_ACTIVITY_COALESCING_MILLISECONDS = 100;
40612
- var CoalescingDaemonActivityPublisher = class {
40613
- #pending = /* @__PURE__ */ new Map();
40860
+ // src/relay-connection/coalescing-agent-event-publisher.ts
40861
+ var AGENT_EVENT_COALESCING_MILLISECONDS = 100;
40862
+ var AGENT_EVENT_TEXT_MAXIMUM_LENGTH = 1e5;
40863
+ var CoalescingAgentEventPublisher = class {
40864
+ #entries = [];
40614
40865
  #publish;
40615
40866
  #publishedActivityIds = /* @__PURE__ */ new Set();
40616
- #scheduled = /* @__PURE__ */ new Map();
40867
+ #scheduled = null;
40617
40868
  #timer;
40618
40869
  constructor(timer, publish) {
40619
40870
  this.#publish = publish;
40620
40871
  this.#timer = timer;
40621
40872
  }
40622
- flush = () => {
40623
- const activities = [...this.#pending.values()].sort((left, right) => left.sequence - right.sequence);
40624
- for (const task of this.#scheduled.values()) {
40625
- task.cancel();
40626
- }
40627
- this.#pending.clear();
40628
- this.#scheduled.clear();
40629
- for (const activity2 of activities) {
40630
- this.#publish(activity2);
40631
- }
40632
- };
40633
- record = (activity2) => {
40634
- if (activity2.status !== "pending" && activity2.status !== "running") {
40635
- this.#discardPending(activity2.activityId);
40636
- this.#publishedActivityIds.add(activity2.activityId);
40637
- this.#publish(activity2);
40638
- return Promise.resolve();
40639
- }
40640
- if (!this.#publishedActivityIds.has(activity2.activityId)) {
40641
- this.#publishedActivityIds.add(activity2.activityId);
40642
- this.#publish(activity2);
40643
- return Promise.resolve();
40644
- }
40645
- this.#pending.set(activity2.activityId, activity2);
40646
- if (!this.#scheduled.has(activity2.activityId)) {
40647
- this.#scheduled.set(
40648
- activity2.activityId,
40649
- this.#timer.schedule(
40650
- () => this.#flushActivity(activity2.activityId),
40651
- AGENT_ACTIVITY_COALESCING_MILLISECONDS
40652
- )
40653
- );
40654
- }
40655
- return Promise.resolve();
40656
- };
40657
- #discardPending = (activityId) => {
40658
- this.#scheduled.get(activityId)?.cancel();
40659
- this.#scheduled.delete(activityId);
40660
- this.#pending.delete(activityId);
40661
- };
40662
- #flushActivity = (activityId) => {
40663
- const activity2 = this.#pending.get(activityId);
40664
- this.#discardPending(activityId);
40665
- if (activity2 !== void 0) {
40666
- this.#publish(activity2);
40667
- }
40668
- };
40669
- };
40670
-
40671
- // src/relay-connection/coalescing-narration-publisher.ts
40672
- var CoalescingNarrationPublisher = class {
40673
- #coalescingMilliseconds;
40674
- #maximumTextLength;
40675
- #publish;
40676
- #timer;
40677
- #pending = /* @__PURE__ */ new Map();
40678
- #scheduled = null;
40679
- constructor(timer, publish, coalescingMilliseconds, maximumTextLength) {
40680
- this.#publish = publish;
40681
- this.#timer = timer;
40682
- this.#coalescingMilliseconds = coalescingMilliseconds;
40683
- this.#maximumTextLength = maximumTextLength;
40684
- }
40685
- /** Emit every buffered increment now, cancelling the pending flush. */
40686
40873
  flush = () => {
40687
40874
  this.#scheduled?.cancel();
40688
40875
  this.#scheduled = null;
40689
- const increments = [...this.#pending.entries()].map(
40690
- ([activityId, pending]) => ({
40691
- activityId,
40692
- activityType: pending.activityType,
40693
- sequence: pending.sequence,
40694
- text: pending.text
40695
- })
40696
- );
40697
- this.#pending.clear();
40698
- for (const increment of increments) {
40699
- this.#publish(increment);
40876
+ const entries = this.#entries;
40877
+ this.#entries = [];
40878
+ for (const entry of entries) {
40879
+ this.#publish(entry);
40700
40880
  }
40701
40881
  };
40702
- /**
40703
- * Buffer an increment, emitting the buffered text when it would exceed the
40704
- * protocol's per-event text limit so no event is rejected by the codec.
40705
- */
40706
- record = (increment) => {
40707
- if (increment.text.length === 0) {
40708
- return;
40709
- }
40710
- const previous = this.#pending.get(increment.activityId);
40711
- if (previous !== void 0 && previous.text.length + increment.text.length > this.#maximumTextLength) {
40882
+ recordActivity = (activity2) => {
40883
+ const latest = this.#entries.at(-1);
40884
+ this.#entries = latest?.kind === "activity" && latest.activity.activityId === activity2.activityId ? [...this.#entries.slice(0, -1), { activity: activity2, kind: "activity" }] : [...this.#entries, { activity: activity2, kind: "activity" }];
40885
+ const first = !this.#publishedActivityIds.has(activity2.activityId);
40886
+ this.#publishedActivityIds.add(activity2.activityId);
40887
+ if (first || activity2.status !== "pending" && activity2.status !== "running") {
40712
40888
  this.flush();
40889
+ } else {
40890
+ this.schedule();
40713
40891
  }
40714
- const current = this.#pending.get(increment.activityId);
40715
- this.#pending.set(increment.activityId, {
40716
- activityType: increment.activityType,
40717
- sequence: increment.sequence,
40718
- text: `${current?.text ?? ""}${increment.text}`
40719
- });
40720
- this.#scheduled ??= this.#timer.schedule(this.flush, this.#coalescingMilliseconds);
40892
+ return Promise.resolve();
40721
40893
  };
40722
- };
40723
-
40724
- // src/relay-connection/coalescing-text-publisher.ts
40725
- var CoalescingTextPublisher = class {
40726
- #coalescingMilliseconds;
40727
- #maximumTextLength;
40728
- #publish;
40729
- #timer;
40730
- #messageId = "";
40731
- #scheduled = null;
40732
- #text = "";
40733
- constructor(timer, publish, coalescingMilliseconds, maximumTextLength) {
40734
- this.#publish = publish;
40735
- this.#timer = timer;
40736
- this.#coalescingMilliseconds = coalescingMilliseconds;
40737
- this.#maximumTextLength = maximumTextLength;
40738
- }
40739
- /** Emit any buffered text now, cancelling the pending flush. */
40740
- flush = () => {
40741
- this.#scheduled?.cancel();
40742
- this.#scheduled = null;
40743
- const messageId = this.#messageId;
40744
- const text2 = this.#text;
40745
- this.#messageId = "";
40746
- this.#text = "";
40747
- if (text2.length > 0) {
40748
- this.#publish(messageId, text2);
40894
+ recordNarration = (increment) => {
40895
+ if (increment.text.length === 0) {
40896
+ return Promise.resolve();
40749
40897
  }
40898
+ let remaining = increment.text;
40899
+ while (remaining.length > 0) {
40900
+ const latest = this.#entries.at(-1);
40901
+ if (latest?.kind === "narration" && latest.increment.activityId === increment.activityId) {
40902
+ const available = AGENT_EVENT_TEXT_MAXIMUM_LENGTH - latest.increment.text.length;
40903
+ if (available > 0) {
40904
+ this.#entries = [
40905
+ ...this.#entries.slice(0, -1),
40906
+ {
40907
+ increment: {
40908
+ ...increment,
40909
+ text: `${latest.increment.text}${remaining.slice(0, available)}`
40910
+ },
40911
+ kind: "narration"
40912
+ }
40913
+ ];
40914
+ remaining = remaining.slice(available);
40915
+ continue;
40916
+ }
40917
+ }
40918
+ this.#entries = [
40919
+ ...this.#entries,
40920
+ {
40921
+ increment: { ...increment, text: remaining.slice(0, AGENT_EVENT_TEXT_MAXIMUM_LENGTH) },
40922
+ kind: "narration"
40923
+ }
40924
+ ];
40925
+ remaining = remaining.slice(AGENT_EVENT_TEXT_MAXIMUM_LENGTH);
40926
+ }
40927
+ this.schedule();
40928
+ return Promise.resolve();
40750
40929
  };
40751
- /**
40752
- * Buffer a chunk, emitting the buffered text when the message changes or the
40753
- * buffer would exceed the protocol's per-event text limit.
40754
- */
40755
- record = (messageId, text2) => {
40930
+ recordText = (text2, messageId) => {
40756
40931
  if (text2.length === 0) {
40757
- return;
40932
+ return Promise.resolve();
40758
40933
  }
40759
- if (this.#text.length > 0 && (this.#messageId !== messageId || this.#text.length + text2.length > this.#maximumTextLength)) {
40760
- this.flush();
40934
+ let remaining = text2;
40935
+ while (remaining.length > 0) {
40936
+ const latest = this.#entries.at(-1);
40937
+ if (latest?.kind === "text" && latest.messageId === messageId) {
40938
+ const available = AGENT_EVENT_TEXT_MAXIMUM_LENGTH - latest.text.length;
40939
+ if (available > 0) {
40940
+ this.#entries = [
40941
+ ...this.#entries.slice(0, -1),
40942
+ { ...latest, text: `${latest.text}${remaining.slice(0, available)}` }
40943
+ ];
40944
+ remaining = remaining.slice(available);
40945
+ continue;
40946
+ }
40947
+ }
40948
+ this.#entries = [
40949
+ ...this.#entries,
40950
+ {
40951
+ kind: "text",
40952
+ messageId,
40953
+ text: remaining.slice(0, AGENT_EVENT_TEXT_MAXIMUM_LENGTH)
40954
+ }
40955
+ ];
40956
+ remaining = remaining.slice(AGENT_EVENT_TEXT_MAXIMUM_LENGTH);
40761
40957
  }
40762
- this.#messageId = messageId;
40763
- this.#text = `${this.#text}${text2}`;
40764
- this.#scheduled ??= this.#timer.schedule(this.flush, this.#coalescingMilliseconds);
40958
+ this.schedule();
40959
+ return Promise.resolve();
40765
40960
  };
40961
+ schedule() {
40962
+ this.#scheduled ??= this.#timer.schedule(this.flush, AGENT_EVENT_COALESCING_MILLISECONDS);
40963
+ }
40766
40964
  };
40767
40965
 
40768
40966
  // src/daemon-prompt-executor.ts
40769
- var AGENT_TEXT_COALESCING_MILLISECONDS = 100;
40770
- var AGENT_TEXT_MAXIMUM_LENGTH = 1e5;
40771
40967
  function daemonActivity(command, activity2) {
40772
40968
  return {
40773
40969
  activityId: activity2.activityId,
@@ -40803,41 +40999,30 @@ async function executePrompt({
40803
40999
  recordLiveEvent,
40804
41000
  cancellationRequested
40805
41001
  }) {
40806
- const narration = new CoalescingNarrationPublisher(
40807
- timer,
40808
- (increment) => {
40809
- const event = {
40810
- activityId: increment.activityId,
40811
- activityType: increment.activityType,
41002
+ const events = new CoalescingAgentEventPublisher(timer, (event) => {
41003
+ if (event.kind === "text") {
41004
+ publisher.publish(
41005
+ command.sessionId,
41006
+ recordLiveEvent({ kind: AGENT_MESSAGE_DELTA_KIND, messageId: event.messageId, text: event.text })
41007
+ );
41008
+ return;
41009
+ }
41010
+ if (event.kind === "narration") {
41011
+ const recorded = {
41012
+ activityId: event.increment.activityId,
41013
+ activityType: event.increment.activityType,
40812
41014
  commandId: command.commandId,
40813
41015
  kind: AGENT_ACTIVITY_NARRATION_KIND,
40814
- sequence: increment.sequence,
41016
+ sequence: event.increment.sequence,
40815
41017
  sessionId: command.sessionId,
40816
- text: increment.text
41018
+ text: event.increment.text
40817
41019
  };
40818
- publisher.publish(command.sessionId, recordLiveEvent(event));
40819
- },
40820
- AGENT_ACTIVITY_COALESCING_MILLISECONDS,
40821
- AGENT_TEXT_MAXIMUM_LENGTH
40822
- );
40823
- const activities = new CoalescingDaemonActivityPublisher(timer, (activity2) => {
40824
- if (activity2.status !== "pending" && activity2.status !== "running") {
40825
- narration.flush();
41020
+ publisher.publish(command.sessionId, recordLiveEvent(recorded));
41021
+ return;
40826
41022
  }
40827
- const event = daemonActivity(command, activity2);
40828
- publisher.publish(command.sessionId, recordLiveEvent(event));
41023
+ const activity2 = daemonActivity(command, event.activity);
41024
+ publisher.publish(command.sessionId, recordLiveEvent(activity2));
40829
41025
  });
40830
- const text2 = new CoalescingTextPublisher(
40831
- timer,
40832
- (messageId, delta) => {
40833
- publisher.publish(
40834
- command.sessionId,
40835
- recordLiveEvent({ kind: AGENT_MESSAGE_DELTA_KIND, messageId, text: delta })
40836
- );
40837
- },
40838
- AGENT_TEXT_COALESCING_MILLISECONDS,
40839
- AGENT_TEXT_MAXIMUM_LENGTH
40840
- );
40841
41026
  try {
40842
41027
  const resolved = await resolveSessionDirectories(
40843
41028
  directories,
@@ -40926,15 +41111,9 @@ async function executePrompt({
40926
41111
  cwd: resolved.cwd,
40927
41112
  disposition: availability.disposition,
40928
41113
  images: attachments.images,
40929
- onActivity: activities.record,
40930
- onNarration: (increment) => {
40931
- narration.record(increment);
40932
- return Promise.resolve();
40933
- },
40934
- onText: (delta, messageId) => {
40935
- text2.record(messageId, delta);
40936
- return Promise.resolve();
40937
- },
41114
+ onActivity: events.recordActivity,
41115
+ onNarration: events.recordNarration,
41116
+ onText: events.recordText,
40938
41117
  prompt: command.prompt,
40939
41118
  resources: attachments.resources,
40940
41119
  sessionId: command.sessionId,
@@ -40943,9 +41122,7 @@ async function executePrompt({
40943
41122
  });
40944
41123
  stopReason = result.stopReason;
40945
41124
  }
40946
- text2.flush();
40947
- narration.flush();
40948
- activities.flush();
41125
+ events.flush();
40949
41126
  publisher.publish(command.sessionId, {
40950
41127
  commandId: command.commandId,
40951
41128
  kind: SESSION_COMPLETED_KIND,
@@ -40959,9 +41136,7 @@ async function executePrompt({
40959
41136
  sessionId: command.sessionId
40960
41137
  });
40961
41138
  } catch (error62) {
40962
- text2.flush();
40963
- narration.flush();
40964
- activities.flush();
41139
+ events.flush();
40965
41140
  if (signal.aborted && cancellationRequested()) {
40966
41141
  publisher.publish(command.sessionId, {
40967
41142
  commandId: command.commandId,