@moxt-ai/mobius 0.0.6 → 0.0.7

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 (33) 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/session-manager.d.ts.map +1 -1
  6. package/dist/acp/session-manager.js +1 -15
  7. package/dist/acp/session-manager.js.map +1 -1
  8. package/dist/agent-installation/installation-grants.d.ts.map +1 -1
  9. package/dist/agent-installation/installation-grants.js +1 -2
  10. package/dist/agent-installation/installation-grants.js.map +1 -1
  11. package/dist/cli.js +1030 -196
  12. package/dist/cli.js.map +4 -4
  13. package/dist/config.js +1 -1
  14. package/dist/config.js.map +1 -1
  15. package/dist/index.js +1037 -203
  16. package/dist/index.js.map +4 -4
  17. package/dist/native-sessions/service.d.ts.map +1 -1
  18. package/dist/native-sessions/service.js +15 -10
  19. package/dist/native-sessions/service.js.map +1 -1
  20. package/dist/pairing/pair-local-machine.d.ts.map +1 -1
  21. package/dist/pairing/pair-local-machine.js +12 -5
  22. package/dist/pairing/pair-local-machine.js.map +1 -1
  23. package/dist/relay-connection/liveness.d.ts.map +1 -1
  24. package/dist/relay-connection/liveness.js +1 -2
  25. package/dist/relay-connection/liveness.js.map +1 -1
  26. package/dist/relay-connection/session-event-outbox.d.ts +19 -0
  27. package/dist/relay-connection/session-event-outbox.d.ts.map +1 -0
  28. package/dist/relay-connection/session-event-outbox.js +182 -0
  29. package/dist/relay-connection/session-event-outbox.js.map +1 -0
  30. package/dist/run-daemon.d.ts.map +1 -1
  31. package/dist/run-daemon.js +78 -63
  32. package/dist/run-daemon.js.map +1 -1
  33. 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, title, 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;
@@ -20448,6 +21004,7 @@ var AcpActivity = class _AcpActivity {
20448
21004
  this.title = title;
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: "",
@@ -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
  };
@@ -21878,14 +22504,14 @@ var AcpProcessSession = class _AcpProcessSession {
21878
22504
  session: { configOptions: { boolean: {} } }
21879
22505
  },
21880
22506
  clientInfo: { name: "mobius", version: "0.0.3" },
21881
- protocolVersion: PROTOCOL_VERSION2
22507
+ protocolVersion: PROTOCOL_VERSION
21882
22508
  },
21883
22509
  { cancellationSignal: signal }
21884
22510
  ),
21885
22511
  "ACP agent exited during initialization",
21886
22512
  signal
21887
22513
  );
21888
- if (initialized.protocolVersion !== PROTOCOL_VERSION2) {
22514
+ if (initialized.protocolVersion !== PROTOCOL_VERSION) {
21889
22515
  throw new AcpExecutionError(
21890
22516
  "ACP agent selected an unsupported protocol version",
21891
22517
  {},
@@ -22273,7 +22899,6 @@ var AcpProcessSession = class _AcpProcessSession {
22273
22899
  _meta: result._meta ?? null,
22274
22900
  commandId: options.commandId,
22275
22901
  kind: SESSION_USAGE_UPDATED_KIND,
22276
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22277
22902
  sessionId: this.#mobiusSessionId,
22278
22903
  source: "prompt",
22279
22904
  usage: result.usage ?? null
@@ -22331,7 +22956,6 @@ var AcpProcessSession = class _AcpProcessSession {
22331
22956
  kind: SESSION_PERMISSION_RESOLVED_KIND,
22332
22957
  optionId: options.outcome === "selected" ? options.optionId : "",
22333
22958
  outcome: options.outcome,
22334
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22335
22959
  sessionId: this.#mobiusSessionId
22336
22960
  });
22337
22961
  };
@@ -22376,7 +23000,6 @@ var AcpProcessSession = class _AcpProcessSession {
22376
23000
  action: options.action,
22377
23001
  interactionId: options.interactionId,
22378
23002
  kind: SESSION_ELICITATION_RESOLVED_KIND,
22379
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22380
23003
  sessionId: this.#mobiusSessionId
22381
23004
  });
22382
23005
  };
@@ -22410,7 +23033,6 @@ var AcpProcessSession = class _AcpProcessSession {
22410
23033
  interactionId,
22411
23034
  kind: SESSION_PERMISSION_REQUESTED_KIND,
22412
23035
  options,
22413
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22414
23036
  sessionId: this.#mobiusSessionId,
22415
23037
  title: truncate2(request.toolCall.title ?? "Permission required", 500),
22416
23038
  toolCallId: truncate2(request.toolCall.toolCallId, 255),
@@ -22464,7 +23086,6 @@ var AcpProcessSession = class _AcpProcessSession {
22464
23086
  kind: SESSION_ELICITATION_REQUESTED_KIND,
22465
23087
  message: truncate2(request.message, 2e3),
22466
23088
  mode: request.mode,
22467
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22468
23089
  sessionId: this.#mobiusSessionId,
22469
23090
  url: request.mode === "url" && typeof Reflect.get(request, "url") === "string" ? truncate2(readString3(Reflect.get(request, "url")), 4096) : ""
22470
23091
  });
@@ -22486,7 +23107,6 @@ var AcpProcessSession = class _AcpProcessSession {
22486
23107
  action: "complete",
22487
23108
  interactionId,
22488
23109
  kind: SESSION_ELICITATION_RESOLVED_KIND,
22489
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22490
23110
  sessionId: this.#mobiusSessionId
22491
23111
  });
22492
23112
  };
@@ -22523,7 +23143,6 @@ var AcpProcessSession = class _AcpProcessSession {
22523
23143
  contentId: `content-${crypto.randomUUID()}`,
22524
23144
  kind: AGENT_CONTENT_KIND,
22525
23145
  messageId: truncate2(update.messageId ?? "", 255),
22526
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22527
23146
  sessionId: this.#mobiusSessionId
22528
23147
  });
22529
23148
  }
@@ -22569,7 +23188,6 @@ var AcpProcessSession = class _AcpProcessSession {
22569
23188
  await this.#getObserver().onCommands({
22570
23189
  commands,
22571
23190
  kind: SESSION_COMMANDS_UPDATED_KIND,
22572
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22573
23191
  sessionId: this.#mobiusSessionId
22574
23192
  });
