@moxt-ai/mobius 0.0.150 → 0.0.152

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 (51) hide show
  1. package/dist/acp/agent-runtime-manager.d.ts.map +1 -1
  2. package/dist/acp/agent-runtime-manager.js +8 -1
  3. package/dist/acp/agent-runtime-manager.js.map +1 -1
  4. package/dist/acp/agent-session.d.ts.map +1 -1
  5. package/dist/acp/agent-session.js +8 -4
  6. package/dist/acp/agent-session.js.map +1 -1
  7. package/dist/acp/session-contracts.d.ts +2 -1
  8. package/dist/acp/session-contracts.d.ts.map +1 -1
  9. package/dist/acp/session-contracts.js +3 -1
  10. package/dist/acp/session-contracts.js.map +1 -1
  11. package/dist/acp/session-store.d.ts +2 -1
  12. package/dist/acp/session-store.d.ts.map +1 -1
  13. package/dist/acp/session-store.js +6 -2
  14. package/dist/acp/session-store.js.map +1 -1
  15. package/dist/cli.js +228 -45
  16. package/dist/cli.js.map +3 -3
  17. package/dist/daemon-command-handler.d.ts.map +1 -1
  18. package/dist/daemon-command-handler.js +1 -0
  19. package/dist/daemon-command-handler.js.map +1 -1
  20. package/dist/daemon-prompt-executor.d.ts.map +1 -1
  21. package/dist/daemon-prompt-executor.js +28 -8
  22. package/dist/daemon-prompt-executor.js.map +1 -1
  23. package/dist/daemon-turn-registry.d.ts +13 -13
  24. package/dist/generated/acp-session-store-migrations.d.ts +3 -0
  25. package/dist/generated/acp-session-store-migrations.d.ts.map +1 -1
  26. package/dist/generated/acp-session-store-migrations.js +5 -1
  27. package/dist/generated/acp-session-store-migrations.js.map +1 -1
  28. package/dist/index.js +227 -44
  29. package/dist/index.js.map +3 -3
  30. package/dist/native-sessions/handle-native-requests.d.ts +2 -0
  31. package/dist/native-sessions/handle-native-requests.d.ts.map +1 -1
  32. package/dist/native-sessions/handle-native-requests.js +12 -1
  33. package/dist/native-sessions/handle-native-requests.js.map +1 -1
  34. package/dist/native-sessions/service.d.ts.map +1 -1
  35. package/dist/native-sessions/service.js +47 -0
  36. package/dist/native-sessions/service.js.map +1 -1
  37. package/dist/relay-connection/session-event-outbox.d.ts +1 -0
  38. package/dist/relay-connection/session-event-outbox.d.ts.map +1 -1
  39. package/dist/relay-connection/session-event-outbox.js +37 -22
  40. package/dist/relay-connection/session-event-outbox.js.map +1 -1
  41. package/dist/relay-connection/session-event-publisher.d.ts +1 -0
  42. package/dist/relay-connection/session-event-publisher.d.ts.map +1 -1
  43. package/dist/relay-connection/session-event-publisher.js +10 -2
  44. package/dist/relay-connection/session-event-publisher.js.map +1 -1
  45. package/dist/runtime.js +229 -46
  46. package/dist/runtime.js.map +3 -3
  47. package/dist/schema/acp-session-store/acp-session.d.ts +19 -0
  48. package/dist/schema/acp-session-store/acp-session.d.ts.map +1 -1
  49. package/dist/schema/acp-session-store/acp-session.js +1 -0
  50. package/dist/schema/acp-session-store/acp-session.js.map +1 -1
  51. package/package.json +1 -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.150",
3384
+ version: "0.0.152",
3385
3385
  description: "Mobius CLI for pairing and running local AI agent services.",
3386
3386
  type: "module",
