@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/index.js CHANGED
@@ -20955,7 +20955,7 @@ var userHistoryMessage = external_exports.strictObject({
20955
20955
  text: external_exports.string().max(SESSION_HISTORY_CHARACTER_LIMIT),
20956
20956
  images: external_exports.array(historyImage).max(8).readonly().optional()
20957
20957
  }).readonly();
20958
- var assistantHistoryMessage = external_exports.strictObject({
20958
+ var assistantHistoryMessageSchema = external_exports.strictObject({
20959
20959
  activities: external_exports.array(nativeMessageActivitySchema).max(100).readonly().default([]),
20960
20960
  content: external_exports.array(displayContentSchema).max(100).readonly().default([]),
20961
20961
  role: external_exports.literal("assistant"),
@@ -20964,7 +20964,7 @@ var assistantHistoryMessage = external_exports.strictObject({
20964
20964
  text: external_exports.string().max(SESSION_HISTORY_CHARACTER_LIMIT),
20965
20965
  images: external_exports.array(historyImage).max(8).readonly().optional()
20966
20966
  }).readonly();
20967
- var historyMessage = external_exports.discriminatedUnion("role", [userHistoryMessage, assistantHistoryMessage]);
20967
+ var historyMessage = external_exports.discriminatedUnion("role", [userHistoryMessage, assistantHistoryMessageSchema]);
20968
20968
  var availableSessionHistoryObjectSchema = external_exports.strictObject({
20969
20969
  status: external_exports.literal("available"),
20970
20970
  messages: external_exports.array(historyMessage).max(SESSION_HISTORY_MESSAGE_LIMIT).readonly(),
@@ -21035,6 +21035,7 @@ var activeTurnSnapshotSchema = external_exports.strictObject({
21035
21035
  truncated: external_exports.boolean(),
21036
21036
  epoch: identifierStringSchema,
21037
21037
  interaction: external_exports.discriminatedUnion("kind", [sessionPermissionRequestedEventSchema, sessionElicitationRequestedEventSchema]).nullable(),
21038
+ messages: external_exports.array(assistantHistoryMessageSchema).max(SESSION_HISTORY_MESSAGE_LIMIT).readonly(),
21038
21039
  sequence: external_exports.number().int().nonnegative(),
21039
21040
  state: external_exports.literal("running")
21040
21041
  }).readonly();
@@ -23729,6 +23730,48 @@ var AgentUpdateStream = class {
23729
23730
  };
23730
23731
  };
23731
23732
 
23733
+ // src/acp/runtime-operations.ts
23734
+ var RuntimeOperations = class {
23735
+ #shutdown = new AbortController();
23736
+ #pending = /* @__PURE__ */ new Set();
23737
+ #closing = null;
23738
+ run = async (options, operation) => {
23739
+ const signal = AbortSignal.any([options.signal, this.#shutdown.signal]);
23740
+ signal.throwIfAborted();
23741
+ const pending = Promise.resolve().then(() => operation({ ...options, signal }));
23742
+ this.#pending.add(pending);
23743
+ try {
23744
+ const result = await pending;
23745
+ signal.throwIfAborted();
23746
+ return result;
23747
+ } finally {
23748
+ this.#pending.delete(pending);
23749
+ }
23750
+ };
23751
+ close = (release) => {
23752
+ if (this.#closing !== null) {
23753
+ return this.#closing;
23754
+ }
23755
+ this.#shutdown.abort();
23756
+ this.#closing = (async () => {
23757
+ await Promise.allSettled([...this.#pending]);
23758
+ await release();
23759
+ })();
23760
+ return this.#closing;
23761
+ };
23762
+ };
23763
+ async function waitForSharedOperation(pending, signal) {
23764
+ signal.throwIfAborted();
23765
+ const cancelled = Promise.withResolvers();
23766
+ const abort = () => cancelled.reject(signal.reason);
23767
+ signal.addEventListener("abort", abort, { once: true });
23768
+ try {
23769
+ return await Promise.race([pending, cancelled.promise]);
23770
+ } finally {
23771
+ signal.removeEventListener("abort", abort);
23772
+ }
23773
+ }
23774
+
23732
23775
  // src/acp/session-config/session-config-protocol.ts
23733
23776
  import { methods as methods2 } from "@agentclientprotocol/sdk";
23734
23777
  var MAXIMUM_CONFIG_OPTIONS = 100;
@@ -30425,9 +30468,7 @@ var AgentSession = class _AgentSession {
30425
30468
  #configOptions = [];
30426
30469
  #prompted = false;
30427
30470
  #nativePrompt = null;
30428
- #replay = {
30429
- kind: "idle"
30430
- };
30471
+ #sessionLoad = { kind: "not-requested" };
30431
30472
  #restored = false;
30432
30473
  #sessionTitle = null;
30433
30474
  #sessionUpdatedAt = "";
@@ -30540,30 +30581,46 @@ var AgentSession = class _AgentSession {
30540
30581
  }
30541
30582
  };
30542
30583
  }
30543
- const history = new AcpHistoryReplay();
30544
- this.#replay = { kind: "capture", history };
30545
- try {
30546
- await this.race(
30547
- this.#connection.connection.agent.request(
30548
- methods3.agent.session.load,
30549
- {
30550
- additionalDirectories: [...this.#additionalDirectories],
30551
- cwd: this.#cwd,
30552
- mcpServers: [],
30553
- sessionId: this.#updates.sessionId()
30554
- },
30555
- { cancellationSignal: signal }
30556
- ),
30557
- "ACP agent exited while loading history",
30558
- signal
30559
- );
30560
- await this.#updates.drained();
30561
- signal.throwIfAborted();
30562
- return await embedLocalHistoryImages(await history.snapshot(), signal);
30563
- } finally {
30564
- this.#replay = { kind: "idle" };
30565
- }
30584
+ const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
30585
+ return await embedLocalHistoryImages(await loaded.history.snapshot(), signal);
30566
30586
  };
30587
+ async #loadSession(signal, exitMessage) {
30588
+ if (this.#sessionLoad.kind === "loaded") {
30589
+ return this.#sessionLoad;
30590
+ }
30591
+ if (this.#sessionLoad.kind === "capturing") {
30592
+ return await waitForSharedOperation(this.#sessionLoad.completion, signal);
30593
+ }
30594
+ const history = new AcpHistoryReplay();
30595
+ const completion = Promise.resolve().then(async () => {
30596
+ try {
30597
+ const response = await this.race(
30598
+ this.#connection.connection.agent.request(
30599
+ methods3.agent.session.load,
30600
+ {
30601
+ additionalDirectories: [...this.#additionalDirectories],
30602
+ cwd: this.#cwd,
30603
+ mcpServers: [],
30604
+ sessionId: this.#updates.sessionId()
30605
+ },
30606
+ { cancellationSignal: signal }
30607
+ ),
30608
+ exitMessage,
30609
+ signal
30610
+ );
30611
+ await this.#updates.drained();
30612
+ signal.throwIfAborted();
30613
+ const loaded = { history, kind: "loaded", response };
30614
+ this.#sessionLoad = loaded;
30615
+ return loaded;
30616
+ } catch (cause) {
30617
+ this.#sessionLoad = { kind: "not-requested" };
30618
+ throw cause;
30619
+ }
30620
+ });
30621
+ this.#sessionLoad = { completion, history, kind: "capturing" };
30622
+ return await completion;
30623
+ }
30567
30624
  prepareAgentContent = async (content) => {
30568
30625
  if (content.type === "image" && content.uri.length > 0) {
30569
30626
  const signal = AbortSignal.timeout(2e4);
@@ -30766,29 +30823,10 @@ var AgentSession = class _AgentSession {
30766
30823
  )
30767
30824
  );
30768
30825
  } else if (this.#capabilities.loadSession) {
30769
- this.#replay = { kind: "discard" };
30770
- try {
30771
- lifecycleResponse = await this.#metrics.measure(
30772
- "session-load",
30773
- async () => await this.race(
30774
- this.#connection.connection.agent.request(
30775
- methods3.agent.session.load,
30776
- {
30777
- additionalDirectories: [...this.#additionalDirectories],
30778
- cwd: this.#cwd,
30779
- mcpServers: [],
30780
- sessionId: this.#updates.sessionId()
30781
- },
30782
- { cancellationSignal: signal }
30783
- ),
30784
- "ACP agent exited while loading a session",
30785
- signal
30786
- )
30787
- );
30788
- } finally {
30789
- await this.#updates.drained();
30790
- this.#replay = { kind: "idle" };
30791
- }
30826
+ lifecycleResponse = await this.#metrics.measure(
30827
+ "session-load",
30828
+ async () => (await this.#loadSession(signal, "ACP agent exited while loading a session")).response
30829
+ );
30792
30830
  } else {
30793
30831
  throw new AcpExecutionError(
30794
30832
  "The ACP agent cannot restore its persisted session",
@@ -31173,10 +31211,10 @@ var AgentSession = class _AgentSession {
31173
31211
  #processUpdate = async (notification) => {
31174
31212
  this.assertNativeSession(notification.sessionId);
31175
31213
  const update = notification.update;
31176
- if (this.#replay.kind === "capture") {
31177
- await this.#replay.history.record(update);
31214
+ if (this.#sessionLoad.kind !== "not-requested") {
31215
+ await this.#sessionLoad.history.record(update);
31178
31216
  }
31179
- 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")) {
31217
+ 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")) {
31180
31218
  return;
31181
31219
  }
31182
31220
  if (update.sessionUpdate === "agent_message_chunk") {
@@ -31446,48 +31484,6 @@ var RetainedAgentProcesses = class {
31446
31484
  };
31447
31485
  };
31448
31486
 
31449
- // src/acp/runtime-operations.ts
31450
- var RuntimeOperations = class {
31451
- #shutdown = new AbortController();
31452
- #pending = /* @__PURE__ */ new Set();
31453
- #closing = null;
31454
- run = async (options, operation) => {
31455
- const signal = AbortSignal.any([options.signal, this.#shutdown.signal]);
31456
- signal.throwIfAborted();
31457
- const pending = Promise.resolve().then(() => operation({ ...options, signal }));
31458
- this.#pending.add(pending);
31459
- try {
31460
- const result = await pending;
31461
- signal.throwIfAborted();
31462
- return result;
31463
- } finally {
31464
- this.#pending.delete(pending);
31465
- }
31466
- };
31467
- close = (release) => {
31468
- if (this.#closing !== null) {
31469
- return this.#closing;
31470
- }
31471
- this.#shutdown.abort();
31472
- this.#closing = (async () => {
31473
- await Promise.allSettled([...this.#pending]);
31474
- await release();
31475
- })();
31476
- return this.#closing;
31477
- };
31478
- };
31479
- async function waitForPreparation(pending, signal) {
31480
- signal.throwIfAborted();
31481
- const cancelled = Promise.withResolvers();
31482
- const abort = () => cancelled.reject(signal.reason);
31483
- signal.addEventListener("abort", abort, { once: true });
31484
- try {
31485
- return await Promise.race([pending, cancelled.promise]);
31486
- } finally {
31487
- signal.removeEventListener("abort", abort);
31488
- }
31489
- }
31490
-
31491
31487
  // src/acp/agent-query-processes.ts
31492
31488
  var AgentQueryProcesses = class {
31493
31489
  #processesByQuery;
@@ -31534,7 +31530,7 @@ var AgentQueryProcesses = class {
31534
31530
  prepare = async (options) => {
31535
31531
  const pending = this.#processesByQuery.pending(options.sessionId);
31536
31532
  if (pending !== void 0) {
31537
- const runtime2 = await waitForPreparation(pending, options.signal);
31533
+ const runtime2 = await waitForSharedOperation(pending, options.signal);
31538
31534
  if (runtime2.belongsTo(options.agent.id, options.cwd, options.additionalDirectories)) {
31539
31535
  this.#processesByQuery.touch(options.sessionId, runtime2);
31540
31536
  return runtime2.prepared();
@@ -31952,7 +31948,7 @@ var AgentRuntimeManager = class {
31952
31948
  if (pending !== void 0) {
31953
31949
  const runtime2 = await metrics.measure(
31954
31950
  "session-preparation-wait",
31955
- async () => await waitForPreparation(pending, options2.signal)
31951
+ async () => await waitForSharedOperation(pending, options2.signal)
31956
31952
  );
31957
31953
  if (runtime2.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
31958
31954
  this.#executionProcesses.touch(options2.sessionId, runtime2);
@@ -32042,7 +32038,7 @@ var AgentRuntimeManager = class {
32042
32038
  prepareExecutionSession = async (options) => this.#operations.run(options, async (options2) => {
32043
32039
  const pending = this.#executionProcesses.pending(options2.sessionId);
32044
32040
  if (pending !== void 0) {
32045
- await waitForPreparation(pending, options2.signal);
32041
+ await waitForSharedOperation(pending, options2.signal);
32046
32042
  return await this.prepareExecutionSession(options2);
32047
32043
  }
32048
32044
  const existing = this.#executionProcesses.get(options2.sessionId);
@@ -32096,7 +32092,7 @@ var AgentRuntimeManager = class {
32096
32092
  }
32097
32093
  const pending = this.#executionProcesses.pending(options2.sessionId);
32098
32094
  if (pending !== void 0) {
32099
- await waitForPreparation(pending, options2.signal);
32095
+ await waitForSharedOperation(pending, options2.signal);
32100
32096
  }
32101
32097
  if (this.#executions.command(options2.sessionId) !== options2.targetCommandId) {
32102
32098
  throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
@@ -38662,6 +38658,7 @@ var ActiveDaemonTurn = class {
38662
38658
  #text = "";
38663
38659
  #activities = /* @__PURE__ */ new Map();
38664
38660
  #content = /* @__PURE__ */ new Map();
38661
+ #timeline = [];
38665
38662
  #sequence = 0;
38666
38663
  #interaction = null;
38667
38664
  #epoch = decodeIdentifier(randomUUID2());
@@ -38705,12 +38702,16 @@ var ActiveDaemonTurn = class {
38705
38702
  recordEvent = (event) => {
38706
38703
  if (event.kind === AGENT_MESSAGE_DELTA_KIND) {
38707
38704
  this.#text += event.text;
38705
+ this.appendMessageText(event.messageId, event.text);
38708
38706
  return this.updated();
38709
38707
  }
38710
38708
  if (event.sessionId !== this.command.sessionId || "commandId" in event && event.commandId !== this.command.commandId) {
38711
38709
  return event;
38712
38710
  }
38713
38711
  if (event.kind === AGENT_ACTIVITY_KIND) {
38712
+ if (!this.#activities.has(event.activityId)) {
38713
+ this.#timeline = [...this.#timeline, { activityId: event.activityId, kind: "activity" }];
38714
+ }
38714
38715
  this.#activities.set(event.activityId, {
38715
38716
  activityId: event.activityId,
38716
38717
  activityType: event.activityType,
@@ -38726,6 +38727,9 @@ var ActiveDaemonTurn = class {
38726
38727
  });
38727
38728
  } else if (event.kind === AGENT_ACTIVITY_NARRATION_KIND) {
38728
38729
  const previous = this.#activities.get(event.activityId);
38730
+ if (previous === void 0) {
38731
+ this.#timeline = [...this.#timeline, { activityId: event.activityId, kind: "activity" }];
38732
+ }
38729
38733
  this.#activities.set(event.activityId, {
38730
38734
  activityId: event.activityId,
38731
38735
  activityType: event.activityType,
@@ -38741,6 +38745,24 @@ var ActiveDaemonTurn = class {
38741
38745
  });
38742
38746
  } else if (event.kind === AGENT_CONTENT_KIND) {
38743
38747
  this.#content.set(event.contentId, event.content);
38748
+ const target = this.#timeline.findLastIndex(
38749
+ (entry) => entry.kind === "message" && entry.messageId === event.messageId
38750
+ );
38751
+ if (target < 0) {
38752
+ this.#timeline = [
38753
+ ...this.#timeline,
38754
+ {
38755
+ content: /* @__PURE__ */ new Map([[event.contentId, event.content]]),
38756
+ kind: "message",
38757
+ messageId: event.messageId,
38758
+ text: ""
38759
+ }
38760
+ ];
38761
+ } else {
38762
+ this.#timeline = this.#timeline.map(
38763
+ (entry, index) => index === target && entry.kind === "message" ? { ...entry, content: new Map([...entry.content, [event.contentId, event.content]]) } : entry
38764
+ );
38765
+ }
38744
38766
  } else if (event.kind === SESSION_PERMISSION_REQUESTED_KIND || event.kind === SESSION_ELICITATION_REQUESTED_KIND) {
38745
38767
  this.#interaction = event;
38746
38768
  } else if ((event.kind === SESSION_PERMISSION_RESOLVED_KIND || event.kind === SESSION_ELICITATION_RESOLVED_KIND) && this.#interaction?.interactionId === event.interactionId) {
@@ -38751,6 +38773,49 @@ var ActiveDaemonTurn = class {
38751
38773
  }
38752
38774
  return event;
38753
38775
  };
38776
+ appendMessageText(messageId, text2) {
38777
+ let remaining = text2;
38778
+ while (remaining.length > 0) {
38779
+ const latest = this.#timeline.at(-1);
38780
+ if (latest?.kind === "message" && latest.messageId === messageId) {
38781
+ const available = SESSION_HISTORY_CHARACTER_LIMIT - latest.text.length;
38782
+ if (available > 0) {
38783
+ this.#timeline = [
38784
+ ...this.#timeline.slice(0, -1),
38785
+ { ...latest, text: `${latest.text}${remaining.slice(0, available)}` }
38786
+ ];
38787
+ remaining = remaining.slice(available);
38788
+ continue;
38789
+ }
38790
+ }
38791
+ this.#timeline = [
38792
+ ...this.#timeline,
38793
+ {
38794
+ content: /* @__PURE__ */ new Map(),
38795
+ kind: "message",
38796
+ messageId,
38797
+ text: remaining.slice(0, SESSION_HISTORY_CHARACTER_LIMIT)
38798
+ }
38799
+ ];
38800
+ remaining = remaining.slice(SESSION_HISTORY_CHARACTER_LIMIT);
38801
+ }
38802
+ }
38803
+ timelineMessages() {
38804
+ return this.#timeline.flatMap((entry) => {
38805
+ if (entry.kind === "message") {
38806
+ return [
38807
+ {
38808
+ activities: [],
38809
+ content: [...entry.content.values()],
38810
+ role: "assistant",
38811
+ text: entry.text
38812
+ }
38813
+ ];
38814
+ }
38815
+ const activity2 = this.#activities.get(entry.activityId);
38816
+ return activity2 === void 0 ? [] : [{ activities: [activity2], content: [], role: "assistant", text: "" }];
38817
+ });
38818
+ }
38754
38819
  updated = () => {
38755
38820
  this.#sequence += 1;
38756
38821
  const turn = this.snapshot();
@@ -38759,18 +38824,26 @@ var ActiveDaemonTurn = class {
38759
38824
  }
38760
38825
  return { kind: "session.turn.updated", sessionId: this.command.sessionId, turn };
38761
38826
  };
38762
- snapshot = () => this.#dispatch.kind === "running" ? {
38763
- activities: [...this.#activities.values()].sort((left, right) => left.sequence - right.sequence),
38764
- commandId: decodeIdentifier(this.command.commandId),
38765
- content: [...this.#content.values()],
38766
- prompt: this.command.prompt,
38767
- text: this.#text,
38768
- truncated: false,
38769
- epoch: this.#epoch,
38770
- interaction: this.#interaction,
38771
- sequence: this.#sequence,
38772
- state: "running"
38773
- } : null;
38827
+ snapshot = () => {
38828
+ if (this.#dispatch.kind !== "running") {
38829
+ return null;
38830
+ }
38831
+ const completeMessages = this.timelineMessages();
38832
+ const messages = completeMessages.slice(-SESSION_HISTORY_MESSAGE_LIMIT);
38833
+ return {
38834
+ activities: [...this.#activities.values()].sort((left, right) => left.sequence - right.sequence),
38835
+ commandId: decodeIdentifier(this.command.commandId),
38836
+ content: [...this.#content.values()],
38837
+ prompt: this.command.prompt,
38838
+ text: this.#text,
38839
+ truncated: messages.length !== completeMessages.length,
38840
+ epoch: this.#epoch,
38841
+ interaction: this.#interaction,
38842
+ messages,
38843
+ sequence: this.#sequence,
38844
+ state: "running"
38845
+ };
38846
+ };
38774
38847
  matches = (cancellation) => cancellation.commandId === this.command.commandId && cancellation.sessionId === this.command.sessionId;
38775
38848
  matchesInteraction = (interactionId, sessionId) => this.command.sessionId === sessionId && this.#interaction?.interactionId === interactionId;
38776
38849
  requestCancellation = () => {
@@ -38956,15 +39029,21 @@ var turnsSchema = external_exports.object({
38956
39029
  });
38957
39030
  var itemTypeSchema = external_exports.object({ type: external_exports.string().min(1).max(80) });
38958
39031
  var userMessageSchema = external_exports.object({
38959
- content: external_exports.array(external_exports.unknown()).max(1e4)
39032
+ content: external_exports.array(external_exports.unknown()).max(1e4),
39033
+ type: external_exports.literal("userMessage")
38960
39034
  });
38961
39035
  var textSchema = external_exports.object({ text: external_exports.string() });
38962
39036
  var imageSchema = external_exports.object({ url: external_exports.string() });
38963
- var agentMessageSchema = textSchema.extend({ phase: external_exports.string().nullish() });
39037
+ var agentMessageSchema = textSchema.extend({
39038
+ id: external_exports.string().optional(),
39039
+ phase: external_exports.string().nullish(),
39040
+ type: external_exports.literal("agentMessage")
39041
+ });
38964
39042
  var reasoningSchema = external_exports.object({
38965
39043
  id: external_exports.string(),
38966
39044
  summary: external_exports.array(external_exports.string()).max(1e4),
38967
- content: external_exports.array(external_exports.string()).max(1e4)
39045
+ content: external_exports.array(external_exports.string()).max(1e4),
39046
+ type: external_exports.literal("reasoning")
38968
39047
  });
38969
39048
  var commandExecutionSchema = external_exports.object({
38970
39049
  id: external_exports.string(),
@@ -38973,8 +39052,45 @@ var commandExecutionSchema = external_exports.object({
38973
39052
  status: external_exports.string(),
38974
39053
  commandActions: external_exports.array(external_exports.object({ type: external_exports.string() }).passthrough()).max(100),
38975
39054
  aggregatedOutput: external_exports.string().nullish(),
38976
- exitCode: external_exports.number().int().nullish()
39055
+ exitCode: external_exports.number().int().nullish(),
39056
+ type: external_exports.literal("commandExecution")
39057
+ });
39058
+ var fileChangeSchema = external_exports.object({
39059
+ changes: external_exports.array(external_exports.object({ diff: external_exports.string(), path: external_exports.string() })).max(1e4),
39060
+ id: external_exports.string(),
39061
+ status: external_exports.string(),
39062
+ type: external_exports.literal("fileChange")
39063
+ });
39064
+ var mcpToolCallSchema = external_exports.object({
39065
+ arguments: external_exports.unknown().optional(),
39066
+ error: external_exports.unknown().nullish(),
39067
+ id: external_exports.string(),
39068
+ result: external_exports.unknown().nullish(),
39069
+ server: external_exports.string(),
39070
+ status: external_exports.string(),
39071
+ tool: external_exports.string(),
39072
+ type: external_exports.literal("mcpToolCall")
39073
+ });
39074
+ var dynamicToolCallSchema = external_exports.object({
39075
+ arguments: external_exports.unknown().optional(),
39076
+ contentItems: external_exports.array(external_exports.unknown()).max(1e4).nullish(),
39077
+ id: external_exports.string(),
39078
+ namespace: external_exports.string().nullish(),
39079
+ status: external_exports.string(),
39080
+ tool: external_exports.string(),
39081
+ type: external_exports.literal("dynamicToolCall")
38977
39082
  });
39083
+ var planSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), type: external_exports.literal("plan") });
39084
+ var historyItemSchema = external_exports.discriminatedUnion("type", [
39085
+ userMessageSchema,
39086
+ agentMessageSchema,
39087
+ reasoningSchema,
39088
+ commandExecutionSchema,
39089
+ fileChangeSchema,
39090
+ mcpToolCallSchema,
39091
+ dynamicToolCallSchema,
39092
+ planSchema
39093
+ ]);
38978
39094
  function bounded(value, maximum) {
38979
39095
  return value.slice(0, maximum);
38980
39096
  }
@@ -39005,6 +39121,33 @@ function errorMessage(value) {
39005
39121
  }
39006
39122
  return JSON.stringify(value) ?? "Codex stopped before completing this turn.";
39007
39123
  }
39124
+ function formatted(value) {
39125
+ if (value === void 0) {
39126
+ return "";
39127
+ }
39128
+ if (typeof value === "string") {
39129
+ return value;
39130
+ }
39131
+ return JSON.stringify(value) ?? "";
39132
+ }
39133
+ function toolStatus(status) {
39134
+ return status === "inProgress" ? "running" : status === "completed" ? "completed" : "failed";
39135
+ }
39136
+ function diffDisplayContent(path2, newText) {
39137
+ return {
39138
+ artifactId: "",
39139
+ data: "",
39140
+ mimeType: "",
39141
+ name: "",
39142
+ newText,
39143
+ oldText: "",
39144
+ path: path2,
39145
+ terminalId: "",
39146
+ text: "",
39147
+ type: "diff",
39148
+ uri: ""
39149
+ };
39150
+ }
39008
39151
  function messageSize(message) {
39009
39152
  return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
39010
39153
  }
@@ -39042,8 +39185,8 @@ function fitActivities(activities, maximumCharacters) {
39042
39185
  const maximumActivityCharacters = Math.floor(Math.max(0, maximumCharacters - arrayCharacters) / activities.length);
39043
39186
  return activities.map((activity2) => fitActivity(activity2, maximumActivityCharacters));
39044
39187
  }
39045
- function fitHistoryMessage(message) {
39046
- const text2 = message.text.slice(-SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT);
39188
+ function fitHistoryMessage(message, maximumCharacters = SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT) {
39189
+ const text2 = message.text.slice(-maximumCharacters);
39047
39190
  if (message.role === "user") {
39048
39191
  return {
39049
39192
  message: { ...message, text: text2 },
@@ -39053,12 +39196,12 @@ function fitHistoryMessage(message) {
39053
39196
  let activities = message.activities;
39054
39197
  const content = message.content;
39055
39198
  let fitted = { ...message, activities, content, text: text2 };
39056
- if (messageSize(fitted) > SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT && activities.length > 0) {
39057
- const maximumCharacters = SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT - text2.length - JSON.stringify(content).length;
39058
- activities = fitActivities(activities, maximumCharacters);
39199
+ if (messageSize(fitted) > maximumCharacters && activities.length > 0) {
39200
+ const maximumActivityCharacters = maximumCharacters - text2.length - JSON.stringify(content).length;
39201
+ activities = fitActivities(activities, maximumActivityCharacters);
39059
39202
  fitted = { ...fitted, activities };
39060
39203
  }
39061
- const excess = Math.max(0, messageSize(fitted) - SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT);
39204
+ const excess = Math.max(0, messageSize(fitted) - maximumCharacters);
39062
39205
  if (excess > 0) {
39063
39206
  const maximumTextLength = Math.max(0, fitted.text.length - excess);
39064
39207
  fitted = {
@@ -39096,128 +39239,209 @@ function decodeHistory(thread, value, options) {
39096
39239
  let truncated = page.nextCursor != null;
39097
39240
  for (const turn of page.data.toReversed()) {
39098
39241
  const outcome = turnOutcome(turn.status);
39099
- const activities = [];
39100
- let assignedActivityCount = 0;
39242
+ const turnMessageCharacterLimit = Math.max(
39243
+ 1,
39244
+ Math.floor(SESSION_HISTORY_CHARACTER_LIMIT / Math.max(1, turn.items.length + (turn.error == null ? 0 : 1)))
39245
+ );
39101
39246
  let sequence = 0;
39102
39247
  let assistantMessageIndex = null;
39103
- const activitySlice = () => {
39104
- const assigned = activities.slice(assignedActivityCount).slice(-100);
39105
- assignedActivityCount = activities.length;
39106
- return assigned;
39248
+ const append = (message) => {
39249
+ const fitted = fitHistoryMessage(message, turnMessageCharacterLimit);
39250
+ 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)) {
39251
+ return;
39252
+ }
39253
+ truncated ||= fitted.truncated;
39254
+ messages.push(fitted.message);
39255
+ if (fitted.message.role === "assistant") {
39256
+ assistantMessageIndex = messages.length - 1;
39257
+ }
39258
+ characters += messageSize(fitted.message);
39107
39259
  };
39108
39260
  for (const item of turn.items) {
39109
- const { type } = itemTypeSchema.parse(item);
39110
- let message;
39111
- if (type === "userMessage") {
39112
- const { content } = userMessageSchema.parse(item);
39113
- const text2 = content.map((block) => {
39114
- const { type: type2 } = itemTypeSchema.parse(block);
39115
- if (type2 === "text") {
39261
+ const decoded = historyItemSchema.safeParse(item);
39262
+ if (!decoded.success) {
39263
+ continue;
39264
+ }
39265
+ const historyItem = decoded.data;
39266
+ if (historyItem.type === "userMessage") {
39267
+ const text2 = historyItem.content.map((block) => {
39268
+ const { type } = itemTypeSchema.parse(block);
39269
+ if (type === "text") {
39116
39270
  return textSchema.parse(block).text;
39117
39271
  }
39118
- if (type2 === "image") {
39272
+ if (type === "image") {
39119
39273
  return `[@image](${imageSchema.parse(block).url})`;
39120
39274
  }
39121
39275
  return "[Attachment]";
39122
39276
  }).join("");
39123
- message = {
39277
+ append({
39124
39278
  role: "user",
39125
39279
  text: text2
39126
- };
39127
- } else if (type === "agentMessage") {
39128
- const agent = agentMessageSchema.parse(item);
39129
- if (agent.phase === "commentary") {
39130
- if (options.detail === "rich" && agent.text.length > 0) {
39131
- activities.push(
39132
- activity(`progress-${sequence.toString()}`, "progress", sequence, {
39280
+ });
39281
+ } else if (historyItem.type === "agentMessage") {
39282
+ if (historyItem.phase === "commentary") {
39283
+ if (options.detail === "rich" && historyItem.text.length > 0) {
39284
+ append({
39285
+ activities: [
39286
+ activity(historyItem.id ?? `progress-${sequence.toString()}`, "progress", sequence, {
39287
+ input: "",
39288
+ locations: [],
39289
+ name: "",
39290
+ output: historyItem.text,
39291
+ status: "completed",
39292
+ title: "Progress",
39293
+ toolKind: ""
39294
+ })
39295
+ ],
39296
+ content: [],
39297
+ role: "assistant",
39298
+ text: ""
39299
+ });
39300
+ sequence += 1;
39301
+ }
39302
+ continue;
39303
+ }
39304
+ append({ activities: [], content: [], role: "assistant", text: historyItem.text });
39305
+ } else if (historyItem.type === "reasoning" && options.detail === "rich") {
39306
+ const output2 = (historyItem.summary.length > 0 ? historyItem.summary : historyItem.content).join(
39307
+ "\n\n"
39308
+ );
39309
+ if (output2.length > 0) {
39310
+ append({
39311
+ activities: [
39312
+ activity(historyItem.id, "reasoning", sequence, {
39133
39313
  input: "",
39134
39314
  locations: [],
39135
39315
  name: "",
39136
- output: agent.text,
39316
+ output: output2,
39137
39317
  status: "completed",
39138
- title: "Progress",
39318
+ title: "Reasoning",
39139
39319
  toolKind: ""
39140
39320
  })
39141
- );
39142
- sequence += 1;
39143
- }
39144
- continue;
39321
+ ],
39322
+ content: [],
39323
+ role: "assistant",
39324
+ text: ""
39325
+ });
39326
+ sequence += 1;
39145
39327
  }
39146
- message = { activities: activitySlice(), content: [], role: "assistant", text: agent.text };
39147
- } else if (type === "reasoning" && options.detail === "rich") {
39148
- const reasoning = reasoningSchema.parse(item);
39149
- const output2 = (reasoning.summary.length > 0 ? reasoning.summary : reasoning.content).join("\n\n");
39150
- if (output2.length > 0) {
39151
- activities.push(
39152
- activity(reasoning.id, "reasoning", sequence, {
39328
+ } else if (historyItem.type === "commandExecution" && options.detail === "rich") {
39329
+ const action = historyItem.commandActions[0]?.type ?? "execute";
39330
+ append({
39331
+ activities: [
39332
+ activity(historyItem.id, "tool", sequence, {
39333
+ input: JSON.stringify({ command: historyItem.command, cwd: historyItem.cwd }),
39334
+ locations: [historyItem.cwd],
39335
+ name: "",
39336
+ output: JSON.stringify({
39337
+ formatted_output: historyItem.aggregatedOutput ?? "",
39338
+ ...historyItem.exitCode == null ? {} : { exit_code: historyItem.exitCode }
39339
+ }),
39340
+ status: toolStatus(historyItem.status),
39341
+ title: historyItem.command,
39342
+ toolKind: action
39343
+ })
39344
+ ],
39345
+ content: [],
39346
+ role: "assistant",
39347
+ text: ""
39348
+ });
39349
+ sequence += 1;
39350
+ } else if (historyItem.type === "fileChange" && options.detail === "rich") {
39351
+ const paths = historyItem.changes.map((change) => change.path);
39352
+ const content = historyItem.changes.map(
39353
+ (change) => diffDisplayContent(change.path, change.diff)
39354
+ );
39355
+ append({
39356
+ activities: [
39357
+ activity(historyItem.id, "tool", sequence, {
39358
+ input: JSON.stringify({ changes: paths }),
39359
+ locations: paths,
39360
+ name: "",
39361
+ output: "",
39362
+ status: toolStatus(historyItem.status),
39363
+ title: paths.join(", "),
39364
+ toolKind: "edit"
39365
+ })
39366
+ ].map((entry) => ({ ...entry, content })),
39367
+ content: [],
39368
+ role: "assistant",
39369
+ text: ""
39370
+ });
39371
+ sequence += 1;
39372
+ } else if (historyItem.type === "mcpToolCall" && options.detail === "rich") {
39373
+ append({
39374
+ activities: [
39375
+ activity(historyItem.id, "tool", sequence, {
39376
+ input: formatted(historyItem.arguments),
39377
+ locations: [],
39378
+ name: historyItem.tool,
39379
+ output: formatted(historyItem.error ?? historyItem.result),
39380
+ status: toolStatus(historyItem.status),
39381
+ title: `${historyItem.server}/${historyItem.tool}`,
39382
+ toolKind: "other"
39383
+ })
39384
+ ],
39385
+ content: [],
39386
+ role: "assistant",
39387
+ text: ""
39388
+ });
39389
+ sequence += 1;
39390
+ } else if (historyItem.type === "dynamicToolCall" && options.detail === "rich") {
39391
+ append({
39392
+ activities: [
39393
+ activity(historyItem.id, "tool", sequence, {
39394
+ input: formatted(historyItem.arguments),
39395
+ locations: [],
39396
+ name: historyItem.tool,
39397
+ output: formatted(historyItem.contentItems),
39398
+ status: toolStatus(historyItem.status),
39399
+ title: historyItem.namespace == null ? historyItem.tool : `${historyItem.namespace}/${historyItem.tool}`,
39400
+ toolKind: "other"
39401
+ })
39402
+ ],
39403
+ content: [],
39404
+ role: "assistant",
39405
+ text: ""
39406
+ });
39407
+ sequence += 1;
39408
+ } else if (historyItem.type === "plan" && options.detail === "rich") {
39409
+ append({
39410
+ activities: [
39411
+ activity(historyItem.id, "plan", sequence, {
39153
39412
  input: "",
39154
39413
  locations: [],
39155
39414
  name: "",
39156
- output: output2,
39415
+ output: historyItem.text,
39157
39416
  status: "completed",
39158
- title: "Reasoning",
39417
+ title: "Plan",
39159
39418
  toolKind: ""
39160
39419
  })
39161
- );
39162
- sequence += 1;
39163
- }
39164
- continue;
39165
- } else if (type === "commandExecution" && options.detail === "rich") {
39166
- const command = commandExecutionSchema.parse(item);
39167
- const action = command.commandActions[0]?.type ?? "execute";
39168
- activities.push(
39169
- activity(command.id, "tool", sequence, {
39170
- input: JSON.stringify({ command: command.command, cwd: command.cwd }),
39171
- locations: [command.cwd],
39172
- name: "",
39173
- output: JSON.stringify({
39174
- formatted_output: command.aggregatedOutput ?? "",
39175
- ...command.exitCode == null ? {} : { exit_code: command.exitCode }
39176
- }),
39177
- status: command.status === "completed" ? "completed" : "failed",
39178
- title: command.command,
39179
- toolKind: action
39180
- })
39181
- );
39420
+ ],
39421
+ content: [],
39422
+ role: "assistant",
39423
+ text: ""
39424
+ });
39182
39425
  sequence += 1;
39183
- continue;
39184
- } else {
39185
- continue;
39186
39426
  }
39187
- const fitted = fitHistoryMessage(message);
39188
- if (fitted.message.text.length === 0 && (fitted.message.images?.length ?? 0) === 0) {
39189
- continue;
39190
- }
39191
- truncated ||= fitted.truncated;
39192
- messages.push(fitted.message);
39193
- if (message.role === "assistant") {
39194
- assistantMessageIndex = messages.length - 1;
39195
- }
39196
- characters += messageSize(fitted.message);
39197
39427
  }
39198
39428
  if (options.detail === "rich" && turn.error != null) {
39199
- activities.push(
39200
- activity(`agent-error-${sequence.toString()}`, "tool", sequence, {
39201
- input: "",
39202
- locations: [],
39203
- name: "",
39204
- output: errorMessage(turn.error),
39205
- status: "failed",
39206
- title: "Agent error",
39207
- toolKind: "other"
39208
- })
39209
- );
39210
- }
39211
- if (options.detail === "rich" && activities.length > assignedActivityCount) {
39212
- const message = {
39213
- activities: activitySlice(),
39429
+ append({
39430
+ activities: [
39431
+ activity(`agent-error-${sequence.toString()}`, "tool", sequence, {
39432
+ input: "",
39433
+ locations: [],
39434
+ name: "",
39435
+ output: errorMessage(turn.error),
39436
+ status: "failed",
39437
+ title: "Agent error",
39438
+ toolKind: "other"
39439
+ })
39440
+ ],
39214
39441
  content: [],
39215
39442
  role: "assistant",
39216
39443
  text: ""
39217
- };
39218
- messages.push(message);
39219
- assistantMessageIndex = messages.length - 1;
39220
- characters += messageSize(message);
39444
+ });
39221
39445
  }
39222
39446
  if (assistantMessageIndex !== null) {
39223
39447
  const assistant = messages[assistantMessageIndex];
@@ -39227,20 +39451,20 @@ function decodeHistory(thread, value, options) {
39227
39451
  ...assistant,
39228
39452
  ...outcome === void 0 ? {} : { outcome }
39229
39453
  };
39230
- const fitted = fitHistoryMessage(updated);
39454
+ const fitted = fitHistoryMessage(updated, turnMessageCharacterLimit);
39231
39455
  truncated ||= fitted.truncated;
39232
39456
  messages[assistantMessageIndex] = fitted.message;
39233
39457
  characters += messageSize(fitted.message);
39234
39458
  }
39235
- } else if (activities.length > 0 || outcome !== void 0) {
39459
+ } else if (outcome !== void 0) {
39236
39460
  const message = {
39237
- activities: activities.slice(-100),
39461
+ activities: [],
39238
39462
  content: [],
39239
39463
  role: "assistant",
39240
39464
  ...outcome === void 0 ? {} : { outcome },
39241
39465
  text: ""
39242
39466
  };
39243
- const fitted = fitHistoryMessage(message);
39467
+ const fitted = fitHistoryMessage(message, turnMessageCharacterLimit);
39244
39468
  truncated ||= fitted.truncated;
39245
39469
  messages.push(fitted.message);
39246
39470
  characters += messageSize(fitted.message);
@@ -41080,6 +41304,34 @@ function liveHistoryCoveredTurnRanges(history) {
41080
41304
  function historyMessageCharacters(message) {
41081
41305
  return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
41082
41306
  }
41307
+ function boundedActiveMessages(messages, messageLimit, characterLimit) {
41308
+ const selected = [];
41309
+ let remainingCharacters = characterLimit;
41310
+ for (let index = messages.length - 1; index >= 0 && selected.length < messageLimit; index -= 1) {
41311
+ const message = messages[index];
41312
+ if (message === void 0) {
41313
+ break;
41314
+ }
41315
+ const characters = historyMessageCharacters(message);
41316
+ if (characters <= remainingCharacters) {
41317
+ selected.unshift(message);
41318
+ remainingCharacters -= characters;
41319
+ continue;
41320
+ }
41321
+ const structuredCharacters = characters - message.text.length;
41322
+ if (selected.length === 0 && structuredCharacters <= remainingCharacters) {
41323
+ const textCharacters = remainingCharacters - structuredCharacters;
41324
+ selected.unshift({ ...message, text: textCharacters === 0 ? "" : message.text.slice(-textCharacters) });
41325
+ remainingCharacters = 0;
41326
+ }
41327
+ break;
41328
+ }
41329
+ return {
41330
+ characters: characterLimit - remainingCharacters,
41331
+ messages: selected,
41332
+ truncated: selected.length !== messages.length
41333
+ };
41334
+ }
41083
41335
  function paginateAcpSessionHistory(history, sessionId, cursor, limit) {
41084
41336
  if (history.status === "unavailable") {
41085
41337
  if (cursor !== null) {
@@ -41110,30 +41362,19 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
41110
41362
  if (activeTurn === null || cursor !== null) {
41111
41363
  return paginateAcpSessionHistory(history, sessionId, cursor, limit);
41112
41364
  }
41113
- const activeMessageOverhead = 4;
41114
- const activeStructuredCharacters = JSON.stringify(activeTurn.activities).length + JSON.stringify(activeTurn.content).length;
41115
- const maximumActiveTextLength = Math.max(
41116
- 0,
41117
- SESSION_HISTORY_CHARACTER_LIMIT - activeTurn.prompt.length - activeStructuredCharacters - activeMessageOverhead
41118
- );
41119
- const activeText = activeTurn.text.slice(-maximumActiveTextLength);
41120
- const completeActiveMessages = [
41121
- { role: "user", text: activeTurn.prompt },
41122
- {
41123
- activities: activeTurn.activities,
41124
- content: activeTurn.content,
41125
- role: "assistant",
41126
- text: activeText
41127
- }
41128
- ];
41129
41365
  if (history.status === "unavailable") {
41366
+ const bounded3 = boundedActiveMessages(
41367
+ activeTurn.messages,
41368
+ Math.max(0, limit - 1),
41369
+ Math.max(0, SESSION_HISTORY_CHARACTER_LIMIT - activeTurn.prompt.length)
41370
+ );
41130
41371
  return {
41131
41372
  coveredCommandIds: [],
41132
41373
  coveredMessageIds: [],
41133
- messages: completeActiveMessages,
41374
+ messages: [{ role: "user", text: activeTurn.prompt }, ...bounded3.messages],
41134
41375
  nextCursor: null,
41135
41376
  status: "available",
41136
- truncated: activeTurn.truncated || activeText.length !== activeTurn.text.length
41377
+ truncated: activeTurn.truncated || bounded3.truncated
41137
41378
  };
41138
41379
  }
41139
41380
  const activeUserIndex = history.coveredCommandIds.includes(activeTurn.commandId) ? history.messages.findLastIndex((message) => message.role === "user") : -1;
@@ -41148,9 +41389,18 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
41148
41389
  };
41149
41390
  }
41150
41391
  const latestNativeMessage = history.messages.at(-1);
41151
- const activeMessages = activeUserIndex >= 0 || latestNativeMessage?.role === "user" && latestNativeMessage.text === activeTurn.prompt ? completeActiveMessages.slice(1) : completeActiveMessages;
41392
+ const includeActivePrompt = activeUserIndex < 0 && !(latestNativeMessage?.role === "user" && latestNativeMessage.text === activeTurn.prompt);
41393
+ const bounded2 = boundedActiveMessages(
41394
+ activeTurn.messages,
41395
+ Math.max(0, limit - (includeActivePrompt ? 1 : 0)),
41396
+ Math.max(0, SESSION_HISTORY_CHARACTER_LIMIT - (includeActivePrompt ? activeTurn.prompt.length : 0))
41397
+ );
41398
+ const activeMessages = [
41399
+ ...includeActivePrompt ? [{ role: "user", text: activeTurn.prompt }] : [],
41400
+ ...bounded2.messages
41401
+ ];
41152
41402
  let historicalMessageCount = 0;
41153
- let remainingCharacters = SESSION_HISTORY_CHARACTER_LIMIT - activeText.length - activeMessageOverhead - activeStructuredCharacters - (activeMessages.length === completeActiveMessages.length ? activeTurn.prompt.length : 0);
41403
+ let remainingCharacters = SESSION_HISTORY_CHARACTER_LIMIT - bounded2.characters - (includeActivePrompt ? activeTurn.prompt.length : 0);
41154
41404
  const historicalMessageLimit = Math.max(0, limit - activeMessages.length);
41155
41405
  for (let index = history.messages.length - 1; index >= 0 && historicalMessageCount < historicalMessageLimit; index -= 1) {
41156
41406
  const message = history.messages[index];
@@ -41175,7 +41425,7 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
41175
41425
  return {
41176
41426
  ...page,
41177
41427
  messages: [...page.messages, ...activeMessages],
41178
- truncated: page.truncated || activeTurn.truncated || activeText.length !== activeTurn.text.length
41428
+ truncated: page.truncated || activeTurn.truncated || bounded2.truncated
41179
41429
  };
41180
41430
  }
41181
41431
  function mergeLiveSessionHistory(history, activeTurn, sessionId) {
@@ -41485,167 +41735,113 @@ function warnIgnoredSetting(audit, event, commandId, sessionId, agentId, selecti
41485
41735
  `);
41486
41736
  }
41487
41737
 
41488
- // src/relay-connection/coalescing-activity-publisher.ts
41489
- var AGENT_ACTIVITY_COALESCING_MILLISECONDS = 100;
41490
- var CoalescingDaemonActivityPublisher = class {
41491
- #pending = /* @__PURE__ */ new Map();
41738
+ // src/relay-connection/coalescing-agent-event-publisher.ts
41739
+ var AGENT_EVENT_COALESCING_MILLISECONDS = 100;
41740
+ var AGENT_EVENT_TEXT_MAXIMUM_LENGTH = 1e5;
41741
+ var CoalescingAgentEventPublisher = class {
41742
+ #entries = [];
41492
41743
  #publish;
41493
41744
  #publishedActivityIds = /* @__PURE__ */ new Set();
41494
- #scheduled = /* @__PURE__ */ new Map();
41745
+ #scheduled = null;
41495
41746
  #timer;
41496
41747
  constructor(timer, publish) {
41497
41748
  this.#publish = publish;
41498
41749
  this.#timer = timer;
41499
41750
  }
41500
- flush = () => {
41501
- const activities = [...this.#pending.values()].sort((left, right) => left.sequence - right.sequence);
41502
- for (const task of this.#scheduled.values()) {
41503
- task.cancel();
41504
- }
41505
- this.#pending.clear();
41506
- this.#scheduled.clear();
41507
- for (const activity2 of activities) {
41508
- this.#publish(activity2);
41509
- }
41510
- };
41511
- record = (activity2) => {
41512
- if (activity2.status !== "pending" && activity2.status !== "running") {
41513
- this.#discardPending(activity2.activityId);
41514
- this.#publishedActivityIds.add(activity2.activityId);
41515
- this.#publish(activity2);
41516
- return Promise.resolve();
41517
- }
41518
- if (!this.#publishedActivityIds.has(activity2.activityId)) {
41519
- this.#publishedActivityIds.add(activity2.activityId);
41520
- this.#publish(activity2);
41521
- return Promise.resolve();
41522
- }
41523
- this.#pending.set(activity2.activityId, activity2);
41524
- if (!this.#scheduled.has(activity2.activityId)) {
41525
- this.#scheduled.set(
41526
- activity2.activityId,
41527
- this.#timer.schedule(
41528
- () => this.#flushActivity(activity2.activityId),
41529
- AGENT_ACTIVITY_COALESCING_MILLISECONDS
41530
- )
41531
- );
41532
- }
41533
- return Promise.resolve();
41534
- };
41535
- #discardPending = (activityId) => {
41536
- this.#scheduled.get(activityId)?.cancel();
41537
- this.#scheduled.delete(activityId);
41538
- this.#pending.delete(activityId);
41539
- };
41540
- #flushActivity = (activityId) => {
41541
- const activity2 = this.#pending.get(activityId);
41542
- this.#discardPending(activityId);
41543
- if (activity2 !== void 0) {
41544
- this.#publish(activity2);
41545
- }
41546
- };
41547
- };
41548
-
41549
- // src/relay-connection/coalescing-narration-publisher.ts
41550
- var CoalescingNarrationPublisher = class {
41551
- #coalescingMilliseconds;
41552
- #maximumTextLength;
41553
- #publish;
41554
- #timer;
41555
- #pending = /* @__PURE__ */ new Map();
41556
- #scheduled = null;
41557
- constructor(timer, publish, coalescingMilliseconds, maximumTextLength) {
41558
- this.#publish = publish;
41559
- this.#timer = timer;
41560
- this.#coalescingMilliseconds = coalescingMilliseconds;
41561
- this.#maximumTextLength = maximumTextLength;
41562
- }
41563
- /** Emit every buffered increment now, cancelling the pending flush. */
41564
41751
  flush = () => {
41565
41752
  this.#scheduled?.cancel();
41566
41753
  this.#scheduled = null;
41567
- const increments = [...this.#pending.entries()].map(
41568
- ([activityId, pending]) => ({
41569
- activityId,
41570
- activityType: pending.activityType,
41571
- sequence: pending.sequence,
41572
- text: pending.text
41573
- })
41574
- );
41575
- this.#pending.clear();
41576
- for (const increment of increments) {
41577
- this.#publish(increment);
41754
+ const entries = this.#entries;
41755
+ this.#entries = [];
41756
+ for (const entry of entries) {
41757
+ this.#publish(entry);
41578
41758
  }
41579
41759
  };
41580
- /**
41581
- * Buffer an increment, emitting the buffered text when it would exceed the
41582
- * protocol's per-event text limit so no event is rejected by the codec.
41583
- */
41584
- record = (increment) => {
41585
- if (increment.text.length === 0) {
41586
- return;
41587
- }
41588
- const previous = this.#pending.get(increment.activityId);
41589
- if (previous !== void 0 && previous.text.length + increment.text.length > this.#maximumTextLength) {
41760
+ recordActivity = (activity2) => {
41761
+ const latest = this.#entries.at(-1);
41762
+ 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" }];
41763
+ const first = !this.#publishedActivityIds.has(activity2.activityId);
41764
+ this.#publishedActivityIds.add(activity2.activityId);
41765
+ if (first || activity2.status !== "pending" && activity2.status !== "running") {
41590
41766
  this.flush();
41767
+ } else {
41768
+ this.schedule();
41591
41769
  }
41592
- const current = this.#pending.get(increment.activityId);
41593
- this.#pending.set(increment.activityId, {
41594
- activityType: increment.activityType,
41595
- sequence: increment.sequence,
41596
- text: `${current?.text ?? ""}${increment.text}`
41597
- });
41598
- this.#scheduled ??= this.#timer.schedule(this.flush, this.#coalescingMilliseconds);
41770
+ return Promise.resolve();
41599
41771
  };
41600
- };
41601
-
41602
- // src/relay-connection/coalescing-text-publisher.ts
41603
- var CoalescingTextPublisher = class {
41604
- #coalescingMilliseconds;
41605
- #maximumTextLength;
41606
- #publish;
41607
- #timer;
41608
- #messageId = "";
41609
- #scheduled = null;
41610
- #text = "";
41611
- constructor(timer, publish, coalescingMilliseconds, maximumTextLength) {
41612
- this.#publish = publish;
41613
- this.#timer = timer;
41614
- this.#coalescingMilliseconds = coalescingMilliseconds;
41615
- this.#maximumTextLength = maximumTextLength;
41616
- }
41617
- /** Emit any buffered text now, cancelling the pending flush. */
41618
- flush = () => {
41619
- this.#scheduled?.cancel();
41620
- this.#scheduled = null;
41621
- const messageId = this.#messageId;
41622
- const text2 = this.#text;
41623
- this.#messageId = "";
41624
- this.#text = "";
41625
- if (text2.length > 0) {
41626
- this.#publish(messageId, text2);
41772
+ recordNarration = (increment) => {
41773
+ if (increment.text.length === 0) {
41774
+ return Promise.resolve();
41627
41775
  }
41776
+ let remaining = increment.text;
41777
+ while (remaining.length > 0) {
41778
+ const latest = this.#entries.at(-1);
41779
+ if (latest?.kind === "narration" && latest.increment.activityId === increment.activityId) {
41780
+ const available = AGENT_EVENT_TEXT_MAXIMUM_LENGTH - latest.increment.text.length;
41781
+ if (available > 0) {
41782
+ this.#entries = [
41783
+ ...this.#entries.slice(0, -1),
41784
+ {
41785
+ increment: {
41786
+ ...increment,
41787
+ text: `${latest.increment.text}${remaining.slice(0, available)}`
41788
+ },
41789
+ kind: "narration"
41790
+ }
41791
+ ];
41792
+ remaining = remaining.slice(available);
41793
+ continue;
41794
+ }
41795
+ }
41796
+ this.#entries = [
41797
+ ...this.#entries,
41798
+ {
41799
+ increment: { ...increment, text: remaining.slice(0, AGENT_EVENT_TEXT_MAXIMUM_LENGTH) },
41800
+ kind: "narration"
41801
+ }
41802
+ ];
41803
+ remaining = remaining.slice(AGENT_EVENT_TEXT_MAXIMUM_LENGTH);
41804
+ }
41805
+ this.schedule();
41806
+ return Promise.resolve();
41628
41807
  };
41629
- /**
41630
- * Buffer a chunk, emitting the buffered text when the message changes or the
41631
- * buffer would exceed the protocol's per-event text limit.
41632
- */
41633
- record = (messageId, text2) => {
41808
+ recordText = (text2, messageId) => {
41634
41809
  if (text2.length === 0) {
41635
- return;
41810
+ return Promise.resolve();
41636
41811
  }
41637
- if (this.#text.length > 0 && (this.#messageId !== messageId || this.#text.length + text2.length > this.#maximumTextLength)) {
41638
- this.flush();
41812
+ let remaining = text2;
41813
+ while (remaining.length > 0) {
41814
+ const latest = this.#entries.at(-1);
41815
+ if (latest?.kind === "text" && latest.messageId === messageId) {
41816
+ const available = AGENT_EVENT_TEXT_MAXIMUM_LENGTH - latest.text.length;
41817
+ if (available > 0) {
41818
+ this.#entries = [
41819
+ ...this.#entries.slice(0, -1),
41820
+ { ...latest, text: `${latest.text}${remaining.slice(0, available)}` }
41821
+ ];
41822
+ remaining = remaining.slice(available);
41823
+ continue;
41824
+ }
41825
+ }
41826
+ this.#entries = [
41827
+ ...this.#entries,
41828
+ {
41829
+ kind: "text",
41830
+ messageId,
41831
+ text: remaining.slice(0, AGENT_EVENT_TEXT_MAXIMUM_LENGTH)
41832
+ }
41833
+ ];
41834
+ remaining = remaining.slice(AGENT_EVENT_TEXT_MAXIMUM_LENGTH);
41639
41835
  }
41640
- this.#messageId = messageId;
41641
- this.#text = `${this.#text}${text2}`;
41642
- this.#scheduled ??= this.#timer.schedule(this.flush, this.#coalescingMilliseconds);
41836
+ this.schedule();
41837
+ return Promise.resolve();
41643
41838
  };
41839
+ schedule() {
41840
+ this.#scheduled ??= this.#timer.schedule(this.flush, AGENT_EVENT_COALESCING_MILLISECONDS);
41841
+ }
41644
41842
  };
41645
41843
 
41646
41844
  // src/daemon-prompt-executor.ts
41647
- var AGENT_TEXT_COALESCING_MILLISECONDS = 100;
41648
- var AGENT_TEXT_MAXIMUM_LENGTH = 1e5;
41649
41845
  function daemonActivity(command, activity2) {
41650
41846
  return {
41651
41847
  activityId: activity2.activityId,
@@ -41681,41 +41877,30 @@ async function executePrompt({
41681
41877
  recordLiveEvent,
41682
41878
  cancellationRequested
41683
41879
  }) {
41684
- const narration = new CoalescingNarrationPublisher(
41685
- timer,
41686
- (increment) => {
41687
- const event = {
41688
- activityId: increment.activityId,
41689
- activityType: increment.activityType,
41880
+ const events = new CoalescingAgentEventPublisher(timer, (event) => {
41881
+ if (event.kind === "text") {
41882
+ publisher.publish(
41883
+ command.sessionId,
41884
+ recordLiveEvent({ kind: AGENT_MESSAGE_DELTA_KIND, messageId: event.messageId, text: event.text })
41885
+ );
41886
+ return;
41887
+ }
41888
+ if (event.kind === "narration") {
41889
+ const recorded = {
41890
+ activityId: event.increment.activityId,
41891
+ activityType: event.increment.activityType,
41690
41892
  commandId: command.commandId,
41691
41893
  kind: AGENT_ACTIVITY_NARRATION_KIND,
41692
- sequence: increment.sequence,
41894
+ sequence: event.increment.sequence,
41693
41895
  sessionId: command.sessionId,
41694
- text: increment.text
41896
+ text: event.increment.text
41695
41897
  };
41696
- publisher.publish(command.sessionId, recordLiveEvent(event));
41697
- },
41698
- AGENT_ACTIVITY_COALESCING_MILLISECONDS,
41699
- AGENT_TEXT_MAXIMUM_LENGTH
41700
- );
41701
- const activities = new CoalescingDaemonActivityPublisher(timer, (activity2) => {
41702
- if (activity2.status !== "pending" && activity2.status !== "running") {
41703
- narration.flush();
41898
+ publisher.publish(command.sessionId, recordLiveEvent(recorded));
41899
+ return;
41704
41900
  }
41705
- const event = daemonActivity(command, activity2);
41706
- publisher.publish(command.sessionId, recordLiveEvent(event));
41901
+ const activity2 = daemonActivity(command, event.activity);
41902
+ publisher.publish(command.sessionId, recordLiveEvent(activity2));
41707
41903
  });
41708
- const text2 = new CoalescingTextPublisher(
41709
- timer,
41710
- (messageId, delta) => {
41711
- publisher.publish(
41712
- command.sessionId,
41713
- recordLiveEvent({ kind: AGENT_MESSAGE_DELTA_KIND, messageId, text: delta })
41714
- );
41715
- },
41716
- AGENT_TEXT_COALESCING_MILLISECONDS,
41717
- AGENT_TEXT_MAXIMUM_LENGTH
41718
- );
41719
41904
  try {
41720
41905
  const resolved = await resolveSessionDirectories(
41721
41906
  directories,
@@ -41804,15 +41989,9 @@ async function executePrompt({
41804
41989
  cwd: resolved.cwd,
41805
41990
  disposition: availability.disposition,
41806
41991
  images: attachments.images,
41807
- onActivity: activities.record,
41808
- onNarration: (increment) => {
41809
- narration.record(increment);
41810
- return Promise.resolve();
41811
- },
41812
- onText: (delta, messageId) => {
41813
- text2.record(messageId, delta);
41814
- return Promise.resolve();
41815
- },
41992
+ onActivity: events.recordActivity,
41993
+ onNarration: events.recordNarration,
41994
+ onText: events.recordText,
41816
41995
  prompt: command.prompt,
41817
41996
  resources: attachments.resources,
41818
41997
  sessionId: command.sessionId,
@@ -41821,9 +42000,7 @@ async function executePrompt({
41821
42000
  });
41822
42001
  stopReason = result.stopReason;
41823
42002
  }
41824
- text2.flush();
41825
- narration.flush();
41826
- activities.flush();
42003
+ events.flush();
41827
42004
  publisher.publish(command.sessionId, {
41828
42005
  commandId: command.commandId,
41829
42006
  kind: SESSION_COMPLETED_KIND,
@@ -41837,9 +42014,7 @@ async function executePrompt({
41837
42014
  sessionId: command.sessionId
41838
42015
  });
41839
42016
  } catch (error62) {
41840
- text2.flush();
41841
- narration.flush();
41842
- activities.flush();
42017
+ events.flush();
41843
42018
  if (signal.aborted && cancellationRequested()) {
41844
42019
  publisher.publish(command.sessionId, {
41845
42020
  commandId: command.commandId,