@agentxm/extension-lifecycle 0.28.11 → 0.28.13

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 (207) hide show
  1. package/dist/src/activation/display-paths.d.ts +25 -0
  2. package/dist/src/activation/display-paths.js +25 -0
  3. package/dist/src/activation/errors.d.ts +16 -0
  4. package/dist/src/activation/errors.js +7 -0
  5. package/dist/src/activation/set-activation.d.ts +134 -0
  6. package/dist/src/activation/set-activation.js +772 -0
  7. package/dist/src/demote/demote-to-external-source.d.ts +82 -0
  8. package/dist/src/demote/demote-to-external-source.js +233 -0
  9. package/dist/src/errors.d.ts +0 -8
  10. package/dist/src/errors.js +0 -8
  11. package/dist/src/glob.d.ts +35 -0
  12. package/dist/src/glob.js +75 -0
  13. package/dist/src/hooks/configured-agent-outcomes-provider.d.ts +7 -3
  14. package/dist/src/hooks/configured-agent-outcomes-provider.js +11 -4
  15. package/dist/src/hooks/install/plan.d.ts +45 -0
  16. package/dist/src/hooks/install/plan.js +224 -0
  17. package/dist/src/hooks/uninstall/plan.d.ts +20 -0
  18. package/dist/src/hooks/uninstall/plan.js +77 -0
  19. package/dist/src/index.d.ts +48 -16
  20. package/dist/src/index.js +60 -17
  21. package/dist/src/install/aggregate-projection-step.d.ts +16 -0
  22. package/dist/src/install/aggregate-projection-step.js +49 -0
  23. package/dist/src/install/configured.d.ts +65 -0
  24. package/dist/src/install/configured.js +406 -0
  25. package/dist/src/install/inline-mcp-operation.d.ts +4 -0
  26. package/dist/src/install/inline-mcp-operation.js +25 -0
  27. package/dist/src/install/install-extensions.d.ts +110 -0
  28. package/dist/src/install/install-extensions.js +282 -0
  29. package/dist/src/install/per-type-install.d.ts +12 -0
  30. package/dist/src/install/per-type-install.js +12 -0
  31. package/dist/src/install/registry-install-target.d.ts +35 -0
  32. package/dist/src/install/registry-install-target.js +66 -0
  33. package/dist/src/install/registry-login-suggestion.d.ts +21 -0
  34. package/dist/src/install/registry-login-suggestion.js +34 -0
  35. package/dist/src/install/registry-source-resolution.d.ts +54 -0
  36. package/dist/src/install/registry-source-resolution.js +216 -0
  37. package/dist/src/install/root-intent.d.ts +19 -0
  38. package/dist/src/install/root-intent.js +122 -0
  39. package/dist/src/install/selection-interaction.d.ts +46 -0
  40. package/dist/src/install/selection-interaction.js +22 -0
  41. package/dist/src/install/vocabulary.d.ts +143 -0
  42. package/dist/src/install/vocabulary.js +29 -0
  43. package/dist/src/knowledge/install/plan.d.ts +35 -0
  44. package/dist/src/knowledge/install/plan.js +128 -0
  45. package/dist/src/knowledge/uninstall/plan.d.ts +23 -0
  46. package/dist/src/knowledge/uninstall/plan.js +140 -0
  47. package/dist/src/live.d.ts +4 -11
  48. package/dist/src/live.js +4 -11
  49. package/dist/src/mcps/install/plan.d.ts +65 -0
  50. package/dist/src/mcps/install/plan.js +301 -0
  51. package/dist/src/mcps/operations/disable.d.ts +5 -3
  52. package/dist/src/mcps/operations/disable.js +6 -4
  53. package/dist/src/mcps/operations/enable.d.ts +5 -3
  54. package/dist/src/mcps/operations/enable.js +8 -6
  55. package/dist/src/mcps/operations/sync-outcome.d.ts +1 -1
  56. package/dist/src/mcps/operations/uninstall.d.ts +5 -3
  57. package/dist/src/mcps/operations/uninstall.js +4 -4
  58. package/dist/src/mcps/uninstall/plan.d.ts +24 -0
  59. package/dist/src/mcps/uninstall/plan.js +109 -0
  60. package/dist/src/packs/artifact.d.ts +21 -0
  61. package/dist/src/packs/artifact.js +32 -0
  62. package/dist/src/packs/constraint-gate.d.ts +30 -0
  63. package/dist/src/packs/constraint-gate.js +76 -0
  64. package/dist/src/packs/expansion.d.ts +13 -14
  65. package/dist/src/packs/expansion.js +1 -2
  66. package/dist/src/packs/graph-transition.d.ts +64 -0
  67. package/dist/src/packs/graph-transition.js +219 -0
  68. package/dist/src/packs/install/plan.d.ts +95 -0
  69. package/dist/src/packs/install/plan.js +845 -0
  70. package/dist/src/packs/member-install-step.d.ts +29 -0
  71. package/dist/src/packs/member-install-step.js +156 -0
  72. package/dist/src/packs/operations/install.d.ts +3 -3
  73. package/dist/src/packs/operations/install.js +5 -5
  74. package/dist/src/packs/promote-authored-pack.d.ts +86 -0
  75. package/dist/src/packs/promote-authored-pack.js +239 -0
  76. package/dist/src/packs/resolved-dependency.d.ts +9 -26
  77. package/dist/src/packs/resolved-dependency.js +8 -20
  78. package/dist/src/packs/uninstall/plan.d.ts +66 -0
  79. package/dist/src/packs/uninstall/plan.js +344 -0
  80. package/dist/src/packs/uninstall/readiness.d.ts +50 -0
  81. package/dist/src/packs/uninstall/readiness.js +130 -0
  82. package/dist/src/publisher-binding.d.ts +8 -40
  83. package/dist/src/publisher-binding.js +8 -46
  84. package/dist/src/rules/install/plan.d.ts +35 -0
  85. package/dist/src/rules/install/plan.js +133 -0
  86. package/dist/src/rules/uninstall/plan.d.ts +19 -0
  87. package/dist/src/rules/uninstall/plan.js +54 -0
  88. package/dist/src/skills/install/bundled.d.ts +73 -0
  89. package/dist/src/skills/install/bundled.js +244 -0
  90. package/dist/src/skills/install/plan.d.ts +72 -0
  91. package/dist/src/skills/install/plan.js +429 -0
  92. package/dist/src/skills/install/selection.d.ts +26 -0
  93. package/dist/src/skills/install/selection.js +41 -0
  94. package/dist/src/skills/install/source.d.ts +21 -0
  95. package/dist/src/skills/install/source.js +76 -0
  96. package/dist/src/skills/operations/disable.d.ts +3 -2
  97. package/dist/src/skills/operations/disable.js +7 -11
  98. package/dist/src/skills/operations/enable.d.ts +3 -2
  99. package/dist/src/skills/operations/enable.js +6 -8
  100. package/dist/src/skills/operations/install.d.ts +4 -4
  101. package/dist/src/skills/operations/install.js +13 -12
  102. package/dist/src/skills/uninstall/plan.d.ts +23 -0
  103. package/dist/src/skills/uninstall/plan.js +165 -0
  104. package/dist/src/skills/utils.js +1 -1
  105. package/dist/src/step-failure-conversion.d.ts +44 -0
  106. package/dist/src/step-failure-conversion.js +26 -0
  107. package/dist/src/step-failure.d.ts +29 -0
  108. package/dist/src/step-failure.js +130 -0
  109. package/dist/src/subagents/install/plan.d.ts +49 -0
  110. package/dist/src/subagents/install/plan.js +270 -0
  111. package/dist/src/subagents/install/selection.d.ts +26 -0
  112. package/dist/src/subagents/install/selection.js +37 -0
  113. package/dist/src/subagents/install/source.d.ts +18 -0
  114. package/dist/src/subagents/install/source.js +72 -0
  115. package/dist/src/subagents/operations/disable.d.ts +5 -3
  116. package/dist/src/subagents/operations/disable.js +5 -3
  117. package/dist/src/subagents/operations/enable.d.ts +5 -3
  118. package/dist/src/subagents/operations/enable.js +17 -12
  119. package/dist/src/subagents/uninstall/plan.d.ts +20 -0
  120. package/dist/src/subagents/uninstall/plan.js +142 -0
  121. package/dist/src/test-packages.d.ts +34 -0
  122. package/dist/src/test-packages.js +111 -0
  123. package/dist/src/test-registry.d.ts +78 -0
  124. package/dist/src/test-registry.js +223 -0
  125. package/dist/src/testing.d.ts +108 -0
  126. package/dist/src/testing.js +241 -0
  127. package/dist/src/uninstall/retention-policy.d.ts +21 -0
  128. package/dist/src/uninstall/retention-policy.js +28 -0
  129. package/dist/src/uninstall/root-intent.d.ts +17 -0
  130. package/dist/src/uninstall/root-intent.js +101 -0
  131. package/dist/src/uninstall/uninstall-extensions.d.ts +61 -0
  132. package/dist/src/uninstall/uninstall-extensions.js +127 -0
  133. package/dist/src/uninstall/vocabulary.d.ts +40 -0
  134. package/dist/src/uninstall/vocabulary.js +14 -0
  135. package/dist/src/update/atomicity.d.ts +22 -0
  136. package/dist/src/update/atomicity.js +23 -0
  137. package/dist/src/update/blockers.d.ts +31 -0
  138. package/dist/src/update/blockers.js +78 -0
  139. package/dist/src/update/configured.d.ts +78 -0
  140. package/dist/src/update/configured.js +546 -0
  141. package/dist/src/update/root-request.d.ts +39 -0
  142. package/dist/src/update/root-request.js +117 -0
  143. package/dist/src/update/selective/plan.d.ts +45 -0
  144. package/dist/src/update/selective/plan.js +61 -0
  145. package/dist/src/update/selective/requirements.d.ts +17 -0
  146. package/dist/src/update/selective/requirements.js +14 -0
  147. package/dist/src/update/selective/selection.d.ts +63 -0
  148. package/dist/src/update/selective/selection.js +85 -0
  149. package/dist/src/update/selective/skills.d.ts +55 -0
  150. package/dist/src/update/selective/skills.js +596 -0
  151. package/dist/src/update/selective/subagents.d.ts +52 -0
  152. package/dist/src/update/selective/subagents.js +331 -0
  153. package/dist/src/update/selective/use-case.d.ts +121 -0
  154. package/dist/src/update/selective/use-case.js +28 -0
  155. package/dist/src/update/selective/vocabulary.d.ts +43 -0
  156. package/dist/src/update/selective/vocabulary.js +28 -0
  157. package/dist/src/update/selector.d.ts +72 -0
  158. package/dist/src/update/selector.js +120 -0
  159. package/dist/src/update/targeted-plan.d.ts +30 -0
  160. package/dist/src/update/targeted-plan.js +113 -0
  161. package/dist/src/update/update-extensions.d.ts +164 -0
  162. package/dist/src/update/update-extensions.js +579 -0
  163. package/dist/src/workspace-paths.d.ts +31 -0
  164. package/dist/src/workspace-paths.js +46 -0
  165. package/package.json +22 -12
  166. package/dist/src/configured-entry-resolution.d.ts +0 -111
  167. package/dist/src/configured-entry-resolution.js +0 -731
  168. package/dist/src/failure-adapter.d.ts +0 -35
  169. package/dist/src/failure-adapter.js +0 -23
  170. package/dist/src/hooks/manager.d.ts +0 -15
  171. package/dist/src/hooks/manager.js +0 -769
  172. package/dist/src/internal/fs-helpers.d.ts +0 -12
  173. package/dist/src/internal/fs-helpers.js +0 -13
  174. package/dist/src/internal/integrity.d.ts +0 -13
  175. package/dist/src/internal/integrity.js +0 -17
  176. package/dist/src/knowledge/manager.d.ts +0 -11
  177. package/dist/src/knowledge/manager.js +0 -711
  178. package/dist/src/mcps/manager.d.ts +0 -16
  179. package/dist/src/mcps/manager.js +0 -247
  180. package/dist/src/mcps/operations/artifact.d.ts +0 -24
  181. package/dist/src/mcps/operations/artifact.js +0 -74
  182. package/dist/src/mcps/operations/install.d.ts +0 -78
  183. package/dist/src/mcps/operations/install.js +0 -596
  184. package/dist/src/packs/dependency-resolution.d.ts +0 -65
  185. package/dist/src/packs/dependency-resolution.js +0 -414
  186. package/dist/src/packs/manager.d.ts +0 -16
  187. package/dist/src/packs/manager.js +0 -181
  188. package/dist/src/registry-materialization.d.ts +0 -52
  189. package/dist/src/registry-materialization.js +0 -72
  190. package/dist/src/release-age-posture.d.ts +0 -23
  191. package/dist/src/release-age-posture.js +0 -15
  192. package/dist/src/resolution-timeout.d.ts +0 -5
  193. package/dist/src/resolution-timeout.js +0 -11
  194. package/dist/src/rules/manager.d.ts +0 -20
  195. package/dist/src/rules/manager.js +0 -480
  196. package/dist/src/skills/manager.d.ts +0 -18
  197. package/dist/src/skills/manager.js +0 -346
  198. package/dist/src/skills/materialization.d.ts +0 -54
  199. package/dist/src/skills/materialization.js +0 -158
  200. package/dist/src/skills/operations/source-hash.d.ts +0 -2
  201. package/dist/src/skills/operations/source-hash.js +0 -6
  202. package/dist/src/subagents/manager.d.ts +0 -18
  203. package/dist/src/subagents/manager.js +0 -722
  204. package/dist/src/workflows/install-command/workflow.d.ts +0 -56
  205. package/dist/src/workflows/install-command/workflow.js +0 -46
  206. package/dist/src/workflows/uninstall-command/workflow.d.ts +0 -42
  207. package/dist/src/workflows/uninstall-command/workflow.js +0 -29