22575
23193
  return;
@@ -22598,7 +23216,6 @@ var AcpProcessSession = class _AcpProcessSession {
22598
23216
  }
22599
23217
  await this.#getObserver().onInfo({
22600
23218
  kind: SESSION_INFO_UPDATED_KIND,
22601
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22602
23219
  sessionId: this.#mobiusSessionId,
22603
23220
  title: this.#sessionTitle,
22604
23221
  updatedAt: this.#sessionUpdatedAt
@@ -22611,7 +23228,6 @@ var AcpProcessSession = class _AcpProcessSession {
22611
23228
  costCurrency: truncate2(update.cost?.currency ?? "", 16),
22612
23229
  hasCost: update.cost !== void 0 && update.cost !== null,
22613
23230
  kind: SESSION_USAGE_UPDATED_KIND,
22614
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22615
23231
  sessionId: this.#mobiusSessionId,
22616
23232
  size: Math.max(0, Math.trunc(update.size)),
22617
23233
  source: "context",
@@ -22679,7 +23295,6 @@ var AcpProcessSession = class _AcpProcessSession {
22679
23295
  await this.#getObserver().onConfig({
22680
23296
  configOptions: this.#configOptions,
22681
23297
  kind: SESSION_CONFIG_UPDATED_KIND,
22682
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22683
23298
  requestId: `agent-update-${crypto.randomUUID()}`,
22684
23299
  sessionId: this.#mobiusSessionId
22685
23300
  });
@@ -22695,7 +23310,6 @@ var AcpProcessSession = class _AcpProcessSession {
22695
23310
  kind: SESSION_PERMISSION_RESOLVED_KIND,
22696
23311
  optionId: "",
22697
23312
  outcome: "cancelled",
22698
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22699
23313
  sessionId: this.#mobiusSessionId
22700
23314
  });
22701
23315
  };
@@ -22709,7 +23323,6 @@ var AcpProcessSession = class _AcpProcessSession {
22709
23323
  action: "cancel",
22710
23324
  interactionId,
22711
23325
  kind: SESSION_ELICITATION_RESOLVED_KIND,
22712
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22713
23326
  sessionId: this.#mobiusSessionId
22714
23327
  });
22715
23328
  };
@@ -22729,7 +23342,6 @@ var AcpProcessSession = class _AcpProcessSession {
22729
23342
  action: "cancel",
22730
23343
  interactionId,
22731
23344
  kind: SESSION_ELICITATION_RESOLVED_KIND,
22732
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
22733
23345
  sessionId: this.#mobiusSessionId
22734
23346
  });
22735
23347
  }
@@ -23177,7 +23789,7 @@ import { isAbsolute, join as join6 } from "node:path";
23177
23789
  import {
23178
23790
  methods as methods3,
23179
23791
  ndJsonStream as ndJsonStream2,
23180
- PROTOCOL_VERSION as PROTOCOL_VERSION3
23792
+ PROTOCOL_VERSION as PROTOCOL_VERSION2
23181
23793
  } from "@agentclientprotocol/sdk";
23182
23794
 
23183
23795
  // src/agent-installation/installation-grants.ts
@@ -23206,7 +23818,7 @@ async function readGrantedAgents(stateDirectory) {
23206
23818
  }
23207
23819
  const encoded = await handle.readFile({ encoding: "utf8" });
23208
23820
  const value = JSON.parse(encoded);
23209
- if (!isRecord4(value) || Object.keys(value).length !== 2 || value["version"] !== 1 || !Array.isArray(value["agents"])) {
23821
+ if (!isRecord4(value) || Object.keys(value).length !== 1 || !Array.isArray(value["agents"])) {
23210
23822
  throw new Error("The local installation grant file is invalid");
23211
23823
  }
23212
23824
  const agents = /* @__PURE__ */ new Set();
@@ -23815,13 +24427,13 @@ async function probeAcp(agent, environment, defaultWorkspace, signal) {
23815
24427
  {
23816
24428
  clientCapabilities: {},
23817
24429
  clientInfo: { name: "mobius", version: "0.0.3" },
23818
- protocolVersion: PROTOCOL_VERSION3
24430
+ protocolVersion: PROTOCOL_VERSION2
23819
24431
  },
23820
24432
  { cancellationSignal: controller.signal }
23821
24433
  ),
23822
24434
  processExit
23823
24435
  ]);
