@moxt-ai/mobius 0.0.6 → 0.0.8

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 (38) hide show
  1. package/dist/acp/activity.d.ts +7 -2
  2. package/dist/acp/activity.d.ts.map +1 -1
  3. package/dist/acp/activity.js +95 -7
  4. package/dist/acp/activity.js.map +1 -1
  5. package/dist/acp/native-session.d.ts +2 -2
  6. package/dist/acp/native-session.d.ts.map +1 -1
  7. package/dist/acp/native-session.js +2 -1
  8. package/dist/acp/native-session.js.map +1 -1
  9. package/dist/acp/session-manager.d.ts +2 -0
  10. package/dist/acp/session-manager.d.ts.map +1 -1
  11. package/dist/acp/session-manager.js +127 -44
  12. package/dist/acp/session-manager.js.map +1 -1
  13. package/dist/agent-installation/installation-grants.d.ts.map +1 -1
  14. package/dist/agent-installation/installation-grants.js +1 -2
  15. package/dist/agent-installation/installation-grants.js.map +1 -1
  16. package/dist/cli.js +1226 -240
  17. package/dist/cli.js.map +4 -4
  18. package/dist/config.js +1 -1
  19. package/dist/config.js.map +1 -1
  20. package/dist/index.js +1233 -247
  21. package/dist/index.js.map +4 -4
  22. package/dist/native-sessions/service.d.ts.map +1 -1
  23. package/dist/native-sessions/service.js +16 -11
  24. package/dist/native-sessions/service.js.map +1 -1
  25. package/dist/pairing/pair-local-machine.d.ts.map +1 -1
  26. package/dist/pairing/pair-local-machine.js +12 -5
  27. package/dist/pairing/pair-local-machine.js.map +1 -1
  28. package/dist/relay-connection/liveness.d.ts.map +1 -1
  29. package/dist/relay-connection/liveness.js +1 -2
  30. package/dist/relay-connection/liveness.js.map +1 -1
  31. package/dist/relay-connection/session-event-outbox.d.ts +19 -0
  32. package/dist/relay-connection/session-event-outbox.d.ts.map +1 -0
  33. package/dist/relay-connection/session-event-outbox.js +182 -0
  34. package/dist/relay-connection/session-event-outbox.js.map +1 -0
  35. package/dist/run-daemon.d.ts.map +1 -1
  36. package/dist/run-daemon.js +87 -63
  37. package/dist/run-daemon.js.map +1 -1
  38. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -60,7 +60,7 @@ async function readGrantedAgents(stateDirectory) {
60
60
  }
61
61
  const encoded = await handle.readFile({ encoding: "utf8" });
62
62
  const value = JSON.parse(encoded);
