@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/cli.js CHANGED
@@ -3381,7 +3381,7 @@ var program = new Command();
3381
3381
  // package.json
3382
3382
  var package_default = {
3383
3383
  name: "@moxt-ai/mobius",
3384
- version: "0.0.142",
3384
+ version: "0.0.144",
3385
3385
  description: "Mobius CLI for pairing and running local AI agent services.",
3386
3386
  type: "module",
3387
3387
  bin: {
@@ -29441,7 +29441,7 @@ var userHistoryMessage = external_exports.strictObject({
29441
29441
  text: external_exports.string().max(SESSION_HISTORY_CHARACTER_LIMIT),
29442
29442
  images: external_exports.array(historyImage).max(8).readonly().optional()
29443
29443
  }).readonly();
29444
- var assistantHistoryMessage = external_exports.strictObject({
29444
+ var assistantHistoryMessageSchema = external_exports.strictObject({
29445
29445
  activities: external_exports.array(nativeMessageActivitySchema).max(100).readonly().default([]),
29446
29446
  content: external_exports.array(displayContentSchema).max(100).readonly().default([]),
29447
29447
  role: external_exports.literal("assistant"),
@@ -29450,7 +29450,7 @@ var assistantHistoryMessage = external_exports.strictObject({
29450
29450
  text: external_exports.string().max(SESSION_HISTORY_CHARACTER_LIMIT),
29451
29451
  images: external_exports.array(historyImage).max(8).readonly().optional()
29452
29452
  }).readonly();
29453
- var historyMessage = external_exports.discriminatedUnion("role", [userHistoryMessage, assistantHistoryMessage]);
29453
+ var historyMessage = external_exports.discriminatedUnion("role", [userHistoryMessage, assistantHistoryMessageSchema]);
29454
29454
  var availableSessionHistoryObjectSchema = external_exports.strictObject({
29455
29455
  status: external_exports.literal("available"),
29456
29456
  messages: external_exports.array(historyMessage).max(SESSION_HISTORY_MESSAGE_LIMIT).readonly(),
@@ -29521,6 +29521,7 @@ var activeTurnSnapshotSchema = external_exports.strictObject({
29521
29521
  truncated: external_exports.boolean(),
29522
29522
  epoch: identifierStringSchema,
29523
29523
  interaction: external_exports.discriminatedUnion("kind", [sessionPermissionRequestedEventSchema, sessionElicitationRequestedEventSchema]).nullable(),
29524
+ messages: external_exports.array(assistantHistoryMessageSchema).max(SESSION_HISTORY_MESSAGE_LIMIT).readonly(),
29524
29525
  sequence: external_exports.number().int().nonnegative(),
29525
29526
  state: external_exports.literal("running")
29526
29527
  }).readonly();
@@ -32240,6 +32241,48 @@ var AgentUpdateStream = class {
32240
32241
  };
32241
32242
  };
32242
32243
 
32244
+ // src/acp/runtime-operations.ts
32245
+ var RuntimeOperations = class {
32246
+ #shutdown = new AbortController();
32247
+ #pending = /* @__PURE__ */ new Set();
32248
+ #closing = null;
32249
+ run = async (options, operation) => {
32250
+ const signal = AbortSignal.any([options.signal, this.#shutdown.signal]);
32251
+ signal.throwIfAborted();
32252
+ const pending = Promise.resolve().then(() => operation({ ...options, signal }));
32253
+ this.#pending.add(pending);
32254
+ try {
32255
+ const result = await pending;
32256
+ signal.throwIfAborted();
32257
+ return result;
32258
+ } finally {
32259
+ this.#pending.delete(pending);
32260
+ }
32261
+ };
32262
+ close = (release) => {
32263
+ if (this.#closing !== null) {
32264
+ return this.#closing;
32265
+ }
32266
+ this.#shutdown.abort();
32267
+ this.#closing = (async () => {
32268
+ await Promise.allSettled([...this.#pending]);
32269
+ await release();
32270
+ })();
32271
+ return this.#closing;
32272
+ };
32273
+ };
32274
+ async function waitForSharedOperation(pending, signal) {
32275
+ signal.throwIfAborted();
32276
+ const cancelled = Promise.withResolvers();
32277
+ const abort = () => cancelled.reject(signal.reason);
32278
+ signal.addEventListener("abort", abort, { once: true });
32279
+ try {
32280
+ return await Promise.race([pending, cancelled.promise]);
32281
+ } finally {
32282
+ signal.removeEventListener("abort", abort);
32283
+ }
32284
+ }
32285
+
32243
32286
  // src/acp/session-config/session-config-protocol.ts
32244
32287
  import { methods as methods7 } from "@agentclientprotocol/sdk";
32245
32288
  var MAXIMUM_CONFIG_OPTIONS = 100;
@@ -38879,9 +38922,7 @@ var AgentSession = class _AgentSession {
38879
38922
  #configOptions = [];
38880
38923
  #prompted = false;
38881
38924
  #nativePrompt = null;
38882
- #replay = {
38883
- kind: "idle"
38884
- };
38925
+ #sessionLoad = { kind: "not-requested" };
38885
38926
  #restored = false;
38886
38927
  #sessionTitle = null;
38887
38928
  #sessionUpdatedAt = "";
@@ -38994,30 +39035,46 @@ var AgentSession = class _AgentSession {
38994
39035
  }
38995
39036
  };
38996
39037
  }
38997
- const history = new AcpHistoryReplay();
38998
- this.#replay = { kind: "capture", history };
38999
- try {
39000
- await this.race(
39001
- this.#connection.connection.agent.request(
39002
- methods8.agent.session.load,
39003
- {
39004
- additionalDirectories: [...this.#additionalDirectories],
39005
- cwd: this.#cwd,
39006
- mcpServers: [],
39007
- sessionId: this.#updates.sessionId()
39008
- },
39009
- { cancellationSignal: signal }
39010
- ),
39011
- "ACP agent exited while loading history",
39012
- signal
39013
- );
39014
- await this.#updates.drained();
39015
- signal.throwIfAborted();
39016
- return await embedLocalHistoryImages(await history.snapshot(), signal);
39017
- } finally {
39018
- this.#replay = { kind: "idle" };
39019
- }
39038
+ const loaded = await this.#loadSession(signal, "ACP agent exited while loading history");
39039
+ return await embedLocalHistoryImages(await loaded.history.snapshot(), signal);
39020
39040
  };
39041
+ async #loadSession(signal, exitMessage) {
39042
+ if (this.#sessionLoad.kind === "loaded") {
39043
+ return this.#sessionLoad;
39044
+ }
39045
+ if (this.#sessionLoad.kind === "capturing") {
39046
+ return await waitForSharedOperation(this.#sessionLoad.completion, signal);
39047
+ }
39048
+ const history = new AcpHistoryReplay();
39049
+ const completion = Promise.resolve().then(async () => {
39050
+ try {
39051
+ const response = await this.race(
39052
+ this.#connection.connection.agent.request(
39053
+ methods8.agent.session.load,
39054
+ {
39055
+ additionalDirectories: [...this.#additionalDirectories],
39056
+ cwd: this.#cwd,
39057
+ mcpServers: [],
39058
+ sessionId: this.#updates.sessionId()
39059
+ },
39060
+ { cancellationSignal: signal }
39061
+ ),
39062
+ exitMessage,
39063
+ signal
39064
+ );
39065
+ await this.#updates.drained();
39066
+ signal.throwIfAborted();
39067
+ const loaded = { history, kind: "loaded", response };
39068
+ this.#sessionLoad = loaded;
39069
+ return loaded;
39070
+ } catch (cause) {
39071
+ this.#sessionLoad = { kind: "not-requested" };
39072
+ throw cause;
39073
+ }
39074
+ });
39075
+ this.#sessionLoad = { completion, history, kind: "capturing" };
39076
+ return await completion;
39077
+ }
39021
39078
  prepareAgentContent = async (content) => {
39022
39079
  if (content.type === "image" && content.uri.length > 0) {
39023
39080
  const signal = AbortSignal.timeout(2e4);
@@ -39220,29 +39277,10 @@ var AgentSession = class _AgentSession {
39220
39277
  )
39221
39278
  );
39222
39279
  } else if (this.#capabilities.loadSession) {
39223
- this.#replay = { kind: "discard" };
39224
- try {
39225
- lifecycleResponse = await this.#metrics.measure(
39226
- "session-load",
39227
- async () => await this.race(
39228
- this.#connection.connection.agent.request(
39229
- methods8.agent.session.load,
39230
- {
39231
- additionalDirectories: [...this.#additionalDirectories],
39232
- cwd: this.#cwd,
39233
- mcpServers: [],
39234
- sessionId: this.#updates.sessionId()
39235
- },
39236
- { cancellationSignal: signal }
39237
- ),
39238
- "ACP agent exited while loading a session",
39239
- signal
39240
- )
39241
- );
39242
- } finally {
39243
- await this.#updates.drained();
39244
- this.#replay = { kind: "idle" };
39245
- }
39280
+ lifecycleResponse = await this.#metrics.measure(
39281
+ "session-load",
39282
+ async () => (await this.#loadSession(signal, "ACP agent exited while loading a session")).response
39283
+ );
39246
39284
  } else {
39247
39285
  throw new AcpExecutionError(
39248
39286
  "The ACP agent cannot restore its persisted session",
@@ -39627,10 +39665,10 @@ var AgentSession = class _AgentSession {
39627
39665
  #processUpdate = async (notification) => {
39628
39666
  this.assertNativeSession(notification.sessionId);
39629
39667
  const update = notification.update;
39630
- if (this.#replay.kind === "capture") {
39631
- await this.#replay.history.record(update);
39668
+ if (this.#sessionLoad.kind !== "not-requested") {
39669
+ await this.#sessionLoad.history.record(update);
39632
39670
  }
39633
- 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")) {
39671
+ 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")) {
39634
39672
  return;
39635
39673
  }
39636
39674
  if (update.sessionUpdate === "agent_message_chunk") {
@@ -39900,48 +39938,6 @@ var RetainedAgentProcesses = class {
39900
39938
  };
39901
39939
  };
39902
39940
 
39903
- // src/acp/runtime-operations.ts
39904
- var RuntimeOperations = class {
39905
- #shutdown = new AbortController();
39906
- #pending = /* @__PURE__ */ new Set();
39907
- #closing = null;
39908
- run = async (options, operation) => {
39909
- const signal = AbortSignal.any([options.signal, this.#shutdown.signal]);
39910
- signal.throwIfAborted();
39911
- const pending = Promise.resolve().then(() => operation({ ...options, signal }));
39912
- this.#pending.add(pending);
39913
- try {
39914
- const result = await pending;
39915
- signal.throwIfAborted();
39916
- return result;
39917
- } finally {
39918
- this.#pending.delete(pending);
39919
- }
39920
- };
39921
- close = (release) => {
39922
- if (this.#closing !== null) {
39923
- return this.#closing;
39924
- }
39925
- this.#shutdown.abort();
39926
- this.#closing = (async () => {
39927
- await Promise.allSettled([...this.#pending]);
39928
- await release();
39929
- })();
39930
- return this.#closing;
39931
- };
39932
- };
39933
- async function waitForPreparation(pending, signal) {
39934
- signal.throwIfAborted();
39935
- const cancelled = Promise.withResolvers();
39936
- const abort = () => cancelled.reject(signal.reason);
39937
- signal.addEventListener("abort", abort, { once: true });
39938
- try {
39939
- return await Promise.race([pending, cancelled.promise]);
39940
- } finally {
39941
- signal.removeEventListener("abort", abort);
39942
- }
39943
- }
39944
-
39945
39941
  // src/acp/agent-query-processes.ts
39946
39942
  var AgentQueryProcesses = class {
39947
39943
  #processesByQuery;
@@ -39988,7 +39984,7 @@ var AgentQueryProcesses = class {
39988
39984
  prepare = async (options) => {
39989
39985
  const pending = this.#processesByQuery.pending(options.sessionId);
39990
39986
  if (pending !== void 0) {
39991
- const runtime2 = await waitForPreparation(pending, options.signal);
39987
+ const runtime2 = await waitForSharedOperation(pending, options.signal);
39992
39988
  if (runtime2.belongsTo(options.agent.id, options.cwd, options.additionalDirectories)) {
39993
39989
  this.#processesByQuery.touch(options.sessionId, runtime2);
39994
39990
  return runtime2.prepared();
@@ -40406,7 +40402,7 @@ var AgentRuntimeManager = class {
40406
40402
  if (pending !== void 0) {
40407
40403
  const runtime2 = await metrics.measure(
40408
40404
  "session-preparation-wait",
40409
- async () => await waitForPreparation(pending, options2.signal)
40405
+ async () => await waitForSharedOperation(pending, options2.signal)
40410
40406
  );
40411
40407
  if (runtime2.belongsTo(options2.agent.id, options2.cwd, options2.additionalDirectories)) {
40412
40408
  this.#executionProcesses.touch(options2.sessionId, runtime2);
@@ -40496,7 +40492,7 @@ var AgentRuntimeManager = class {
40496
40492
  prepareExecutionSession = async (options) => this.#operations.run(options, async (options2) => {
40497
40493
  const pending = this.#executionProcesses.pending(options2.sessionId);
40498
40494
  if (pending !== void 0) {
40499
- await waitForPreparation(pending, options2.signal);
40495
+ await waitForSharedOperation(pending, options2.signal);
40500
40496
  return await this.prepareExecutionSession(options2);
40501
40497
  }
40502
40498
  const existing = this.#executionProcesses.get(options2.sessionId);
@@ -40550,7 +40546,7 @@ var AgentRuntimeManager = class {
40550
40546
  }
40551
40547
  const pending = this.#executionProcesses.pending(options2.sessionId);
40552
40548
  if (pending !== void 0) {
40553
- await waitForPreparation(pending, options2.signal);
40549
+ await waitForSharedOperation(pending, options2.signal);
40554
40550
  }
40555
40551
  if (this.#executions.command(options2.sessionId) !== options2.targetCommandId) {
40556
40552
  throw new AcpExecutionError("The target turn is no longer active", {}, "steering_target_unavailable");
@@ -42103,6 +42099,7 @@ var ActiveDaemonTurn = class {
42103
42099
  #text = "";
42104
42100
  #activities = /* @__PURE__ */ new Map();
42105
42101
  #content = /* @__PURE__ */ new Map();
42102
+ #timeline = [];
42106
42103
  #sequence = 0;
42107
42104
  #interaction = null;
42108
42105
  #epoch = decodeIdentifier(randomUUID2());
@@ -42146,12 +42143,16 @@ var ActiveDaemonTurn = class {
42146
42143
  recordEvent = (event) => {
42147
42144
  if (event.kind === AGENT_MESSAGE_DELTA_KIND) {
42148
42145
  this.#text += event.text;
42146
+ this.appendMessageText(event.messageId, event.text);
42149
42147
  return this.updated();
42150
42148
  }
42151
42149
  if (event.sessionId !== this.command.sessionId || "commandId" in event && event.commandId !== this.command.commandId) {
42152
42150
  return event;
42153
42151
  }
42154
42152
  if (event.kind === AGENT_ACTIVITY_KIND) {
42153
+ if (!this.#activities.has(event.activityId)) {
42154
+ this.#timeline = [...this.#timeline, { activityId: event.activityId, kind: "activity" }];
42155
+ }
42155
42156
  this.#activities.set(event.activityId, {
42156
42157
  activityId: event.activityId,
42157
42158
  activityType: event.activityType,
@@ -42167,6 +42168,9 @@ var ActiveDaemonTurn = class {
42167
42168
  });
42168
42169
  } else if (event.kind === AGENT_ACTIVITY_NARRATION_KIND) {
42169
42170
  const previous = this.#activities.get(event.activityId);
42171
+ if (previous === void 0) {
42172
+ this.#timeline = [...this.#timeline, { activityId: event.activityId, kind: "activity" }];
42173
+ }
42170
42174
  this.#activities.set(event.activityId, {
42171
42175
  activityId: event.activityId,
42172
42176
  activityType: event.activityType,
@@ -42182,6 +42186,24 @@ var ActiveDaemonTurn = class {
42182
42186
  });
42183
42187
  } else if (event.kind === AGENT_CONTENT_KIND) {
42184
42188
  this.#content.set(event.contentId, event.content);
42189
+ const target = this.#timeline.findLastIndex(
42190
+ (entry) => entry.kind === "message" && entry.messageId === event.messageId
42191
+ );
42192
+ if (target < 0) {
42193
+ this.#timeline = [
42194
+ ...this.#timeline,
42195
+ {
42196
+ content: /* @__PURE__ */ new Map([[event.contentId, event.content]]),
42197
+ kind: "message",
42198
+ messageId: event.messageId,
42199
+ text: ""
42200
+ }
42201
+ ];
42202
+ } else {
42203
+ this.#timeline = this.#timeline.map(
42204
+ (entry, index) => index === target && entry.kind === "message" ? { ...entry, content: new Map([...entry.content, [event.contentId, event.content]]) } : entry
42205
+ );
42206
+ }
42185
42207
  } else if (event.kind === SESSION_PERMISSION_REQUESTED_KIND || event.kind === SESSION_ELICITATION_REQUESTED_KIND) {
42186
42208
  this.#interaction = event;
42187
42209
  } else if ((event.kind === SESSION_PERMISSION_RESOLVED_KIND || event.kind === SESSION_ELICITATION_RESOLVED_KIND) && this.#interaction?.interactionId === event.interactionId) {
@@ -42192,6 +42214,49 @@ var ActiveDaemonTurn = class {
42192
42214
  }
42193
42215
  return event;
42194
42216
  };
42217
+ appendMessageText(messageId, text2) {
42218
+ let remaining = text2;
42219
+ while (remaining.length > 0) {
42220
+ const latest = this.#timeline.at(-1);
42221
+ if (latest?.kind === "message" && latest.messageId === messageId) {
42222
+ const available = SESSION_HISTORY_CHARACTER_LIMIT - latest.text.length;
42223
+ if (available > 0) {
42224
+ this.#timeline = [
42225
+ ...this.#timeline.slice(0, -1),
42226
+ { ...latest, text: `${latest.text}${remaining.slice(0, available)}` }
42227
+ ];
42228
+ remaining = remaining.slice(available);
42229
+ continue;
42230
+ }
42231
+ }
42232
+ this.#timeline = [
42233
+ ...this.#timeline,
42234
+ {
42235
+ content: /* @__PURE__ */ new Map(),
42236
+ kind: "message",
42237
+ messageId,
42238
+ text: remaining.slice(0, SESSION_HISTORY_CHARACTER_LIMIT)
42239
+ }
42240
+ ];
42241
+ remaining = remaining.slice(SESSION_HISTORY_CHARACTER_LIMIT);
42242
+ }
42243
+ }
42244
+ timelineMessages() {
42245
+ return this.#timeline.flatMap((entry) => {
42246
+ if (entry.kind === "message") {
42247
+ return [
42248
+ {
42249
+ activities: [],
42250
+ content: [...entry.content.values()],
42251
+ role: "assistant",
42252
+ text: entry.text
42253
+ }
42254
+ ];
42255
+ }
42256
+ const activity2 = this.#activities.get(entry.activityId);
42257
+ return activity2 === void 0 ? [] : [{ activities: [activity2], content: [], role: "assistant", text: "" }];
42258
+ });
42259
+ }
42195
42260
  updated = () => {
42196
42261
  this.#sequence += 1;
42197
42262
  const turn = this.snapshot();
@@ -42200,18 +42265,26 @@ var ActiveDaemonTurn = class {
42200
42265
  }
42201
42266
  return { kind: "session.turn.updated", sessionId: this.command.sessionId, turn };
42202
42267
  };
42203
- snapshot = () => this.#dispatch.kind === "running" ? {
42204
- activities: [...this.#activities.values()].sort((left, right) => left.sequence - right.sequence),
42205
- commandId: decodeIdentifier(this.command.commandId),
42206
- content: [...this.#content.values()],
42207
- prompt: this.command.prompt,
42208
- text: this.#text,
42209
- truncated: false,
42210
- epoch: this.#epoch,
42211
- interaction: this.#interaction,
42212
- sequence: this.#sequence,
42213
- state: "running"
42214
- } : null;
42268
+ snapshot = () => {
42269
+ if (this.#dispatch.kind !== "running") {
42270
+ return null;
42271
+ }
42272
+ const completeMessages = this.timelineMessages();
42273
+ const messages = completeMessages.slice(-SESSION_HISTORY_MESSAGE_LIMIT);
42274
+ return {
42275
+ activities: [...this.#activities.values()].sort((left, right) => left.sequence - right.sequence),
42276
+ commandId: decodeIdentifier(this.command.commandId),
42277
+ content: [...this.#content.values()],
42278
+ prompt: this.command.prompt,
42279
+ text: this.#text,
42280
+ truncated: messages.length !== completeMessages.length,
42281
+ epoch: this.#epoch,
42282
+ interaction: this.#interaction,
42283
+ messages,
42284
+ sequence: this.#sequence,
42285
+ state: "running"
42286
+ };
42287
+ };
42215
42288
  matches = (cancellation) => cancellation.commandId === this.command.commandId && cancellation.sessionId === this.command.sessionId;
42216
42289
  matchesInteraction = (interactionId, sessionId) => this.command.sessionId === sessionId && this.#interaction?.interactionId === interactionId;
42217
42290
  requestCancellation = () => {
@@ -42397,15 +42470,21 @@ var turnsSchema = external_exports.object({
42397
42470
  });
42398
42471
  var itemTypeSchema = external_exports.object({ type: external_exports.string().min(1).max(80) });
42399
42472
  var userMessageSchema = external_exports.object({
42400
- content: external_exports.array(external_exports.unknown()).max(1e4)
42473
+ content: external_exports.array(external_exports.unknown()).max(1e4),
42474
+ type: external_exports.literal("userMessage")
42401
42475
  });
42402
42476
  var textSchema = external_exports.object({ text: external_exports.string() });
42403
42477
  var imageSchema = external_exports.object({ url: external_exports.string() });
42404
- var agentMessageSchema = textSchema.extend({ phase: external_exports.string().nullish() });
42478
+ var agentMessageSchema = textSchema.extend({
42479
+ id: external_exports.string().optional(),
42480
+ phase: external_exports.string().nullish(),
42481
+ type: external_exports.literal("agentMessage")
42482
+ });
42405
42483
  var reasoningSchema = external_exports.object({
42406
42484
  id: external_exports.string(),
42407
42485
  summary: external_exports.array(external_exports.string()).max(1e4),
42408
- content: external_exports.array(external_exports.string()).max(1e4)
42486
+ content: external_exports.array(external_exports.string()).max(1e4),
42487
+ type: external_exports.literal("reasoning")
42409
42488
  });
42410
42489
  var commandExecutionSchema = external_exports.object({
42411
42490
  id: external_exports.string(),
@@ -42414,8 +42493,45 @@ var commandExecutionSchema = external_exports.object({
42414
42493
  status: external_exports.string(),
42415
42494
  commandActions: external_exports.array(external_exports.object({ type: external_exports.string() }).passthrough()).max(100),
42416
42495
  aggregatedOutput: external_exports.string().nullish(),
42417
- exitCode: external_exports.number().int().nullish()
42496
+ exitCode: external_exports.number().int().nullish(),
42497
+ type: external_exports.literal("commandExecution")
42498
+ });
42499
+ var fileChangeSchema = external_exports.object({
42500
+ changes: external_exports.array(external_exports.object({ diff: external_exports.string(), path: external_exports.string() })).max(1e4),
42501
+ id: external_exports.string(),
42502
+ status: external_exports.string(),
42503
+ type: external_exports.literal("fileChange")
42504
+ });
42505
+ var mcpToolCallSchema = external_exports.object({
42506
+ arguments: external_exports.unknown().optional(),
42507
+ error: external_exports.unknown().nullish(),
42508
+ id: external_exports.string(),
42509
+ result: external_exports.unknown().nullish(),
42510
+ server: external_exports.string(),
42511
+ status: external_exports.string(),
42512
+ tool: external_exports.string(),
42513
+ type: external_exports.literal("mcpToolCall")
42514
+ });
42515
+ var dynamicToolCallSchema = external_exports.object({
42516
+ arguments: external_exports.unknown().optional(),
42517
+ contentItems: external_exports.array(external_exports.unknown()).max(1e4).nullish(),
42518
+ id: external_exports.string(),
42519
+ namespace: external_exports.string().nullish(),
42520
+ status: external_exports.string(),
42521
+ tool: external_exports.string(),
42522
+ type: external_exports.literal("dynamicToolCall")
42418
42523
  });
42524
+ var planSchema = external_exports.object({ id: external_exports.string(), text: external_exports.string(), type: external_exports.literal("plan") });
42525
+ var historyItemSchema = external_exports.discriminatedUnion("type", [
42526
+ userMessageSchema,
42527
+ agentMessageSchema,
42528
+ reasoningSchema,
42529
+ commandExecutionSchema,
42530
+ fileChangeSchema,
42531
+ mcpToolCallSchema,
42532
+ dynamicToolCallSchema,
42533
+ planSchema
42534
+ ]);
42419
42535
  function bounded(value, maximum) {
42420
42536
  return value.slice(0, maximum);
42421
42537
  }
@@ -42446,6 +42562,33 @@ function errorMessage(value) {
42446
42562
  }
42447
42563
  return JSON.stringify(value) ?? "Codex stopped before completing this turn.";
42448
42564
  }
42565
+ function formatted(value) {
42566
+ if (value === void 0) {
42567
+ return "";
42568
+ }
42569
+ if (typeof value === "string") {
42570
+ return value;
42571
+ }
42572
+ return JSON.stringify(value) ?? "";
42573
+ }
42574
+ function toolStatus(status) {
42575
+ return status === "inProgress" ? "running" : status === "completed" ? "completed" : "failed";
42576
+ }
42577
+ function diffDisplayContent(path3, newText) {
42578
+ return {
42579
+ artifactId: "",
42580
+ data: "",
42581
+ mimeType: "",
42582
+ name: "",
42583
+ newText,
42584
+ oldText: "",
42585
+ path: path3,
42586
+ terminalId: "",
42587
+ text: "",
42588
+ type: "diff",
42589
+ uri: ""
42590
+ };
42591
+ }
42449
42592
  function messageSize(message) {
42450
42593
  return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
42451
42594
  }
@@ -42483,8 +42626,8 @@ function fitActivities(activities, maximumCharacters) {
42483
42626
  const maximumActivityCharacters = Math.floor(Math.max(0, maximumCharacters - arrayCharacters) / activities.length);
42484
42627
  return activities.map((activity2) => fitActivity(activity2, maximumActivityCharacters));
42485
42628
  }
42486
- function fitHistoryMessage(message) {
42487
- const text2 = message.text.slice(-SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT);
42629
+ function fitHistoryMessage(message, maximumCharacters = SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT) {
42630
+ const text2 = message.text.slice(-maximumCharacters);
42488
42631
  if (message.role === "user") {
42489
42632
  return {
42490
42633
  message: { ...message, text: text2 },
@@ -42494,12 +42637,12 @@ function fitHistoryMessage(message) {
42494
42637
  let activities = message.activities;
42495
42638
  const content = message.content;
42496
42639
  let fitted = { ...message, activities, content, text: text2 };
42497
- if (messageSize(fitted) > SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT && activities.length > 0) {
42498
- const maximumCharacters = SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT - text2.length - JSON.stringify(content).length;
42499
- activities = fitActivities(activities, maximumCharacters);
42640
+ if (messageSize(fitted) > maximumCharacters && activities.length > 0) {
42641
+ const maximumActivityCharacters = maximumCharacters - text2.length - JSON.stringify(content).length;
42642
+ activities = fitActivities(activities, maximumActivityCharacters);
42500
42643
  fitted = { ...fitted, activities };
42501
42644
  }
42502
- const excess = Math.max(0, messageSize(fitted) - SESSION_HISTORY_MESSAGE_CHARACTER_LIMIT);
42645
+ const excess = Math.max(0, messageSize(fitted) - maximumCharacters);
42503
42646
  if (excess > 0) {
42504
42647
  const maximumTextLength = Math.max(0, fitted.text.length - excess);
42505
42648
  fitted = {
@@ -42537,128 +42680,209 @@ function decodeHistory(thread, value, options) {
42537
42680
  let truncated = page.nextCursor != null;
42538
42681
  for (const turn of page.data.toReversed()) {
42539
42682
  const outcome = turnOutcome(turn.status);
42540
- const activities = [];
42541
- let assignedActivityCount = 0;
42683
+ const turnMessageCharacterLimit = Math.max(
42684
+ 1,
42685
+ Math.floor(SESSION_HISTORY_CHARACTER_LIMIT / Math.max(1, turn.items.length + (turn.error == null ? 0 : 1)))
42686
+ );
42542
42687
  let sequence = 0;
42543
42688
  let assistantMessageIndex = null;
42544
- const activitySlice = () => {
42545
- const assigned = activities.slice(assignedActivityCount).slice(-100);
42546
- assignedActivityCount = activities.length;
42547
- return assigned;
42689
+ const append = (message) => {
42690
+ const fitted = fitHistoryMessage(message, turnMessageCharacterLimit);
42691
+ 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)) {
42692
+ return;
42693
+ }
42694
+ truncated ||= fitted.truncated;
42695
+ messages.push(fitted.message);
42696
+ if (fitted.message.role === "assistant") {
42697
+ assistantMessageIndex = messages.length - 1;
42698
+ }
42699
+ characters += messageSize(fitted.message);
42548
42700
  };
42549
42701
  for (const item of turn.items) {
42550
- const { type } = itemTypeSchema.parse(item);
42551
- let message;
42552
- if (type === "userMessage") {
42553
- const { content } = userMessageSchema.parse(item);
42554
- const text2 = content.map((block) => {
42555
- const { type: type2 } = itemTypeSchema.parse(block);
42556
- if (type2 === "text") {
42702
+ const decoded = historyItemSchema.safeParse(item);
42703
+ if (!decoded.success) {
42704
+ continue;
42705
+ }
42706
+ const historyItem = decoded.data;
42707
+ if (historyItem.type === "userMessage") {
42708
+ const text2 = historyItem.content.map((block) => {
42709
+ const { type } = itemTypeSchema.parse(block);
42710
+ if (type === "text") {
42557
42711
  return textSchema.parse(block).text;
42558
42712
  }
42559
- if (type2 === "image") {
42713
+ if (type === "image") {
42560
42714
  return `[@image](${imageSchema.parse(block).url})`;
42561
42715
  }
42562
42716
  return "[Attachment]";
42563
42717
  }).join("");
42564
- message = {
42718
+ append({
42565
42719
  role: "user",
42566
42720
  text: text2
42567
- };
42568
- } else if (type === "agentMessage") {
42569
- const agent = agentMessageSchema.parse(item);
42570
- if (agent.phase === "commentary") {
42571
- if (options.detail === "rich" && agent.text.length > 0) {
42572
- activities.push(
42573
- activity(`progress-${sequence.toString()}`, "progress", sequence, {
42721
+ });
42722
+ } else if (historyItem.type === "agentMessage") {
42723
+ if (historyItem.phase === "commentary") {
42724
+ if (options.detail === "rich" && historyItem.text.length > 0) {
42725
+ append({
42726
+ activities: [
42727
+ activity(historyItem.id ?? `progress-${sequence.toString()}`, "progress", sequence, {
42728
+ input: "",
42729
+ locations: [],
42730
+ name: "",
42731
+ output: historyItem.text,
42732
+ status: "completed",
42733
+ title: "Progress",
42734
+ toolKind: ""
42735
+ })
42736
+ ],
42737
+ content: [],
42738
+ role: "assistant",
42739
+ text: ""
42740
+ });
42741
+ sequence += 1;
42742
+ }
42743
+ continue;
42744
+ }
42745
+ append({ activities: [], content: [], role: "assistant", text: historyItem.text });
42746
+ } else if (historyItem.type === "reasoning" && options.detail === "rich") {
42747
+ const output2 = (historyItem.summary.length > 0 ? historyItem.summary : historyItem.content).join(
42748
+ "\n\n"
42749
+ );
42750
+ if (output2.length > 0) {
42751
+ append({
42752
+ activities: [
42753
+ activity(historyItem.id, "reasoning", sequence, {
42574
42754
  input: "",
42575
42755
  locations: [],
42576
42756
  name: "",
42577
- output: agent.text,
42757
+ output: output2,
42578
42758
  status: "completed",
42579
- title: "Progress",
42759
+ title: "Reasoning",
42580
42760
  toolKind: ""
42581
42761
  })
42582
- );
42583
- sequence += 1;
42584
- }
42585
- continue;
42762
+ ],
42763
+ content: [],
42764
+ role: "assistant",
42765
+ text: ""
42766
+ });
42767
+ sequence += 1;
42586
42768
  }
42587
- message = { activities: activitySlice(), content: [], role: "assistant", text: agent.text };
42588
- } else if (type === "reasoning" && options.detail === "rich") {
42589
- const reasoning = reasoningSchema.parse(item);
42590
- const output2 = (reasoning.summary.length > 0 ? reasoning.summary : reasoning.content).join("\n\n");
42591
- if (output2.length > 0) {
42592
- activities.push(
42593
- activity(reasoning.id, "reasoning", sequence, {
42769
+ } else if (historyItem.type === "commandExecution" && options.detail === "rich") {
42770
+ const action = historyItem.commandActions[0]?.type ?? "execute";
42771
+ append({
42772
+ activities: [
42773
+ activity(historyItem.id, "tool", sequence, {
42774
+ input: JSON.stringify({ command: historyItem.command, cwd: historyItem.cwd }),
42775
+ locations: [historyItem.cwd],
42776
+ name: "",
42777
+ output: JSON.stringify({
42778
+ formatted_output: historyItem.aggregatedOutput ?? "",
42779
+ ...historyItem.exitCode == null ? {} : { exit_code: historyItem.exitCode }
42780
+ }),
42781
+ status: toolStatus(historyItem.status),
42782
+ title: historyItem.command,
42783
+ toolKind: action
42784
+ })
42785
+ ],
42786
+ content: [],
42787
+ role: "assistant",
42788
+ text: ""
42789
+ });
42790
+ sequence += 1;
42791
+ } else if (historyItem.type === "fileChange" && options.detail === "rich") {
42792
+ const paths = historyItem.changes.map((change) => change.path);
42793
+ const content = historyItem.changes.map(
42794
+ (change) => diffDisplayContent(change.path, change.diff)
42795
+ );
42796
+ append({
42797
+ activities: [
42798
+ activity(historyItem.id, "tool", sequence, {
42799
+ input: JSON.stringify({ changes: paths }),
42800
+ locations: paths,
42801
+ name: "",
42802
+ output: "",
42803
+ status: toolStatus(historyItem.status),
42804
+ title: paths.join(", "),
42805
+ toolKind: "edit"
42806
+ })
42807
+ ].map((entry) => ({ ...entry, content })),
42808
+ content: [],
42809
+ role: "assistant",
42810
+ text: ""
42811
+ });
42812
+ sequence += 1;
42813
+ } else if (historyItem.type === "mcpToolCall" && options.detail === "rich") {
42814
+ append({
42815
+ activities: [
42816
+ activity(historyItem.id, "tool", sequence, {
42817
+ input: formatted(historyItem.arguments),
42818
+ locations: [],
42819
+ name: historyItem.tool,
42820
+ output: formatted(historyItem.error ?? historyItem.result),
42821
+ status: toolStatus(historyItem.status),
42822
+ title: `${historyItem.server}/${historyItem.tool}`,
42823
+ toolKind: "other"
42824
+ })
42825
+ ],
42826
+ content: [],
42827
+ role: "assistant",
42828
+ text: ""
42829
+ });
42830
+ sequence += 1;
42831
+ } else if (historyItem.type === "dynamicToolCall" && options.detail === "rich") {
42832
+ append({
42833
+ activities: [
42834
+ activity(historyItem.id, "tool", sequence, {
42835
+ input: formatted(historyItem.arguments),
42836
+ locations: [],
42837
+ name: historyItem.tool,
42838
+ output: formatted(historyItem.contentItems),
42839
+ status: toolStatus(historyItem.status),
42840
+ title: historyItem.namespace == null ? historyItem.tool : `${historyItem.namespace}/${historyItem.tool}`,
42841
+ toolKind: "other"
42842
+ })
42843
+ ],
42844
+ content: [],
42845
+ role: "assistant",
42846
+ text: ""
42847
+ });
42848
+ sequence += 1;
42849
+ } else if (historyItem.type === "plan" && options.detail === "rich") {
42850
+ append({
42851
+ activities: [
42852
+ activity(historyItem.id, "plan", sequence, {
42594
42853
  input: "",
42595
42854
  locations: [],
42596
42855
  name: "",
42597
- output: output2,
42856
+ output: historyItem.text,
42598
42857
  status: "completed",
42599
- title: "Reasoning",
42858
+ title: "Plan",
42600
42859
  toolKind: ""
42601
42860
  })
42602
- );
42603
- sequence += 1;
42604
- }
42605
- continue;
42606
- } else if (type === "commandExecution" && options.detail === "rich") {
42607
- const command = commandExecutionSchema.parse(item);
42608
- const action = command.commandActions[0]?.type ?? "execute";
42609
- activities.push(
42610
- activity(command.id, "tool", sequence, {
42611
- input: JSON.stringify({ command: command.command, cwd: command.cwd }),
42612
- locations: [command.cwd],
42613
- name: "",
42614
- output: JSON.stringify({
42615
- formatted_output: command.aggregatedOutput ?? "",
42616
- ...command.exitCode == null ? {} : { exit_code: command.exitCode }
42617
- }),
42618
- status: command.status === "completed" ? "completed" : "failed",
42619
- title: command.command,
42620
- toolKind: action
42621
- })
42622
- );
42861
+ ],
42862
+ content: [],
42863
+ role: "assistant",
42864
+ text: ""
42865
+ });
42623
42866
  sequence += 1;
42624
- continue;
42625
- } else {
42626
- continue;
42627
- }
42628
- const fitted = fitHistoryMessage(message);
42629
- if (fitted.message.text.length === 0 && (fitted.message.images?.length ?? 0) === 0) {
42630
- continue;
42631
42867
  }
42632
- truncated ||= fitted.truncated;
42633
- messages.push(fitted.message);
42634
- if (message.role === "assistant") {
42635
- assistantMessageIndex = messages.length - 1;
42636
- }
42637
- characters += messageSize(fitted.message);
42638
42868
  }
42639
42869
  if (options.detail === "rich" && turn.error != null) {
42640
- activities.push(
42641
- activity(`agent-error-${sequence.toString()}`, "tool", sequence, {
42642
- input: "",
42643
- locations: [],
42644
- name: "",
42645
- output: errorMessage(turn.error),
42646
- status: "failed",
42647
- title: "Agent error",
42648
- toolKind: "other"
42649
- })
42650
- );
42651
- }
42652
- if (options.detail === "rich" && activities.length > assignedActivityCount) {
42653
- const message = {
42654
- activities: activitySlice(),
42870
+ append({
42871
+ activities: [
42872
+ activity(`agent-error-${sequence.toString()}`, "tool", sequence, {
42873
+ input: "",
42874
+ locations: [],
42875
+ name: "",
42876
+ output: errorMessage(turn.error),
42877
+ status: "failed",
42878
+ title: "Agent error",
42879
+ toolKind: "other"
42880
+ })
42881
+ ],
42655
42882
  content: [],
42656
42883
  role: "assistant",
42657
42884
  text: ""
42658
- };
42659
- messages.push(message);
42660
- assistantMessageIndex = messages.length - 1;
42661
- characters += messageSize(message);
42885
+ });
42662
42886
  }
42663
42887
  if (assistantMessageIndex !== null) {
42664
42888
  const assistant = messages[assistantMessageIndex];
@@ -42668,20 +42892,20 @@ function decodeHistory(thread, value, options) {
42668
42892
  ...assistant,
42669
42893
  ...outcome === void 0 ? {} : { outcome }
42670
42894
  };
42671
- const fitted = fitHistoryMessage(updated);
42895
+ const fitted = fitHistoryMessage(updated, turnMessageCharacterLimit);
42672
42896
  truncated ||= fitted.truncated;
42673
42897
  messages[assistantMessageIndex] = fitted.message;
42674
42898
  characters += messageSize(fitted.message);
42675
42899
  }
42676
- } else if (activities.length > 0 || outcome !== void 0) {
42900
+ } else if (outcome !== void 0) {
42677
42901
  const message = {
42678
- activities: activities.slice(-100),
42902
+ activities: [],
42679
42903
  content: [],
42680
42904
  role: "assistant",
42681
42905
  ...outcome === void 0 ? {} : { outcome },
42682
42906
  text: ""
42683
42907
  };
42684
- const fitted = fitHistoryMessage(message);
42908
+ const fitted = fitHistoryMessage(message, turnMessageCharacterLimit);
42685
42909
  truncated ||= fitted.truncated;
42686
42910
  messages.push(fitted.message);
42687
42911
  characters += messageSize(fitted.message);
@@ -44521,6 +44745,34 @@ function liveHistoryCoveredTurnRanges(history) {
44521
44745
  function historyMessageCharacters(message) {
44522
44746
  return message.text.length + (message.role === "assistant" ? JSON.stringify(message.activities).length + JSON.stringify(message.content).length : 0);
44523
44747
  }
44748
+ function boundedActiveMessages(messages, messageLimit, characterLimit) {
44749
+ const selected = [];
44750
+ let remainingCharacters = characterLimit;
44751
+ for (let index = messages.length - 1; index >= 0 && selected.length < messageLimit; index -= 1) {
44752
+ const message = messages[index];
44753
+ if (message === void 0) {
44754
+ break;
44755
+ }
44756
+ const characters = historyMessageCharacters(message);
44757
+ if (characters <= remainingCharacters) {
44758
+ selected.unshift(message);
44759
+ remainingCharacters -= characters;
44760
+ continue;
44761
+ }
44762
+ const structuredCharacters = characters - message.text.length;
44763
+ if (selected.length === 0 && structuredCharacters <= remainingCharacters) {
44764
+ const textCharacters = remainingCharacters - structuredCharacters;
44765
+ selected.unshift({ ...message, text: textCharacters === 0 ? "" : message.text.slice(-textCharacters) });
44766
+ remainingCharacters = 0;
44767
+ }
44768
+ break;
44769
+ }
44770
+ return {
44771
+ characters: characterLimit - remainingCharacters,
44772
+ messages: selected,
44773
+ truncated: selected.length !== messages.length
44774
+ };
44775
+ }
44524
44776
  function paginateAcpSessionHistory(history, sessionId, cursor, limit) {
44525
44777
  if (history.status === "unavailable") {
44526
44778
  if (cursor !== null) {
@@ -44551,30 +44803,19 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
44551
44803
  if (activeTurn === null || cursor !== null) {
44552
44804
  return paginateAcpSessionHistory(history, sessionId, cursor, limit);
44553
44805
  }
44554
- const activeMessageOverhead = 4;
44555
- const activeStructuredCharacters = JSON.stringify(activeTurn.activities).length + JSON.stringify(activeTurn.content).length;
44556
- const maximumActiveTextLength = Math.max(
44557
- 0,
44558
- SESSION_HISTORY_CHARACTER_LIMIT - activeTurn.prompt.length - activeStructuredCharacters - activeMessageOverhead
44559
- );
44560
- const activeText = activeTurn.text.slice(-maximumActiveTextLength);
44561
- const completeActiveMessages = [
44562
- { role: "user", text: activeTurn.prompt },
44563
- {
44564
- activities: activeTurn.activities,
44565
- content: activeTurn.content,
44566
- role: "assistant",
44567
- text: activeText
44568
- }
44569
- ];
44570
44806
  if (history.status === "unavailable") {
44807
+ const bounded3 = boundedActiveMessages(
44808
+ activeTurn.messages,
44809
+ Math.max(0, limit - 1),
44810
+ Math.max(0, SESSION_HISTORY_CHARACTER_LIMIT - activeTurn.prompt.length)
44811
+ );
44571
44812
  return {
44572
44813
  coveredCommandIds: [],
44573
44814
  coveredMessageIds: [],
44574
- messages: completeActiveMessages,
44815
+ messages: [{ role: "user", text: activeTurn.prompt }, ...bounded3.messages],
44575
44816
  nextCursor: null,
44576
44817
  status: "available",
44577
- truncated: activeTurn.truncated || activeText.length !== activeTurn.text.length
44818
+ truncated: activeTurn.truncated || bounded3.truncated
44578
44819
  };
44579
44820
  }
44580
44821
  const activeUserIndex = history.coveredCommandIds.includes(activeTurn.commandId) ? history.messages.findLastIndex((message) => message.role === "user") : -1;
@@ -44589,9 +44830,18 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
44589
44830
  };
44590
44831
  }
44591
44832
  const latestNativeMessage = history.messages.at(-1);
44592
- const activeMessages = activeUserIndex >= 0 || latestNativeMessage?.role === "user" && latestNativeMessage.text === activeTurn.prompt ? completeActiveMessages.slice(1) : completeActiveMessages;
44833
+ const includeActivePrompt = activeUserIndex < 0 && !(latestNativeMessage?.role === "user" && latestNativeMessage.text === activeTurn.prompt);
44834
+ const bounded2 = boundedActiveMessages(
44835
+ activeTurn.messages,
44836
+ Math.max(0, limit - (includeActivePrompt ? 1 : 0)),
44837
+ Math.max(0, SESSION_HISTORY_CHARACTER_LIMIT - (includeActivePrompt ? activeTurn.prompt.length : 0))
44838
+ );
44839
+ const activeMessages = [
44840
+ ...includeActivePrompt ? [{ role: "user", text: activeTurn.prompt }] : [],
44841
+ ...bounded2.messages
44842
+ ];
44593
44843
  let historicalMessageCount = 0;
44594
- let remainingCharacters = SESSION_HISTORY_CHARACTER_LIMIT - activeText.length - activeMessageOverhead - activeStructuredCharacters - (activeMessages.length === completeActiveMessages.length ? activeTurn.prompt.length : 0);
44844
+ let remainingCharacters = SESSION_HISTORY_CHARACTER_LIMIT - bounded2.characters - (includeActivePrompt ? activeTurn.prompt.length : 0);
44595
44845
  const historicalMessageLimit = Math.max(0, limit - activeMessages.length);
44596
44846
  for (let index = history.messages.length - 1; index >= 0 && historicalMessageCount < historicalMessageLimit; index -= 1) {
44597
44847
  const message = history.messages[index];
@@ -44616,7 +44866,7 @@ function paginateLiveSessionHistory(history, activeTurn, sessionId, cursor, limi
44616
44866
  return {
44617
44867
  ...page,
44618
44868
  messages: [...page.messages, ...activeMessages],
44619
- truncated: page.truncated || activeTurn.truncated || activeText.length !== activeTurn.text.length
44869
+ truncated: page.truncated || activeTurn.truncated || bounded2.truncated
44620
44870
  };
44621
44871
  }
44622
44872
  function mergeLiveSessionHistory(history, activeTurn, sessionId) {
@@ -44926,167 +45176,113 @@ function warnIgnoredSetting(audit, event, commandId, sessionId, agentId, selecti
44926
45176
  `);
44927
45177
  }
44928
45178
 
44929
- // src/relay-connection/coalescing-activity-publisher.ts
44930
- var AGENT_ACTIVITY_COALESCING_MILLISECONDS = 100;
44931
- var CoalescingDaemonActivityPublisher = class {
44932
- #pending = /* @__PURE__ */ new Map();
45179
+ // src/relay-connection/coalescing-agent-event-publisher.ts
45180
+ var AGENT_EVENT_COALESCING_MILLISECONDS = 100;
45181
+ var AGENT_EVENT_TEXT_MAXIMUM_LENGTH = 1e5;
45182
+ var CoalescingAgentEventPublisher = class {
45183
+ #entries = [];
44933
45184
  #publish;
44934
45185
  #publishedActivityIds = /* @__PURE__ */ new Set();
44935
- #scheduled = /* @__PURE__ */ new Map();
45186
+ #scheduled = null;
44936
45187
  #timer;
44937
45188
  constructor(timer, publish) {
44938
45189
  this.#publish = publish;
44939
45190
  this.#timer = timer;
44940
45191
  }
44941
- flush = () => {
44942
- const activities = [...this.#pending.values()].sort((left, right) => left.sequence - right.sequence);
44943
- for (const task of this.#scheduled.values()) {
44944
- task.cancel();
44945
- }
44946
- this.#pending.clear();
44947
- this.#scheduled.clear();
44948
- for (const activity2 of activities) {
44949
- this.#publish(activity2);
44950
- }
44951
- };
44952
- record = (activity2) => {
44953
- if (activity2.status !== "pending" && activity2.status !== "running") {
44954
- this.#discardPending(activity2.activityId);
44955
- this.#publishedActivityIds.add(activity2.activityId);
44956
- this.#publish(activity2);
44957
- return Promise.resolve();
44958
- }
44959
- if (!this.#publishedActivityIds.has(activity2.activityId)) {
44960
- this.#publishedActivityIds.add(activity2.activityId);
44961
- this.#publish(activity2);
44962
- return Promise.resolve();
44963
- }
44964
- this.#pending.set(activity2.activityId, activity2);
44965
- if (!this.#scheduled.has(activity2.activityId)) {
44966
- this.#scheduled.set(
44967
- activity2.activityId,
44968
- this.#timer.schedule(
44969
- () => this.#flushActivity(activity2.activityId),
44970
- AGENT_ACTIVITY_COALESCING_MILLISECONDS
44971
- )
44972
- );
44973
- }
44974
- return Promise.resolve();
44975
- };
44976
- #discardPending = (activityId) => {
44977
- this.#scheduled.get(activityId)?.cancel();
44978
- this.#scheduled.delete(activityId);
44979
- this.#pending.delete(activityId);
44980
- };
44981
- #flushActivity = (activityId) => {
44982
- const activity2 = this.#pending.get(activityId);
44983
- this.#discardPending(activityId);
44984
- if (activity2 !== void 0) {
44985
- this.#publish(activity2);
44986
- }
44987
- };
44988
- };
44989
-
44990
- // src/relay-connection/coalescing-narration-publisher.ts
44991
- var CoalescingNarrationPublisher = class {
44992
- #coalescingMilliseconds;
44993
- #maximumTextLength;
44994
- #publish;
44995
- #timer;
44996
- #pending = /* @__PURE__ */ new Map();
44997
- #scheduled = null;
44998
- constructor(timer, publish, coalescingMilliseconds, maximumTextLength) {
44999
- this.#publish = publish;
45000
- this.#timer = timer;
45001
- this.#coalescingMilliseconds = coalescingMilliseconds;
45002
- this.#maximumTextLength = maximumTextLength;
45003
- }
45004
- /** Emit every buffered increment now, cancelling the pending flush. */
45005
45192
  flush = () => {
45006
45193
  this.#scheduled?.cancel();
45007
45194
  this.#scheduled = null;
45008
- const increments = [...this.#pending.entries()].map(
45009
- ([activityId, pending]) => ({
45010
- activityId,
45011
- activityType: pending.activityType,
45012
- sequence: pending.sequence,
45013
- text: pending.text
45014
- })
45015
- );
45016
- this.#pending.clear();
45017
- for (const increment of increments) {
45018
- this.#publish(increment);
45195
+ const entries = this.#entries;
45196
+ this.#entries = [];
45197
+ for (const entry of entries) {
45198
+ this.#publish(entry);
45019
45199
  }
45020
45200
  };
45021
- /**
45022
- * Buffer an increment, emitting the buffered text when it would exceed the
45023
- * protocol's per-event text limit so no event is rejected by the codec.
45024
- */
45025
- record = (increment) => {
45026
- if (increment.text.length === 0) {
45027
- return;
45028
- }
45029
- const previous = this.#pending.get(increment.activityId);
45030
- if (previous !== void 0 && previous.text.length + increment.text.length > this.#maximumTextLength) {
45201
+ recordActivity = (activity2) => {
45202
+ const latest = this.#entries.at(-1);
45203
+ 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" }];
45204
+ const first = !this.#publishedActivityIds.has(activity2.activityId);
45205
+ this.#publishedActivityIds.add(activity2.activityId);
45206
+ if (first || activity2.status !== "pending" && activity2.status !== "running") {
45031
45207
  this.flush();
45208
+ } else {
45209
+ this.schedule();
45032
45210
  }
45033
- const current = this.#pending.get(increment.activityId);
45034
- this.#pending.set(increment.activityId, {
45035
- activityType: increment.activityType,
45036
- sequence: increment.sequence,
45037
- text: `${current?.text ?? ""}${increment.text}`
45038
- });
45039
- this.#scheduled ??= this.#timer.schedule(this.flush, this.#coalescingMilliseconds);
45211
+ return Promise.resolve();
45040
45212
  };
45041
- };
45042
-
45043
- // src/relay-connection/coalescing-text-publisher.ts
45044
- var CoalescingTextPublisher = class {
45045
- #coalescingMilliseconds;
45046
- #maximumTextLength;
45047
- #publish;
45048
- #timer;
45049
- #messageId = "";
45050
- #scheduled = null;
45051
- #text = "";
45052
- constructor(timer, publish, coalescingMilliseconds, maximumTextLength) {
45053
- this.#publish = publish;
45054
- this.#timer = timer;
45055
- this.#coalescingMilliseconds = coalescingMilliseconds;
45056
- this.#maximumTextLength = maximumTextLength;
45057
- }
45058
- /** Emit any buffered text now, cancelling the pending flush. */
45059
- flush = () => {
45060
- this.#scheduled?.cancel();
45061
- this.#scheduled = null;
45062
- const messageId = this.#messageId;
45063
- const text2 = this.#text;
45064
- this.#messageId = "";
45065
- this.#text = "";
45066
- if (text2.length > 0) {
45067
- this.#publish(messageId, text2);
45213
+ recordNarration = (increment) => {
45214
+ if (increment.text.length === 0) {
45215
+ return Promise.resolve();
45068
45216
  }
45217
+ let remaining = increment.text;
45218
+ while (remaining.length > 0) {
45219
+ const latest = this.#entries.at(-1);
45220
+ if (latest?.kind === "narration" && latest.increment.activityId === increment.activityId) {
45221
+ const available = AGENT_EVENT_TEXT_MAXIMUM_LENGTH - latest.increment.text.length;
45222
+ if (available > 0) {
45223
+ this.#entries = [
45224
+ ...this.#entries.slice(0, -1),
45225
+ {
45226
+ increment: {
45227
+ ...increment,
45228
+ text: `${latest.increment.text}${remaining.slice(0, available)}`
45229
+ },
45230
+ kind: "narration"
45231
+ }
45232
+ ];
45233
+ remaining = remaining.slice(available);
45234
+ continue;
45235
+ }
45236
+ }
45237
+ this.#entries = [
45238
+ ...this.#entries,
45239
+ {
45240
+ increment: { ...increment, text: remaining.slice(0, AGENT_EVENT_TEXT_MAXIMUM_LENGTH) },
45241
+ kind: "narration"
45242
+ }
45243
+ ];
45244
+ remaining = remaining.slice(AGENT_EVENT_TEXT_MAXIMUM_LENGTH);
45245
+ }
45246
+ this.schedule();
45247
+ return Promise.resolve();
45069
45248
  };
45070
- /**
45071
- * Buffer a chunk, emitting the buffered text when the message changes or the
45072
- * buffer would exceed the protocol's per-event text limit.
45073
- */
45074
- record = (messageId, text2) => {
45249
+ recordText = (text2, messageId) => {
45075
45250
  if (text2.length === 0) {
45076
- return;
45251
+ return Promise.resolve();
45077
45252
  }
45078
- if (this.#text.length > 0 && (this.#messageId !== messageId || this.#text.length + text2.length > this.#maximumTextLength)) {
45079
- this.flush();
45253
+ let remaining = text2;
45254
+ while (remaining.length > 0) {
45255
+ const latest = this.#entries.at(-1);
45256
+ if (latest?.kind === "text" && latest.messageId === messageId) {
45257
+ const available = AGENT_EVENT_TEXT_MAXIMUM_LENGTH - latest.text.length;
45258
+ if (available > 0) {
45259
+ this.#entries = [
45260
+ ...this.#entries.slice(0, -1),
45261
+ { ...latest, text: `${latest.text}${remaining.slice(0, available)}` }
45262
+ ];
45263
+ remaining = remaining.slice(available);
45264
+ continue;
45265
+ }
45266
+ }
45267
+ this.#entries = [
45268
+ ...this.#entries,
45269
+ {
45270
+ kind: "text",
45271
+ messageId,
45272
+ text: remaining.slice(0, AGENT_EVENT_TEXT_MAXIMUM_LENGTH)
45273
+ }
45274
+ ];
45275
+ remaining = remaining.slice(AGENT_EVENT_TEXT_MAXIMUM_LENGTH);
45080
45276
  }
45081
- this.#messageId = messageId;
45082
- this.#text = `${this.#text}${text2}`;
45083
- this.#scheduled ??= this.#timer.schedule(this.flush, this.#coalescingMilliseconds);
45277
+ this.schedule();
45278
+ return Promise.resolve();
45084
45279
  };
45280
+ schedule() {
45281
+ this.#scheduled ??= this.#timer.schedule(this.flush, AGENT_EVENT_COALESCING_MILLISECONDS);
45282
+ }
45085
45283
  };
45086
45284
 
45087
45285
  // src/daemon-prompt-executor.ts
45088
- var AGENT_TEXT_COALESCING_MILLISECONDS = 100;
45089
- var AGENT_TEXT_MAXIMUM_LENGTH = 1e5;
45090
45286
  function daemonActivity(command, activity2) {
45091
45287
  return {
45092
45288
  activityId: activity2.activityId,
@@ -45122,41 +45318,30 @@ async function executePrompt({
45122
45318
  recordLiveEvent,
45123
45319
  cancellationRequested
45124
45320
  }) {
45125
- const narration = new CoalescingNarrationPublisher(
45126
- timer,
45127
- (increment) => {
45128
- const event = {
45129
- activityId: increment.activityId,
45130
- activityType: increment.activityType,
45321
+ const events = new CoalescingAgentEventPublisher(timer, (event) => {
45322
+ if (event.kind === "text") {
45323
+ publisher.publish(
45324
+ command.sessionId,
45325
+ recordLiveEvent({ kind: AGENT_MESSAGE_DELTA_KIND, messageId: event.messageId, text: event.text })
45326
+ );
45327
+ return;
45328
+ }
45329
+ if (event.kind === "narration") {
45330
+ const recorded = {
45331
+ activityId: event.increment.activityId,
45332
+ activityType: event.increment.activityType,
45131
45333
  commandId: command.commandId,
45132
45334
  kind: AGENT_ACTIVITY_NARRATION_KIND,
45133
- sequence: increment.sequence,
45335
+ sequence: event.increment.sequence,
45134
45336
  sessionId: command.sessionId,
45135
- text: increment.text
45337
+ text: event.increment.text
45136
45338
  };
45137
- publisher.publish(command.sessionId, recordLiveEvent(event));
45138
- },
45139
- AGENT_ACTIVITY_COALESCING_MILLISECONDS,
45140
- AGENT_TEXT_MAXIMUM_LENGTH
45141
- );
45142
- const activities = new CoalescingDaemonActivityPublisher(timer, (activity2) => {
45143
- if (activity2.status !== "pending" && activity2.status !== "running") {
45144
- narration.flush();
45339
+ publisher.publish(command.sessionId, recordLiveEvent(recorded));
45340
+ return;
45145
45341
  }
45146
- const event = daemonActivity(command, activity2);
45147
- publisher.publish(command.sessionId, recordLiveEvent(event));
45342
+ const activity2 = daemonActivity(command, event.activity);
45343
+ publisher.publish(command.sessionId, recordLiveEvent(activity2));
45148
45344
  });
45149
- const text2 = new CoalescingTextPublisher(
45150
- timer,
45151
- (messageId, delta) => {
45152
- publisher.publish(
45153
- command.sessionId,
45154
- recordLiveEvent({ kind: AGENT_MESSAGE_DELTA_KIND, messageId, text: delta })
45155
- );
45156
- },
45157
- AGENT_TEXT_COALESCING_MILLISECONDS,
45158
- AGENT_TEXT_MAXIMUM_LENGTH
45159
- );
45160
45345
  try {
45161
45346
  const resolved = await resolveSessionDirectories(
45162
45347
  directories,
@@ -45245,15 +45430,9 @@ async function executePrompt({
45245
45430
  cwd: resolved.cwd,
45246
45431
  disposition: availability.disposition,
45247
45432
  images: attachments.images,
45248
- onActivity: activities.record,
45249
- onNarration: (increment) => {
45250
- narration.record(increment);
45251
- return Promise.resolve();
45252
- },
45253
- onText: (delta, messageId) => {
45254
- text2.record(messageId, delta);
45255
- return Promise.resolve();
45256
- },
45433
+ onActivity: events.recordActivity,
45434
+ onNarration: events.recordNarration,
45435
+ onText: events.recordText,
45257
45436
  prompt: command.prompt,
45258
45437
  resources: attachments.resources,
45259
45438
  sessionId: command.sessionId,
@@ -45262,9 +45441,7 @@ async function executePrompt({
45262
45441
  });
45263
45442
  stopReason = result.stopReason;
45264
45443
  }
45265
- text2.flush();
45266
- narration.flush();
45267
- activities.flush();
45444
+ events.flush();
45268
45445
  publisher.publish(command.sessionId, {
45269
45446
  commandId: command.commandId,
45270
45447
  kind: SESSION_COMPLETED_KIND,
@@ -45278,9 +45455,7 @@ async function executePrompt({
45278
45455
  sessionId: command.sessionId
45279
45456
  });
45280
45457
  } catch (error62) {
45281
- text2.flush();
45282
- narration.flush();
45283
- activities.flush();
45458
+ events.flush();
45284
45459
  if (signal.aborted && cancellationRequested()) {
45285
45460
  publisher.publish(command.sessionId, {
45286
45461
  commandId: command.commandId,