23824
- if (initialized.protocolVersion !== PROTOCOL_VERSION3) {
24436
+ if (initialized.protocolVersion !== PROTOCOL_VERSION2) {
23825
24437
  throw new AgentProbeError(
23826
24438
  "acp_incompatible",
23827
24439
  "ACP adapter selected an unsupported protocol version"
@@ -23979,10 +24591,14 @@ var environmentProxyDispatcher = new EnvHttpProxyAgent();
23979
24591
  // src/pairing/pair-local-machine.ts
23980
24592
  var PAIRING_TIMEOUT_MILLISECONDS = 2e4;
23981
24593
  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}$/;
24594
+ var IDENTIFIER_PATTERN5 = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
23983
24595
  var TOKEN_PATTERN = /^[a-zA-Z0-9_-]{32,256}$/;
23984
24596
  var MAX_CONNECTION_FILE_LENGTH = 16 * 1024;
23985
- var CLAIM_RESPONSE_KEYS = ["channelId", "daemonToken"];
24597
+ var CLAIM_RESPONSE_KEYS = [
24598
+ "channelId",
24599
+ "daemonToken",
24600
+ "runtimeId"
24601
+ ];
23986
24602
  var SAVED_CONNECTION_KEYS = [
23987
24603
  "defaultWorkspace",
23988
24604
  "channelId",
@@ -24099,7 +24715,7 @@ function parseChannelArgument(arguments_) {
24099
24715
  );
24100
24716
  }
24101
24717
  const channelId = arguments_[1] ?? "";
24102
- if (!IDENTIFIER_PATTERN3.test(channelId)) {
24718
+ if (!IDENTIFIER_PATTERN5.test(channelId)) {
24103
24719
  throw new PairingClientError(
24104
24720
  "invalid_channel_id",
24105
24721
  "The saved channel ID is invalid"
@@ -24174,20 +24790,21 @@ function decodeClaimResponse(value) {
24174
24790
  }
24175
24791
  const channelId = value["channelId"];
24176
24792
  const daemonToken = value["daemonToken"];
24177
- if (typeof channelId !== "string" || !IDENTIFIER_PATTERN3.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken)) {
24793
+ const runtimeId = value["runtimeId"];
24794
+ if (typeof channelId !== "string" || !IDENTIFIER_PATTERN5.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof runtimeId !== "string" || !IDENTIFIER_PATTERN5.test(runtimeId)) {
24178
24795
  throw new PairingClientError(
24179
24796
  "invalid_relay_response",
24180
24797
  "The relay returned an invalid pairing response"
24181
24798
  );
24182
24799
  }
24183
- return { channelId, daemonToken };
24800
+ return { channelId, daemonToken, runtimeId };
24184
24801
  }
24185
24802
  async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
24186
24803
  const agents = localAgents.map((agent) => ({
24187
24804
  id: agent.id,
24188
24805
  label: agent.label
24189
24806
  }));
24190
- const endpoint = new URL("/v1/pairings/claim", options.relayOrigin);
24807
+ const endpoint = new URL("/api/pairings/claim", options.relayOrigin);
24191
24808
  let response;
24192
24809
  try {
24193
24810
  response = await fetch(endpoint, {
@@ -24260,7 +24877,7 @@ function decodeSavedConnection(value, expectedChannelId) {
24260
24877
  const channelId = value["channelId"];
24261
24878
  const daemonToken = value["daemonToken"];
24262
24879
  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") {
24880
+ if (typeof defaultWorkspace !== "string" || typeof channelId !== "string" || channelId !== expectedChannelId || !IDENTIFIER_PATTERN5.test(channelId) || typeof daemonToken !== "string" || !TOKEN_PATTERN.test(daemonToken) || typeof relayOrigin !== "string") {
24264
24881
  throw new PairingClientError(
24265
24882
  "invalid_connection",
24266
24883
  "The saved connection is invalid"
@@ -24324,7 +24941,7 @@ function assertInventoryUsable(inventory) {
24324
24941
  function buildPairedDaemon(connection, connectionPath, inventory) {
24325
24942
  assertInventoryUsable(inventory);
24326
24943
  const relayUrl = new URL(
24327
- `/v1/channels/${encodeURIComponent(connection.channelId)}/daemon`,
24944
+ `/api/channels/${encodeURIComponent(connection.channelId)}/daemon`,
24328
24945
  connection.relayOrigin
24329
24946
  );
24330
24947
  relayUrl.protocol = relayUrl.protocol === "https:" ? "wss:" : "ws:";
@@ -24403,7 +25020,6 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
24403
25020
  }
24404
25021
 
24405
25022
  // src/run-daemon.ts
24406
- import { randomUUID as randomUUID5 } from "node:crypto";
24407
25023
  import { basename as basename3 } from "node:path";
24408
25024
  import { WebSocket as WebSocket2 } from "undici";
24409
25025
 
@@ -26060,12 +26676,12 @@ var NativeSessionService = class {
26060
26676
  execute = async (command, signal) => {
26061
26677
  signal.throwIfAborted();
26062
26678
  const cwd = await this.#directories.resolve(
26063
- command.bindingId,
26679
+ this.#config.bindingId,
26064
26680
  command.directoryId,
26065
26681
  signal
26066
26682
  );
26067
26683
  const additionalDirectories = await this.#directories.resolveMany(
26068
- command.bindingId,
26684
+ this.#config.bindingId,
26069
26685
  command.additionalDirectoryIds,
26070
26686
  signal
26071
26687
  );
@@ -26084,15 +26700,14 @@ var NativeSessionService = class {
26084
26700
  {},
26085
26701
  "native_session_unsupported"
26086
26702
  );
26087
- const scope = JSON.stringify([
26703
+ const entryScope = JSON.stringify([
26088
26704
  command.agentId,
26089
26705
  command.bindingId,
26090
- command.sessionId,
26091
- cwd
26706
+ command.sessionId
26092
26707
  ]);
26708
+ const cursorScope = JSON.stringify([entryScope, cwd]);
26093
26709
  const envelope2 = {
26094
26710
  kind: "native.session.result",
26095
- protocolVersion: 1,
26096
26711
  requestId: command.requestId,
26097
26712
  sessionId: command.sessionId
26098
26713
  };
@@ -26100,7 +26715,7 @@ var NativeSessionService = class {
26100
26715
  let cursor = null;
26101
26716
  if (command.cursor !== null) {
26102
26717
  const known = this.#cursors.get(command.cursor);
26103
- if (known?.scope !== scope)
26718
+ if (known?.scope !== cursorScope)
26104
26719
  throw new AcpExecutionError(
26105
26720
  "Refresh the native session list before continuing",
26106
26721
  {},
@@ -26116,7 +26731,7 @@ var NativeSessionService = class {
26116
26731
  const entryId = randomUUID3();
26117
26732
  if (this.#entries.size >= 5e3) this.#entries.clear();
26118
26733
  this.#entries.set(entryId, {
26119
- scope,
26734
+ scope: entryScope,
26120
26735
  nativeSessionId: info.sessionId,
26121
26736
  cwd: authorized.cwd,
26122
26737
  additionalDirectories: authorized.additionalDirectories
@@ -26140,7 +26755,10 @@ var NativeSessionService = class {
26140
26755
  );
26141
26756
  nextCursor = randomUUID3();
26142
26757
  if (this.#cursors.size >= 500) this.#cursors.clear();
26143
- this.#cursors.set(nextCursor, { scope, cursor: page.nextCursor });
26758
+ this.#cursors.set(nextCursor, {
26759
+ scope: cursorScope,
26760
+ cursor: page.nextCursor
26761
+ });
26144
26762
  }
26145
26763
  this.record(command, "native_sessions_listed");
26146
26764
  return {
@@ -26152,12 +26770,18 @@ var NativeSessionService = class {
26152
26770
  };
26153
26771
  }
26154
26772
  const selected = this.#entries.get(command.entryId);
26155
- if (selected?.scope !== scope)
26773
+ if (selected?.scope !== entryScope)
26156
26774
  throw new AcpExecutionError(
26157
26775
  "Select a session from a fresh native session list",
26158
26776
  {},
26159
26777
  "native_session_not_found"
26160
26778
  );
26779
+ if (selected.cwd !== cwd)
26780
+ throw new AcpExecutionError(
26781
+ "The selected session belongs to a different workspace. Refresh the list before continuing.",
26782
+ {},
26783
+ "native_session_target_changed"
26784
+ );
26161
26785
  const target = await this.resolveTarget(command, options, selected);
26162
26786
  if (command.action === "delete") {
26163
26787
  if (!prepared.capabilities.deleteSession)
@@ -26238,6 +26862,7 @@ var NativeSessionService = class {
26238
26862
  action: "preview",
26239
26863
  entryId: command.entryId,
26240
26864
  reason: "continuation_unavailable",
26865
+ targetSessionId: command.targetSessionId,
26241
26866
  title: target.info.title ?? "Untitled session",
26242
26867
  history: opened.history
26243
26868
  };
@@ -26253,7 +26878,6 @@ var NativeSessionService = class {
26253
26878
  directoryId: target.directoryId,
26254
26879
  directoryLabel: target.directoryLabel,
26255
26880
  kind: "session.ready",
26256
- protocolVersion: 1,
26257
26881
  requestId: command.requestId,
26258
26882
  restored: true,
26259
26883
  sessionId: opened.sessionId
@@ -26266,6 +26890,7 @@ var NativeSessionService = class {
26266
26890
  ...envelope2,
26267
26891
  action: command.action,
26268
26892
  ready,
26893
+ targetSessionId: command.targetSessionId,
26269
26894
  title: target.info.title ?? "Untitled session",
26270
26895
  history: opened.history
26271
26896
  };
@@ -26550,13 +27175,171 @@ var RelayConnectionLiveness = class {
26550
27175
  this.#transport.send(
26551
27176
  encodeRuntimeHeartbeatEvent({
26552
27177
  heartbeatId,
26553
- kind: RUNTIME_HEARTBEAT_KIND,
26554
- protocolVersion: MOBIUS_PROTOCOL_VERSION
27178
+ kind: RUNTIME_HEARTBEAT_KIND
26555
27179
  })
26556
27180
  );
26557
27181
  };
26558
27182
  };
26559
27183
 
27184
+ // src/relay-connection/session-event-outbox.ts
27185
+ import { mkdirSync as mkdirSync3 } from "node:fs";
27186
+ import { dirname as dirname5 } from "node:path";
27187
+ import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
27188
+ function readPendingEnvelope(row) {
27189
+ if (typeof row !== "object" || row === null || Array.isArray(row)) {
27190
+ throw new Error("SQLite returned an invalid session event outbox row");
27191
+ }
27192
+ const envelope2 = Reflect.get(row, "envelope_json");
27193
+ if (typeof envelope2 !== "string") {
27194
+ throw new Error("SQLite returned an invalid session event envelope");
27195
+ }
27196
+ return envelope2;
27197
+ }
27198
+ var SessionEventOutbox = class {
27199
+ #database;
27200
+ constructor(path2) {
27201
+ mkdirSync3(dirname5(path2), { recursive: true });
27202
+ this.#database = new DatabaseSync3(path2);
27203
+ this.#database.exec(`
27204
+ CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
27205
+ ordinal INTEGER PRIMARY KEY AUTOINCREMENT,
27206
+ event_id TEXT NOT NULL UNIQUE,
27207
+ session_id TEXT NOT NULL,
27208
+ envelope_json TEXT NOT NULL
27209
+ ) STRICT;
27210
+ CREATE INDEX IF NOT EXISTS relay_session_event_outbox_order
27211
+ ON relay_session_event_outbox(ordinal);
27212
+ CREATE TABLE IF NOT EXISTS relay_session_event_sources (
27213
+ source_key TEXT PRIMARY KEY,
27214
+ next_source_seq INTEGER NOT NULL
27215
+ ) STRICT;
27216
+ CREATE TABLE IF NOT EXISTS relay_turn_receipts (
27217
+ command_id TEXT PRIMARY KEY,
27218
+ session_id TEXT NOT NULL,
27219
+ command_json TEXT NOT NULL,
27220
+ attempt_id TEXT NOT NULL,
27221
+ state TEXT NOT NULL CHECK (
27222
+ state IN ('dispatching', 'running', 'succeeded', 'failed', 'cancelled')
27223
+ )
27224
+ ) STRICT;
27225
+ `);
27226
+ }
27227
+ claimExecution = (commandId, sessionId, commandJson) => {
27228
+ this.#database.exec("BEGIN IMMEDIATE");
27229
+ try {
27230
+ const existing = this.#database.prepare(
27231
+ `SELECT session_id, command_json, attempt_id, state
27232
+ FROM relay_turn_receipts WHERE command_id = ?`
27233
+ ).get(commandId);
27234
+ if (typeof existing === "object" && existing !== null) {
27235
+ const storedSessionId = Reflect.get(existing, "session_id");
27236
+ const storedCommand = Reflect.get(existing, "command_json");
27237
+ const attemptId2 = Reflect.get(existing, "attempt_id");
27238
+ const state = Reflect.get(existing, "state");
27239
+ if (storedSessionId !== sessionId || storedCommand !== commandJson || typeof attemptId2 !== "string" || !isDaemonExecutionState(state)) {
27240
+ throw new Error(
27241
+ "The daemon command identity conflicts with its durable receipt"
27242
+ );
27243
+ }
27244
+ this.#database.exec("COMMIT");
27245
+ return { attemptId: attemptId2, commandId, kind: "duplicate", state };
27246
+ }
27247
+ const attemptId = crypto.randomUUID();
27248
+ this.#database.prepare(
27249
+ `INSERT INTO relay_turn_receipts (
27250
+ command_id, session_id, command_json, attempt_id, state
27251
+ ) VALUES (?, ?, ?, ?, 'dispatching')`
27252
+ ).run(commandId, sessionId, commandJson, attemptId);
27253
+ this.#database.exec("COMMIT");
27254
+ return {
27255
+ attemptId,
27256
+ commandId,
27257
+ kind: "accepted",
27258
+ state: "dispatching"
27259
+ };
27260
+ } catch (error61) {
27261
+ this.#database.exec("ROLLBACK");
27262
+ throw error61;
27263
+ }
27264
+ };
27265
+ transitionExecution = (commandId, state) => {
27266
+ const row = this.#database.prepare(`SELECT state FROM relay_turn_receipts WHERE command_id = ?`).get(commandId);
27267
+ const current = typeof row === "object" && row !== null ? Reflect.get(row, "state") : void 0;
27268
+ if (!isDaemonExecutionState(current)) {
27269
+ throw new Error("The daemon execution receipt does not exist");
27270
+ }
27271
+ if (current === state) {
27272
+ return;
27273
+ }
27274
+ const allowed = current === "dispatching" && (state === "running" || state === "failed" || state === "cancelled") || current === "running" && (state === "succeeded" || state === "failed" || state === "cancelled");
27275
+ if (!allowed) {
27276
+ throw new Error("The daemon execution transition is invalid");
27277
+ }
27278
+ this.#database.prepare(`UPDATE relay_turn_receipts SET state = ? WHERE command_id = ?`).run(state, commandId);
27279
+ };
27280
+ acknowledge = (acknowledgement) => {
27281
+ this.#database.prepare(
27282
+ `DELETE FROM relay_session_event_outbox
27283
+ WHERE event_id = ? AND session_id = ?`
27284
+ ).run(acknowledgement.eventId, acknowledgement.sessionId);
27285
+ };
27286
+ close = () => {
27287
+ this.#database.close();
27288
+ };
27289
+ enqueue = (sessionId, payload, attemptId = null) => {
27290
+ const sourceKey = attemptId === null ? `runtime:${sessionId}` : `attempt:${sessionId}:${attemptId}`;
27291
+ this.#database.exec("BEGIN IMMEDIATE");
27292
+ try {
27293
+ const row = this.#database.prepare(
27294
+ `SELECT next_source_seq FROM relay_session_event_sources
27295
+ WHERE source_key = ?`
27296
+ ).get(sourceKey);
27297
+ const storedSourceSeq = typeof row === "object" && row !== null ? Reflect.get(row, "next_source_seq") : void 0;
27298
+ const nextSourceSeq = typeof storedSourceSeq === "number" ? storedSourceSeq : 1;
27299
+ if (!Number.isSafeInteger(nextSourceSeq) || nextSourceSeq < 1) {
27300
+ throw new Error("SQLite returned an invalid event source sequence");
27301
+ }
27302
+ const envelope2 = {
27303
+ eventId: crypto.randomUUID(),
27304
+ kind: SESSION_EVENT_KIND,
27305
+ payload,
27306
+ sessionId,
27307
+ source: attemptId === null ? { kind: "runtime", sourceSeq: nextSourceSeq.toString() } : {
27308
+ attemptId,
27309
+ kind: "attempt",
27310
+ sourceSeq: nextSourceSeq.toString()
27311
+ }
27312
+ };
27313
+ const encoded = encodeSessionEventEnvelope(envelope2);
27314
+ this.#database.prepare(
27315
+ `INSERT INTO relay_session_event_sources (
27316
+ source_key, next_source_seq
27317
+ ) VALUES (?, ?)
27318
+ ON CONFLICT(source_key) DO UPDATE SET
27319
+ next_source_seq = excluded.next_source_seq`
27320
+ ).run(sourceKey, nextSourceSeq + 1);
27321
+ this.#database.prepare(
27322
+ `INSERT INTO relay_session_event_outbox (
27323
+ event_id, session_id, envelope_json
27324
+ ) VALUES (?, ?, ?)`
27325
+ ).run(envelope2.eventId, envelope2.sessionId, encoded);
27326
+ this.#database.exec("COMMIT");
27327
+ return encoded;
27328
+ } catch (error61) {
27329
+ this.#database.exec("ROLLBACK");
27330
+ throw error61;
27331
+ }
27332
+ };
27333
+ pending = () => this.#database.prepare(
27334
+ `SELECT envelope_json
27335
+ FROM relay_session_event_outbox
27336
+ ORDER BY ordinal`
27337
+ ).all().map(readPendingEnvelope);
27338
+ };
27339
+ function isDaemonExecutionState(value) {
27340
+ return value === "cancelled" || value === "dispatching" || value === "failed" || value === "running" || value === "succeeded";
27341
+ }
27342
+
26560
27343
  // src/relay-connection/timer.ts
26561
27344
  var SystemDaemonTimer = class {
26562
27345
  schedule = (callback, milliseconds) => {
@@ -26621,44 +27404,47 @@ var RelayConnectionRefresh = class {
26621
27404
  };
26622
27405
  };
26623
27406
  var DaemonAcpObserver = class {
26624
- #socket;
26625
- constructor(socket) {
26626
- this.#socket = socket;
27407
+ #record;
27408
+ constructor(record2) {
27409
+ this.#record = record2;
26627
27410
  }
26628
27411
  onCommands = (event) => {
26629
- send(this.#socket, encodeSessionCommandsUpdatedEvent(event));
27412
+ this.#record(event.sessionId, encodeSessionCommandsUpdatedEvent(event));
26630
27413
  return Promise.resolve();
26631
27414
  };
26632
27415
  onConfig = (event) => {
26633
- send(this.#socket, encodeSessionConfigUpdatedEvent(event));
27416
+ this.#record(event.sessionId, encodeSessionConfigUpdatedEvent(event));
26634
27417
  return Promise.resolve();
26635
27418
  };
26636
27419
  onContent = (event) => {
26637
- send(this.#socket, encodeAgentContentEvent(event));
27420
+ this.#record(event.sessionId, encodeAgentContentEvent(event));
26638
27421
  return Promise.resolve();
26639
27422
  };
26640
27423
  onElicitation = (event) => {
26641
- send(this.#socket, encodeSessionElicitationRequestedEvent(event));
27424
+ this.#record(
27425
+ event.sessionId,
27426
+ encodeSessionElicitationRequestedEvent(event)
27427
+ );
26642
27428
  return Promise.resolve();
26643
27429
  };
26644
27430
  onElicitationResolved = (event) => {
26645
- send(this.#socket, encodeSessionElicitationResolvedEvent(event));
27431
+ this.#record(event.sessionId, encodeSessionElicitationResolvedEvent(event));
26646
27432
  return Promise.resolve();
26647
27433
  };
26648
27434
  onInfo = (event) => {
26649
- send(this.#socket, encodeSessionInfoUpdatedEvent(event));
27435
+ this.#record(event.sessionId, encodeSessionInfoUpdatedEvent(event));
26650
27436
  return Promise.resolve();
26651
27437
  };
26652
27438
  onPermission = (event) => {
26653
- send(this.#socket, encodeSessionPermissionRequestedEvent(event));
27439
+ this.#record(event.sessionId, encodeSessionPermissionRequestedEvent(event));
26654
27440
  return Promise.resolve();
26655
27441
  };
26656
27442
  onPermissionResolved = (event) => {
26657
- send(this.#socket, encodeSessionPermissionResolvedEvent(event));
27443
+ this.#record(event.sessionId, encodeSessionPermissionResolvedEvent(event));
26658
27444
  return Promise.resolve();
26659
27445
  };
26660
27446
  onUsage = (event) => {
26661
- send(this.#socket, encodeSessionUsageUpdatedEvent(event));
27447
+ this.#record(event.sessionId, encodeSessionUsageUpdatedEvent(event));
26662
27448
  return Promise.resolve();
26663
27449
  };
26664
27450
  };
@@ -26710,7 +27496,6 @@ var DaemonInstallationObserver = class {
26710
27496
  encodeAgentInstallAwaitingApprovalEvent({
26711
27497
  agentId: state.agentId,
26712
27498
  kind: AGENT_INSTALL_AWAITING_APPROVAL_KIND,
26713
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26714
27499
  requestId: state.requestId
26715
27500
  })
26716
27501
  );
@@ -26724,7 +27509,6 @@ var DaemonInstallationObserver = class {
26724
27509
  encodeAgentInstallStartedEvent({
26725
27510
  agentId: state.agentId,
26726
27511
  kind: AGENT_INSTALL_STARTED_KIND,
26727
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26728
27512
  requestId: state.requestId
26729
27513
  })
26730
27514
  );
@@ -26734,7 +27518,6 @@ var DaemonInstallationObserver = class {
26734
27518
  encodeAgentInstallProgressEvent({
26735
27519
  agentId: state.agentId,
26736
27520
  kind: AGENT_INSTALL_PROGRESS_KIND,
26737
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26738
27521
  requestId: state.requestId,
26739
27522
  stage: state.stage
26740
27523
  })
@@ -26748,7 +27531,6 @@ var DaemonInstallationObserver = class {
26748
27531
  agentId: state.agentId,
26749
27532
  authenticationMayBeRequired: state.authenticationMayBeRequired,
26750
27533
  kind: AGENT_INSTALL_COMPLETED_KIND,
26751
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26752
27534
  requestId: state.requestId
26753
27535
  })
26754
27536
  );
@@ -26762,7 +27544,6 @@ var DaemonInstallationObserver = class {
26762
27544
  code: state.code,
26763
27545
  kind: AGENT_INSTALL_FAILED_KIND,
26764
27546
  message: state.message,
26765
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26766
27547
  requestId: state.requestId
26767
27548
  })
26768
27549
  );
@@ -26774,7 +27555,6 @@ var DaemonInstallationObserver = class {
26774
27555
  encodeAgentInstallCancelledEvent({
26775
27556
  agentId: state.agentId,
26776
27557
  kind: AGENT_INSTALL_CANCELLED_KIND,
26777
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26778
27558
  requestId: state.requestId
26779
27559
  })
26780
27560
  );
@@ -26822,20 +27602,25 @@ function send(socket, message) {
26822
27602
  }
26823
27603
  socket.send(message);
26824
27604
  }
26825
- function reportFailure(socket, command, code, message) {
26826
- if (socket.readyState !== WebSocket2.OPEN) {
26827
- return;
27605
+ function recordSessionEvent(outbox, socket, sessionId, payload, attemptId = null) {
27606
+ const envelope2 = outbox.enqueue(sessionId, payload, attemptId);
27607
+ if (socket.readyState === WebSocket2.OPEN) {
27608
+ socket.send(envelope2);
26828
27609
  }
26829
- send(
27610
+ }
27611
+ function reportFailure(outbox, socket, command, code, message, attemptId = null) {
27612
+ recordSessionEvent(
27613
+ outbox,
26830
27614
  socket,
27615
+ command.sessionId,
26831
27616
  encodeSessionFailedEvent({
26832
27617
  code,
26833
27618
  commandId: command.commandId,
26834
27619
  kind: SESSION_FAILED_KIND,
26835
27620
  message,
26836
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26837
27621
  sessionId: command.sessionId
26838
- })
27622
+ }),
27623
+ attemptId
26839
27624
  );
26840
27625
  }
26841
27626
  function operationErrorCode(error61) {
@@ -26860,7 +27645,6 @@ function reportOperationFailure(socket, requestId, sessionId, error61) {
26860
27645
  code: operationErrorCode(error61),
26861
27646
  kind: "session.operation.failed",
26862
27647
  message: operationErrorMessage(error61),
26863
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26864
27648
  requestId,
26865
27649
  sessionId
26866
27650
  })
@@ -26916,7 +27700,6 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
26916
27700
  entries: listing.entries,
26917
27701
  kind: "workspace.entries",
26918
27702
  parentDirectoryId: listing.parentDirectoryId,
26919
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26920
27703
  requestId: command.requestId
26921
27704
  })
26922
27705
  );
@@ -26924,11 +27707,11 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
26924
27707
  reportOperationFailure(socket, command.requestId, "", error61);
26925
27708
  }
26926
27709
  }
26927
- async function executeSessionPrepare(socket, command, config2, directories, audit, sessions, signal) {
27710
+ async function executeSessionPrepare(outbox, socket, command, config2, directories, audit, sessions, signal) {
26928
27711
  try {
26929
27712
  const resolved = await resolveSessionDirectories(
26930
27713
  directories,
26931
- command.bindingId,
27714
+ config2.bindingId,
26932
27715
  command.directoryId,
26933
27716
  command.additionalDirectoryIds,
26934
27717
  signal
@@ -26942,7 +27725,7 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26942
27725
  signal
26943
27726
  });
26944
27727
  const listing = await directories.list(
26945
- command.bindingId,
27728
+ config2.bindingId,
26946
27729
  command.directoryId,
26947
27730
  signal
26948
27731
  );
@@ -26951,8 +27734,10 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26951
27734
  event: "session_prepared",
26952
27735
  sessionId: command.sessionId
26953
27736
  });
26954
- send(
27737
+ recordSessionEvent(
27738
+ outbox,
26955
27739
  socket,
27740
+ command.sessionId,
26956
27741
  encodeSessionReadyEvent({
26957
27742
  additionalDirectories: resolved.additionalDirectoryEntries,
26958
27743
  agentId: command.agentId,
@@ -26964,7 +27749,6 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26964
27749
  directoryId: command.directoryId,
26965
27750
  directoryLabel: listing.directoryLabel,
26966
27751
  kind: "session.ready",
26967
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
26968
27752
  requestId: command.requestId,
26969
27753
  restored: prepared.restored,
26970
27754
  sessionId: command.sessionId
@@ -26974,11 +27758,11 @@ async function executeSessionPrepare(socket, command, config2, directories, audi
26974
27758
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
26975
27759
  }
26976
27760
  }
26977
- async function executeSessionConfigure(socket, command, config2, directories, audit, sessions, signal) {
27761
+ async function executeSessionConfigure(outbox, socket, command, config2, directories, audit, sessions, signal) {
26978
27762
  try {
26979
27763
  const resolved = await resolveSessionDirectories(
26980
27764
  directories,
26981
- command.bindingId,
27765
+ config2.bindingId,
26982
27766
  command.directoryId,
26983
27767
  command.additionalDirectoryIds,
26984
27768
  signal
@@ -27000,12 +27784,13 @@ async function executeSessionConfigure(socket, command, config2, directories, au
27000
27784
  event: "session_configured",
27001
27785
  sessionId: command.sessionId
27002
27786
  });
27003
- send(
27787
+ recordSessionEvent(
27788
+ outbox,
27004
27789
  socket,
27790
+ command.sessionId,
27005
27791
  encodeSessionConfigUpdatedEvent({
27006
27792
  configOptions,
27007
27793
  kind: "session.config.updated",
27008
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27009
27794
  requestId: command.requestId,
27010
27795
  sessionId: command.sessionId
27011
27796
  })
@@ -27014,31 +27799,33 @@ async function executeSessionConfigure(socket, command, config2, directories, au
27014
27799
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
27015
27800
  }
27016
27801
  }
27017
- async function executePrompt(socket, command, config2, directories, audit, sessions, signal) {
27802
+ async function executePrompt(outbox, socket, command, config2, directories, audit, sessions, attemptId, signal) {
27018
27803
  try {
27019
27804
  const resolved = await resolveSessionDirectories(
27020
27805
  directories,
27021
- command.bindingId,
27806
+ config2.bindingId,
27022
27807
  command.directoryId,
27023
27808
  command.additionalDirectoryIds,
27024
27809
  signal
27025
27810
  );
27026
27811
  const agent = config2.catalog.find(command.agentId);
27027
- const processAttemptId = randomUUID5();
27028
27812
  audit.record({
27029
27813
  commandId: command.commandId,
27030
27814
  event: "session_authorized",
27031
27815
  sessionId: command.sessionId
27032
27816
  });
27033
- send(
27817
+ outbox.transitionExecution(command.commandId, "running");
27818
+ recordSessionEvent(
27819
+ outbox,
27034
27820
  socket,
27821
+ command.sessionId,
27035
27822
  encodeSessionStartedEvent({
27036
27823
  commandId: command.commandId,
27037
27824
  kind: SESSION_STARTED_KIND,
27038
- processAttemptId,
27039
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27825
+ attemptId,
27040
27826
  sessionId: command.sessionId
27041
- })
27827
+ }),
27828
+ attemptId
27042
27829
  );
27043
27830
  const result = await sessions.runPrompt({
27044
27831
  additionalDirectories: resolved.additionalDirectories,
@@ -27047,38 +27834,43 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27047
27834
  cwd: resolved.cwd,
27048
27835
  images: command.images,
27049
27836
  onActivity: (activity) => {
27050
- send(
27837
+ recordSessionEvent(
27838
+ outbox,
27051
27839
  socket,
27840
+ command.sessionId,
27052
27841
  encodeAgentActivityEvent({
27053
27842
  activityId: activity.activityId,
27054
27843
  activityType: activity.activityType,
27055
27844
  commandId: command.commandId,
27056
27845
  content: activity.content,
27846
+ detail: activity.detail,
27057
27847
  input: activity.input,
27058
27848
  kind: AGENT_ACTIVITY_KIND,
27059
27849
  locations: activity.locations,
27060
27850
  name: activity.name,
27061
27851
  output: activity.output,
27062
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27063
27852
  sequence: activity.sequence,
27064
27853
  sessionId: command.sessionId,
27065
27854
  status: activity.status,
27066
27855
  title: activity.title,
27067
27856
  toolKind: activity.toolKind
27068
- })
27857
+ }),
27858
+ attemptId
27069
27859
  );
27070
27860
  return Promise.resolve();
27071
27861
  },
27072
27862
  onText: (text) => {
27073
- send(
27863
+ recordSessionEvent(
27864
+ outbox,
27074
27865
  socket,
27866
+ command.sessionId,
27075
27867
  encodeAgentMessageDeltaEvent({
27076
27868
  commandId: command.commandId,
27077
27869
  kind: AGENT_MESSAGE_DELTA_KIND,
27078
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27079
27870
  sessionId: command.sessionId,
27080
27871
  text
27081
- })
27872
+ }),
27873
+ attemptId
27082
27874
  );
27083
27875
  return Promise.resolve();
27084
27876
  },
@@ -27087,15 +27879,21 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27087
27879
  sessionId: command.sessionId,
27088
27880
  signal
27089
27881
  });
27090
- send(
27882
+ recordSessionEvent(
27883
+ outbox,
27091
27884
  socket,
27885
+ command.sessionId,
27092
27886
  encodeSessionCompletedEvent({
27093
27887
  commandId: command.commandId,
27094
27888
  kind: SESSION_COMPLETED_KIND,
27095
- protocolVersion: MOBIUS_PROTOCOL_VERSION,
27096
27889
  sessionId: command.sessionId,
27097
27890
  stopReason: result.stopReason
27098
- })
27891
+ }),
27892
+ attemptId
27893
+ );
27894
+ outbox.transitionExecution(
27895
+ command.commandId,
27896
+ result.stopReason === "cancelled" ? "cancelled" : "succeeded"
27099
27897
  );
27100
27898
  audit.record({
27101
27899
  commandId: command.commandId,
@@ -27110,11 +27908,14 @@ async function executePrompt(socket, command, config2, directories, audit, sessi
27110
27908
  });
27111
27909
  const code = operationErrorCode(error61);
27112
27910
  reportFailure(
27911
+ outbox,
27113
27912
  socket,
27114
27913
  command,
27115
27914
  code === "session_operation_failed" ? "agent_execution_failed" : code,
27116
- code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error61)
27915
+ code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error61),
27916
+ attemptId
27117
27917
  );
27918
+ outbox.transitionExecution(command.commandId, "failed");
27118
27919
  console.error("Mobius daemon command failed", error61);
27119
27920
  }
27120
27921
  }
@@ -27132,15 +27933,28 @@ function waitForRelayRetry(signal, timer) {
27132
27933
  signal.addEventListener("abort", finish, { once: true });
27133
27934
  });
27134
27935
  }
27135
- async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, signal, timer) {
27936
+ async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, signal, timer) {
27136
27937
  const relayUrl = new URL(config2.relayUrl);
27137
27938
  relayUrl.searchParams.set("liveness", "1");
27138
27939
  const socket = await connectRelay(relayUrl, signal);
27139
27940
  const activeTurns = /* @__PURE__ */ new Map();
27941
+ const activeAttemptIds = /* @__PURE__ */ new Map();
27140
27942
  const connectionController = new AbortController();
27141
27943
  const nativeRequests = /* @__PURE__ */ new Map();
27142
- sessions.setObserver(new DaemonAcpObserver(socket));
27944
+ const record2 = (sessionId, payload) => {
27945
+ recordSessionEvent(
27946
+ outbox,
27947
+ socket,
27948
+ sessionId,
27949
+ payload,
27950
+ activeAttemptIds.get(sessionId) ?? null
27951
+ );
27952
+ };
27953
+ sessions.setObserver(new DaemonAcpObserver(record2));
27143
27954
  installationObserver.connect(socket);
27955
+ for (const pending of outbox.pending()) {
27956
+ send(socket, pending);
27957
+ }
27144
27958
  try {
27145
27959
  await new Promise((resolve5, reject) => {
27146
27960
  let finished = false;
@@ -27214,6 +28028,10 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27214
28028
  }
27215
28029
  try {
27216
28030
  const kind = decodeMessageKind(encoded);
28031
+ if (kind === SESSION_EVENT_ACK_KIND) {
28032
+ outbox.acknowledge(decodeSessionEventAcknowledgement(encoded));
28033
+ return;
28034
+ }
27217
28035
  if (kind === NATIVE_SESSION_CANCEL_KIND) {
27218
28036
  const command2 = decodeNativeSessionCancel(encoded);
27219
28037
  const pending = nativeRequests.get(command2.requestId);
@@ -27371,6 +28189,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27371
28189
  if (kind === SESSION_PREPARE_KIND) {
27372
28190
  const command2 = decodeSessionPrepareCommand(encoded);
27373
28191
  void executeSessionPrepare(
28192
+ outbox,
27374
28193
  socket,
27375
28194
  command2,
27376
28195
  config2,
@@ -27384,6 +28203,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27384
28203
  if (kind === SESSION_CONFIGURE_KIND) {
27385
28204
  const command2 = decodeSessionConfigureCommand(encoded);
27386
28205
  void executeSessionConfigure(
28206
+ outbox,
27387
28207
  socket,
27388
28208
  command2,
27389
28209
  config2,
@@ -27449,28 +28269,36 @@ async function runRelayConnection(config2, directories, audit, sessions, install
27449
28269
  }
27450
28270
  const command = decodeSessionPromptCommand(encoded);
27451
28271
  if (activeTurns.has(command.commandId)) {
27452
- reportFailure(
27453
- socket,
27454
- command,
27455
- "duplicate_command",
27456
- "The command is already running"
27457
- );
28272
+ return;
28273
+ }
28274
+ const receipt = outbox.claimExecution(
28275
+ command.commandId,
28276
+ command.sessionId,
28277
+ encoded
28278
+ );
28279
+ if (receipt.kind === "duplicate") {
27458
28280
  return;
27459
28281
  }
27460
28282
  const turn = new ActiveDaemonTurn(command, new AbortController());
27461
28283
  activeTurns.set(command.commandId, turn);
28284
+ activeAttemptIds.set(command.sessionId, receipt.attemptId);
27462
28285
  void executePrompt(
28286
+ outbox,
27463
28287
  socket,
27464
28288
  command,
27465
28289
  config2,
27466
28290
  directories,
27467
28291
  audit,
27468
28292
  sessions,
28293
+ receipt.attemptId,
27469
28294
  turn.signal
27470
28295
  ).catch((error61) => {
27471
28296
  console.error("Mobius daemon turn failed", error61);
27472
28297
  }).finally(() => {
27473
28298
  activeTurns.delete(command.commandId);
28299
+ if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
28300
+ activeAttemptIds.delete(command.sessionId);
28301
+ }
27474
28302
  connectionRefresh.afterTurnFinished();
27475
28303
  });
27476
28304
  } catch (error61) {
@@ -27519,6 +28347,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27519
28347
  specifications
27520
28348
  ).prepare(signal);
27521
28349
  const sessionStore = new SqliteAcpSessionStore(config2.auditDatabasePath);
28350
+ const outbox = new SessionEventOutbox(config2.auditDatabasePath);
27522
28351
  const sessions = new AcpSessionManager(
27523
28352
  new NullAcpSessionObserver(),
27524
28353
  sessionStore
@@ -27554,6 +28383,7 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27554
28383
  installations,
27555
28384
  installationObserver,
27556
28385
  nativeSessions,
28386
+ outbox,
27557
28387
  signal,
27558
28388
  timer
27559
28389
  );
@@ -27576,7 +28406,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
27576
28406
  try {
27577
28407
  await sessions.close();
27578
28408
  } finally {
27579
- sessionStore.close();
28409
+ try {
28410
+ sessionStore.close();
28411
+ } finally {
28412
+ outbox.close();
28413
+ }
27580
28414
  }
27581
28415
  }
27582
28416
  }