3387
3387
  bin: {
@@ -29672,6 +29672,12 @@ var nativeSessionRequestSchema = external_exports.discriminatedUnion("action", [
29672
29672
  entryId: identifierStringSchema,
29673
29673
  targetSessionId: identifierStringSchema
29674
29674
  }).readonly(),
29675
+ external_exports.strictObject({
29676
+ ...identity,
29677
+ action: external_exports.literal("fork-recorded"),
29678
+ targetSessionId: identifierStringSchema,
29679
+ throughCommandId: identifierStringSchema
29680
+ }).readonly(),
29675
29681
  external_exports.strictObject({
29676
29682
  ...identity,
29677
29683
  action: external_exports.literal("delete"),
@@ -29695,6 +29701,12 @@ var nativeSessionCommandSchema = external_exports.discriminatedUnion("action", [
29695
29701
  entryId: identifierStringSchema,
29696
29702
  targetSessionId: identifierStringSchema
29697
29703
  }).readonly(),
29704
+ external_exports.strictObject({
29705
+ ...identity,
29706
+ action: external_exports.literal("fork-recorded"),
29707
+ targetSessionId: identifierStringSchema,
29708
+ throughCommandId: identifierStringSchema
29709
+ }).readonly(),
29698
29710
  external_exports.strictObject({
29699
29711
  ...identity,
29700
29712
  action: external_exports.literal("delete"),
@@ -29744,7 +29756,7 @@ var nativeSessionResultSchema = external_exports.discriminatedUnion("action", [
29744
29756
  }).readonly(),
29745
29757
  external_exports.strictObject({
29746
29758
  ...resultEnvelope,
29747
- action: external_exports.enum(["import", "fork"]),
29759
+ action: external_exports.enum(["import", "fork", "fork-recorded"]),
29748
29760
  targetSessionId: identifierStringSchema,
29749
29761
  ready: sessionReadyEventSchema,
29750
29762
  title: external_exports.string().max(500)
@@ -29793,6 +29805,7 @@ var SESSION_EVENT_KIND = "session.event";
29793
29805
  var SESSION_EVENT_ACK_KIND = "session.event.ack";
29794
29806
  var SESSION_EVENT_DEFERRED_KIND = "session.event.deferred";
29795
29807
  var SESSION_EVENT_REJECTED_KIND = "session.event.rejected";
29808
+ var SESSION_FORKED_KIND = "session.forked";
29796
29809
  var SessionEventRejectionCode = {
29797
29810
  IdempotencyConflict: "idempotency_conflict",
29798
29811
  InvalidEvent: "invalid_event",
@@ -29810,13 +29823,13 @@ var reliableDeliverySchema = external_exports.strictObject({
29810
29823
  sourceSeq: external_exports.string().regex(/^(?:0|[1-9][0-9]*)$/u).max(40),
29811
29824
  streamId: identifierStringSchema
29812
29825
  }).readonly();
29813
- var reliableEventEnvelopeSchema = external_exports.strictObject({
29826
+ var reliableSessionEventEnvelopeSchema = external_exports.strictObject({
29814
29827
  delivery: reliableDeliverySchema,
29815
29828
  kind: external_exports.literal(SESSION_EVENT_KIND),
29816
29829
  payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
29817
29830
  sessionId: identifierStringSchema
29818
29831
  }).readonly();
29819
- var eventEnvelopeSchema = external_exports.union([ephemeralEventEnvelopeSchema, reliableEventEnvelopeSchema]).readonly();
29832
+ var eventEnvelopeSchema = external_exports.union([ephemeralEventEnvelopeSchema, reliableSessionEventEnvelopeSchema]).readonly();
29820
29833
  var acknowledgementOutcomeSchema = external_exports.discriminatedUnion("kind", [
29821
29834
  external_exports.strictObject({ kind: external_exports.literal("relayed") }).readonly(),
29822
29835
  external_exports.strictObject({
@@ -29845,6 +29858,12 @@ var eventRejectedSchema = external_exports.strictObject({
29845
29858
  }).readonly();
29846
29859
  var SESSION_QUEUE_CHANGED_KIND = "session.queue.changed";
29847
29860
  var sessionQueueChangedSchema = external_exports.strictObject({ kind: external_exports.literal(SESSION_QUEUE_CHANGED_KIND), sessionId: identifierStringSchema }).readonly();
29861
+ var sessionForkedSchema = external_exports.strictObject({
29862
+ kind: external_exports.literal(SESSION_FORKED_KIND),
29863
+ sessionId: identifierStringSchema,
29864
+ sourceSessionId: identifierStringSchema,
29865
+ throughCommandId: identifierStringSchema
29866
+ }).readonly();
29848
29867
  function decode5(encoded, schema) {
29849
29868
  let value;
29850
29869
  try {
@@ -29882,6 +29901,8 @@ function decodeRecordedSessionEvent(encoded) {
29882
29901
  switch (kind) {
29883
29902
  case SESSION_QUEUE_CHANGED_KIND:
29884
29903
  return decode5(encoded, sessionQueueChangedSchema);
29904
+ case SESSION_FORKED_KIND:
29905
+ return decode5(encoded, sessionForkedSchema);
29885
29906
  case AGENT_ACTIVITY_KIND:
29886
29907
  return decodeAgentActivityEvent(encoded);
29887
29908
  case AGENT_ACTIVITY_NARRATION_KIND:
@@ -32686,13 +32707,15 @@ var AcpPreparedSession = class {
32686
32707
  capabilities;
32687
32708
  commands;
32688
32709
  configOptions;
32710
+ prompted;
32689
32711
  restored;
32690
- constructor(agentName, agentVersion, capabilities, commands, configOptions, restored) {
32712
+ constructor(agentName, agentVersion, capabilities, commands, configOptions, prompted, restored) {
32691
32713
  this.agentName = agentName;
32692
32714
  this.agentVersion = agentVersion;
32693
32715
  this.capabilities = capabilities;
32694
32716
  this.commands = commands;
32695
32717
  this.configOptions = configOptions;
32718
+ this.prompted = prompted;
32696
32719
  this.restored = restored;
32697
32720
  }
32698
32721
  };
@@ -38862,6 +38885,10 @@ var acpSessionStoreMigrations = [
38862
38885
  {
38863
38886
  "name": "0000_slimy_captain_midlands.sql",
38864
38887
  "sql": "CREATE TABLE `acp_session` (\n `session_id` text PRIMARY KEY NOT NULL,\n `agent_id` text NOT NULL,\n `native_session_id` text NOT NULL,\n `cwd` text NOT NULL,\n `additional_directories` text NOT NULL,\n `prompted` integer NOT NULL,\n `title` text NOT NULL,\n `updated_at` text NOT NULL\n);\n--> statement-breakpoint\nCREATE TABLE `deleted_acp_session` (\n `session_id` text PRIMARY KEY NOT NULL\n);\n"
38888
+ },
38889
+ {
38890
+ "name": "0001_regular_ultimates.sql",
38891
+ "sql": "ALTER TABLE `acp_session` ADD `last_terminal_command_id` text;"
38865
38892
  }
38866
38893
  ];
38867
38894
 
@@ -38879,6 +38906,7 @@ var acpSession = sqliteTable("acp_session", {
38879
38906
  nativeSessionId: text("native_session_id").notNull(),
38880
38907
  cwd: text("cwd").notNull(),
38881
38908
  additionalDirectories: text("additional_directories").notNull(),
38909
+ lastTerminalCommandId: text("last_terminal_command_id"),
38882
38910
  prompted: integer2("prompted", { mode: "boolean" }).notNull(),
38883
38911
  title: text("title").notNull(),
38884
38912
  updatedAt: text("updated_at").notNull()
@@ -38894,15 +38922,17 @@ var AcpStoredSession = class {
38894
38922
  additionalDirectories;
38895
38923
  agentId;
38896
38924
  cwd;
38925
+ lastTerminalCommandId;
38897
38926
  nativeSessionId;
38898
38927
  prompted;
38899
38928
  sessionId;
38900
38929
  title;
38901
38930
  updatedAt;
38902
- constructor(sessionId, agentId, nativeSessionId, cwd, additionalDirectories, prompted, title2, updatedAt = (/* @__PURE__ */ new Date()).toISOString()) {
38931
+ constructor(sessionId, agentId, nativeSessionId, cwd, additionalDirectories, prompted, title2, updatedAt = (/* @__PURE__ */ new Date()).toISOString(), lastTerminalCommandId = null) {
38903
38932
  this.additionalDirectories = [...additionalDirectories];
38904
38933
  this.agentId = agentId;
38905
38934
  this.cwd = cwd;
38935
+ this.lastTerminalCommandId = lastTerminalCommandId;
38906
38936
  this.nativeSessionId = nativeSessionId;
38907
38937
  this.prompted = prompted;
38908
38938
  this.sessionId = sessionId;
@@ -38963,6 +38993,7 @@ var storedSessionRowSchema = external_exports.object({
38963
38993
  additionalDirectories: external_exports.string(),
38964
38994
  agentId: external_exports.string(),
38965
38995
  cwd: external_exports.string(),
38996
+ lastTerminalCommandId: external_exports.string().nullable(),
38966
38997
  nativeSessionId: external_exports.string(),
38967
38998
  prompted: external_exports.boolean(),
38968
38999
  sessionId: external_exports.string(),
@@ -38982,7 +39013,8 @@ function decodeStoredSession(value) {
38982
39013
  additionalDirectories,
38983
39014
  row.prompted,
38984
39015
  row.title,
38985
- row.updatedAt
39016
+ row.updatedAt,
39017
+ row.lastTerminalCommandId
38986
39018
  );
38987
39019
  }
38988
39020
  var SqliteAcpSessionStore = class {
@@ -39049,6 +39081,7 @@ var SqliteAcpSessionStore = class {
39049
39081
  additionalDirectories: JSON.stringify(session.additionalDirectories),
39050
39082
  agentId: session.agentId,
39051
39083
  cwd: session.cwd,
39084
+ lastTerminalCommandId: session.lastTerminalCommandId,
39052
39085
  nativeSessionId: session.nativeSessionId,
39053
39086
  prompted: session.prompted,
39054
39087
  sessionId: session.sessionId,
@@ -39101,6 +39134,7 @@ var AgentSession = class _AgentSession {
39101
39134
  #commands = [];
39102
39135
  #configRevision = 0;
39103
39136
  #configOptions = [];
39137
+ #lastTerminalCommandId = null;
39104
39138
  #prompted = false;
39105
39139
  #nativePrompt = null;
39106
39140
  #sessionLoad = { kind: "not-requested" };
@@ -39204,6 +39238,7 @@ var AgentSession = class _AgentSession {
39204
39238
  this.#capabilities,
39205
39239
  this.#commands,
39206
39240
  this.#configOptions,
39241
+ this.#prompted,
39207
39242
  this.#restored
39208
39243
  );
39209
39244
  loadHistory = async (signal) => {
@@ -39437,6 +39472,7 @@ var AgentSession = class _AgentSession {
39437
39472
  } else if (stored instanceof FoundAcpStoredSession && stored.session.agentId === this.#agentId && stored.session.cwd === this.#cwd && arraysEqual(stored.session.additionalDirectories, this.#additionalDirectories)) {
39438
39473
  this.selectNativeSession(stored.session.nativeSessionId);
39439
39474
  this.#prompted = stored.session.prompted;
39475
+ this.#lastTerminalCommandId = stored.session.lastTerminalCommandId;
39440
39476
  this.#sessionTitle = stored.session.title;
39441
39477
  this.#restored = true;
39442
39478
  if (this.#capabilities.resumeSession) {
@@ -39510,7 +39546,9 @@ var AgentSession = class _AgentSession {
39510
39546
  this.#cwd,
39511
39547
  this.#additionalDirectories,
39512
39548
  this.#prompted,
39513
- this.#sessionTitle ?? ""
39549
+ this.#sessionTitle ?? "",
39550
+ (/* @__PURE__ */ new Date()).toISOString(),
39551
+ this.#lastTerminalCommandId
39514
39552
  )
39515
39553
  );
39516
39554
  };
@@ -39710,7 +39748,9 @@ var AgentSession = class _AgentSession {
39710
39748
  this.#cwd,
39711
39749
  this.#additionalDirectories,
39712
39750
  true,
39713
- this.#sessionTitle
39751
+ this.#sessionTitle,
39752
+ (/* @__PURE__ */ new Date()).toISOString(),
39753
+ this.#lastTerminalCommandId
39714
39754
  )
39715
39755
  );
39716
39756
  this.#prompted = true;
@@ -39762,6 +39802,20 @@ var AgentSession = class _AgentSession {
39762
39802
  usage: result.usage ?? null
39763
39803
  });
39764
39804
  }
39805
+ this.#lastTerminalCommandId = options.commandId;
39806
+ this.#store.write(
39807
+ new AcpStoredSession(
39808
+ this.#mobiusSessionId,
39809
+ this.#agentId,
39810
+ this.#updates.sessionId(),
39811
+ this.#cwd,
39812
+ this.#additionalDirectories,
39813
+ true,
39814
+ this.#sessionTitle ?? "",
39815
+ (/* @__PURE__ */ new Date()).toISOString(),
39816
+ this.#lastTerminalCommandId
39817
+ )
39818
+ );
39765
39819
  return result;
39766
39820
  } catch (error62) {
39767
39821
  await running.activities.finish();
@@ -39954,7 +40008,9 @@ var AgentSession = class _AgentSession {
39954
40008
  this.#cwd,
39955
40009
  this.#additionalDirectories,
39956
40010
  this.#prompted,
39957
- this.#sessionTitle ?? ""
40011
+ this.#sessionTitle ?? "",
40012
+ (/* @__PURE__ */ new Date()).toISOString(),
40013
+ this.#lastTerminalCommandId
39958
40014
  )
39959
40015
  );
39960
40016
  }
@@ -41000,9 +41056,17 @@ var AgentRuntimeManager = class {
41000
41056
  const openedKey = `${options2.agent.id}:${runtime.nativeSessionId()}`;
41001
41057
  this.#nativeOperations.add(openedKey);
41002
41058
  try {
41059
+ const prepared = runtime.prepared();
41060
+ if (origin.kind === "fork" && options2.agent.id === "claude") {
41061
+ await this.#retireSessionProcess(
41062
+ options2.sessionId,
41063
+ runtime,
41064
+ async () => await runtime.closeProcess()
41065
+ );
41066
+ }
41003
41067
  return {
41004
41068
  sessionId: options2.sessionId,
41005
- prepared: runtime.prepared()
41069
+ prepared
41006
41070
  };
41007
41071
  } finally {
41008
41072
  this.#nativeOperations.delete(openedKey);
@@ -43413,6 +43477,7 @@ var readCodexFullHistory = async (agent, cwd, nativeSessionId, signal, nativeTur
43413
43477
 
43414
43478
  // src/native-sessions/service.ts
43415
43479
  import { randomUUID as randomUUID3 } from "node:crypto";
43480
+ import { basename as basename5 } from "node:path";
43416
43481
 
43417
43482
  // src/native-sessions/acp-history.ts
43418
43483
  async function readAcpHistory(sessions, directories, bindingId, options, nativeSessionId) {
@@ -43553,6 +43618,64 @@ var NativeSessionService = class {
43553
43618
  sessionId: command.sessionId
43554
43619
  };
43555
43620
  }
43621
+ if (command.action === "fork-recorded") {
43622
+ const source = this.#sessions.findSessions([command.sessionId])[0];
43623
+ if (source === void 0 || !source.prompted) {
43624
+ throw new AcpExecutionError(
43625
+ "The source conversation has no resumable native Agent session",
43626
+ {},
43627
+ "native_session_not_found"
43628
+ );
43629
+ }
43630
+ if (source.agentId !== command.agentId || source.cwd !== cwd || source.additionalDirectories.length !== additionalDirectories.length || source.additionalDirectories.some((path3, index) => path3 !== additionalDirectories[index])) {
43631
+ throw new AcpExecutionError(
43632
+ "The source conversation execution target does not match the fork request",
43633
+ {},
43634
+ "native_session_target_changed"
43635
+ );
43636
+ }
43637
+ if (source.lastTerminalCommandId !== command.throughCommandId) {
43638
+ throw new AcpExecutionError(
43639
+ "The selected Turn is no longer the source conversation head",
43640
+ {},
43641
+ "fork_point_stale"
43642
+ );
43643
+ }
43644
+ const opened2 = await this.#sessions.openNativeSession(
43645
+ { ...options, sessionId: command.targetSessionId },
43646
+ { kind: "fork", nativeSessionId: source.nativeSessionId }
43647
+ );
43648
+ signal.throwIfAborted();
43649
+ const directory = await this.#directories.list(this.#config.bindingId, command.directoryId, signal);
43650
+ const ready2 = {
43651
+ additionalDirectories: additionalDirectories.map((path3, index) => ({
43652
+ directoryId: command.additionalDirectoryIds[index] ?? command.directoryId,
43653
+ name: basename5(path3) || path3
43654
+ })),
43655
+ agentId: command.agentId,
43656
+ agentName: opened2.prepared.agentName,
43657
+ agentVersion: opened2.prepared.agentVersion,
43658
+ capabilities: opened2.prepared.capabilities,
43659
+ commands: opened2.prepared.commands,
43660
+ configOptions: opened2.prepared.configOptions,
43661
+ directoryId: command.directoryId,
43662
+ directoryLabel: directory.directoryLabel,
43663
+ kind: "session.ready",
43664
+ requestId: command.requestId,
43665
+ restored: true,
43666
+ sessionId: opened2.sessionId
43667
+ };
43668
+ this.record(command, "native_recorded_session_forked");
43669
+ return {
43670
+ action: "fork-recorded",
43671
+ kind: "native.session.result",
43672
+ ready: ready2,
43673
+ requestId: command.requestId,
43674
+ sessionId: command.sessionId,
43675
+ targetSessionId: command.targetSessionId,
43676
+ title: source.title || "Untitled session"
43677
+ };
43678
+ }
43556
43679
  const prepared = await this.#sessions.prepareNativeSessionBrowser(options);
43557
43680
  if (!prepared.capabilities.listSessions) {
43558
43681
  throw new AcpExecutionError(
@@ -44874,7 +44997,7 @@ function createAgentSettingsDiscoveryHandler(dependencies) {
44874
44997
  // src/artifacts/local-file-streamer.ts
44875
44998
  import { createReadStream as createReadStream2 } from "node:fs";
44876
44999
  import { realpath as realpath9, stat as stat8 } from "node:fs/promises";
44877
- import { basename as basename5, isAbsolute as isAbsolute10, normalize as normalize4, resolve as resolve7 } from "node:path";
45000
+ import { basename as basename6, isAbsolute as isAbsolute10, normalize as normalize4, resolve as resolve7 } from "node:path";
44878
45001
  import { fileURLToPath as fileURLToPath2 } from "node:url";
44879
45002
  var CHUNK_BYTES = 192 * 1024;
44880
45003
  function requestedPath(value) {
@@ -44925,7 +45048,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
44925
45048
  kind: FILE_BEGIN_KIND,
44926
45049
  mediaType: raster?.mimeType ?? "application/octet-stream",
44927
45050
  modifiedAt: before.mtime.toISOString(),
44928
- name: basename5(target) || "file",
45051
+ name: basename6(target) || "file",
44929
45052
  requestId: command.requestId,
44930
45053
  sessionId: command.sessionId
44931
45054
  });
@@ -44955,7 +45078,7 @@ async function streamLocalFile(command, send2, signal, workingDirectory) {
44955
45078
  }
44956
45079
 
44957
45080
  // src/authorization/resolve-session-directories.ts
44958
- import { basename as basename6 } from "node:path";
45081
+ import { basename as basename7 } from "node:path";
44959
45082
  var ResolvedSessionDirectories = class {
44960
45083
  additionalDirectories;
44961
45084
  additionalDirectoryEntries;
@@ -44980,7 +45103,7 @@ async function resolveSessionDirectories(directories, bindingId, directoryId2, a
44980
45103
  additionalDirectories.push(directory);
44981
45104
  additionalDirectoryEntries.push({
44982
45105
  directoryId: additionalDirectoryId,
44983
- name: basename6(directory)
45106
+ name: basename7(directory)
44984
45107
  });
44985
45108
  }
44986
45109
  return new ResolvedSessionDirectories(cwd, additionalDirectories, additionalDirectoryEntries);
@@ -45717,14 +45840,15 @@ async function executePrompt({
45717
45840
  const appliedSettings = command.sessionConfigurations === void 0 ? void 0 : agentForSessionConfiguration(agent, command.sessionConfigurations);
45718
45841
  const executionAgent = appliedSettings?.agent ?? agent;
45719
45842
  const sessionConfigurations = appliedSettings?.sessionConfigurations;
45843
+ const preparation = {
45844
+ additionalDirectories: resolved.additionalDirectories,
45845
+ agent: executionAgent,
45846
+ cwd: resolved.cwd,
45847
+ sessionId: command.sessionId,
45848
+ signal
45849
+ };
45850
+ let prepared = await sessions.prepareExecutionSession(preparation);
45720
45851
  if (command.sessionConfigurations !== void 0) {
45721
- const prepared = await sessions.prepareExecutionSession({
45722
- additionalDirectories: resolved.additionalDirectories,
45723
- agent: executionAgent,
45724
- cwd: resolved.cwd,
45725
- sessionId: command.sessionId,
45726
- signal
45727
- });
45728
45852
  if (availability.disposition === SessionPromptDisposition.Steer) {
45729
45853
  assertAppliedSessionConfiguration(prepared.configOptions, sessionConfigurations ?? []);
45730
45854
  } else {
@@ -45740,6 +45864,7 @@ async function executePrompt({
45740
45864
  command.sessionId,
45741
45865
  signal
45742
45866
  );
45867
+ prepared = await sessions.prepareExecutionSession(preparation);
45743
45868
  }
45744
45869
  }
45745
45870
  audit.record({
@@ -45758,6 +45883,24 @@ async function executePrompt({
45758
45883
  }
45759
45884
  }
45760
45885
  const stream = activateAttempt();
45886
+ if (!prepared.prompted) {
45887
+ const listing = await directories.list(config2.bindingId, command.directoryId, signal);
45888
+ publisher.publish(command.sessionId, {
45889
+ additionalDirectories: resolved.additionalDirectoryEntries,
45890
+ agentId: command.agentId,
45891
+ agentName: prepared.agentName,
45892
+ agentVersion: prepared.agentVersion,
45893
+ capabilities: prepared.capabilities,
45894
+ commands: prepared.commands,
45895
+ configOptions: prepared.configOptions,
45896
+ directoryId: command.directoryId,
45897
+ directoryLabel: listing.directoryLabel,
45898
+ kind: SESSION_READY_KIND,
45899
+ requestId: command.commandId,
45900
+ restored: prepared.restored,
45901
+ sessionId: command.sessionId
45902
+ });
45903
+ }
45761
45904
  publisher.publish(command.sessionId, {
45762
45905
  commandId: command.commandId,
45763
45906
  epoch: stream.epoch,
@@ -46011,7 +46154,7 @@ async function executeSessionConfigure(publisher, socket, command, config2, dire
46011
46154
  // src/native-sessions/handle-native-requests.ts
46012
46155
  import { WebSocket as WebSocket5 } from "undici";
46013
46156
  function createNativeSessionRequestHandler(dependencies) {
46014
- const { audit, diagnostics, nativeSessions, signal, socket, timer } = dependencies;
46157
+ const { audit, diagnostics, nativeSessions, publisher, signal, socket, timer } = dependencies;
46015
46158
  const pending = /* @__PURE__ */ new Map();
46016
46159
  const cancel = (command) => {
46017
46160
  const request = pending.get(command.requestId);
@@ -46063,6 +46206,17 @@ function createNativeSessionRequestHandler(dependencies) {
46063
46206
  }
46064
46207
  operationSignal.throwIfAborted();
46065
46208
  const result = await nativeSessions.execute(command, operationSignal);
46209
+ if (command.action === "fork-recorded" && result.action === "fork-recorded") {
46210
+ publisher.publishBatch(result.ready.sessionId, [
46211
+ result.ready,
46212
+ {
46213
+ kind: "session.forked",
46214
+ sessionId: result.ready.sessionId,
46215
+ sourceSessionId: command.sessionId,
46216
+ throughCommandId: command.throughCommandId
46217
+ }
46218
+ ]);
46219
+ }
46066
46220
  if (socket.readyState === WebSocket5.OPEN) {
46067
46221
  send(socket, result);
46068
46222
  }
@@ -46148,6 +46302,7 @@ function createDaemonCommandHandler({
46148
46302
  audit,
46149
46303
  diagnostics,
46150
46304
  nativeSessions,
46305
+ publisher,
46151
46306
  signal,
46152
46307
  socket,
46153
46308
  timer
@@ -46920,6 +47075,16 @@ var SessionEventOutbox = class {
46920
47075
  this.#database.close();
46921
47076
  };
46922
47077
  enqueue = (sessionId, payload, critical) => {
47078
+ const envelope2 = this.enqueueBatch(sessionId, [payload], critical)[0];
47079
+ if (envelope2 === void 0) {
47080
+ throw new Error("The Session event outbox did not enqueue the event");
47081
+ }
47082
+ return envelope2;
47083
+ };
47084
+ enqueueBatch = (sessionId, payloads, critical) => {
47085
+ if (payloads.length < 1 || payloads.length > 32) {
47086
+ throw new Error("A Session event batch must contain between 1 and 32 events");
47087
+ }
46923
47088
  this.#database.exec("BEGIN IMMEDIATE");
46924
47089
  try {
46925
47090
  const state = this.#database.prepare(
@@ -46928,39 +47093,52 @@ var SessionEventOutbox = class {
46928
47093
  WHERE singleton = 1`
46929
47094
  ).get();
46930
47095
  const sourceSeq = rowNumber(state, "next_source_seq");
46931
- if (sourceSeq < 1 || !Number.isSafeInteger(sourceSeq + 1)) {
47096
+ if (sourceSeq < 1 || !Number.isSafeInteger(sourceSeq + payloads.length)) {
46932
47097
  throw new Error("The Session event source sequence is exhausted");
46933
47098
  }
46934
- const envelope2 = {
46935
- delivery: {
46936
- eventId: randomUUID7(),
46937
- kind: "reliable",
46938
- sourceSeq: sourceSeq.toString(),
46939
- streamId: rowString(state, "stream_id")
46940
- },
46941
- kind: SESSION_EVENT_KIND,
46942
- payload,
46943
- sessionId
46944
- };
46945
- const encoded = encodeSessionEventEnvelope(envelope2);
46946
- const byteLength = Buffer.byteLength(encoded, "utf8");
47099
+ const streamId = rowString(state, "stream_id");
47100
+ const stored = payloads.map((payload, index) => {
47101
+ const envelope2 = {
47102
+ delivery: {
47103
+ eventId: randomUUID7(),
47104
+ kind: "reliable",
47105
+ sourceSeq: (sourceSeq + index).toString(),
47106
+ streamId
47107
+ },
47108
+ kind: SESSION_EVENT_KIND,
47109
+ payload,
47110
+ sessionId
47111
+ };
47112
+ const encoded = encodeSessionEventEnvelope(envelope2);
47113
+ return { byteLength: Buffer.byteLength(encoded, "utf8"), encoded, envelope: envelope2 };
47114
+ });
47115
+ const byteLength = stored.reduce((total, entry) => total + entry.byteLength, 0);
46947
47116
  const maximumBytes = critical ? this.#limits.criticalEventBytes : this.#limits.standardEventBytes;
46948
47117
  if (rowNumber(state, "total_bytes") + byteLength > maximumBytes) {
46949
47118
  throw new SessionEventOutboxCapacityError();
46950
47119
  }
46951
- this.#database.prepare(
47120
+ const insert = this.#database.prepare(
46952
47121
  `INSERT INTO relay_session_event_outbox (
46953
- event_id, session_id, source_seq, byte_length, envelope_json
46954
- ) VALUES (?, ?, ?, ?, ?)`
46955
- ).run(envelope2.delivery.eventId, sessionId, sourceSeq, byteLength, encoded);
47122
+ event_id, session_id, source_seq, byte_length, envelope_json
47123
+ ) VALUES (?, ?, ?, ?, ?)`
47124
+ );
47125
+ for (const entry of stored) {
47126
+ insert.run(
47127
+ entry.envelope.delivery.eventId,
47128
+ sessionId,
47129
+ Number(entry.envelope.delivery.sourceSeq),
47130
+ entry.byteLength,
47131
+ entry.encoded
47132
+ );
47133
+ }
46956
47134
  this.#database.prepare(
46957
47135
  `UPDATE relay_session_event_outbox_state
46958
- SET next_source_seq = next_source_seq + 1,
47136
+ SET next_source_seq = next_source_seq + ?,
46959
47137
  total_bytes = total_bytes + ?
46960
47138
  WHERE singleton = 1`
46961
- ).run(byteLength);
47139
+ ).run(stored.length, byteLength);
46962
47140
  this.#database.exec("COMMIT");
46963
- return envelope2;
47141
+ return stored.map((entry) => entry.envelope);
46964
47142
  } catch (error62) {
46965
47143
  this.#database.exec("ROLLBACK");
46966
47144
  throw error62;
@@ -47061,7 +47239,7 @@ import { WebSocket as WebSocket9 } from "undici";
47061
47239
  var SESSION_EVENT_REPLAY_WINDOW = 16;
47062
47240
  var SESSION_EVENT_REPLAY_BYTE_LIMIT = 32 * 1024 * 1024;
47063
47241
  function reservesSessionEventCapacity(event) {
47064
- if (event.kind === SESSION_COMPLETED_KIND || event.kind === SESSION_FAILED_KIND) {
47242
+ if (event.kind === SESSION_COMPLETED_KIND || event.kind === SESSION_FAILED_KIND || event.kind === SESSION_FORKED_KIND || event.kind === SESSION_READY_KIND) {
47065
47243
  return true;
47066
47244
  }
47067
47245
  return event.kind === AGENT_ACTIVITY_KIND && (event.activityType === "progress" || event.activityType === "reasoning") && (event.status === "completed" || event.status === "failed");
@@ -47134,6 +47312,11 @@ var DaemonSessionEventPublisher = class {
47134
47312
  }
47135
47313
  this.#publishNextBatch();
47136
47314
  };
47315
+ publishBatch = (sessionId, events) => {
47316
+ const critical = events.some(reservesSessionEventCapacity);
47317
+ this.#outbox.enqueueBatch(sessionId, events.map(encodeRecordedSessionEvent), critical);
47318
+ this.#publishNextBatch();
47319
+ };
47137
47320
  quarantine = (rejection) => {
47138
47321
  if (!this.#outbox.quarantine(rejection)) {
47139
47322
  return;