@moxt-ai/mobius 0.0.16 → 0.0.18

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 (87) hide show
  1. package/dist/acp/session-config/grok-build-session-config.d.ts +10 -0
  2. package/dist/acp/session-config/grok-build-session-config.d.ts.map +1 -0
  3. package/dist/acp/session-config/grok-build-session-config.js +202 -0
  4. package/dist/acp/session-config/grok-build-session-config.js.map +1 -0
  5. package/dist/acp/session-config/session-config-protocol.d.ts +32 -0
  6. package/dist/acp/session-config/session-config-protocol.d.ts.map +1 -0
  7. package/dist/acp/session-config/session-config-protocol.js +237 -0
  8. package/dist/acp/session-config/session-config-protocol.js.map +1 -0
  9. package/dist/acp/session-config/session-config-registry.d.ts +3 -0
  10. package/dist/acp/session-config/session-config-registry.d.ts.map +1 -0
  11. package/dist/acp/session-config/session-config-registry.js +8 -0
  12. package/dist/acp/session-config/session-config-registry.js.map +1 -0
  13. package/dist/acp/session-manager.d.ts.map +1 -1
  14. package/dist/acp/session-manager.js +29 -155
  15. package/dist/acp/session-manager.js.map +1 -1
  16. package/dist/agent-catalog/agent-discovery.d.ts +19 -9
  17. package/dist/agent-catalog/agent-discovery.d.ts.map +1 -1
  18. package/dist/agent-catalog/agent-discovery.js +32 -16
  19. package/dist/agent-catalog/agent-discovery.js.map +1 -1
  20. package/dist/agent-catalog/agent-specification.d.ts +0 -1
  21. package/dist/agent-catalog/agent-specification.d.ts.map +1 -1
  22. package/dist/agent-catalog/agent-specification.js +0 -2
  23. package/dist/agent-catalog/agent-specification.js.map +1 -1
  24. package/dist/agent-catalog/agents/cursor-cli-agent.d.ts +0 -1
  25. package/dist/agent-catalog/agents/cursor-cli-agent.d.ts.map +1 -1
  26. package/dist/agent-catalog/agents/cursor-cli-agent.js +0 -1
  27. package/dist/agent-catalog/agents/cursor-cli-agent.js.map +1 -1
  28. package/dist/agent-catalog/discover-agent.d.ts.map +1 -1
  29. package/dist/agent-catalog/discover-agent.js +30 -21
  30. package/dist/agent-catalog/discover-agent.js.map +1 -1
  31. package/dist/agent-catalog/discover-local-agents.d.ts +0 -1
  32. package/dist/agent-catalog/discover-local-agents.d.ts.map +1 -1
  33. package/dist/agent-catalog/discover-local-agents.js +1 -1
  34. package/dist/agent-catalog/discover-local-agents.js.map +1 -1
  35. package/dist/agent-catalog/local-agent.d.ts +12 -1
  36. package/dist/agent-catalog/local-agent.d.ts.map +1 -1
  37. package/dist/agent-catalog/local-agent.js +16 -0
  38. package/dist/agent-catalog/local-agent.js.map +1 -1
  39. package/dist/agent-catalog/publish-agent-catalog.d.ts.map +1 -1
  40. package/dist/agent-catalog/publish-agent-catalog.js +3 -4
  41. package/dist/agent-catalog/publish-agent-catalog.js.map +1 -1
  42. package/dist/agent-installation/agent-installation-manager.d.ts.map +1 -1
  43. package/dist/agent-installation/agent-installation-manager.js +6 -7
  44. package/dist/agent-installation/agent-installation-manager.js.map +1 -1
  45. package/dist/agent-installation/fixed-installation-executor.d.ts +2 -3
  46. package/dist/agent-installation/fixed-installation-executor.d.ts.map +1 -1
  47. package/dist/agent-installation/fixed-installation-executor.js +47 -67
  48. package/dist/agent-installation/fixed-installation-executor.js.map +1 -1
  49. package/dist/agent-installation/managed-agent-archive.d.ts +2 -5
  50. package/dist/agent-installation/managed-agent-archive.d.ts.map +1 -1
  51. package/dist/agent-installation/managed-agent-archive.js +1 -1
  52. package/dist/agent-installation/managed-agent-archive.js.map +1 -1
  53. package/dist/agent-installation/verified-download.d.ts +0 -4
  54. package/dist/agent-installation/verified-download.d.ts.map +1 -1
  55. package/dist/agent-installation/verified-download.js +1 -1
  56. package/dist/agent-installation/verified-download.js.map +1 -1
  57. package/dist/cli.js +1128 -1782
  58. package/dist/cli.js.map +4 -4
  59. package/dist/index.js +1129 -1783
  60. package/dist/index.js.map +4 -4
  61. package/dist/pairing/pair-local-machine.d.ts.map +1 -1
  62. package/dist/pairing/pair-local-machine.js +4 -5
  63. package/dist/pairing/pair-local-machine.js.map +1 -1
  64. package/dist/run-daemon.d.ts.map +1 -1
  65. package/dist/run-daemon.js +162 -57
  66. package/dist/run-daemon.js.map +1 -1
  67. package/package.json +1 -1
  68. package/dist/agent-installation/automatic-adapter-provisioner.d.ts +0 -19
  69. package/dist/agent-installation/automatic-adapter-provisioner.d.ts.map +0 -1
  70. package/dist/agent-installation/automatic-adapter-provisioner.js +0 -125
  71. package/dist/agent-installation/automatic-adapter-provisioner.js.map +0 -1
  72. package/dist/agent-installation/fixed-agent-install-recipe.d.ts +0 -20
  73. package/dist/agent-installation/fixed-agent-install-recipe.d.ts.map +0 -1
  74. package/dist/agent-installation/fixed-agent-install-recipe.js +0 -18
  75. package/dist/agent-installation/fixed-agent-install-recipe.js.map +0 -1
  76. package/dist/agent-installation/fixed-agent-install-recipes.d.ts +0 -26
  77. package/dist/agent-installation/fixed-agent-install-recipes.d.ts.map +0 -1
  78. package/dist/agent-installation/fixed-agent-install-recipes.js +0 -301
  79. package/dist/agent-installation/fixed-agent-install-recipes.js.map +0 -1
  80. package/dist/agent-installation/grok-build-install-recipe.d.ts +0 -12
  81. package/dist/agent-installation/grok-build-install-recipe.d.ts.map +0 -1
  82. package/dist/agent-installation/grok-build-install-recipe.js +0 -102
  83. package/dist/agent-installation/grok-build-install-recipe.js.map +0 -1
  84. package/dist/agent-installation/workbuddy-install-recipe.d.ts +0 -12
  85. package/dist/agent-installation/workbuddy-install-recipe.d.ts.map +0 -1
  86. package/dist/agent-installation/workbuddy-install-recipe.js +0 -51
  87. package/dist/agent-installation/workbuddy-install-recipe.js.map +0 -1
package/dist/index.js CHANGED
@@ -2007,8 +2007,8 @@ function emoji() {
2007
2007
  }
2008
2008
  var ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;
2009
2009
  var ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
2010
- var mac = (delimiter3) => {
2011
- const escapedDelim = escapeRegex(delimiter3 ?? ":");
2010
+ var mac = (delimiter2) => {
2011
+ const escapedDelim = escapeRegex(delimiter2 ?? ":");
2012
2012
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
2013
2013
  };
2014
2014
  var cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
@@ -18981,13 +18981,13 @@ var SESSION_ELICITATION_RESPOND_KIND = "session.elicitation.respond";
18981
18981
  var SESSION_ELICITATION_RESOLVED_KIND = "session.elicitation.resolved";
18982
18982
  var SESSION_OPERATION_FAILED_KIND = "session.operation.failed";
18983
18983
  var AGENT_CONTENT_KIND = "agent.content";
18984
- var AGENT_INSTALL_REQUEST_KIND = "agent.install.request";
18985
- var AGENT_INSTALL_CANCEL_KIND = "agent.install.cancel";
18986
- var AGENT_INSTALL_STARTED_KIND = "agent.install.started";
18987
- var AGENT_INSTALL_PROGRESS_KIND = "agent.install.progress";
18988
- var AGENT_INSTALL_COMPLETED_KIND = "agent.install.completed";
18989
- var AGENT_INSTALL_FAILED_KIND = "agent.install.failed";
18990
- var AGENT_INSTALL_CANCELLED_KIND = "agent.install.cancelled";
18984
+ var AGENT_INSTALL_REQUEST_KIND = "agent.integration.install.request";
18985
+ var AGENT_INSTALL_CANCEL_KIND = "agent.integration.install.cancel";
18986
+ var AGENT_INSTALL_STARTED_KIND = "agent.integration.install.started";
18987
+ var AGENT_INSTALL_PROGRESS_KIND = "agent.integration.install.progress";
18988
+ var AGENT_INSTALL_COMPLETED_KIND = "agent.integration.install.completed";
18989
+ var AGENT_INSTALL_FAILED_KIND = "agent.integration.install.failed";
18990
+ var AGENT_INSTALL_CANCELLED_KIND = "agent.integration.install.cancelled";
18991
18991
  var IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}$/;
18992
18992
  var DIRECTORY_IDENTIFIER_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,2047}$/;
18993
18993
  var IDENTIFIER = external_exports.string().min(1).max(128).regex(IDENTIFIER_PATTERN);
@@ -21025,6 +21025,22 @@ var InstallableAgentDefinition = class {
21025
21025
  this.label = label;
21026
21026
  }
21027
21027
  };