@@ -1,596 +0,0 @@
1
- /**
2
- * Install MCP server executor — orchestrates the per-server installation pipeline.
3
- *
4
- * Registry-only install: fetch archive, extract to canonical path, update lockfile/settings.
5
- * Simpler than skills — no agent symlinks.
6
- *
7
- * @experimental This API is unstable and may change without notice.
8
- */
9
- var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
10
- if (typeof path === "string" && /^\.\.?\//.test(path)) {
11
- return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
12
- return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
13
- });
14
- }
15
- return path;
16
- };
17
- import * as FileSystem from "effect/FileSystem";
18
- import * as Path from "effect/Path";
19
- import * as Array from "effect/Array";
20
- import * as Effect from "effect/Effect";
21
- import * as Option from "effect/Option";
22
- import * as Schema from "effect/Schema";
23
- import { createHash } from "node:crypto";
24
- import { CodingAgentRepository, applyProjectionPlansWithResults, planSingletonProjection, } from "@agentxm/extension-workspace";
25
- import { isPathSafe, mcpRegistryResolutionKey } from "@agentxm/workspace-state";
26
- import { acceptedRegistryVersionForRef, validateExactResolvedVersion, } from "@agentxm/workspace-state";
27
- import { appendWarningsToMessage } from "@agentxm/workspace-operations";
28
- import { WorkspaceMutations } from "@agentxm/workspace-state";
29
- import { canReuseInstalledPackage } from "@agentxm/extension-workspace";
30
- import { materializeRegistryPackage } from "../../registry-materialization.js";
31
- import { computeExtensionPathsForLayout } from "@agentxm/workspace-state";
32
- import { printSourceParams } from "@agentxm/extension-model/unstable/sources/printer";
33
- import { computeMaterializedTreeIntegrity } from "@agentxm/workspace-state";
34
- import { decodeVersionSync } from "@agentxm/extension-model/unstable/version-constraints";
35
- import { MCP_SERVER_MANIFEST_FILENAME, McpServerManifestSchema, } from "@agentxm/extension-model/unstable/mcps/manifest-schema";
36
- import { agentConfigTargets, mcpServerArtifact, mcpSettingsTarget, mcpSourceTarget, } from "./artifact.js";
37
- import { LifecycleFailureAdapter, withAdaptedStepFailures } from "../../failure-adapter.js";
38
- import { ExtensionLifecycleFailed } from "../../errors.js";
39
- // -----------------------------------------------------------------------------
40
- // Lock entry builder
41
- // -----------------------------------------------------------------------------
42
- const buildLockEntry = (ref, treeIntegrity) => ({
43
- type: "registry",
44
- sourceType: "registry",
45
- packageFormat: "agentxm",
46
- endpoint: ref.source.location,
47
- extensionType: "mcp-server",
48
- workspaceName: ref.server.name,
49
- owner: ref.owner,
50
- name: ref.name,
51
- resolvedVersion: decodeVersionSync(ref.version),
52
- integrity: Option.getOrElse(ref.integrity, () => ""),
53
- sourceName: ref.source.name,
54
- publisherBindingId: ref.publisherBindingId,
55
- treeIntegrity,
56
- });
57
- const MCP_SECRET_SERVICE = "axm-mcp";
58
- export const mcpSecretAccount = (args) => createHash("sha256")
59
- .update([args.scopeRoot, args.localName, args.sourceIdentity, args.inputName].join("\0"))
60
- .digest("hex");
61
- const keyringModuleSpecifier = ["@napi-rs", "keyring"].join("/");
62
- const loadKeyringEntry = Effect.tryPromise({
63
- try: async () => {
64
- const keyring = await import(__rewriteRelativeImportExtension(keyringModuleSpecifier));
65
- return keyring.Entry;
66
- },
67
- catch: () => undefined,
68
- });
69
- const saveMcpSecret = (account, inputName, value) => Effect.gen(function* () {
70
- const Entry = yield* loadKeyringEntry;
71
- return yield* Effect.try({
72
- try: () => {
73
- const entry = new Entry(MCP_SECRET_SERVICE, account);
74
- entry.setPassword(value);
75
- return { _tag: "saved", inputName };
76
- },
77
- catch: () => undefined,
78
- });
79
- }).pipe(Effect.catch(() => Effect.succeed({ _tag: "failed", inputName })));
80
- const loadMcpSecret = (account) => Effect.gen(function* () {
81
- const Entry = yield* loadKeyringEntry;
82
- return yield* Effect.try({
83
- try: () => {
84
- const entry = new Entry(MCP_SECRET_SERVICE, account);
85
- return Option.fromNullOr(entry.getPassword());
86
- },
87
- catch: () => undefined,
88
- }).pipe(Effect.catch(() => Effect.succeed(Option.none())));
89
- }).pipe(Effect.catch(() => Effect.succeed(Option.none())));
90
- const maybeSecretInputName = (input) => {
91
- if (input.isSecret !== true)
92
- return undefined;
93
- if ("name" in input)
94
- return input.name;
95
- if ("valueHint" in input)
96
- return input.valueHint;
97
- return undefined;
98
- };
99
- /**
100
- * Named environment inputs the manifest marks required. Only key/value inputs
101
- * are collected: an unnamed input has nothing a caller could pass through
102
- * `--env KEY=VALUE`, so it cannot be reported as a missing name.
103
- */
104
- const collectRequiredInputNames = (manifest) => {
105
- const names = new Set();
106
- const add = (input) => {
107
- if (input.isRequired === true && input.value === undefined && input.default === undefined) {
108
- names.add(input.name);
109
- }
110
- };
111
- for (const pkg of manifest.server.packages ?? []) {
112
- for (const input of pkg.environmentVariables ?? [])
113
- add(input);
114
- }
115
- for (const remote of manifest.server.remotes ?? []) {
116
- for (const input of remote.headers ?? [])
117
- add(input);
118
- }
119
- return names;
120
- };
121
- export const collectSecretInputNames = (manifest) => {
122
- const names = new Set();
123
- const add = (input) => {
124
- const name = maybeSecretInputName(input);
125
- if (name !== undefined)
126
- names.add(name);
127
- };
128
- for (const pkg of manifest.server.packages ?? []) {
129
- for (const input of pkg.environmentVariables ?? [])
130
- add(input);
131
- for (const input of pkg.runtimeArguments ?? [])
132
- add(input);
133
- for (const input of pkg.packageArguments ?? [])
134
- add(input);
135
- }
136
- for (const remote of manifest.server.remotes ?? []) {
137
- for (const input of remote.headers ?? [])
138
- add(input);
139
- for (const [name, input] of Object.entries(remote.variables ?? {})) {
140
- if (input.isSecret === true)
141
- names.add(name);
142
- }
143
- }
144
- return names;
145
- };
146
- // -----------------------------------------------------------------------------
147
- // Registry install
148
- // -----------------------------------------------------------------------------
149
- const installFromRegistry = (ref, reuse) => Effect.gen(function* () {
150
- const path = yield* Path.Path;
151
- const ws = yield* WorkspaceMutations;
152
- const canonicalPath = computeExtensionPathsForLayout(path.join, ws.layout, ref, "mcps", ref.name).canonicalPath;
153
- if (!isPathSafe(path, ws.baseDir, canonicalPath)) {
154
- return yield* new ExtensionLifecycleFailed({
155
- category: "internal",
156
- detail: `Path traversal detected: ${canonicalPath}`,
157
- });
158
- }
159
- const useExisting = yield* canReuseInstalledPackage({
160
- installedPath: canonicalPath,
161
- force: reuse.force,
162
- refVersion: ref.version,
163
- hasIntegrity: Option.isSome(ref.integrity),
164
- ...(reuse.lockedVersion === undefined ? {} : { lockedVersion: reuse.lockedVersion }),
165
- existsFailureDetail: (target) => `Failed to check if canonical path exists: ${target}`,
166
- });
167
- if (!useExisting) {
168
- yield* materializeRegistryPackage({
169
- baseDir: ws.baseDir,
170
- destinationPath: canonicalPath,
171
- sourceLocation: ref.source.location,
172
- owner: ref.owner,
173
- type: "mcp-server",
174
- name: ref.name,
175
- version: ref.version,
176
- integrity: ref.integrity,
177
- messages: {
178
- integrityMismatchDetail: `Integrity mismatch for ${ref.name}@${ref.version}`,
179
- },
180
- });
181
- }
182
- return canonicalPath;
183
- });
184
- export const readMcpServerManifest = (canonicalPath) => Effect.gen(function* () {
185
- const fs = yield* FileSystem.FileSystem;
186
- const path = yield* Path.Path;
187
- const manifestPath = path.join(canonicalPath, MCP_SERVER_MANIFEST_FILENAME);
188
- const exists = yield* fs.exists(manifestPath).pipe(Effect.catch(() => Effect.succeed(false)));
189
- if (!exists) {
190
- return Option.none();
191
- }
192
- const manifest = yield* fs.readFileString(manifestPath).pipe(Effect.flatMap((raw) => Effect.try({
193
- try: () => {
194
- const parsed = JSON.parse(raw);
195
- return Schema.decodeUnknownSync(McpServerManifestSchema)(parsed);
196
- },
197
- catch: () => undefined,
198
- })), Effect.catch(() => Effect.void));
199
- if (manifest === undefined) {
200
- return Option.none();
201
- }
202
- return Option.some(manifest);
203
- });
204
- const isNothingRunnableManifest = (manifest) => Option.match(manifest, {
205
- onNone: () => false,
206
- onSome: (value) => (value.server.packages === undefined || value.server.packages.length === 0) &&
207
- (value.server.remotes === undefined || value.server.remotes.length === 0),
208
- });
209
- const loadStoredMcpSecrets = (identity, secretNames) => Effect.gen(function* () {
210
- const entries = yield* Effect.forEach(secretNames, (name) => loadMcpSecret(mcpSecretAccount({ ...identity, inputName: name })).pipe(Effect.map((value) => ({ name, value }))), { concurrency: "unbounded" });
211
- const loaded = {};
212
- for (const { name, value } of entries) {
213
- if (Option.isSome(value))
214
- loaded[name] = value.value;
215
- }
216
- return loaded;
217
- });
218
- const persistMcpSecrets = (identity, secretNames, values) => Effect.forEach(secretNames, (name) => {
219
- const value = values[name];
220
- return value === undefined
221
- ? Effect.succeed({ _tag: "skipped", inputName: name })
222
- : saveMcpSecret(mcpSecretAccount({ ...identity, inputName: name }), name, value);
223
- }, { concurrency: "unbounded" });
224
- export const deleteMcpSecrets = (identity, secretNames) => Effect.forEach(secretNames, (inputName) => Effect.gen(function* () {
225
- const Entry = yield* loadKeyringEntry;
226
- return yield* Effect.try({
227
- try: () => {
228
- const entry = new Entry(MCP_SECRET_SERVICE, mcpSecretAccount({ ...identity, inputName }));
229
- return entry.deletePassword()
230
- ? { _tag: "deleted", inputName }
231
- : { _tag: "absent", inputName };
232
- },
233
- catch: () => undefined,
234
- });
235
- }).pipe(Effect.catch(() => Effect.succeed({ _tag: "failed", inputName }))), { concurrency: "unbounded" });
236
- const redactSettingsEnv = (values, secretNames) => {
237
- const redacted = {};
238
- for (const [name, value] of Object.entries(values)) {
239
- if (!secretNames.has(name))
240
- redacted[name] = value;
241
- }
242
- return redacted;
243
- };
244
- const preserveSecretReferences = (values, secretNames) => Object.fromEntries(Object.entries(values).map(([name, value]) => [
245
- name,
246
- secretNames.has(name) ? `\${${name}}` : value,
247
- ]));
248
- const REQUIRED_AGENT_IDS = new Set([
249
- "claude-code",
250
- "opencode",
251
- "github-copilot-cli",
252
- "cursor",
253
- "gemini-cli",
254
- "codex",
255
- ]);
256
- const formatAgentSyncWarning = (serverName, outcomes) => {
257
- const warningMessage = outcomes
258
- .map(({ agentId, outcome }) => outcome._tag === "success"
259
- ? `${agentId}:success`
260
- : outcome._tag === "fallback"
261
- ? `${agentId}:fallback(${outcome.fallbackFrom}):${outcome.reason}`
262
- : `${agentId}:${outcome.reason}`)
263
- .join(", ");
264
- return `MCP agent sync warnings for ${serverName}: ${warningMessage}`;
265
- };
266
- const summarizeAgentSync = (outcomes, warnings) => {
267
- const degraded = outcomes.some(({ outcome }) => outcome._tag === "failed" || outcome._tag === "fallback");
268
- const details = outcomes.map(({ agentId, outcome }) => outcome._tag === "success"
269
- ? `${agentId}:success`
270
- : outcome._tag === "fallback"
271
- ? `${agentId}:fallback:${outcome.fallbackFrom}`
272
- : `${agentId}:${outcome._tag}`);
273
- return {
274
- status: degraded ? "degraded" : "green",
275
- details,
276
- warnings,
277
- outcomes,
278
- };
279
- };
280
- const syncConfiguredAgentsOnInstall = (args) => Effect.gen(function* () {
281
- const agentRepo = yield* CodingAgentRepository;
282
- const fs = yield* FileSystem.FileSystem;
283
- const path = yield* Path.Path;
284
- const warnings = [];
285
- const unknownConfiguredAgentIds = yield* agentRepo.getUnknownConfiguredAgentIds();
286
- if (args.strict && unknownConfiguredAgentIds.length > 0) {
287
- const message = `Unknown configured agents in strict mode: ${unknownConfiguredAgentIds.join(", ")}`;
288
- return yield* new ExtensionLifecycleFailed({
289
- category: "not_found",
290
- detail: message,
291
- });
292
- }
293
- if (unknownConfiguredAgentIds.length > 0) {
294
- warnings.push(`Skipping unknown configured agents: ${unknownConfiguredAgentIds.join(", ")}`);
295
- }
296
- const configuredAgents = yield* agentRepo.getConfiguredAgents();
297
- let outcomes;
298
- if (args.nothingRunnable) {
299
- outcomes = configuredAgents.map((agent) => ({
300
- agentId: agent.id,
301
- outcome: {
302
- _tag: "nothing-runnable",
303
- reason: "manifest server has no packages or remotes",
304
- },
305
- }));
306
- }
307
- else {
308
- outcomes = yield* applyProjectionPlansWithResults(configuredAgents.map((agent) => planSingletonProjection({
309
- unitId: "mcp-server:native-config-entry",
310
- targetFile: "mcp:configured-agents",
311
- contributor: args,
312
- adapter: {
313
- observe: () => Effect.succeed({
314
- unitId: "mcp-server:native-config-entry",
315
- path: `${agent.id}:${args.serverName}`,
316
- present: false,
317
- current: false,
318
- expectedContributors: [args.serverName],
319
- observedContributors: [],
320
- }),
321
- apply: () => Effect.gen(function* () {
322
- const outcome = yield* agent.addMcpServer({
323
- workspaceRoot: args.wsBaseDir,
324
- scope: args.scope,
325
- serverName: args.serverName,
326
- canonicalPath: args.canonicalPath,
327
- owner: args.owner,
328
- resolvedVersion: args.resolvedVersion,
329
- enabled: args.enabled,
330
- configValues: args.configValues,
331
- });
332
- return { agentId: agent.id, outcome };
333
- }).pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path.Path, path)),
334
- },
335
- })));
336
- }
337
- const misconfigured = Array.filter(outcomes, ({ outcome }) => outcome._tag === "misconfigured");
338
- if (misconfigured.length > 0) {
339
- return yield* new ExtensionLifecycleFailed({
340
- category: "internal",
341
- detail: `MCP server ${args.serverName} could not be synced to configured agents`,
342
- });
343
- }
344
- const failed = Array.filter(outcomes, ({ outcome }) => outcome._tag === "failed");
345
- if (args.strict && failed.length > 0) {
346
- return yield* new ExtensionLifecycleFailed({
347
- category: "internal",
348
- detail: `MCP server ${args.serverName} sync failed in strict mode`,
349
- });
350
- }
351
- const strictDisabledFailures = Array.filter(outcomes, ({ agentId, outcome }) => (outcome._tag === "disabled" ||
352
- (outcome._tag === "fallback" && outcome.fallbackFrom === "disabled")) &&
353
- args.strict &&
354
- REQUIRED_AGENT_IDS.has(agentId));
355
- if (strictDisabledFailures.length > 0) {
356
- return yield* new ExtensionLifecycleFailed({
357
- category: "internal",
358
- detail: `MCP server ${args.serverName} sync disabled for required configured agents`,
359
- });
360
- }
361
- const warningOutcomes = Array.filter(outcomes, ({ outcome }) => outcome._tag === "unsupported" ||
362
- outcome._tag === "disabled" ||
363
- outcome._tag === "nothing-runnable" ||
364
- outcome._tag === "needs-input" ||
365
- outcome._tag === "failed" ||
366
- outcome._tag === "fallback");
367
- if (warningOutcomes.length > 0) {
368
- warnings.push(formatAgentSyncWarning(args.serverName, warningOutcomes));
369
- }
370
- return summarizeAgentSync(outcomes, warnings);
371
- });
372
- // -----------------------------------------------------------------------------
373
- // Public API
374
- // -----------------------------------------------------------------------------
375
- /**
376
- * Install-mcp-server operation handler.
377
- *
378
- * Registry-only: fetch archive, validate integrity, extract to canonical path,
379
- * then update lockfile/settings.
380
- */
381
- export const installMcpServer = (op) => Effect.gen(function* () {
382
- const ws = yield* WorkspaceMutations;
383
- const path = yield* Path.Path;
384
- const { ref } = op.args;
385
- const localName = op.args.localName ?? ref.server.name;
386
- if (ref.refType !== "registry" && ref.refType !== "workspace") {
387
- return yield* new ExtensionLifecycleFailed({
388
- category: "usage",
389
- detail: `MCP servers install from a registry or a workspace package, not from a ${ref.refType} source`,
390
- suggestions: [
391
- {
392
- description: "Install from the registry",
393
- cmd: `axm mcps install @owner/mcps/${ref.server.name}`,
394
- },
395
- ],
396
- });
397
- }
398
- const strictAgentSync = Option.getOrElse(op.args.strictAgentSync ?? Option.none(), () => false);
399
- const env = Option.getOrElse(op.args.env ?? Option.none(), () => ({}));
400
- const resolutionKey = ref.refType === "registry"
401
- ? mcpRegistryResolutionKey({
402
- authority: ref.source.location,
403
- owner: ref.owner,
404
- name: ref.server.name,
405
- })
406
- : undefined;
407
- const sourceIdentity = resolutionKey ?? `workspace:${ref.owner}/mcps/${ref.server.name}`;
408
- const desiredGraph = yield* ws.getDesiredStateGraph();
409
- const existingLocalNode = desiredGraph.nodes.find((node) => node.type === "mcp-server" && node.name === localName);
410
- if (existingLocalNode !== undefined &&
411
- (existingLocalNode.authority === "inline" || existingLocalNode.identity !== sourceIdentity)) {
412
- return yield* new ExtensionLifecycleFailed({
413
- category: "conflict",
414
- detail: `Local MCP name "${localName}" is already owned by a different source`,
415
- });
416
- }
417
- const existingClosure = desiredGraph.mcpSourceClosures.find((closure) => closure.identity === sourceIdentity);
418
- const lockedVersion = ref.refType === "registry"
419
- ? acceptedRegistryVersionForRef(yield* ws.getLockedMcpServer(resolutionKey ?? ""), ref)
420
- : undefined;
421
- const canonicalPath = ref.refType === "registry"
422
- ? yield* installFromRegistry(ref, { force: op.args.force, lockedVersion })
423
- : yield* Effect.gen(function* () {
424
- const fs = yield* FileSystem.FileSystem;
425
- const path = yield* Path.Path;
426
- const expectedPath = path.join(ws.layout.scope === "project"
427
- ? ws.layout.authoredRoot("mcp-server")
428
- : path.join(ws.layout.acquiredRoot, ref.owner, "mcps"), ref.name);
429
- if (ref.scope !== ws.scope ||
430
- path.resolve(ref.location) !== path.resolve(expectedPath)) {
431
- return yield* new ExtensionLifecycleFailed({
432
- category: "validation",
433
- detail: `Invalid workspace MCP server source location: ${ref.location}`,
434
- });
435
- }
436
- const exists = yield* fs.exists(ref.location).pipe(Effect.mapError((error) => new ExtensionLifecycleFailed({
437
- category: "internal",
438
- detail: `Failed to inspect workspace MCP server package: ${ref.location}`,
439
- cause: error,
440
- })));
441
- if (!exists) {
442
- return yield* new ExtensionLifecycleFailed({
443
- category: "validation",
444
- detail: `Workspace MCP server package is missing: ${ref.location}`,
445
- });
446
- }
447
- return ref.location;
448
- });
449
- const manifest = yield* readMcpServerManifest(canonicalPath);
450
- const nothingRunnable = isNothingRunnableManifest(manifest);
451
- const secretNames = Option.match(manifest, {
452
- onNone: () => new Set(),
453
- onSome: collectSecretInputNames,
454
- });
455
- if (ref.refType === "registry") {
456
- yield* validateExactResolvedVersion(`mcpServers.${ref.server.name}.resolvedVersion`, ref.version);
457
- }
458
- const lockEntry = ref.refType === "registry"
459
- ? buildLockEntry(ref, yield* computeMaterializedTreeIntegrity(canonicalPath))
460
- : undefined;
461
- const currentMcpServers = yield* ws.getConfiguredMcpServerEntries();
462
- const currentEntry = currentMcpServers[localName];
463
- const secretIdentity = {
464
- scopeRoot: path.resolve(ws.baseDir),
465
- localName,
466
- sourceIdentity,
467
- };
468
- const storedSecrets = yield* loadStoredMcpSecrets(secretIdentity, secretNames);
469
- const mergedEnv = { ...storedSecrets, ...(currentEntry?.env ?? {}), ...env };
470
- // Under --non-interactive there is nobody to prompt, so a required input
471
- // that nothing supplied would otherwise install a server that cannot start.
472
- // Fail with the exact recipe instead.
473
- const requiredInputNames = Option.match(manifest, {
474
- onNone: () => new Set(),
475
- onSome: collectRequiredInputNames,
476
- });
477
- const missingInputs = [...requiredInputNames]
478
- .filter((name) => mergedEnv[name] === undefined || mergedEnv[name] === "")
479
- .sort((left, right) => left.localeCompare(right));
480
- if (missingInputs.length > 0 && op.args.nonInteractive) {
481
- return yield* new ExtensionLifecycleFailed({
482
- category: "usage",
483
- detail: `${localName} needs ${missingInputs.join(", ")}, and --non-interactive cannot prompt for them`,
484
- suggestions: [
485
- {
486
- description: "Supply each required input on the command line",
487
- cmd: missingInputs.map((name) => `--env ${name}=<value>`).join(" "),
488
- },
489
- ],
490
- });
491
- }
492
- const persistedEnv = redactSettingsEnv(mergedEnv, secretNames);
493
- const enabled = currentEntry?.enabled ?? true;
494
- const settingsEntry = {
495
- kind: "sourced",
496
- source: ref.refType === "workspace" ? "workspace" : printSourceParams(ref.source),
497
- env: persistedEnv,
498
- enabled,
499
- };
500
- const writeEffect = op.args.skipStateWrites === true
501
- ? Effect.void
502
- : Option.getOrElse(op.args.skipSettings, () => false)
503
- ? lockEntry === undefined
504
- ? Effect.void
505
- : ws.setMcpServerLock({
506
- name: resolutionKey ?? ref.server.name,
507
- resolutionKey: resolutionKey ?? ref.server.name,
508
- lockEntry,
509
- versionRange: Option.none(),
510
- })
511
- : lockEntry === undefined
512
- ? ws.setMcpServerEntry(localName, {
513
- ...settingsEntry,
514
- })
515
- : ws.setMcpServer({
516
- name: localName,
517
- resolutionKey: resolutionKey ?? localName,
518
- lockEntry,
519
- versionRange: op.args.versionRange,
520
- env: persistedEnv,
521
- enabled,
522
- });
523
- yield* writeEffect;
524
- const projectionNames = ref.refType === "registry" && lockedVersion !== undefined && lockedVersion !== ref.version
525
- ? [...new Set([...(existingClosure?.localNames ?? []), localName])].sort()
526
- : [localName];
527
- const agentSyncResults = yield* Effect.forEach(projectionNames, (projectionName) => Effect.gen(function* () {
528
- const projectionEntry = projectionName === localName ? settingsEntry : currentMcpServers[projectionName];
529
- if (projectionEntry === undefined || projectionEntry.kind === "inline") {
530
- return undefined;
531
- }
532
- const projectionSecretIdentity = {
533
- scopeRoot: path.resolve(ws.baseDir),
534
- localName: projectionName,
535
- sourceIdentity,
536
- };
537
- const projectionStoredSecrets = yield* loadStoredMcpSecrets(projectionSecretIdentity, secretNames);
538
- const projectionEnv = projectionName === localName
539
- ? mergedEnv
540
- : { ...projectionStoredSecrets, ...projectionEntry.env };
541
- return yield* syncConfiguredAgentsOnInstall({
542
- wsBaseDir: ws.baseDir,
543
- scope: ws.scope,
544
- strict: strictAgentSync,
545
- serverName: projectionName,
546
- canonicalPath,
547
- owner: ref.owner,
548
- resolvedVersion: ref.version,
549
- nothingRunnable,
550
- enabled: projectionEntry.enabled,
551
- configValues: preserveSecretReferences(projectionEnv, secretNames),
552
- entry: projectionEntry,
553
- });
554
- }), { concurrency: 1 });
555
- const agentSyncSummaries = agentSyncResults.filter((summary) => summary !== undefined);
556
- const agentSync = {
557
- status: agentSyncSummaries.some((summary) => summary.status === "degraded")
558
- ? "degraded"
559
- : "green",
560
- details: agentSyncSummaries.flatMap((summary) => summary.details),
561
- warnings: agentSyncSummaries.flatMap((summary) => summary.warnings),
562
- outcomes: agentSyncSummaries.flatMap((summary) => summary.outcomes),
563
- };
564
- const secretPersistence = yield* persistMcpSecrets(secretIdentity, secretNames, mergedEnv);
565
- const secretWarnings = secretPersistence.flatMap((outcome) => outcome._tag === "failed"
566
- ? [
567
- `${outcome.inputName} could not be saved to the system keychain; AXM state was applied and credential action is required`,
568
- ]
569
- : []);
570
- const warnings = [...secretWarnings, ...agentSync.warnings];
571
- const change = currentEntry === undefined ? "created" : "updated";
572
- const agentOutcomes = agentSync.outcomes.flatMap(({ agentId, outcome }) => outcome._tag === "success" || outcome._tag === "fallback"
573
- ? [
574
- {
575
- agentId,
576
- ...(outcome.targets === undefined ? {} : { targets: outcome.targets }),
577
- },
578
- ]
579
- : []);
580
- return {
581
- result: "success",
582
- message: appendWarningsToMessage(`Installed ${localName} from ${ref.owner}/mcps/${ref.server.name} (canonical=success, agent-sync=${agentSync.status})`, warnings),
583
- artifact: mcpServerArtifact({
584
- lockEntry,
585
- scope: ws.scope,
586
- change,
587
- agents: agentOutcomes.map(({ agentId }) => agentId),
588
- targets: [
589
- ...(lockEntry === undefined ? [] : [mcpSourceTarget(ws.scope, lockEntry, change)]),
590
- mcpSettingsTarget(ws.scope, change),
591
- ...agentConfigTargets(agentOutcomes),
592
- ],
593
- }),
594
- };
595
- }).pipe(withAdaptedStepFailures);
596
- //# sourceMappingURL=install.js.map
@@ -1,65 +0,0 @@
1
- import * as Effect from "effect/Effect";
2
- import * as Option from "effect/Option";
3
- import type { SourceAuthorityBlockedFact } from "@agentxm/extension-workspace";
4
- /** Failures pack dependency resolution can surface. */
5
- type PackDependencyResolutionError = SourceResolutionFailure | PackManagerError | SourceAuthorityBlocked;
6
- import type { ExtensionRef } from "@agentxm/extension-model/unstable/extensions/refs/extension-ref";
7
- import type { Handle, ExtensionName, ExtensionType } from "@agentxm/extension-model/unstable/extensions";
8
- import type { ResolvedPackDependencyMap } from "./resolved-dependency.js";
9
- import type { SourceHostProvidersService, SourceResolutionFailure } from "@agentxm/extension-sources";
10
- import type { RegistrySource } from "@agentxm/extension-model/unstable/sources/types";
11
- import { SourceAuthorityBlocked, type PackManagerError } from "@agentxm/extension-workspace";
12
- import type { PackRef } from "@agentxm/extension-model/unstable/extensions/refs/pack";
13
- import type * as Duration from "effect/Duration";
14
- import type { VersionRange } from "@agentxm/extension-model/unstable/version-constraints";
15
- import type { ReleaseAgeBypassRecord, ReleaseAgeHoldbackRecord } from "@agentxm/registry-protocol/unstable/registry/release-age-policy";
16
- import type { ReleaseAgeEvaluation } from "@agentxm/extension-model/unstable/extensions/release-age";
17
- /** Every extension type a pack can depend on — packs cannot nest. */
18
- type SupportedPackDependencyType = Exclude<ExtensionType, "pack">;
19
- export type WorkspacePackDependencyResolution = {
20
- readonly kind: "absent";
21
- } | {
22
- readonly kind: "selected";
23
- readonly ref: ExtensionRef;
24
- } | {
25
- readonly kind: "blocked";
26
- readonly fact: SourceAuthorityBlockedFact;
27
- };
28
- export type WorkspacePackDependencyResolver<E = never> = (args: {
29
- readonly owner: Handle;
30
- readonly type: SupportedPackDependencyType;
31
- readonly name: ExtensionName;
32
- readonly constraint: VersionRange;
33
- readonly root: string;
34
- }) => Effect.Effect<WorkspacePackDependencyResolution, E>;
35
- /** Resolve a Pack member from an already-authorized immutable candidate. */
36
- export type PackDependencyRefResolver<E = never> = (args: {
37
- readonly owner: Handle;
38
- readonly type: SupportedPackDependencyType;
39
- readonly name: ExtensionName;
40
- readonly constraint: VersionRange;
41
- readonly root: string;
42
- }) => Effect.Effect<ExtensionRef, E>;
43
- export interface ResolvedPackDependencies {
44
- readonly resolvedSkills: ResolvedPackDependencyMap;
45
- readonly resolvedMcpServers: ResolvedPackDependencyMap;
46
- readonly resolvedSubagents: ResolvedPackDependencyMap;
47
- readonly resolvedRules: ResolvedPackDependencyMap;
48
- readonly resolvedHooks: ResolvedPackDependencyMap;
49
- readonly resolvedKnowledge: ResolvedPackDependencyMap;
50
- readonly dependencyRefs: ReadonlyArray<ExtensionRef>;
51
- }
52
- export type ReleaseAgeAwarePackDependencyResolution = {
53
- readonly kind: "selected";
54
- readonly dependencies: ResolvedPackDependencies;
55
- readonly holdbacks: ReadonlyArray<ReleaseAgeHoldbackRecord>;
56
- readonly bypasses: ReadonlyArray<ReleaseAgeBypassRecord>;
57
- } | {
58
- readonly kind: "policy_held";
59
- readonly holdbacks: ReadonlyArray<ReleaseAgeHoldbackRecord>;
60
- readonly bypasses: ReadonlyArray<ReleaseAgeBypassRecord>;
61
- };
62
- export declare const resolvePackDependencies: <E = never>(pack: PackRef, sources: SourceHostProvidersService, minimumReleaseAge?: Option.Option<Duration.Duration>, sourceOverride?: RegistrySource, workspaceResolver?: WorkspacePackDependencyResolver<E>, dependencyResolver?: PackDependencyRefResolver<E>) => Effect.Effect<ResolvedPackDependencies, PackDependencyResolutionError | E>;
63
- export declare const resolvePackDependenciesWithReleaseAge: <E = never>(pack: PackRef, sources: SourceHostProvidersService, evaluation: ReleaseAgeEvaluation, sourceOverride?: RegistrySource, workspaceResolver?: WorkspacePackDependencyResolver<E>, dependencyResolver?: PackDependencyRefResolver<E>) => Effect.Effect<ReleaseAgeAwarePackDependencyResolution, PackDependencyResolutionError | E>;
64
- export {};
65
- //# sourceMappingURL=dependency-resolution.d.ts.map