63
- if (!isRecord(value) || Object.keys(value).length !== 2 || value["version"] !== 1 || !Array.isArray(value["agents"])) {
63
+ if (!isRecord(value) || Object.keys(value).length !== 1 || !Array.isArray(value["agents"])) {
64
64
  throw new Error("The local installation grant file is invalid");
65
65
  }
66
66
  const agents = /* @__PURE__ */ new Set();
@@ -1441,7 +1441,11 @@ var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
1441
1441
  var IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
1442
1442
  var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
1443
1443
  var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
1444
- var CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken"];
1444
+ var CLAIM_RESPONSE_KEYS = [
1445
+ "channelId",
1446
+ "daemonToken",
1447
+ "runtimeId"
1448
+ ];
1445
1449
  var SAVED_CONNECTION_KEYS = [
1446
1450
  "defaultWorkspace",
1447
1451
  "channelId",
@@ -1633,20 +1637,21 @@ function decodeClaimResponse(value) {
1633
1637
  }
1634
1638
  const channelId = value["channelId"];
1635
1639
  const daemonToken = value["daemonToken"];
1636
- if (typeof channelId !== "string" || !IDENTIFIER_PATTERN.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken)) {
1640
+ const runtimeId = value["runtimeId"];
1641
+ if (typeof channelId !== "string" || !IDENTIFIER_PATTERN.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN.test(runtimeId)) {
1637
1642
  throw new PairingClientError(
1638
1643
  "invalid_relay_response",
1639
1644
  "The relay returned an invalid pairing response"
1640
1645
  );
1641
1646
  }
1642
- return { channelId, daemonToken };
1647
+ return { channelId, daemonToken, runtimeId };
1643
1648
  }
1644
1649
  async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
1645
1650
  const agents = localAgents.map((agent) => ({
1646
1651
  id: agent.id,
1647
1652
  label: agent.label
1648
1653
  }));
1649
- const endpoint = new URL("/v1/pairings/claim", options.relayOrigin);
1654
+ const endpoint = new URL("/api/pairings/claim", options.relayOrigin);
1650
1655
  let response;
1651
1656
  try {
1652
1657
  response = await fetch(endpoint, {
@@ -1783,7 +1788,7 @@ function assertInventoryUsable(inventory) {
1783
1788
  function buildPairedDaemon(connection, connectionPath, inventory) {
1784
1789
  assertInventoryUsable(inventory);
1785
1790
  const relayUrl = new URL(
1786
- `/v1/channels/${encodeURIComponent(connection.channelId)}/daemon`,
1791
+ `/api/channels/${encodeURIComponent(connection.channelId)}/daemon`,
1787
1792
  connection.relayOrigin
1788
1793
  );
1789
1794
  relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
@@ -1862,7 +1867,6 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
1862
1867
  }
1863
1868
 
1864
1869
  // src/run-daemon.ts
1865
- import { randomUUID as randomUUID5 } from "node:crypto";
1866
1870
  import { basename as basename3 } from "node:path";
1867
1871
 
1868
1872
  // ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
@@ -20781,9 +20785,6 @@ function decodeAgentPromptResponse(value) {
20781
20785
  return result.data;
20782
20786
  }
20783
20787
 
20784
- // ../protocol/src/version.ts
20785
- var MOBIUS_PROTOCOL_VERSION = 1;
20786
-
20787
20788
  // ../protocol/src/control-messages.ts
20788
20789
  var WORKSPACE_LIST_KIND = "workspace.list";
20789
20790
  var WORKSPACE_ENTRIES_KIND = "workspace.entries";
@@ -20816,7 +20817,6 @@ var IDENTIFIER = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATT
20816
20817
  var DIRECTORY_IDENTIFIER = external_exports.string().min(1).max(2048).regex(DIRECTORY_IDENTIFIER_PATTERN);
20817
20818
  var SHORT_TEXT = external_exports.string().max(500);
20818
20819
  var LONG_TEXT = external_exports.string().max(1e5);
20819
- var PROTOCOL_VERSION2 = external_exports.literal(MOBIUS_PROTOCOL_VERSION);
20820
20820
  var workspaceEntrySchema = external_exports.strictObject({
20821
20821
  directoryId: DIRECTORY_IDENTIFIER,
20822
20822
  name: external_exports.string().min(1).max(255)
@@ -20914,6 +20914,25 @@ var displayContentSchema = external_exports.strictObject({
20914
20914
  ]),
20915
20915
  uri: external_exports.string().max(4096)
20916
20916
  }).readonly();
20917
+ var recordedDisplayContentSchema = external_exports.strictObject({
20918
+ data: external_exports.string().max(4e6),
20919
+ mimeType: external_exports.string().max(255),
20920
+ name: external_exports.string().max(500),
20921
+ newText: external_exports.string().max(4e6),
20922
+ oldText: external_exports.string().max(4e6),
20923
+ path: external_exports.string().max(2048),
20924
+ terminalId: external_exports.string().max(255),
20925
+ text: external_exports.string().max(4e6),
20926
+ type: external_exports.enum([
20927
+ "diff",
20928
+ "image",
20929
+ "resource",
20930
+ "resource_link",
20931
+ "terminal",
20932
+ "text"
20933
+ ]),
20934
+ uri: external_exports.string().max(4096)
20935
+ }).readonly();
20917
20936
  var promptImageSchema = external_exports.strictObject({
20918
20937
  data: external_exports.string().min(1).max(4e6),
20919
20938
  mimeType: external_exports.string().min(1).max(255),
@@ -20930,7 +20949,6 @@ var workspaceListCommandSchema = external_exports.strictObject({
20930
20949
  bindingId: IDENTIFIER,
20931
20950
  directoryId: DIRECTORY_IDENTIFIER,
20932
20951
  kind: external_exports.literal(WORKSPACE_LIST_KIND),
20933
- protocolVersion: PROTOCOL_VERSION2,
20934
20952
  requestId: IDENTIFIER
20935
20953
  }).readonly();
20936
20954
  var workspaceEntriesEventSchema = external_exports.strictObject({
@@ -20940,7 +20958,6 @@ var workspaceEntriesEventSchema = external_exports.strictObject({
20940
20958
  entries: external_exports.array(workspaceEntrySchema).max(500).readonly(),
20941
20959
  kind: external_exports.literal(WORKSPACE_ENTRIES_KIND),
20942
20960
  parentDirectoryId: external_exports.string().max(2048),
20943
- protocolVersion: PROTOCOL_VERSION2,
20944
20961
  requestId: IDENTIFIER
20945
20962
  }).readonly();
20946
20963
  var sessionIdentityFields = {
@@ -20953,7 +20970,6 @@ var sessionIdentityFields = {
20953
20970
  var sessionPrepareCommandSchema = external_exports.strictObject({
20954
20971
  ...sessionIdentityFields,
20955
20972
  kind: external_exports.literal(SESSION_PREPARE_KIND),
20956
- protocolVersion: PROTOCOL_VERSION2,
20957
20973
  requestId: IDENTIFIER
20958
20974
  }).readonly();
20959
20975
  var sessionReadyEventSchema = external_exports.strictObject({
@@ -20967,7 +20983,6 @@ var sessionReadyEventSchema = external_exports.strictObject({
20967
20983
  directoryId: DIRECTORY_IDENTIFIER,
20968
20984
  directoryLabel: external_exports.string().min(1).max(2048),
20969
20985
  kind: external_exports.literal(SESSION_READY_KIND),
20970
- protocolVersion: PROTOCOL_VERSION2,
20971
20986
  requestId: IDENTIFIER,
20972
20987
  restored: external_exports.boolean(),
20973
20988
  sessionId: IDENTIFIER
@@ -20977,7 +20992,6 @@ var sessionConfigureCommandSchema = external_exports.strictObject({
20977
20992
  booleanValue: external_exports.boolean(),
20978
20993
  configId: external_exports.string().min(1).max(128),
20979
20994
  kind: external_exports.literal(SESSION_CONFIGURE_KIND),
20980
- protocolVersion: PROTOCOL_VERSION2,
20981
20995
  requestId: IDENTIFIER,
20982
20996
  value: external_exports.string().max(500),
20983
20997
  valueType: external_exports.enum(["boolean", "select"])
@@ -20985,7 +20999,6 @@ var sessionConfigureCommandSchema = external_exports.strictObject({
20985
20999
  var sessionConfigUpdatedEventSchema = external_exports.strictObject({
20986
21000
  configOptions: external_exports.array(configOptionSchema).max(100).readonly(),
20987
21001
  kind: external_exports.literal(SESSION_CONFIG_UPDATED_KIND),
20988
- protocolVersion: PROTOCOL_VERSION2,
20989
21002
  requestId: IDENTIFIER,
20990
21003
  sessionId: IDENTIFIER
20991
21004
  }).readonly();
@@ -20994,7 +21007,6 @@ var sessionContextUsageUpdatedEventSchema = external_exports.strictObject({
20994
21007
  costCurrency: external_exports.string().max(16),
20995
21008
  hasCost: external_exports.boolean(),
20996
21009
  kind: external_exports.literal(SESSION_USAGE_UPDATED_KIND),
20997
- protocolVersion: PROTOCOL_VERSION2,
20998
21010
  sessionId: IDENTIFIER,
20999
21011
  size: external_exports.number().int().nonnegative(),
21000
21012
  source: external_exports.literal("context").default("context"),
@@ -21004,7 +21016,6 @@ var sessionPromptUsageUpdatedEventSchema = external_exports.strictObject({
21004
21016
  _meta: promptMetadataSchema.nullable(),
21005
21017
  commandId: IDENTIFIER,
21006
21018
  kind: external_exports.literal(SESSION_USAGE_UPDATED_KIND),
21007
- protocolVersion: PROTOCOL_VERSION2,
21008
21019
  sessionId: IDENTIFIER,
21009
21020
  source: external_exports.literal("prompt"),
21010
21021
  usage: promptUsageSchema.nullable()
@@ -21016,12 +21027,10 @@ var sessionUsageUpdatedEventSchema = external_exports.union([
21016
21027
  var sessionCommandsUpdatedEventSchema = external_exports.strictObject({
21017
21028
  commands: external_exports.array(sessionCommandSchema).max(500).readonly(),
21018
21029
  kind: external_exports.literal(SESSION_COMMANDS_UPDATED_KIND),
21019
- protocolVersion: PROTOCOL_VERSION2,
21020
21030
  sessionId: IDENTIFIER
21021
21031
  }).readonly();
21022
21032
  var sessionInfoUpdatedEventSchema = external_exports.strictObject({
21023
21033
  kind: external_exports.literal(SESSION_INFO_UPDATED_KIND),
21024
- protocolVersion: PROTOCOL_VERSION2,
21025
21034
  sessionId: IDENTIFIER,
21026
21035
  title: external_exports.string().max(500).nullable(),
21027
21036
  updatedAt: external_exports.string().max(128)
@@ -21031,7 +21040,6 @@ var sessionPermissionRequestedEventSchema = external_exports.strictObject({
21031
21040
  interactionId: IDENTIFIER,
21032
21041
  kind: external_exports.literal(SESSION_PERMISSION_REQUESTED_KIND),
21033
21042
  options: external_exports.array(permissionOptionSchema).min(1).max(20).readonly(),
21034
- protocolVersion: PROTOCOL_VERSION2,
21035
21043
  sessionId: IDENTIFIER,
21036
21044
  title: external_exports.string().min(1).max(500),
21037
21045
  toolCallId: external_exports.string().min(1).max(255),
@@ -21042,7 +21050,6 @@ var sessionPermissionRespondCommandSchema = external_exports.strictObject({
21042
21050
  kind: external_exports.literal(SESSION_PERMISSION_RESPOND_KIND),
21043
21051
  optionId: external_exports.string().max(255),
21044
21052
  outcome: external_exports.enum(["cancelled", "selected"]),
21045
- protocolVersion: PROTOCOL_VERSION2,
21046
21053
  sessionId: IDENTIFIER
21047
21054
  }).readonly();
21048
21055
  var sessionPermissionResolvedEventSchema = external_exports.strictObject({
@@ -21050,7 +21057,6 @@ var sessionPermissionResolvedEventSchema = external_exports.strictObject({
21050
21057
  kind: external_exports.literal(SESSION_PERMISSION_RESOLVED_KIND),
21051
21058
  optionId: external_exports.string().max(255),
21052
21059
  outcome: external_exports.enum(["cancelled", "selected"]),
21053
- protocolVersion: PROTOCOL_VERSION2,
21054
21060
  sessionId: IDENTIFIER
21055
21061
  }).readonly();
21056
21062
  var sessionElicitationRequestedEventSchema = external_exports.strictObject({
@@ -21062,7 +21068,6 @@ var sessionElicitationRequestedEventSchema = external_exports.strictObject({
21062
21068
  kind: external_exports.literal(SESSION_ELICITATION_REQUESTED_KIND),
21063
21069
  message: external_exports.string().min(1).max(2e3),
21064
21070
  mode: external_exports.enum(["form", "url"]),
21065
- protocolVersion: PROTOCOL_VERSION2,
21066
21071
  sessionId: IDENTIFIER,
21067
21072
  url: external_exports.string().max(4096)
21068
21073
  }).readonly();
@@ -21071,21 +21076,18 @@ var sessionElicitationRespondCommandSchema = external_exports.strictObject({
21071
21076
  content: external_exports.string().max(1e5),
21072
21077
  interactionId: IDENTIFIER,
21073
21078
  kind: external_exports.literal(SESSION_ELICITATION_RESPOND_KIND),
21074
- protocolVersion: PROTOCOL_VERSION2,
21075
21079
  sessionId: IDENTIFIER
21076
21080
  }).readonly();
21077
21081
  var sessionElicitationResolvedEventSchema = external_exports.strictObject({
21078
21082
  action: external_exports.enum(["accept", "cancel", "decline", "complete"]),
21079
21083
  interactionId: IDENTIFIER,
21080
21084
  kind: external_exports.literal(SESSION_ELICITATION_RESOLVED_KIND),
21081
- protocolVersion: PROTOCOL_VERSION2,
21082
21085
  sessionId: IDENTIFIER
21083
21086
  }).readonly();
21084
21087
  var sessionOperationFailedEventSchema = external_exports.strictObject({
21085
21088
  code: IDENTIFIER,
21086
21089
  kind: external_exports.literal(SESSION_OPERATION_FAILED_KIND),
21087
21090
  message: external_exports.string().min(1).max(500),
21088
- protocolVersion: PROTOCOL_VERSION2,
21089
21091
  requestId: IDENTIFIER,
21090
21092
  sessionId: external_exports.string().max(128)
21091
21093
  }).readonly();
@@ -21095,12 +21097,10 @@ var agentContentEventSchema = external_exports.strictObject({
21095
21097
  contentId: IDENTIFIER,
21096
21098
  kind: external_exports.literal(AGENT_CONTENT_KIND),
21097
21099
  messageId: external_exports.string().max(255),
21098
- protocolVersion: PROTOCOL_VERSION2,
21099
21100
  sessionId: IDENTIFIER
21100
21101
  }).readonly();
21101
21102
  var agentInstallIdentityFields = {
21102
21103
  agentId: IDENTIFIER,
21103
- protocolVersion: PROTOCOL_VERSION2,
21104
21104
  requestId: IDENTIFIER
21105
21105
  };
21106
21106
  var agentInstallRequestCommandSchema = external_exports.strictObject({
@@ -21109,7 +21109,6 @@ var agentInstallRequestCommandSchema = external_exports.strictObject({
21109
21109
  }).readonly();
21110
21110
  var agentInstallCancelCommandSchema = external_exports.strictObject({
21111
21111
  kind: external_exports.literal(AGENT_INSTALL_CANCEL_KIND),
21112
- protocolVersion: PROTOCOL_VERSION2,
21113
21112
  requestId: IDENTIFIER
21114
21113
  }).readonly();
21115
21114
  var agentInstallAwaitingApprovalEventSchema = external_exports.strictObject({
@@ -21175,6 +21174,7 @@ function decodeValue(value, schema) {
21175
21174
  return result.data;
21176
21175
  }
21177
21176
  var decodeAgentDisplayContentValue = (value) => decodeValue(value, displayContentSchema);
21177
+ var decodeRecordedAgentContentValue = (value) => decodeValue(value, recordedDisplayContentSchema);
21178
21178
  var decodePromptImagesValue = (value) => decodeValue(value, external_exports.array(promptImageSchema).max(8).readonly());
21179
21179
  var decodePromptResourcesValue = (value) => decodeValue(value, external_exports.array(promptResourceSchema).max(16).readonly());
21180
21180
  var encode3 = (message, schema) => JSON.stringify(decodeValue(message, schema));
@@ -21214,6 +21214,8 @@ var SESSION_STARTED_KIND = "session.started";
21214
21214
  var AGENT_MESSAGE_DELTA_KIND = "agent.message.delta";
21215
21215
  var AGENT_ACTIVITY_KIND = "agent.activity";
21216
21216
  var AGENT_ACTIVITY_DETAIL_LIMIT = 24e3;
21217
+ var AGENT_ACTIVITY_RECORDED_FIELD_LIMIT = 4e6;
21218
+ var AGENT_ACTIVITY_RECORDED_DETAIL_LIMIT = 6e6;
21217
21219
  var AGENT_ACTIVITY_LOCATION_LIMIT = 12;
21218
21220
  var AGENT_ACTIVITY_LOCATION_LENGTH_LIMIT = 1024;
21219
21221
  var SESSION_COMPLETED_KIND = "session.completed";
@@ -21346,6 +21348,53 @@ function readActivityContent(value) {
21346
21348
  }
21347
21349
  return field.map((entry) => decodeAgentDisplayContentValue(entry));
21348
21350
  }
21351
+ function readActivityDetail(value) {
21352
+ const field = value["detail"];
21353
+ if (!isRecord4(field)) {
21354
+ throw new ProtocolMessageError("Invalid activity detail field");
21355
+ }
21356
+ const kind = readString(field, "kind", 32);
21357
+ if (kind === "available") {
21358
+ assertExactKeys(field, ["artifactId", "kind"]);
21359
+ return {
21360
+ artifactId: readIdentifier(field, "artifactId"),
21361
+ kind
21362
+ };
21363
+ }
21364
+ if (kind === "unrecorded") {
21365
+ assertExactKeys(field, ["kind"]);
21366
+ return { kind };
21367
+ }
21368
+ if (kind === "truncated") {
21369
+ assertExactKeys(field, ["capturedBytes", "kind", "originalBytes"]);
21370
+ const capturedBytes = readSequence(field, "capturedBytes");
21371
+ const originalBytes = readSequence(field, "originalBytes");
21372
+ if (capturedBytes > originalBytes) {
21373
+ throw new ProtocolMessageError("Invalid truncated activity detail size");
21374
+ }
21375
+ return { capturedBytes, kind, originalBytes };
21376
+ }
21377
+ if (kind === "recorded") {
21378
+ assertExactKeys(field, ["content", "input", "kind", "output"]);
21379
+ const contentValue = field["content"];
21380
+ if (!Array.isArray(contentValue) || contentValue.length > 100) {
21381
+ throw new ProtocolMessageError("Invalid recorded activity content");
21382
+ }
21383
+ const detail = {
21384
+ content: contentValue.map(
21385
+ (entry) => decodeRecordedAgentContentValue(entry)
21386
+ ),
21387
+ input: readText(field, "input", AGENT_ACTIVITY_RECORDED_FIELD_LIMIT),
21388
+ kind,
21389
+ output: readText(field, "output", AGENT_ACTIVITY_RECORDED_FIELD_LIMIT)
21390
+ };
21391
+ if (JSON.stringify(detail).length > AGENT_ACTIVITY_RECORDED_DETAIL_LIMIT) {
21392
+ throw new ProtocolMessageError("Recorded activity detail is too large");
21393
+ }
21394
+ return detail;
21395
+ }
21396
+ throw new ProtocolMessageError("Invalid activity detail availability");
21397
+ }
21349
21398
  function readIdentifier(value, key) {
21350
21399
  const field = readString(value, key, 128);
21351
21400
  if (!IDENTIFIER_PATTERN3.test(field)) {
@@ -21362,11 +21411,6 @@ function readDirectoryIdentifier(value, key) {
21362
21411
  }
21363
21412
  return field;
21364
21413
  }
21365
- function assertProtocolVersion(value) {
21366
- if (value["protocolVersion"] !== MOBIUS_PROTOCOL_VERSION) {
21367
- throw new ProtocolMessageError("Unsupported protocol version");
21368
- }
21369
- }
21370
21414
  function assertKind(value, expectedKind) {
21371
21415
  if (value["kind"] !== expectedKind) {
21372
21416
  throw new ProtocolMessageError(`Expected message kind: ${expectedKind}`);
@@ -21386,11 +21430,9 @@ function decodeSessionPromptCommand(encoded) {
21386
21430
  "images",
21387
21431
  "kind",
21388
21432
  "prompt",
21389
- "protocolVersion",
21390
21433
  "resources",
21391
21434
  "sessionId"
21392
21435
  ]);
21393
- assertProtocolVersion(value);
21394
21436
  assertKind(value, SESSION_PROMPT_KIND);
21395
21437
  const prompt = readText(value, "prompt", MAX_PROMPT_LENGTH);
21396
21438
  const images = decodePromptImagesValue(value["images"]);
@@ -21415,89 +21457,62 @@ function decodeSessionPromptCommand(encoded) {
21415
21457
  images,
21416
21458
  kind: SESSION_PROMPT_KIND,
21417
21459
  prompt,
21418
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
21419
21460
  resources,
21420
21461
  sessionId: readIdentifier(value, "sessionId")
21421
21462
  };
21422
21463
  }
21423
21464
  function decodeSessionCancelCommand(encoded) {
21424
21465
  const value = parseJson2(encoded);
21425
- assertExactKeys(value, ["commandId", "kind", "protocolVersion", "sessionId"]);
21426
- assertProtocolVersion(value);
21466
+ assertExactKeys(value, ["commandId", "kind", "sessionId"]);
21427
21467
  assertKind(value, SESSION_CANCEL_KIND);
21428
21468
  return {
21429
21469
  commandId: readIdentifier(value, "commandId"),
21430
21470
  kind: SESSION_CANCEL_KIND,
21431
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
21432
21471
  sessionId: readIdentifier(value, "sessionId")
21433
21472
  };
21434
21473
  }
21435
21474
  function decodeRuntimeLivenessReadyEvent(encoded) {
21436
21475
  const value = parseJson2(encoded);
21437
- assertExactKeys(value, ["kind", "protocolVersion"]);
21438
- assertProtocolVersion(value);
21476
+ assertExactKeys(value, ["kind"]);
21439
21477
  assertKind(value, RUNTIME_LIVENESS_READY_KIND);
21440
- return {
21441
- kind: RUNTIME_LIVENESS_READY_KIND,
21442
- protocolVersion: MOBIUS_PROTOCOL_VERSION
21443
- };
21478
+ return { kind: RUNTIME_LIVENESS_READY_KIND };
21444
21479
  }
21445
21480
  function decodeRuntimeHeartbeatEvent(encoded) {
21446
21481
  const value = parseJson2(encoded);
21447
- assertExactKeys(value, ["heartbeatId", "kind", "protocolVersion"]);
21448
- assertProtocolVersion(value);
21482
+ assertExactKeys(value, ["heartbeatId", "kind"]);
21449
21483
  assertKind(value, RUNTIME_HEARTBEAT_KIND);
21450
21484
  return {
21451
21485
  heartbeatId: readIdentifier(value, "heartbeatId"),
21452
- kind: RUNTIME_HEARTBEAT_KIND,
21453
- protocolVersion: MOBIUS_PROTOCOL_VERSION
21486
+ kind: RUNTIME_HEARTBEAT_KIND
21454
21487
  };
21455
21488
  }
21456
21489
  function decodeRuntimeHeartbeatAckEvent(encoded) {
21457
21490
  const value = parseJson2(encoded);
21458
- assertExactKeys(value, ["heartbeatId", "kind", "protocolVersion"]);
21459
- assertProtocolVersion(value);
21491
+ assertExactKeys(value, ["heartbeatId", "kind"]);
21460
21492
  assertKind(value, RUNTIME_HEARTBEAT_ACK_KIND);
21461
21493
  return {
21462
21494
  heartbeatId: readIdentifier(value, "heartbeatId"),
21463
- kind: RUNTIME_HEARTBEAT_ACK_KIND,
21464
- protocolVersion: MOBIUS_PROTOCOL_VERSION
21495
+ kind: RUNTIME_HEARTBEAT_ACK_KIND
21465
21496
  };
21466
21497
  }
21467
21498
  function decodeSessionStartedEvent(encoded) {
21468
21499
  const value = parseJson2(encoded);
21469
- assertExactKeys(value, [
21470
- "commandId",
21471
- "kind",
21472
- "processAttemptId",
21473
- "protocolVersion",
21474
- "sessionId"
21475
- ]);
21476
- assertProtocolVersion(value);
21500
+ assertExactKeys(value, ["commandId", "kind", "attemptId", "sessionId"]);
21477
21501
  assertKind(value, SESSION_STARTED_KIND);
21478
21502
  return {
21479
21503
  commandId: readIdentifier(value, "commandId"),
21480
21504
  kind: SESSION_STARTED_KIND,
21481
- processAttemptId: readIdentifier(value, "processAttemptId"),
21482
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
21505
+ attemptId: readIdentifier(value, "attemptId"),
21483
21506
  sessionId: readIdentifier(value, "sessionId")
21484
21507
  };
21485
21508
  }
21486
21509
  function decodeAgentMessageDeltaEvent(encoded) {
21487
21510
  const value = parseJson2(encoded);
21488
- assertExactKeys(value, [
21489
- "commandId",
21490
- "kind",
21491
- "protocolVersion",
21492
- "sessionId",
21493
- "text"
21494
- ]);
21495
- assertProtocolVersion(value);
21511
+ assertExactKeys(value, ["commandId", "kind", "sessionId", "text"]);
21496
21512
  assertKind(value, AGENT_MESSAGE_DELTA_KIND);
21497
21513
  return {
21498
21514
  commandId: readIdentifier(value, "commandId"),
21499
21515
  kind: AGENT_MESSAGE_DELTA_KIND,
21500
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
21501
21516
  sessionId: readIdentifier(value, "sessionId"),
21502
21517
  text: readString(value, "text", MAX_EVENT_TEXT_LENGTH)
21503
21518
  };
@@ -21509,31 +21524,30 @@ function decodeAgentActivityEvent(encoded) {
21509
21524
  "activityType",
21510
21525
  "commandId",
21511
21526
  "content",
21527
+ "detail",
21512
21528
  "input",
21513
21529
  "kind",
21514
21530
  "locations",
21515
21531
  "name",
21516
21532
  "output",
21517
- "protocolVersion",
21518
21533
  "sequence",
21519
21534
  "sessionId",
21520
21535
  "status",
21521
21536
  "title",
21522
21537
  "toolKind"
21523
21538
  ]);
21524
- assertProtocolVersion(value);
21525
21539
  assertKind(value, AGENT_ACTIVITY_KIND);
21526
21540
  return {
21527
21541
  activityId: readIdentifier(value, "activityId"),
21528
21542
  activityType: readAllowedString(value, "activityType", ACTIVITY_TYPES),
21529
21543
  commandId: readIdentifier(value, "commandId"),
21530
21544
  content: readActivityContent(value),
21545
+ detail: readActivityDetail(value),
21531
21546
  input: readText(value, "input", AGENT_ACTIVITY_DETAIL_LIMIT),
21532
21547
  kind: AGENT_ACTIVITY_KIND,
21533
21548
  locations: readLocations(value),
21534
21549
  name: readText(value, "name", 128),
21535
21550
  output: readText(value, "output", AGENT_ACTIVITY_DETAIL_LIMIT),
21536
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
21537
21551
  sequence: readSequence(value, "sequence"),
21538
21552
  sessionId: readIdentifier(value, "sessionId"),
21539
21553
  status: readAllowedString(value, "status", ACTIVITY_STATUSES),
@@ -21543,41 +21557,24 @@ function decodeAgentActivityEvent(encoded) {
21543
21557
  }
21544
21558
  function decodeSessionCompletedEvent(encoded) {
21545
21559
  const value = parseJson2(encoded);
21546
- assertExactKeys(value, [
21547
- "commandId",
21548
- "kind",
21549
- "protocolVersion",
21550
- "sessionId",
21551
- "stopReason"
21552
- ]);
21553
- assertProtocolVersion(value);
21560
+ assertExactKeys(value, ["commandId", "kind", "sessionId", "stopReason"]);
21554
21561
  assertKind(value, SESSION_COMPLETED_KIND);
21555
21562
  return {
21556
21563
  commandId: readIdentifier(value, "commandId"),
21557
21564
  kind: SESSION_COMPLETED_KIND,
21558
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
21559
21565
  sessionId: readIdentifier(value, "sessionId"),
21560
21566
  stopReason: readString(value, "stopReason", 64)
21561
21567
  };
21562
21568
  }
21563
21569
  function decodeSessionFailedEvent(encoded) {
21564
21570
  const value = parseJson2(encoded);
21565
- assertExactKeys(value, [
21566
- "code",
21567
- "commandId",
21568
- "kind",
21569
- "message",
21570
- "protocolVersion",
21571
- "sessionId"
21572
- ]);
21573
- assertProtocolVersion(value);
21571
+ assertExactKeys(value, ["code", "commandId", "kind", "message", "sessionId"]);
21574
21572
  assertKind(value, SESSION_FAILED_KIND);
21575
21573
  return {
21576
21574
  code: readIdentifier(value, "code"),
21577
21575
  commandId: readIdentifier(value, "commandId"),
21578
21576
  kind: SESSION_FAILED_KIND,
21579
21577
  message: readString(value, "message", 500),
21580
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
21581
21578
  sessionId: readIdentifier(value, "sessionId")
21582
21579
  };
21583
21580
  }
@@ -21667,7 +21664,6 @@ var NATIVE_SESSION_CANCEL_KIND = "native.session.cancel";
21667
21664
  var identifier = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/);
21668
21665
  var directoryId = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/);
21669
21666
  var envelope = {
21670
- protocolVersion: external_exports.literal(MOBIUS_PROTOCOL_VERSION),
21671
21667
  requestId: identifier,
21672
21668
  sessionId: identifier
21673
21669
  };
@@ -21722,6 +21718,7 @@ var nativeSessionResultSchema = external_exports.discriminatedUnion("action", [
21722
21718
  external_exports.strictObject({
21723
21719
  ...resultEnvelope,
21724
21720
  action: external_exports.enum(["import", "fork"]),
21721
+ targetSessionId: identifier,
21725
21722
  ready: sessionReadyEventSchema,
21726
21723
  history: sessionHistorySchema,
21727
21724
  title: external_exports.string().max(500)
@@ -21730,6 +21727,7 @@ var nativeSessionResultSchema = external_exports.discriminatedUnion("action", [
21730
21727
  ...resultEnvelope,
21731
21728
  action: external_exports.literal("preview"),
21732
21729
  entryId: identifier,
21730
+ targetSessionId: identifier,
21733
21731
  reason: external_exports.literal("continuation_unavailable"),
21734
21732
  history: sessionHistorySchema,
21735
21733
  title: external_exports.string().max(500)
@@ -21754,6 +21752,563 @@ var decodeNativeSessionCommand = (encoded) => decode4(nativeSessionCommandSchema
21754
21752
  var encodeNativeSessionResult = (value) => JSON.stringify(nativeSessionResultSchema.parse(value));
21755
21753
  var decodeNativeSessionCancel = (encoded) => decode4(nativeSessionCancelSchema, encoded);
21756
21754
 
21755
+ // ../protocol/src/resource-model.ts
21756
+ var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
21757
+ var DECIMAL_SEQUENCE_PATTERN = /^(?:0|[1-9][0-9]*)$/;
21758
+ var SHA256_PATTERN = /^[a-f0-9]{64}$/;
21759
+ var identifierSchema = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4);
21760
+ var timestampSchema = external_exports.string().datetime({ offset: true });
21761
+ var decimalSequenceSchema = external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN);
21762
+ var digestSchema = external_exports.string().length(64).regex(SHA256_PATTERN);
21763
+ var recordingPolicySchema = external_exports.strictObject({
21764
+ contentLimitBytes: external_exports.number().int().positive().safe(),
21765
+ hotEventLimit: external_exports.number().int().positive().safe(),
21766
+ idempotencyRetentionMilliseconds: external_exports.number().int().positive().safe(),
21767
+ level: external_exports.enum(["full", "summary"]),
21768
+ retentionMilliseconds: external_exports.number().int().positive().safe()
21769
+ }).readonly();
21770
+ var tenantLifecycleSchema = external_exports.discriminatedUnion("kind", [
21771
+ external_exports.strictObject({ kind: external_exports.literal("active") }).readonly(),
21772
+ external_exports.strictObject({
21773
+ kind: external_exports.literal("suspended"),
21774
+ suspendedAt: timestampSchema
21775
+ }).readonly(),
21776
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
21777
+ ]);
21778
+ var tenantSchema = external_exports.strictObject({
21779
+ lifecycle: tenantLifecycleSchema,
21780
+ quotaPolicyRevision: external_exports.number().int().nonnegative().safe(),
21781
+ recordingPolicy: recordingPolicySchema,
21782
+ tenantId: identifierSchema
21783
+ }).readonly();
21784
+ var projectLifecycleSchema = external_exports.discriminatedUnion("kind", [
21785
+ external_exports.strictObject({ kind: external_exports.literal("active") }).readonly(),
21786
+ external_exports.strictObject({ archivedAt: timestampSchema, kind: external_exports.literal("archived") }).readonly(),
21787
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
21788
+ ]);
21789
+ var projectSchema = external_exports.strictObject({
21790
+ displayName: external_exports.string().min(1).max(120),
21791
+ lifecycle: projectLifecycleSchema,
21792
+ projectId: identifierSchema,
21793
+ tenantId: identifierSchema
21794
+ }).readonly();
21795
+ var runtimeLifecycleSchema = external_exports.discriminatedUnion("kind", [
21796
+ external_exports.strictObject({ kind: external_exports.literal("registered") }).readonly(),
21797
+ external_exports.strictObject({ disabledAt: timestampSchema, kind: external_exports.literal("disabled") }).readonly(),
21798
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
21799
+ ]);
21800
+ var runtimeCapabilitySchema = external_exports.strictObject({
21801
+ name: identifierSchema,
21802
+ revision: external_exports.number().int().nonnegative().safe()
21803
+ }).readonly();
21804
+ var runtimeSchema = external_exports.strictObject({
21805
+ capabilities: external_exports.array(runtimeCapabilitySchema).max(100).readonly(),
21806
+ displayName: external_exports.string().min(1).max(120),
21807
+ lifecycle: runtimeLifecycleSchema,
21808
+ runtimeId: identifierSchema,
21809
+ tenantId: identifierSchema
21810
+ }).readonly();
21811
+ var channelStateSchema = external_exports.discriminatedUnion("kind", [
21812
+ external_exports.strictObject({
21813
+ connectionEpoch: external_exports.number().int().nonnegative().safe(),
21814
+ connectedAt: timestampSchema,
21815
+ connectionId: identifierSchema,
21816
+ kind: external_exports.literal("online")
21817
+ }).readonly(),
21818
+ external_exports.strictObject({
21819
+ connectionEpoch: external_exports.number().int().nonnegative().safe(),
21820
+ disconnectedAt: timestampSchema,
21821
+ kind: external_exports.literal("offline")
21822
+ }).readonly()
21823
+ ]);
21824
+ var channelSchema = external_exports.strictObject({
21825
+ channelId: identifierSchema,
21826
+ runtimeId: identifierSchema,
21827
+ state: channelStateSchema
21828
+ }).readonly();
21829
+ var sessionLifecycleSchema = external_exports.discriminatedUnion("kind", [
21830
+ external_exports.strictObject({ kind: external_exports.literal("ready") }).readonly(),
21831
+ external_exports.strictObject({ kind: external_exports.literal("deleting"), requestedAt: timestampSchema }).readonly(),
21832
+ external_exports.strictObject({ completedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
21833
+ ]);
21834
+ var sessionSchema = external_exports.strictObject({
21835
+ createdAt: timestampSchema,
21836
+ createdBy: identifierSchema,
21837
+ defaultBindingId: identifierSchema,
21838
+ lastCommittedSeq: decimalSequenceSchema,
21839
+ lifecycle: sessionLifecycleSchema,
21840
+ projectId: identifierSchema,
21841
+ sessionId: identifierSchema,
21842
+ tenantId: identifierSchema
21843
+ }).readonly();
21844
+ var sessionBindingSchema = external_exports.strictObject({
21845
+ agentRef: identifierSchema,
21846
+ bindingId: identifierSchema,
21847
+ configRevision: external_exports.number().int().nonnegative().safe(),
21848
+ createdAt: timestampSchema,
21849
+ runtimeId: identifierSchema,
21850
+ sessionId: identifierSchema,
21851
+ workspaceRef: identifierSchema
21852
+ }).readonly();
21853
+ var domainErrorSchema = external_exports.strictObject({
21854
+ code: identifierSchema,
21855
+ message: external_exports.string().min(1).max(2e3),
21856
+ retryable: external_exports.boolean()
21857
+ }).readonly();
21858
+ var executionResultSchema = external_exports.strictObject({
21859
+ kind: external_exports.literal("agent_result"),
21860
+ stopReason: external_exports.string().min(1).max(128)
21861
+ }).readonly();
21862
+ var reconciliationSchema = external_exports.strictObject({
21863
+ detectedAt: timestampSchema,
21864
+ reason: external_exports.enum([
21865
+ "connection_lost",
21866
+ "dispatch_indeterminate",
21867
+ "runtime_restarted"
21868
+ ])
21869
+ }).readonly();
21870
+ var turnStateSchema = external_exports.discriminatedUnion("kind", [
21871
+ external_exports.strictObject({ kind: external_exports.literal("queued") }).readonly(),
21872
+ external_exports.strictObject({ kind: external_exports.literal("running"), startedAt: timestampSchema }).readonly(),
21873
+ external_exports.strictObject({
21874
+ completedAt: timestampSchema,
21875
+ kind: external_exports.literal("succeeded"),
21876
+ result: executionResultSchema
21877
+ }).readonly(),
21878
+ external_exports.strictObject({
21879
+ error: domainErrorSchema,
21880
+ failedAt: timestampSchema,
21881
+ kind: external_exports.literal("failed")
21882
+ }).readonly(),
21883
+ external_exports.strictObject({
21884
+ cancelledAt: timestampSchema,
21885
+ kind: external_exports.literal("cancelled")
21886
+ }).readonly(),
21887
+ external_exports.strictObject({
21888
+ kind: external_exports.literal("indeterminate"),
21889
+ reconciliation: reconciliationSchema
21890
+ }).readonly()
21891
+ ]);
21892
+ var turnRequestSchema = external_exports.discriminatedUnion("kind", [
21893
+ external_exports.strictObject({
21894
+ content: external_exports.string().max(1e5),
21895
+ kind: external_exports.literal("prompt")
21896
+ }).readonly()
21897
+ ]);
21898
+ var turnSchema = external_exports.strictObject({
21899
+ acceptedAt: timestampSchema,
21900
+ bindingId: identifierSchema,
21901
+ idempotencyKey: identifierSchema,
21902
+ request: turnRequestSchema,
21903
+ sessionId: identifierSchema,
21904
+ state: turnStateSchema,
21905
+ turnId: identifierSchema
21906
+ }).readonly();
21907
+ var attemptStateSchema = external_exports.discriminatedUnion("kind", [
21908
+ external_exports.strictObject({
21909
+ dispatchedAt: timestampSchema,
21910
+ kind: external_exports.literal("dispatching")
21911
+ }).readonly(),
21912
+ external_exports.strictObject({ kind: external_exports.literal("running"), startedAt: timestampSchema }).readonly(),
21913
+ external_exports.strictObject({
21914
+ interactionIds: external_exports.array(identifierSchema).min(1).max(100).readonly(),
21915
+ kind: external_exports.literal("waiting_input"),
21916
+ startedAt: timestampSchema
21917
+ }).readonly(),
21918
+ external_exports.strictObject({
21919
+ completedAt: timestampSchema,
21920
+ kind: external_exports.literal("succeeded"),
21921
+ result: executionResultSchema,
21922
+ startedAt: timestampSchema
21923
+ }).readonly(),
21924
+ external_exports.strictObject({
21925
+ error: domainErrorSchema,
21926
+ failedAt: timestampSchema,
21927
+ kind: external_exports.literal("failed"),
21928
+ startedAt: timestampSchema
21929
+ }).readonly(),
21930
+ external_exports.strictObject({
21931
+ cancelledAt: timestampSchema,
21932
+ kind: external_exports.literal("cancelled"),
21933
+ startedAt: timestampSchema
21934
+ }).readonly(),
21935
+ external_exports.strictObject({
21936
+ kind: external_exports.literal("indeterminate"),
21937
+ reconciliation: reconciliationSchema,
21938
+ startedAt: timestampSchema
21939
+ }).readonly()
21940
+ ]);
21941
+ var attemptSchema = external_exports.strictObject({
21942
+ attemptId: identifierSchema,
21943
+ bindingId: identifierSchema,
21944
+ sessionId: identifierSchema,
21945
+ state: attemptStateSchema,
21946
+ turnId: identifierSchema
21947
+ }).readonly();
21948
+ var permissionRequestSchema = external_exports.strictObject({
21949
+ kind: external_exports.literal("permission"),
21950
+ options: external_exports.array(permissionOptionSchema).min(1).max(20).readonly(),
21951
+ title: external_exports.string().min(1).max(500),
21952
+ toolCallId: external_exports.string().min(1).max(255),
21953
+ toolKind: external_exports.string().max(64)
21954
+ }).readonly();
21955
+ var elicitationRequestSchema = external_exports.strictObject({
21956
+ elicitationId: external_exports.string().max(255),
21957
+ fields: external_exports.array(elicitationFieldSchema).max(100).readonly(),
21958
+ kind: external_exports.literal("elicitation"),
21959
+ message: external_exports.string().min(1).max(2e3),
21960
+ mode: external_exports.enum(["form", "url"]),
21961
+ url: external_exports.string().max(4096)
21962
+ }).readonly();
21963
+ var interactionRequestSchema = external_exports.discriminatedUnion("kind", [
21964
+ permissionRequestSchema,
21965
+ elicitationRequestSchema
21966
+ ]);
21967
+ var interactionResponseSchema = external_exports.strictObject({
21968
+ content: external_exports.string().max(1e5),
21969
+ kind: external_exports.enum(["permission", "elicitation"])
21970
+ }).readonly();
21971
+ var interactionStateSchema = external_exports.discriminatedUnion("kind", [
21972
+ external_exports.strictObject({ kind: external_exports.literal("pending") }).readonly(),
21973
+ external_exports.strictObject({
21974
+ kind: external_exports.literal("responded"),
21975
+ respondedAt: timestampSchema,
21976
+ responderId: identifierSchema,
21977
+ response: interactionResponseSchema
21978
+ }).readonly(),
21979
+ external_exports.strictObject({
21980
+ kind: external_exports.literal("resolved"),
21981
+ resolution: external_exports.discriminatedUnion("kind", [
21982
+ external_exports.strictObject({ kind: external_exports.literal("without_response") }).readonly(),
21983
+ external_exports.strictObject({
21984
+ kind: external_exports.literal("response_applied"),
21985
+ respondedAt: timestampSchema,
21986
+ responderId: identifierSchema,
21987
+ response: interactionResponseSchema
21988
+ }).readonly()
21989
+ ]),
21990
+ resolvedAt: timestampSchema
21991
+ }).readonly(),
21992
+ external_exports.strictObject({ expiredAt: timestampSchema, kind: external_exports.literal("expired") }).readonly(),
21993
+ external_exports.strictObject({
21994
+ cancelledAt: timestampSchema,
21995
+ kind: external_exports.literal("cancelled")
21996
+ }).readonly()
21997
+ ]);
21998
+ var interactionSchema = external_exports.strictObject({
21999
+ attemptId: identifierSchema,
22000
+ interactionId: identifierSchema,
22001
+ request: interactionRequestSchema,
22002
+ sessionId: identifierSchema,
22003
+ state: interactionStateSchema,
22004
+ turnId: identifierSchema
22005
+ }).readonly();
22006
+ var recordingCompletenessSchema = external_exports.discriminatedUnion("kind", [
22007
+ external_exports.strictObject({ kind: external_exports.literal("complete") }).readonly(),
22008
+ external_exports.strictObject({
22009
+ capturedBytes: external_exports.number().int().nonnegative().safe(),
22010
+ kind: external_exports.literal("truncated"),
22011
+ originalBytes: external_exports.number().int().positive().safe()
22012
+ }).readonly(),
22013
+ external_exports.strictObject({ kind: external_exports.literal("redacted"), reason: identifierSchema }).readonly(),
22014
+ external_exports.strictObject({ kind: external_exports.literal("uncaptured") }).readonly()
22015
+ ]);
22016
+ var messageViewStateSchema = external_exports.discriminatedUnion("kind", [
22017
+ external_exports.strictObject({ kind: external_exports.literal("building") }).readonly(),
22018
+ external_exports.strictObject({
22019
+ completeness: recordingCompletenessSchema,
22020
+ kind: external_exports.literal("available")
22021
+ }).readonly(),
22022
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
22023
+ ]);
22024
+ var messageViewCommon = {
22025
+ contentArtifactIds: external_exports.array(identifierSchema).max(100).readonly(),
22026
+ lastAppliedSeq: decimalSequenceSchema,
22027
+ messageId: identifierSchema,
22028
+ preview: external_exports.string().max(4e3),
22029
+ sessionId: identifierSchema,
22030
+ state: messageViewStateSchema
22031
+ };
22032
+ var messageViewSchema = external_exports.discriminatedUnion("role", [
22033
+ external_exports.strictObject({
22034
+ ...messageViewCommon,
22035
+ role: external_exports.literal("user"),
22036
+ source: external_exports.strictObject({ kind: external_exports.literal("turn"), turnId: identifierSchema }).readonly()
22037
+ }).readonly(),
22038
+ external_exports.strictObject({
22039
+ ...messageViewCommon,
22040
+ role: external_exports.literal("agent"),
22041
+ source: external_exports.strictObject({
22042
+ attemptId: identifierSchema,
22043
+ kind: external_exports.literal("attempt"),
22044
+ turnId: identifierSchema
22045
+ }).readonly()
22046
+ }).readonly(),
22047
+ external_exports.strictObject({
22048
+ ...messageViewCommon,
22049
+ role: external_exports.literal("tool"),
22050
+ source: external_exports.strictObject({
22051
+ attemptId: identifierSchema,
22052
+ kind: external_exports.literal("tool_call"),
22053
+ toolCallId: identifierSchema,
22054
+ turnId: identifierSchema
22055
+ }).readonly()
22056
+ }).readonly(),
22057
+ external_exports.strictObject({
22058
+ ...messageViewCommon,
22059
+ role: external_exports.literal("system"),
22060
+ source: external_exports.strictObject({ kind: external_exports.literal("system") }).readonly()
22061
+ }).readonly()
22062
+ ]);
22063
+ var toolCallDetailSchema = external_exports.discriminatedUnion("kind", [
22064
+ external_exports.strictObject({
22065
+ artifactId: identifierSchema,
22066
+ kind: external_exports.literal("available")
22067
+ }).readonly(),
22068
+ external_exports.strictObject({
22069
+ capturedBytes: external_exports.number().int().nonnegative().safe(),
22070
+ kind: external_exports.literal("truncated"),
22071
+ originalBytes: external_exports.number().int().positive().safe()
22072
+ }).readonly(),
22073
+ external_exports.strictObject({ kind: external_exports.literal("uncaptured") }).readonly(),
22074
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
22075
+ ]);
22076
+ var toolCallViewStateSchema = external_exports.discriminatedUnion("kind", [
22077
+ external_exports.strictObject({ kind: external_exports.literal("pending") }).readonly(),
22078
+ external_exports.strictObject({ kind: external_exports.literal("running"), startedAt: timestampSchema }).readonly(),
22079
+ external_exports.strictObject({
22080
+ completedAt: timestampSchema,
22081
+ kind: external_exports.literal("succeeded")
22082
+ }).readonly(),
22083
+ external_exports.strictObject({
22084
+ error: domainErrorSchema,
22085
+ failedAt: timestampSchema,
22086
+ kind: external_exports.literal("failed")
22087
+ }).readonly(),
22088
+ external_exports.strictObject({
22089
+ cancelledAt: timestampSchema,
22090
+ kind: external_exports.literal("cancelled")
22091
+ }).readonly()
22092
+ ]);
22093
+ var toolCallViewSchema = external_exports.strictObject({
22094
+ attemptId: identifierSchema,
22095
+ detail: toolCallDetailSchema,
22096
+ inputPreview: external_exports.string().max(4e3),
22097
+ lastAppliedSeq: decimalSequenceSchema,
22098
+ name: external_exports.string().max(128),
22099
+ outputPreview: external_exports.string().max(4e3),
22100
+ state: toolCallViewStateSchema,
22101
+ title: external_exports.string().min(1).max(500),
22102
+ toolCallId: identifierSchema,
22103
+ toolKind: identifierSchema
22104
+ }).readonly();
22105
+ var sessionListEntrySchema = external_exports.strictObject({
22106
+ lastAppliedSeq: decimalSequenceSchema,
22107
+ preview: external_exports.string().max(4e3),
22108
+ projectId: identifierSchema,
22109
+ projectedAttemptState: external_exports.enum([
22110
+ "idle",
22111
+ "dispatching",
22112
+ "running",
22113
+ "waiting_input",
22114
+ "indeterminate"
22115
+ ]),
22116
+ sessionId: identifierSchema,
22117
+ tenantId: identifierSchema,
22118
+ title: external_exports.string().max(500),
22119
+ updatedAt: timestampSchema
22120
+ }).readonly();
22121
+ var artifactStateSchema = external_exports.discriminatedUnion("kind", [
22122
+ external_exports.strictObject({
22123
+ expectedBytes: external_exports.number().int().nonnegative().safe(),
22124
+ expiresAt: timestampSchema,
22125
+ kind: external_exports.literal("uploading"),
22126
+ uploadId: identifierSchema
22127
+ }).readonly(),
22128
+ external_exports.strictObject({
22129
+ availableAt: timestampSchema,
22130
+ byteLength: external_exports.number().int().nonnegative().safe(),
22131
+ kind: external_exports.literal("available"),
22132
+ sha256: digestSchema
22133
+ }).readonly(),
22134
+ external_exports.strictObject({ kind: external_exports.literal("deleting"), requestedAt: timestampSchema }).readonly(),
22135
+ external_exports.strictObject({ completedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly(),
22136
+ external_exports.strictObject({
22137
+ error: domainErrorSchema,
22138
+ failedAt: timestampSchema,
22139
+ kind: external_exports.literal("failed")
22140
+ }).readonly(),
22141
+ external_exports.strictObject({ expiredAt: timestampSchema, kind: external_exports.literal("expired") }).readonly()
22142
+ ]);
22143
+ var artifactSchema = external_exports.strictObject({
22144
+ artifactId: identifierSchema,
22145
+ completeness: recordingCompletenessSchema,
22146
+ contentKind: identifierSchema,
22147
+ mediaType: external_exports.string().min(1).max(128),
22148
+ projectId: identifierSchema,
22149
+ provenance: external_exports.discriminatedUnion("kind", [
22150
+ external_exports.strictObject({ kind: external_exports.literal("user_upload") }).readonly(),
22151
+ external_exports.strictObject({
22152
+ attemptId: identifierSchema,
22153
+ kind: external_exports.literal("tool_call"),
22154
+ toolCallId: identifierSchema,
22155
+ turnId: identifierSchema
22156
+ }).readonly(),
22157
+ external_exports.strictObject({
22158
+ attemptId: identifierSchema,
22159
+ kind: external_exports.literal("agent_generated"),
22160
+ turnId: identifierSchema
22161
+ }).readonly()
22162
+ ]),
22163
+ sessionId: identifierSchema,
22164
+ state: artifactStateSchema,
22165
+ tenantId: identifierSchema
22166
+ }).readonly();
22167
+ var archiveSegmentStateSchema = external_exports.discriminatedUnion("kind", [
22168
+ external_exports.strictObject({ kind: external_exports.literal("pending"), queuedAt: timestampSchema }).readonly(),
22169
+ external_exports.strictObject({
22170
+ byteLength: external_exports.number().int().nonnegative().safe(),
22171
+ kind: external_exports.literal("uploaded"),
22172
+ sha256: digestSchema,
22173
+ uploadedAt: timestampSchema
22174
+ }).readonly(),
22175
+ external_exports.strictObject({
22176
+ byteLength: external_exports.number().int().nonnegative().safe(),
22177
+ kind: external_exports.literal("published"),
22178
+ publishedAt: timestampSchema,
22179
+ sha256: digestSchema
22180
+ }).readonly(),
22181
+ external_exports.strictObject({ kind: external_exports.literal("deleting"), requestedAt: timestampSchema }).readonly(),
22182
+ external_exports.strictObject({ completedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
22183
+ ]);
22184
+ var archiveSegmentSchema = external_exports.strictObject({
22185
+ compression: external_exports.literal("gzip"),
22186
+ eventCount: external_exports.number().int().positive().safe(),
22187
+ firstSeq: decimalSequenceSchema,
22188
+ lastSeq: decimalSequenceSchema,
22189
+ segmentId: identifierSchema,
22190
+ sessionId: identifierSchema,
22191
+ state: archiveSegmentStateSchema
22192
+ }).readonly();
22193
+ var pendingWorkStateSchema = external_exports.discriminatedUnion("kind", [
22194
+ external_exports.strictObject({ kind: external_exports.literal("pending"), queuedAt: timestampSchema }).readonly(),
22195
+ external_exports.strictObject({
22196
+ attempt: external_exports.number().int().positive().safe(),
22197
+ kind: external_exports.literal("running"),
22198
+ startedAt: timestampSchema
22199
+ }).readonly(),
22200
+ external_exports.strictObject({
22201
+ completedAt: timestampSchema,
22202
+ kind: external_exports.literal("completed")
22203
+ }).readonly(),
22204
+ external_exports.strictObject({
22205
+ error: domainErrorSchema,
22206
+ kind: external_exports.literal("retryable"),
22207
+ nextAttemptAt: timestampSchema
22208
+ }).readonly(),
22209
+ external_exports.strictObject({
22210
+ error: domainErrorSchema,
22211
+ failedAt: timestampSchema,
22212
+ kind: external_exports.literal("failed")
22213
+ }).readonly()
22214
+ ]);
22215
+ var pendingWorkSchema = external_exports.strictObject({
22216
+ kind: external_exports.enum([
22217
+ "archive",
22218
+ "delete",
22219
+ "dispatch",
22220
+ "interaction_response",
22221
+ "projection"
22222
+ ]),
22223
+ projectId: identifierSchema,
22224
+ sessionId: identifierSchema,
22225
+ state: pendingWorkStateSchema,
22226
+ tenantId: identifierSchema,
22227
+ workId: identifierSchema
22228
+ }).readonly();
22229
+ var commandReceiptSchema = external_exports.strictObject({
22230
+ acceptedAt: timestampSchema,
22231
+ commandKind: identifierSchema,
22232
+ expiresAt: timestampSchema,
22233
+ idempotencyKey: identifierSchema,
22234
+ projectId: identifierSchema,
22235
+ requestHash: digestSchema,
22236
+ resultId: identifierSchema,
22237
+ sessionId: identifierSchema,
22238
+ tenantId: identifierSchema
22239
+ }).readonly();
22240
+
22241
+ // ../protocol/src/session-events.ts
22242
+ var SESSION_EVENT_KIND = "session.event";
22243
+ var SESSION_EVENT_ACK_KIND = "session.event.ack";
22244
+ var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
22245
+ var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
22246
+ var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
22247
+ var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
22248
+ var DECIMAL_SEQUENCE_PATTERN2 = /^(?:0|[1-9][0-9]*)$/;
22249
+ var eventSourceSchema = external_exports.discriminatedUnion("kind", [
22250
+ external_exports.strictObject({
22251
+ attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
22252
+ kind: external_exports.literal("attempt"),
22253
+ sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2)
22254
+ }).readonly(),
22255
+ external_exports.strictObject({
22256
+ kind: external_exports.literal("runtime"),
22257
+ sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2)
22258
+ }).readonly()
22259
+ ]);
22260
+ var eventEnvelopeSchema = external_exports.strictObject({
22261
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
22262
+ kind: external_exports.literal(SESSION_EVENT_KIND),
22263
+ payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
22264
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
22265
+ source: eventSourceSchema
22266
+ }).readonly();
22267
+ var committedEventSchema = external_exports.strictObject({
22268
+ cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
22269
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
22270
+ kind: external_exports.literal(SESSION_EVENT_COMMITTED_KIND),
22271
+ payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
22272
+ recordedAt: external_exports.string().datetime({ offset: true }),
22273
+ sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2),
22274
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
22275
+ source: eventSourceSchema
22276
+ }).readonly();
22277
+ var eventAcknowledgementSchema = external_exports.strictObject({
22278
+ cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
22279
+ duplicate: external_exports.boolean(),
22280
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5),
22281
+ kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
22282
+ sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2),
22283
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN5)
22284
+ }).readonly();
22285
+ function decode5(encoded, schema) {
22286
+ let value;
22287
+ try {
22288
+ value = JSON.parse(encoded);
22289
+ } catch (cause) {
22290
+ throw new ProtocolMessageError("Message is not valid JSON", { cause });
22291
+ }
22292
+ const decoded = schema.safeParse(value);
22293
+ if (!decoded.success) {
22294
+ throw new ProtocolMessageError("Message does not match its schema", {
22295
+ cause: decoded.error
22296
+ });
22297
+ }
22298
+ return decoded.data;
22299
+ }
22300
+ var encode4 = (message, schema) => {
22301
+ const decoded = schema.safeParse(message);
22302
+ if (!decoded.success) {
22303
+ throw new ProtocolMessageError("Message does not match its schema", {
22304
+ cause: decoded.error
22305
+ });
22306
+ }
22307
+ return JSON.stringify(decoded.data);
22308
+ };
22309
+ var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
22310
+ var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
22311
+
21757
22312
  // src/run-daemon.ts
21758
22313
  import { WebSocket as WebSocket2 } from "undici";
21759
22314
 
@@ -21762,7 +22317,7 @@ import { spawn as spawn3 } from "node:child_process";
21762
22317
  import {
21763
22318
  methods as methods3,
21764
22319
  ndJsonStream as ndJsonStream2,
21765
- PROTOCOL_VERSION as PROTOCOL_VERSION3
22320
+ PROTOCOL_VERSION as PROTOCOL_VERSION2
21766
22321
  } from "@agentclientprotocol/sdk";
21767
22322
 
21768
22323
  // src/acp/activity.ts
@@ -21782,7 +22337,12 @@ var AcpActivity = class _AcpActivity {
21782
22337
  title;
21783
22338
  toolKind;
21784
22339
  content;
21785
- constructor(activityId, activityType, input2, locations, name, output2, sequence, status, title, toolKind, content = []) {
22340
+ detail;
22341
+ constructor(activityId, activityType, input2, locations, name, output2, sequence, status, title2, toolKind, content = [], detail = captureActivityDetail(
22342
+ content,
22343
+ input2,
22344
+ output2
22345
+ )) {
21786
22346
  this.activityId = activityId;
21787
22347
  this.activityType = activityType;
21788
22348
  this.input = input2;
@@ -21791,9 +22351,10 @@ var AcpActivity = class _AcpActivity {
21791
22351
  this.output = output2;
21792
22352
  this.sequence = sequence;
21793
22353
  this.status = status;
21794
- this.title = title;
22354
+ this.title = title2;
21795
22355
  this.toolKind = toolKind;
21796
22356
  this.content = content;
22357
+ this.detail = detail;
21797
22358
  }
21798
22359
  complete = () => (this.activityType === "progress" || this.activityType === "reasoning") && (this.status === "pending" || this.status === "running") ? new _AcpActivity(
21799
22360
  this.activityId,
@@ -21806,7 +22367,8 @@ var AcpActivity = class _AcpActivity {
21806
22367
  "completed",
21807
22368
  this.title,
21808
22369
  this.toolKind,
21809
- this.content
22370
+ this.content,
22371
+ this.detail
21810
22372
  ) : this;
21811
22373
  };
21812
22374
  var ActivityIdentity = class {
@@ -21834,12 +22396,67 @@ function formatUnknown(value) {
21834
22396
  return truncate(String(value), AGENT_ACTIVITY_DETAIL_LIMIT);
21835
22397
  }
21836
22398
  }
22399
+ function formatUnknownDetail(value) {
22400
+ if (typeof value === "string") {
22401
+ return value;
22402
+ }
22403
+ try {
22404
+ return JSON.stringify(value, null, 2) ?? "";
22405
+ } catch {
22406
+ return String(value);
22407
+ }
22408
+ }
21837
22409
  function readContentOutput(content) {
21838
22410
  if (!Array.isArray(content) || content.length === 0) {
21839
22411
  return "";
21840
22412
  }
21841
22413
  return formatUnknown(content);
21842
22414
  }
22415
+ function readContentOutputDetail(content) {
22416
+ if (!Array.isArray(content) || content.length === 0) {
22417
+ return "";
22418
+ }
22419
+ return formatUnknownDetail(content);
22420
+ }
22421
+ function summarizeDisplayContent(content) {
22422
+ return {
22423
+ ...content,
22424
+ data: truncate(content.data, AGENT_ACTIVITY_DETAIL_LIMIT),
22425
+ mimeType: truncate(content.mimeType, 255),
22426
+ name: truncate(content.name, 500),
22427
+ newText: truncate(content.newText, AGENT_ACTIVITY_DETAIL_LIMIT),
22428
+ oldText: truncate(content.oldText, AGENT_ACTIVITY_DETAIL_LIMIT),
22429
+ path: truncate(content.path, 2048),
22430
+ terminalId: truncate(content.terminalId, 255),
22431
+ text: truncate(content.text, AGENT_ACTIVITY_DETAIL_LIMIT),
22432
+ uri: truncate(content.uri, 4096)
22433
+ };
22434
+ }
22435
+ function contentFitsRecordingEnvelope(content) {
22436
+ return content.data.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.mimeType.length <= 255 && content.name.length <= 500 && content.newText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.oldText.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.path.length <= 2048 && content.terminalId.length <= 255 && content.text.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && content.uri.length <= 4096;
22437
+ }
22438
+ function encodedByteLength(value) {
22439
+ return new TextEncoder().encode(JSON.stringify(value)).byteLength;
22440
+ }
22441
+ function captureActivityDetail(content, input2, output2) {
22442
+ const recorded = { content, input: input2, kind: "recorded", output: output2 };
22443
+ const originalBytes = encodedByteLength(recorded);
22444
+ if (content.length <= 100 && content.every(contentFitsRecordingEnvelope) && input2.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && output2.length <= AGENT_ACTIVITY_RECORDED_FIELD_LIMIT && JSON.stringify(recorded).length <= AGENT_ACTIVITY_RECORDED_DETAIL_LIMIT) {
22445
+ return recorded;
22446
+ }
22447
+ return {
22448
+ capturedBytes: encodedByteLength({
22449
+ content: content.slice(0, 100).map(summarizeDisplayContent),
22450
+ input: truncate(input2, AGENT_ACTIVITY_DETAIL_LIMIT),
22451
+ output: truncate(output2, AGENT_ACTIVITY_DETAIL_LIMIT)
22452
+ }),
22453
+ kind: "truncated",
22454
+ originalBytes
22455
+ };
22456
+ }
22457
+ function recordedDetail(activity) {
22458
+ return activity?.detail.kind === "recorded" ? activity.detail : null;
22459
+ }
21843
22460
  function emptyDisplayContent(type) {
21844
22461
  return {
21845
22462
  data: "",
@@ -21950,8 +22567,8 @@ function normalizeToolStatus(status, fallback) {
21950
22567
  }
21951
22568
  return fallback;
21952
22569
  }
21953
- function normalizeTitle(title, fallback) {
21954
- const normalized = title.trim();
22570
+ function normalizeTitle(title2, fallback) {
22571
+ const normalized = title2.trim();
21955
22572
  return truncate(normalized.length === 0 ? fallback : normalized, 500);
21956
22573
  }
21957
22574
  function formatPlanEntries(entries) {
@@ -22004,17 +22621,20 @@ var AcpActivityTracker = class {
22004
22621
  }
22005
22622
  const previous = this.#activities.get(key);
22006
22623
  const identity2 = this.#identity(key);
22624
+ const fullOutput = `${recordedDetail(previous)?.output ?? previous?.output ?? ""}${text}`;
22007
22625
  const activity = new AcpActivity(
22008
22626
  identity2.id,
22009
22627
  activityType,
22010
22628
  "",
22011
22629
  [],
22012
22630
  "",
22013
- truncate(`${previous?.output ?? ""}${text}`, AGENT_ACTIVITY_DETAIL_LIMIT),
22631
+ truncate(fullOutput, AGENT_ACTIVITY_DETAIL_LIMIT),
22014
22632
  identity2.sequence,
22015
22633
  "running",
22016
22634
  activityType === "reasoning" ? "Reasoning" : "Progress update",
22017
- activityType === "reasoning" ? "think" : ""
22635
+ activityType === "reasoning" ? "think" : "",
22636
+ [],
22637
+ captureActivityDetail([], "", fullOutput)
22018
22638
  );
22019
22639
  await this.#record(key, activity);
22020
22640
  this.#activeNarrativeKey = key;
@@ -22067,7 +22687,8 @@ var AcpActivityTracker = class {
22067
22687
  "completed",
22068
22688
  previous.title,
22069
22689
  previous.toolKind,
22070
- previous.content
22690
+ previous.content,
22691
+ previous.detail
22071
22692
  )
22072
22693
  );
22073
22694
  }
@@ -22077,6 +22698,9 @@ var AcpActivityTracker = class {
22077
22698
  const key = `tool:${update.toolCallId}`;
22078
22699
  const identity2 = this.#identity(key);
22079
22700
  const output2 = update.rawOutput === void 0 ? readContentOutput(update.content) : formatUnknown(update.rawOutput);
22701
+ const detailInput = update.rawInput === void 0 ? "" : formatUnknownDetail(update.rawInput);
22702
+ const detailOutput = update.rawOutput === void 0 ? readContentOutputDetail(update.content) : formatUnknownDetail(update.rawOutput);
22703
+ const detailContent = normalizeToolContent(update.content ?? []);
22080
22704
  await this.#record(
22081
22705
  key,
22082
22706
  new AcpActivity(
@@ -22090,7 +22714,8 @@ var AcpActivityTracker = class {
22090
22714
  normalizeToolStatus(update.status ?? "pending", "pending"),
22091
22715
  normalizeTitle(update.title, "Tool call"),
22092
22716
  update.kind ?? "other",
22093
- normalizeToolContent(update.content ?? [])
22717
+ detailContent.slice(0, 100).map(summarizeDisplayContent),
22718
+ captureActivityDetail(detailContent, detailInput, detailOutput)
22094
22719
  )
22095
22720
  );
22096
22721
  };
@@ -22099,8 +22724,12 @@ var AcpActivityTracker = class {
22099
22724
  const key = `tool:${update.toolCallId}`;
22100
22725
  const previous = this.#activities.get(key);
22101
22726
  const identity2 = this.#identity(key);
22727
+ const previousDetail = recordedDetail(previous);
22102
22728
  const output2 = update.rawOutput !== void 0 ? formatUnknown(update.rawOutput) : update.content !== void 0 && update.content !== null ? readContentOutput(update.content) : previous?.output ?? "";
22103
22729
  const content = update.content === void 0 || update.content === null ? previous?.content ?? [] : normalizeToolContent(update.content);
22730
+ const detailInput = update.rawInput === void 0 ? previousDetail?.input ?? previous?.input ?? "" : formatUnknownDetail(update.rawInput);
22731
+ const detailOutput = update.rawOutput !== void 0 ? formatUnknownDetail(update.rawOutput) : update.content !== void 0 && update.content !== null ? readContentOutputDetail(update.content) : previousDetail?.output ?? previous?.output ?? "";
22732
+ const detailContent = update.content === void 0 || update.content === null ? previousDetail?.content ?? previous?.content ?? [] : normalizeToolContent(update.content);
22104
22733
  await this.#record(
22105
22734
  key,
22106
22735
  new AcpActivity(
@@ -22114,7 +22743,8 @@ var AcpActivityTracker = class {
22114
22743
  update.status === void 0 || update.status === null ? previous?.status ?? "pending" : normalizeToolStatus(update.status, previous?.status ?? "pending"),
22115
22744
  update.title === void 0 || update.title === null ? previous?.title ?? "Tool call" : normalizeTitle(update.title, "Tool call"),
22116
22745
  update.kind === void 0 || update.kind === null ? previous?.toolKind ?? "other" : update.kind,
22117
- content
22746
+ content.slice(0, 100).map(summarizeDisplayContent),
22747
+ captureActivityDetail(detailContent, detailInput, detailOutput)
22118
22748
  )
22119
22749
  );
22120
22750
  };
@@ -22184,12 +22814,13 @@ var AcpActivityTracker = class {
22184
22814
 
22185
22815
  // src/acp/native-session.ts
22186
22816
  var path = external_exports.string().min(1).max(2048).refine((value) => !value.includes("\0"));
22817
+ var title = external_exports.string().transform((value) => value.slice(0, 500));
22187
22818
  var nativeSessionIdSchema = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,255}$/);
22188
22819
  var nativeSessionInfoSchema = external_exports.object({
22189
22820
  sessionId: nativeSessionIdSchema,
22190
22821
  cwd: path,
22191
22822
  additionalDirectories: external_exports.array(path).max(16).default([]).readonly(),
22192
- title: external_exports.string().max(500).nullish(),
22823
+ title: title.nullish(),
22193
22824
  updatedAt: external_exports.iso.datetime({ offset: true }).nullish()
22194
22825
  }).readonly();
22195
22826
  var nativeSessionPageSchema = external_exports.object({
@@ -22512,6 +23143,12 @@ var AcpExecutionError = class extends Error {
22512
23143
  this.name = "AcpExecutionError";
22513
23144
  }
22514
23145
  };
23146
+ var RetryableAcpInitializationError = class extends AcpExecutionError {
23147
+ constructor(cause) {
23148
+ super("ACP agent initialization failed", { cause });
23149
+ this.name = "RetryableAcpInitializationError";
23150
+ }
23151
+ };
22515
23152
  function readableWebStream(input2) {
22516
23153
  let streamOpen = true;
22517
23154
  return new ReadableStream({
@@ -23141,42 +23778,63 @@ var AcpProcessSession = class _AcpProcessSession {
23141
23778
  );
23142
23779
  this.#connection = createAcpClient(this).connect(stream);
23143
23780
  }
23144
- static start = async (options, getObserver, store) => {
23145
- options.signal.throwIfAborted();
23146
- const [adapterUnchanged, agentUnchanged] = await Promise.all([
23147
- revalidateExecutable(options.agent.adapterIdentity),
23148
- revalidateExecutable(options.agent.agentIdentity)
23149
- ]);
23150
- options.signal.throwIfAborted();
23151
- if (!adapterUnchanged || !agentUnchanged) {
23152
- throw new AcpExecutionError(
23153
- "The local Agent runtime changed; restart Mobius before starting a new conversation",
23154
- {},
23155
- "agent_runtime_changed"
23156
- );
23157
- }
23158
- const runtime = new _AcpProcessSession(
23159
- options.agent,
23160
- options.cwd,
23161
- options.additionalDirectories,
23162
- options.sessionId,
23163
- getObserver,
23164
- store
23165
- );
23166
- try {
23167
- await runtime.initialize(options.signal, options.origin);
23168
- return runtime;
23169
- } catch (error61) {
23170
- await runtime.closeProcess();
23781
+ static async #start(options, getObserver, store, initialize) {
23782
+ for (let attempt = 1; attempt <= 2; attempt += 1) {
23171
23783
  options.signal.throwIfAborted();
23172
- if (error61 instanceof AcpExecutionError) {
23173
- throw error61;
23784
+ const [adapterUnchanged, agentUnchanged] = await Promise.all([
23785
+ revalidateExecutable(options.agent.adapterIdentity),
23786
+ revalidateExecutable(options.agent.agentIdentity)
23787
+ ]);
23788
+ options.signal.throwIfAborted();
23789
+ if (!adapterUnchanged || !agentUnchanged) {
23790
+ throw new AcpExecutionError(
23791
+ "The local Agent runtime changed; restart Mobius before starting a new conversation",
23792
+ {},
23793
+ "agent_runtime_changed"
23794
+ );
23795
+ }
23796
+ const runtime = new _AcpProcessSession(
23797
+ options.agent,
23798
+ options.cwd,
23799
+ options.additionalDirectories,
23800
+ options.sessionId,
23801
+ getObserver,
23802
+ store
23803
+ );
23804
+ try {
23805
+ await initialize(runtime);
23806
+ return runtime;
23807
+ } catch (error61) {
23808
+ await runtime.closeProcess();
23809
+ options.signal.throwIfAborted();
23810
+ if (error61 instanceof RetryableAcpInitializationError && attempt === 1) {
23811
+ console.warn(
23812
+ `[${options.agent.id}-acp] ACP agent initialization failed; retrying once`
23813
+ );
23814
+ continue;
23815
+ }
23816
+ if (error61 instanceof AcpExecutionError) {
23817
+ throw error61;
23818
+ }
23819
+ throw new AcpExecutionError("ACP agent initialization failed", {
23820
+ cause: error61
23821
+ });
23174
23822
  }
23175
- throw new AcpExecutionError("ACP agent initialization failed", {
23176
- cause: error61
23177
- });
23178
23823
  }
23179
- };
23824
+ throw new AcpExecutionError("ACP agent initialization failed");
23825
+ }
23826
+ static start = async (options, getObserver, store) => await _AcpProcessSession.#start(
23827
+ options,
23828
+ getObserver,
23829
+ store,
23830
+ async (runtime) => await runtime.initialize(options.signal, options.origin)
23831
+ );
23832
+ static startNativeSessionBrowser = async (options, getObserver, store) => await _AcpProcessSession.#start(
23833
+ options,
23834
+ getObserver,
23835
+ store,
23836
+ async (runtime) => await runtime.#initializeAgent(options.signal)
23837
+ );
23180
23838
  belongsTo = (agentId, cwd, additionalDirectories) => this.#agentId === agentId && this.#cwd === cwd && arraysEqual(this.#additionalDirectories, additionalDirectories);
23181
23839
  canRebind = () => !this.#prompted && !this.#turn.running;
23182
23840
  prepared = () => new AcpPreparedSession(
@@ -23213,7 +23871,7 @@ var AcpProcessSession = class _AcpProcessSession {
23213
23871
  this.#replay = { kind: "idle" };
23214
23872
  }
23215
23873
  };
23216
- initialize = async (signal, origin) => {
23874
+ async #initializeAgent(signal) {
23217
23875
  const initialized = await this.race(
23218
23876
  this.#connection.agent.request(
23219
23877
  methods3.agent.initialize,
@@ -23224,14 +23882,17 @@ var AcpProcessSession = class _AcpProcessSession {
23224
23882
  session: { configOptions: { boolean: {} } }
23225
23883
  },
23226
23884
  clientInfo: { name: "mobius", version: "0.0.3" },
23227
- protocolVersion: PROTOCOL_VERSION3
23885
+ protocolVersion: PROTOCOL_VERSION2
23228
23886
  },
23229
23887
  { cancellationSignal: signal }
23230
23888
  ),
23231
23889
  "ACP agent exited during initialization",
23232
23890
  signal
23233
- );
23234
- if (initialized.protocolVersion !== PROTOCOL_VERSION3) {
23891
+ ).catch((cause) => {
23892
+ signal.throwIfAborted();
23893
+ throw new RetryableAcpInitializationError(cause);
23894
+ });
23895
+ if (initialized.protocolVersion !== PROTOCOL_VERSION2) {
23235
23896
  throw new AcpExecutionError(
23236
23897
  "ACP agent selected an unsupported protocol version",
23237
23898
  {},
@@ -23245,6 +23906,9 @@ var AcpProcessSession = class _AcpProcessSession {
23245
23906
  255
23246
23907
  );
23247
23908
  this.#agentVersion = truncate2(initialized.agentInfo?.version ?? "", 128);
23909
+ }
23910
+ initialize = async (signal, origin) => {
23911
+ await this.#initializeAgent(signal);
23248
23912
  const stored = origin?.kind === "import" ? new FoundAcpStoredSession(
23249
23913
  new AcpStoredSession(
23250
23914
  this.#mobiusSessionId,
@@ -23619,7 +24283,6 @@ var AcpProcessSession = class _AcpProcessSession {
23619
24283
  _meta: result._meta ?? null,
23620
24284
  commandId: options.commandId,
23621
24285
  kind: SESSION_USAGE_UPDATED_KIND,
23622
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23623
24286
  sessionId: this.#mobiusSessionId,
23624
24287
  source: "prompt",
23625
24288
  usage: result.usage ?? null
@@ -23677,7 +24340,6 @@ var AcpProcessSession = class _AcpProcessSession {
23677
24340
  kind: SESSION_PERMISSION_RESOLVED_KIND,
23678
24341
  optionId: options.outcome === "selected" ? options.optionId : "",
23679
24342
  outcome: options.outcome,
23680
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23681
24343
  sessionId: this.#mobiusSessionId
23682
24344
  });
23683
24345
  };
@@ -23722,7 +24384,6 @@ var AcpProcessSession = class _AcpProcessSession {
23722
24384
  action: options.action,
23723
24385
  interactionId: options.interactionId,
23724
24386
  kind: SESSION_ELICITATION_RESOLVED_KIND,
23725
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23726
24387
  sessionId: this.#mobiusSessionId
23727
24388
  });
23728
24389
  };
@@ -23756,7 +24417,6 @@ var AcpProcessSession = class _AcpProcessSession {
23756
24417
  interactionId,
23757
24418
  kind: SESSION_PERMISSION_REQUESTED_KIND,
23758
24419
  options,
23759
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23760
24420
  sessionId: this.#mobiusSessionId,
23761
24421
  title: truncate2(request.toolCall.title ?? "Permission required", 500),
23762
24422
  toolCallId: truncate2(request.toolCall.toolCallId, 255),
@@ -23810,7 +24470,6 @@ var AcpProcessSession = class _AcpProcessSession {
23810
24470
  kind: SESSION_ELICITATION_REQUESTED_KIND,
23811
24471
  message: truncate2(request.message, 2e3),
23812
24472
  mode: request.mode,
23813
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23814
24473
  sessionId: this.#mobiusSessionId,
23815
24474
  url: request.mode === "url" && typeof Reflect.get(request, "url") === "string" ? truncate2(readString3(Reflect.get(request, "url")), 4096) : ""
23816
24475
  });
@@ -23832,7 +24491,6 @@ var AcpProcessSession = class _AcpProcessSession {
23832
24491
  action: "complete",
23833
24492
  interactionId,
23834
24493
  kind: SESSION_ELICITATION_RESOLVED_KIND,
23835
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23836
24494
  sessionId: this.#mobiusSessionId
23837
24495
  });
23838
24496
  };
@@ -23869,7 +24527,6 @@ var AcpProcessSession = class _AcpProcessSession {
23869
24527
  contentId: `content-${crypto.randomUUID()}`,
23870
24528
  kind: AGENT_CONTENT_KIND,
23871
24529
  messageId: truncate2(update.messageId ?? "", 255),
23872
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23873
24530
  sessionId: this.#mobiusSessionId
23874
24531
  });
23875
24532
  }
@@ -23915,7 +24572,6 @@ var AcpProcessSession = class _AcpProcessSession {
23915
24572
  await this.#getObserver().onCommands({
23916
24573
  commands,
23917
24574
  kind: SESSION_COMMANDS_UPDATED_KIND,
23918
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23919
24575
  sessionId: this.#mobiusSessionId
23920
24576
  });
23921
24577
  return;
@@ -23944,7 +24600,6 @@ var AcpProcessSession = class _AcpProcessSession {
23944
24600
  }
23945
24601
  await this.#getObserver().onInfo({
23946
24602
  kind: SESSION_INFO_UPDATED_KIND,
23947
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23948
24603
  sessionId: this.#mobiusSessionId,
23949
24604
  title: this.#sessionTitle,
23950
24605
  updatedAt: this.#sessionUpdatedAt
@@ -23957,7 +24612,6 @@ var AcpProcessSession = class _AcpProcessSession {
23957
24612
  costCurrency: truncate2(update.cost?.currency ?? "", 16),
23958
24613
  hasCost: update.cost !== void 0 && update.cost !== null,
23959
24614
  kind: SESSION_USAGE_UPDATED_KIND,
23960
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
23961
24615
  sessionId: this.#mobiusSessionId,
23962
24616
  size: Math.max(0, Math.trunc(update.size)),
23963
24617
  source: "context",
@@ -24025,7 +24679,6 @@ var AcpProcessSession = class _AcpProcessSession {
24025
24679
  await this.#getObserver().onConfig({
24026
24680
  configOptions: this.#configOptions,
24027
24681
  kind: SESSION_CONFIG_UPDATED_KIND,
24028
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
24029
24682
  requestId: `agent-update-${crypto.randomUUID()}`,
24030
24683
  sessionId: this.#mobiusSessionId
24031
24684
  });
@@ -24041,7 +24694,6 @@ var AcpProcessSession = class _AcpProcessSession {
24041
24694
  kind: SESSION_PERMISSION_RESOLVED_KIND,
24042
24695
  optionId: "",
24043
24696
  outcome: "cancelled",
24044
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
24045
24697
  sessionId: this.#mobiusSessionId
24046
24698
  });
24047
24699
  };
@@ -24055,7 +24707,6 @@ var AcpProcessSession = class _AcpProcessSession {
24055
24707
  action: "cancel",
24056
24708
  interactionId,
24057
24709
  kind: SESSION_ELICITATION_RESOLVED_KIND,
24058
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
24059
24710
  sessionId: this.#mobiusSessionId
24060
24711
  });
24061
24712
  };
@@ -24075,7 +24726,6 @@ var AcpProcessSession = class _AcpProcessSession {
24075
24726
  action: "cancel",
24076
24727
  interactionId,
24077
24728
  kind: SESSION_ELICITATION_RESOLVED_KIND,
24078
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
24079
24729
  sessionId: this.#mobiusSessionId
24080
24730
  });
24081
24731
  }
@@ -24083,6 +24733,10 @@ var AcpProcessSession = class _AcpProcessSession {
24083
24733
  };
24084
24734
  var AcpSessionManager = class {
24085
24735
  #nativeOperations = /* @__PURE__ */ new Set();
24736
+ #nativeBrowserObserver = new NullAcpSessionObserver();
24737
+ #nativeBrowserPreparing = /* @__PURE__ */ new Map();
24738
+ #nativeBrowserSessions = /* @__PURE__ */ new Map();
24739
+ #nativeBrowserStore = new MemoryAcpSessionStore();
24086
24740
  #activeSessionIds = /* @__PURE__ */ new Set();
24087
24741
  #cancellationRequests = /* @__PURE__ */ new Set();
24088
24742
  #preparing = /* @__PURE__ */ new Map();
@@ -24096,6 +24750,43 @@ var AcpSessionManager = class {
24096
24750
  setObserver = (observer) => {
24097
24751
  this.#observer = observer;
24098
24752
  };
24753
+ async #startNativeBrowserPreparation(options) {
24754
+ const operation = (async () => {
24755
+ try {
24756
+ const runtime = await AcpProcessSession.startNativeSessionBrowser(
24757
+ options,
24758
+ () => this.#nativeBrowserObserver,
24759
+ this.#nativeBrowserStore
24760
+ );
24761
+ this.#nativeBrowserSessions.set(options.sessionId, runtime);
24762
+ return runtime;
24763
+ } finally {
24764
+ this.#nativeBrowserPreparing.delete(options.sessionId);
24765
+ }
24766
+ })();
24767
+ this.#nativeBrowserPreparing.set(options.sessionId, operation);
24768
+ return await operation;
24769
+ }
24770
+ async #replaceNativeBrowserPreparation(existing, options) {
24771
+ const operation = (async () => {
24772
+ try {
24773
+ this.#nativeBrowserSessions.delete(options.sessionId);
24774
+ await existing.close();
24775
+ this.#nativeBrowserStore.remove(options.sessionId);
24776
+ const runtime = await AcpProcessSession.startNativeSessionBrowser(
24777
+ options,
24778
+ () => this.#nativeBrowserObserver,
24779
+ this.#nativeBrowserStore
24780
+ );
24781
+ this.#nativeBrowserSessions.set(options.sessionId, runtime);
24782
+ return runtime;
24783
+ } finally {
24784
+ this.#nativeBrowserPreparing.delete(options.sessionId);
24785
+ }
24786
+ })();
24787
+ this.#nativeBrowserPreparing.set(options.sessionId, operation);
24788
+ return await operation;
24789
+ }
24099
24790
  async #startPreparation(options) {
24100
24791
  const operation = (async () => {
24101
24792
  try {
@@ -24183,6 +24874,44 @@ var AcpSessionManager = class {
24183
24874
  const runtime = await this.#startPreparation(options);
24184
24875
  return runtime.prepared();
24185
24876
  };
24877
+ prepareNativeSessionBrowser = async (options) => {
24878
+ const pending = this.#nativeBrowserPreparing.get(options.sessionId);
24879
+ if (pending !== void 0) {
24880
+ const runtime2 = await pending;
24881
+ if (runtime2.belongsTo(
24882
+ options.agent.id,
24883
+ options.cwd,
24884
+ options.additionalDirectories
24885
+ )) {
24886
+ return runtime2.prepared();
24887
+ }
24888
+ return await this.prepareNativeSessionBrowser(options);
24889
+ }
24890
+ const existing = this.#nativeBrowserSessions.get(options.sessionId);
24891
+ if (existing !== void 0) {
24892
+ if (existing.belongsTo(
24893
+ options.agent.id,
24894
+ options.cwd,
24895
+ options.additionalDirectories
24896
+ )) {
24897
+ return existing.prepared();
24898
+ }
24899
+ if (!existing.canRebind()) {
24900
+ throw new AcpExecutionError(
24901
+ "The agent or workspace cannot change after a conversation has started",
24902
+ {},
24903
+ "session_identity_mismatch"
24904
+ );
24905
+ }
24906
+ const runtime2 = await this.#replaceNativeBrowserPreparation(
24907
+ existing,
24908
+ options
24909
+ );
24910
+ return runtime2.prepared();
24911
+ }
24912
+ const runtime = await this.#startNativeBrowserPreparation(options);
24913
+ return runtime.prepared();
24914
+ };
24186
24915
  configureSession = async (options) => {
24187
24916
  const runtime = await this.ensureSession(options);
24188
24917
  return await runtime.configure(options);
@@ -24271,8 +25000,14 @@ var AcpSessionManager = class {
24271
25000
  };
24272
25001
  close = async () => {
24273
25002
  const sessions = [...this.#sessions.values()];
25003
+ const nativeBrowserSessions = [...this.#nativeBrowserSessions.values()];
24274
25004
  this.#sessions.clear();
24275
- await Promise.all(sessions.map(async (session) => await session.close()));
25005
+ this.#nativeBrowserSessions.clear();
25006
+ await Promise.all(
25007
+ [...sessions, ...nativeBrowserSessions].map(
25008
+ async (session) => await session.close()
25009
+ )
25010
+ );
24276
25011
  };
24277
25012
  ensureSession = async (options) => {
24278
25013
  const existing = this.#sessions.get(options.sessionId);
@@ -24297,7 +25032,30 @@ var AcpSessionManager = class {
24297
25032
  }
24298
25033
  return started;
24299
25034
  };
24300
- listNativeSessions = async (options, cursor) => await (await this.ensureSession(options)).listNativeSessions(
25035
+ async #ensureNativeSessionBrowser(options) {
25036
+ const existing = this.#nativeBrowserSessions.get(options.sessionId);
25037
+ if (existing !== void 0) {
25038
+ if (!existing.belongsTo(
25039
+ options.agent.id,
25040
+ options.cwd,
25041
+ options.additionalDirectories
25042
+ )) {
25043
+ throw new AcpExecutionError(
25044
+ "The agent or workspace cannot change after a conversation has started",
25045
+ {},
25046
+ "session_identity_mismatch"
25047
+ );
25048
+ }
25049
+ return existing;
25050
+ }
25051
+ await this.prepareNativeSessionBrowser(options);
25052
+ const started = this.#nativeBrowserSessions.get(options.sessionId);
25053
+ if (started === void 0) {
25054
+ throw new AcpExecutionError("ACP native session browser did not start");
25055
+ }
25056
+ return started;
25057
+ }
25058
+ listNativeSessions = async (options, cursor) => await (await this.#ensureNativeSessionBrowser(options)).listNativeSessions(
24301
25059
  cursor,
24302
25060
  options.signal
24303
25061
  );
@@ -24380,7 +25138,7 @@ var AcpSessionManager = class {
24380
25138
  }
24381
25139
  };
24382
25140
  deleteNativeSession = async (options, nativeSessionId) => {
24383
- const runtime = await this.ensureSession(options);
25141
+ const runtime = await this.#ensureNativeSessionBrowser(options);
24384
25142
  const key = `${options.agent.id}:${nativeSessionId}`;
24385
25143
  const linked = this.#store.findNative(options.agent.id, nativeSessionId);
24386
25144
  if (this.#nativeOperations.has(key) || linked.some(
@@ -24407,7 +25165,8 @@ var AcpSessionManager = class {
24407
25165
  nativeSessionId
24408
25166
  );
24409
25167
  if (runtime.nativeSessionId() === nativeSessionId) {
24410
- this.#sessions.delete(options.sessionId);
25168
+ this.#nativeBrowserSessions.delete(options.sessionId);
25169
+ this.#nativeBrowserStore.remove(options.sessionId);
24411
25170
  await runtime.close();
24412
25171
  }
24413
25172
  return deleted;
@@ -26079,12 +26838,12 @@ var NativeSessionService = class {
26079
26838
  execute = async (command, signal) => {
26080
26839
  signal.throwIfAborted();
26081
26840
  const cwd = await this.#directories.resolve(
26082
- command.bindingId,
26841
+ this.#config.bindingId,
26083
26842
  command.directoryId,
26084
26843
  signal
26085
26844
  );
26086
26845
  const additionalDirectories = await this.#directories.resolveMany(
26087
- command.bindingId,
26846
+ this.#config.bindingId,
26088
26847
  command.additionalDirectoryIds,
26089
26848
  signal
26090
26849
  );
@@ -26096,22 +26855,21 @@ var NativeSessionService = class {
26096
26855
  sessionId: command.sessionId,
26097
26856
  signal
26098
26857
  };
26099
- const prepared = await this.#sessions.prepareSession(options);
26858
+ const prepared = await this.#sessions.prepareNativeSessionBrowser(options);
26100
26859
  if (!prepared.capabilities.listSessions)
26101
26860
  throw new AcpExecutionError(
26102
26861
  "This Agent does not support native session listing",
26103
26862
  {},
26104
26863
  "native_session_unsupported"
26105
26864
  );
26106
- const scope = JSON.stringify([
26865
+ const entryScope = JSON.stringify([
26107
26866
  command.agentId,
26108
26867
  command.bindingId,
26109
- command.sessionId,
26110
- cwd
26868
+ command.sessionId
26111
26869
  ]);
26870
+ const cursorScope = JSON.stringify([entryScope, cwd]);
26112
26871
  const envelope2 = {
26113
26872
  kind: "native.session.result",
26114
- protocolVersion: 1,
26115
26873
  requestId: command.requestId,
26116
26874
  sessionId: command.sessionId
26117
26875
  };
@@ -26119,7 +26877,7 @@ var NativeSessionService = class {
26119
26877
  let cursor = null;
26120
26878
  if (command.cursor !== null) {
26121
26879
  const known = this.#cursors.get(command.cursor);
26122
- if (known?.scope !== scope)
26880
+ if (known?.scope !== cursorScope)
26123
26881
  throw new AcpExecutionError(
26124
26882
  "Refresh the native session list before continuing",
26125
26883
  {},
@@ -26135,7 +26893,7 @@ var NativeSessionService = class {
26135
26893
  const entryId = randomUUID3();
26136
26894
  if (this.#entries.size >= 5e3) this.#entries.clear();
26137
26895
  this.#entries.set(entryId, {
26138
- scope,
26896
+ scope: entryScope,
26139
26897
  nativeSessionId: info.sessionId,
26140
26898
  cwd: authorized.cwd,
26141
26899
  additionalDirectories: authorized.additionalDirectories
@@ -26159,7 +26917,10 @@ var NativeSessionService = class {
26159
26917
  );
26160
26918
  nextCursor = randomUUID3();
26161
26919
  if (this.#cursors.size >= 500) this.#cursors.clear();
26162
- this.#cursors.set(nextCursor, { scope, cursor: page.nextCursor });
26920
+ this.#cursors.set(nextCursor, {
26921
+ scope: cursorScope,
26922
+ cursor: page.nextCursor
26923
+ });
26163
26924
  }
26164
26925
  this.record(command, "native_sessions_listed");
26165
26926
  return {
@@ -26171,12 +26932,18 @@ var NativeSessionService = class {
26171
26932
  };
26172
26933
  }
26173
26934
  const selected = this.#entries.get(command.entryId);
26174
- if (selected?.scope !== scope)
26935
+ if (selected?.scope !== entryScope)
26175
26936
  throw new AcpExecutionError(
26176
26937
  "Select a session from a fresh native session list",
26177
26938
  {},
26178
26939
  "native_session_not_found"
26179
26940
  );
26941
+ if (selected.cwd !== cwd)
26942
+ throw new AcpExecutionError(
26943
+ "The selected session belongs to a different workspace. Refresh the list before continuing.",
26944
+ {},
26945
+ "native_session_target_changed"
26946
+ );
26180
26947
  const target = await this.resolveTarget(command, options, selected);
26181
26948
  if (command.action === "delete") {
26182
26949
  if (!prepared.capabilities.deleteSession)
@@ -26257,6 +27024,7 @@ var NativeSessionService = class {
26257
27024
  action: "preview",
26258
27025
  entryId: command.entryId,
26259
27026
  reason: "continuation_unavailable",
27027
+ targetSessionId: command.targetSessionId,
26260
27028
  title: target.info.title ?? "Untitled session",
26261
27029
  history: opened.history
26262
27030
  };
@@ -26272,7 +27040,6 @@ var NativeSessionService = class {
26272
27040
  directoryId: target.directoryId,
26273
27041
  directoryLabel: target.directoryLabel,
26274
27042
  kind: "session.ready",
26275
- protocolVersion: 1,
26276
27043
  requestId: command.requestId,
26277
27044
  restored: true,
26278
27045
  sessionId: opened.sessionId
@@ -26285,6 +27052,7 @@ var NativeSessionService = class {
26285
27052
  ...envelope2,
26286
27053
  action: command.action,
26287
27054
  ready,
27055
+ targetSessionId: command.targetSessionId,
26288
27056
  title: target.info.title ?? "Untitled session",
26289
27057
  history: opened.history
26290
27058
  };
@@ -26569,13 +27337,171 @@ var RelayConnectionLiveness = class {
26569
27337
  this.#transport.send(
26570
27338
  encodeRuntimeHeartbeatEvent({
26571
27339
  heartbeatId,
26572
- kind: RUNTIME_HEARTBEAT_KIND,
26573
- protocolVersion: MOBIUS_PROTOCOL_VERSION
27340
+ kind: RUNTIME_HEARTBEAT_KIND
26574
27341
  })
26575
27342
  );
26576
27343
  };
26577
27344
  };
26578
27345
 
27346
+ // src/relay-connection/session-event-outbox.ts
27347
+ import { mkdirSync as mkdirSync3 } from "node:fs";
27348
+ import { dirname as dirname5 } from "node:path";
27349
+ import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
27350
+ function readPendingEnvelope(row) {
27351
+ if (typeof row !== "object" || row === null || Array.isArray(row)) {
27352
+ throw new Error("SQLite returned an invalid session event outbox row");
27353
+ }
27354
+ const envelope2 = Reflect.get(row, "envelope_json");
27355
+ if (typeof envelope2 !== "string") {
27356
+ throw new Error("SQLite returned an invalid session event envelope");
27357
+ }
27358
+ return envelope2;
27359
+ }
27360
+ var SessionEventOutbox = class {
27361
+ #database;
27362
+ constructor(path2) {
27363
+ mkdirSync3(dirname5(path2), { recursive: true });
27364
+ this.#database = new DatabaseSync3(path2);
27365
+ this.#database.exec(`
27366
+ CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
27367
+ ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
27368
+ event_id TEXT NOT NULL UNIQUE,
27369
+ session_id TEXT NOT NULL,
27370
+ envelope_json TEXT NOT NULL
27371
+ ) STRICT;
27372
+ CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
27373
+ ON relay_session_event_outbox(ordinal);
27374
+ CREATE TABLE IF NOT EXISTS relay_session_event_sources (
27375
+ source_key TEXT PRIMARY KEY,
27376
+ next_source_seq INTEGER NOT NULL
27377
+ ) STRICT;
27378
+ CREATE TABLE IF NOT EXISTS relay_turn_receipts (
27379
+ command_id TEXT PRIMARY KEY,
27380
+ session_id TEXT NOT NULL,
27381
+ command_json TEXT NOT NULL,
27382
+ attempt_id TEXT NOT NULL,
27383
+ state TEXT NOT NULL CHECK (
27384
+ state IN ('dispatching', 'running', 'succeeded', 'failed', 'cancelled')
27385
+ )
27386
+ ) STRICT;
27387
+ `);
27388
+ }
27389
+ claimExecution = (commandId, sessionId, commandJson) => {
27390
+ this.#database.exec("BEGIN IMMEDIATE");
27391
+ try {
27392
+ const existing = this.#database.prepare(
27393
+ `SELECT session_id, command_json, attempt_id, state
27394
+ FROM relay_turn_receipts WHERE command_id = ?`
27395
+ ).get(commandId);
27396
+ if (typeof existing === "object" && existing !== null) {
27397
+ const storedSessionId = Reflect.get(existing, "session_id");
27398
+ const storedCommand = Reflect.get(existing, "command_json");
27399
+ const attemptId2 = Reflect.get(existing, "attempt_id");
27400
+ const state = Reflect.get(existing, "state");
27401
+ if (storedSessionId !== sessionId || storedCommand !== commandJson || typeof attemptId2 !== "string" || !isDaemonExecutionState(state)) {
27402
+ throw new Error(
27403
+ "The daemon command identity conflicts with its durable receipt"
27404
+ );
27405
+ }
27406
+ this.#database.exec("COMMIT");
27407
+ return { attemptId: attemptId2, commandId, kind: "duplicate", state };
27408
+ }
27409
+ const attemptId = crypto.randomUUID();
27410
+ this.#database.prepare(
27411
+ `INSERT INTO relay_turn_receipts (
27412
+ command_id, session_id, command_json, attempt_id, state
27413
+ ) VALUES (?, ?, ?, ?, 'dispatching')`
27414
+ ).run(commandId, sessionId, commandJson, attemptId);
27415
+ this.#database.exec("COMMIT");
27416
+ return {
27417
+ attemptId,
27418
+ commandId,
27419
+ kind: "accepted",
27420
+ state: "dispatching"
27421
+ };
27422
+ } catch (error61) {
27423
+ this.#database.exec("ROLLBACK");
27424
+ throw error61;
27425
+ }
27426
+ };
27427
+ transitionExecution = (commandId, state) => {
27428
+ const row = this.#database.prepare(`SELECT state FROM relay_turn_receipts WHERE command_id = ?`).get(commandId);
27429
+ const current = typeof row === "object" && row !== null ? Reflect.get(row, "state") : void 0;
27430
+ if (!isDaemonExecutionState(current)) {
27431
+ throw new Error("The daemon execution receipt does not exist");
27432
+ }
27433
+ if (current === state) {
27434
+ return;
27435
+ }
27436
+ const allowed = current === "dispatching" && (state === "running" || state === "failed" || state === "cancelled") || current === "running" && (state === "succeeded" || state === "failed" || state === "cancelled");
27437
+ if (!allowed) {
27438
+ throw new Error("The daemon execution transition is invalid");
27439
+ }
27440
+ this.#database.prepare(`UPDATE relay_turn_receipts SET state = ? WHERE command_id = ?`).run(state, commandId);
27441
+ };
27442
+ acknowledge = (acknowledgement) => {
27443
+ this.#database.prepare(
27444
+ `DELETE FROM relay_session_event_outbox
27445
+ WHERE event_id = ? AND session_id = ?`
27446
+ ).run(acknowledgement.eventId, acknowledgement.sessionId);
27447
+ };
27448
+ close = () => {
27449
+ this.#database.close();
27450
+ };
27451
+ enqueue = (sessionId, payload, attemptId = null) => {
27452
+ const sourceKey = attemptId === null ? `runtime:${sessionId}` : `attempt:${sessionId}:${attemptId}`;
27453
+ this.#database.exec("BEGIN IMMEDIATE");
27454
+ try {
27455
+ const row = this.#database.prepare(
27456
+ `SELECT next_source_seq FROM relay_session_event_sources
27457
+ WHERE source_key = ?`
27458
+ ).get(sourceKey);
27459
+ const storedSourceSeq = typeof row === "object" && row !== null ? Reflect.get(row, "next_source_seq") : void 0;
27460
+ const nextSourceSeq = typeof storedSourceSeq === "number" ? storedSourceSeq : 1;
27461
+ if (!Number.isSafeInteger(nextSourceSeq) || nextSourceSeq < 1) {
27462
+ throw new Error("SQLite returned an invalid event source sequence");
27463
+ }
27464
+ const envelope2 = {
27465
+ eventId: crypto.randomUUID(),
27466
+ kind: SESSION_EVENT_KIND,
27467
+ payload,
27468
+ sessionId,
27469
+ source: attemptId === null ? { kind: "runtime", sourceSeq: nextSourceSeq.toString() } : {
27470
+ attemptId,
27471
+ kind: "attempt",
27472
+ sourceSeq: nextSourceSeq.toString()
27473
+ }
27474
+ };
27475
+ const encoded = encodeSessionEventEnvelope(envelope2);
27476
+ this.#database.prepare(
27477
+ `INSERT INTO relay_session_event_sources (
27478
+ source_key, next_source_seq
27479
+ ) VALUES (?, ?)
27480
+ ON CONFLICT(source_key) DO UPDATE SET
27481
+ next_source_seq = excluded.next_source_seq`
27482
+ ).run(sourceKey, nextSourceSeq + 1);
27483
+ this.#database.prepare(
27484
+ `INSERT INTO relay_session_event_outbox (
27485
+ event_id, session_id, envelope_json
27486
+ ) VALUES (?, ?, ?)`
27487
+ ).run(envelope2.eventId, envelope2.sessionId, encoded);
27488
+ this.#database.exec("COMMIT");
27489
+ return encoded;
27490
+ } catch (error61) {
27491
+ this.#database.exec("ROLLBACK");
27492
+ throw error61;
27493
+ }
27494
+ };
27495
+ pending = () => this.#database.prepare(
27496
+ `SELECT envelope_json
27497
+ FROM relay_session_event_outbox
27498
+ ORDER BY ordinal`
27499
+ ).all().map(readPendingEnvelope);
27500
+ };
27501
+ function isDaemonExecutionState(value) {
27502
+ return value === "cancelled" || value === "dispatching" || value === "failed" || value === "running" || value === "succeeded";
27503
+ }
27504
+
26579
27505
  // src/relay-connection/timer.ts
26580
27506
  var SystemDaemonTimer = class {
26581
27507
  schedule = (callback, milliseconds) => {
@@ -26640,44 +27566,47 @@ var RelayConnectionRefresh = class {
26640
27566
  };
26641
27567
  };
26642
27568
  var DaemonAcpObserver = class {
26643
- #socket;
26644
- constructor(socket) {
26645
- this.#socket = socket;
27569
+ #record;
27570
+ constructor(record2) {
27571
+ this.#record = record2;
26646
27572
  }
26647
27573
  onCommands = (event) => {
26648
- send(this.#socket, encodeSessionCommandsUpdatedEvent(event));
27574
+ this.#record(event.sessionId, encodeSessionCommandsUpdatedEvent(event));
26649
27575
  return Promise.resolve();
26650
27576
  };
26651
27577
  onConfig = (event) => {
26652
- send(this.#socket, encodeSessionConfigUpdatedEvent(event));
27578
+ this.#record(event.sessionId, encodeSessionConfigUpdatedEvent(event));
26653
27579
  return Promise.resolve();
26654
27580
  };
26655
27581
  onContent = (event) => {
26656
- send(this.#socket, encodeAgentContentEvent(event));
27582
+ this.#record(event.sessionId, encodeAgentContentEvent(event));
26657
27583
  return Promise.resolve();
26658
27584
  };
26659
27585
  onElicitation = (event) => {
26660
- send(this.#socket, encodeSessionElicitationRequestedEvent(event));
27586
+ this.#record(
27587
+ event.sessionId,
27588
+ encodeSessionElicitationRequestedEvent(event)
27589
+ );
26661
27590
  return Promise.resolve();
26662
27591
  };
26663
27592
  onElicitationResolved = (event) => {
26664
- send(this.#socket, encodeSessionElicitationResolvedEvent(event));
27593
+ this.#record(event.sessionId, encodeSessionElicitationResolvedEvent(event));
26665
27594
  return Promise.resolve();
26666
27595
  };
26667
27596
  onInfo = (event) => {
26668
- send(this.#socket, encodeSessionInfoUpdatedEvent(event));
27597
+ this.#record(event.sessionId, encodeSessionInfoUpdatedEvent(event));
26669
27598
  return Promise.resolve();
26670
27599
  };
26671
27600
  onPermission = (event) => {
26672
- send(this.#socket, encodeSessionPermissionRequestedEvent(event));
27601
+ this.#record(event.sessionId, encodeSessionPermissionRequestedEvent(event));
26673
27602
  return Promise.resolve();
26674
27603
  };
26675
27604
  onPermissionResolved = (event) => {
26676
- send(this.#socket, encodeSessionPermissionResolvedEvent(event));
27605
+ this.#record(event.sessionId, encodeSessionPermissionResolvedEvent(event));
26677
27606
  return Promise.resolve();
26678
27607
  };
26679
27608
  onUsage = (event) => {
26680
- send(this.#socket, encodeSessionUsageUpdatedEvent(event));
27609
+ this.#record(event.sessionId, encodeSessionUsageUpdatedEvent(event));
26681
27610
  return Promise.resolve();
26682
27611
  };
26683
27612
  };
@@ -26729,7 +27658,6 @@ var DaemonInstallationObserver = class {
26729
27658
  encodeAgentInstallAwaitingApprovalEvent({
26730
27659
  agentId: state.agentId,
26731
27660
  kind: AGENT_INSTALL_AWAITING_APPROVAL_KIND,
26732
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26733
27661
  requestId: state.requestId
26734
27662
  })
26735
27663
  );
@@ -26743,7 +27671,6 @@ var DaemonInstallationObserver = class {
26743
27671
  encodeAgentInstallStartedEvent({
26744
27672
  agentId: state.agentId,
26745
27673
  kind: AGENT_INSTALL_STARTED_KIND,
26746
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26747
27674
  requestId: state.requestId
26748
27675
  })
26749
27676
  );
@@ -26753,7 +27680,6 @@ var DaemonInstallationObserver = class {
26753
27680
  encodeAgentInstallProgressEvent({
26754
27681
  agentId: state.agentId,
26755
27682
  kind: AGENT_INSTALL_PROGRESS_KIND,
26756
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26757
27683
  requestId: state.requestId,
26758
27684
  stage: state.stage
26759
27685
  })
@@ -26767,7 +27693,6 @@ var DaemonInstallationObserver = class {
26767
27693
  agentId: state.agentId,
26768
27694
  authenticationMayBeRequired: state.authenticationMayBeRequired,
26769
27695
  kind: AGENT_INSTALL_COMPLETED_KIND,
26770
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26771
27696
  requestId: state.requestId
26772
27697
  })
26773
27698
  );
@@ -26781,7 +27706,6 @@ var DaemonInstallationObserver = class {
26781
27706
  code: state.code,
26782
27707
  kind: AGENT_INSTALL_FAILED_KIND,
26783
27708
  message: state.message,
26784
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26785
27709
  requestId: state.requestId
26786
27710
  })
26787
27711
  );
@@ -26793,7 +27717,6 @@ var DaemonInstallationObserver = class {
26793
27717
  encodeAgentInstallCancelledEvent({
26794
27718
  agentId: state.agentId,
26795
27719
  kind: AGENT_INSTALL_CANCELLED_KIND,
26796
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26797
27720
  requestId: state.requestId
26798
27721
  })
26799
27722
  );
@@ -26841,20 +27764,25 @@ function send(socket, message) {
26841
27764
  }
26842
27765
  socket.send(message);
26843
27766
  }
26844
- function reportFailure(socket, command, code, message) {
26845
- if (socket.readyState !== WebSocket2.OPEN) {
26846
- return;
27767
+ function recordSessionEvent(outbox, socket, sessionId, payload, attemptId = null) {
27768
+ const envelope2 = outbox.enqueue(sessionId, payload, attemptId);
27769
+ if (socket.readyState === WebSocket2.OPEN) {
27770
+ socket.send(envelope2);
26847
27771
  }
26848
- send(
27772
+ }
27773
+ function reportFailure(outbox, socket, command, code, message, attemptId = null) {
27774
+ recordSessionEvent(
27775
+ outbox,
26849
27776
  socket,
27777
+ command.sessionId,
26850
27778
  encodeSessionFailedEvent({
26851
27779
  code,
26852
27780
  commandId: command.commandId,
26853
27781
  kind: SESSION_FAILED_KIND,
26854
27782
  message,
26855
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26856
27783
  sessionId: command.sessionId
26857
- })
27784
+ }),
27785
+ attemptId
26858
27786
  );
26859
27787
  }
26860
27788
  function operationErrorCode(error61) {
@@ -26879,7 +27807,6 @@ function reportOperationFailure(socket, requestId, sessionId, error61) {
26879
27807
  code: operationErrorCode(error61),
26880
27808
  kind: "session.operation.failed",
26881
27809
  message: operationErrorMessage(error61),
26882
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26883
27810
  requestId,
26884
27811
  sessionId
26885
27812
  })
@@ -26935,7 +27862,6 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
26935
27862
  entries: listing.entries,
26936
27863
  kind: "workspace.entries",
26937
27864
  parentDirectoryId: listing.parentDirectoryId,
26938
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26939
27865
  requestId: command.requestId
26940
27866
  })
26941
27867
  );
@@ -26943,11 +27869,11 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
26943
27869
  reportOperationFailure(socket, command.requestId, "", error61);
26944
27870
  }
26945
27871
  }
26946
- async function executeSessionPrepare(socket, command, config2, directories, audit, sessions, signal) {
27872
+ async function executeSessionPrepare(outbox, socket, command, config2, directories, audit, sessions, signal) {
26947
27873
  try {
26948
27874
  const resolved = await resolveSessionDirectories(
26949
27875
  directories,
26950
- command.bindingId,
27876
+ config2.bindingId,
26951
27877
  command.directoryId,
26952
27878
  command.additionalDirectoryIds,
26953
27879
  signal
@@ -26961,7 +27887,7 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26961
27887
  signal
26962
27888
  });
26963
27889
  const listing = await directories.list(
26964
- command.bindingId,
27890
+ config2.bindingId,
26965
27891
  command.directoryId,
26966
27892
  signal
26967
27893
  );
@@ -26970,8 +27896,10 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26970
27896
  event: "session_prepared",
26971
27897
  sessionId: command.sessionId
26972
27898
  });
26973
- send(
27899
+ recordSessionEvent(
27900
+ outbox,
26974
27901
  socket,
27902
+ command.sessionId,
26975
27903
  encodeSessionReadyEvent({
26976
27904
  additionalDirectories: resolved.additionalDirectoryEntries,
26977
27905
  agentId: command.agentId,
@@ -26983,21 +27911,29 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26983
27911
  directoryId: command.directoryId,
26984
27912
  directoryLabel: listing.directoryLabel,
26985
27913
  kind: "session.ready",
26986
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26987
27914
  requestId: command.requestId,
26988
27915
  restored: prepared.restored,
26989
27916
  sessionId: command.sessionId
26990
27917
  })
26991
27918
  );
26992
27919
  } catch (error61) {
27920
+ audit.record({
27921
+ commandId: command.requestId,
27922
+ details: {
27923
+ agentId: command.agentId,
27924
+ code: operationErrorCode(error61)
27925
+ },
27926
+ event: "session_prepare_failed",
27927
+ sessionId: command.sessionId
27928
+ });
26993
27929
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
26994
27930
  }
26995
27931
  }
26996
- async function executeSessionConfigure(socket, command, config2, directories, audit, sessions, signal) {
27932
+ async function executeSessionConfigure(outbox, socket, command, config2, directories, audit, sessions, signal) {
26997
27933
  try {
26998
27934
  const resolved = await resolveSessionDirectories(
26999
27935
  directories,
27000
- command.bindingId,
27936
+ config2.bindingId,
27001
27937
  command.directoryId,
27002
27938
  command.additionalDirectoryIds,
27003
27939
  signal
@@ -27019,12 +27955,13 @@ async function executeSessionConfigure(socket, command, config2, directories, au
27019
27955
  event: "session_configured",
27020
27956
  sessionId: command.sessionId
27021
27957
  });
27022
- send(
27958
+ recordSessionEvent(
27959
+ outbox,
27023
27960
  socket,
27961
+ command.sessionId,
27024
27962
  encodeSessionConfigUpdatedEvent({
27025
27963
  configOptions,
27026
27964
  kind: "session.config.updated",
27027
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27028
27965
  requestId: command.requestId,
27029
27966
  sessionId: command.sessionId
27030
27967
  })
@@ -27033,31 +27970,33 @@ async function executeSessionConfigure(socket, command, config2, directories, au
27033
27970
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
27034
27971
  }
27035
27972
  }
27036
- async function executePrompt(socket, command, config2, directories, audit, sessions, signal) {
27973
+ async function executePrompt(outbox, socket, command, config2, directories, audit, sessions, attemptId, signal) {
27037
27974
  try {
27038
27975
  const resolved = await resolveSessionDirectories(
27039
27976
  directories,
27040
- command.bindingId,
27977
+ config2.bindingId,
27041
27978
  command.directoryId,
27042
27979
  command.additionalDirectoryIds,
27043
27980
  signal
27044
27981
  );
27045
27982
  const agent = config2.catalog.find(command.agentId);
27046
- const processAttemptId = randomUUID5();
27047
27983
  audit.record({
27048
27984
  commandId: command.commandId,
27049
27985
  event: "session_authorized",
27050
27986
  sessionId: command.sessionId
27051
27987
  });
27052
- send(
27988
+ outbox.transitionExecution(command.commandId, "running");
27989
+ recordSessionEvent(
27990
+ outbox,
27053
27991
  socket,
27992
+ command.sessionId,
27054
27993
  encodeSessionStartedEvent({
27055
27994
  commandId: command.commandId,
27056
27995
  kind: SESSION_STARTED_KIND,
27057
- processAttemptId,
27058
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27996
+ attemptId,
27059
27997
  sessionId: command.sessionId
27060
- })
27998
+ }),
27999
+ attemptId
27061
28000
  );
27062
28001
  const result = await sessions.runPrompt({
27063
28002
  additionalDirectories: resolved.additionalDirectories,
@@ -27066,38 +28005,43 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27066
28005
  cwd: resolved.cwd,
27067
28006
  images: command.images,
27068
28007
  onActivity: (activity) => {
27069
- send(
28008
+ recordSessionEvent(
28009
+ outbox,
27070
28010
  socket,
28011
+ command.sessionId,
27071
28012
  encodeAgentActivityEvent({
27072
28013
  activityId: activity.activityId,
27073
28014
  activityType: activity.activityType,
27074
28015
  commandId: command.commandId,
27075
28016
  content: activity.content,
28017
+ detail: activity.detail,
27076
28018
  input: activity.input,
27077
28019
  kind: AGENT_ACTIVITY_KIND,
27078
28020
  locations: activity.locations,
27079
28021
  name: activity.name,
27080
28022
  output: activity.output,
27081
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27082
28023
  sequence: activity.sequence,
27083
28024
  sessionId: command.sessionId,
27084
28025
  status: activity.status,
27085
28026
  title: activity.title,
27086
28027
  toolKind: activity.toolKind
27087
- })
28028
+ }),
28029
+ attemptId
27088
28030
  );
27089
28031
  return Promise.resolve();
27090
28032
  },
27091
28033
  onText: (text) => {
27092
- send(
28034
+ recordSessionEvent(
28035
+ outbox,
27093
28036
  socket,
28037
+ command.sessionId,
27094
28038
  encodeAgentMessageDeltaEvent({
27095
28039
  commandId: command.commandId,
27096
28040
  kind: AGENT_MESSAGE_DELTA_KIND,
27097
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27098
28041
  sessionId: command.sessionId,
27099
28042
  text
27100
- })
28043
+ }),
28044
+ attemptId
27101
28045
  );
27102
28046
  return Promise.resolve();
27103
28047
  },
@@ -27106,15 +28050,21 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27106
28050
  sessionId: command.sessionId,
27107
28051
  signal
27108
28052
  });
27109
- send(
28053
+ recordSessionEvent(
28054
+ outbox,
27110
28055
  socket,
28056
+ command.sessionId,
27111
28057
  encodeSessionCompletedEvent({
27112
28058
  commandId: command.commandId,
27113
28059
  kind: SESSION_COMPLETED_KIND,
27114
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27115
28060
  sessionId: command.sessionId,
27116
28061
  stopReason: result.stopReason
27117
- })
28062
+ }),
28063
+ attemptId
28064
+ );
28065
+ outbox.transitionExecution(
28066
+ command.commandId,
28067
+ result.stopReason === "cancelled" ? "cancelled" : "succeeded"
27118
28068
  );
27119
28069
  audit.record({
27120
28070
  commandId: command.commandId,
@@ -27129,11 +28079,14 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27129
28079
  });
27130
28080
  const code = operationErrorCode(error61);
27131
28081
  reportFailure(
28082
+ outbox,
27132
28083
  socket,
27133
28084
  command,
27134
28085
  code === "session_operation_failed" ? "agent_execution_failed" : code,
27135
- code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error61)
28086
+ code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error61),
28087
+ attemptId
27136
28088
  );
28089
+ outbox.transitionExecution(command.commandId, "failed");
27137
28090
  console.error("Mobius daemon command failed", error61);
27138
28091
  }
27139
28092
  }
@@ -27151,15 +28104,28 @@ function waitForRelayRetry(signal, timer) {
27151
28104
  signal.addEventListener("abort", finish, { once: true });
27152
28105
  });
27153
28106
  }
27154
- async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, signal, timer) {
28107
+ async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, signal, timer) {
27155
28108
  const relayUrl = new URL(config2.relayUrl);
27156
28109
  relayUrl.searchParams.set("liveness", "1");
27157
28110
  const socket = await connectRelay(relayUrl, signal);
27158
28111
  const activeTurns = /* @__PURE__ */ new Map();
28112
+ const activeAttemptIds = /* @__PURE__ */ new Map();
27159
28113
  const connectionController = new AbortController();
27160
28114
  const nativeRequests = /* @__PURE__ */ new Map();
27161
- sessions.setObserver(new DaemonAcpObserver(socket));
28115
+ const record2 = (sessionId, payload) => {
28116
+ recordSessionEvent(
28117
+ outbox,
28118
+ socket,
28119
+ sessionId,
28120
+ payload,
28121
+ activeAttemptIds.get(sessionId) ?? null
28122
+ );
28123
+ };
28124
+ sessions.setObserver(new DaemonAcpObserver(record2));
27162
28125
  installationObserver.connect(socket);
28126
+ for (const pending of outbox.pending()) {
28127
+ send(socket, pending);
28128
+ }
27163
28129
  try {
27164
28130
  await new Promise((resolve5, reject) => {
27165
28131
  let finished = false;
@@ -27233,6 +28199,10 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27233
28199
  }
27234
28200
  try {
27235
28201
  const kind = decodeMessageKind(encoded);
28202
+ if (kind === SESSION_EVENT_ACK_KIND) {
28203
+ outbox.acknowledge(decodeSessionEventAcknowledgement(encoded));
28204
+ return;
28205
+ }
27236
28206
  if (kind === NATIVE_SESSION_CANCEL_KIND) {
27237
28207
  const command2 = decodeNativeSessionCancel(encoded);
27238
28208
  const pending = nativeRequests.get(command2.requestId);
@@ -27390,6 +28360,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27390
28360
  if (kind === SESSION_PREPARE_KIND) {
27391
28361
  const command2 = decodeSessionPrepareCommand(encoded);
27392
28362
  void executeSessionPrepare(
28363
+ outbox,
27393
28364
  socket,
27394
28365
  command2,
27395
28366
  config2,
@@ -27403,6 +28374,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27403
28374
  if (kind === SESSION_CONFIGURE_KIND) {
27404
28375
  const command2 = decodeSessionConfigureCommand(encoded);
27405
28376
  void executeSessionConfigure(
28377
+ outbox,
27406
28378
  socket,
27407
28379
  command2,
27408
28380
  config2,
@@ -27468,28 +28440,36 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27468
28440
  }
27469
28441
  const command = decodeSessionPromptCommand(encoded);
27470
28442
  if (activeTurns.has(command.commandId)) {
27471
- reportFailure(
27472
- socket,
27473
- command,
27474
- "duplicate_command",
27475
- "The command is already running"
27476
- );
28443
+ return;
28444
+ }
28445
+ const receipt = outbox.claimExecution(
28446
+ command.commandId,
28447
+ command.sessionId,
28448
+ encoded
28449
+ );
28450
+ if (receipt.kind === "duplicate") {
27477
28451
  return;
27478
28452
  }
27479
28453
  const turn = new ActiveDaemonTurn(command, new AbortController());
27480
28454
  activeTurns.set(command.commandId, turn);
28455
+ activeAttemptIds.set(command.sessionId, receipt.attemptId);
27481
28456
  void executePrompt(
28457
+ outbox,
27482
28458
  socket,
27483
28459
  command,
27484
28460
  config2,
27485
28461
  directories,
27486
28462
  audit,
27487
28463
  sessions,
28464
+ receipt.attemptId,
27488
28465
  turn.signal
27489
28466
  ).catch((error61) => {
27490
28467
  console.error("Mobius daemon turn failed", error61);
27491
28468
  }).finally(() => {
27492
28469
  activeTurns.delete(command.commandId);
28470
+ if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
28471
+ activeAttemptIds.delete(command.sessionId);
28472
+ }
27493
28473
  connectionRefresh.afterTurnFinished();
27494
28474
  });
27495
28475
  } catch (error61) {
@@ -27538,6 +28518,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27538
28518
  specifications
27539
28519
  ).prepare(signal);
27540
28520
  const sessionStore = new SqliteAcpSessionStore(config2.auditDatabasePath);
28521
+ const outbox = new SessionEventOutbox(config2.auditDatabasePath);
27541
28522
  const sessions = new AcpSessionManager(
27542
28523
  new NullAcpSessionObserver(),
27543
28524
  sessionStore
@@ -27573,6 +28554,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27573
28554
  installations,
27574
28555
  installationObserver,
27575
28556
  nativeSessions,
28557
+ outbox,
27576
28558
  signal,
27577
28559
  timer
27578
28560
  );
@@ -27595,7 +28577,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27595
28577
  try {
27596
28578
  await sessions.close();
27597
28579
  } finally {
27598
- sessionStore.close();
28580
+ try {
28581
+ sessionStore.close();
28582
+ } finally {
28583
+ outbox.close();
28584
+ }
27599
28585
  }
27600
28586
  }
27601
28587
  }