21028
+ var MissingAgentDefinition = class extends InstallableAgentDefinition {
21029
+ status = "agent_not_installed";
21030
+ constructor(id, label) {
21031
+ super(id, label);
21032
+ }
21033
+ };
21034
+ var AgentIntegrationDefinition = class extends InstallableAgentDefinition {
21035
+ agentPath;
21036
+ agentVersion;
21037
+ status = "integration_not_installed";
21038
+ constructor(id, label, agentPath, agentVersion) {
21039
+ super(id, label);
21040
+ this.agentPath = agentPath;
21041
+ this.agentVersion = agentVersion;
21042
+ }
21043
+ };
21028
21044
  var LocalAgentCatalogSnapshot = class {
21029
21045
  agents;
21030
21046
  installableAgents;
@@ -21139,7 +21155,7 @@ function loadDaemonConfig() {
21139
21155
  // src/acp/session-manager.ts
21140
21156
  import { spawn as spawn2 } from "node:child_process";
21141
21157
  import {
21142
- methods as methods2,
21158
+ methods as methods3,
21143
21159
  ndJsonStream,
21144
21160
  PROTOCOL_VERSION,
21145
21161
  RequestError
@@ -21653,6 +21669,491 @@ var nativeSessionPageSchema = external_exports.object({
21653
21669
  nextCursor: external_exports.string().min(1).max(4096).nullish()
21654
21670
  }).readonly();
21655
21671
 
21672
+ // src/acp/session-config/session-config-protocol.ts
21673
+ import { methods as methods2 } from "@agentclientprotocol/sdk";
21674
+ var AGENT_DEFAULT_REASONING_EFFORT = "agent_default";
21675
+ var MAXIMUM_CONFIG_OPTIONS = 100;
21676
+ var SessionConfigProtocolError = class extends Error {
21677
+ code = "invalid_session_configuration_response";
21678
+ constructor(message, options = {}) {
21679
+ super(message, options);
21680
+ this.name = "SessionConfigProtocolError";
21681
+ }
21682
+ };
21683
+ function isRecord3(value) {
21684
+ return typeof value === "object" && value !== null && !Array.isArray(value);
21685
+ }
21686
+ function readString2(value, fallback = "") {
21687
+ return typeof value === "string" ? value : fallback;
21688
+ }
21689
+ function truncate2(value, maximum) {
21690
+ return value.length <= maximum ? value : value.slice(0, maximum);
21691
+ }
21692
+ function readBoolean(value, fallback = false) {
21693
+ return typeof value === "boolean" ? value : fallback;
21694
+ }
21695
+ function normalizeConfigValue(option, groupId = "", groupName = "") {
21696
+ return {
21697
+ description: truncate2(readString2(option["description"]), 500),
21698
+ groupId: truncate2(groupId, 128),
21699
+ groupName: truncate2(groupName, 255),
21700
+ name: truncate2(
21701
+ readString2(option["name"], readString2(option["value"])),
21702
+ 255
21703
+ ),
21704
+ value: truncate2(readString2(option["value"]), 500)
21705
+ };
21706
+ }
21707
+ function normalizeConfigValues(value) {
21708
+ if (!Array.isArray(value)) {
21709
+ return [];
21710
+ }
21711
+ const normalized = [];
21712
+ for (const entry of value) {
21713
+ if (!isRecord3(entry)) {
21714
+ continue;
21715
+ }
21716
+ const groupedOptions = entry["options"];
21717
+ if (Array.isArray(groupedOptions)) {
21718
+ const groupId = readString2(entry["group"]);
21719
+ const groupName = readString2(entry["name"]);
21720
+ for (const groupedOption of groupedOptions) {
21721
+ if (isRecord3(groupedOption)) {
21722
+ normalized.push(
21723
+ normalizeConfigValue(groupedOption, groupId, groupName)
21724
+ );
21725
+ }
21726
+ }
21727
+ continue;
21728
+ }
21729
+ normalized.push(normalizeConfigValue(entry));
21730
+ }
21731
+ return normalized.filter((entry) => entry.value.length > 0).slice(0, 500);
21732
+ }
21733
+ function normalizeConfigOptions(value, modes) {
21734
+ const normalized = [];
21735
+ if (Array.isArray(value)) {
21736
+ for (const option of value) {
21737
+ if (!isRecord3(option)) {
21738
+ continue;
21739
+ }
21740
+ const id = truncate2(readString2(option["id"]), 128);
21741
+ const name = truncate2(readString2(option["name"], id), 255);
21742
+ if (id.length === 0 || name.length === 0) {
21743
+ continue;
21744
+ }
21745
+ if (option["type"] === "boolean") {
21746
+ normalized.push({
21747
+ booleanValue: readBoolean(option["currentValue"]),
21748
+ category: truncate2(readString2(option["category"]), 128),
21749
+ currentValue: "",
21750
+ description: truncate2(readString2(option["description"]), 500),
21751
+ id,
21752
+ name,
21753
+ type: "boolean",
21754
+ values: []
21755
+ });
21756
+ continue;
21757
+ }
21758
+ if (option["type"] === "select") {
21759
+ const values = normalizeConfigValues(option["options"]);
21760
+ const currentValue = truncate2(readString2(option["currentValue"]), 500);
21761
+ if (currentValue.length > 0 && values.some((entry) => entry.value === currentValue)) {
21762
+ normalized.push({
21763
+ booleanValue: false,
21764
+ category: truncate2(readString2(option["category"]), 128),
21765
+ currentValue,
21766
+ description: truncate2(readString2(option["description"]), 500),
21767
+ id,
21768
+ name,
21769
+ type: "select",
21770
+ values
21771
+ });
21772
+ }
21773
+ }
21774
+ }
21775
+ }
21776
+ if (isRecord3(modes)) {
21777
+ const values = [];
21778
+ const availableModes = modes["availableModes"];
21779
+ if (Array.isArray(availableModes)) {
21780
+ for (const mode of availableModes) {
21781
+ if (!isRecord3(mode)) {
21782
+ continue;
21783
+ }
21784
+ const id = truncate2(readString2(mode["id"]), 500);
21785
+ if (id.length === 0) {
21786
+ continue;
21787
+ }
21788
+ values.push({
21789
+ description: truncate2(readString2(mode["description"]), 500),
21790
+ groupId: "",
21791
+ groupName: "",
21792
+ name: truncate2(readString2(mode["name"], id), 255),
21793
+ value: id
21794
+ });
21795
+ }
21796
+ }
21797
+ const currentValue = truncate2(readString2(modes["currentModeId"]), 500);
21798
+ if (currentValue.length > 0 && values.some((entry) => entry.value === currentValue) && !normalized.some((entry) => entry.category === "mode")) {
21799
+ normalized.unshift({
21800
+ booleanValue: false,
21801
+ category: "mode",
21802
+ currentValue,
21803
+ description: "Agent session mode",
21804
+ id: "mode",
21805
+ name: "Mode",
21806
+ type: "select",
21807
+ values
21808
+ });
21809
+ }
21810
+ }
21811
+ return normalized.slice(0, 100);
21812
+ }
21813
+ function ensureReasoningEffortOption(current) {
21814
+ if (current.some((option) => option.category === "thought_level")) {
21815
+ return current;
21816
+ }
21817
+ const unavailable = {
21818
+ booleanValue: false,
21819
+ category: "thought_level",
21820
+ currentValue: AGENT_DEFAULT_REASONING_EFFORT,
21821
+ description: "This Agent does not expose adjustable reasoning effort for the selected model.",
21822
+ id: "reasoning_effort",
21823
+ name: "Reasoning effort",
21824
+ type: "select",
21825
+ values: [
21826
+ {
21827
+ description: "Selected by the Agent",
21828
+ groupId: "",
21829
+ groupName: "",
21830
+ name: "Agent default",
21831
+ value: AGENT_DEFAULT_REASONING_EFFORT
21832
+ }
21833
+ ]
21834
+ };
21835
+ const modelIndex = current.findIndex((option) => option.category === "model");
21836
+ if (current.length < MAXIMUM_CONFIG_OPTIONS) {
21837
+ if (modelIndex < 0) {
21838
+ return [...current, unavailable];
21839
+ }
21840
+ return [
21841
+ ...current.slice(0, modelIndex + 1),
21842
+ unavailable,
21843
+ ...current.slice(modelIndex + 1)
21844
+ ];
21845
+ }
21846
+ if (modelIndex < 0) {
21847
+ return [...current.slice(0, MAXIMUM_CONFIG_OPTIONS - 1), unavailable];
21848
+ }
21849
+ if (modelIndex < MAXIMUM_CONFIG_OPTIONS - 1) {
21850
+ return [
21851
+ ...current.slice(0, modelIndex + 1),
21852
+ unavailable,
21853
+ ...current.slice(modelIndex + 1, MAXIMUM_CONFIG_OPTIONS - 1)
21854
+ ];
21855
+ }
21856
+ const model = current[modelIndex];
21857
+ if (model === void 0) {
21858
+ return [...current.slice(0, MAXIMUM_CONFIG_OPTIONS - 1), unavailable];
21859
+ }
21860
+ return [...current.slice(0, MAXIMUM_CONFIG_OPTIONS - 2), model, unavailable];
21861
+ }
21862
+ function normalizeStandardLifecycle(response) {
21863
+ const lifecycle = isRecord3(response) ? response : {};
21864
+ return ensureReasoningEffortOption(
21865
+ normalizeConfigOptions(lifecycle["configOptions"], lifecycle["modes"])
21866
+ );
21867
+ }
21868
+ function replaceStandardConfigOptions(current, value) {
21869
+ const next = normalizeConfigOptions(value, void 0);
21870
+ const withMode = next.some((option) => option.category === "mode") ? next : [
21871
+ ...current.filter((option) => option.category === "mode"),
21872
+ ...next
21873
+ ].slice(0, 100);
21874
+ return ensureReasoningEffortOption(withMode);
21875
+ }
21876
+ function updateCurrentValue(current, configId, value) {
21877
+ return current.map(
21878
+ (option) => option.id === configId ? { ...option, currentValue: value } : option
21879
+ );
21880
+ }
21881
+ var StandardSessionConfigProtocol = class {
21882
+ configure = async (current, change, nativeSessionId, transport) => {
21883
+ const existing = current.find((option) => option.id === change.configId);
21884
+ if (existing === void 0) {
21885
+ return current;
21886
+ }
21887
+ if (existing.type === "select" && existing.category === "mode") {
21888
+ await transport.request(
21889
+ methods2.agent.session.setMode,
21890
+ { modeId: change.value, sessionId: nativeSessionId },
21891
+ "ACP agent exited while setting the session mode",
21892
+ change.signal
21893
+ );
21894
+ return updateCurrentValue(current, existing.id, change.value);
21895
+ }
21896
+ const params = existing.type === "boolean" ? {
21897
+ configId: existing.id,
21898
+ sessionId: nativeSessionId,
21899
+ type: "boolean",
21900
+ value: change.booleanValue
21901
+ } : {
21902
+ configId: existing.id,
21903
+ sessionId: nativeSessionId,
21904
+ value: change.value
21905
+ };
21906
+ const response = await transport.request(
21907
+ methods2.agent.session.setConfigOption,
21908
+ params,
21909
+ "ACP agent exited while changing session configuration",
21910
+ change.signal
21911
+ );
21912
+ if (!isRecord3(response) || !Array.isArray(response["configOptions"])) {
21913
+ throw new SessionConfigProtocolError(
21914
+ "The Agent returned an invalid session configuration response"
21915
+ );
21916
+ }
21917
+ return replaceStandardConfigOptions(current, response["configOptions"]);
21918
+ };
21919
+ normalizeLifecycle = (response) => normalizeStandardLifecycle(response);
21920
+ normalizeUpdate = (current, value) => replaceStandardConfigOptions(current, value);
21921
+ };
21922
+ var standardSessionConfigProtocol = new StandardSessionConfigProtocol();
21923
+
21924
+ // src/acp/session-config/grok-build-session-config.ts
21925
+ var LEGACY_MODEL_CONFIG_ID = "grok_build_legacy_model";
21926
+ var LEGACY_REASONING_EFFORT_CONFIG_ID = "grok_build_legacy_reasoning_effort";
21927
+ function legacyOptions(response) {
21928
+ if (!isRecord3(response)) {
21929
+ return [];
21930
+ }
21931
+ const metadata = response["_meta"];
21932
+ if (!isRecord3(metadata)) {
21933
+ return [];
21934
+ }
21935
+ const sessionConfig = metadata["x.ai/sessionConfig"];
21936
+ if (!isRecord3(sessionConfig) || !Array.isArray(sessionConfig["options"])) {
21937
+ return [];
21938
+ }
21939
+ return sessionConfig["options"].slice(0, 500).filter(isRecord3);
21940
+ }
21941
+ function legacyValue(option) {
21942
+ const value = readString2(option["id"]);
21943
+ return {
21944
+ description: readString2(option["description"]).slice(0, 500),
21945
+ groupId: "",
21946
+ groupName: "",
21947
+ name: readString2(option["label"], value).slice(0, 255),
21948
+ value: value.slice(0, 500)
21949
+ };
21950
+ }
21951
+ function modelsRecord(response) {
21952
+ if (!isRecord3(response) || !isRecord3(response["models"])) {
21953
+ return {};
21954
+ }
21955
+ return response["models"];
21956
+ }
21957
+ function legacyModelOptions(response) {
21958
+ const options = legacyOptions(response);
21959
+ const models = modelsRecord(response);
21960
+ const values = [];
21961
+ for (const option of options) {
21962
+ if (option["category"] === "model") {
21963
+ const value = legacyValue(option);
21964
+ if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
21965
+ values.push(value);
21966
+ }
21967
+ }
21968
+ }
21969
+ if (values.length === 0 && Array.isArray(models["availableModels"])) {
21970
+ for (const model of models["availableModels"]) {
21971
+ if (!isRecord3(model)) {
21972
+ continue;
21973
+ }
21974
+ const value = readString2(model["modelId"]).slice(0, 500);
21975
+ if (value.length === 0) {
21976
+ continue;
21977
+ }
21978
+ if (!values.some((existing) => existing.value === value)) {
21979
+ values.push({
21980
+ description: "",
21981
+ groupId: "",
21982
+ groupName: "",
21983
+ name: readString2(model["name"], value).slice(0, 255),
21984
+ value
21985
+ });
21986
+ }
21987
+ }
21988
+ }
21989
+ const selected = options.find(
21990
+ (option) => option["category"] === "model" && option["selected"] === true
21991
+ );
21992
+ const currentValue = readString2(
21993
+ models["currentModelId"],
21994
+ selected === void 0 ? "" : readString2(selected["id"])
21995
+ ).slice(0, 500);
21996
+ if (values.length === 0 || !values.some((value) => value.value === currentValue)) {
21997
+ return [];
21998
+ }
21999
+ const result = {
22000
+ booleanValue: false,
22001
+ category: "model",
22002
+ currentValue,
22003
+ description: "Model used by Grok Build",
22004
+ id: LEGACY_MODEL_CONFIG_ID,
22005
+ name: "Model",
22006
+ type: "select",
22007
+ values: values.slice(0, 500)
22008
+ };
22009
+ return [result];
22010
+ }
22011
+ function legacyReasoningEffortOptions(response) {
22012
+ const options = legacyOptions(response);
22013
+ const values = [];
22014
+ for (const option of options) {
22015
+ if (option["category"] !== "mode") {
22016
+ continue;
22017
+ }
22018
+ const value = legacyValue(option);
22019
+ if (value.value.length > 0 && !values.some((existing) => existing.value === value.value)) {
22020
+ values.push(value);
22021
+ }
22022
+ }
22023
+ if (values.length === 0) {
22024
+ return [];
22025
+ }
22026
+ const selected = options.find(
22027
+ (option) => option["category"] === "mode" && option["selected"] === true
22028
+ );
22029
+ if (selected === void 0) {
22030
+ values.unshift({
22031
+ description: "Use the selected model's default reasoning effort",
22032
+ groupId: "",
22033
+ groupName: "",
22034
+ name: "Agent default",
22035
+ value: AGENT_DEFAULT_REASONING_EFFORT
22036
+ });
22037
+ }
22038
+ const currentValue = selected === void 0 ? AGENT_DEFAULT_REASONING_EFFORT : readString2(selected["id"], AGENT_DEFAULT_REASONING_EFFORT);
22039
+ if (!values.some((value) => value.value === currentValue)) {
22040
+ return [];
22041
+ }
22042
+ const result = {
22043
+ booleanValue: false,
22044
+ category: "thought_level",
22045
+ currentValue,
22046
+ description: "Reasoning effort used by Grok Build",
22047
+ id: LEGACY_REASONING_EFFORT_CONFIG_ID,
22048
+ name: "Reasoning effort",
22049
+ type: "select",
22050
+ values: values.slice(0, 500)
22051
+ };
22052
+ return [result];
22053
+ }
22054
+ function normalizeGrokLifecycle(response) {
22055
+ const lifecycle = isRecord3(response) ? response : {};
22056
+ const standard = normalizeConfigOptions(
22057
+ lifecycle["configOptions"],
22058
+ lifecycle["modes"]
22059
+ );
22060
+ const normalized = [...standard];
22061
+ if (!normalized.some((option) => option.category === "model")) {
22062
+ normalized.push(...legacyModelOptions(response));
22063
+ }
22064
+ if (!normalized.some((option) => option.category === "thought_level")) {
22065
+ const efforts = legacyReasoningEffortOptions(response);
22066
+ if (efforts.length > 0) {
22067
+ const modelIndex = normalized.findIndex(
22068
+ (option) => option.category === "model"
22069
+ );
22070
+ normalized.splice(
22071
+ modelIndex < 0 ? normalized.length : modelIndex + 1,
22072
+ 0,
22073
+ ...efforts
22074
+ );
22075
+ }
22076
+ }
22077
+ return ensureReasoningEffortOption(normalized.slice(0, 100));
22078
+ }
22079
+ function updateCurrentValue2(current, category, value) {
22080
+ return current.map(
22081
+ (option) => option.category === category ? { ...option, currentValue: value } : option
22082
+ );
22083
+ }
22084
+ function validateGrokResponse(response, modelId) {
22085
+ if (!isRecord3(response) || !isRecord3(response["_meta"])) {
22086
+ throw new SessionConfigProtocolError(
22087
+ "Grok Build returned an invalid session configuration response"
22088
+ );
22089
+ }
22090
+ const model = response["_meta"]["model"];
22091
+ const appliedModel = isRecord3(model) ? model["Ok"] : model;
22092
+ if (appliedModel !== modelId) {
22093
+ throw new SessionConfigProtocolError(
22094
+ "Grok Build returned an invalid session configuration response"
22095
+ );
22096
+ }
22097
+ }
22098
+ var GrokBuildSessionConfigProtocol = class {
22099
+ configure = async (current, change, nativeSessionId, transport) => {
22100
+ const existing = current.find((option) => option.id === change.configId);
22101
+ if (existing === void 0 || existing.id !== LEGACY_MODEL_CONFIG_ID && existing.id !== LEGACY_REASONING_EFFORT_CONFIG_ID) {
22102
+ return await standardSessionConfigProtocol.configure(
22103
+ current,
22104
+ change,
22105
+ nativeSessionId,
22106
+ transport
22107
+ );
22108
+ }
22109
+ const model = current.find((option) => option.category === "model");
22110
+ if (model === void 0) {
22111
+ return current;
22112
+ }
22113
+ if (existing.category === "thought_level" && change.value === AGENT_DEFAULT_REASONING_EFFORT) {
22114
+ return current;
22115
+ }
22116
+ const modelId = existing.category === "model" ? change.value : model.currentValue;
22117
+ const params = {
22118
+ modelId,
22119
+ sessionId: nativeSessionId
22120
+ };
22121
+ if (existing.category === "thought_level") {
22122
+ params["_meta"] = {
22123
+ reasoningEffort: change.value
22124
+ };
22125
+ }
22126
+ const response = await transport.request(
22127
+ "session/set_model",
22128
+ params,
22129
+ existing.category === "model" ? "Grok Build exited while setting the session model" : "Grok Build exited while setting reasoning effort",
22130
+ change.signal
22131
+ );
22132
+ validateGrokResponse(response, modelId);
22133
+ const updated = updateCurrentValue2(
22134
+ current,
22135
+ existing.category,
22136
+ change.value
22137
+ );
22138
+ return existing.category === "thought_level" ? updated.map(
22139
+ (option) => option.category === "thought_level" ? {
22140
+ ...option,
22141
+ values: option.values.filter(
22142
+ (value) => value.value !== AGENT_DEFAULT_REASONING_EFFORT
22143
+ )
22144
+ } : option
22145
+ ) : updated;
22146
+ };
22147
+ normalizeLifecycle = (response) => normalizeGrokLifecycle(response);
22148
+ normalizeUpdate = (current, value) => standardSessionConfigProtocol.normalizeUpdate(current, value);
22149
+ };
22150
+ var grokBuildSessionConfigProtocol = new GrokBuildSessionConfigProtocol();
22151
+
22152
+ // src/acp/session-config/session-config-registry.ts
22153
+ function sessionConfigProtocolForAgent(agentId) {
22154
+ return agentId === "grok-build" ? grokBuildSessionConfigProtocol : standardSessionConfigProtocol;
22155
+ }
22156
+
21656
22157
  // src/acp/session-history.ts
21657
22158
  var AcpHistoryReplay = class {
21658
22159
  #messages = [];
@@ -21757,7 +22258,7 @@ var FoundAcpStoredSession = class extends AcpStoredSessionLookup {
21757
22258
  var DeletedAcpStoredSession = class extends AcpStoredSessionLookup {
21758
22259
  found = false;
21759
22260
  };
21760
- function readString2(value, field) {
22261
+ function readString3(value, field) {
21761
22262
  if (typeof value !== "string" || value.length === 0) {
21762
22263
  throw new Error(`Stored ACP session has an invalid ${field}`);
21763
22264
  }
@@ -21787,10 +22288,10 @@ function decodeSessionRow(row) {
21787
22288
  throw new Error("Stored ACP session is not an object");
21788
22289
  }
21789
22290
  return new AcpStoredSession(
21790
- readString2(Reflect.get(row, "session_id"), "session ID"),
21791
- readString2(Reflect.get(row, "agent_id"), "agent ID"),
21792
- readString2(Reflect.get(row, "native_session_id"), "native session ID"),
21793
- readString2(Reflect.get(row, "cwd"), "working directory"),
22291
+ readString3(Reflect.get(row, "session_id"), "session ID"),
22292
+ readString3(Reflect.get(row, "agent_id"), "agent ID"),
22293
+ readString3(Reflect.get(row, "native_session_id"), "native session ID"),
22294
+ readString3(Reflect.get(row, "cwd"), "working directory"),
21794
22295
  readAdditionalDirectories(Reflect.get(row, "additional_directories_json")),
21795
22296
  readPrompted(Reflect.get(row, "prompted"))
21796
22297
  );
@@ -22052,168 +22553,37 @@ function createWritableAcpStream(output2) {
22052
22553
  }
22053
22554
  });
22054
22555
  }
22055
- function truncate2(value, maximumLength) {
22556
+ function truncate3(value, maximumLength) {
22056
22557
  return value.length <= maximumLength ? value : `${value.slice(0, Math.max(0, maximumLength - 1))}\u2026`;
22057
22558
  }
22058
- function isRecord3(value) {
22559
+ function isRecord4(value) {
22059
22560
  return typeof value === "object" && value !== null && !Array.isArray(value);
22060
22561
  }
22061
- function readString3(value, fallback = "") {
22562
+ function readString4(value, fallback = "") {
22062
22563
  return typeof value === "string" ? value : fallback;
22063
22564
  }
22064
- function readBoolean(value, fallback = false) {
22065
- return typeof value === "boolean" ? value : fallback;
22066
- }
22067
22565
  function arraysEqual(left, right) {
22068
22566
  return left.length === right.length && left.every((value, index) => value === right[index]);
22069
22567
  }
22070
- function normalizeConfigValue(option, groupId = "", groupName = "") {
22568
+ function normalizeCapabilities(capabilities) {
22569
+ const session = capabilities.sessionCapabilities;
22570
+ const prompt = capabilities.promptCapabilities;
22071
22571
  return {
22072
- description: truncate2(readString3(option["description"]), 500),
22073
- groupId: truncate2(groupId, 128),
22074
- groupName: truncate2(groupName, 255),
22075
- name: truncate2(
22076
- readString3(option["name"], readString3(option["value"])),
22077
- 255
22078
- ),
22079
- value: truncate2(readString3(option["value"]), 500)
22572
+ additionalDirectories: session?.additionalDirectories != null,
22573
+ audioPrompt: prompt?.audio === true,
22574
+ closeSession: session?.close != null,
22575
+ deleteSession: session?.delete != null,
22576
+ embeddedContextPrompt: prompt?.embeddedContext === true,
22577
+ imagePrompt: prompt?.image === true,
22578
+ listSessions: session?.list != null,
22579
+ loadSession: capabilities.loadSession === true,
22580
+ resumeSession: session?.resume != null,
22581
+ unstableForkSession: session?.fork != null
22080
22582
  };
22081
22583
  }
22082
- function normalizeConfigValues(value) {
22083
- if (!Array.isArray(value)) {
22084
- return [];
22085
- }
22086
- const normalized = [];
22087
- for (const entry of value) {
22088
- if (!isRecord3(entry)) {
22089
- continue;
22090
- }
22091
- const groupedOptions = entry["options"];
22092
- if (Array.isArray(groupedOptions)) {
22093
- const groupId = readString3(entry["group"]);
22094
- const groupName = readString3(entry["name"]);
22095
- for (const groupedOption of groupedOptions) {
22096
- if (isRecord3(groupedOption)) {
22097
- normalized.push(
22098
- normalizeConfigValue(groupedOption, groupId, groupName)
22099
- );
22100
- }
22101
- }
22102
- continue;
22103
- }
22104
- normalized.push(normalizeConfigValue(entry));
22105
- }
22106
- return normalized.filter((entry) => entry.value.length > 0).slice(0, 500);
22107
- }
22108
- function normalizeConfigOptions(value, modes) {
22109
- const normalized = [];
22110
- if (Array.isArray(value)) {
22111
- for (const option of value) {
22112
- if (!isRecord3(option)) {
22113
- continue;
22114
- }
22115
- const id = truncate2(readString3(option["id"]), 128);
22116
- const name = truncate2(readString3(option["name"], id), 255);
22117
- if (id.length === 0 || name.length === 0) {
22118
- continue;
22119
- }
22120
- if (option["type"] === "boolean") {
22121
- normalized.push({
22122
- booleanValue: readBoolean(option["currentValue"]),
22123
- category: truncate2(readString3(option["category"]), 128),
22124
- currentValue: "",
22125
- description: truncate2(readString3(option["description"]), 500),
22126
- id,
22127
- name,
22128
- type: "boolean",
22129
- values: []
22130
- });
22131
- continue;
22132
- }
22133
- if (option["type"] === "select") {
22134
- const values = normalizeConfigValues(option["options"]);
22135
- const currentValue = truncate2(readString3(option["currentValue"]), 500);
22136
- if (currentValue.length > 0 && values.some((entry) => entry.value === currentValue)) {
22137
- normalized.push({
22138
- booleanValue: false,
22139
- category: truncate2(readString3(option["category"]), 128),
22140
- currentValue,
22141
- description: truncate2(readString3(option["description"]), 500),
22142
- id,
22143
- name,
22144
- type: "select",
22145
- values
22146
- });
22147
- }
22148
- }
22149
- }
22150
- }
22151
- if (isRecord3(modes)) {
22152
- const values = [];
22153
- const availableModes = modes["availableModes"];
22154
- if (Array.isArray(availableModes)) {
22155
- for (const mode of availableModes) {
22156
- if (!isRecord3(mode)) {
22157
- continue;
22158
- }
22159
- const id = truncate2(readString3(mode["id"]), 500);
22160
- if (id.length === 0) {
22161
- continue;
22162
- }
22163
- values.push({
22164
- description: truncate2(readString3(mode["description"]), 500),
22165
- groupId: "",
22166
- groupName: "",
22167
- name: truncate2(readString3(mode["name"], id), 255),
22168
- value: id
22169
- });
22170
- }
22171
- }
22172
- const currentValue = truncate2(readString3(modes["currentModeId"]), 500);
22173
- if (currentValue.length > 0 && values.some((entry) => entry.value === currentValue) && !normalized.some((entry) => entry.category === "mode")) {
22174
- normalized.unshift({
22175
- booleanValue: false,
22176
- category: "mode",
22177
- currentValue,
22178
- description: "Agent session mode",
22179
- id: "mode",
22180
- name: "Mode",
22181
- type: "select",
22182
- values
22183
- });
22184
- }
22185
- }
22186
- return normalized.slice(0, 100);
22187
- }
22188
- function replaceConfigOptionsKeepingMode(current, value) {
22189
- const next = normalizeConfigOptions(value, void 0);
22190
- if (next.some((option) => option.category === "mode")) {
22191
- return next;
22192
- }
22193
- return [
22194
- ...current.filter((option) => option.category === "mode"),
22195
- ...next
22196
- ].slice(0, 100);
22197
- }
22198
- function normalizeCapabilities(capabilities) {
22199
- const session = capabilities.sessionCapabilities;
22200
- const prompt = capabilities.promptCapabilities;
22201
- return {
22202
- additionalDirectories: session?.additionalDirectories != null,
22203
- audioPrompt: prompt?.audio === true,
22204
- closeSession: session?.close != null,
22205
- deleteSession: session?.delete != null,
22206
- embeddedContextPrompt: prompt?.embeddedContext === true,
22207
- imagePrompt: prompt?.image === true,
22208
- listSessions: session?.list != null,
22209
- loadSession: capabilities.loadSession === true,
22210
- resumeSession: session?.resume != null,
22211
- unstableForkSession: session?.fork != null
22212
- };
22213
- }
22214
- function elicitationFieldType(value) {
22215
- if (value === "boolean") {
22216
- return "boolean";
22584
+ function elicitationFieldType(value) {
22585
+ if (value === "boolean") {
22586
+ return "boolean";
22217
22587
  }
22218
22588
  if (value === "integer") {
22219
22589
  return "integer";
@@ -22231,11 +22601,11 @@ function normalizeElicitationOptions(schema) {
22231
22601
  const oneOf = schema["oneOf"];
22232
22602
  if (Array.isArray(oneOf)) {
22233
22603
  for (const option of oneOf) {
22234
- if (isRecord3(option) && typeof option["const"] === "string") {
22604
+ if (isRecord4(option) && typeof option["const"] === "string") {
22235
22605
  normalized.push({
22236
- description: truncate2(readString3(option["description"]), 500),
22237
- label: truncate2(readString3(option["title"], option["const"]), 255),
22238
- value: truncate2(option["const"], 500)
22606
+ description: truncate3(readString4(option["description"]), 500),
22607
+ label: truncate3(readString4(option["title"], option["const"]), 255),
22608
+ value: truncate3(option["const"], 500)
22239
22609
  });
22240
22610
  }
22241
22611
  }
@@ -22251,7 +22621,7 @@ function normalizeElicitationOptions(schema) {
22251
22621
  return normalized.slice(0, 200);
22252
22622
  }
22253
22623
  const items = schema["items"];
22254
- if (!isRecord3(items)) {
22624
+ if (!isRecord4(items)) {
22255
22625
  return normalized;
22256
22626
  }
22257
22627
  const anyOf = items["anyOf"];
@@ -22264,7 +22634,7 @@ function numericString(value) {
22264
22634
  return typeof value === "number" && Number.isFinite(value) ? value.toString() : "";
22265
22635
  }
22266
22636
  function normalizeElicitationFields(requestedSchema) {
22267
- if (!isRecord3(requestedSchema) || !isRecord3(requestedSchema["properties"])) {
22637
+ if (!isRecord4(requestedSchema) || !isRecord4(requestedSchema["properties"])) {
22268
22638
  return [];
22269
22639
  }
22270
22640
  const properties = requestedSchema["properties"];
@@ -22274,7 +22644,7 @@ function normalizeElicitationFields(requestedSchema) {
22274
22644
  );
22275
22645
  const normalized = [];
22276
22646
  for (const [name, property] of Object.entries(properties)) {
22277
- if (!isRecord3(property)) {
22647
+ if (!isRecord4(property)) {
22278
22648
  continue;
22279
22649
  }
22280
22650
  const type = elicitationFieldType(property["type"]);
@@ -22284,9 +22654,9 @@ function normalizeElicitationFields(requestedSchema) {
22284
22654
  normalized.push({
22285
22655
  defaultBooleanValue: typeof defaultValue === "boolean" ? defaultValue : false,
22286
22656
  defaultNumberValue: typeof defaultValue === "number" && Number.isFinite(defaultValue) ? defaultValue : 0,
22287
- defaultStringValue: typeof defaultValue === "string" ? truncate2(defaultValue, 1e4) : Array.isArray(defaultValue) ? truncate2(JSON.stringify(defaultValue), 1e4) : "",
22288
- description: truncate2(readString3(property["description"]), 500),
22289
- format: truncate2(readString3(property["format"]), 64),
22657
+ defaultStringValue: typeof defaultValue === "string" ? truncate3(defaultValue, 1e4) : Array.isArray(defaultValue) ? truncate3(JSON.stringify(defaultValue), 1e4) : "",
22658
+ description: truncate3(readString4(property["description"]), 500),
22659
+ format: truncate3(readString4(property["format"]), 64),
22290
22660
  hasDefaultValue: defaultValue !== void 0 && defaultValue !== null,
22291
22661
  maximum: numericString(property["maximum"]),
22292
22662
  maximumLength: numericString(
@@ -22296,11 +22666,11 @@ function normalizeElicitationFields(requestedSchema) {
22296
22666
  minimumLength: numericString(
22297
22667
  property["minLength"] ?? property["minItems"]
22298
22668
  ),
22299
- name: truncate2(name, 128),
22669
+ name: truncate3(name, 128),
22300
22670
  options,
22301
- pattern: truncate2(readString3(property["pattern"]), 500),
22671
+ pattern: truncate3(readString4(property["pattern"]), 500),
22302
22672
  required: required2.has(name),
22303
- title: truncate2(readString3(property["title"], name), 255),
22673
+ title: truncate3(readString4(property["title"], name), 255),
22304
22674
  type: normalizedType
22305
22675
  });
22306
22676
  }
@@ -22369,7 +22739,7 @@ function validateElicitationContent(encoded, requestedSchema) {
22369
22739
  "invalid_elicitation_response"
22370
22740
  );
22371
22741
  }
22372
- if (!isRecord3(decoded) || !isRecord3(requestedSchema) || !isRecord3(requestedSchema["properties"])) {
22742
+ if (!isRecord4(decoded) || !isRecord4(requestedSchema) || !isRecord4(requestedSchema["properties"])) {
22373
22743
  throw new AcpExecutionError(
22374
22744
  "Elicitation response does not match the requested form",
22375
22745
  {},
@@ -22393,7 +22763,7 @@ function validateElicitationContent(encoded, requestedSchema) {
22393
22763
  const validated = {};
22394
22764
  for (const [name, value] of Object.entries(decoded)) {
22395
22765
  const property = properties[name];
22396
- if (!isRecord3(property)) {
22766
+ if (!isRecord4(property)) {
22397
22767
  throw new AcpExecutionError(
22398
22768
  `Elicitation field ${name} was not requested`,
22399
22769
  {},
@@ -22545,6 +22915,7 @@ var AcpProcessSession = class _AcpProcessSession {
22545
22915
  #pendingPermissions = /* @__PURE__ */ new Map();
22546
22916
  #preSessionUpdates = [];
22547
22917
  #processExit;
22918
+ #sessionConfigProtocol;
22548
22919
  #store;
22549
22920
  #verifiedAgentVersion;
22550
22921
  #preSessionUpdateBytes = 0;
@@ -22563,6 +22934,7 @@ var AcpProcessSession = class _AcpProcessSession {
22563
22934
  unstableForkSession: false
22564
22935
  };
22565
22936
  #commands = [];
22937
+ #configRevision = 0;
22566
22938
  #configOptions = [];
22567
22939
  #nativeSessionId = "";
22568
22940
  #prompted = false;
@@ -22580,6 +22952,7 @@ var AcpProcessSession = class _AcpProcessSession {
22580
22952
  this.#cwd = cwd;
22581
22953
  this.#getObserver = getObserver;
22582
22954
  this.#mobiusSessionId = mobiusSessionId;
22955
+ this.#sessionConfigProtocol = sessionConfigProtocolForAgent(agent.id);
22583
22956
  this.#store = store;
22584
22957
  this.#verifiedAgentVersion = agent.agentVersion;
22585
22958
  this.#child = spawn2(agent.adapterPath, [...agent.arguments], {
@@ -22684,7 +23057,7 @@ var AcpProcessSession = class _AcpProcessSession {
22684
23057
  try {
22685
23058
  await this.race(
22686
23059
  this.#connection.agent.request(
22687
- methods2.agent.session.load,
23060
+ methods3.agent.session.load,
22688
23061
  {
22689
23062
  additionalDirectories: [...this.#additionalDirectories],
22690
23063
  cwd: this.#cwd,
@@ -22706,7 +23079,7 @@ var AcpProcessSession = class _AcpProcessSession {
22706
23079
  async #initializeAgent(signal) {
22707
23080
  const initialized = await this.race(
22708
23081
  this.#connection.agent.request(
22709
- methods2.agent.initialize,
23082
+ methods3.agent.initialize,
22710
23083
  {
22711
23084
  clientCapabilities: {
22712
23085
  elicitation: { form: {}, url: {} },
@@ -22733,11 +23106,11 @@ var AcpProcessSession = class _AcpProcessSession {
22733
23106
  }
22734
23107
  const capabilities = initialized.agentCapabilities ?? {};
22735
23108
  this.#capabilities = normalizeCapabilities(capabilities);
22736
- this.#agentName = truncate2(
23109
+ this.#agentName = truncate3(
22737
23110
  initialized.agentInfo?.title ?? initialized.agentInfo?.name ?? this.#agentId,
22738
23111
  255
22739
23112
  );
22740
- this.#agentVersion = truncate2(
23113
+ this.#agentVersion = truncate3(
22741
23114
  this.#verifiedAgentVersion.length > 0 ? this.#verifiedAgentVersion : initialized.agentInfo?.version ?? "",
22742
23115
  128
22743
23116
  );
@@ -22774,7 +23147,7 @@ var AcpProcessSession = class _AcpProcessSession {
22774
23147
  );
22775
23148
  const forked = await this.race(
22776
23149
  this.#connection.agent.request(
22777
- methods2.agent.session.fork,
23150
+ methods3.agent.session.fork,
22778
23151
  {
22779
23152
  sessionId: nativeSessionIdSchema.parse(origin.nativeSessionId),
22780
23153
  cwd: this.#cwd,
@@ -22807,7 +23180,7 @@ var AcpProcessSession = class _AcpProcessSession {
22807
23180
  if (this.#capabilities.resumeSession) {
22808
23181
  lifecycleResponse = await this.race(
22809
23182
  this.#connection.agent.request(
22810
- methods2.agent.session.resume,
23183
+ methods3.agent.session.resume,
22811
23184
  {
22812
23185
  additionalDirectories: [...this.#additionalDirectories],
22813
23186
  cwd: this.#cwd,
@@ -22824,7 +23197,7 @@ var AcpProcessSession = class _AcpProcessSession {
22824
23197
  try {
22825
23198
  lifecycleResponse = await this.race(
22826
23199
  this.#connection.agent.request(
22827
- methods2.agent.session.load,
23200
+ methods3.agent.session.load,
22828
23201
  {
22829
23202
  additionalDirectories: [...this.#additionalDirectories],
22830
23203
  cwd: this.#cwd,
@@ -22860,7 +23233,7 @@ var AcpProcessSession = class _AcpProcessSession {
22860
23233
  }
22861
23234
  const created = await this.race(
22862
23235
  this.#connection.agent.request(
22863
- methods2.agent.session.new,
23236
+ methods3.agent.session.new,
22864
23237
  {
22865
23238
  additionalDirectories: [...this.#additionalDirectories],
22866
23239
  cwd: this.#cwd,
@@ -22874,11 +23247,7 @@ var AcpProcessSession = class _AcpProcessSession {
22874
23247
  this.selectNativeSession(created.sessionId);
22875
23248
  lifecycleResponse = created;
22876
23249
  }
22877
- const lifecycleRecord = isRecord3(lifecycleResponse) ? lifecycleResponse : {};
22878
- this.#configOptions = normalizeConfigOptions(
22879
- lifecycleRecord["configOptions"],
22880
- lifecycleRecord["modes"]
22881
- );
23250
+ this.#configOptions = this.#sessionConfigProtocol.normalizeLifecycle(lifecycleResponse);
22882
23251
  await this.#updateTail;
22883
23252
  signal.throwIfAborted();
22884
23253
  if (this.#prompted) {
@@ -22903,7 +23272,7 @@ var AcpProcessSession = class _AcpProcessSession {
22903
23272
  );
22904
23273
  const response = await this.race(
22905
23274
  this.#connection.agent.request(
22906
- methods2.agent.session.list,
23275
+ methods3.agent.session.list,
22907
23276
  cursor === null ? {} : { cursor },
22908
23277
  { cancellationSignal: signal }
22909
23278
  ),
@@ -22928,7 +23297,7 @@ var AcpProcessSession = class _AcpProcessSession {
22928
23297
  );
22929
23298
  await this.race(
22930
23299
  this.#connection.agent.request(
22931
- methods2.agent.session.delete,
23300
+ methods3.agent.session.delete,
22932
23301
  { sessionId: nativeSessionIdSchema.parse(nativeSessionId) },
22933
23302
  { cancellationSignal: signal }
22934
23303
  ),
@@ -22949,64 +23318,50 @@ var AcpProcessSession = class _AcpProcessSession {
22949
23318
  );
22950
23319
  }
22951
23320
  if (existing.type === "select") {
22952
- if (!existing.values.some((entry) => entry.value === options.value)) {
23321
+ if (existing.values.length < 2) {
22953
23322
  throw new AcpExecutionError(
22954
- "The requested ACP configuration value is unavailable",
23323
+ "The requested ACP configuration option is unavailable",
22955
23324
  {},
22956
23325
  "invalid_session_configuration"
22957
23326
  );
22958
23327
  }
22959
- if (existing.category === "mode") {
22960
- await this.race(
22961
- this.#connection.agent.request(
22962
- methods2.agent.session.setMode,
22963
- { modeId: options.value, sessionId: this.#nativeSessionId },
22964
- { cancellationSignal: options.signal }
22965
- ),
22966
- "ACP agent exited while setting the session mode",
22967
- options.signal
22968
- );
22969
- this.#configOptions = this.#configOptions.map(
22970
- (option) => option.id === existing.id ? { ...option, currentValue: options.value } : option
22971
- );
22972
- } else {
22973
- const response = await this.race(
22974
- this.#connection.agent.request(
22975
- methods2.agent.session.setConfigOption,
22976
- {
22977
- configId: existing.id,
22978
- sessionId: this.#nativeSessionId,
22979
- value: options.value
22980
- },
22981
- { cancellationSignal: options.signal }
22982
- ),
22983
- "ACP agent exited while changing session configuration",
22984
- options.signal
22985
- );
22986
- this.#configOptions = replaceConfigOptionsKeepingMode(
22987
- this.#configOptions,
22988
- response.configOptions
23328
+ if (!existing.values.some((entry) => entry.value === options.value)) {
23329
+ throw new AcpExecutionError(
23330
+ "The requested ACP configuration value is unavailable",
23331
+ {},
23332
+ "invalid_session_configuration"
22989
23333
  );
22990
23334
  }
22991
- } else {
22992
- const response = await this.race(
22993
- this.#connection.agent.request(
22994
- methods2.agent.session.setConfigOption,
22995
- {
22996
- configId: existing.id,
22997
- sessionId: this.#nativeSessionId,
22998
- type: "boolean",
22999
- value: options.booleanValue
23000
- },
23001
- { cancellationSignal: options.signal }
23002
- ),
23003
- "ACP agent exited while changing session configuration",
23004
- options.signal
23005
- );
23006
- this.#configOptions = replaceConfigOptionsKeepingMode(
23335
+ }
23336
+ const configRevision = this.#configRevision;
23337
+ try {
23338
+ const configured = await this.#sessionConfigProtocol.configure(
23007
23339
  this.#configOptions,
23008
- response.configOptions
23340
+ options,
23341
+ this.#nativeSessionId,
23342
+ {
23343
+ request: async (method, params, failureMessage, signal) => await this.race(
23344
+ this.#connection.agent.request(method, params, {
23345
+ cancellationSignal: signal
23346
+ }),
23347
+ failureMessage,
23348
+ signal
23349
+ )
23350
+ }
23009
23351
  );
23352
+ await this.#updateTail;
23353
+ if (this.#configRevision === configRevision) {
23354
+ this.#configOptions = configured;
23355
+ }
23356
+ } catch (error61) {
23357
+ if (error61 instanceof SessionConfigProtocolError) {
23358
+ throw new AcpExecutionError(
23359
+ error61.message,
23360
+ { cause: error61 },
23361
+ error61.code
23362
+ );
23363
+ }
23364
+ throw error61;
23010
23365
  }
23011
23366
  return this.#configOptions;
23012
23367
  };
@@ -23090,7 +23445,7 @@ var AcpProcessSession = class _AcpProcessSession {
23090
23445
  try {
23091
23446
  const response = await this.race(
23092
23447
  this.#connection.agent.request(
23093
- methods2.agent.session.prompt,
23448
+ methods3.agent.session.prompt,
23094
23449
  { prompt, sessionId: this.#nativeSessionId },
23095
23450
  { cancellationSignal: options.signal }
23096
23451
  ),
@@ -23137,7 +23492,7 @@ var AcpProcessSession = class _AcpProcessSession {
23137
23492
  try {
23138
23493
  await this.cancelPendingInteractions();
23139
23494
  if (this.#turn.running) {
23140
- await this.#connection.agent.notify(methods2.agent.session.cancel, {
23495
+ await this.#connection.agent.notify(methods3.agent.session.cancel, {
23141
23496
  sessionId: this.#nativeSessionId
23142
23497
  });
23143
23498
  }
@@ -23227,8 +23582,8 @@ var AcpProcessSession = class _AcpProcessSession {
23227
23582
  const interactionId = `permission-${crypto.randomUUID()}`;
23228
23583
  const options = request.options.slice(0, 20).map((option) => ({
23229
23584
  kind: option.kind,
23230
- name: truncate2(option.name, 255),
23231
- optionId: truncate2(option.optionId, 255)
23585
+ name: truncate3(option.name, 255),
23586
+ optionId: truncate3(option.optionId, 255)
23232
23587
  }));
23233
23588
  if (options.length === 0) {
23234
23589
  throw new AcpExecutionError(
@@ -23253,9 +23608,9 @@ var AcpProcessSession = class _AcpProcessSession {
23253
23608
  kind: SESSION_PERMISSION_REQUESTED_KIND,
23254
23609
  options,
23255
23610
  sessionId: this.#mobiusSessionId,
23256
- title: truncate2(request.toolCall.title ?? "Permission required", 500),
23257
- toolCallId: truncate2(request.toolCall.toolCallId, 255),
23258
- toolKind: truncate2(request.toolCall.kind ?? "other", 64)
23611
+ title: truncate3(request.toolCall.title ?? "Permission required", 500),
23612
+ toolCallId: truncate3(request.toolCall.toolCallId, 255),
23613
+ toolKind: truncate3(request.toolCall.kind ?? "other", 64)
23259
23614
  });
23260
23615
  return await pending.completion.promise;
23261
23616
  } finally {
@@ -23284,7 +23639,7 @@ var AcpProcessSession = class _AcpProcessSession {
23284
23639
  const schemaValue = Reflect.get(request, "requestedSchema");
23285
23640
  const requestedSchema = request.mode === "form" ? schemaValue : {};
23286
23641
  const elicitationIdValue = Reflect.get(request, "elicitationId");
23287
- const elicitationId = request.mode === "url" && typeof elicitationIdValue === "string" ? truncate2(elicitationIdValue, 255) : "";
23642
+ const elicitationId = request.mode === "url" && typeof elicitationIdValue === "string" ? truncate3(elicitationIdValue, 255) : "";
23288
23643
  const pending = new PendingElicitation(
23289
23644
  interactionId,
23290
23645
  elicitationId,
@@ -23303,10 +23658,10 @@ var AcpProcessSession = class _AcpProcessSession {
23303
23658
  fields: normalizeElicitationFields(requestedSchema),
23304
23659
  interactionId,
23305
23660
  kind: SESSION_ELICITATION_REQUESTED_KIND,
23306
- message: truncate2(request.message, 2e3),
23661
+ message: truncate3(request.message, 2e3),
23307
23662
  mode: request.mode,
23308
23663
  sessionId: this.#mobiusSessionId,
23309
- url: request.mode === "url" && typeof Reflect.get(request, "url") === "string" ? truncate2(readString3(Reflect.get(request, "url")), 4096) : ""
23664
+ url: request.mode === "url" && typeof Reflect.get(request, "url") === "string" ? truncate3(readString4(Reflect.get(request, "url")), 4096) : ""
23310
23665
  });
23311
23666
  return await pending.completion.promise;
23312
23667
  } finally {
@@ -23395,7 +23750,7 @@ var AcpProcessSession = class _AcpProcessSession {
23395
23750
  content: normalizeContentBlock(update.content),
23396
23751
  contentId: `content-${crypto.randomUUID()}`,
23397
23752
  kind: AGENT_CONTENT_KIND,
23398
- messageId: truncate2(update.messageId ?? "", 255),
23753
+ messageId: truncate3(update.messageId ?? "", 255),
23399
23754
  sessionId: this.#mobiusSessionId
23400
23755
  });
23401
23756
  }
@@ -23433,9 +23788,9 @@ var AcpProcessSession = class _AcpProcessSession {
23433
23788
  }
23434
23789
  if (update.sessionUpdate === "available_commands_update") {
23435
23790
  const commands = update.availableCommands.slice(0, 500).map((command) => ({
23436
- description: truncate2(command.description, 500),
23437
- inputHint: truncate2(command.input?.hint ?? "", 255),
23438
- name: truncate2(command.name, 128)
23791
+ description: truncate3(command.description, 500),
23792
+ inputHint: truncate3(command.input?.hint ?? "", 255),
23793
+ name: truncate3(command.name, 128)
23439
23794
  })).filter((command) => command.name.length > 0);
23440
23795
  this.#commands = commands;
23441
23796
  await this.#getObserver().onCommands({
@@ -23446,10 +23801,11 @@ var AcpProcessSession = class _AcpProcessSession {
23446
23801
  return;
23447
23802
  }
23448
23803
  if (update.sessionUpdate === "config_option_update") {
23449
- this.#configOptions = replaceConfigOptionsKeepingMode(
23804
+ this.#configOptions = this.#sessionConfigProtocol.normalizeUpdate(
23450
23805
  this.#configOptions,
23451
23806
  update.configOptions
23452
23807
  );
23808
+ this.#configRevision += 1;
23453
23809
  await this.emitConfigUpdate();
23454
23810
  return;
23455
23811
  }
@@ -23457,15 +23813,16 @@ var AcpProcessSession = class _AcpProcessSession {
23457
23813
  this.#configOptions = this.#configOptions.map(
23458
23814
  (option) => option.category === "mode" ? { ...option, currentValue: update.currentModeId } : option
23459
23815
  );
23816
+ this.#configRevision += 1;
23460
23817
  await this.emitConfigUpdate();
23461
23818
  return;
23462
23819
  }
23463
23820
  if (update.sessionUpdate === "session_info_update") {
23464
23821
  if (Object.hasOwn(update, "title")) {
23465
- this.#sessionTitle = truncate2(update.title ?? "", 500);
23822
+ this.#sessionTitle = truncate3(update.title ?? "", 500);
23466
23823
  }
23467
23824
  if (Object.hasOwn(update, "updatedAt")) {
23468
- this.#sessionUpdatedAt = truncate2(update.updatedAt ?? "", 128);
23825
+ this.#sessionUpdatedAt = truncate3(update.updatedAt ?? "", 128);
23469
23826
  }
23470
23827
  await this.#getObserver().onInfo({
23471
23828
  kind: SESSION_INFO_UPDATED_KIND,
@@ -23478,7 +23835,7 @@ var AcpProcessSession = class _AcpProcessSession {
23478
23835
  if (update.sessionUpdate === "usage_update") {
23479
23836
  await this.#getObserver().onUsage({
23480
23837
  costAmount: update.cost?.amount ?? 0,
23481
- costCurrency: truncate2(update.cost?.currency ?? "", 16),
23838
+ costCurrency: truncate3(update.cost?.currency ?? "", 16),
23482
23839
  hasCost: update.cost !== void 0 && update.cost !== null,
23483
23840
  kind: SESSION_USAGE_UPDATED_KIND,
23484
23841
  sessionId: this.#mobiusSessionId,
@@ -23493,7 +23850,7 @@ var AcpProcessSession = class _AcpProcessSession {
23493
23850
  if (this.#capabilities.closeSession && this.#nativeSessionId.length > 0) {
23494
23851
  try {
23495
23852
  await this.#connection.agent.request(
23496
- methods2.agent.session.close,
23853
+ methods3.agent.session.close,
23497
23854
  { sessionId: this.#nativeSessionId },
23498
23855
  {
23499
23856
  cancellationSignal: AbortSignal.timeout(
@@ -24184,7 +24541,7 @@ var LocalAuthorizationError = class extends Error {
24184
24541
  import { randomUUID } from "node:crypto";
24185
24542
  import {
24186
24543
  mkdir as mkdir3,
24187
- open as open5,
24544
+ open as open4,
24188
24545
  realpath as realpath6,
24189
24546
  rename as rename3,
24190
24547
  stat as stat5,
@@ -24211,12 +24568,19 @@ var AvailableAgent = class extends AgentDiscovery {
24211
24568
  };
24212
24569
  var UnavailableAgent = class extends AgentDiscovery {
24213
24570
  };
24214
- var MissingAdapter = class extends UnavailableAgent {
24571
+ var UnavailableInstalledAgent = class extends UnavailableAgent {
24572
+ agent;
24573
+ constructor(specification, agent) {
24574
+ super(specification);
24575
+ this.agent = agent;
24576
+ }
24577
+ };
24578
+ var MissingAdapter = class extends UnavailableInstalledAgent {
24215
24579
  code = "adapter_not_found";
24216
24580
  message = "ACP adapter not found";
24217
24581
  status = "missing_adapter";
24218
- constructor(specification) {
24219
- super(specification);
24582
+ constructor(specification, agent) {
24583
+ super(specification, agent);
24220
24584
  }
24221
24585
  };
24222
24586
  var MissingAgent = class extends UnavailableAgent {
@@ -24227,7 +24591,7 @@ var MissingAgent = class extends UnavailableAgent {
24227
24591
  super(specification);
24228
24592
  }
24229
24593
  };
24230
- var ProbeFailed = class extends UnavailableAgent {
24594
+ var AgentProbeFailed = class extends UnavailableAgent {
24231
24595
  code;
24232
24596
  message;
24233
24597
  status = "probe_failed";
@@ -24237,20 +24601,30 @@ var ProbeFailed = class extends UnavailableAgent {
24237
24601
  this.message = message;
24238
24602
  }
24239
24603
  };
24240
- var IncompatibleAdapter = class extends UnavailableAgent {
24604
+ var IntegrationProbeFailed = class extends UnavailableInstalledAgent {
24605
+ code;
24606
+ message;
24607
+ status = "probe_failed";
24608
+ constructor(specification, agent, code, message) {
24609
+ super(specification, agent);
24610
+ this.code = code;
24611
+ this.message = message;
24612
+ }
24613
+ };
24614
+ var IncompatibleAdapter = class extends UnavailableInstalledAgent {
24241
24615
  code = "acp_incompatible";
24242
24616
  message = "ACP adapter is incompatible";
24243
24617
  status = "incompatible_adapter";
24244
- constructor(specification) {
24245
- super(specification);
24618
+ constructor(specification, agent) {
24619
+ super(specification, agent);
24246
24620
  }
24247
24621
  };
24248
- var AuthenticationRequiredAgent = class extends UnavailableAgent {
24622
+ var AuthenticationRequiredAgent = class extends UnavailableInstalledAgent {
24249
24623
  code = "authentication_required";
24250
24624
  message = "Agent authentication is required";
24251
24625
  status = "authentication_required";
24252
- constructor(specification) {
24253
- super(specification);
24626
+ constructor(specification, agent) {
24627
+ super(specification, agent);
24254
24628
  }
24255
24629
  };
24256
24630
  var LocalAgentInventory = class {
@@ -24258,7 +24632,7 @@ var LocalAgentInventory = class {
24258
24632
  discoveries;
24259
24633
  installable;
24260
24634
  unavailable;
24261
- constructor(discoveries, platform = process.platform, architecture = process.arch) {
24635
+ constructor(discoveries) {
24262
24636
  const available = [];
24263
24637
  const unavailable = [];
24264
24638
  for (const discovery of discoveries) {
@@ -24273,13 +24647,8 @@ var LocalAgentInventory = class {
24273
24647
  this.available = Object.freeze(available);
24274
24648
  this.discoveries = Object.freeze([...discoveries]);
24275
24649
  this.installable = Object.freeze(
24276
- unavailable.filter(
24277
- (discovery) => !(discovery instanceof AuthenticationRequiredAgent) && discovery.specification.supportsInstallation(
24278
- platform,
24279
- architecture
24280
- )
24281
- ).map(
24282
- (discovery) => new InstallableAgentDefinition(
24650
+ unavailable.map(
24651
+ (discovery) => discovery instanceof UnavailableInstalledAgent ? discovery.agent : new MissingAgentDefinition(
24283
24652
  discovery.specification.id,
24284
24653
  discovery.specification.label
24285
24654
  )
@@ -24347,7 +24716,7 @@ var ManagedNpmPackageError = class extends Error {
24347
24716
  this.name = "ManagedNpmPackageError";
24348
24717
  }
24349
24718
  };
24350
- function isRecord4(value) {
24719
+ function isRecord5(value) {
24351
24720
  return typeof value === "object" && value !== null && !Array.isArray(value);
24352
24721
  }
24353
24722
  function packagePath(root, packageName) {
@@ -24371,7 +24740,7 @@ async function readJsonRecord(path2, maximumBytes) {
24371
24740
  const value = JSON.parse(
24372
24741
  await handle.readFile({ encoding: "utf8" })
24373
24742
  );
24374
- if (!isRecord4(value)) {
24743
+ if (!isRecord5(value)) {
24375
24744
  throw new ManagedNpmPackageError(
24376
24745
  "managed_package_verification_failed",
24377
24746
  "The managed npm package metadata is invalid"
@@ -24397,7 +24766,7 @@ function readBinPath(packageMetadata, executableName) {
24397
24766
  if (typeof bin === "string") {
24398
24767
  return bin;
24399
24768
  }
24400
- if (isRecord4(bin) && typeof bin[executableName] === "string") {
24769
+ if (isRecord5(bin) && typeof bin[executableName] === "string") {
24401
24770
  return bin[executableName];
24402
24771
  }
24403
24772
  throw new ManagedNpmPackageError(
@@ -24413,7 +24782,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
24413
24782
  );
24414
24783
  }
24415
24784
  const packages = lock["packages"];
24416
- if (!isRecord4(packages)) {
24785
+ if (!isRecord5(packages)) {
24417
24786
  throw new ManagedNpmPackageError(
24418
24787
  "managed_package_verification_failed",
24419
24788
  "The managed npm package lockfile is invalid"
@@ -24427,7 +24796,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
24427
24796
  if (verifyDependencyClosure && normalizedKey.length > 0) {
24428
24797
  let resolved;
24429
24798
  try {
24430
- if (!normalizedKey.split("/").includes("node_modules") || !isRecord4(candidate) || typeof candidate["version"] !== "string" || candidate["version"].length === 0 || typeof candidate["integrity"] !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(candidate["integrity"]) || typeof candidate["resolved"] !== "string") {
24799
+ if (!normalizedKey.split("/").includes("node_modules") || !isRecord5(candidate) || typeof candidate["version"] !== "string" || candidate["version"].length === 0 || typeof candidate["integrity"] !== "string" || !/^sha512-[A-Za-z0-9+/]{86}==$/.test(candidate["integrity"]) || typeof candidate["resolved"] !== "string") {
24431
24800
  throw new Error("Invalid locked dependency");
24432
24801
  }
24433
24802
  resolved = new URL(candidate["resolved"]);
@@ -24450,7 +24819,7 @@ function verifyPackageLockEntry(lock, definition, verifyDependencyClosure) {
24450
24819
  matches += 1;
24451
24820
  }
24452
24821
  }
24453
- if (matches !== 1 || !isRecord4(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
24822
+ if (matches !== 1 || !isRecord5(entry) || entry["integrity"] !== definition.integrity || entry["resolved"] !== definition.tarballUrl || entry["version"] !== definition.version) {
24454
24823
  throw new ManagedNpmPackageError(
24455
24824
  "managed_package_verification_failed",
24456
24825
  "The managed npm package lockfile does not match the pinned artifact"
@@ -24673,7 +25042,6 @@ var LocalAgentSpecification = class {
24673
25042
  createLaunchEnvironment = async (_agent, _context) => Object.freeze({});
24674
25043
  recoveryCommand = () => "";
24675
25044
  resolveInstalledAgentExecutables = (_context) => Promise.resolve([]);
24676
- supportsInstallation = (platform, architecture) => (platform === "darwin" || platform === "linux") && (architecture === "arm64" || architecture === "x64");
24677
25045
  verifyAcp = (_connection, _initialized, _defaultWorkspace, _signal) => Promise.resolve();
24678
25046
  };
24679
25047
  var DirectAcpAgentDefinition = class extends LocalAgentSpecification {
@@ -24779,11 +25147,11 @@ var AgentProbeError = class extends Error {
24779
25147
 
24780
25148
  // src/agent-catalog/agents/verify-session-creation.ts
24781
25149
  import {
24782
- methods as methods3
25150
+ methods as methods4
24783
25151
  } from "@agentclientprotocol/sdk";
24784
25152
  async function verifySessionCreation(connection, capabilities, defaultWorkspace, signal, label) {
24785
25153
  const session = await connection.agent.request(
24786
- methods3.agent.session.new,
25154
+ methods4.agent.session.new,
24787
25155
  {
24788
25156
  additionalDirectories: [],
24789
25157
  cwd: defaultWorkspace,
@@ -24799,7 +25167,7 @@ async function verifySessionCreation(connection, capabilities, defaultWorkspace,
24799
25167
  }
24800
25168
  if (capabilities.sessionCapabilities?.close != null) {
24801
25169
  await connection.agent.request(
24802
- methods3.agent.session.close,
25170
+ methods4.agent.session.close,
24803
25171
  { sessionId: session.sessionId },
24804
25172
  { cancellationSignal: signal }
24805
25173
  );
@@ -24821,7 +25189,6 @@ var CursorCliAgentSpecification = class extends DirectAcpAgentDefinition {
24821
25189
  ["agents", "cursor", CURSOR_CLI_TESTED_VERSION, "bin", "cursor-agent"]
24822
25190
  );
24823
25191
  }
24824
- supportsInstallation = (_platform, _architecture) => false;
24825
25192
  verifyAcp = async (connection, initialized, defaultWorkspace, signal) => {
24826
25193
  const capabilities = initialized.agentCapabilities ?? {};
24827
25194
  if (capabilities.loadSession !== true || capabilities.sessionCapabilities?.list == null || !(initialized.authMethods ?? []).some(
@@ -25124,14 +25491,14 @@ var GrokBuildAgentSpecification = class extends DirectAcpAgentDefinition {
25124
25491
  import { join as join9 } from "node:path";
25125
25492
 
25126
25493
  // src/agent-installation/managed-agent-archive.ts
25127
- import { createHash as createHash2 } from "node:crypto";
25494
+ import { createHash } from "node:crypto";
25128
25495
  import { createReadStream } from "node:fs";
25129
25496
  import {
25130
25497
  chmod,
25131
25498
  copyFile,
25132
25499
  mkdir as mkdir2,
25133
25500
  mkdtemp as mkdtemp2,
25134
- open as open4,
25501
+ open as open3,
25135
25502
  realpath as realpath5,
25136
25503
  rename as rename2,
25137
25504
  rm as rm2,
@@ -25141,259 +25508,64 @@ import {
25141
25508
  import { dirname as dirname4, isAbsolute as isAbsolute4, join as join8, relative as relative3, sep as sep3 } from "node:path";
25142
25509
 
25143
25510
  // src/agent-installation/verified-download.ts
25144
- import { createHash } from "node:crypto";
25145
- import { open as open3, unlink } from "node:fs/promises";
25146
25511
  import { fetch } from "undici";
25147
25512
 
25148
25513
  // src/network/environment-proxy.ts
25149
25514
  import { EnvHttpProxyAgent } from "undici";
25150
25515
  var environmentProxyDispatcher = new EnvHttpProxyAgent();
25151
25516
 
25152
- // src/agent-installation/verified-download.ts
25153
- var MAX_REDIRECTS = 4;
25154
- var REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
25155
- var InstallerDownloadError = class extends Error {
25517
+ // src/agent-installation/managed-agent-archive.ts
25518
+ var ARCHIVE_DOWNLOAD_LIMIT_BYTES = 128 * 1024 * 1024;
25519
+ var ARCHIVE_DOWNLOAD_TIMEOUT_MILLISECONDS = 2 * 60 * 1e3;
25520
+ var MANIFEST_LIMIT_BYTES = 16 * 1024;
25521
+ var ManagedAgentArchiveDefinition = class {
25522
+ archiveName;
25523
+ archiveSha256;
25524
+ archiveUrl;
25525
+ executableName;
25526
+ version;
25527
+ constructor(version2, archiveName, archiveUrl, archiveSha256, executableName) {
25528
+ this.archiveName = archiveName;
25529
+ this.archiveSha256 = archiveSha256;
25530
+ this.archiveUrl = new URL(archiveUrl);
25531
+ this.executableName = executableName;
25532
+ this.version = version2;
25533
+ }
25534
+ };
25535
+ var ZipManagedAgentArchiveDefinition = class extends ManagedAgentArchiveDefinition {
25536
+ extractor = "/usr/bin/unzip";
25537
+ extractArguments = (archivePath, destination) => ["-q", archivePath, "-d", destination];
25538
+ listArguments = (archivePath) => [
25539
+ "-Z1",
25540
+ archivePath
25541
+ ];
25542
+ };
25543
+ var TarGzipManagedAgentArchiveDefinition = class extends ManagedAgentArchiveDefinition {
25544
+ extractor = "/usr/bin/tar";
25545
+ extractArguments = (archivePath, destination) => ["-xzf", archivePath, "-C", destination];
25546
+ listArguments = (archivePath) => [
25547
+ "-tzf",
25548
+ archivePath
25549
+ ];
25550
+ };
25551
+ var ManagedAgentArchiveError = class extends Error {
25156
25552
  code;
25157
25553
  constructor(code, message, options = {}) {
25158
25554
  super(message, options);
25159
25555
  this.code = code;
25160
- this.name = "InstallerDownloadError";
25161
- }
25162
- };
25163
- var VerifiedDownload = class {
25164
- bytes;
25165
- sha256;
25166
- url;
25167
- constructor(url2, bytes, sha256) {
25168
- this.bytes = bytes;
25169
- this.sha256 = sha256;
25170
- this.url = url2;
25556
+ this.name = "ManagedAgentArchiveError";
25171
25557
  }
25172
25558
  };
25173
- var UndiciInstallerDownloadTransport = class {
25174
- get = async (url2, signal) => await fetch(url2, {
25175
- dispatcher: environmentProxyDispatcher,
25176
- headers: {
25177
- accept: "text/plain, application/octet-stream;q=0.9",
25178
- "user-agent": "Mobius-Agent-Installer/0.0.3"
25179
- },
25180
- method: "GET",
25181
- redirect: "manual",
25182
- signal
25183
- });
25184
- };
25185
- function validateUrl(url2, allowedHosts) {
25186
- if (url2.protocol !== "https:" || url2.username.length > 0 || url2.password.length > 0 || url2.port.length > 0 || !allowedHosts.has(url2.hostname)) {
25187
- throw new InstallerDownloadError(
25188
- "installer_host_not_allowed",
25189
- "The installer download target is not allowed"
25190
- );
25191
- }
25559
+ function isRecord6(value) {
25560
+ return typeof value === "object" && value !== null && !Array.isArray(value);
25192
25561
  }
25193
- async function fetchInstaller(options, signal, transport) {
25194
- let url2 = new URL(options.url);
25195
- for (let redirectCount = 0; redirectCount <= MAX_REDIRECTS; redirectCount += 1) {
25196
- validateUrl(url2, options.allowedHosts);
25197
- const response = await transport.get(url2, signal);
25198
- if (!REDIRECT_STATUSES.has(response.status)) {
25199
- return { response, url: url2 };
25200
- }
25201
- await response.body?.cancel();
25202
- const location = response.headers.get("location");
25203
- if (location === null || redirectCount === MAX_REDIRECTS) {
25204
- throw new InstallerDownloadError(
25205
- "installer_redirect_invalid",
25206
- "The installer returned an invalid redirect"
25207
- );
25208
- }
25209
- let redirected;
25210
- try {
25211
- redirected = new URL(location, url2);
25212
- } catch (error61) {
25213
- throw new InstallerDownloadError(
25214
- "installer_redirect_invalid",
25215
- "The installer returned an invalid redirect",
25216
- { cause: error61 }
25217
- );
25218
- }
25219
- try {
25220
- validateUrl(redirected, options.allowedHosts);
25221
- } catch (error61) {
25222
- throw new InstallerDownloadError(
25223
- "installer_redirect_not_allowed",
25224
- "The installer redirect left the approved host allowlist",
25225
- { cause: error61 }
25226
- );
25227
- }
25228
- url2 = redirected;
25229
- }
25230
- throw new InstallerDownloadError(
25231
- "installer_redirect_invalid",
25232
- "The installer returned too many redirects"
25233
- );
25234
- }
25235
- async function writeCompleteChunk(handle, chunk) {
25236
- let offset = 0;
25237
- while (offset < chunk.byteLength) {
25238
- const written = await handle.write(
25239
- chunk,
25240
- offset,
25241
- chunk.byteLength - offset
25242
- );
25243
- if (written.bytesWritten < 1) {
25244
- throw new InstallerDownloadError(
25245
- "installer_write_failed",
25246
- "The verified installer could not be stored"
25247
- );
25248
- }
25249
- offset += written.bytesWritten;
25250
- }
25251
- }
25252
- async function downloadVerifiedFile(options, transport = new UndiciInstallerDownloadTransport()) {
25253
- options.signal.throwIfAborted();
25254
- const timeoutSignal = AbortSignal.timeout(options.timeoutMilliseconds);
25255
- const signal = AbortSignal.any([options.signal, timeoutSignal]);
25256
- let handle = null;
25257
- let responseBody = null;
25258
- try {
25259
- const fetched = await fetchInstaller(options, signal, transport);
25260
- responseBody = fetched.response.body;
25261
- if (!fetched.response.ok || fetched.response.body === null) {
25262
- throw new InstallerDownloadError(
25263
- "installer_download_failed",
25264
- "The approved installer could not be downloaded"
25265
- );
25266
- }
25267
- const contentLength = fetched.response.headers.get("content-length");
25268
- if (contentLength !== null) {
25269
- const declaredLength = Number(contentLength);
25270
- if (!Number.isSafeInteger(declaredLength) || declaredLength < 1 || declaredLength > options.maximumBytes) {
25271
- throw new InstallerDownloadError(
25272
- "installer_size_invalid",
25273
- "The installer size is outside the approved limit"
25274
- );
25275
- }
25276
- }
25277
- handle = await open3(options.destination, "wx", 384);
25278
- const digest = createHash("sha256");
25279
- const reader = fetched.response.body.getReader();
25280
- let bytes = 0;
25281
- try {
25282
- while (true) {
25283
- signal.throwIfAborted();
25284
- const chunk = await reader.read();
25285
- if (chunk.done) {
25286
- break;
25287
- }
25288
- bytes += chunk.value.byteLength;
25289
- if (bytes > options.maximumBytes) {
25290
- throw new InstallerDownloadError(
25291
- "installer_size_invalid",
25292
- "The installer exceeded the approved size limit"
25293
- );
25294
- }
25295
- digest.update(chunk.value);
25296
- await writeCompleteChunk(handle, chunk.value);
25297
- }
25298
- } finally {
25299
- await reader.cancel().catch(() => void 0);
25300
- reader.releaseLock();
25301
- }
25302
- if (bytes === 0) {
25303
- throw new InstallerDownloadError(
25304
- "installer_verification_failed",
25305
- "The downloaded installer is empty"
25306
- );
25307
- }
25308
- await handle.sync();
25309
- await handle.close();
25310
- handle = null;
25311
- return new VerifiedDownload(fetched.url, bytes, digest.digest("hex"));
25312
- } catch (error61) {
25313
- if (handle !== null) {
25314
- await handle.close().catch(() => void 0);
25315
- }
25316
- await unlink(options.destination).catch(() => void 0);
25317
- if (options.signal.aborted) {
25318
- options.signal.throwIfAborted();
25319
- }
25320
- if (timeoutSignal.aborted) {
25321
- throw new InstallerDownloadError(
25322
- "installer_download_timeout",
25323
- "The installer download timed out",
25324
- { cause: error61 }
25325
- );
25326
- }
25327
- if (error61 instanceof InstallerDownloadError) {
25328
- throw error61;
25329
- }
25330
- throw new InstallerDownloadError(
25331
- "installer_download_failed",
25332
- "The approved installer could not be downloaded",
25333
- { cause: error61 }
25334
- );
25335
- } finally {
25336
- await responseBody?.cancel().catch(() => void 0);
25337
- }
25338
- }
25339
-
25340
- // src/agent-installation/managed-agent-archive.ts
25341
- var ARCHIVE_DOWNLOAD_LIMIT_BYTES = 128 * 1024 * 1024;
25342
- var ARCHIVE_DOWNLOAD_TIMEOUT_MILLISECONDS = 2 * 60 * 1e3;
25343
- var ARCHIVE_EXTRACTION_TIMEOUT_MILLISECONDS = 6e4;
25344
- var MANIFEST_LIMIT_BYTES = 16 * 1024;
25345
- var MINIMAL_PATH = "/usr/bin:/bin";
25346
- var ManagedAgentArchiveDefinition = class {
25347
- archiveName;
25348
- archiveSha256;
25349
- archiveUrl;
25350
- executableName;
25351
- version;
25352
- constructor(version2, archiveName, archiveUrl, archiveSha256, executableName) {
25353
- this.archiveName = archiveName;
25354
- this.archiveSha256 = archiveSha256;
25355
- this.archiveUrl = new URL(archiveUrl);
25356
- this.executableName = executableName;
25357
- this.version = version2;
25358
- }
25359
- };
25360
- var ZipManagedAgentArchiveDefinition = class extends ManagedAgentArchiveDefinition {
25361
- extractor = "/usr/bin/unzip";
25362
- extractArguments = (archivePath, destination) => ["-q", archivePath, "-d", destination];
25363
- listArguments = (archivePath) => [
25364
- "-Z1",
25365
- archivePath
25366
- ];
25367
- };
25368
- var TarGzipManagedAgentArchiveDefinition = class extends ManagedAgentArchiveDefinition {
25369
- extractor = "/usr/bin/tar";
25370
- extractArguments = (archivePath, destination) => ["-xzf", archivePath, "-C", destination];
25371
- listArguments = (archivePath) => [
25372
- "-tzf",
25373
- archivePath
25374
- ];
25375
- };
25376
- var ManagedAgentArchiveError = class extends Error {
25377
- code;
25378
- constructor(code, message, options = {}) {
25379
- super(message, options);
25380
- this.code = code;
25381
- this.name = "ManagedAgentArchiveError";
25382
- }
25383
- };
25384
- var ManagedAgentArchiveDownloader = class {
25385
- download = async (options) => await downloadVerifiedFile(options);
25386
- };
25387
- function isRecord5(value) {
25388
- return typeof value === "object" && value !== null && !Array.isArray(value);
25389
- }
25390
- function isContainedPath3(root, candidate) {
25391
- const difference = relative3(root, candidate);
25392
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute4(difference);
25562
+ function isContainedPath3(root, candidate) {
25563
+ const difference = relative3(root, candidate);
25564
+ return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep3}`) && !isAbsolute4(difference);
25393
25565
  }
25394
25566
  async function hashFile(path2, signal) {
25395
25567
  signal.throwIfAborted();
25396
- const digest = createHash2("sha256");
25568
+ const digest = createHash("sha256");
25397
25569
  const stream = createReadStream(path2, { signal });
25398
25570
  try {
25399
25571
  for await (const chunk of stream) {
@@ -25424,7 +25596,7 @@ async function hashFile(path2, signal) {
25424
25596
  async function readManifest(path2) {
25425
25597
  let handle;
25426
25598
  try {
25427
- handle = await open4(path2, "r");
25599
+ handle = await open3(path2, "r");
25428
25600
  } catch (error61) {
25429
25601
  throw new ManagedAgentArchiveError(
25430
25602
  "managed_archive_verification_failed",
@@ -25443,7 +25615,7 @@ async function readManifest(path2) {
25443
25615
  const parsed = JSON.parse(
25444
25616
  await handle.readFile({ encoding: "utf8" })
25445
25617
  );
25446
- if (!isRecord5(parsed)) {
25618
+ if (!isRecord6(parsed)) {
25447
25619
  throw new ManagedAgentArchiveError(
25448
25620
  "managed_archive_verification_failed",
25449
25621
  "The managed Agent archive manifest is invalid"
@@ -25495,144 +25667,6 @@ async function validateManagedAgentArchive(root, definition, signal) {
25495
25667
  );
25496
25668
  }
25497
25669
  }
25498
- function validateArchiveEntries(output2, definition) {
25499
- const entries = output2.split(/\r?\n/).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
25500
- if (entries.length !== 1 || entries[0] !== definition.executableName && entries[0] !== `./${definition.executableName}`) {
25501
- throw new ManagedAgentArchiveError(
25502
- "managed_archive_verification_failed",
25503
- "The managed Agent archive contains unexpected entries"
25504
- );
25505
- }
25506
- }
25507
- var ManagedAgentArchiveInstaller = class {
25508
- #downloader;
25509
- constructor(downloader = new ManagedAgentArchiveDownloader()) {
25510
- this.#downloader = downloader;
25511
- }
25512
- install = async (root, definition, signal) => {
25513
- signal.throwIfAborted();
25514
- try {
25515
- const metadata = await stat4(root);
25516
- if (metadata.isDirectory()) {
25517
- return await validateManagedAgentArchive(root, definition, signal);
25518
- }
25519
- } catch (error61) {
25520
- if (error61 instanceof ManagedAgentArchiveError || !(error61 instanceof Error) || !("code" in error61) || error61.code !== "ENOENT") {
25521
- throw error61;
25522
- }
25523
- }
25524
- const parent = dirname4(root);
25525
- await mkdir2(parent, { mode: 448, recursive: true });
25526
- const working = await mkdtemp2(
25527
- join8(parent, `.${definition.version}.archive-`)
25528
- );
25529
- const staging = await mkdtemp2(
25530
- join8(parent, `.${definition.version}.staging-`)
25531
- );
25532
- try {
25533
- const archivePath = join8(working, definition.archiveName);
25534
- const extractionRoot = join8(working, "extracted");
25535
- await mkdir2(extractionRoot, { mode: 448 });
25536
- const canonicalExtractionRoot = await realpath5(extractionRoot);
25537
- const download = await this.#downloader.download({
25538
- allowedHosts: /* @__PURE__ */ new Set([
25539
- "github.com",
25540
- "objects.githubusercontent.com",
25541
- "release-assets.githubusercontent.com"
25542
- ]),
25543
- destination: archivePath,
25544
- maximumBytes: ARCHIVE_DOWNLOAD_LIMIT_BYTES,
25545
- signal,
25546
- timeoutMilliseconds: ARCHIVE_DOWNLOAD_TIMEOUT_MILLISECONDS,
25547
- url: definition.archiveUrl
25548
- });
25549
- if (download.sha256 !== definition.archiveSha256) {
25550
- throw new ManagedAgentArchiveError(
25551
- "managed_archive_verification_failed",
25552
- "The managed Agent archive checksum is invalid"
25553
- );
25554
- }
25555
- const list = await runBoundedProcess({
25556
- arguments: definition.listArguments(archivePath),
25557
- command: definition.extractor,
25558
- cwd: working,
25559
- environment: { PATH: MINIMAL_PATH },
25560
- outputLimitBytes: 64 * 1024,
25561
- signal,
25562
- timeoutMilliseconds: ARCHIVE_EXTRACTION_TIMEOUT_MILLISECONDS
25563
- });
25564
- validateArchiveEntries(list.stdout, definition);
25565
- await runBoundedProcess({
25566
- arguments: definition.extractArguments(archivePath, extractionRoot),
25567
- command: definition.extractor,
25568
- cwd: working,
25569
- environment: { PATH: MINIMAL_PATH },
25570
- outputLimitBytes: 64 * 1024,
25571
- signal,
25572
- timeoutMilliseconds: ARCHIVE_EXTRACTION_TIMEOUT_MILLISECONDS
25573
- });
25574
- const extracted = await realpath5(
25575
- join8(canonicalExtractionRoot, definition.executableName)
25576
- );
25577
- const extractedMetadata = await stat4(extracted);
25578
- if (!isContainedPath3(canonicalExtractionRoot, extracted) || !extractedMetadata.isFile()) {
25579
- throw new ManagedAgentArchiveError(
25580
- "managed_archive_verification_failed",
25581
- "The managed Agent archive executable is invalid"
25582
- );
25583
- }
25584
- const binDirectory = join8(staging, "bin");
25585
- const executablePath = join8(binDirectory, definition.executableName);
25586
- await mkdir2(binDirectory, { mode: 448 });
25587
- await copyFile(extracted, executablePath);
25588
- await chmod(executablePath, 448);
25589
- const executableSha256 = await hashFile(executablePath, signal);
25590
- await writeFile(
25591
- join8(staging, "archive.json"),
25592
- `${JSON.stringify({
25593
- archiveSha256: definition.archiveSha256,
25594
- archiveUrl: definition.archiveUrl.toString(),
25595
- executableSha256,
25596
- version: definition.version
25597
- })}
25598
- `,
25599
- { mode: 384 }
25600
- );
25601
- await validateManagedAgentArchive(staging, definition, signal);
25602
- try {
25603
- await rename2(staging, root);
25604
- } catch (error61) {
25605
- try {
25606
- return await validateManagedAgentArchive(root, definition, signal);
25607
- } catch {
25608
- throw new ManagedAgentArchiveError(
25609
- "managed_archive_publish_failed",
25610
- "The managed Agent archive could not be published",
25611
- { cause: error61 }
25612
- );
25613
- }
25614
- }
25615
- return await validateManagedAgentArchive(root, definition, signal);
25616
- } catch (error61) {
25617
- if (signal.aborted) {
25618
- signal.throwIfAborted();
25619
- }
25620
- if (error61 instanceof ManagedAgentArchiveError) {
25621
- throw error61;
25622
- }
25623
- throw new ManagedAgentArchiveError(
25624
- "managed_archive_install_failed",
25625
- "The pinned Agent archive could not be installed",
25626
- { cause: error61 }
25627
- );
25628
- } finally {
25629
- await Promise.all([
25630
- rm2(working, { force: true, recursive: true }),
25631
- rm2(staging, { force: true, recursive: true })
25632
- ]);
25633
- }
25634
- };
25635
- };
25636
25670
 
25637
25671
  // src/agent-installation/opencode-managed-release.ts
25638
25672
  var OPENCODE_MANAGED_VERSION = "1.18.29";
@@ -25730,7 +25764,7 @@ var OpenCodeAgentSpecification = class extends DirectAcpAgentDefinition {
25730
25764
  // src/agent-catalog/agents/pi-agent.ts
25731
25765
  import { join as join10 } from "node:path";
25732
25766
  import {
25733
- methods as methods4
25767
+ methods as methods5
25734
25768
  } from "@agentclientprotocol/sdk";
25735
25769
 
25736
25770
  // src/agent-installation/pi-managed-packages.ts
@@ -25802,7 +25836,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
25802
25836
  );
25803
25837
  }
25804
25838
  const session = await connection.agent.request(
25805
- methods4.agent.session.new,
25839
+ methods5.agent.session.new,
25806
25840
  {
25807
25841
  additionalDirectories: [],
25808
25842
  cwd: defaultWorkspace,
@@ -25817,7 +25851,7 @@ var PiAgentSpecification = class extends BridgedAcpAgentDefinition {
25817
25851
  );
25818
25852
  }
25819
25853
  const prompt = await connection.agent.request(
25820
- methods4.agent.session.prompt,
25854
+ methods5.agent.session.prompt,
25821
25855
  {
25822
25856
  prompt: [{ text: "/session", type: "text" }],
25823
25857
  sessionId: session.sessionId
@@ -25954,7 +25988,7 @@ function supportedLocalAgentSpecifications() {
25954
25988
  // src/agent-catalog/acp-readiness-probe.ts
25955
25989
  import { spawn as spawn3 } from "node:child_process";
25956
25990
  import {
25957
- methods as methods5,
25991
+ methods as methods6,
25958
25992
  ndJsonStream as ndJsonStream2,
25959
25993
  PROTOCOL_VERSION as PROTOCOL_VERSION2,
25960
25994
  RequestError as RequestError2
@@ -26135,10 +26169,6 @@ async function resolveAdapterExecutables(specification, context) {
26135
26169
  context
26136
26170
  );
26137
26171
  }
26138
- async function resolveAgentExecutable(specification, context) {
26139
- const executables = await resolveAgentExecutables(specification, context);
26140
- return executables[0] ?? null;
26141
- }
26142
26172
  async function resolveAdapterExecutable(specification, context) {
26143
26173
  const executables = await resolveAdapterExecutables(specification, context);
26144
26174
  return executables[0] ?? null;
@@ -26204,41 +26234,41 @@ var DiscoveryAcpHandler = class {
26204
26234
  };
26205
26235
  function readableAcpStream(input2) {
26206
26236
  let byteLength = 0;
26207
- let open6 = true;
26237
+ let open5 = true;
26208
26238
  return new ReadableStream({
26209
26239
  start(controller) {
26210
26240
  input2.on("data", (chunk) => {
26211
- if (!open6) {
26241
+ if (!open5) {
26212
26242
  return;
26213
26243
  }
26214
26244
  if (!(chunk instanceof Uint8Array)) {
26215
- open6 = false;
26245
+ open5 = false;
26216
26246
  controller.error(new Error("ACP adapter produced invalid output"));
26217
26247
  return;
26218
26248
  }
26219
26249
  byteLength += chunk.byteLength;
26220
26250
  if (byteLength > ACP_OUTPUT_LIMIT_BYTES) {
26221
- open6 = false;
26251
+ open5 = false;
26222
26252
  controller.error(new Error("ACP adapter output limit exceeded"));
26223
26253
  return;
26224
26254
  }
26225
26255
  controller.enqueue(new Uint8Array(chunk));
26226
26256
  });
26227
26257
  input2.once("end", () => {
26228
- if (open6) {
26229
- open6 = false;
26258
+ if (open5) {
26259
+ open5 = false;
26230
26260
  controller.close();
26231
26261
  }
26232
26262
  });
26233
26263
  input2.once("error", (error61) => {
26234
- if (open6) {
26235
- open6 = false;
26264
+ if (open5) {
26265
+ open5 = false;
26236
26266
  controller.error(error61);
26237
26267
  }
26238
26268
  });
26239
26269
  },
26240
26270
  cancel() {
26241
- open6 = false;
26271
+ open5 = false;
26242
26272
  }
26243
26273
  });
26244
26274
  }
@@ -26307,7 +26337,7 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
26307
26337
  try {
26308
26338
  const initialized = await Promise.race([
26309
26339
  connection.agent.request(
26310
- methods5.agent.initialize,
26340
+ methods6.agent.initialize,
26311
26341
  {
26312
26342
  clientCapabilities: {},
26313
26343
  clientInfo: { name: "mobius", version: "0.0.3" },
@@ -26367,25 +26397,50 @@ async function probeAcpReadiness(specification, agent, environment, defaultWorks
26367
26397
  }
26368
26398
 
26369
26399
  // src/agent-catalog/discover-agent.ts
26370
- function probeFailure(specification, executableKind, error61) {
26400
+ function agentProbeFailure(specification, error61) {
26401
+ if (error61 instanceof AgentProbeError) {
26402
+ return new AgentProbeFailed(specification, error61.code, error61.message);
26403
+ }
26404
+ if (error61 instanceof ProcessExecutionError) {
26405
+ const code = error61.code === "process_timeout" ? "agent_probe_timeout" : "agent_probe_failed";
26406
+ return new AgentProbeFailed(
26407
+ specification,
26408
+ code,
26409
+ "Agent version probe failed"
26410
+ );
26411
+ }
26412
+ return new AgentProbeFailed(
26413
+ specification,
26414
+ "agent_probe_failed",
26415
+ "Agent probe failed"
26416
+ );
26417
+ }
26418
+ function integrationProbeFailure(specification, agent, error61) {
26371
26419
  if (error61 instanceof AgentProbeError) {
26372
26420
  if (error61.code === "authentication_required") {
26373
- return new AuthenticationRequiredAgent(specification);
26421
+ return new AuthenticationRequiredAgent(specification, agent);
26374
26422
  }
26375
- return error61.code === "acp_incompatible" ? new IncompatibleAdapter(specification) : new ProbeFailed(specification, error61.code, error61.message);
26423
+ return error61.code === "acp_incompatible" ? new IncompatibleAdapter(specification, agent) : new IntegrationProbeFailed(
26424
+ specification,
26425
+ agent,
26426
+ error61.code,
26427
+ error61.message
26428
+ );
26376
26429
  }
26377
26430
  if (error61 instanceof ProcessExecutionError) {
26378
- const code = error61.code === "process_timeout" ? `${executableKind}_probe_timeout` : `${executableKind}_probe_failed`;
26379
- return new ProbeFailed(
26431
+ const code = error61.code === "process_timeout" ? "adapter_probe_timeout" : "adapter_probe_failed";
26432
+ return new IntegrationProbeFailed(
26380
26433
  specification,
26434
+ agent,
26381
26435
  code,
26382
- `${executableKind === "agent" ? "Agent" : "Adapter"} version probe failed`
26436
+ "Adapter version probe failed"
26383
26437
  );
26384
26438
  }
26385
- return new ProbeFailed(
26439
+ return new IntegrationProbeFailed(
26386
26440
  specification,
26387
- `${executableKind}_probe_failed`,
26388
- `${executableKind === "agent" ? "Agent" : "Adapter"} probe failed`
26441
+ agent,
26442
+ "adapter_probe_failed",
26443
+ "Adapter probe failed"
26389
26444
  );
26390
26445
  }
26391
26446
  async function discoverAgent(specification, context) {
@@ -26394,12 +26449,6 @@ async function discoverAgent(specification, context) {
26394
26449
  resolveAdapterExecutables(specification, context),
26395
26450
  resolveAgentExecutables(specification, context)
26396
26451
  ]);
26397
- if (specification instanceof DirectAcpAgentDefinition && agents.length === 0) {
26398
- return new MissingAgent(specification);
26399
- }
26400
- if (adapters.length === 0) {
26401
- return new MissingAdapter(specification);
26402
- }
26403
26452
  if (agents.length === 0) {
26404
26453
  return new MissingAgent(specification);
26405
26454
  }
@@ -26419,9 +26468,18 @@ async function discoverAgent(specification, context) {
26419
26468
  if (context.signal.aborted) {
26420
26469
  context.signal.throwIfAborted();
26421
26470
  }
26422
- lastFailure = probeFailure(specification, "agent", error61);
26471
+ lastFailure = agentProbeFailure(specification, error61);
26423
26472
  continue;
26424
26473
  }
26474
+ const installedAgent = new AgentIntegrationDefinition(
26475
+ specification.id,
26476
+ specification.label,
26477
+ agent.identity.requestedPath,
26478
+ agentVersion
26479
+ );
26480
+ if (adapters.length === 0) {
26481
+ return new MissingAdapter(specification, installedAgent);
26482
+ }
26425
26483
  for (const adapter of adapters) {
26426
26484
  if (specification instanceof DirectAcpAgentDefinition && adapter.path !== agent.path) {
26427
26485
  continue;
@@ -26450,7 +26508,11 @@ async function discoverAgent(specification, context) {
26450
26508
  if (context.signal.aborted) {
26451
26509
  context.signal.throwIfAborted();
26452
26510
  }
26453
- lastFailure = probeFailure(specification, "adapter", error61);
26511
+ lastFailure = integrationProbeFailure(
26512
+ specification,
26513
+ installedAgent,
26514
+ error61
26515
+ );
26454
26516
  continue;
26455
26517
  }
26456
26518
  const definition = new LocalAgentDefinition(
@@ -26499,7 +26561,11 @@ async function discoverAgent(specification, context) {
26499
26561
  if (context.signal.aborted) {
26500
26562
  context.signal.throwIfAborted();
26501
26563
  }
26502
- const failure = probeFailure(specification, "adapter", error61);
26564
+ const failure = integrationProbeFailure(
26565
+ specification,
26566
+ installedAgent,
26567
+ error61
26568
+ );
26503
26569
  if (failure instanceof AuthenticationRequiredAgent) {
26504
26570
  return failure;
26505
26571
  }
@@ -26507,7 +26573,7 @@ async function discoverAgent(specification, context) {
26507
26573
  }
26508
26574
  }
26509
26575
  }
26510
- return lastFailure ?? new IncompatibleAdapter(specification);
26576
+ return lastFailure ?? new MissingAgent(specification);
26511
26577
  }
26512
26578
 
26513
26579
  // src/agent-catalog/discover-local-agents.ts
@@ -26518,11 +26584,7 @@ async function discoverLocalAgentInventory(options) {
26518
26584
  async (specification) => await discoverAgent(specification, options)
26519
26585
  )
26520
26586
  );
26521
- return new LocalAgentInventory(
26522
- discoveries,
26523
- options.platform,
26524
- options.architecture
26525
- );
26587
+ return new LocalAgentInventory(discoveries);
26526
26588
  }
26527
26589
 
26528
26590
  // src/pairing/pair-local-machine.ts
@@ -26550,7 +26612,7 @@ var PairingClientError = class extends Error {
26550
26612
  this.name = "PairingClientError";
26551
26613
  }
26552
26614
  };
26553
- function isRecord6(value) {
26615
+ function isRecord7(value) {
26554
26616
  return typeof value === "object" && value !== null && !Array.isArray(value);
26555
26617
  }
26556
26618
  function hasExactKeys(value, expectedKeys) {
@@ -26703,9 +26765,9 @@ async function readJsonResponse(response) {
26703
26765
  }
26704
26766
  }
26705
26767
  function readRelayError(value) {
26706
- if (isRecord6(value)) {
26768
+ if (isRecord7(value)) {
26707
26769
  const error61 = value["error"];
26708
- if (isRecord6(error61)) {
26770
+ if (isRecord7(error61)) {
26709
26771
  const code = error61["code"];
26710
26772
  const message = error61["message"];
26711
26773
  if (typeof code === "string" && typeof message === "string") {
@@ -26719,7 +26781,7 @@ function readRelayError(value) {
26719
26781
  );
26720
26782
  }
26721
26783
  function decodeClaimResponse(value) {
26722
- if (!isRecord6(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
26784
+ if (!isRecord7(value) || !hasExactKeys(value, CLAIM_RESPONSE_KEYS)) {
26723
26785
  throw new PairingClientError(
26724
26786
  "invalid_relay_response",
26725
26787
  "The relay returned an invalid pairing response"
@@ -26738,6 +26800,8 @@ function decodeClaimResponse(value) {
26738
26800
  }
26739
26801
  async function claimPairing(options, defaultWorkspace, localAgents, installableAgents, signal) {
26740
26802
  const agents = localAgents.map((agent) => ({
26803
+ agentPath: agent.agentIdentity.requestedPath,
26804
+ agentVersion: agent.agentVersion,
26741
26805
  id: agent.id,
26742
26806
  label: agent.label
26743
26807
  }));
@@ -26747,10 +26811,7 @@ async function claimPairing(options, defaultWorkspace, localAgents, installableA
26747
26811
  response = await fetch2(endpoint, {
26748
26812
  body: JSON.stringify({
26749
26813
  agents,
26750
- installableAgents: installableAgents.map((agent) => ({
26751
- id: agent.id,
26752
- label: agent.label
26753
- })),
26814
+ installableAgents,
26754
26815
  machineName: hostname3(),
26755
26816
  pairingCode: options.code,
26756
26817
  workspaceName: basename(defaultWorkspace) || "Local workspace"
@@ -26803,7 +26864,7 @@ async function persistConnection(channelId, relayOrigin, daemonToken, defaultWor
26803
26864
  return connectionPath;
26804
26865
  }
26805
26866
  function decodeSavedConnection(value, expectedChannelId) {
26806
- if (!isRecord6(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
26867
+ if (!isRecord7(value) || !hasExactKeys(value, SAVED_CONNECTION_KEYS)) {
26807
26868
  throw new PairingClientError(
26808
26869
  "invalid_connection",
26809
26870
  "The saved connection is invalid"
@@ -26833,7 +26894,7 @@ async function readSavedConnection(channelId) {
26833
26894
  `${channelId}.json`
26834
26895
  );
26835
26896
  let encoded = "";
26836
- const handle = await open5(connectionPath, "r");
26897
+ const handle = await open4(connectionPath, "r");
26837
26898
  try {
26838
26899
  const metadata = await handle.stat();
26839
26900
  if (!metadata.isFile() || metadata.size > MAX_CONNECTION_FILE_LENGTH) {
@@ -26870,7 +26931,7 @@ function assertInventoryUsable(inventory) {
26870
26931
  if (inventory.available.length + inventory.installable.length === 0) {
26871
26932
  throw new PairingClientError(
26872
26933
  "no_supported_agent",
26873
- "No supported Agent is ready or safely installable on this machine"
26934
+ "No supported Agent is available for local discovery"
26874
26935
  );
26875
26936
  }
26876
26937
  }
@@ -26958,7 +27019,7 @@ async function resumeLocalMachine(arguments_, signal = new AbortController().sig
26958
27019
  // src/run-daemon.ts
26959
27020
  import { basename as basename3 } from "node:path";
26960
27021
  import { styleText } from "node:util";
26961
- import { WebSocket as WebSocket2 } from "undici";
27022
+ import { fetch as fetch4, WebSocket as WebSocket2 } from "undici";
26962
27023
 
26963
27024
  // src/agent-catalog/publish-agent-catalog.ts
26964
27025
  import { fetch as fetch3 } from "undici";
@@ -26991,13 +27052,12 @@ async function publishAgentCatalog(config2, signal) {
26991
27052
  response = await fetch3(catalogEndpoint(config2.relayUrl), {
26992
27053
  body: JSON.stringify({
26993
27054
  agents: catalog.agents.map((agent) => ({
27055
+ agentPath: agent.agentIdentity.requestedPath,
27056
+ agentVersion: agent.agentVersion,
26994
27057
  id: agent.id,
26995
27058
  label: agent.label
26996
27059
  })),
26997
- installableAgents: catalog.installableAgents.map((agent) => ({
26998
- id: agent.id,
26999
- label: agent.label
27000
- }))
27060
+ installableAgents: catalog.installableAgents
27001
27061
  }),
27002
27062
  dispatcher: environmentProxyDispatcher,
27003
27063
  headers: { "content-type": "application/json" },
@@ -27093,7 +27153,7 @@ var InstallationJob = class {
27093
27153
  };
27094
27154
  function authorizedSpecificationFor(specifications, agentId) {
27095
27155
  for (const specification of specifications) {
27096
- if (specification.id === agentId && specification.supportsInstallation(process.platform, process.arch)) {
27156
+ if (specification.id === agentId) {
27097
27157
  return specification;
27098
27158
  }
27099
27159
  }
@@ -27105,7 +27165,7 @@ function executionFailure(error61) {
27105
27165
  }
27106
27166
  return new InstallationManagerError(
27107
27167
  "installation_failed",
27108
- "The local Agent installation failed",
27168
+ "The local Agent integration installation failed",
27109
27169
  { cause: error61 }
27110
27170
  );
27111
27171
  }
@@ -27176,7 +27236,7 @@ var AgentInstallationManager = class {
27176
27236
  command.requestId,
27177
27237
  command.agentId,
27178
27238
  "installation_in_progress",
27179
- "An installation for this Agent is already running"
27239
+ "An integration installation for this Agent is already running"
27180
27240
  );
27181
27241
  const job2 = new InstallationJob(command.requestId, command.agentId);
27182
27242
  job2.state = busy;
@@ -27213,7 +27273,7 @@ var AgentInstallationManager = class {
27213
27273
  job.requestId,
27214
27274
  job.agentId
27215
27275
  );
27216
- job.controller.abort(new Error("Agent installation cancelled"));
27276
+ job.controller.abort(new Error("Agent integration installation cancelled"));
27217
27277
  return await job.completion.promise;
27218
27278
  };
27219
27279
  close = async () => {
@@ -27223,7 +27283,7 @@ var AgentInstallationManager = class {
27223
27283
  if (job === void 0) {
27224
27284
  throw new InstallationManagerError(
27225
27285
  "installation_state_invalid",
27226
- "An active Agent installation is unavailable"
27286
+ "An active Agent integration installation is unavailable"
27227
27287
  );
27228
27288
  }
27229
27289
  job.controller.abort(new Error("Mobius daemon stopped"));
@@ -27245,7 +27305,7 @@ var AgentInstallationManager = class {
27245
27305
  job.controller.abort(
27246
27306
  new InstallationManagerError(
27247
27307
  "installation_timeout",
27248
- "The local Agent installation exceeded its deadline"
27308
+ "The local Agent integration installation exceeded its deadline"
27249
27309
  )
27250
27310
  );
27251
27311
  }, INSTALLATION_DEADLINE_MILLISECONDS);
@@ -27257,898 +27317,87 @@ var AgentInstallationManager = class {
27257
27317
  job.requestId,
27258
27318
  specification.id
27259
27319
  );
27260
- await this.#executor.execute(
27261
- specification.id,
27262
- job.requestId,
27263
- async (stage) => {
27264
- signal.throwIfAborted();
27265
- await this.#transition(
27266
- job,
27267
- new RunningInstallation(job.requestId, job.agentId, stage)
27268
- );
27269
- this.#audit.record(
27270
- `agent_installation_${stage}`,
27271
- job.requestId,
27272
- job.agentId
27273
- );
27274
- },
27275
- signal
27276
- );
27277
- signal.throwIfAborted();
27278
- const succeeded = new SucceededInstallation(job.requestId, job.agentId);
27279
- await this.#transition(job, succeeded);
27280
- this.#audit.record(
27281
- "agent_installation_completed",
27282
- job.requestId,
27283
- job.agentId
27284
- );
27285
- job.completion.resolve(succeeded);
27286
- } catch (error61) {
27287
- if (signal.aborted) {
27288
- if (signal.reason instanceof InstallationManagerError && signal.reason.code === "installation_timeout") {
27289
- const timedOut = new FailedInstallation(
27290
- job.requestId,
27291
- job.agentId,
27292
- signal.reason.code,
27293
- signal.reason.message
27294
- );
27295
- await this.#transition(job, timedOut);
27296
- this.#audit.record(
27297
- "agent_installation_failed_installation_timeout",
27298
- job.requestId,
27299
- job.agentId
27300
- );
27301
- job.completion.resolve(timedOut);
27302
- return;
27303
- }
27304
- const cancelled = new CancelledInstallation(job.requestId, job.agentId);
27305
- await this.#transition(job, cancelled);
27306
- this.#audit.record(
27307
- "agent_installation_cancelled",
27308
- job.requestId,
27309
- job.agentId
27310
- );
27311
- job.completion.resolve(cancelled);
27312
- } else {
27313
- const failure = executionFailure(error61);
27314
- const failed = new FailedInstallation(
27315
- job.requestId,
27316
- job.agentId,
27317
- failure.code,
27318
- failure.message
27319
- );
27320
- await this.#transition(job, failed);
27321
- this.#audit.record(
27322
- `agent_installation_failed_${failure.code}`,
27323
- job.requestId,
27324
- job.agentId
27325
- );
27326
- job.completion.resolve(failed);
27327
- }
27328
- } finally {
27329
- clearTimeout(deadline);
27330
- externalSignal.removeEventListener("abort", abort);
27331
- if (this.#activeAgents.get(job.agentId) === job.requestId) {
27332
- this.#activeAgents.delete(job.agentId);
27333
- }
27334
- }
27335
- };
27336
- };
27337
-
27338
- // src/agent-installation/automatic-adapter-provisioner.ts
27339
- import { randomUUID as randomUUID2 } from "node:crypto";
27340
- var AUTOMATIC_ADAPTER_FAILURE_CODES = /* @__PURE__ */ new Set([
27341
- "adapter_not_found",
27342
- "adapter_probe_failed",
27343
- "adapter_probe_timeout",
27344
- "acp_incompatible"
27345
- ]);
27346
- var InstalledAutomaticAdapter = class {
27347
- executable;
27348
- requestId;
27349
- specification;
27350
- constructor(specification, requestId, executable) {
27351
- this.executable = executable;
27352
- this.requestId = requestId;
27353
- this.specification = specification;
27354
- }
27355
- };
27356
- function shouldProvisionAdapter(unavailable, options) {
27357
- return unavailable.specification instanceof BridgedAcpAgentDefinition && AUTOMATIC_ADAPTER_FAILURE_CODES.has(unavailable.code) && options.environment[unavailable.specification.adapterOverrideVariable] === void 0 && unavailable.specification.supportsInstallation(
27358
- options.platform ?? process.platform,
27359
- options.architecture ?? process.arch
27360
- );
27361
- }
27362
- function stableFailureCode(error61) {
27363
- return error61 instanceof ManagedAdapterInstallError ? error61.code : "adapter_install_failed";
27364
- }
27365
- function discoveryOptions(options, environment, signal, specifications) {
27366
- return {
27367
- ...options.architecture === void 0 ? {} : { architecture: options.architecture },
27368
- defaultWorkspace: options.defaultWorkspace,
27369
- environment,
27370
- ...options.platform === void 0 ? {} : { platform: options.platform },
27371
- signal,
27372
- specifications
27373
- };
27374
- }
27375
- var AutomaticAdapterProvisioner = class {
27376
- #adapterInstaller;
27377
- #options;
27378
- #specifications;
27379
- constructor(options, adapterInstaller, specifications = supportedLocalAgentSpecifications()) {
27380
- this.#adapterInstaller = adapterInstaller;
27381
- this.#options = options;
27382
- this.#specifications = Object.freeze([...specifications]);
27383
- }
27384
- prepare = async (signal) => {
27385
- signal.throwIfAborted();
27386
- let inventory = await discoverLocalAgentInventory(
27387
- discoveryOptions(
27388
- this.#options,
27389
- this.#options.environment,
27390
- signal,
27391
- this.#specifications
27392
- )
27393
- );
27394
- const candidates = inventory.unavailable.filter(
27395
- (unavailable) => shouldProvisionAdapter(unavailable, this.#options)
27396
- );
27397
- const attempts = [];
27398
- for (const unavailable of candidates) {
27399
- signal.throwIfAborted();
27400
- const specification = unavailable.specification;
27401
- if (!(specification instanceof BridgedAcpAgentDefinition)) {
27402
- attempts.push(null);
27403
- continue;
27404
- }
27405
- const verifiedAgent = await findVerifiedAgentExecutable(
27406
- specification,
27407
- discoveryOptions(
27408
- this.#options,
27409
- this.#options.environment,
27410
- signal,
27411
- this.#specifications
27412
- )
27413
- );
27414
- if (verifiedAgent === null) {
27415
- attempts.push(null);
27416
- continue;
27417
- }
27418
- const requestId = `automatic-adapter-${randomUUID2()}`;
27419
- this.#options.audit.record(
27420
- "agent_adapter_auto_install_started",
27421
- requestId,
27422
- specification.id,
27423
- {
27424
- agentVersion: verifiedAgent.version,
27425
- adapterVersion: specification.adapterVersion
27426
- }
27427
- );
27428
- process.stdout.write(
27429
- `Installing the pinned ACP adapter for ${specification.label}.
27430
- `
27431
- );
27432
- try {
27433
- const executable = await this.#adapterInstaller.install(
27434
- specification,
27435
- signal
27436
- );
27437
- this.#options.audit.record(
27438
- "agent_adapter_auto_install_completed",
27439
- requestId,
27440
- specification.id,
27441
- { adapterVersion: specification.adapterVersion }
27442
- );
27443
- attempts.push(
27444
- new InstalledAutomaticAdapter(specification, requestId, executable)
27445
- );
27446
- } catch (error61) {
27447
- if (signal.aborted) {
27448
- this.#options.audit.record(
27449
- "agent_adapter_auto_install_cancelled",
27450
- requestId,
27451
- specification.id
27452
- );
27453
- signal.throwIfAborted();
27454
- }
27455
- this.#options.audit.record(
27456
- "agent_adapter_auto_install_failed",
27457
- requestId,
27458
- specification.id,
27459
- { code: stableFailureCode(error61) }
27460
- );
27461
- process.stderr.write(
27462
- `The pinned ACP adapter for ${specification.label} could not be installed automatically; the daemon will continue.
27463
- `
27464
- );
27465
- attempts.push(null);
27466
- }
27467
- }
27468
- signal.throwIfAborted();
27469
- const installed = attempts.filter(
27470
- (attempt) => attempt !== null
27471
- );
27472
- if (installed.length > 0) {
27473
- const verificationEnvironment = {
27474
- ...this.#options.environment
27475
- };
27476
- for (const attempt of installed) {
27477
- verificationEnvironment[attempt.specification.adapterOverrideVariable] = attempt.executable.path;
27478
- }
27479
- inventory = await discoverLocalAgentInventory(
27480
- discoveryOptions(
27481
- this.#options,
27482
- verificationEnvironment,
27483
- signal,
27484
- this.#specifications
27485
- )
27486
- );
27487
- }
27488
- this.#options.catalog.transition(
27489
- inventory.readyAgents(),
27490
- inventory.installable
27491
- );
27492
- for (const attempt of installed) {
27493
- const available = inventory.available.find(
27494
- (candidate) => candidate instanceof AvailableAgent && candidate.specification.id === attempt.specification.id
27495
- );
27496
- if (available === void 0) {
27497
- const unavailable = inventory.unavailable.find(
27498
- (candidate) => candidate.specification.id === attempt.specification.id
27499
- );
27500
- this.#options.audit.record(
27501
- "agent_adapter_auto_install_verification_failed",
27502
- attempt.requestId,
27503
- attempt.specification.id,
27504
- { code: unavailable?.code ?? "agent_verification_failed" }
27505
- );
27506
- continue;
27507
- }
27508
- this.#options.audit.record(
27509
- "agent_adapter_auto_install_verified",
27510
- attempt.requestId,
27511
- attempt.specification.id,
27512
- {
27513
- adapterVersion: available.agent.adapterVersion,
27514
- agentVersion: available.agent.agentVersion
27515
- }
27516
- );
27517
- process.stdout.write(
27518
- `${attempt.specification.label} ACP integration is ready.
27519
- `
27520
- );
27521
- }
27522
- return inventory;
27523
- };
27524
- };
27525
-
27526
- // src/agent-installation/fixed-installation-executor.ts
27527
- import { realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
27528
- import { resolve as resolve4 } from "node:path";
27529
-
27530
- // src/agent-installation/fixed-agent-install-recipes.ts
27531
- import { mkdir as mkdir5, mkdtemp as mkdtemp3, rm as rm3 } from "node:fs/promises";
27532
- import { join as join17 } from "node:path";
27533
-
27534
- // src/agent-installation/fixed-agent-install-recipe.ts
27535
- var FixedAgentInstallRecipe = class {
27536
- assertSupportedPlatform = () => {
27537
- if (process.platform !== "darwin" && process.platform !== "linux" || process.arch !== "arm64" && process.arch !== "x64") {
27538
- throw new InstallationManagerError(
27539
- "unsupported_install_platform",
27540
- "This Agent installation recipe does not support the local platform"
27541
- );
27542
- }
27543
- };
27544
- requireInstalledExecutable = async (path2) => {
27545
- const executable = await resolveExecutablePath(path2);
27546
- if (executable === null) {
27547
- throw new InstallationManagerError(
27548
- "agent_verification_failed",
27549
- "The Agent installer did not produce a valid executable"
27550
- );
27551
- }
27552
- return executable;
27553
- };
27554
- };
27555
-
27556
- // src/agent-installation/grok-build-install-recipe.ts
27557
- import { mkdir as mkdir4, realpath as realpath7, stat as stat6 } from "node:fs/promises";
27558
- import { delimiter as delimiter2, dirname as dirname5, isAbsolute as isAbsolute7, join as join15, relative as relative4, sep as sep4 } from "node:path";
27559
- var INSTALL_TIMEOUT_MILLISECONDS2 = 5 * 60 * 1e3;
27560
- function isContainedPath4(root, candidate) {
27561
- const difference = relative4(root, candidate);
27562
- return difference.length > 0 && difference !== ".." && !difference.startsWith(`..${sep4}`) && !isAbsolute7(difference);
27563
- }
27564
- async function resolveLifecycleScript(packageRoot) {
27565
- try {
27566
- const canonicalPackageRoot = await realpath7(packageRoot);
27567
- const script = await realpath7(
27568
- join15(canonicalPackageRoot, "bin", "postinstall.js")
27569
- );
27570
- const metadata = await stat6(script);
27571
- if (!metadata.isFile() || !isContainedPath4(canonicalPackageRoot, script)) {
27572
- throw new Error("Invalid Grok Build lifecycle script");
27573
- }
27574
- return script;
27575
- } catch (error61) {
27576
- throw new InstallationManagerError(
27577
- "agent_verification_failed",
27578
- "The managed Grok Build lifecycle script is invalid",
27579
- { cause: error61 }
27580
- );
27581
- }
27582
- }
27583
- var GrokBuildInstallRecipe = class extends FixedAgentInstallRecipe {
27584
- #npmInstaller;
27585
- id = "grok-build";
27586
- label = "Grok Build";
27587
- releaseChannel = GROK_BUILD_MANAGED_VERSION;
27588
- constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27589
- super();
27590
- this.#npmInstaller = npmInstaller;
27591
- }
27592
- install = async (options) => {
27593
- this.assertSupportedPlatform();
27594
- const definition = grokBuildManagedPackage(process.platform, process.arch);
27595
- const versionRoot = join15(
27596
- options.stateDirectory,
27597
- "agents",
27598
- this.id,
27599
- GROK_BUILD_MANAGED_VERSION
27600
- );
27601
- const packageRoot = join15(versionRoot, "package");
27602
- const managedHome = join15(versionRoot, "home");
27603
- try {
27604
- await mkdir4(managedHome, { mode: 448, recursive: true });
27605
- const canonicalHome = await realpath7(managedHome);
27606
- await options.report("downloading");
27607
- await options.report("verifying");
27608
- await options.report("installing_agent");
27609
- await this.#npmInstaller.install(
27610
- packageRoot,
27611
- definition,
27612
- options.environment,
27613
- options.signal
27614
- );
27615
- options.audit.record(
27616
- "agent_npm_package_verified",
27617
- options.requestId,
27618
- this.id,
27619
- {
27620
- integrity: definition.integrity,
27621
- package: definition.packageName,
27622
- version: definition.version
27623
- }
27624
- );
27625
- const script = await resolveLifecycleScript(
27626
- join15(packageRoot, "node_modules", "@xai-official", "grok")
27627
- );
27628
- await runBoundedProcess({
27629
- arguments: [script],
27630
- command: process.execPath,
27631
- cwd: dirname5(script),
27632
- environment: {
27633
- GROK_HOME: canonicalHome,
27634
- GROK_INSTALL_COMPLETIONS: "0",
27635
- GROK_NPM_REGISTRY: "https://registry.npmjs.org/",
27636
- HOME: canonicalHome,
27637
- PATH: `${dirname5(process.execPath)}${delimiter2}/usr/bin${delimiter2}/bin`
27638
- },
27639
- outputLimitBytes: 64 * 1024,
27640
- signal: options.signal,
27641
- timeoutMilliseconds: INSTALL_TIMEOUT_MILLISECONDS2
27642
- });
27643
- options.audit.record(
27644
- "agent_lifecycle_step_completed",
27645
- options.requestId,
27646
- this.id,
27647
- {
27648
- lifecycle: "postinstall",
27649
- package: definition.packageName,
27650
- version: definition.version
27651
- }
27652
- );
27653
- return await this.requireInstalledExecutable(
27654
- join15(canonicalHome, "bin", "grok")
27655
- );
27656
- } catch (error61) {
27657
- if (options.signal.aborted) {
27658
- options.signal.throwIfAborted();
27659
- }
27660
- if (error61 instanceof ManagedNpmPackageError) {
27661
- if (error61.code === "managed_package_verification_failed") {
27662
- throw new InstallationManagerError(
27663
- "agent_verification_failed",
27664
- "The managed Grok Build packages did not match their pinned artifacts",
27665
- { cause: error61 }
27666
- );
27667
- }
27668
- if (error61.code === "managed_package_publish_failed") {
27669
- throw new InstallationManagerError(
27670
- "agent_publish_failed",
27671
- "The managed Grok Build package could not be published",
27672
- { cause: error61 }
27673
- );
27674
- }
27675
- throw new InstallationManagerError(error61.code, error61.message, {
27676
- cause: error61
27677
- });
27678
- }
27679
- if (error61 instanceof InstallationManagerError) {
27680
- throw error61;
27681
- }
27682
- throw new InstallationManagerError(
27683
- "agent_install_failed",
27684
- "The fixed Grok Build installation recipe failed",
27685
- { cause: error61 }
27686
- );
27687
- }
27688
- };
27689
- };
27690
-
27691
- // src/agent-installation/workbuddy-install-recipe.ts
27692
- import { join as join16 } from "node:path";
27693
- var WorkBuddyInstallRecipe = class extends FixedAgentInstallRecipe {
27694
- #npmInstaller;
27695
- id = "workbuddy";
27696
- label = "WorkBuddy";
27697
- releaseChannel = WORKBUDDY_MANAGED_VERSION;
27698
- constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27699
- super();
27700
- this.#npmInstaller = npmInstaller;
27701
- }
27702
- install = async (options) => {
27703
- this.assertSupportedPlatform();
27704
- try {
27705
- await options.report("downloading");
27706
- await options.report("verifying");
27707
- await options.report("installing_agent");
27708
- const executable = await this.#npmInstaller.install(
27709
- join16(
27710
- options.stateDirectory,
27711
- "agents",
27712
- this.id,
27713
- WORKBUDDY_MANAGED_VERSION
27714
- ),
27715
- WORKBUDDY_MANAGED_PACKAGE,
27716
- options.environment,
27717
- options.signal
27718
- );
27719
- options.audit.record(
27720
- "agent_npm_package_verified",
27721
- options.requestId,
27722
- this.id,
27723
- {
27724
- integrity: WORKBUDDY_MANAGED_PACKAGE.integrity,
27725
- package: WORKBUDDY_MANAGED_PACKAGE.packageName,
27726
- version: WORKBUDDY_MANAGED_PACKAGE.version
27727
- }
27728
- );
27729
- return executable;
27730
- } catch (error61) {
27731
- if (options.signal.aborted) {
27732
- options.signal.throwIfAborted();
27733
- }
27734
- if (error61 instanceof ManagedNpmPackageError) {
27735
- if (error61.code === "managed_package_verification_failed") {
27736
- throw new InstallationManagerError(
27737
- "agent_verification_failed",
27738
- "The managed WorkBuddy package did not match its pinned artifact",
27739
- { cause: error61 }
27740
- );
27741
- }
27742
- if (error61.code === "managed_package_publish_failed") {
27743
- throw new InstallationManagerError(
27744
- "agent_publish_failed",
27745
- "The managed WorkBuddy package could not be published",
27746
- { cause: error61 }
27747
- );
27748
- }
27749
- throw new InstallationManagerError(error61.code, error61.message, {
27750
- cause: error61
27751
- });
27752
- }
27753
- if (error61 instanceof InstallationManagerError) {
27754
- throw error61;
27755
- }
27756
- throw new InstallationManagerError(
27757
- "agent_install_failed",
27758
- "The fixed WorkBuddy installation recipe failed",
27759
- { cause: error61 }
27760
- );
27761
- }
27762
- };
27763
- };
27764
-
27765
- // src/agent-installation/fixed-agent-install-recipes.ts
27766
- var INSTALLER_DOWNLOAD_LIMIT_BYTES = 1024 * 1024;
27767
- var INSTALLER_DOWNLOAD_TIMEOUT_MILLISECONDS = 6e4;
27768
- var AGENT_INSTALL_TIMEOUT_MILLISECONDS = 5 * 60 * 1e3;
27769
- var MINIMAL_PATH2 = "/usr/bin:/bin";
27770
- var CodexInstallRecipe = class extends FixedAgentInstallRecipe {
27771
- id = "codex";
27772
- label = "Codex";
27773
- releaseChannel = "latest";
27774
- install = async (options) => {
27775
- this.assertSupportedPlatform();
27776
- const root = join17(options.stateDirectory, "agents", this.id);
27777
- const temporaryRoot = join17(options.stateDirectory, "temporary");
27778
- await Promise.all([
27779
- mkdir5(root, { mode: 448, recursive: true }),
27780
- mkdir5(temporaryRoot, { mode: 448, recursive: true })
27781
- ]);
27782
- const temporaryDirectory = await mkdtemp3(
27783
- join17(temporaryRoot, ".codex-install-")
27784
- );
27785
- const installerPath = join17(temporaryDirectory, "install.sh");
27786
- const installDirectory = join17(root, "bin");
27787
- const codexHome = join17(root, "home");
27788
- try {
27789
- await Promise.all([
27790
- mkdir5(installDirectory, { mode: 448, recursive: true }),
27791
- mkdir5(codexHome, { mode: 448, recursive: true })
27792
- ]);
27793
- await options.report("downloading");
27794
- const download = await downloadVerifiedFile({
27795
- allowedHosts: /* @__PURE__ */ new Set(["chatgpt.com", "releases.openai.com"]),
27796
- destination: installerPath,
27797
- maximumBytes: INSTALLER_DOWNLOAD_LIMIT_BYTES,
27798
- signal: options.signal,
27799
- timeoutMilliseconds: INSTALLER_DOWNLOAD_TIMEOUT_MILLISECONDS,
27800
- url: new URL("https://chatgpt.com/codex/install.sh")
27801
- });
27802
- options.audit.record(
27803
- "agent_installer_download_verified",
27804
- options.requestId,
27805
- this.id,
27806
- {
27807
- bytes: download.bytes.toString(),
27808
- releaseChannel: this.releaseChannel,
27809
- sha256: download.sha256
27810
- }
27811
- );
27812
- await options.report("verifying");
27813
- await options.report("installing_agent");
27814
- await runBoundedProcess({
27815
- arguments: [installerPath],
27816
- command: "/bin/sh",
27817
- cwd: temporaryDirectory,
27818
- environment: {
27819
- CODEX_HOME: codexHome,
27820
- CODEX_INSTALL_DIR: installDirectory,
27821
- CODEX_NON_INTERACTIVE: "1",
27822
- CODEX_RELEASE: this.releaseChannel,
27823
- HOME: codexHome,
27824
- PATH: MINIMAL_PATH2
27825
- },
27826
- outputLimitBytes: 64 * 1024,
27827
- signal: options.signal,
27828
- timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
27829
- });
27830
- return await this.requireInstalledExecutable(
27831
- join17(installDirectory, "codex")
27832
- );
27833
- } catch (error61) {
27834
- if (options.signal.aborted) {
27835
- options.signal.throwIfAborted();
27836
- }
27837
- if (error61 instanceof InstallationManagerError || error61 instanceof Error && "code" in error61) {
27838
- throw error61;
27839
- }
27840
- throw new InstallationManagerError(
27841
- "agent_install_failed",
27842
- "The fixed Codex installation recipe failed"
27843
- );
27844
- } finally {
27845
- await rm3(temporaryDirectory, { force: true, recursive: true });
27846
- }
27847
- };
27848
- };
27849
- var ClaudeCodeInstallRecipe = class extends FixedAgentInstallRecipe {
27850
- id = "claude";
27851
- label = "Claude Code";
27852
- releaseChannel = "stable";
27853
- install = async (options) => {
27854
- this.assertSupportedPlatform();
27855
- const root = join17(options.stateDirectory, "agents", this.id);
27856
- const managedHome = join17(root, "home");
27857
- const temporaryRoot = join17(options.stateDirectory, "temporary");
27858
- await Promise.all([
27859
- mkdir5(managedHome, { mode: 448, recursive: true }),
27860
- mkdir5(temporaryRoot, { mode: 448, recursive: true })
27861
- ]);
27862
- const temporaryDirectory = await mkdtemp3(
27863
- join17(temporaryRoot, ".claude-install-")
27864
- );
27865
- const installerPath = join17(temporaryDirectory, "install.sh");
27866
- try {
27867
- await options.report("downloading");
27868
- const download = await downloadVerifiedFile({
27869
- allowedHosts: /* @__PURE__ */ new Set(["claude.ai"]),
27870
- destination: installerPath,
27871
- maximumBytes: INSTALLER_DOWNLOAD_LIMIT_BYTES,
27872
- signal: options.signal,
27873
- timeoutMilliseconds: INSTALLER_DOWNLOAD_TIMEOUT_MILLISECONDS,
27874
- url: new URL("https://claude.ai/install.sh")
27875
- });
27876
- options.audit.record(
27877
- "agent_installer_download_verified",
27878
- options.requestId,
27879
- this.id,
27880
- {
27881
- bytes: download.bytes.toString(),
27882
- releaseChannel: this.releaseChannel,
27883
- sha256: download.sha256
27884
- }
27885
- );
27886
- await options.report("verifying");
27887
- await options.report("installing_agent");
27888
- await runBoundedProcess({
27889
- arguments: [installerPath, "stable"],
27890
- command: "/bin/bash",
27891
- cwd: temporaryDirectory,
27892
- environment: {
27893
- HOME: managedHome,
27894
- PATH: MINIMAL_PATH2,
27895
- SHELL: "/bin/bash"
27896
- },
27897
- outputLimitBytes: 64 * 1024,
27898
- signal: options.signal,
27899
- timeoutMilliseconds: AGENT_INSTALL_TIMEOUT_MILLISECONDS
27900
- });
27901
- return await this.requireInstalledExecutable(
27902
- join17(managedHome, ".local", "bin", "claude")
27903
- );
27904
- } catch (error61) {
27905
- if (options.signal.aborted) {
27906
- options.signal.throwIfAborted();
27907
- }
27908
- if (error61 instanceof InstallationManagerError || error61 instanceof Error && "code" in error61) {
27909
- throw error61;
27910
- }
27911
- throw new InstallationManagerError(
27912
- "agent_install_failed",
27913
- "The fixed Claude Code installation recipe failed"
27914
- );
27915
- } finally {
27916
- await rm3(temporaryDirectory, { force: true, recursive: true });
27917
- }
27918
- };
27919
- };
27920
- var PiInstallRecipe = class extends FixedAgentInstallRecipe {
27921
- #npmInstaller;
27922
- id = "pi";
27923
- label = "Pi";
27924
- releaseChannel = PI_AGENT_PACKAGE.version;
27925
- constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27926
- super();
27927
- this.#npmInstaller = npmInstaller;
27928
- }
27929
- install = async (options) => {
27930
- this.assertSupportedPlatform();
27931
- try {
27932
- await options.report("downloading");
27933
- await options.report("verifying");
27934
- await options.report("installing_agent");
27935
- const executable = await this.#npmInstaller.install(
27936
- join17(
27937
- options.stateDirectory,
27938
- "agents",
27939
- this.id,
27940
- PI_AGENT_PACKAGE.version
27941
- ),
27942
- PI_AGENT_PACKAGE,
27943
- options.environment,
27944
- options.signal
27945
- );
27946
- options.audit.record(
27947
- "agent_npm_package_verified",
27948
- options.requestId,
27949
- this.id,
27950
- {
27951
- integrity: PI_AGENT_PACKAGE.integrity,
27952
- package: PI_AGENT_PACKAGE.packageName,
27953
- version: PI_AGENT_PACKAGE.version
27954
- }
27955
- );
27956
- return executable;
27957
- } catch (error61) {
27958
- if (options.signal.aborted) {
27959
- options.signal.throwIfAborted();
27960
- }
27961
- if (error61 instanceof ManagedNpmPackageError) {
27962
- if (error61.code === "managed_package_verification_failed") {
27963
- throw new InstallationManagerError(
27964
- "agent_verification_failed",
27965
- "The managed Pi package did not match its pinned artifact",
27966
- { cause: error61 }
27967
- );
27968
- }
27969
- if (error61.code === "managed_package_publish_failed") {
27970
- throw new InstallationManagerError(
27971
- "agent_publish_failed",
27972
- "The managed Pi package could not be published",
27973
- { cause: error61 }
27974
- );
27975
- }
27976
- throw new InstallationManagerError(error61.code, error61.message, {
27977
- cause: error61
27978
- });
27979
- }
27980
- if (error61 instanceof InstallationManagerError) {
27981
- throw error61;
27982
- }
27983
- throw new InstallationManagerError(
27984
- "agent_install_failed",
27985
- "The fixed Pi installation recipe failed",
27986
- { cause: error61 }
27987
- );
27988
- }
27989
- };
27990
- };
27991
- var DeepSeekHarnessInstallRecipe = class extends FixedAgentInstallRecipe {
27992
- #npmInstaller;
27993
- id = "deepseek-harness";
27994
- label = "DeepSeek Harness";
27995
- releaseChannel = DEEPSEEK_HARNESS_PACKAGE.version;
27996
- constructor(npmInstaller = new ManagedNpmPackageInstaller()) {
27997
- super();
27998
- this.#npmInstaller = npmInstaller;
27999
- }
28000
- install = async (options) => {
28001
- this.assertSupportedPlatform();
28002
- try {
28003
- const managedHome = join17(
28004
- options.stateDirectory,
28005
- "agents",
28006
- this.id,
28007
- "home"
28008
- );
28009
- await mkdir5(managedHome, { mode: 448, recursive: true });
28010
- await options.report("downloading");
28011
- await options.report("verifying");
28012
- await options.report("installing_agent");
28013
- const executable = await this.#npmInstaller.install(
28014
- join17(
28015
- options.stateDirectory,
28016
- "agents",
28017
- this.id,
28018
- DEEPSEEK_HARNESS_PACKAGE.version
28019
- ),
28020
- DEEPSEEK_HARNESS_PACKAGE,
28021
- options.environment,
28022
- options.signal
28023
- );
28024
- options.audit.record(
28025
- "agent_npm_package_verified",
28026
- options.requestId,
28027
- this.id,
28028
- {
28029
- integrity: DEEPSEEK_HARNESS_PACKAGE.integrity,
28030
- package: DEEPSEEK_HARNESS_PACKAGE.packageName,
28031
- version: DEEPSEEK_HARNESS_PACKAGE.version
28032
- }
28033
- );
28034
- return executable;
28035
- } catch (error61) {
28036
- if (options.signal.aborted) {
28037
- options.signal.throwIfAborted();
28038
- }
28039
- if (error61 instanceof ManagedNpmPackageError) {
28040
- if (error61.code === "managed_package_verification_failed") {
28041
- throw new InstallationManagerError(
28042
- "agent_verification_failed",
28043
- "The managed DeepSeek Harness package did not match its pinned artifact",
28044
- { cause: error61 }
27320
+ await this.#executor.execute(
27321
+ specification.id,
27322
+ job.requestId,
27323
+ async (stage) => {
27324
+ signal.throwIfAborted();
27325
+ await this.#transition(
27326
+ job,
27327
+ new RunningInstallation(job.requestId, job.agentId, stage)
28045
27328
  );
28046
- }
28047
- if (error61.code === "managed_package_publish_failed") {
28048
- throw new InstallationManagerError(
28049
- "agent_publish_failed",
28050
- "The managed DeepSeek Harness package could not be published",
28051
- { cause: error61 }
27329
+ this.#audit.record(
27330
+ `agent_installation_${stage}`,
27331
+ job.requestId,
27332
+ job.agentId
28052
27333
  );
28053
- }
28054
- throw new InstallationManagerError(error61.code, error61.message, {
28055
- cause: error61
28056
- });
28057
- }
28058
- if (error61 instanceof InstallationManagerError) {
28059
- throw error61;
28060
- }
28061
- throw new InstallationManagerError(
28062
- "agent_install_failed",
28063
- "The fixed DeepSeek Harness installation recipe failed",
28064
- { cause: error61 }
28065
- );
28066
- }
28067
- };
28068
- };
28069
- var OpenCodeInstallRecipe = class extends FixedAgentInstallRecipe {
28070
- #archiveInstaller;
28071
- id = "opencode";
28072
- label = "OpenCode";
28073
- releaseChannel = OPENCODE_MANAGED_VERSION;
28074
- constructor(archiveInstaller = new ManagedAgentArchiveInstaller()) {
28075
- super();
28076
- this.#archiveInstaller = archiveInstaller;
28077
- }
28078
- install = async (options) => {
28079
- this.assertSupportedPlatform();
28080
- const definition = openCodeManagedArchive(process.platform, process.arch);
28081
- try {
28082
- await options.report("downloading");
28083
- await options.report("verifying");
28084
- await options.report("installing_agent");
28085
- const executable = await this.#archiveInstaller.install(
28086
- join17(
28087
- options.stateDirectory,
28088
- "agents",
28089
- this.id,
28090
- OPENCODE_MANAGED_VERSION
28091
- ),
28092
- definition,
28093
- options.signal
27334
+ },
27335
+ signal
28094
27336
  );
28095
- options.audit.record(
28096
- "agent_archive_verified",
28097
- options.requestId,
28098
- this.id,
28099
- {
28100
- sha256: definition.archiveSha256,
28101
- version: definition.version
28102
- }
27337
+ signal.throwIfAborted();
27338
+ const succeeded = new SucceededInstallation(job.requestId, job.agentId);
27339
+ await this.#transition(job, succeeded);
27340
+ this.#audit.record(
27341
+ "agent_installation_completed",
27342
+ job.requestId,
27343
+ job.agentId
28103
27344
  );
28104
- return executable;
27345
+ job.completion.resolve(succeeded);
28105
27346
  } catch (error61) {
28106
- if (options.signal.aborted) {
28107
- options.signal.throwIfAborted();
28108
- }
28109
- if (error61 instanceof ManagedAgentArchiveError) {
28110
- if (error61.code === "managed_archive_verification_failed") {
28111
- throw new InstallationManagerError(
28112
- "agent_verification_failed",
28113
- "The managed OpenCode archive did not match its pinned artifact",
28114
- { cause: error61 }
27347
+ if (signal.aborted) {
27348
+ if (signal.reason instanceof InstallationManagerError && signal.reason.code === "installation_timeout") {
27349
+ const timedOut = new FailedInstallation(
27350
+ job.requestId,
27351
+ job.agentId,
27352
+ signal.reason.code,
27353
+ signal.reason.message
28115
27354
  );
28116
- }
28117
- if (error61.code === "managed_archive_publish_failed") {
28118
- throw new InstallationManagerError(
28119
- "agent_publish_failed",
28120
- "The managed OpenCode archive could not be published",
28121
- { cause: error61 }
27355
+ await this.#transition(job, timedOut);
27356
+ this.#audit.record(
27357
+ "agent_installation_failed_installation_timeout",
27358
+ job.requestId,
27359
+ job.agentId
28122
27360
  );
27361
+ job.completion.resolve(timedOut);
27362
+ return;
28123
27363
  }
28124
- throw new InstallationManagerError(error61.code, error61.message, {
28125
- cause: error61
28126
- });
27364
+ const cancelled = new CancelledInstallation(job.requestId, job.agentId);
27365
+ await this.#transition(job, cancelled);
27366
+ this.#audit.record(
27367
+ "agent_installation_cancelled",
27368
+ job.requestId,
27369
+ job.agentId
27370
+ );
27371
+ job.completion.resolve(cancelled);
27372
+ } else {
27373
+ const failure = executionFailure(error61);
27374
+ const failed = new FailedInstallation(
27375
+ job.requestId,
27376
+ job.agentId,
27377
+ failure.code,
27378
+ failure.message
27379
+ );
27380
+ await this.#transition(job, failed);
27381
+ this.#audit.record(
27382
+ `agent_installation_failed_${failure.code}`,
27383
+ job.requestId,
27384
+ job.agentId
27385
+ );
27386
+ job.completion.resolve(failed);
28127
27387
  }
28128
- if (error61 instanceof InstallationManagerError) {
28129
- throw error61;
27388
+ } finally {
27389
+ clearTimeout(deadline);
27390
+ externalSignal.removeEventListener("abort", abort);
27391
+ if (this.#activeAgents.get(job.agentId) === job.requestId) {
27392
+ this.#activeAgents.delete(job.agentId);
28130
27393
  }
28131
- throw new InstallationManagerError(
28132
- "agent_install_failed",
28133
- "The fixed OpenCode installation recipe failed",
28134
- { cause: error61 }
28135
- );
28136
27394
  }
28137
27395
  };
28138
27396
  };
28139
- function fixedAgentInstallRecipes() {
28140
- return Object.freeze([
28141
- new CodexInstallRecipe(),
28142
- new ClaudeCodeInstallRecipe(),
28143
- new PiInstallRecipe(),
28144
- new DeepSeekHarnessInstallRecipe(),
28145
- new OpenCodeInstallRecipe(),
28146
- new GrokBuildInstallRecipe(),
28147
- new WorkBuddyInstallRecipe()
28148
- ]);
28149
- }
28150
27397
 
28151
27398
  // src/agent-installation/fixed-installation-executor.ts
27399
+ import { realpathSync as realpathSync2, statSync as statSync2 } from "node:fs";
27400
+ import { resolve as resolve4 } from "node:path";
28152
27401
  function findSpecification(specifications, agentId) {
28153
27402
  for (const specification of specifications) {
28154
27403
  if (specification.id === agentId) {
@@ -28160,17 +27409,6 @@ function findSpecification(specifications, agentId) {
28160
27409
  "The requested Agent is not supported"
28161
27410
  );
28162
27411
  }
28163
- function findRecipe(recipes, agentId) {
28164
- for (const recipe of recipes) {
28165
- if (recipe.id === agentId) {
28166
- return recipe;
28167
- }
28168
- }
28169
- throw new InstallationManagerError(
28170
- "agent_not_installable",
28171
- "The requested Agent does not have an approved installation recipe"
28172
- );
28173
- }
28174
27412
  function resolveDefaultWorkspace2(path2) {
28175
27413
  try {
28176
27414
  const directory = realpathSync2(resolve4(path2));
@@ -28186,7 +27424,7 @@ function resolveDefaultWorkspace2(path2) {
28186
27424
  );
28187
27425
  }
28188
27426
  }
28189
- function resolveUserInstallationDirectory(path2) {
27427
+ function resolveIntegrationStateDirectory(path2) {
28190
27428
  try {
28191
27429
  const directory = realpathSync2(resolve4(path2));
28192
27430
  const metadata = statSync2(directory);
@@ -28197,7 +27435,7 @@ function resolveUserInstallationDirectory(path2) {
28197
27435
  } catch (error61) {
28198
27436
  throw new InstallationManagerError(
28199
27437
  "unsafe_installation_root",
28200
- "The local Agent installation root is unavailable or unsafe",
27438
+ "The local integration state directory is unavailable or unsafe",
28201
27439
  { cause: error61 }
28202
27440
  );
28203
27441
  }
@@ -28206,20 +27444,17 @@ function translateExecutionError(error61) {
28206
27444
  if (error61 instanceof InstallationManagerError) {
28207
27445
  return error61;
28208
27446
  }
28209
- if (error61 instanceof ManagedAdapterInstallError || error61 instanceof InstallerDownloadError || error61 instanceof ProcessExecutionError) {
27447
+ if (error61 instanceof ManagedAdapterInstallError) {
28210
27448
  return new InstallationManagerError(error61.code, error61.message, {
28211
27449
  cause: error61
28212
27450
  });
28213
27451
  }
28214
27452
  return new InstallationManagerError(
28215
27453
  "installation_failed",
28216
- "The fixed local Agent installation failed",
27454
+ "The local Agent integration installation failed",
28217
27455
  { cause: error61 }
28218
27456
  );
28219
27457
  }
28220
- function requiresAgentReplacement(code) {
28221
- return code === "agent_not_found" || code === "agent_probe_failed" || code === "agent_probe_timeout";
28222
- }
28223
27458
  function requiresAdapterReplacement(code) {
28224
27459
  return code === "adapter_not_found" || code === "adapter_probe_failed" || code === "adapter_probe_timeout" || code === "acp_incompatible";
28225
27460
  }
@@ -28230,12 +27465,10 @@ var FixedInstallationExecutor = class {
28230
27465
  #catalog;
28231
27466
  #environment;
28232
27467
  #publishCatalog;
28233
- #recipes;
28234
27468
  #specifications;
28235
- #stateDirectory;
28236
- constructor(options, specifications = supportedLocalAgentSpecifications(), recipes = fixedAgentInstallRecipes(), adapterInstaller) {
27469
+ constructor(options, specifications = supportedLocalAgentSpecifications(), adapterInstaller) {
28237
27470
  const defaultWorkspace = resolveDefaultWorkspace2(options.defaultWorkspace);
28238
- const stateDirectory = resolveUserInstallationDirectory(
27471
+ const stateDirectory = resolveIntegrationStateDirectory(
28239
27472
  options.stateDirectory
28240
27473
  );
28241
27474
  this.#defaultWorkspace = defaultWorkspace;
@@ -28243,9 +27476,7 @@ var FixedInstallationExecutor = class {
28243
27476
  this.#catalog = options.catalog;
28244
27477
  this.#environment = Object.freeze({ ...options.environment });
28245
27478
  this.#publishCatalog = options.publishCatalog;
28246
- this.#recipes = Object.freeze([...recipes]);
28247
27479
  this.#specifications = Object.freeze([...specifications]);
28248
- this.#stateDirectory = stateDirectory;
28249
27480
  this.#adapterInstaller = adapterInstaller ?? new ManagedAdapterInstaller({
28250
27481
  environment: this.#environment,
28251
27482
  stateDirectory
@@ -28254,35 +27485,59 @@ var FixedInstallationExecutor = class {
28254
27485
  execute = async (agentId, requestId, report, signal) => {
28255
27486
  try {
28256
27487
  const specification = findSpecification(this.#specifications, agentId);
28257
- const recipe = findRecipe(this.#recipes, agentId);
28258
- this.#audit.record(
28259
- "agent_installation_recipe_resolved",
28260
- requestId,
28261
- agentId,
28262
- {
28263
- adapterVersion: specification.adapterVersion,
28264
- releaseChannel: recipe.releaseChannel
28265
- }
28266
- );
28267
- const discoveryOptions2 = {
27488
+ const discoveryOptions = {
28268
27489
  defaultWorkspace: this.#defaultWorkspace,
28269
27490
  environment: this.#environment,
28270
27491
  signal
28271
27492
  };
28272
- let agent = await resolveAgentExecutable(specification, discoveryOptions2);
28273
- let installedAgent = false;
28274
- if (agent === null) {
28275
- agent = await recipe.install({
28276
- audit: this.#audit,
28277
- environment: this.#environment,
28278
- report,
28279
- requestId,
28280
- signal,
28281
- stateDirectory: this.#stateDirectory
28282
- });
28283
- installedAgent = true;
27493
+ const initialInventory = await discoverLocalAgentInventory({
27494
+ ...discoveryOptions,
27495
+ specifications: this.#specifications
27496
+ });
27497
+ const previous = this.#catalog.read();
27498
+ this.#catalog.transition(
27499
+ initialInventory.readyAgents(),
27500
+ initialInventory.installable
27501
+ );
27502
+ try {
27503
+ await this.#publishCatalog(signal);
27504
+ } catch (error61) {
27505
+ this.#catalog.transition(previous.agents, previous.installableAgents);
27506
+ throw error61;
27507
+ }
27508
+ const alreadyReady = initialInventory.available.find(
27509
+ (candidate2) => candidate2.specification.id === agentId
27510
+ );
27511
+ if (alreadyReady instanceof AvailableAgent) {
27512
+ return;
27513
+ }
27514
+ const candidate = initialInventory.installable.find(
27515
+ (agent2) => agent2.id === agentId
27516
+ );
27517
+ if (candidate instanceof MissingAgentDefinition) {
27518
+ throw new InstallationManagerError(
27519
+ "agent_not_installed",
27520
+ `Install ${specification.label} on this machine, then try installing the integration again.`
27521
+ );
27522
+ }
27523
+ if (!(candidate instanceof AgentIntegrationDefinition)) {
27524
+ throw new InstallationManagerError(
27525
+ "agent_verification_failed",
27526
+ "The local Agent discovery result is unavailable"
27527
+ );
27528
+ }
27529
+ const verifiedAgent = await findVerifiedAgentExecutable(
27530
+ specification,
27531
+ discoveryOptions
27532
+ );
27533
+ if (verifiedAgent === null) {
27534
+ throw new InstallationManagerError(
27535
+ "agent_not_installed",
27536
+ `Install ${specification.label} on this machine, then try installing the integration again.`
27537
+ );
28284
27538
  }
28285
- let adapter = specification instanceof DirectAcpAgentDefinition ? agent : await resolveAdapterExecutable(specification, discoveryOptions2);
27539
+ const agent = verifiedAgent.executable;
27540
+ let adapter = specification instanceof DirectAcpAgentDefinition ? agent : await resolveAdapterExecutable(specification, discoveryOptions);
28286
27541
  let installedAdapter = false;
28287
27542
  if (adapter === null) {
28288
27543
  if (!(specification instanceof BridgedAcpAgentDefinition)) {
@@ -28291,6 +27546,12 @@ var FixedInstallationExecutor = class {
28291
27546
  "The direct Agent executable is unavailable"
28292
27547
  );
28293
27548
  }
27549
+ if (this.#environment[specification.adapterOverrideVariable] !== void 0) {
27550
+ throw new InstallationManagerError(
27551
+ "adapter_not_found",
27552
+ "The configured ACP adapter is unavailable"
27553
+ );
27554
+ }
28294
27555
  await report("installing_adapter");
28295
27556
  adapter = await this.#adapterInstaller.install(specification, signal);
28296
27557
  installedAdapter = true;
@@ -28301,8 +27562,8 @@ var FixedInstallationExecutor = class {
28301
27562
  while (true) {
28302
27563
  await report("checking_acp");
28303
27564
  const environment = { ...this.#environment };
28304
- environment[specification.agentOverrideVariable] = agent.path;
28305
- environment[specification.adapterOverrideVariable] = adapter.path;
27565
+ environment[specification.agentOverrideVariable] = agent.identity.requestedPath;
27566
+ environment[specification.adapterOverrideVariable] = adapter.identity.requestedPath;
28306
27567
  const inventory = await discoverLocalAgentInventory({
28307
27568
  defaultWorkspace: this.#defaultWorkspace,
28308
27569
  environment,
@@ -28310,7 +27571,7 @@ var FixedInstallationExecutor = class {
28310
27571
  specifications: this.#specifications
28311
27572
  });
28312
27573
  const verified = inventory.available.find(
28313
- (candidate) => candidate.specification.id === agentId
27574
+ (candidate2) => candidate2.specification.id === agentId
28314
27575
  );
28315
27576
  if (verified instanceof AvailableAgent) {
28316
27577
  this.#audit.record(
@@ -28322,7 +27583,7 @@ var FixedInstallationExecutor = class {
28322
27583
  agentVersion: verified.agent.agentVersion
28323
27584
  }
28324
27585
  );
28325
- const previous = this.#catalog.read();
27586
+ const previousCatalog = this.#catalog.read();
28326
27587
  this.#catalog.transition(
28327
27588
  inventory.readyAgents(),
28328
27589
  inventory.installable
@@ -28331,15 +27592,15 @@ var FixedInstallationExecutor = class {
28331
27592
  await this.#publishCatalog(signal);
28332
27593
  } catch (error61) {
28333
27594
  this.#catalog.transition(
28334
- previous.agents,
28335
- previous.installableAgents
27595
+ previousCatalog.agents,
27596
+ previousCatalog.installableAgents
28336
27597
  );
28337
27598
  throw error61;
28338
27599
  }
28339
27600
  return;
28340
27601
  }
28341
27602
  const unavailable = inventory.unavailable.find(
28342
- (candidate) => candidate.specification.id === agentId
27603
+ (candidate2) => candidate2.specification.id === agentId
28343
27604
  );
28344
27605
  if (unavailable === void 0) {
28345
27606
  throw new InstallationManagerError(
@@ -28347,7 +27608,7 @@ var FixedInstallationExecutor = class {
28347
27608
  "The complete Agent ACP path did not pass verification"
28348
27609
  );
28349
27610
  }
28350
- if (!installedAdapter && specification instanceof BridgedAcpAgentDefinition && requiresAdapterReplacement(unavailable.code)) {
27611
+ if (!installedAdapter && specification instanceof BridgedAcpAgentDefinition && this.#environment[specification.adapterOverrideVariable] === void 0 && requiresAdapterReplacement(unavailable.code)) {
28351
27612
  await report("installing_adapter");
28352
27613
  adapter = await this.#adapterInstaller.install(specification, signal);
28353
27614
  installedAdapter = true;
@@ -28356,21 +27617,6 @@ var FixedInstallationExecutor = class {
28356
27617
  });
28357
27618
  continue;
28358
27619
  }
28359
- if (!installedAgent && (requiresAgentReplacement(unavailable.code) || unavailable.code === "acp_incompatible")) {
28360
- agent = await recipe.install({
28361
- audit: this.#audit,
28362
- environment: this.#environment,
28363
- report,
28364
- requestId,
28365
- signal,
28366
- stateDirectory: this.#stateDirectory
28367
- });
28368
- installedAgent = true;
28369
- if (specification instanceof DirectAcpAgentDefinition) {
28370
- adapter = agent;
28371
- }
28372
- continue;
28373
- }
28374
27620
  throw new InstallationManagerError(
28375
27621
  unavailable.code,
28376
27622
  unavailable.message
@@ -28386,15 +27632,15 @@ var FixedInstallationExecutor = class {
28386
27632
  };
28387
27633
 
28388
27634
  // src/authorization/workspace-directory.ts
28389
- import { readdir, realpath as realpath8, stat as stat7 } from "node:fs/promises";
27635
+ import { readdir, realpath as realpath7, stat as stat6 } from "node:fs/promises";
28390
27636
  import { homedir as homedir2 } from "node:os";
28391
27637
  import {
28392
27638
  basename as basename2,
28393
- dirname as dirname6,
28394
- isAbsolute as isAbsolute8,
28395
- join as join18,
27639
+ dirname as dirname5,
27640
+ isAbsolute as isAbsolute7,
27641
+ join as join15,
28396
27642
  normalize as normalize2,
28397
- relative as relative5
27643
+ relative as relative4
28398
27644
  } from "node:path";
28399
27645
  var WorkspaceDirectoryListing = class {
28400
27646
  directoryId;
@@ -28444,20 +27690,20 @@ var WorkspaceDirectoryService = class {
28444
27690
  if (id === "home") return homedir2();
28445
27691
  if (id.startsWith("path-")) {
28446
27692
  const path2 = decodePath(id, "path-");
28447
- if (isAbsolute8(path2)) return path2;
27693
+ if (isAbsolute7(path2)) return path2;
28448
27694
  }
28449
27695
  throw new LocalAuthorizationError("The directory identifier is invalid");
28450
27696
  };
28451
27697
  resolvePath = async (requested, signal) => {
28452
27698
  signal.throwIfAborted();
28453
- if (!isAbsolute8(requested) || requested.includes("\0") || normalize2(requested) !== requested)
27699
+ if (!isAbsolute7(requested) || requested.includes("\0") || normalize2(requested) !== requested)
28454
27700
  throw new LocalAuthorizationError("The local directory path is invalid");
28455
27701
  try {
28456
- const target = await realpath8(requested);
27702
+ const target = await realpath7(requested);
28457
27703
  signal.throwIfAborted();
28458
- const metadata = await stat7(target);
27704
+ const metadata = await stat6(target);
28459
27705
  signal.throwIfAborted();
28460
- if (!isAbsolute8(target) || normalize2(target) !== target || !metadata.isDirectory())
27706
+ if (!isAbsolute7(target) || normalize2(target) !== target || !metadata.isDirectory())
28461
27707
  throw new LocalAuthorizationError(
28462
27708
  "The selected location is not a directory"
28463
27709
  );
@@ -28472,8 +27718,8 @@ var WorkspaceDirectoryService = class {
28472
27718
  }
28473
27719
  };
28474
27720
  label = (path2) => {
28475
- const suffix = relative5(homedir2(), path2);
28476
- return suffix === "" ? "~" : !isAbsolute8(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
27721
+ const suffix = relative4(homedir2(), path2);
27722
+ return suffix === "" ? "~" : !isAbsolute7(suffix) && suffix !== ".." && !suffix.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) ? `~/${suffix.replaceAll("\\", "/")}` : path2;
28477
27723
  };
28478
27724
  identify = async (bindingId, requestedPath, signal) => {
28479
27725
  this.authorizeMachine(bindingId);
@@ -28501,7 +27747,7 @@ var WorkspaceDirectoryService = class {
28501
27747
  continue;
28502
27748
  }
28503
27749
  try {
28504
- const path2 = await this.resolvePath(join18(target, child.name), signal);
27750
+ const path2 = await this.resolvePath(join15(target, child.name), signal);
28505
27751
  entries.push({ directoryId: encodePath(path2), name: child.name });
28506
27752
  } catch (cause) {
28507
27753
  signal.throwIfAborted();
@@ -28509,7 +27755,7 @@ var WorkspaceDirectoryService = class {
28509
27755
  }
28510
27756
  }
28511
27757
  entries.sort((a, b) => a.name.localeCompare(b.name));
28512
- const parent = dirname6(target);
27758
+ const parent = dirname5(target);
28513
27759
  return new WorkspaceDirectoryListing(
28514
27760
  id,
28515
27761
  this.label(target),
@@ -28533,7 +27779,7 @@ var WorkspaceDirectoryService = class {
28533
27779
  };
28534
27780
 
28535
27781
  // src/native-sessions/service.ts
28536
- import { randomUUID as randomUUID3 } from "node:crypto";
27782
+ import { randomUUID as randomUUID2 } from "node:crypto";
28537
27783
 
28538
27784
  // src/native-sessions/codex-history.ts
28539
27785
  import { spawn as spawn4 } from "node:child_process";
@@ -28847,7 +28093,7 @@ var NativeSessionService = class {
28847
28093
  for (const info of page.sessions) {
28848
28094
  const authorized = await this.authorizeEntry(command, options, info);
28849
28095
  if (authorized === null) continue;
28850
- const entryId = randomUUID3();
28096
+ const entryId = randomUUID2();
28851
28097
  if (this.#entries.size >= 5e3) this.#entries.clear();
28852
28098
  this.#entries.set(entryId, {
28853
28099
  scope: entryScope,
@@ -28872,7 +28118,7 @@ var NativeSessionService = class {
28872
28118
  {},
28873
28119
  "invalid_native_session_response"
28874
28120
  );
28875
- nextCursor = randomUUID3();
28121
+ nextCursor = randomUUID2();
28876
28122
  if (this.#cursors.size >= 500) this.#cursors.clear();
28877
28123
  this.#cursors.set(nextCursor, {
28878
28124
  scope: cursorScope,
@@ -29192,7 +28438,7 @@ function connectRelay(url2, signal) {
29192
28438
  }
29193
28439
 
29194
28440
  // src/relay-connection/liveness.ts
29195
- import { randomUUID as randomUUID4 } from "node:crypto";
28441
+ import { randomUUID as randomUUID3 } from "node:crypto";
29196
28442
  var HEARTBEAT_ACK_TIMEOUT_MILLISECONDS = 1e4;
29197
28443
  var HEARTBEAT_INTERVAL_MILLISECONDS = 2e4;
29198
28444
  var RelayLivenessState = class {
@@ -29283,7 +28529,7 @@ var RelayConnectionLiveness = class {
29283
28529
  }
29284
28530
  throw new Error("Heartbeat was scheduled in an invalid state");
29285
28531
  }
29286
- const heartbeatId = randomUUID4();
28532
+ const heartbeatId = randomUUID3();
29287
28533
  this.#state = new AwaitingHeartbeatAckState(
29288
28534
  heartbeatId,
29289
28535
  this.#timer.schedule(
@@ -29302,7 +28548,7 @@ var RelayConnectionLiveness = class {
29302
28548
 
29303
28549
  // src/relay-connection/session-event-outbox.ts
29304
28550
  import { mkdirSync as mkdirSync3 } from "node:fs";
29305
- import { dirname as dirname7 } from "node:path";
28551
+ import { dirname as dirname6 } from "node:path";
29306
28552
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
29307
28553
  function readPendingEnvelope(row) {
29308
28554
  if (typeof row !== "object" || row === null || Array.isArray(row)) {
@@ -29317,7 +28563,7 @@ function readPendingEnvelope(row) {
29317
28563
  var SessionEventOutbox = class {
29318
28564
  #database;
29319
28565
  constructor(path2) {
29320
- mkdirSync3(dirname7(path2), { recursive: true });
28566
+ mkdirSync3(dirname6(path2), { recursive: true });
29321
28567
  this.#database = new DatabaseSync3(path2);
29322
28568
  this.#database.exec(`
29323
28569
  CREATE TABLE IF NOT EXISTS relay_session_event_outbox (
@@ -29471,6 +28717,7 @@ var systemDaemonTimer = new SystemDaemonTimer();
29471
28717
  // src/run-daemon.ts
29472
28718
  var RELAY_RECONNECT_DELAY_MILLISECONDS = 500;
29473
28719
  var RELAY_CONNECTION_REFRESH_MILLISECONDS = 20 * 60 * 1e3;
28720
+ var ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS = 2e4;
29474
28721
  var RelayConnectionRefreshState = class {
29475
28722
  };
29476
28723
  var ScheduledRelayConnectionRefreshState = class extends RelayConnectionRefreshState {
@@ -29668,7 +28915,7 @@ var DaemonInstallationObserver = class {
29668
28915
  );
29669
28916
  return Promise.resolve();
29670
28917
  }
29671
- throw new Error("Unsupported Agent installation state");
28918
+ throw new Error("Unsupported Agent integration installation state");
29672
28919
  };
29673
28920
  };
29674
28921
  var ResolvedSessionDirectories = class {
@@ -29682,16 +28929,20 @@ var ResolvedSessionDirectories = class {
29682
28929
  }
29683
28930
  };
29684
28931
  var ActiveDaemonTurn = class {
28932
+ attemptId;
29685
28933
  command;
29686
- #connectionController;
28934
+ #controller;
28935
+ #finished = Promise.withResolvers();
29687
28936
  #cancellationRequested = false;
29688
- constructor(command, connectionController) {
28937
+ constructor(command, attemptId) {
28938
+ this.attemptId = attemptId;
29689
28939
  this.command = command;
29690
- this.#connectionController = connectionController;
28940
+ this.#controller = new AbortController();
29691
28941
  }
29692
- abortConnection = () => {
29693
- this.#connectionController.abort();
28942
+ abortDaemon = () => {
28943
+ this.#controller.abort();
29694
28944
  };
28945
+ finish = () => this.#finished.resolve();
29695
28946
  matches = (cancellation) => cancellation.commandId === this.command.commandId && cancellation.sessionId === this.command.sessionId;
29696
28947
  requestCancellation = () => {
29697
28948
  if (this.#cancellationRequested) {
@@ -29701,25 +28952,118 @@ var ActiveDaemonTurn = class {
29701
28952
  return true;
29702
28953
  };
29703
28954
  get signal() {
29704
- return this.#connectionController.signal;
28955
+ return this.#controller.signal;
28956
+ }
28957
+ get completion() {
28958
+ return this.#finished.promise;
28959
+ }
28960
+ };
28961
+ var ActiveTurnReconciliationError = class extends Error {
28962
+ code = "active_turn_reconciliation_failed";
28963
+ constructor(message, options = {}) {
28964
+ super(message, options);
28965
+ this.name = "ActiveTurnReconciliationError";
29705
28966
  }
29706
28967
  };
28968
+ function activeTurnReconciliationEndpoint(config2, turn) {
28969
+ const endpoint = new URL(config2.relayUrl);
28970
+ endpoint.protocol = endpoint.protocol === "wss:" ? "https:" : "http:";
28971
+ if (!endpoint.pathname.endsWith("/daemon")) {
28972
+ throw new ActiveTurnReconciliationError("The Relay URL is invalid");
28973
+ }
28974
+ endpoint.pathname = `${endpoint.pathname.slice(0, -"/daemon".length)}/sessions/${encodeURIComponent(turn.command.sessionId)}/attempts/${encodeURIComponent(turn.attemptId)}/reconciliation`;
28975
+ endpoint.searchParams.delete("liveness");
28976
+ return endpoint;
28977
+ }
28978
+ async function reconcileActiveTurn(config2, turn, signal) {
28979
+ signal.throwIfAborted();
28980
+ const timeoutSignal = AbortSignal.timeout(
28981
+ ACTIVE_TURN_RECONCILIATION_TIMEOUT_MILLISECONDS
28982
+ );
28983
+ const requestSignal = AbortSignal.any([signal, timeoutSignal]);
28984
+ let response;
28985
+ try {
28986
+ response = await fetch4(activeTurnReconciliationEndpoint(config2, turn), {
28987
+ body: JSON.stringify({ outcome: { kind: "running" } }),
28988
+ dispatcher: environmentProxyDispatcher,
28989
+ headers: { "content-type": "application/json" },
28990
+ method: "POST",
28991
+ signal: requestSignal
28992
+ });
28993
+ } catch (error61) {
28994
+ if (signal.aborted) {
28995
+ signal.throwIfAborted();
28996
+ }
28997
+ throw new ActiveTurnReconciliationError(
28998
+ timeoutSignal.aborted ? "The active Agent turn reconciliation timed out" : "The active Agent turn could not be reconciled",
28999
+ { cause: error61 }
29000
+ );
29001
+ }
29002
+ await response.body?.cancel();
29003
+ if (!response.ok) {
29004
+ throw new ActiveTurnReconciliationError(
29005
+ "The Relay rejected the active Agent turn reconciliation"
29006
+ );
29007
+ }
29008
+ }
29009
+ async function reconcileActiveTurns(config2, turns, signal) {
29010
+ await Promise.all(
29011
+ turns.map(async (turn) => await reconcileActiveTurn(config2, turn, signal))
29012
+ );
29013
+ }
29707
29014
  function send(socket, message) {
29708
29015
  if (socket.readyState !== WebSocket2.OPEN) {
29709
29016
  throw new Error("Relay connection is not open");
29710
29017
  }
29711
29018
  socket.send(message);
29712
29019
  }
29713
- function recordSessionEvent(outbox, socket, sessionId, payload, attemptId = null) {
29714
- const envelope2 = outbox.enqueue(sessionId, payload, attemptId);
29715
- if (socket.readyState === WebSocket2.OPEN) {
29716
- socket.send(envelope2);
29020
+ var DaemonSessionEventConnectionState = class {
29021
+ };
29022
+ var DisconnectedDaemonSessionEventState = class extends DaemonSessionEventConnectionState {
29023
+ disconnect = () => this;
29024
+ send = () => void 0;
29025
+ };
29026
+ var ConnectedDaemonSessionEventState = class extends DaemonSessionEventConnectionState {
29027
+ #socket;
29028
+ constructor(socket) {
29029
+ super();
29030
+ this.#socket = socket;
29717
29031
  }
29718
- }
29719
- function reportFailure(outbox, socket, command, code, message, attemptId = null) {
29720
- recordSessionEvent(
29721
- outbox,
29722
- socket,
29032
+ disconnect = (socket) => socket === this.#socket ? new DisconnectedDaemonSessionEventState() : this;
29033
+ send = (message) => {
29034
+ if (this.#socket.readyState === WebSocket2.OPEN) {
29035
+ try {
29036
+ this.#socket.send(message);
29037
+ } catch {
29038
+ }
29039
+ }
29040
+ };
29041
+ };
29042
+ var DaemonSessionEventPublisher = class {
29043
+ #outbox;
29044
+ #connection = new DisconnectedDaemonSessionEventState();
29045
+ constructor(outbox) {
29046
+ this.#outbox = outbox;
29047
+ }
29048
+ connect = (socket) => {
29049
+ const connection = new ConnectedDaemonSessionEventState(socket);
29050
+ this.#connection = connection;
29051
+ for (const pending of this.#outbox.pending()) {
29052
+ connection.send(pending);
29053
+ }
29054
+ };
29055
+ disconnect = (socket) => {
29056
+ this.#connection = this.#connection.disconnect(socket);
29057
+ };
29058
+ recordAttempt = (sessionId, payload, attemptId) => {
29059
+ this.#connection.send(this.#outbox.enqueue(sessionId, payload, attemptId));
29060
+ };
29061
+ recordRuntime = (sessionId, payload) => {
29062
+ this.#connection.send(this.#outbox.enqueue(sessionId, payload));
29063
+ };
29064
+ };
29065
+ function reportFailure(publisher, command, code, message, attemptId) {
29066
+ publisher.recordAttempt(
29723
29067
  command.sessionId,
29724
29068
  encodeSessionFailedEvent({
29725
29069
  code,
@@ -29815,7 +29159,7 @@ async function executeWorkspaceList(socket, command, directories, audit, signal)
29815
29159
  reportOperationFailure(socket, command.requestId, "", error61);
29816
29160
  }
29817
29161
  }
29818
- async function executeSessionPrepare(outbox, socket, command, config2, directories, audit, sessions, signal) {
29162
+ async function executeSessionPrepare(publisher, socket, command, config2, directories, audit, sessions, signal) {
29819
29163
  try {
29820
29164
  const resolved = await resolveSessionDirectories(
29821
29165
  directories,
@@ -29842,9 +29186,7 @@ async function executeSessionPrepare(outbox, socket, command, config2, directori
29842
29186
  event: "session_prepared",
29843
29187
  sessionId: command.sessionId
29844
29188
  });
29845
- recordSessionEvent(
29846
- outbox,
29847
- socket,
29189
+ publisher.recordRuntime(
29848
29190
  command.sessionId,
29849
29191
  encodeSessionReadyEvent({
29850
29192
  additionalDirectories: resolved.additionalDirectoryEntries,
@@ -29875,7 +29217,7 @@ async function executeSessionPrepare(outbox, socket, command, config2, directori
29875
29217
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
29876
29218
  }
29877
29219
  }
29878
- async function executeSessionConfigure(outbox, socket, command, config2, directories, audit, sessions, signal) {
29220
+ async function executeSessionConfigure(publisher, socket, command, config2, directories, audit, sessions, signal) {
29879
29221
  try {
29880
29222
  const resolved = await resolveSessionDirectories(
29881
29223
  directories,
@@ -29901,9 +29243,7 @@ async function executeSessionConfigure(outbox, socket, command, config2, directo
29901
29243
  event: "session_configured",
29902
29244
  sessionId: command.sessionId
29903
29245
  });
29904
- recordSessionEvent(
29905
- outbox,
29906
- socket,
29246
+ publisher.recordRuntime(
29907
29247
  command.sessionId,
29908
29248
  encodeSessionConfigUpdatedEvent({
29909
29249
  configOptions,
@@ -29916,7 +29256,7 @@ async function executeSessionConfigure(outbox, socket, command, config2, directo
29916
29256
  reportOperationFailure(socket, command.requestId, command.sessionId, error61);
29917
29257
  }
29918
29258
  }
29919
- async function executePrompt(outbox, socket, command, config2, directories, audit, sessions, attemptId, signal) {
29259
+ async function executePrompt(outbox, publisher, command, config2, directories, audit, sessions, attemptId, signal) {
29920
29260
  try {
29921
29261
  const resolved = await resolveSessionDirectories(
29922
29262
  directories,
@@ -29932,9 +29272,7 @@ async function executePrompt(outbox, socket, command, config2, directories, audi
29932
29272
  sessionId: command.sessionId
29933
29273
  });
29934
29274
  outbox.transitionExecution(command.commandId, "running");
29935
- recordSessionEvent(
29936
- outbox,
29937
- socket,
29275
+ publisher.recordAttempt(
29938
29276
  command.sessionId,
29939
29277
  encodeSessionStartedEvent({
29940
29278
  commandId: command.commandId,
@@ -29951,9 +29289,7 @@ async function executePrompt(outbox, socket, command, config2, directories, audi
29951
29289
  cwd: resolved.cwd,
29952
29290
  images: command.images,
29953
29291
  onActivity: (activity) => {
29954
- recordSessionEvent(
29955
- outbox,
29956
- socket,
29292
+ publisher.recordAttempt(
29957
29293
  command.sessionId,
29958
29294
  encodeAgentActivityEvent({
29959
29295
  activityId: activity.activityId,
@@ -29977,9 +29313,7 @@ async function executePrompt(outbox, socket, command, config2, directories, audi
29977
29313
  return Promise.resolve();
29978
29314
  },
29979
29315
  onText: (text) => {
29980
- recordSessionEvent(
29981
- outbox,
29982
- socket,
29316
+ publisher.recordAttempt(
29983
29317
  command.sessionId,
29984
29318
  encodeAgentMessageDeltaEvent({
29985
29319
  commandId: command.commandId,
@@ -29996,9 +29330,7 @@ async function executePrompt(outbox, socket, command, config2, directories, audi
29996
29330
  sessionId: command.sessionId,
29997
29331
  signal
29998
29332
  });
29999
- recordSessionEvent(
30000
- outbox,
30001
- socket,
29333
+ publisher.recordAttempt(
30002
29334
  command.sessionId,
30003
29335
  encodeSessionCompletedEvent({
30004
29336
  commandId: command.commandId,
@@ -30025,8 +29357,7 @@ async function executePrompt(outbox, socket, command, config2, directories, audi
30025
29357
  });
30026
29358
  const code = operationErrorCode(error61);
30027
29359
  reportFailure(
30028
- outbox,
30029
- socket,
29360
+ publisher,
30030
29361
  command,
30031
29362
  code === "session_operation_failed" ? "agent_execution_failed" : code,
30032
29363
  code === "session_operation_failed" ? "The local agent could not complete the request" : operationErrorMessage(error61),
@@ -30072,29 +29403,15 @@ async function publishAgentCatalogUntilAvailable(config2, signal, timer) {
30072
29403
  }
30073
29404
  }
30074
29405
  }
30075
- async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, onConnected, signal, timer) {
29406
+ async function runRelayConnection(config2, directories, audit, sessions, installations, installationObserver, nativeSessions, outbox, publisher, activeTurns, activeAttemptIds, onConnected, signal, timer) {
30076
29407
  const relayUrl = new URL(config2.relayUrl);
30077
29408
  relayUrl.searchParams.set("liveness", "1");
30078
29409
  const socket = await connectRelay(relayUrl, signal);
29410
+ const reconnectingTurns = [...activeTurns.values()];
30079
29411
  onConnected();
30080
- const activeTurns = /* @__PURE__ */ new Map();
30081
- const activeAttemptIds = /* @__PURE__ */ new Map();
30082
29412
  const connectionController = new AbortController();
30083
29413
  const nativeRequests = /* @__PURE__ */ new Map();
30084
- const record2 = (sessionId, payload) => {
30085
- recordSessionEvent(
30086
- outbox,
30087
- socket,
30088
- sessionId,
30089
- payload,
30090
- activeAttemptIds.get(sessionId) ?? null
30091
- );
30092
- };
30093
- sessions.setObserver(new DaemonAcpObserver(record2));
30094
29414
  installationObserver.connect(socket);
30095
- for (const pending of outbox.pending()) {
30096
- send(socket, pending);
30097
- }
30098
29415
  try {
30099
29416
  await new Promise((resolve5, reject) => {
30100
29417
  let finished = false;
@@ -30106,11 +29423,8 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30106
29423
  socket.removeEventListener("error", handleError);
30107
29424
  socket.removeEventListener("message", handleMessage);
30108
29425
  installationObserver.disconnect(socket);
29426
+ publisher.disconnect(socket);
30109
29427
  connectionController.abort();
30110
- for (const turn of activeTurns.values()) {
30111
- turn.abortConnection();
30112
- }
30113
- activeTurns.clear();
30114
29428
  };
30115
29429
  const resolveConnection = () => {
30116
29430
  if (finished) {
@@ -30329,7 +29643,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30329
29643
  if (kind === SESSION_PREPARE_KIND) {
30330
29644
  const command2 = decodeSessionPrepareCommand(encoded);
30331
29645
  void executeSessionPrepare(
30332
- outbox,
29646
+ publisher,
30333
29647
  socket,
30334
29648
  command2,
30335
29649
  config2,
@@ -30343,7 +29657,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30343
29657
  if (kind === SESSION_CONFIGURE_KIND) {
30344
29658
  const command2 = decodeSessionConfigureCommand(encoded);
30345
29659
  void executeSessionConfigure(
30346
- outbox,
29660
+ publisher,
30347
29661
  socket,
30348
29662
  command2,
30349
29663
  config2,
@@ -30393,7 +29707,10 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30393
29707
  if (kind === AGENT_INSTALL_REQUEST_KIND) {
30394
29708
  const command2 = decodeAgentInstallRequestCommand(encoded);
30395
29709
  void installations.request(command2, signal).catch((error61) => {
30396
- console.error("Mobius Agent installation failed", error61);
29710
+ console.error(
29711
+ "Mobius Agent integration installation failed",
29712
+ error61
29713
+ );
30397
29714
  });
30398
29715
  return;
30399
29716
  }
@@ -30419,12 +29736,12 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30419
29736
  if (receipt.kind === "duplicate") {
30420
29737
  return;
30421
29738
  }
30422
- const turn = new ActiveDaemonTurn(command, new AbortController());
29739
+ const turn = new ActiveDaemonTurn(command, receipt.attemptId);
30423
29740
  activeTurns.set(command.commandId, turn);
30424
29741
  activeAttemptIds.set(command.sessionId, receipt.attemptId);
30425
29742
  void executePrompt(
30426
29743
  outbox,
30427
- socket,
29744
+ publisher,
30428
29745
  command,
30429
29746
  config2,
30430
29747
  directories,
@@ -30439,6 +29756,7 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30439
29756
  if (activeAttemptIds.get(command.sessionId) === receipt.attemptId) {
30440
29757
  activeAttemptIds.delete(command.sessionId);
30441
29758
  }
29759
+ turn.finish();
30442
29760
  connectionRefresh.afterTurnFinished();
30443
29761
  });
30444
29762
  } catch (error61) {
@@ -30450,6 +29768,28 @@ async function runRelayConnection(config2, directories, audit, sessions, install
30450
29768
  socket.addEventListener("close", handleClose);
30451
29769
  socket.addEventListener("error", handleError);
30452
29770
  socket.addEventListener("message", handleMessage);
29771
+ void reconcileActiveTurns(
29772
+ config2,
29773
+ reconnectingTurns,
29774
+ connectionController.signal
29775
+ ).then(
29776
+ () => {
29777
+ if (finished) {
29778
+ return;
29779
+ }
29780
+ publisher.connect(socket);
29781
+ void Promise.all(
29782
+ reconnectingTurns.map((turn) => turn.completion)
29783
+ ).then(connectionRefresh.afterTurnFinished);
29784
+ },
29785
+ () => {
29786
+ if (finished) {
29787
+ return;
29788
+ }
29789
+ socket.close(1011, "Active Agent turn reconciliation failed");
29790
+ rejectConnection();
29791
+ }
29792
+ );
30453
29793
  if (signal.aborted) {
30454
29794
  stop();
30455
29795
  }
@@ -30473,23 +29813,21 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
30473
29813
  publishCatalog: async (installationSignal) => await publishAgentCatalog(config2, installationSignal),
30474
29814
  stateDirectory
30475
29815
  });
30476
- await new AutomaticAdapterProvisioner(
30477
- {
30478
- defaultWorkspace: config2.defaultWorkspace,
30479
- audit: installationAudit,
30480
- catalog: config2.catalog,
30481
- environment: process.env
30482
- },
30483
- new ManagedAdapterInstaller({
30484
- environment: process.env,
30485
- stateDirectory
30486
- }),
30487
- specifications
30488
- ).prepare(signal);
30489
29816
  const sessionStore = new SqliteAcpSessionStore(config2.auditDatabasePath);
30490
29817
  const outbox = new SessionEventOutbox(config2.auditDatabasePath);
29818
+ const publisher = new DaemonSessionEventPublisher(outbox);
29819
+ const activeTurns = /* @__PURE__ */ new Map();
29820
+ const activeAttemptIds = /* @__PURE__ */ new Map();
29821
+ const recordSessionEvent = (sessionId, payload) => {
29822
+ const attemptId = activeAttemptIds.get(sessionId);
29823
+ if (attemptId === void 0) {
29824
+ publisher.recordRuntime(sessionId, payload);
29825
+ return;
29826
+ }
29827
+ publisher.recordAttempt(sessionId, payload, attemptId);
29828
+ };
30491
29829
  const sessions = new AcpSessionManager(
30492
- new NullAcpSessionObserver(),
29830
+ new DaemonAcpObserver(recordSessionEvent),
30493
29831
  sessionStore
30494
29832
  );
30495
29833
  const directories = new WorkspaceDirectoryService(
@@ -30545,6 +29883,9 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
30545
29883
  installationObserver,
30546
29884
  nativeSessions,
30547
29885
  outbox,
29886
+ publisher,
29887
+ activeTurns,
29888
+ activeAttemptIds,
30548
29889
  announceConnection,
30549
29890
  signal,
30550
29891
  timer
@@ -30562,6 +29903,11 @@ async function runDaemon(config2, audit, signal, timer = systemDaemonTimer) {
30562
29903
  await waitForRelayRetry(signal, timer);
30563
29904
  }
30564
29905
  } finally {
29906
+ const turns = [...activeTurns.values()];
29907
+ for (const turn of turns) {
29908
+ turn.abortDaemon();
29909
+ }
29910
+ await Promise.all(turns.map((turn) => turn.completion));
30565
29911
  try {
30566
29912
  await catalogPublication;
30567
29913
  } finally {