@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/index.js CHANGED
@@ -494,7 +494,7 @@ function createDaemonConfig(connection, agents = [], installableAgents = []) {
494
494
  function loadDaemonConfig() {
495
495
  const relayUrl = new URL(
496
496
  // biome-ignore lint/complexity/useLiteralKeys: Environment variables use an index signature.
497
- process.env["MOBIUS_RELAY_URL"] ?? "ws://127.0.0.1:8787/v1/channels/local/daemon"
497
+ process.env["MOBIUS_RELAY_URL"] ?? "ws://127.0.0.1:8787/api/channels/local/daemon"
498
498
  );
499
499
  relayUrl.searchParams.set(
500
500
  "token",
@@ -527,7 +527,7 @@ import { spawn as spawn2 } from "node:child_process";
527
527
  import {
528
528
  methods as methods2,
529
529
  ndJsonStream,
530
- PROTOCOL_VERSION as PROTOCOL_VERSION2
530
+ PROTOCOL_VERSION
531
531
  } from "@agentclientprotocol/sdk";
532
532
 
533
533
  // ../../node_modules/.pnpm/zod@4.5.4/node_modules/zod/v4/classic/external.js
@@ -19446,9 +19446,6 @@ function decodeAgentPromptResponse(value) {
19446
19446
  return result.data;
19447
19447
  }
19448
19448
 
19449
- // ../protocol/src/version.ts
19450
- var MOBIUS_PROTOCOL_VERSION = 1;
19451
-
19452
19449
  // ../protocol/src/control-messages.ts
19453
19450
  var WORKSPACE_LIST_KIND = "workspace.list";
19454
19451
  var WORKSPACE_ENTRIES_KIND = "workspace.entries";
@@ -19481,7 +19478,6 @@ var IDENTIFIER = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATT
19481
19478
  var DIRECTORY_IDENTIFIER = external_exports.string().min(1).max(2048).regex(DIRECTORY_IDENTIFIER_PATTERN);
19482
19479
  var SHORT_TEXT = external_exports.string().max(500);
19483
19480
  var LONG_TEXT = external_exports.string().max(1e5);
19484
- var PROTOCOL_VERSION = external_exports.literal(MOBIUS_PROTOCOL_VERSION);
19485
19481
  var workspaceEntrySchema = external_exports.strictObject({
19486
19482
  directoryId: DIRECTORY_IDENTIFIER,
19487
19483
  name: external_exports.string().min(1).max(255)
@@ -19579,6 +19575,25 @@ var displayContentSchema = external_exports.strictObject({
19579
19575
  ]),
19580
19576
  uri: external_exports.string().max(4096)
19581
19577
  }).readonly();
19578
+ var recordedDisplayContentSchema = external_exports.strictObject({
19579
+ data: external_exports.string().max(4e6),
19580
+ mimeType: external_exports.string().max(255),
19581
+ name: external_exports.string().max(500),
19582
+ newText: external_exports.string().max(4e6),
19583
+ oldText: external_exports.string().max(4e6),
19584
+ path: external_exports.string().max(2048),
19585
+ terminalId: external_exports.string().max(255),
19586
+ text: external_exports.string().max(4e6),
19587
+ type: external_exports.enum([
19588
+ "diff",
19589
+ "image",
19590
+ "resource",
19591
+ "resource_link",
19592
+ "terminal",
19593
+ "text"
19594
+ ]),
19595
+ uri: external_exports.string().max(4096)
19596
+ }).readonly();
19582
19597
  var promptImageSchema = external_exports.strictObject({
19583
19598
  data: external_exports.string().min(1).max(4e6),
19584
19599
  mimeType: external_exports.string().min(1).max(255),
@@ -19595,7 +19610,6 @@ var workspaceListCommandSchema = external_exports.strictObject({
19595
19610
  bindingId: IDENTIFIER,
19596
19611
  directoryId: DIRECTORY_IDENTIFIER,
19597
19612
  kind: external_exports.literal(WORKSPACE_LIST_KIND),
19598
- protocolVersion: PROTOCOL_VERSION,
19599
19613
  requestId: IDENTIFIER
19600
19614
  }).readonly();
19601
19615
  var workspaceEntriesEventSchema = external_exports.strictObject({
@@ -19605,7 +19619,6 @@ var workspaceEntriesEventSchema = external_exports.strictObject({
19605
19619
  entries: external_exports.array(workspaceEntrySchema).max(500).readonly(),
19606
19620
  kind: external_exports.literal(WORKSPACE_ENTRIES_KIND),
19607
19621
  parentDirectoryId: external_exports.string().max(2048),
19608
- protocolVersion: PROTOCOL_VERSION,
19609
19622
  requestId: IDENTIFIER
19610
19623
  }).readonly();
19611
19624
  var sessionIdentityFields = {
@@ -19618,7 +19631,6 @@ var sessionIdentityFields = {
19618
19631
  var sessionPrepareCommandSchema = external_exports.strictObject({
19619
19632
  ...sessionIdentityFields,
19620
19633
  kind: external_exports.literal(SESSION_PREPARE_KIND),
19621
- protocolVersion: PROTOCOL_VERSION,
19622
19634
  requestId: IDENTIFIER
19623
19635
  }).readonly();
19624
19636
  var sessionReadyEventSchema = external_exports.strictObject({
@@ -19632,7 +19644,6 @@ var sessionReadyEventSchema = external_exports.strictObject({
19632
19644
  directoryId: DIRECTORY_IDENTIFIER,
19633
19645
  directoryLabel: external_exports.string().min(1).max(2048),
19634
19646
  kind: external_exports.literal(SESSION_READY_KIND),
19635
- protocolVersion: PROTOCOL_VERSION,
19636
19647
  requestId: IDENTIFIER,
19637
19648
  restored: external_exports.boolean(),
19638
19649
  sessionId: IDENTIFIER
@@ -19642,7 +19653,6 @@ var sessionConfigureCommandSchema = external_exports.strictObject({
19642
19653
  booleanValue: external_exports.boolean(),
19643
19654
  configId: external_exports.string().min(1).max(128),
19644
19655
  kind: external_exports.literal(SESSION_CONFIGURE_KIND),
19645
- protocolVersion: PROTOCOL_VERSION,
19646
19656
  requestId: IDENTIFIER,
19647
19657
  value: external_exports.string().max(500),
19648
19658
  valueType: external_exports.enum(["boolean", "select"])
@@ -19650,7 +19660,6 @@ var sessionConfigureCommandSchema = external_exports.strictObject({
19650
19660
  var sessionConfigUpdatedEventSchema = external_exports.strictObject({
19651
19661
  configOptions: external_exports.array(configOptionSchema).max(100).readonly(),
19652
19662
  kind: external_exports.literal(SESSION_CONFIG_UPDATED_KIND),
19653
- protocolVersion: PROTOCOL_VERSION,
19654
19663
  requestId: IDENTIFIER,
19655
19664
  sessionId: IDENTIFIER
19656
19665
  }).readonly();
@@ -19659,7 +19668,6 @@ var sessionContextUsageUpdatedEventSchema = external_exports.strictObject({
19659
19668
  costCurrency: external_exports.string().max(16),
19660
19669
  hasCost: external_exports.boolean(),
19661
19670
  kind: external_exports.literal(SESSION_USAGE_UPDATED_KIND),
19662
- protocolVersion: PROTOCOL_VERSION,
19663
19671
  sessionId: IDENTIFIER,
19664
19672
  size: external_exports.number().int().nonnegative(),
19665
19673
  source: external_exports.literal("context").default("context"),
@@ -19669,7 +19677,6 @@ var sessionPromptUsageUpdatedEventSchema = external_exports.strictObject({
19669
19677
  _meta: promptMetadataSchema.nullable(),
19670
19678
  commandId: IDENTIFIER,
19671
19679
  kind: external_exports.literal(SESSION_USAGE_UPDATED_KIND),
19672
- protocolVersion: PROTOCOL_VERSION,
19673
19680
  sessionId: IDENTIFIER,
19674
19681
  source: external_exports.literal("prompt"),
19675
19682
  usage: promptUsageSchema.nullable()
@@ -19681,12 +19688,10 @@ var sessionUsageUpdatedEventSchema = external_exports.union([
19681
19688
  var sessionCommandsUpdatedEventSchema = external_exports.strictObject({
19682
19689
  commands: external_exports.array(sessionCommandSchema).max(500).readonly(),
19683
19690
  kind: external_exports.literal(SESSION_COMMANDS_UPDATED_KIND),
19684
- protocolVersion: PROTOCOL_VERSION,
19685
19691
  sessionId: IDENTIFIER
19686
19692
  }).readonly();
19687
19693
  var sessionInfoUpdatedEventSchema = external_exports.strictObject({
19688
19694
  kind: external_exports.literal(SESSION_INFO_UPDATED_KIND),
19689
- protocolVersion: PROTOCOL_VERSION,
19690
19695
  sessionId: IDENTIFIER,
19691
19696
  title: external_exports.string().max(500).nullable(),
19692
19697
  updatedAt: external_exports.string().max(128)
@@ -19696,7 +19701,6 @@ var sessionPermissionRequestedEventSchema = external_exports.strictObject({
19696
19701
  interactionId: IDENTIFIER,
19697
19702
  kind: external_exports.literal(SESSION_PERMISSION_REQUESTED_KIND),
19698
19703
  options: external_exports.array(permissionOptionSchema).min(1).max(20).readonly(),
19699
- protocolVersion: PROTOCOL_VERSION,
19700
19704
  sessionId: IDENTIFIER,
19701
19705
  title: external_exports.string().min(1).max(500),
19702
19706
  toolCallId: external_exports.string().min(1).max(255),
@@ -19707,7 +19711,6 @@ var sessionPermissionRespondCommandSchema = external_exports.strictObject({
19707
19711
  kind: external_exports.literal(SESSION_PERMISSION_RESPOND_KIND),
19708
19712
  optionId: external_exports.string().max(255),
19709
19713
  outcome: external_exports.enum(["cancelled", "selected"]),
19710
- protocolVersion: PROTOCOL_VERSION,
19711
19714
  sessionId: IDENTIFIER
19712
19715
  }).readonly();
19713
19716
  var sessionPermissionResolvedEventSchema = external_exports.strictObject({
@@ -19715,7 +19718,6 @@ var sessionPermissionResolvedEventSchema = external_exports.strictObject({
19715
19718
  kind: external_exports.literal(SESSION_PERMISSION_RESOLVED_KIND),
19716
19719
  optionId: external_exports.string().max(255),
19717
19720
  outcome: external_exports.enum(["cancelled", "selected"]),
19718
- protocolVersion: PROTOCOL_VERSION,
19719
19721
  sessionId: IDENTIFIER
19720
19722
  }).readonly();
19721
19723
  var sessionElicitationRequestedEventSchema = external_exports.strictObject({
@@ -19727,7 +19729,6 @@ var sessionElicitationRequestedEventSchema = external_exports.strictObject({
19727
19729
  kind: external_exports.literal(SESSION_ELICITATION_REQUESTED_KIND),
19728
19730
  message: external_exports.string().min(1).max(2e3),
19729
19731
  mode: external_exports.enum(["form", "url"]),
19730
- protocolVersion: PROTOCOL_VERSION,
19731
19732
  sessionId: IDENTIFIER,
19732
19733
  url: external_exports.string().max(4096)
19733
19734
  }).readonly();
@@ -19736,21 +19737,18 @@ var sessionElicitationRespondCommandSchema = external_exports.strictObject({
19736
19737
  content: external_exports.string().max(1e5),
19737
19738
  interactionId: IDENTIFIER,
19738
19739
  kind: external_exports.literal(SESSION_ELICITATION_RESPOND_KIND),
19739
- protocolVersion: PROTOCOL_VERSION,
19740
19740
  sessionId: IDENTIFIER
19741
19741
  }).readonly();
19742
19742
  var sessionElicitationResolvedEventSchema = external_exports.strictObject({
19743
19743
  action: external_exports.enum(["accept", "cancel", "decline", "complete"]),
19744
19744
  interactionId: IDENTIFIER,
19745
19745
  kind: external_exports.literal(SESSION_ELICITATION_RESOLVED_KIND),
19746
- protocolVersion: PROTOCOL_VERSION,
19747
19746
  sessionId: IDENTIFIER
19748
19747
  }).readonly();
19749
19748
  var sessionOperationFailedEventSchema = external_exports.strictObject({
19750
19749
  code: IDENTIFIER,
19751
19750
  kind: external_exports.literal(SESSION_OPERATION_FAILED_KIND),
19752
19751
  message: external_exports.string().min(1).max(500),
19753
- protocolVersion: PROTOCOL_VERSION,
19754
19752
  requestId: IDENTIFIER,
19755
19753
  sessionId: external_exports.string().max(128)
19756
19754
  }).readonly();
@@ -19760,12 +19758,10 @@ var agentContentEventSchema = external_exports.strictObject({
19760
19758
  contentId: IDENTIFIER,
19761
19759
  kind: external_exports.literal(AGENT_CONTENT_KIND),
19762
19760
  messageId: external_exports.string().max(255),
19763
- protocolVersion: PROTOCOL_VERSION,
19764
19761
  sessionId: IDENTIFIER
19765
19762
  }).readonly();
19766
19763
  var agentInstallIdentityFields = {
19767
19764
  agentId: IDENTIFIER,
19768
- protocolVersion: PROTOCOL_VERSION,
19769
19765
  requestId: IDENTIFIER
19770
19766
  };
19771
19767
  var agentInstallRequestCommandSchema = external_exports.strictObject({
@@ -19774,7 +19770,6 @@ var agentInstallRequestCommandSchema = external_exports.strictObject({
19774
19770
  }).readonly();
19775
19771
  var agentInstallCancelCommandSchema = external_exports.strictObject({
19776
19772
  kind: external_exports.literal(AGENT_INSTALL_CANCEL_KIND),
19777
- protocolVersion: PROTOCOL_VERSION,
19778
19773
  requestId: IDENTIFIER
19779
19774
  }).readonly();
19780
19775
  var agentInstallAwaitingApprovalEventSchema = external_exports.strictObject({
@@ -19840,6 +19835,7 @@ function decodeValue(value, schema) {
19840
19835
  return result.data;
19841
19836
  }
19842
19837
  var decodeAgentDisplayContentValue = (value) => decodeValue(value, displayContentSchema);
19838
+ var decodeRecordedAgentContentValue = (value) => decodeValue(value, recordedDisplayContentSchema);
19843
19839
  var decodePromptImagesValue = (value) => decodeValue(value, external_exports.array(promptImageSchema).max(8).readonly());
19844
19840
  var decodePromptResourcesValue = (value) => decodeValue(value, external_exports.array(promptResourceSchema).max(16).readonly());
19845
19841
  var encode3 = (message, schema) => JSON.stringify(decodeValue(message, schema));
@@ -19879,6 +19875,8 @@ var SESSION_STARTED_KIND = "session.started";
19879
19875
  var AGENT_MESSAGE_DELTA_KIND = "agent.message.delta";
19880
19876
  var AGENT_ACTIVITY_KIND = "agent.activity";
19881
19877
  var AGENT_ACTIVITY_DETAIL_LIMIT = 24e3;
19878
+ var AGENT_ACTIVITY_RECORDED_FIELD_LIMIT = 4e6;
19879
+ var AGENT_ACTIVITY_RECORDED_DETAIL_LIMIT = 6e6;
19882
19880
  var AGENT_ACTIVITY_LOCATION_LIMIT = 12;
19883
19881
  var AGENT_ACTIVITY_LOCATION_LENGTH_LIMIT = 1024;
19884
19882
  var SESSION_COMPLETED_KIND = "session.completed";
@@ -20011,6 +20009,53 @@ function readActivityContent(value) {
20011
20009
  }
20012
20010
  return field.map((entry) => decodeAgentDisplayContentValue(entry));
20013
20011
  }
20012
+ function readActivityDetail(value) {
20013
+ const field = value["detail"];
20014
+ if (!isRecord(field)) {
20015
+ throw new ProtocolMessageError("Invalid activity detail field");
20016
+ }
20017
+ const kind = readString(field, "kind", 32);
20018
+ if (kind === "available") {
20019
+ assertExactKeys(field, ["artifactId", "kind"]);
20020
+ return {
20021
+ artifactId: readIdentifier(field, "artifactId"),
20022
+ kind
20023
+ };
20024
+ }
20025
+ if (kind === "unrecorded") {
20026
+ assertExactKeys(field, ["kind"]);
20027
+ return { kind };
20028
+ }
20029
+ if (kind === "truncated") {
20030
+ assertExactKeys(field, ["capturedBytes", "kind", "originalBytes"]);
20031
+ const capturedBytes = readSequence(field, "capturedBytes");
20032
+ const originalBytes = readSequence(field, "originalBytes");
20033
+ if (capturedBytes > originalBytes) {
20034
+ throw new ProtocolMessageError("Invalid truncated activity detail size");
20035
+ }
20036
+ return { capturedBytes, kind, originalBytes };
20037
+ }
20038
+ if (kind === "recorded") {
20039
+ assertExactKeys(field, ["content", "input", "kind", "output"]);
20040
+ const contentValue = field["content"];
20041
+ if (!Array.isArray(contentValue) || contentValue.length > 100) {
20042
+ throw new ProtocolMessageError("Invalid recorded activity content");
20043
+ }
20044
+ const detail = {
20045
+ content: contentValue.map(
20046
+ (entry) => decodeRecordedAgentContentValue(entry)
20047
+ ),
20048
+ input: readText(field, "input", AGENT_ACTIVITY_RECORDED_FIELD_LIMIT),
20049
+ kind,
20050
+ output: readText(field, "output", AGENT_ACTIVITY_RECORDED_FIELD_LIMIT)
20051
+ };
20052
+ if (JSON.stringify(detail).length > AGENT_ACTIVITY_RECORDED_DETAIL_LIMIT) {
20053
+ throw new ProtocolMessageError("Recorded activity detail is too large");
20054
+ }
20055
+ return detail;
20056
+ }
20057
+ throw new ProtocolMessageError("Invalid activity detail availability");
20058
+ }
20014
20059
  function readIdentifier(value, key) {
20015
20060
  const field = readString(value, key, 128);
20016
20061
  if (!IDENTIFIER_PATTERN2.test(field)) {
@@ -20027,11 +20072,6 @@ function readDirectoryIdentifier(value, key) {
20027
20072
  }
20028
20073
  return field;
20029
20074
  }
20030
- function assertProtocolVersion(value) {
20031
- if (value["protocolVersion"] !== MOBIUS_PROTOCOL_VERSION) {
20032
- throw new ProtocolMessageError("Unsupported protocol version");
20033
- }
20034
- }
20035
20075
  function assertKind(value, expectedKind) {
20036
20076
  if (value["kind"] !== expectedKind) {
20037
20077
  throw new ProtocolMessageError(`Expected message kind: ${expectedKind}`);
@@ -20051,11 +20091,9 @@ function decodeSessionPromptCommand(encoded) {
20051
20091
  "images",
20052
20092
  "kind",
20053
20093
  "prompt",
20054
- "protocolVersion",
20055
20094
  "resources",
20056
20095
  "sessionId"
20057
20096
  ]);
20058
- assertProtocolVersion(value);
20059
20097
  assertKind(value, SESSION_PROMPT_KIND);
20060
20098
  const prompt = readText(value, "prompt", MAX_PROMPT_LENGTH);
20061
20099
  const images = decodePromptImagesValue(value["images"]);
@@ -20080,89 +20118,62 @@ function decodeSessionPromptCommand(encoded) {
20080
20118
  images,
20081
20119
  kind: SESSION_PROMPT_KIND,
20082
20120
  prompt,
20083
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
20084
20121
  resources,
20085
20122
  sessionId: readIdentifier(value, "sessionId")
20086
20123
  };
20087
20124
  }
20088
20125
  function decodeSessionCancelCommand(encoded) {
20089
20126
  const value = parseJson2(encoded);
20090
- assertExactKeys(value, ["commandId", "kind", "protocolVersion", "sessionId"]);
20091
- assertProtocolVersion(value);
20127
+ assertExactKeys(value, ["commandId", "kind", "sessionId"]);
20092
20128
  assertKind(value, SESSION_CANCEL_KIND);
20093
20129
  return {
20094
20130
  commandId: readIdentifier(value, "commandId"),
20095
20131
  kind: SESSION_CANCEL_KIND,
20096
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
20097
20132
  sessionId: readIdentifier(value, "sessionId")
20098
20133
  };
20099
20134
  }
20100
20135
  function decodeRuntimeLivenessReadyEvent(encoded) {
20101
20136
  const value = parseJson2(encoded);
20102
- assertExactKeys(value, ["kind", "protocolVersion"]);
20103
- assertProtocolVersion(value);
20137
+ assertExactKeys(value, ["kind"]);
20104
20138
  assertKind(value, RUNTIME_LIVENESS_READY_KIND);
20105
- return {
20106
- kind: RUNTIME_LIVENESS_READY_KIND,
20107
- protocolVersion: MOBIUS_PROTOCOL_VERSION
20108
- };
20139
+ return { kind: RUNTIME_LIVENESS_READY_KIND };
20109
20140
  }
20110
20141
  function decodeRuntimeHeartbeatEvent(encoded) {
20111
20142
  const value = parseJson2(encoded);
20112
- assertExactKeys(value, ["heartbeatId", "kind", "protocolVersion"]);
20113
- assertProtocolVersion(value);
20143
+ assertExactKeys(value, ["heartbeatId", "kind"]);
20114
20144
  assertKind(value, RUNTIME_HEARTBEAT_KIND);
20115
20145
  return {
20116
20146
  heartbeatId: readIdentifier(value, "heartbeatId"),
20117
- kind: RUNTIME_HEARTBEAT_KIND,
20118
- protocolVersion: MOBIUS_PROTOCOL_VERSION
20147
+ kind: RUNTIME_HEARTBEAT_KIND
20119
20148
  };
20120
20149
  }
20121
20150
  function decodeRuntimeHeartbeatAckEvent(encoded) {
20122
20151
  const value = parseJson2(encoded);
20123
- assertExactKeys(value, ["heartbeatId", "kind", "protocolVersion"]);
20124
- assertProtocolVersion(value);
20152
+ assertExactKeys(value, ["heartbeatId", "kind"]);
20125
20153
  assertKind(value, RUNTIME_HEARTBEAT_ACK_KIND);
20126
20154
  return {
20127
20155
  heartbeatId: readIdentifier(value, "heartbeatId"),
20128
- kind: RUNTIME_HEARTBEAT_ACK_KIND,
20129
- protocolVersion: MOBIUS_PROTOCOL_VERSION
20156
+ kind: RUNTIME_HEARTBEAT_ACK_KIND
20130
20157
  };
20131
20158
  }
20132
20159
  function decodeSessionStartedEvent(encoded) {
20133
20160
  const value = parseJson2(encoded);
20134
- assertExactKeys(value, [
20135
- "commandId",
20136
- "kind",
20137
- "processAttemptId",
20138
- "protocolVersion",
20139
- "sessionId"
20140
- ]);
20141
- assertProtocolVersion(value);
20161
+ assertExactKeys(value, ["commandId", "kind", "attemptId", "sessionId"]);
20142
20162
  assertKind(value, SESSION_STARTED_KIND);
20143
20163
  return {
20144
20164
  commandId: readIdentifier(value, "commandId"),
20145
20165
  kind: SESSION_STARTED_KIND,
20146
- processAttemptId: readIdentifier(value, "processAttemptId"),
20147
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
20166
+ attemptId: readIdentifier(value, "attemptId"),
20148
20167
  sessionId: readIdentifier(value, "sessionId")
20149
20168
  };
20150
20169
  }
20151
20170
  function decodeAgentMessageDeltaEvent(encoded) {
20152
20171
  const value = parseJson2(encoded);
20153
- assertExactKeys(value, [
20154
- "commandId",
20155
- "kind",
20156
- "protocolVersion",
20157
- "sessionId",
20158
- "text"
20159
- ]);
20160
- assertProtocolVersion(value);
20172
+ assertExactKeys(value, ["commandId", "kind", "sessionId", "text"]);
20161
20173
  assertKind(value, AGENT_MESSAGE_DELTA_KIND);
20162
20174
  return {
20163
20175
  commandId: readIdentifier(value, "commandId"),
20164
20176
  kind: AGENT_MESSAGE_DELTA_KIND,
20165
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
20166
20177
  sessionId: readIdentifier(value, "sessionId"),
20167
20178
  text: readString(value, "text", MAX_EVENT_TEXT_LENGTH)
20168
20179
  };
@@ -20174,31 +20185,30 @@ function decodeAgentActivityEvent(encoded) {
20174
20185
  "activityType",
20175
20186
  "commandId",
20176
20187
  "content",
20188
+ "detail",
20177
20189
  "input",
20178
20190
  "kind",
20179
20191
  "locations",
20180
20192
  "name",
20181
20193
  "output",
20182
- "protocolVersion",
20183
20194
  "sequence",
20184
20195
  "sessionId",
20185
20196
  "status",
20186
20197
  "title",
20187
20198
  "toolKind"
20188
20199
  ]);
20189
- assertProtocolVersion(value);
20190
20200
  assertKind(value, AGENT_ACTIVITY_KIND);
20191
20201
  return {
20192
20202
  activityId: readIdentifier(value, "activityId"),
20193
20203
  activityType: readAllowedString(value, "activityType", ACTIVITY_TYPES),
20194
20204
  commandId: readIdentifier(value, "commandId"),
20195
20205
  content: readActivityContent(value),
20206
+ detail: readActivityDetail(value),
20196
20207
  input: readText(value, "input", AGENT_ACTIVITY_DETAIL_LIMIT),
20197
20208
  kind: AGENT_ACTIVITY_KIND,
20198
20209
  locations: readLocations(value),
20199
20210
  name: readText(value, "name", 128),
20200
20211
  output: readText(value, "output", AGENT_ACTIVITY_DETAIL_LIMIT),
20201
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
20202
20212
  sequence: readSequence(value, "sequence"),
20203
20213
  sessionId: readIdentifier(value, "sessionId"),
20204
20214
  status: readAllowedString(value, "status", ACTIVITY_STATUSES),
@@ -20208,41 +20218,24 @@ function decodeAgentActivityEvent(encoded) {
20208
20218
  }
20209
20219
  function decodeSessionCompletedEvent(encoded) {
20210
20220
  const value = parseJson2(encoded);
20211
- assertExactKeys(value, [
20212
- "commandId",
20213
- "kind",
20214
- "protocolVersion",
20215
- "sessionId",
20216
- "stopReason"
20217
- ]);
20218
- assertProtocolVersion(value);
20221
+ assertExactKeys(value, ["commandId", "kind", "sessionId", "stopReason"]);
20219
20222
  assertKind(value, SESSION_COMPLETED_KIND);
20220
20223
  return {
20221
20224
  commandId: readIdentifier(value, "commandId"),
20222
20225
  kind: SESSION_COMPLETED_KIND,
20223
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
20224
20226
  sessionId: readIdentifier(value, "sessionId"),
20225
20227
  stopReason: readString(value, "stopReason", 64)
20226
20228
  };
20227
20229
  }
20228
20230
  function decodeSessionFailedEvent(encoded) {
20229
20231
  const value = parseJson2(encoded);
20230
- assertExactKeys(value, [
20231
- "code",
20232
- "commandId",
20233
- "kind",
20234
- "message",
20235
- "protocolVersion",
20236
- "sessionId"
20237
- ]);
20238
- assertProtocolVersion(value);
20232
+ assertExactKeys(value, ["code", "commandId", "kind", "message", "sessionId"]);
20239
20233
  assertKind(value, SESSION_FAILED_KIND);
20240
20234
  return {
20241
20235
  code: readIdentifier(value, "code"),
20242
20236
  commandId: readIdentifier(value, "commandId"),
20243
20237
  kind: SESSION_FAILED_KIND,
20244
20238
  message: readString(value, "message", 500),
20245
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
20246
20239
  sessionId: readIdentifier(value, "sessionId")
20247
20240
  };
20248
20241
  }
@@ -20332,7 +20325,6 @@ var NATIVE_SESSION_CANCEL_KIND = "native.session.cancel";
20332
20325
  var identifier = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/);
20333
20326
  var directoryId = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/);
20334
20327
  var envelope = {
20335
- protocolVersion: external_exports.literal(MOBIUS_PROTOCOL_VERSION),
20336
20328
  requestId: identifier,
20337
20329
  sessionId: identifier
20338
20330
  };
@@ -20387,6 +20379,7 @@ var nativeSessionResultSchema = external_exports.discriminatedUnion("action", [
20387
20379
  external_exports.strictObject({
20388
20380
  ...resultEnvelope,
20389
20381
  action: external_exports.enum(["import", "fork"]),
20382
+ targetSessionId: identifier,
20390
20383
  ready: sessionReadyEventSchema,
20391
20384
  history: sessionHistorySchema,
20392
20385
  title: external_exports.string().max(500)
@@ -20395,6 +20388,7 @@ var nativeSessionResultSchema = external_exports.discriminatedUnion("action", [
20395
20388
  ...resultEnvelope,
20396
20389
  action: external_exports.literal("preview"),
20397
20390
  entryId: identifier,
20391
+ targetSessionId: identifier,
20398
20392
  reason: external_exports.literal("continuation_unavailable"),
20399
20393
  history: sessionHistorySchema,
20400
20394
  title: external_exports.string().max(500)
@@ -20419,6 +20413,563 @@ var decodeNativeSessionCommand = (encoded) => decode4(nativeSessionCommandSchema
20419
20413
  var encodeNativeSessionResult = (value) => JSON.stringify(nativeSessionResultSchema.parse(value));
20420
20414
  var decodeNativeSessionCancel = (encoded) => decode4(nativeSessionCancelSchema, encoded);
20421
20415
 
20416
+ // ../protocol/src/resource-model.ts
20417
+ var IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
20418
+ var DECIMAL_SEQUENCE_PATTERN = /^(?:0|[1-9][0-9]*)$/;
20419
+ var SHA256_PATTERN = /^[a-f0-9]{64}$/;
20420
+ var identifierSchema = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN3);
20421
+ var timestampSchema = external_exports.string().datetime({ offset: true });
20422
+ var decimalSequenceSchema = external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN);
20423
+ var digestSchema = external_exports.string().length(64).regex(SHA256_PATTERN);
20424
+ var recordingPolicySchema = external_exports.strictObject({
20425
+ contentLimitBytes: external_exports.number().int().positive().safe(),
20426
+ hotEventLimit: external_exports.number().int().positive().safe(),
20427
+ idempotencyRetentionMilliseconds: external_exports.number().int().positive().safe(),
20428
+ level: external_exports.enum(["full", "summary"]),
20429
+ retentionMilliseconds: external_exports.number().int().positive().safe()
20430
+ }).readonly();
20431
+ var tenantLifecycleSchema = external_exports.discriminatedUnion("kind", [
20432
+ external_exports.strictObject({ kind: external_exports.literal("active") }).readonly(),
20433
+ external_exports.strictObject({
20434
+ kind: external_exports.literal("suspended"),
20435
+ suspendedAt: timestampSchema
20436
+ }).readonly(),
20437
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
20438
+ ]);
20439
+ var tenantSchema = external_exports.strictObject({
20440
+ lifecycle: tenantLifecycleSchema,
20441
+ quotaPolicyRevision: external_exports.number().int().nonnegative().safe(),
20442
+ recordingPolicy: recordingPolicySchema,
20443
+ tenantId: identifierSchema
20444
+ }).readonly();
20445
+ var projectLifecycleSchema = external_exports.discriminatedUnion("kind", [
20446
+ external_exports.strictObject({ kind: external_exports.literal("active") }).readonly(),
20447
+ external_exports.strictObject({ archivedAt: timestampSchema, kind: external_exports.literal("archived") }).readonly(),
20448
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
20449
+ ]);
20450
+ var projectSchema = external_exports.strictObject({
20451
+ displayName: external_exports.string().min(1).max(120),
20452
+ lifecycle: projectLifecycleSchema,
20453
+ projectId: identifierSchema,
20454
+ tenantId: identifierSchema
20455
+ }).readonly();
20456
+ var runtimeLifecycleSchema = external_exports.discriminatedUnion("kind", [
20457
+ external_exports.strictObject({ kind: external_exports.literal("registered") }).readonly(),
20458
+ external_exports.strictObject({ disabledAt: timestampSchema, kind: external_exports.literal("disabled") }).readonly(),
20459
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
20460
+ ]);
20461
+ var runtimeCapabilitySchema = external_exports.strictObject({
20462
+ name: identifierSchema,
20463
+ revision: external_exports.number().int().nonnegative().safe()
20464
+ }).readonly();
20465
+ var runtimeSchema = external_exports.strictObject({
20466
+ capabilities: external_exports.array(runtimeCapabilitySchema).max(100).readonly(),
20467
+ displayName: external_exports.string().min(1).max(120),
20468
+ lifecycle: runtimeLifecycleSchema,
20469
+ runtimeId: identifierSchema,
20470
+ tenantId: identifierSchema
20471
+ }).readonly();
20472
+ var channelStateSchema = external_exports.discriminatedUnion("kind", [
20473
+ external_exports.strictObject({
20474
+ connectionEpoch: external_exports.number().int().nonnegative().safe(),
20475
+ connectedAt: timestampSchema,
20476
+ connectionId: identifierSchema,
20477
+ kind: external_exports.literal("online")
20478
+ }).readonly(),
20479
+ external_exports.strictObject({
20480
+ connectionEpoch: external_exports.number().int().nonnegative().safe(),
20481
+ disconnectedAt: timestampSchema,
20482
+ kind: external_exports.literal("offline")
20483
+ }).readonly()
20484
+ ]);
20485
+ var channelSchema = external_exports.strictObject({
20486
+ channelId: identifierSchema,
20487
+ runtimeId: identifierSchema,
20488
+ state: channelStateSchema
20489
+ }).readonly();
20490
+ var sessionLifecycleSchema = external_exports.discriminatedUnion("kind", [
20491
+ external_exports.strictObject({ kind: external_exports.literal("ready") }).readonly(),
20492
+ external_exports.strictObject({ kind: external_exports.literal("deleting"), requestedAt: timestampSchema }).readonly(),
20493
+ external_exports.strictObject({ completedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
20494
+ ]);
20495
+ var sessionSchema = external_exports.strictObject({
20496
+ createdAt: timestampSchema,
20497
+ createdBy: identifierSchema,
20498
+ defaultBindingId: identifierSchema,
20499
+ lastCommittedSeq: decimalSequenceSchema,
20500
+ lifecycle: sessionLifecycleSchema,
20501
+ projectId: identifierSchema,
20502
+ sessionId: identifierSchema,
20503
+ tenantId: identifierSchema
20504
+ }).readonly();
20505
+ var sessionBindingSchema = external_exports.strictObject({
20506
+ agentRef: identifierSchema,
20507
+ bindingId: identifierSchema,
20508
+ configRevision: external_exports.number().int().nonnegative().safe(),
20509
+ createdAt: timestampSchema,
20510
+ runtimeId: identifierSchema,
20511
+ sessionId: identifierSchema,
20512
+ workspaceRef: identifierSchema
20513
+ }).readonly();
20514
+ var domainErrorSchema = external_exports.strictObject({
20515
+ code: identifierSchema,
20516
+ message: external_exports.string().min(1).max(2e3),
20517
+ retryable: external_exports.boolean()
20518
+ }).readonly();
20519
+ var executionResultSchema = external_exports.strictObject({
20520
+ kind: external_exports.literal("agent_result"),
20521
+ stopReason: external_exports.string().min(1).max(128)
20522
+ }).readonly();
20523
+ var reconciliationSchema = external_exports.strictObject({
20524
+ detectedAt: timestampSchema,
20525
+ reason: external_exports.enum([
20526
+ "connection_lost",
20527
+ "dispatch_indeterminate",
20528
+ "runtime_restarted"
20529
+ ])
20530
+ }).readonly();
20531
+ var turnStateSchema = external_exports.discriminatedUnion("kind", [
20532
+ external_exports.strictObject({ kind: external_exports.literal("queued") }).readonly(),
20533
+ external_exports.strictObject({ kind: external_exports.literal("running"), startedAt: timestampSchema }).readonly(),
20534
+ external_exports.strictObject({
20535
+ completedAt: timestampSchema,
20536
+ kind: external_exports.literal("succeeded"),
20537
+ result: executionResultSchema
20538
+ }).readonly(),
20539
+ external_exports.strictObject({
20540
+ error: domainErrorSchema,
20541
+ failedAt: timestampSchema,
20542
+ kind: external_exports.literal("failed")
20543
+ }).readonly(),
20544
+ external_exports.strictObject({
20545
+ cancelledAt: timestampSchema,
20546
+ kind: external_exports.literal("cancelled")
20547
+ }).readonly(),
20548
+ external_exports.strictObject({
20549
+ kind: external_exports.literal("indeterminate"),
20550
+ reconciliation: reconciliationSchema
20551
+ }).readonly()
20552
+ ]);
20553
+ var turnRequestSchema = external_exports.discriminatedUnion("kind", [
20554
+ external_exports.strictObject({
20555
+ content: external_exports.string().max(1e5),
20556
+ kind: external_exports.literal("prompt")
20557
+ }).readonly()
20558
+ ]);
20559
+ var turnSchema = external_exports.strictObject({
20560
+ acceptedAt: timestampSchema,
20561
+ bindingId: identifierSchema,
20562
+ idempotencyKey: identifierSchema,
20563
+ request: turnRequestSchema,
20564
+ sessionId: identifierSchema,
20565
+ state: turnStateSchema,
20566
+ turnId: identifierSchema
20567
+ }).readonly();
20568
+ var attemptStateSchema = external_exports.discriminatedUnion("kind", [
20569
+ external_exports.strictObject({
20570
+ dispatchedAt: timestampSchema,
20571
+ kind: external_exports.literal("dispatching")
20572
+ }).readonly(),
20573
+ external_exports.strictObject({ kind: external_exports.literal("running"), startedAt: timestampSchema }).readonly(),
20574
+ external_exports.strictObject({
20575
+ interactionIds: external_exports.array(identifierSchema).min(1).max(100).readonly(),
20576
+ kind: external_exports.literal("waiting_input"),
20577
+ startedAt: timestampSchema
20578
+ }).readonly(),
20579
+ external_exports.strictObject({
20580
+ completedAt: timestampSchema,
20581
+ kind: external_exports.literal("succeeded"),
20582
+ result: executionResultSchema,
20583
+ startedAt: timestampSchema
20584
+ }).readonly(),
20585
+ external_exports.strictObject({
20586
+ error: domainErrorSchema,
20587
+ failedAt: timestampSchema,
20588
+ kind: external_exports.literal("failed"),
20589
+ startedAt: timestampSchema
20590
+ }).readonly(),
20591
+ external_exports.strictObject({
20592
+ cancelledAt: timestampSchema,
20593
+ kind: external_exports.literal("cancelled"),
20594
+ startedAt: timestampSchema
20595
+ }).readonly(),
20596
+ external_exports.strictObject({
20597
+ kind: external_exports.literal("indeterminate"),
20598
+ reconciliation: reconciliationSchema,
20599
+ startedAt: timestampSchema
20600
+ }).readonly()
20601
+ ]);
20602
+ var attemptSchema = external_exports.strictObject({
20603
+ attemptId: identifierSchema,
20604
+ bindingId: identifierSchema,
20605
+ sessionId: identifierSchema,
20606
+ state: attemptStateSchema,
20607
+ turnId: identifierSchema
20608
+ }).readonly();
20609
+ var permissionRequestSchema = external_exports.strictObject({
20610
+ kind: external_exports.literal("permission"),
20611
+ options: external_exports.array(permissionOptionSchema).min(1).max(20).readonly(),
20612
+ title: external_exports.string().min(1).max(500),
20613
+ toolCallId: external_exports.string().min(1).max(255),
20614
+ toolKind: external_exports.string().max(64)
20615
+ }).readonly();
20616
+ var elicitationRequestSchema = external_exports.strictObject({
20617
+ elicitationId: external_exports.string().max(255),
20618
+ fields: external_exports.array(elicitationFieldSchema).max(100).readonly(),
20619
+ kind: external_exports.literal("elicitation"),
20620
+ message: external_exports.string().min(1).max(2e3),
20621
+ mode: external_exports.enum(["form", "url"]),
20622
+ url: external_exports.string().max(4096)
20623
+ }).readonly();
20624
+ var interactionRequestSchema = external_exports.discriminatedUnion("kind", [
20625
+ permissionRequestSchema,
20626
+ elicitationRequestSchema
20627
+ ]);
20628
+ var interactionResponseSchema = external_exports.strictObject({
20629
+ content: external_exports.string().max(1e5),
20630
+ kind: external_exports.enum(["permission", "elicitation"])
20631
+ }).readonly();
20632
+ var interactionStateSchema = external_exports.discriminatedUnion("kind", [
20633
+ external_exports.strictObject({ kind: external_exports.literal("pending") }).readonly(),
20634
+ external_exports.strictObject({
20635
+ kind: external_exports.literal("responded"),
20636
+ respondedAt: timestampSchema,
20637
+ responderId: identifierSchema,
20638
+ response: interactionResponseSchema
20639
+ }).readonly(),
20640
+ external_exports.strictObject({
20641
+ kind: external_exports.literal("resolved"),
20642
+ resolution: external_exports.discriminatedUnion("kind", [
20643
+ external_exports.strictObject({ kind: external_exports.literal("without_response") }).readonly(),
20644
+ external_exports.strictObject({
20645
+ kind: external_exports.literal("response_applied"),
20646
+ respondedAt: timestampSchema,
20647
+ responderId: identifierSchema,
20648
+ response: interactionResponseSchema
20649
+ }).readonly()
20650
+ ]),
20651
+ resolvedAt: timestampSchema
20652
+ }).readonly(),
20653
+ external_exports.strictObject({ expiredAt: timestampSchema, kind: external_exports.literal("expired") }).readonly(),
20654
+ external_exports.strictObject({
20655
+ cancelledAt: timestampSchema,
20656
+ kind: external_exports.literal("cancelled")
20657
+ }).readonly()
20658
+ ]);
20659
+ var interactionSchema = external_exports.strictObject({
20660
+ attemptId: identifierSchema,
20661
+ interactionId: identifierSchema,
20662
+ request: interactionRequestSchema,
20663
+ sessionId: identifierSchema,
20664
+ state: interactionStateSchema,
20665
+ turnId: identifierSchema
20666
+ }).readonly();
20667
+ var recordingCompletenessSchema = external_exports.discriminatedUnion("kind", [
20668
+ external_exports.strictObject({ kind: external_exports.literal("complete") }).readonly(),
20669
+ external_exports.strictObject({
20670
+ capturedBytes: external_exports.number().int().nonnegative().safe(),
20671
+ kind: external_exports.literal("truncated"),
20672
+ originalBytes: external_exports.number().int().positive().safe()
20673
+ }).readonly(),
20674
+ external_exports.strictObject({ kind: external_exports.literal("redacted"), reason: identifierSchema }).readonly(),
20675
+ external_exports.strictObject({ kind: external_exports.literal("uncaptured") }).readonly()
20676
+ ]);
20677
+ var messageViewStateSchema = external_exports.discriminatedUnion("kind", [
20678
+ external_exports.strictObject({ kind: external_exports.literal("building") }).readonly(),
20679
+ external_exports.strictObject({
20680
+ completeness: recordingCompletenessSchema,
20681
+ kind: external_exports.literal("available")
20682
+ }).readonly(),
20683
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
20684
+ ]);
20685
+ var messageViewCommon = {
20686
+ contentArtifactIds: external_exports.array(identifierSchema).max(100).readonly(),
20687
+ lastAppliedSeq: decimalSequenceSchema,
20688
+ messageId: identifierSchema,
20689
+ preview: external_exports.string().max(4e3),
20690
+ sessionId: identifierSchema,
20691
+ state: messageViewStateSchema
20692
+ };
20693
+ var messageViewSchema = external_exports.discriminatedUnion("role", [
20694
+ external_exports.strictObject({
20695
+ ...messageViewCommon,
20696
+ role: external_exports.literal("user"),
20697
+ source: external_exports.strictObject({ kind: external_exports.literal("turn"), turnId: identifierSchema }).readonly()
20698
+ }).readonly(),
20699
+ external_exports.strictObject({
20700
+ ...messageViewCommon,
20701
+ role: external_exports.literal("agent"),
20702
+ source: external_exports.strictObject({
20703
+ attemptId: identifierSchema,
20704
+ kind: external_exports.literal("attempt"),
20705
+ turnId: identifierSchema
20706
+ }).readonly()
20707
+ }).readonly(),
20708
+ external_exports.strictObject({
20709
+ ...messageViewCommon,
20710
+ role: external_exports.literal("tool"),
20711
+ source: external_exports.strictObject({
20712
+ attemptId: identifierSchema,
20713
+ kind: external_exports.literal("tool_call"),
20714
+ toolCallId: identifierSchema,
20715
+ turnId: identifierSchema
20716
+ }).readonly()
20717
+ }).readonly(),
20718
+ external_exports.strictObject({
20719
+ ...messageViewCommon,
20720
+ role: external_exports.literal("system"),
20721
+ source: external_exports.strictObject({ kind: external_exports.literal("system") }).readonly()
20722
+ }).readonly()
20723
+ ]);
20724
+ var toolCallDetailSchema = external_exports.discriminatedUnion("kind", [
20725
+ external_exports.strictObject({
20726
+ artifactId: identifierSchema,
20727
+ kind: external_exports.literal("available")
20728
+ }).readonly(),
20729
+ external_exports.strictObject({
20730
+ capturedBytes: external_exports.number().int().nonnegative().safe(),
20731
+ kind: external_exports.literal("truncated"),
20732
+ originalBytes: external_exports.number().int().positive().safe()
20733
+ }).readonly(),
20734
+ external_exports.strictObject({ kind: external_exports.literal("uncaptured") }).readonly(),
20735
+ external_exports.strictObject({ deletedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
20736
+ ]);
20737
+ var toolCallViewStateSchema = external_exports.discriminatedUnion("kind", [
20738
+ external_exports.strictObject({ kind: external_exports.literal("pending") }).readonly(),
20739
+ external_exports.strictObject({ kind: external_exports.literal("running"), startedAt: timestampSchema }).readonly(),
20740
+ external_exports.strictObject({
20741
+ completedAt: timestampSchema,
20742
+ kind: external_exports.literal("succeeded")
20743
+ }).readonly(),
20744
+ external_exports.strictObject({
20745
+ error: domainErrorSchema,
20746
+ failedAt: timestampSchema,
20747
+ kind: external_exports.literal("failed")
20748
+ }).readonly(),
20749
+ external_exports.strictObject({
20750
+ cancelledAt: timestampSchema,
20751
+ kind: external_exports.literal("cancelled")
20752
+ }).readonly()
20753
+ ]);
20754
+ var toolCallViewSchema = external_exports.strictObject({
20755
+ attemptId: identifierSchema,
20756
+ detail: toolCallDetailSchema,
20757
+ inputPreview: external_exports.string().max(4e3),
20758
+ lastAppliedSeq: decimalSequenceSchema,
20759
+ name: external_exports.string().max(128),
20760
+ outputPreview: external_exports.string().max(4e3),
20761
+ state: toolCallViewStateSchema,
20762
+ title: external_exports.string().min(1).max(500),
20763
+ toolCallId: identifierSchema,
20764
+ toolKind: identifierSchema
20765
+ }).readonly();
20766
+ var sessionListEntrySchema = external_exports.strictObject({
20767
+ lastAppliedSeq: decimalSequenceSchema,
20768
+ preview: external_exports.string().max(4e3),
20769
+ projectId: identifierSchema,
20770
+ projectedAttemptState: external_exports.enum([
20771
+ "idle",
20772
+ "dispatching",
20773
+ "running",
20774
+ "waiting_input",
20775
+ "indeterminate"
20776
+ ]),
20777
+ sessionId: identifierSchema,
20778
+ tenantId: identifierSchema,
20779
+ title: external_exports.string().max(500),
20780
+ updatedAt: timestampSchema
20781
+ }).readonly();
20782
+ var artifactStateSchema = external_exports.discriminatedUnion("kind", [
20783
+ external_exports.strictObject({
20784
+ expectedBytes: external_exports.number().int().nonnegative().safe(),
20785
+ expiresAt: timestampSchema,
20786
+ kind: external_exports.literal("uploading"),
20787
+ uploadId: identifierSchema
20788
+ }).readonly(),
20789
+ external_exports.strictObject({
20790
+ availableAt: timestampSchema,
20791
+ byteLength: external_exports.number().int().nonnegative().safe(),
20792
+ kind: external_exports.literal("available"),
20793
+ sha256: digestSchema
20794
+ }).readonly(),
20795
+ external_exports.strictObject({ kind: external_exports.literal("deleting"), requestedAt: timestampSchema }).readonly(),
20796
+ external_exports.strictObject({ completedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly(),
20797
+ external_exports.strictObject({
20798
+ error: domainErrorSchema,
20799
+ failedAt: timestampSchema,
20800
+ kind: external_exports.literal("failed")
20801
+ }).readonly(),
20802
+ external_exports.strictObject({ expiredAt: timestampSchema, kind: external_exports.literal("expired") }).readonly()
20803
+ ]);
20804
+ var artifactSchema = external_exports.strictObject({
20805
+ artifactId: identifierSchema,
20806
+ completeness: recordingCompletenessSchema,
20807
+ contentKind: identifierSchema,
20808
+ mediaType: external_exports.string().min(1).max(128),
20809
+ projectId: identifierSchema,
20810
+ provenance: external_exports.discriminatedUnion("kind", [
20811
+ external_exports.strictObject({ kind: external_exports.literal("user_upload") }).readonly(),
20812
+ external_exports.strictObject({
20813
+ attemptId: identifierSchema,
20814
+ kind: external_exports.literal("tool_call"),
20815
+ toolCallId: identifierSchema,
20816
+ turnId: identifierSchema
20817
+ }).readonly(),
20818
+ external_exports.strictObject({
20819
+ attemptId: identifierSchema,
20820
+ kind: external_exports.literal("agent_generated"),
20821
+ turnId: identifierSchema
20822
+ }).readonly()
20823
+ ]),
20824
+ sessionId: identifierSchema,
20825
+ state: artifactStateSchema,
20826
+ tenantId: identifierSchema
20827
+ }).readonly();
20828
+ var archiveSegmentStateSchema = external_exports.discriminatedUnion("kind", [
20829
+ external_exports.strictObject({ kind: external_exports.literal("pending"), queuedAt: timestampSchema }).readonly(),
20830
+ external_exports.strictObject({
20831
+ byteLength: external_exports.number().int().nonnegative().safe(),
20832
+ kind: external_exports.literal("uploaded"),
20833
+ sha256: digestSchema,
20834
+ uploadedAt: timestampSchema
20835
+ }).readonly(),
20836
+ external_exports.strictObject({
20837
+ byteLength: external_exports.number().int().nonnegative().safe(),
20838
+ kind: external_exports.literal("published"),
20839
+ publishedAt: timestampSchema,
20840
+ sha256: digestSchema
20841
+ }).readonly(),
20842
+ external_exports.strictObject({ kind: external_exports.literal("deleting"), requestedAt: timestampSchema }).readonly(),
20843
+ external_exports.strictObject({ completedAt: timestampSchema, kind: external_exports.literal("deleted") }).readonly()
20844
+ ]);
20845
+ var archiveSegmentSchema = external_exports.strictObject({
20846
+ compression: external_exports.literal("gzip"),
20847
+ eventCount: external_exports.number().int().positive().safe(),
20848
+ firstSeq: decimalSequenceSchema,
20849
+ lastSeq: decimalSequenceSchema,
20850
+ segmentId: identifierSchema,
20851
+ sessionId: identifierSchema,
20852
+ state: archiveSegmentStateSchema
20853
+ }).readonly();
20854
+ var pendingWorkStateSchema = external_exports.discriminatedUnion("kind", [
20855
+ external_exports.strictObject({ kind: external_exports.literal("pending"), queuedAt: timestampSchema }).readonly(),
20856
+ external_exports.strictObject({
20857
+ attempt: external_exports.number().int().positive().safe(),
20858
+ kind: external_exports.literal("running"),
20859
+ startedAt: timestampSchema
20860
+ }).readonly(),
20861
+ external_exports.strictObject({
20862
+ completedAt: timestampSchema,
20863
+ kind: external_exports.literal("completed")
20864
+ }).readonly(),
20865
+ external_exports.strictObject({
20866
+ error: domainErrorSchema,
20867
+ kind: external_exports.literal("retryable"),
20868
+ nextAttemptAt: timestampSchema
20869
+ }).readonly(),
20870
+ external_exports.strictObject({
20871
+ error: domainErrorSchema,
20872
+ failedAt: timestampSchema,
20873
+ kind: external_exports.literal("failed")
20874
+ }).readonly()
20875
+ ]);
20876
+ var pendingWorkSchema = external_exports.strictObject({
20877
+ kind: external_exports.enum([
20878
+ "archive",
20879
+ "delete",
20880
+ "dispatch",
20881
+ "interaction_response",
20882
+ "projection"
20883
+ ]),
20884
+ projectId: identifierSchema,
20885
+ sessionId: identifierSchema,
20886
+ state: pendingWorkStateSchema,
20887
+ tenantId: identifierSchema,
20888
+ workId: identifierSchema
20889
+ }).readonly();
20890
+ var commandReceiptSchema = external_exports.strictObject({
20891
+ acceptedAt: timestampSchema,
20892
+ commandKind: identifierSchema,
20893
+ expiresAt: timestampSchema,
20894
+ idempotencyKey: identifierSchema,
20895
+ projectId: identifierSchema,
20896
+ requestHash: digestSchema,
20897
+ resultId: identifierSchema,
20898
+ sessionId: identifierSchema,
20899
+ tenantId: identifierSchema
20900
+ }).readonly();
20901
+
20902
+ // ../protocol/src/session-events.ts
20903
+ var SESSION_EVENT_KIND = "session.event";
20904
+ var SESSION_EVENT_ACK_KIND = "session.event.ack";
20905
+ var SESSION_EVENT_COMMITTED_KIND = "session.event.committed";
20906
+ var IDENTIFIER_PATTERN4 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
20907
+ var CURSOR_PATTERN = /^[A-Za-z0-9_-]{1,512}$/;
20908
+ var MAX_RECORDED_EVENT_LENGTH = 8 * 1024 * 1024;
20909
+ var DECIMAL_SEQUENCE_PATTERN2 = /^(?:0|[1-9][0-9]*)$/;
20910
+ var eventSourceSchema = external_exports.discriminatedUnion("kind", [
20911
+ external_exports.strictObject({
20912
+ attemptId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
20913
+ kind: external_exports.literal("attempt"),
20914
+ sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2)
20915
+ }).readonly(),
20916
+ external_exports.strictObject({
20917
+ kind: external_exports.literal("runtime"),
20918
+ sourceSeq: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2)
20919
+ }).readonly()
20920
+ ]);
20921
+ var eventEnvelopeSchema = external_exports.strictObject({
20922
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
20923
+ kind: external_exports.literal(SESSION_EVENT_KIND),
20924
+ payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
20925
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
20926
+ source: eventSourceSchema
20927
+ }).readonly();
20928
+ var committedEventSchema = external_exports.strictObject({
20929
+ cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
20930
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
20931
+ kind: external_exports.literal(SESSION_EVENT_COMMITTED_KIND),
20932
+ payload: external_exports.string().min(2).max(MAX_RECORDED_EVENT_LENGTH),
20933
+ recordedAt: external_exports.string().datetime({ offset: true }),
20934
+ sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2),
20935
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
20936
+ source: eventSourceSchema
20937
+ }).readonly();
20938
+ var eventAcknowledgementSchema = external_exports.strictObject({
20939
+ cursor: external_exports.string().min(1).max(512).regex(CURSOR_PATTERN),
20940
+ duplicate: external_exports.boolean(),
20941
+ eventId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4),
20942
+ kind: external_exports.literal(SESSION_EVENT_ACK_KIND),
20943
+ sequence: external_exports.string().min(1).max(40).regex(DECIMAL_SEQUENCE_PATTERN2),
20944
+ sessionId: external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN4)
20945
+ }).readonly();
20946
+ function decode5(encoded, schema) {
20947
+ let value;
20948
+ try {
20949
+ value = JSON.parse(encoded);
20950
+ } catch (cause) {
20951
+ throw new ProtocolMessageError("Message is not valid JSON", { cause });
20952
+ }
20953
+ const decoded = schema.safeParse(value);
20954
+ if (!decoded.success) {
20955
+ throw new ProtocolMessageError("Message does not match its schema", {
20956
+ cause: decoded.error
20957
+ });
20958
+ }
20959
+ return decoded.data;
20960
+ }
20961
+ var encode4 = (message, schema) => {
20962
+ const decoded = schema.safeParse(message);
20963
+ if (!decoded.success) {
20964
+ throw new ProtocolMessageError("Message does not match its schema", {
20965
+ cause: decoded.error
20966
+ });
20967
+ }
20968
+ return JSON.stringify(decoded.data);
20969
+ };
20970
+ var encodeSessionEventEnvelope = (message) => encode4(message, eventEnvelopeSchema);
20971
+ var decodeSessionEventAcknowledgement = (encoded) => decode5(encoded, eventAcknowledgementSchema);
20972
+
20422
20973
  // src/acp/activity.ts
20423
20974
  var TRUNCATION_MARKER = "\n\u2026 output truncated by Mobius";
20424
20975
  function isRecord2(value) {
@@ -20436,7 +20987,12 @@ var AcpActivity = class _AcpActivity {
20436
20987
  title;
20437
20988
  toolKind;
20438
20989
  content;
20439
- constructor(activityId, activityType, input2, locations, name, output2, sequence, status, title, toolKind, content = []) {
20990
+ detail;
20991
+ constructor(activityId, activityType, input2, locations, name, output2, sequence, status, title2, toolKind, content = [], detail = captureActivityDetail(
20992
+ content,
20993
+ input2,
20994
+ output2
20995
+ )) {
20440
20996
  this.activityId = activityId;
20441
20997
  this.activityType = activityType;
20442
20998
  this.input = input2;
@@ -20445,9 +21001,10 @@ var AcpActivity = class _AcpActivity {
20445
21001
  this.output = output2;
20446
21002
  this.sequence = sequence;
20447
21003
  this.status = status;
20448
- this.title = title;
21004
+ this.title = title2;
20449
21005
  this.toolKind = toolKind;
20450
21006
  this.content = content;
21007
+ this.detail = detail;
20451
21008
  }
20452
21009
  complete = () => (this.activityType === "progress" || this.activityType === "reasoning") && (this.status === "pending" || this.status === "running") ? new _AcpActivity(
20453
21010
  this.activityId,
@@ -20460,7 +21017,8 @@ var AcpActivity = class _AcpActivity {
20460
21017
  "completed",
20461
21018
  this.title,
20462
21019
  this.toolKind,
20463
- this.content
21020
+ this.content,
21021
+ this.detail
20464
21022
  ) : this;
20465
21023
  };
20466
21024
  var ActivityIdentity = class {
@@ -20488,12 +21046,67 @@ function formatUnknown(value) {
20488
21046
  return truncate(String(value), AGENT_ACTIVITY_DETAIL_LIMIT);
20489
21047
  }
20490
21048
  }
21049
+ function formatUnknownDetail(value) {
21050
+ if (typeof value === "string") {
21051
+ return value;
21052
+ }
21053
+ try {
21054
+ return JSON.stringify(value, null, 2) ?? "";
21055
+ } catch {
21056
+ return String(value);
21057
+ }
21058
+ }
20491
21059
  function readContentOutput(content) {
20492
21060
  if (!Array.isArray(content) || content.length === 0) {
20493
21061
  return "";
20494
21062
  }
20495
21063
  return formatUnknown(content);
20496
21064
  }
21065
+ function readContentOutputDetail(content) {
21066
+ if (!Array.isArray(content) || content.length === 0) {
21067
+ return "";
21068
+ }
21069
+ return formatUnknownDetail(content);
21070
+ }
21071
+ function summarizeDisplayContent(content) {
21072
+ return {
21073
+ ...content,
21074
+ data: truncate(content.data, AGENT_ACTIVITY_DETAIL_LIMIT),
21075
+ mimeType: truncate(content.mimeType, 255),
21076
+ name: truncate(content.name, 500),
21077
+ newText: truncate(content.newText, AGENT_ACTIVITY_DETAIL_LIMIT),
21078
+ oldText: truncate(content.oldText, AGENT_ACTIVITY_DETAIL_LIMIT),
21079
+ path: truncate(content.path, 2048),
21080
+ terminalId: truncate(content.terminalId, 255),
21081
+ text: truncate(content.text, AGENT_ACTIVITY_DETAIL_LIMIT),
21082
+ uri: truncate(content.uri, 4096)
21083
+ };
21084
+ }
21085
+ function contentFitsRecordingEnvelope(content) {
21086
+ 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;
21087
+ }
21088
+ function encodedByteLength(value) {
21089
+ return new TextEncoder().encode(JSON.stringify(value)).byteLength;
21090
+ }
21091
+ function captureActivityDetail(content, input2, output2) {
21092
+ const recorded = { content, input: input2, kind: "recorded", output: output2 };
21093
+ const originalBytes = encodedByteLength(recorded);
21094
+ 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) {
21095
+ return recorded;
21096
+ }
21097
+ return {
21098
+ capturedBytes: encodedByteLength({
21099
+ content: content.slice(0, 100).map(summarizeDisplayContent),
21100
+ input: truncate(input2, AGENT_ACTIVITY_DETAIL_LIMIT),
21101
+ output: truncate(output2, AGENT_ACTIVITY_DETAIL_LIMIT)
21102
+ }),
21103
+ kind: "truncated",
21104
+ originalBytes
21105
+ };
21106
+ }
21107
+ function recordedDetail(activity) {
21108
+ return activity?.detail.kind === "recorded" ? activity.detail : null;
21109
+ }
20497
21110
  function emptyDisplayContent(type) {
20498
21111
  return {
20499
21112
  data: "",
@@ -20604,8 +21217,8 @@ function normalizeToolStatus(status, fallback) {
20604
21217
  }
20605
21218
  return fallback;
20606
21219
  }
20607
- function normalizeTitle(title, fallback) {
20608
- const normalized = title.trim();
21220
+ function normalizeTitle(title2, fallback) {
21221
+ const normalized = title2.trim();
20609
21222
  return truncate(normalized.length === 0 ? fallback : normalized, 500);
20610
21223
  }
20611
21224
  function formatPlanEntries(entries) {
@@ -20658,17 +21271,20 @@ var AcpActivityTracker = class {
20658
21271
  }
20659
21272
  const previous = this.#activities.get(key);
20660
21273
  const identity2 = this.#identity(key);
21274
+ const fullOutput = `${recordedDetail(previous)?.output ?? previous?.output ?? ""}${text}`;
20661
21275
  const activity = new AcpActivity(
20662
21276
  identity2.id,
20663
21277
  activityType,
20664
21278
  "",
20665
21279
  [],
20666
21280
  "",
20667
- truncate(`${previous?.output ?? ""}${text}`, AGENT_ACTIVITY_DETAIL_LIMIT),
21281
+ truncate(fullOutput, AGENT_ACTIVITY_DETAIL_LIMIT),
20668
21282
  identity2.sequence,
20669
21283
  "running",
20670
21284
  activityType === "reasoning" ? "Reasoning" : "Progress update",
20671
- activityType === "reasoning" ? "think" : ""
21285
+ activityType === "reasoning" ? "think" : "",
21286
+ [],
21287
+ captureActivityDetail([], "", fullOutput)
20672
21288
  );
20673
21289
  await this.#record(key, activity);
20674
21290
  this.#activeNarrativeKey = key;
@@ -20721,7 +21337,8 @@ var AcpActivityTracker = class {
20721
21337
  "completed",
20722
21338
  previous.title,
20723
21339
  previous.toolKind,
20724
- previous.content
21340
+ previous.content,
21341
+ previous.detail
20725
21342
  )
20726
21343
  );
20727
21344
  }
@@ -20731,6 +21348,9 @@ var AcpActivityTracker = class {
20731
21348
  const key = `tool:${update.toolCallId}`;
20732
21349
  const identity2 = this.#identity(key);
20733
21350
  const output2 = update.rawOutput === void 0 ? readContentOutput(update.content) : formatUnknown(update.rawOutput);
21351
+ const detailInput = update.rawInput === void 0 ? "" : formatUnknownDetail(update.rawInput);
21352
+ const detailOutput = update.rawOutput === void 0 ? readContentOutputDetail(update.content) : formatUnknownDetail(update.rawOutput);
21353
+ const detailContent = normalizeToolContent(update.content ?? []);
20734
21354
  await this.#record(
20735
21355
  key,
20736
21356
  new AcpActivity(
@@ -20744,7 +21364,8 @@ var AcpActivityTracker = class {
20744
21364
  normalizeToolStatus(update.status ?? "pending", "pending"),
20745
21365
  normalizeTitle(update.title, "Tool call"),
20746
21366
  update.kind ?? "other",
20747
- normalizeToolContent(update.content ?? [])
21367
+ detailContent.slice(0, 100).map(summarizeDisplayContent),
21368
+ captureActivityDetail(detailContent, detailInput, detailOutput)
20748
21369
  )
20749
21370
  );
20750
21371
  };
@@ -20753,8 +21374,12 @@ var AcpActivityTracker = class {
20753
21374
  const key = `tool:${update.toolCallId}`;
20754
21375
  const previous = this.#activities.get(key);
20755
21376
  const identity2 = this.#identity(key);
21377
+ const previousDetail = recordedDetail(previous);
20756
21378
  const output2 = update.rawOutput !== void 0 ? formatUnknown(update.rawOutput) : update.content !== void 0 && update.content !== null ? readContentOutput(update.content) : previous?.output ?? "";
20757
21379
  const content = update.content === void 0 || update.content === null ? previous?.content ?? [] : normalizeToolContent(update.content);
21380
+ const detailInput = update.rawInput === void 0 ? previousDetail?.input ?? previous?.input ?? "" : formatUnknownDetail(update.rawInput);
21381
+ const detailOutput = update.rawOutput !== void 0 ? formatUnknownDetail(update.rawOutput) : update.content !== void 0 && update.content !== null ? readContentOutputDetail(update.content) : previousDetail?.output ?? previous?.output ?? "";
21382
+ const detailContent = update.content === void 0 || update.content === null ? previousDetail?.content ?? previous?.content ?? [] : normalizeToolContent(update.content);
20758
21383
  await this.#record(
20759
21384
  key,
20760
21385
  new AcpActivity(
@@ -20768,7 +21393,8 @@ var AcpActivityTracker = class {
20768
21393
  update.status === void 0 || update.status === null ? previous?.status ?? "pending" : normalizeToolStatus(update.status, previous?.status ?? "pending"),
20769
21394
  update.title === void 0 || update.title === null ? previous?.title ?? "Tool call" : normalizeTitle(update.title, "Tool call"),
20770
21395
  update.kind === void 0 || update.kind === null ? previous?.toolKind ?? "other" : update.kind,
20771
- content
21396
+ content.slice(0, 100).map(summarizeDisplayContent),
21397
+ captureActivityDetail(detailContent, detailInput, detailOutput)
20772
21398
  )
20773
21399
  );
20774
21400
  };
@@ -20838,12 +21464,13 @@ var AcpActivityTracker = class {
20838
21464
 
20839
21465
  // src/acp/native-session.ts
20840
21466
  var path = external_exports.string().min(1).max(2048).refine((value) => !value.includes("\0"));
21467
+ var title = external_exports.string().transform((value) => value.slice(0, 500));
20841
21468
  var nativeSessionIdSchema = external_exports.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,255}$/);
20842
21469
  var nativeSessionInfoSchema = external_exports.object({
20843
21470
  sessionId: nativeSessionIdSchema,
20844
21471
  cwd: path,
20845
21472
  additionalDirectories: external_exports.array(path).max(16).default([]).readonly(),
20846
- title: external_exports.string().max(500).nullish(),
21473
+ title: title.nullish(),
20847
21474
  updatedAt: external_exports.iso.datetime({ offset: true }).nullish()
20848
21475
  }).readonly();
20849
21476
  var nativeSessionPageSchema = external_exports.object({
@@ -21166,6 +21793,12 @@ var AcpExecutionError = class extends Error {
21166
21793
  this.name = "AcpExecutionError";
21167
21794
  }
21168
21795
  };
21796
+ var RetryableAcpInitializationError = class extends AcpExecutionError {
21797
+ constructor(cause) {
21798
+ super("ACP agent initialization failed", { cause });
21799
+ this.name = "RetryableAcpInitializationError";
21800
+ }
21801
+ };
21169
21802
  function readableWebStream(input2) {
21170
21803
  let streamOpen = true;
21171
21804
  return new ReadableStream({
@@ -21795,42 +22428,63 @@ var AcpProcessSession = class _AcpProcessSession {
21795
22428
  );
21796
22429
  this.#connection = createAcpClient(this).connect(stream);
21797
22430
  }
21798
- static start = async (options, getObserver, store) => {
21799
- options.signal.throwIfAborted();
21800
- const [adapterUnchanged, agentUnchanged] = await Promise.all([
21801
- revalidateExecutable(options.agent.adapterIdentity),
21802
- revalidateExecutable(options.agent.agentIdentity)
21803
- ]);
21804
- options.signal.throwIfAborted();
21805
- if (!adapterUnchanged || !agentUnchanged) {
21806
- throw new AcpExecutionError(
21807
- "The local Agent runtime changed; restart Mobius before starting a new conversation",
21808
- {},
21809
- "agent_runtime_changed"
21810
- );
21811
- }
21812
- const runtime = new _AcpProcessSession(
21813
- options.agent,
21814
- options.cwd,
21815
- options.additionalDirectories,
21816
- options.sessionId,
21817
- getObserver,
21818
- store
21819
- );
21820
- try {
21821
- await runtime.initialize(options.signal, options.origin);
21822
- return runtime;
21823
- } catch (error61) {
21824
- await runtime.closeProcess();
22431
+ static async #start(options, getObserver, store, initialize) {
22432
+ for (let attempt = 1; attempt <= 2; attempt += 1) {
21825
22433
  options.signal.throwIfAborted();
21826
- if (error61 instanceof AcpExecutionError) {
21827
- throw error61;
22434
+ const [adapterUnchanged, agentUnchanged] = await Promise.all([
22435
+ revalidateExecutable(options.agent.adapterIdentity),
22436
+ revalidateExecutable(options.agent.agentIdentity)
22437
+ ]);
22438
+ options.signal.throwIfAborted();
22439
+ if (!adapterUnchanged || !agentUnchanged) {
22440
+ throw new AcpExecutionError(
22441
+ "The local Agent runtime changed; restart Mobius before starting a new conversation",
22442
+ {},
22443
+ "agent_runtime_changed"
22444
+ );
22445
+ }
22446
+ const runtime = new _AcpProcessSession(
22447
+ options.agent,
22448
+ options.cwd,
22449
+ options.additionalDirectories,
22450
+ options.sessionId,
22451
+ getObserver,
22452
+ store
22453
+ );
22454
+ try {
22455
+ await initialize(runtime);
22456
+ return runtime;
22457
+ } catch (error61) {
22458
+ await runtime.closeProcess();
22459
+ options.signal.throwIfAborted();
22460
+ if (error61 instanceof RetryableAcpInitializationError && attempt === 1) {
22461
+ console.warn(
22462
+ `[${options.agent.id}-acp] ACP agent initialization failed; retrying once`
22463
+ );
22464
+ continue;
22465
+ }
22466
+ if (error61 instanceof AcpExecutionError) {
22467
+ throw error61;
22468
+ }
22469
+ throw new AcpExecutionError("ACP agent initialization failed", {
22470
+ cause: error61
22471
+ });
21828
22472
  }
21829
- throw new AcpExecutionError("ACP agent initialization failed", {
21830
- cause: error61
21831
- });
21832
22473
  }
21833
- };
22474
+ throw new AcpExecutionError("ACP agent initialization failed");
22475
+ }
22476
+ static start = async (options, getObserver, store) => await _AcpProcessSession.#start(
22477
+ options,
22478
+ getObserver,
22479
+ store,
22480
+ async (runtime) => await runtime.initialize(options.signal, options.origin)
22481
+ );
22482
+ static startNativeSessionBrowser = async (options, getObserver, store) => await _AcpProcessSession.#start(
22483
+ options,
22484
+ getObserver,
22485
+ store,
22486
+ async (runtime) => await runtime.#initializeAgent(options.signal)
22487
+ );
21834
22488
  belongsTo = (agentId, cwd, additionalDirectories) => this.#agentId === agentId && this.#cwd === cwd && arraysEqual(this.#additionalDirectories, additionalDirectories);
21835
22489
  canRebind = () => !this.#prompted && !this.#turn.running;
21836
22490
  prepared = () => new AcpPreparedSession(
@@ -21867,7 +22521,7 @@ var AcpProcessSession = class _AcpProcessSession {
21867
22521
  this.#replay = { kind: "idle" };
21868
22522
  }
21869
22523
  };
21870
- initialize = async (signal, origin) => {
22524
+ async #initializeAgent(signal) {
21871
22525
  const initialized = await this.race(
21872
22526
  this.#connection.agent.request(
21873
22527
  methods2.agent.initialize,
@@ -21878,14 +22532,17 @@ var AcpProcessSession = class _AcpProcessSession {
21878
22532
  session: { configOptions: { boolean: {} } }
21879
22533
  },
21880
22534
  clientInfo: { name: "mobius", version: "0.0.3" },
21881
- protocolVersion: PROTOCOL_VERSION2
22535
+ protocolVersion: PROTOCOL_VERSION
21882
22536
  },
21883
22537
  { cancellationSignal: signal }
21884
22538
  ),
21885
22539
  "ACP agent exited during initialization",
21886
22540
  signal
21887
- );
21888
- if (initialized.protocolVersion !== PROTOCOL_VERSION2) {
22541
+ ).catch((cause) => {
22542
+ signal.throwIfAborted();
22543
+ throw new RetryableAcpInitializationError(cause);
22544
+ });
22545
+ if (initialized.protocolVersion !== PROTOCOL_VERSION) {
21889
22546
  throw new AcpExecutionError(
21890
22547
  "ACP agent selected an unsupported protocol version",
21891
22548
  {},
@@ -21899,6 +22556,9 @@ var AcpProcessSession = class _AcpProcessSession {
21899
22556
  255
21900
22557
  );
21901
22558
  this.#agentVersion = truncate2(initialized.agentInfo?.version ?? "", 128);
22559
+ }
22560
+ initialize = async (signal, origin) => {
22561
+ await this.#initializeAgent(signal);
21902
22562
  const stored = origin?.kind === "import" ? new FoundAcpStoredSession(
21903
22563
  new AcpStoredSession(
21904
22564
  this.#mobiusSessionId,
@@ -22273,7 +22933,6 @@ var AcpProcessSession = class _AcpProcessSession {
22273
22933
  _meta: result._meta ?? null,
22274
22934
  commandId: options.commandId,
22275
22935
  kind: SESSION_USAGE_UPDATED_KIND,
22276
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22277
22936
  sessionId: this.#mobiusSessionId,
22278
22937
  source: "prompt",
22279
22938
  usage: result.usage ?? null
@@ -22331,7 +22990,6 @@ var AcpProcessSession = class _AcpProcessSession {
22331
22990
  kind: SESSION_PERMISSION_RESOLVED_KIND,
22332
22991
  optionId: options.outcome === "selected" ? options.optionId : "",
22333
22992
  outcome: options.outcome,
22334
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22335
22993
  sessionId: this.#mobiusSessionId
22336
22994
  });
22337
22995
  };
@@ -22376,7 +23034,6 @@ var AcpProcessSession = class _AcpProcessSession {
22376
23034
  action: options.action,
22377
23035
  interactionId: options.interactionId,
22378
23036
  kind: SESSION_ELICITATION_RESOLVED_KIND,
22379
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22380
23037
  sessionId: this.#mobiusSessionId
22381
23038
  });
22382
23039
  };
@@ -22410,7 +23067,6 @@ var AcpProcessSession = class _AcpProcessSession {
22410
23067
  interactionId,
22411
23068
  kind: SESSION_PERMISSION_REQUESTED_KIND,
22412
23069
  options,
22413
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22414
23070
  sessionId: this.#mobiusSessionId,
22415
23071
  title: truncate2(request.toolCall.title ?? "Permission required", 500),
22416
23072
  toolCallId: truncate2(request.toolCall.toolCallId, 255),
@@ -22464,7 +23120,6 @@ var AcpProcessSession = class _AcpProcessSession {
22464
23120
  kind: SESSION_ELICITATION_REQUESTED_KIND,
22465
23121
  message: truncate2(request.message, 2e3),
22466
23122
  mode: request.mode,
22467
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22468
23123
  sessionId: this.#mobiusSessionId,
22469
23124
  url: request.mode === "url" && typeof Reflect.get(request, "url") === "string" ? truncate2(readString3(Reflect.get(request, "url")), 4096) : ""
22470
23125
  });
@@ -22486,7 +23141,6 @@ var AcpProcessSession = class _AcpProcessSession {
22486
23141
  action: "complete",
22487
23142
  interactionId,
22488
23143
  kind: SESSION_ELICITATION_RESOLVED_KIND,
22489
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22490
23144
  sessionId: this.#mobiusSessionId
22491
23145
  });
22492
23146
  };
@@ -22523,7 +23177,6 @@ var AcpProcessSession = class _AcpProcessSession {
22523
23177
  contentId: `content-${crypto.randomUUID()}`,
22524
23178
  kind: AGENT_CONTENT_KIND,
22525
23179
  messageId: truncate2(update.messageId ?? "", 255),
22526
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22527
23180
  sessionId: this.#mobiusSessionId
22528
23181
  });
22529
23182
  }
@@ -22569,7 +23222,6 @@ var AcpProcessSession = class _AcpProcessSession {
22569
23222
  await this.#getObserver().onCommands({
22570
23223
  commands,
22571
23224
  kind: SESSION_COMMANDS_UPDATED_KIND,
22572
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22573
23225
  sessionId: this.#mobiusSessionId
22574
23226
  });
22575
23227
  return;
@@ -22598,7 +23250,6 @@ var AcpProcessSession = class _AcpProcessSession {
22598
23250
  }
22599
23251
  await this.#getObserver().onInfo({
22600
23252
  kind: SESSION_INFO_UPDATED_KIND,
22601
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22602
23253
  sessionId: this.#mobiusSessionId,
22603
23254
  title: this.#sessionTitle,
22604
23255
  updatedAt: this.#sessionUpdatedAt
@@ -22611,7 +23262,6 @@ var AcpProcessSession = class _AcpProcessSession {
22611
23262
  costCurrency: truncate2(update.cost?.currency ?? "", 16),
22612
23263
  hasCost: update.cost !== void 0 && update.cost !== null,
22613
23264
  kind: SESSION_USAGE_UPDATED_KIND,
22614
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22615
23265
  sessionId: this.#mobiusSessionId,
22616
23266
  size: Math.max(0, Math.trunc(update.size)),
22617
23267
  source: "context",
@@ -22679,7 +23329,6 @@ var AcpProcessSession = class _AcpProcessSession {
22679
23329
  await this.#getObserver().onConfig({
22680
23330
  configOptions: this.#configOptions,
22681
23331
  kind: SESSION_CONFIG_UPDATED_KIND,
22682
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22683
23332
  requestId: `agent-update-${crypto.randomUUID()}`,
22684
23333
  sessionId: this.#mobiusSessionId
22685
23334
  });
@@ -22695,7 +23344,6 @@ var AcpProcessSession = class _AcpProcessSession {
22695
23344
  kind: SESSION_PERMISSION_RESOLVED_KIND,
22696
23345
  optionId: "",
22697
23346
  outcome: "cancelled",
22698
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22699
23347
  sessionId: this.#mobiusSessionId
22700
23348
  });
22701
23349
  };
@@ -22709,7 +23357,6 @@ var AcpProcessSession = class _AcpProcessSession {
22709
23357
  action: "cancel",
22710
23358
  interactionId,
22711
23359
  kind: SESSION_ELICITATION_RESOLVED_KIND,
22712
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22713
23360
  sessionId: this.#mobiusSessionId
22714
23361
  });
22715
23362
  };
@@ -22729,7 +23376,6 @@ var AcpProcessSession = class _AcpProcessSession {
22729
23376
  action: "cancel",
22730
23377
  interactionId,
22731
23378
  kind: SESSION_ELICITATION_RESOLVED_KIND,
22732
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22733
23379
  sessionId: this.#mobiusSessionId
22734
23380
  });
22735
23381
  }
@@ -22737,6 +23383,10 @@ var AcpProcessSession = class _AcpProcessSession {
22737
23383
  };
22738
23384
  var AcpSessionManager = class {
22739
23385
  #nativeOperations = /* @__PURE__ */ new Set();
23386
+ #nativeBrowserObserver = new NullAcpSessionObserver();
23387
+ #nativeBrowserPreparing = /* @__PURE__ */ new Map();
23388
+ #nativeBrowserSessions = /* @__PURE__ */ new Map();
23389
+ #nativeBrowserStore = new MemoryAcpSessionStore();
22740
23390
  #activeSessionIds = /* @__PURE__ */ new Set();
22741
23391
  #cancellationRequests = /* @__PURE__ */ new Set();
22742
23392
  #preparing = /* @__PURE__ */ new Map();
@@ -22750,6 +23400,43 @@ var AcpSessionManager = class {
22750
23400
  setObserver = (observer) => {
22751
23401
  this.#observer = observer;
22752
23402
  };
23403
+ async #startNativeBrowserPreparation(options) {
23404
+ const operation = (async () => {
23405
+ try {
23406
+ const runtime = await AcpProcessSession.startNativeSessionBrowser(
23407
+ options,
23408
+ () => this.#nativeBrowserObserver,
23409
+ this.#nativeBrowserStore
23410
+ );
23411
+ this.#nativeBrowserSessions.set(options.sessionId, runtime);
23412
+ return runtime;
23413
+ } finally {
23414
+ this.#nativeBrowserPreparing.delete(options.sessionId);
23415
+ }
23416
+ })();
23417
+ this.#nativeBrowserPreparing.set(options.sessionId, operation);
23418
+ return await operation;
23419
+ }
23420
+ async #replaceNativeBrowserPreparation(existing, options) {
23421
+ const operation = (async () => {
23422
+ try {
23423
+ this.#nativeBrowserSessions.delete(options.sessionId);
23424
+ await existing.close();
23425
+ this.#nativeBrowserStore.remove(options.sessionId);
23426
+ const runtime = await AcpProcessSession.startNativeSessionBrowser(
23427
+ options,
23428
+ () => this.#nativeBrowserObserver,
23429
+ this.#nativeBrowserStore
23430
+ );
23431
+ this.#nativeBrowserSessions.set(options.sessionId, runtime);
23432
+ return runtime;
23433
+ } finally {
23434
+ this.#nativeBrowserPreparing.delete(options.sessionId);
23435
+ }
23436
+ })();
23437
+ this.#nativeBrowserPreparing.set(options.sessionId, operation);
23438
+ return await operation;
23439
+ }
22753
23440
  async #startPreparation(options) {
22754
23441
  const operation = (async () => {
22755
23442
  try {
@@ -22837,6 +23524,44 @@ var AcpSessionManager = class {
22837
23524
  const runtime = await this.#startPreparation(options);
22838
23525
  return runtime.prepared();
22839
23526
  };
23527
+ prepareNativeSessionBrowser = async (options) => {
23528
+ const pending = this.#nativeBrowserPreparing.get(options.sessionId);
23529
+ if (pending !== void 0) {
23530
+ const runtime2 = await pending;
23531
+ if (runtime2.belongsTo(
23532
+ options.agent.id,
23533
+ options.cwd,
23534
+ options.additionalDirectories
23535
+ )) {
23536
+ return runtime2.prepared();
23537
+ }
23538
+ return await this.prepareNativeSessionBrowser(options);
23539
+ }
23540
+ const existing = this.#nativeBrowserSessions.get(options.sessionId);
23541
+ if (existing !== void 0) {
23542
+ if (existing.belongsTo(
23543
+ options.agent.id,
23544
+ options.cwd,
23545
+ options.additionalDirectories
23546
+ )) {
23547
+ return existing.prepared();
23548
+ }
23549
+ if (!existing.canRebind()) {
23550
+ throw new AcpExecutionError(
23551
+ "The agent or workspace cannot change after a conversation has started",
23552
+ {},
23553
+ "session_identity_mismatch"
23554
+ );
23555
+ }
23556
+ const runtime2 = await this.#replaceNativeBrowserPreparation(
23557
+ existing,
23558
+ options
23559
+ );
23560
+ return runtime2.prepared();
23561
+ }
23562
+ const runtime = await this.#startNativeBrowserPreparation(options);
23563
+ return runtime.prepared();
23564
+ };
22840
23565
  configureSession = async (options) => {
22841
23566
  const runtime = await this.ensureSession(options);
22842
23567
  return await runtime.configure(options);
@@ -22925,8 +23650,14 @@ var AcpSessionManager = class {
22925
23650
  };
22926
23651
  close = async () => {
22927
23652
  const sessions = [...this.#sessions.values()];
23653
+ const nativeBrowserSessions = [...this.#nativeBrowserSessions.values()];
22928
23654
  this.#sessions.clear();
22929
- await Promise.all(sessions.map(async (session) => await session.close()));
23655
+ this.#nativeBrowserSessions.clear();
23656
+ await Promise.all(
23657
+ [...sessions, ...nativeBrowserSessions].map(
23658
+ async (session) => await session.close()
23659
+ )
23660
+ );
22930
23661
  };
22931
23662
  ensureSession = async (options) => {
22932
23663
  const existing = this.#sessions.get(options.sessionId);
@@ -22951,7 +23682,30 @@ var AcpSessionManager = class {
22951
23682
  }
22952
23683
  return started;
22953
23684
  };
22954
- listNativeSessions = async (options, cursor) => await (await this.ensureSession(options)).listNativeSessions(
23685
+ async #ensureNativeSessionBrowser(options) {
23686
+ const existing = this.#nativeBrowserSessions.get(options.sessionId);
23687
+ if (existing !== void 0) {
23688
+ if (!existing.belongsTo(
23689
+ options.agent.id,
23690
+ options.cwd,
23691
+ options.additionalDirectories
23692
+ )) {
23693
+ throw new AcpExecutionError(
23694
+ "The agent or workspace cannot change after a conversation has started",
23695
+ {},
23696
+ "session_identity_mismatch"
23697
+ );
23698
+ }
23699
+ return existing;
23700
+ }
23701
+ await this.prepareNativeSessionBrowser(options);
23702
+ const started = this.#nativeBrowserSessions.get(options.sessionId);
23703
+ if (started === void 0) {
23704
+ throw new AcpExecutionError("ACP native session browser did not start");
23705
+ }
23706
+ return started;
23707
+ }
23708
+ listNativeSessions = async (options, cursor) => await (await this.#ensureNativeSessionBrowser(options)).listNativeSessions(
22955
23709
  cursor,
22956
23710
  options.signal
22957
23711
  );
@@ -23034,7 +23788,7 @@ var AcpSessionManager = class {
23034
23788
  }
23035
23789
  };
23036
23790
  deleteNativeSession = async (options, nativeSessionId) => {
23037
- const runtime = await this.ensureSession(options);
23791
+ const runtime = await this.#ensureNativeSessionBrowser(options);
23038
23792
  const key = `${options.agent.id}:${nativeSessionId}`;
23039
23793
  const linked = this.#store.findNative(options.agent.id, nativeSessionId);
23040
23794
  if (this.#nativeOperations.has(key) || linked.some(
@@ -23061,7 +23815,8 @@ var AcpSessionManager = class {
23061
23815
  nativeSessionId
23062
23816
  );
23063
23817
  if (runtime.nativeSessionId() === nativeSessionId) {
23064
- this.#sessions.delete(options.sessionId);
23818
+ this.#nativeBrowserSessions.delete(options.sessionId);
23819
+ this.#nativeBrowserStore.remove(options.sessionId);
23065
23820
  await runtime.close();
23066
23821
  }
23067
23822
  return deleted;
@@ -23177,7 +23932,7 @@ import { isAbsolute, join as join6 } from "node:path";
23177
23932
  import {
23178
23933
  methods as methods3,
23179
23934
  ndJsonStream as ndJsonStream2,
23180
- PROTOCOL_VERSION as PROTOCOL_VERSION3
23935
+ PROTOCOL_VERSION as PROTOCOL_VERSION2
23181
23936
  } from "@agentclientprotocol/sdk";
23182
23937
 
23183
23938
  // src/agent-installation/installation-grants.ts
@@ -23206,7 +23961,7 @@ async function readGrantedAgents(stateDirectory) {
23206
23961
  }
23207
23962
  const encoded = await handle.readFile({ encoding: "utf8" });
23208
23963
  const value = JSON.parse(encoded);
23209
- if (!isRecord4(value) || Object.keys(value).length !== 2 || value["version"] !== 1 || !Array.isArray(value["agents"])) {
23964
+ if (!isRecord4(value) || Object.keys(value).length !== 1 || !Array.isArray(value["agents"])) {
23210
23965
  throw new Error("The local installation grant file is invalid");
23211
23966
  }
23212
23967
  const agents = /* @__PURE__ */ new Set();
@@ -23815,13 +24570,13 @@ async function probeAcp(agent, environment, defaultWorkspace, signal) {
23815
24570
  {
23816
24571
  clientCapabilities: {},
23817
24572
  clientInfo: { name: "mobius", version: "0.0.3" },
23818
- protocolVersion: PROTOCOL_VERSION3
24573
+ protocolVersion: PROTOCOL_VERSION2
23819
24574
  },
23820
24575
  { cancellationSignal: controller.signal }
23821
24576
  ),
23822
24577
  processExit
23823
24578
  ]);
23824
- if (initialized.protocolVersion !== PROTOCOL_VERSION3) {
24579
+ if (initialized.protocolVersion !== PROTOCOL_VERSION2) {
23825
24580
  throw new AgentProbeError(
23826
24581
  "acp_incompatible",
23827
24582
  "ACP adapter selected an unsupported protocol version"
@@ -23979,10 +24734,14 @@ var environmentProxyDispatcher = new EnvHttpProxyAgent();
23979
24734
  // src/pairing/pair-local-machine.ts
23980
24735
  var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
23981
24736
  var PAIRING_CODE_PATTERN = /^[A-HJ-NP-Z2-9]{4}(?:-[A-HJ-NP-Z2-9]{4}){4}$/;
23982
- var IDENTIFIER_PATTERN3 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
24737
+ var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
23983
24738
  var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
23984
24739
  var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
23985
- var CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken"];
24740
+ var CLAIM_RESPONSE_KEYS = [
24741
+ "channelId",
24742
+ "daemonToken",
24743
+ "runtimeId"
24744
+ ];
23986
24745
  var SAVED_CONNECTION_KEYS = [
23987
24746
  "defaultWorkspace",
23988
24747
  "channelId",
@@ -24099,7 +24858,7 @@ function parseChannelArgument(arguments_) {
24099
24858
  );
24100
24859
  }
24101
24860
  const channelId = arguments_[1] ?? "";
24102
- if (!IDENTIFIER_PATTERN3.test(channelId)) {
24861
+ if (!IDENTIFIER_PATTERN5.test(channelId)) {
24103
24862
  throw new PairingClientError(
24104
24863
  "invalid_channel_id",
24105
24864
  "The saved channel ID is invalid"
@@ -24174,20 +24933,21 @@ function decodeClaimResponse(value) {
24174
24933
  }
24175
24934
  const channelId = value["channelId"];
24176
24935
  const daemonToken = value["daemonToken"];
24177
- if (typeof channelId !== "string" || !IDENTIFIER_PATTERN3.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken)) {
24936
+ const runtimeId = value["runtimeId"];
24937
+ if (typeof channelId !== "string" || !IDENTIFIER_PATTERN5.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN5.test(runtimeId)) {
24178
24938
  throw new PairingClientError(
24179
24939
  "invalid_relay_response",
24180
24940
  "The relay returned an invalid pairing response"
24181
24941
  );
24182
24942
  }
24183
- return { channelId, daemonToken };
24943
+ return { channelId, daemonToken, runtimeId };
24184
24944
  }
24185
24945
  async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
24186
24946
  const agents = localAgents.map((agent) => ({
24187
24947
  id: agent.id,
24188
24948
  label: agent.label
24189
24949
  }));
24190
- const endpoint = new URL("/v1/pairings/claim", options.relayOrigin);
24950
+ const endpoint = new URL("/api/pairings/claim", options.relayOrigin);
24191
24951
  let response;
24192
24952
  try {
24193
24953
  response = await fetch(endpoint, {
@@ -24260,7 +25020,7 @@ function decodeSavedConnection(value, expectedChannelId) {
24260
25020
  const channelId = value["channelId"];
24261
25021
  const daemonToken = value["daemonToken"];
24262
25022
  const relayOrigin = value["relayOrigin"];
24263
- if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN3.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof relayOrigin !== "string") {
25023
+ if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN5.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof relayOrigin !== "string") {
24264
25024
  throw new PairingClientError(
24265
25025
  "invalid_connection",
24266
25026
  "The saved connection is invalid"
@@ -24324,7 +25084,7 @@ function assertInventoryUsable(inventory) {
24324
25084
  function buildPairedDaemon(connection, connectionPath, inventory) {
24325
25085
  assertInventoryUsable(inventory);
24326
25086
  const relayUrl = new URL(
24327
- `/v1/channels/${encodeURIComponent(connection.channelId)}/daemon`,
25087
+ `/api/channels/${encodeURIComponent(connection.channelId)}/daemon`,
24328
25088
  connection.relayOrigin
24329
25089
  );
24330
25090
  relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
@@ -24403,7 +25163,6 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
24403
25163
  }
24404
25164
 
24405
25165
  // src/run-daemon.ts
24406
- import { randomUUID as randomUUID5 } from "node:crypto";
24407
25166
  import { basename as basename3 } from "node:path";
24408
25167
  import { WebSocket as WebSocket2 } from "undici";
24409
25168
 
@@ -26060,12 +26819,12 @@ var NativeSessionService = class {
26060
26819
  execute = async (command, signal) => {
26061
26820
  signal.throwIfAborted();
26062
26821
  const cwd = await this.#directories.resolve(
26063
- command.bindingId,
26822
+ this.#config.bindingId,
26064
26823
  command.directoryId,
26065
26824
  signal
26066
26825
  );
26067
26826
  const additionalDirectories = await this.#directories.resolveMany(
26068
- command.bindingId,
26827
+ this.#config.bindingId,
26069
26828
  command.additionalDirectoryIds,
26070
26829
  signal
26071
26830
  );
@@ -26077,22 +26836,21 @@ var NativeSessionService = class {
26077
26836
  sessionId: command.sessionId,
26078
26837
  signal
26079
26838
  };
26080
- const prepared = await this.#sessions.prepareSession(options);
26839
+ const prepared = await this.#sessions.prepareNativeSessionBrowser(options);
26081
26840
  if (!prepared.capabilities.listSessions)
26082
26841
  throw new AcpExecutionError(
26083
26842
  "This Agent does not support native session listing",
26084
26843
  {},
26085
26844
  "native_session_unsupported"
26086
26845
  );
26087
- const scope = JSON.stringify([
26846
+ const entryScope = JSON.stringify([
26088
26847
  command.agentId,
26089
26848
  command.bindingId,
26090
- command.sessionId,
26091
- cwd
26849
+ command.sessionId
26092
26850
  ]);
26851
+ const cursorScope = JSON.stringify([entryScope, cwd]);
26093
26852
  const envelope2 = {
26094
26853
  kind: "native.session.result",
26095
- protocolVersion: 1,
26096
26854
  requestId: command.requestId,
26097
26855
  sessionId: command.sessionId
26098
26856
  };
@@ -26100,7 +26858,7 @@ var NativeSessionService = class {
26100
26858
  let cursor = null;
26101
26859
  if (command.cursor !== null) {
26102
26860
  const known = this.#cursors.get(command.cursor);
26103
- if (known?.scope !== scope)
26861
+ if (known?.scope !== cursorScope)
26104
26862
  throw new AcpExecutionError(
26105
26863
  "Refresh the native session list before continuing",
26106
26864
  {},
@@ -26116,7 +26874,7 @@ var NativeSessionService = class {
26116
26874
  const entryId = randomUUID3();
26117
26875
  if (this.#entries.size >= 5e3) this.#entries.clear();
26118
26876
  this.#entries.set(entryId, {
26119
- scope,
26877
+ scope: entryScope,
26120
26878
  nativeSessionId: info.sessionId,
26121
26879
  cwd: authorized.cwd,
26122
26880
  additionalDirectories: authorized.additionalDirectories
@@ -26140,7 +26898,10 @@ var NativeSessionService = class {
26140
26898
  );
26141
26899
  nextCursor = randomUUID3();
26142
26900
  if (this.#cursors.size >= 500) this.#cursors.clear();
26143
- this.#cursors.set(nextCursor, { scope, cursor: page.nextCursor });
26901
+ this.#cursors.set(nextCursor, {
26902
+ scope: cursorScope,
26903
+ cursor: page.nextCursor
26904
+ });
26144
26905
  }
26145
26906
  this.record(command, "native_sessions_listed");
26146
26907
  return {
@@ -26152,12 +26913,18 @@ var NativeSessionService = class {
26152
26913
  };
26153
26914
  }
26154
26915
  const selected = this.#entries.get(command.entryId);
26155
- if (selected?.scope !== scope)
26916
+ if (selected?.scope !== entryScope)
26156
26917
  throw new AcpExecutionError(
26157
26918
  "Select a session from a fresh native session list",
26158
26919
  {},
26159
26920
  "native_session_not_found"
26160
26921
  );
26922
+ if (selected.cwd !== cwd)
26923
+ throw new AcpExecutionError(
26924
+ "The selected session belongs to a different workspace. Refresh the list before continuing.",
26925
+ {},
26926
+ "native_session_target_changed"
26927
+ );
26161
26928
  const target = await this.resolveTarget(command, options, selected);
26162
26929
  if (command.action === "delete") {
26163
26930
  if (!prepared.capabilities.deleteSession)
@@ -26238,6 +27005,7 @@ var NativeSessionService = class {
26238
27005
  action: "preview",
26239
27006
  entryId: command.entryId,
26240
27007
  reason: "continuation_unavailable",
27008
+ targetSessionId: command.targetSessionId,
26241
27009
  title: target.info.title ?? "Untitled session",
26242
27010
  history: opened.history
26243
27011
  };
@@ -26253,7 +27021,6 @@ var NativeSessionService = class {
26253
27021
  directoryId: target.directoryId,
26254
27022
  directoryLabel: target.directoryLabel,
26255
27023
  kind: "session.ready",
26256
- protocolVersion: 1,
26257
27024
  requestId: command.requestId,
26258
27025
  restored: true,
26259
27026
  sessionId: opened.sessionId
@@ -26266,6 +27033,7 @@ var NativeSessionService = class {
26266
27033
  ...envelope2,
26267
27034
  action: command.action,
26268
27035
  ready,
27036
+ targetSessionId: command.targetSessionId,
26269
27037
  title: target.info.title ?? "Untitled session",
26270
27038
  history: opened.history
26271
27039
  };
@@ -26550,13 +27318,171 @@ var RelayConnectionLiveness = class {
26550
27318
  this.#transport.send(
26551
27319
  encodeRuntimeHeartbeatEvent({
26552
27320
  heartbeatId,
26553
- kind: RUNTIME_HEARTBEAT_KIND,
26554
- protocolVersion: MOBIUS_PROTOCOL_VERSION
27321
+ kind: RUNTIME_HEARTBEAT_KIND
26555
27322
  })
26556
27323
  );
26557
27324
  };
26558
27325
  };
26559
27326
 
27327
+ // src/relay-connection/session-event-outbox.ts
27328
+ import { mkdirSync as mkdirSync3 } from "node:fs";
27329
+ import { dirname as dirname5 } from "node:path";
27330
+ import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
27331
+ function readPendingEnvelope(row) {
27332
+ if (typeof row !== "object" || row === null || Array.isArray(row)) {
27333
+ throw new Error("SQLite returned an invalid session event outbox row");
27334
+ }
27335
+ const envelope2 = Reflect.get(row, "envelope_json");
27336
+ if (typeof envelope2 !== "string") {
27337
+ throw new Error("SQLite returned an invalid session event envelope");
27338
+ }
27339
+ return envelope2;
27340
+ }
27341
+ var SessionEventOutbox = class {
27342
+ #database;
27343
+ constructor(path2) {
27344
+ mkdirSync3(dirname5(path2), { recursive: true });
27345
+ this.#database = new DatabaseSync3(path2);
27346
+ this.#database.exec(`
27347
+ CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
27348
+ ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
27349
+ event_id TEXT NOT NULL UNIQUE,
27350
+ session_id TEXT NOT NULL,
27351
+ envelope_json TEXT NOT NULL
27352
+ ) STRICT;
27353
+ CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
27354
+ ON relay_session_event_outbox(ordinal);
27355
+ CREATE TABLE IF NOT EXISTS relay_session_event_sources (
27356
+ source_key TEXT PRIMARY KEY,
27357
+ next_source_seq INTEGER NOT NULL
27358
+ ) STRICT;
27359
+ CREATE TABLE IF NOT EXISTS relay_turn_receipts (
27360
+ command_id TEXT PRIMARY KEY,
27361
+ session_id TEXT NOT NULL,
27362
+ command_json TEXT NOT NULL,
27363
+ attempt_id TEXT NOT NULL,
27364
+ state TEXT NOT NULL CHECK (
27365
+ state IN ('dispatching', 'running', 'succeeded', 'failed', 'cancelled')
27366
+ )
27367
+ ) STRICT;
27368
+ `);
27369
+ }
27370
+ claimExecution = (commandId, sessionId, commandJson) => {
27371
+ this.#database.exec("BEGIN IMMEDIATE");
27372
+ try {
27373
+ const existing = this.#database.prepare(
27374
+ `SELECT session_id, command_json, attempt_id, state
27375
+ FROM relay_turn_receipts WHERE command_id = ?`
27376
+ ).get(commandId);
27377
+ if (typeof existing === "object" && existing !== null) {
27378
+ const storedSessionId = Reflect.get(existing, "session_id");
27379
+ const storedCommand = Reflect.get(existing, "command_json");
27380
+ const attemptId2 = Reflect.get(existing, "attempt_id");
27381
+ const state = Reflect.get(existing, "state");
27382
+ if (storedSessionId !== sessionId || storedCommand !== commandJson || typeof attemptId2 !== "string" || !isDaemonExecutionState(state)) {
27383
+ throw new Error(
27384
+ "The daemon command identity conflicts with its durable receipt"
27385
+ );
27386
+ }
27387
+ this.#database.exec("COMMIT");
27388
+ return { attemptId: attemptId2, commandId, kind: "duplicate", state };
27389
+ }
27390
+ const attemptId = crypto.randomUUID();
27391
+ this.#database.prepare(
27392
+ `INSERT INTO relay_turn_receipts (
27393
+ command_id, session_id, command_json, attempt_id, state
27394
+ ) VALUES (?, ?, ?, ?, 'dispatching')`
27395
+ ).run(commandId, sessionId, commandJson, attemptId);
27396
+ this.#database.exec("COMMIT");
27397
+ return {
27398
+ attemptId,
27399
+ commandId,
27400
+ kind: "accepted",
27401
+ state: "dispatching"
27402
+ };
27403
+ } catch (error61) {
27404
+ this.#database.exec("ROLLBACK");
27405
+ throw error61;
27406
+ }
27407
+ };
27408
+ transitionExecution = (commandId, state) => {
27409
+ const row = this.#database.prepare(`SELECT state FROM relay_turn_receipts WHERE command_id = ?`).get(commandId);
27410
+ const current = typeof row === "object" && row !== null ? Reflect.get(row, "state") : void 0;
27411
+ if (!isDaemonExecutionState(current)) {
27412
+ throw new Error("The daemon execution receipt does not exist");
27413
+ }
27414
+ if (current === state) {
27415
+ return;
27416
+ }
27417
+ const allowed = current === "dispatching" && (state === "running" || state === "failed" || state === "cancelled") || current === "running" && (state === "succeeded" || state === "failed" || state === "cancelled");
27418
+ if (!allowed) {
27419
+ throw new Error("The daemon execution transition is invalid");
27420
+ }
27421
+ this.#database.prepare(`UPDATE relay_turn_receipts SET state = ? WHERE command_id = ?`).run(state, commandId);
27422
+ };
27423
+ acknowledge = (acknowledgement) => {
27424
+ this.#database.prepare(
27425
+ `DELETE FROM relay_session_event_outbox
27426
+ WHERE event_id = ? AND session_id = ?`
27427
+ ).run(acknowledgement.eventId, acknowledgement.sessionId);
27428
+ };
27429
+ close = () => {
27430
+ this.#database.close();
27431
+ };
27432
+ enqueue = (sessionId, payload, attemptId = null) => {
27433
+ const sourceKey = attemptId === null ? `runtime:${sessionId}` : `attempt:${sessionId}:${attemptId}`;
27434
+ this.#database.exec("BEGIN IMMEDIATE");
27435
+ try {
27436
+ const row = this.#database.prepare(
27437
+ `SELECT next_source_seq FROM relay_session_event_sources
27438
+ WHERE source_key = ?`
27439
+ ).get(sourceKey);
27440
+ const storedSourceSeq = typeof row === "object" && row !== null ? Reflect.get(row, "next_source_seq") : void 0;
27441
+ const nextSourceSeq = typeof storedSourceSeq === "number" ? storedSourceSeq : 1;
27442
+ if (!Number.isSafeInteger(nextSourceSeq) || nextSourceSeq < 1) {
27443
+ throw new Error("SQLite returned an invalid event source sequence");
27444
+ }
27445
+ const envelope2 = {
27446
+ eventId: crypto.randomUUID(),
27447
+ kind: SESSION_EVENT_KIND,
27448
+ payload,
27449
+ sessionId,
27450
+ source: attemptId === null ? { kind: "runtime", sourceSeq: nextSourceSeq.toString() } : {
27451
+ attemptId,
27452
+ kind: "attempt",
27453
+ sourceSeq: nextSourceSeq.toString()
27454
+ }
27455
+ };
27456
+ const encoded = encodeSessionEventEnvelope(envelope2);
27457
+ this.#database.prepare(
27458
+ `INSERT INTO relay_session_event_sources (
27459
+ source_key, next_source_seq
27460
+ ) VALUES (?, ?)
27461
+ ON CONFLICT(source_key) DO UPDATE SET
27462
+ next_source_seq = excluded.next_source_seq`
27463
+ ).run(sourceKey, nextSourceSeq + 1);
27464
+ this.#database.prepare(
27465
+ `INSERT INTO relay_session_event_outbox (
27466
+ event_id, session_id, envelope_json
27467
+ ) VALUES (?, ?, ?)`
27468
+ ).run(envelope2.eventId, envelope2.sessionId, encoded);
27469
+ this.#database.exec("COMMIT");
27470
+ return encoded;
27471
+ } catch (error61) {
27472
+ this.#database.exec("ROLLBACK");
27473
+ throw error61;
27474
+ }
27475
+ };
27476
+ pending = () => this.#database.prepare(
27477
+ `SELECT envelope_json
27478
+ FROM relay_session_event_outbox
27479
+ ORDER BY ordinal`
27480
+ ).all().map(readPendingEnvelope);
27481
+ };
27482
+ function isDaemonExecutionState(value) {
27483
+ return value === "cancelled" || value === "dispatching" || value === "failed" || value === "running" || value === "succeeded";
27484
+ }
27485
+
26560
27486
  // src/relay-connection/timer.ts
26561
27487
  var SystemDaemonTimer = class {
26562
27488
  schedule = (callback, milliseconds) => {
@@ -26621,44 +27547,47 @@ var RelayConnectionRefresh = class {
26621
27547
  };
26622
27548
  };
26623
27549
  var DaemonAcpObserver = class {
26624
- #socket;
26625
- constructor(socket) {
26626
- this.#socket = socket;
27550
+ #record;
27551
+ constructor(record2) {
27552
+ this.#record = record2;
26627
27553
  }
26628
27554
  onCommands = (event) => {
26629
- send(this.#socket, encodeSessionCommandsUpdatedEvent(event));
27555
+ this.#record(event.sessionId, encodeSessionCommandsUpdatedEvent(event));
26630
27556
  return Promise.resolve();
26631
27557
  };
26632
27558
  onConfig = (event) => {
26633
- send(this.#socket, encodeSessionConfigUpdatedEvent(event));
27559
+ this.#record(event.sessionId, encodeSessionConfigUpdatedEvent(event));
26634
27560
  return Promise.resolve();
26635
27561
  };
26636
27562
  onContent = (event) => {
26637
- send(this.#socket, encodeAgentContentEvent(event));
27563
+ this.#record(event.sessionId, encodeAgentContentEvent(event));
26638
27564
  return Promise.resolve();
26639
27565
  };
26640
27566
  onElicitation = (event) => {
26641
- send(this.#socket, encodeSessionElicitationRequestedEvent(event));
27567
+ this.#record(
27568
+ event.sessionId,
27569
+ encodeSessionElicitationRequestedEvent(event)
27570
+ );
26642
27571
  return Promise.resolve();
26643
27572
  };
26644
27573
  onElicitationResolved = (event) => {
26645
- send(this.#socket, encodeSessionElicitationResolvedEvent(event));
27574
+ this.#record(event.sessionId, encodeSessionElicitationResolvedEvent(event));
26646
27575
  return Promise.resolve();
26647
27576
  };
26648
27577
  onInfo = (event) => {
26649
- send(this.#socket, encodeSessionInfoUpdatedEvent(event));
27578
+ this.#record(event.sessionId, encodeSessionInfoUpdatedEvent(event));
26650
27579
  return Promise.resolve();
26651
27580
  };
26652
27581
  onPermission = (event) => {
26653
- send(this.#socket, encodeSessionPermissionRequestedEvent(event));
27582
+ this.#record(event.sessionId, encodeSessionPermissionRequestedEvent(event));
26654
27583
  return Promise.resolve();
26655
27584
  };
26656
27585
  onPermissionResolved = (event) => {
26657
- send(this.#socket, encodeSessionPermissionResolvedEvent(event));
27586
+ this.#record(event.sessionId, encodeSessionPermissionResolvedEvent(event));
26658
27587
  return Promise.resolve();
26659
27588
  };
26660
27589
  onUsage = (event) => {
26661
- send(this.#socket, encodeSessionUsageUpdatedEvent(event));
27590
+ this.#record(event.sessionId, encodeSessionUsageUpdatedEvent(event));
26662
27591
  return Promise.resolve();
26663
27592
  };
26664
27593
  };
@@ -26710,7 +27639,6 @@ var DaemonInstallationObserver = class {
26710
27639
  encodeAgentInstallAwaitingApprovalEvent({
26711
27640
  agentId: state.agentId,
26712
27641
  kind: AGENT_INSTALL_AWAITING_APPROVAL_KIND,
26713
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26714
27642
  requestId: state.requestId
26715
27643
  })
26716
27644
  );
@@ -26724,7 +27652,6 @@ var DaemonInstallationObserver = class {
26724
27652
  encodeAgentInstallStartedEvent({
26725
27653
  agentId: state.agentId,
26726
27654
  kind: AGENT_INSTALL_STARTED_KIND,
26727
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26728
27655
  requestId: state.requestId
26729
27656
  })
26730
27657
  );
@@ -26734,7 +27661,6 @@ var DaemonInstallationObserver = class {
26734
27661
  encodeAgentInstallProgressEvent({
26735
27662
  agentId: state.agentId,
26736
27663
  kind: AGENT_INSTALL_PROGRESS_KIND,
26737
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26738
27664
  requestId: state.requestId,
26739
27665
  stage: state.stage
26740
27666
  })
@@ -26748,7 +27674,6 @@ var DaemonInstallationObserver = class {
26748
27674
  agentId: state.agentId,
26749
27675
  authenticationMayBeRequired: state.authenticationMayBeRequired,
26750
27676
  kind: AGENT_INSTALL_COMPLETED_KIND,
26751
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26752
27677
  requestId: state.requestId
26753
27678
  })
26754
27679
  );
@@ -26762,7 +27687,6 @@ var DaemonInstallationObserver = class {
26762
27687
  code: state.code,
26763
27688
  kind: AGENT_INSTALL_FAILED_KIND,
26764
27689
  message: state.message,
26765
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26766
27690
  requestId: state.requestId
26767
27691
  })
26768
27692
  );
@@ -26774,7 +27698,6 @@ var DaemonInstallationObserver = class {
26774
27698
  encodeAgentInstallCancelledEvent({
26775
27699
  agentId: state.agentId,
26776
27700
  kind: AGENT_INSTALL_CANCELLED_KIND,
26777
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26778
27701
  requestId: state.requestId
26779
27702
  })
26780
27703
  );
@@ -26822,20 +27745,25 @@ function send(socket, message) {
26822
27745
  }
26823
27746
  socket.send(message);
26824
27747
  }
26825
- function reportFailure(socket, command, code, message) {
26826
- if (socket.readyState !== WebSocket2.OPEN) {
26827
- return;
27748
+ function recordSessionEvent(outbox, socket, sessionId, payload, attemptId = null) {
27749
+ const envelope2 = outbox.enqueue(sessionId, payload, attemptId);
27750
+ if (socket.readyState === WebSocket2.OPEN) {
27751
+ socket.send(envelope2);
26828
27752
  }
26829
- send(
27753
+ }
27754
+ function reportFailure(outbox, socket, command, code, message, attemptId = null) {
27755
+ recordSessionEvent(
27756
+ outbox,
26830
27757
  socket,
27758
+ command.sessionId,
26831
27759
  encodeSessionFailedEvent({
26832
27760
  code,
26833
27761
  commandId: command.commandId,
26834
27762
  kind: SESSION_FAILED_KIND,
26835
27763
  message,
26836
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26837
27764
  sessionId: command.sessionId
26838
- })
27765
+ }),
27766
+ attemptId
26839
27767
  );
26840
27768
  }
26841
27769
  function operationErrorCode(error61) {
@@ -26860,7 +27788,6 @@ function reportOperationFailure(socket, requestId, sessionId, error61) {
26860
27788
  code: operationErrorCode(error61),
26861
27789
  kind: "session.operation.failed",
26862
27790
  message: operationErrorMessage(error61),
26863
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26864
27791
  requestId,
26865
27792
  sessionId
26866
27793
  })
@@ -26916,7 +27843,6 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
26916
27843
  entries: listing.entries,
26917
27844
  kind: "workspace.entries",
26918
27845
  parentDirectoryId: listing.parentDirectoryId,
26919
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26920
27846
  requestId: command.requestId
26921
27847
  })
26922
27848
  );
@@ -26924,11 +27850,11 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
26924
27850
  reportOperationFailure(socket, command.requestId, "", error61);
26925
27851
  }
26926
27852
  }
26927
- async function executeSessionPrepare(socket, command, config2, directories, audit, sessions, signal) {
27853
+ async function executeSessionPrepare(outbox, socket, command, config2, directories, audit, sessions, signal) {
26928
27854
  try {
26929
27855
  const resolved = await resolveSessionDirectories(
26930
27856
  directories,
26931
- command.bindingId,
27857
+ config2.bindingId,
26932
27858
  command.directoryId,
26933
27859
  command.additionalDirectoryIds,
26934
27860
  signal
@@ -26942,7 +27868,7 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26942
27868
  signal
26943
27869
  });
26944
27870
  const listing = await directories.list(
26945
- command.bindingId,
27871
+ config2.bindingId,
26946
27872
  command.directoryId,
26947
27873
  signal
26948
27874
  );
@@ -26951,8 +27877,10 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26951
27877
  event: "session_prepared",
26952
27878
  sessionId: command.sessionId
26953
27879
  });
26954
- send(
27880
+ recordSessionEvent(
27881
+ outbox,
26955
27882
  socket,
27883
+ command.sessionId,
26956
27884
  encodeSessionReadyEvent({
26957
27885
  additionalDirectories: resolved.additionalDirectoryEntries,
26958
27886
  agentId: command.agentId,
@@ -26964,21 +27892,29 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26964
27892
  directoryId: command.directoryId,
26965
27893
  directoryLabel: listing.directoryLabel,
26966
27894
  kind: "session.ready",
26967
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26968
27895
  requestId: command.requestId,
26969
27896
  restored: prepared.restored,
26970
27897
  sessionId: command.sessionId
26971
27898
  })
26972
27899
  );
26973
27900
  } catch (error61) {
27901
+ audit.record({
27902
+ commandId: command.requestId,
27903
+ details: {
27904
+ agentId: command.agentId,
27905
+ code: operationErrorCode(error61)
27906
+ },
27907
+ event: "session_prepare_failed",
27908
+ sessionId: command.sessionId
27909
+ });
26974
27910
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
26975
27911
  }
26976
27912
  }
26977
- async function executeSessionConfigure(socket, command, config2, directories, audit, sessions, signal) {
27913
+ async function executeSessionConfigure(outbox, socket, command, config2, directories, audit, sessions, signal) {
26978
27914
  try {
26979
27915
  const resolved = await resolveSessionDirectories(
26980
27916
  directories,
26981
- command.bindingId,
27917
+ config2.bindingId,
26982
27918
  command.directoryId,
26983
27919
  command.additionalDirectoryIds,
26984
27920
  signal
@@ -27000,12 +27936,13 @@ async function executeSessionConfigure(socket, command, config2, directories, au
27000
27936
  event: "session_configured",
27001
27937
  sessionId: command.sessionId
27002
27938
  });
27003
- send(
27939
+ recordSessionEvent(
27940
+ outbox,
27004
27941
  socket,
27942
+ command.sessionId,
27005
27943
  encodeSessionConfigUpdatedEvent({
27006
27944
  configOptions,
27007
27945
  kind: "session.config.updated",
27008
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27009
27946
  requestId: command.requestId,
27010
27947
  sessionId: command.sessionId
27011
27948
  })
@@ -27014,31 +27951,33 @@ async function executeSessionConfigure(socket, command, config2, directories, au
27014
27951
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
27015
27952
  }
27016
27953
  }
27017
- async function executePrompt(socket, command, config2, directories, audit, sessions, signal) {
27954
+ async function executePrompt(outbox, socket, command, config2, directories, audit, sessions, attemptId, signal) {
27018
27955
  try {
27019
27956
  const resolved = await resolveSessionDirectories(
27020
27957
  directories,
27021
- command.bindingId,
27958
+ config2.bindingId,
27022
27959
  command.directoryId,
27023
27960
  command.additionalDirectoryIds,
27024
27961
  signal
27025
27962
  );
27026
27963
  const agent = config2.catalog.find(command.agentId);
27027
- const processAttemptId = randomUUID5();
27028
27964
  audit.record({
27029
27965
  commandId: command.commandId,
27030
27966
  event: "session_authorized",
27031
27967
  sessionId: command.sessionId
27032
27968
  });
27033
- send(
27969
+ outbox.transitionExecution(command.commandId, "running");
27970
+ recordSessionEvent(
27971
+ outbox,
27034
27972
  socket,
27973
+ command.sessionId,
27035
27974
  encodeSessionStartedEvent({
27036
27975
  commandId: command.commandId,
27037
27976
  kind: SESSION_STARTED_KIND,
27038
- processAttemptId,
27039
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27977
+ attemptId,
27040
27978
  sessionId: command.sessionId
27041
- })
27979
+ }),
27980
+ attemptId
27042
27981
  );
27043
27982
  const result = await sessions.runPrompt({
27044
27983
  additionalDirectories: resolved.additionalDirectories,
@@ -27047,38 +27986,43 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27047
27986
  cwd: resolved.cwd,
27048
27987
  images: command.images,
27049
27988
  onActivity: (activity) => {
27050
- send(
27989
+ recordSessionEvent(
27990
+ outbox,
27051
27991
  socket,
27992
+ command.sessionId,
27052
27993
  encodeAgentActivityEvent({
27053
27994
  activityId: activity.activityId,
27054
27995
  activityType: activity.activityType,
27055
27996
  commandId: command.commandId,
27056
27997
  content: activity.content,
27998
+ detail: activity.detail,
27057
27999
  input: activity.input,
27058
28000
  kind: AGENT_ACTIVITY_KIND,
27059
28001
  locations: activity.locations,
27060
28002
  name: activity.name,
27061
28003
  output: activity.output,
27062
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27063
28004
  sequence: activity.sequence,
27064
28005
  sessionId: command.sessionId,
27065
28006
  status: activity.status,
27066
28007
  title: activity.title,
27067
28008
  toolKind: activity.toolKind
27068
- })
28009
+ }),
28010
+ attemptId
27069
28011
  );
27070
28012
  return Promise.resolve();
27071
28013
  },
27072
28014
  onText: (text) => {
27073
- send(
28015
+ recordSessionEvent(
28016
+ outbox,
27074
28017
  socket,
28018
+ command.sessionId,
27075
28019
  encodeAgentMessageDeltaEvent({
27076
28020
  commandId: command.commandId,
27077
28021
  kind: AGENT_MESSAGE_DELTA_KIND,
27078
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27079
28022
  sessionId: command.sessionId,
27080
28023
  text
27081
- })
28024
+ }),
28025
+ attemptId
27082
28026
  );
27083
28027
  return Promise.resolve();
27084
28028
  },
@@ -27087,15 +28031,21 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27087
28031
  sessionId: command.sessionId,
27088
28032
  signal
27089
28033
  });
27090
- send(
28034
+ recordSessionEvent(
28035
+ outbox,
27091
28036
  socket,
28037
+ command.sessionId,
27092
28038
  encodeSessionCompletedEvent({
27093
28039
  commandId: command.commandId,
27094
28040
  kind: SESSION_COMPLETED_KIND,
27095
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27096
28041
  sessionId: command.sessionId,
27097
28042
  stopReason: result.stopReason
27098
- })
28043
+ }),
28044
+ attemptId
28045
+ );
28046
+ outbox.transitionExecution(
28047
+ command.commandId,
28048
+ result.stopReason === "cancelled" ? "cancelled" : "succeeded"
27099
28049
  );
27100
28050
  audit.record({
27101
28051
  commandId: command.commandId,
@@ -27110,11 +28060,14 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27110
28060
  });
27111
28061
  const code = operationErrorCode(error61);
27112
28062
  reportFailure(
28063
+ outbox,
27113
28064
  socket,
27114
28065
  command,
27115
28066
  code === "session_operation_failed" ? "agent_execution_failed" : code,
27116
- code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error61)
28067
+ code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error61),
28068
+ attemptId
27117
28069
  );
28070
+ outbox.transitionExecution(command.commandId, "failed");
27118
28071
  console.error("Mobius daemon command failed", error61);
27119
28072
  }
27120
28073
  }
@@ -27132,15 +28085,28 @@ function waitForRelayRetry(signal, timer) {
27132
28085
  signal.addEventListener("abort", finish, { once: true });
27133
28086
  });
27134
28087
  }
27135
- async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, signal, timer) {
28088
+ async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, signal, timer) {
27136
28089
  const relayUrl = new URL(config2.relayUrl);
27137
28090
  relayUrl.searchParams.set("liveness", "1");
27138
28091
  const socket = await connectRelay(relayUrl, signal);
27139
28092
  const activeTurns = /* @__PURE__ */ new Map();
28093
+ const activeAttemptIds = /* @__PURE__ */ new Map();
27140
28094
  const connectionController = new AbortController();
27141
28095
  const nativeRequests = /* @__PURE__ */ new Map();
27142
- sessions.setObserver(new DaemonAcpObserver(socket));
28096
+ const record2 = (sessionId, payload) => {
28097
+ recordSessionEvent(
28098
+ outbox,
28099
+ socket,
28100
+ sessionId,
28101
+ payload,
28102
+ activeAttemptIds.get(sessionId) ?? null
28103
+ );
28104
+ };
28105
+ sessions.setObserver(new DaemonAcpObserver(record2));
27143
28106
  installationObserver.connect(socket);
28107
+ for (const pending of outbox.pending()) {
28108
+ send(socket, pending);
28109
+ }
27144
28110
  try {
27145
28111
  await new Promise((resolve5, reject) => {
27146
28112
  let finished = false;
@@ -27214,6 +28180,10 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27214
28180
  }
27215
28181
  try {
27216
28182
  const kind = decodeMessageKind(encoded);
28183
+ if (kind === SESSION_EVENT_ACK_KIND) {
28184
+ outbox.acknowledge(decodeSessionEventAcknowledgement(encoded));
28185
+ return;
28186
+ }
27217
28187
  if (kind === NATIVE_SESSION_CANCEL_KIND) {
27218
28188
  const command2 = decodeNativeSessionCancel(encoded);
27219
28189
  const pending = nativeRequests.get(command2.requestId);
@@ -27371,6 +28341,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27371
28341
  if (kind === SESSION_PREPARE_KIND) {
27372
28342
  const command2 = decodeSessionPrepareCommand(encoded);
27373
28343
  void executeSessionPrepare(
28344
+ outbox,
27374
28345
  socket,
27375
28346
  command2,
27376
28347
  config2,
@@ -27384,6 +28355,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27384
28355
  if (kind === SESSION_CONFIGURE_KIND) {
27385
28356
  const command2 = decodeSessionConfigureCommand(encoded);
27386
28357
  void executeSessionConfigure(
28358
+ outbox,
27387
28359
  socket,
27388
28360
  command2,
27389
28361
  config2,
@@ -27449,28 +28421,36 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27449
28421
  }
27450
28422
  const command = decodeSessionPromptCommand(encoded);
27451
28423
  if (activeTurns.has(command.commandId)) {
27452
- reportFailure(
27453
- socket,
27454
- command,
27455
- "duplicate_command",
27456
- "The command is already running"
27457
- );
28424
+ return;
28425
+ }
28426
+ const receipt = outbox.claimExecution(
28427
+ command.commandId,
28428
+ command.sessionId,
28429
+ encoded
28430
+ );
28431
+ if (receipt.kind === "duplicate") {
27458
28432
  return;
27459
28433
  }
27460
28434
  const turn = new ActiveDaemonTurn(command, new AbortController());
27461
28435
  activeTurns.set(command.commandId, turn);
28436
+ activeAttemptIds.set(command.sessionId, receipt.attemptId);
27462
28437
  void executePrompt(
28438
+ outbox,
27463
28439
  socket,
27464
28440
  command,
27465
28441
  config2,
27466
28442
  directories,
27467
28443
  audit,
27468
28444
  sessions,
28445
+ receipt.attemptId,
27469
28446
  turn.signal
27470
28447
  ).catch((error61) => {
27471
28448
  console.error("Mobius daemon turn failed", error61);
27472
28449
  }).finally(() => {
27473
28450
  activeTurns.delete(command.commandId);
28451
+ if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
28452
+ activeAttemptIds.delete(command.sessionId);
28453
+ }
27474
28454
  connectionRefresh.afterTurnFinished();
27475
28455
  });
27476
28456
  } catch (error61) {
@@ -27519,6 +28499,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27519
28499
  specifications
27520
28500
  ).prepare(signal);
27521
28501
  const sessionStore = new SqliteAcpSessionStore(config2.auditDatabasePath);
28502
+ const outbox = new SessionEventOutbox(config2.auditDatabasePath);
27522
28503
  const sessions = new AcpSessionManager(
27523
28504
  new NullAcpSessionObserver(),
27524
28505
  sessionStore
@@ -27554,6 +28535,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27554
28535
  installations,
27555
28536
  installationObserver,
27556
28537
  nativeSessions,
28538
+ outbox,
27557
28539
  signal,
27558
28540
  timer
27559
28541
  );
@@ -27576,7 +28558,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27576
28558
  try {
27577
28559
  await sessions.close();
27578
28560
  } finally {
27579
- sessionStore.close();
28561
+ try {
28562
+ sessionStore.close();
28563
+ } finally {
28564
+ outbox.close();
28565
+ }
27580
28566
  }
27581
28567
  }
27582
28568
  }