@agentxm/extension-lifecycle 0.28.4-bootstrap.0

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 (84) hide show
  1. package/LICENSE +110 -0
  2. package/dist/src/configured-entry-resolution.d.ts +110 -0
  3. package/dist/src/configured-entry-resolution.js +723 -0
  4. package/dist/src/errors.d.ts +39 -0
  5. package/dist/src/errors.js +45 -0
  6. package/dist/src/failure-adapter.d.ts +35 -0
  7. package/dist/src/failure-adapter.js +23 -0
  8. package/dist/src/hooks/configured-agent-outcomes-provider.d.ts +18 -0
  9. package/dist/src/hooks/configured-agent-outcomes-provider.js +39 -0
  10. package/dist/src/hooks/manager.d.ts +15 -0
  11. package/dist/src/hooks/manager.js +751 -0
  12. package/dist/src/index.d.ts +38 -0
  13. package/dist/src/index.js +41 -0
  14. package/dist/src/internal/fs-helpers.d.ts +12 -0
  15. package/dist/src/internal/fs-helpers.js +13 -0
  16. package/dist/src/internal/integrity.d.ts +13 -0
  17. package/dist/src/internal/integrity.js +17 -0
  18. package/dist/src/knowledge/manager.d.ts +11 -0
  19. package/dist/src/knowledge/manager.js +655 -0
  20. package/dist/src/live.d.ts +18 -0
  21. package/dist/src/live.js +18 -0
  22. package/dist/src/mcps/manager.d.ts +16 -0
  23. package/dist/src/mcps/manager.js +213 -0
  24. package/dist/src/mcps/operations/artifact.d.ts +24 -0
  25. package/dist/src/mcps/operations/artifact.js +74 -0
  26. package/dist/src/mcps/operations/disable.d.ts +18 -0
  27. package/dist/src/mcps/operations/disable.js +113 -0
  28. package/dist/src/mcps/operations/enable.d.ts +18 -0
  29. package/dist/src/mcps/operations/enable.js +218 -0
  30. package/dist/src/mcps/operations/install.d.ts +59 -0
  31. package/dist/src/mcps/operations/install.js +566 -0
  32. package/dist/src/mcps/operations/sync-outcome.d.ts +10 -0
  33. package/dist/src/mcps/operations/sync-outcome.js +27 -0
  34. package/dist/src/mcps/operations/uninstall.d.ts +41 -0
  35. package/dist/src/mcps/operations/uninstall.js +189 -0
  36. package/dist/src/packs/dependency-resolution.d.ts +65 -0
  37. package/dist/src/packs/dependency-resolution.js +414 -0
  38. package/dist/src/packs/expansion.d.ts +59 -0
  39. package/dist/src/packs/expansion.js +44 -0
  40. package/dist/src/packs/manager.d.ts +16 -0
  41. package/dist/src/packs/manager.js +181 -0
  42. package/dist/src/packs/operations/install.d.ts +67 -0
  43. package/dist/src/packs/operations/install.js +156 -0
  44. package/dist/src/packs/resolved-dependency.d.ts +29 -0
  45. package/dist/src/packs/resolved-dependency.js +28 -0
  46. package/dist/src/registry-materialization.d.ts +52 -0
  47. package/dist/src/registry-materialization.js +67 -0
  48. package/dist/src/resolution-progress.d.ts +18 -0
  49. package/dist/src/resolution-progress.js +11 -0
  50. package/dist/src/resolution-timeout.d.ts +5 -0
  51. package/dist/src/resolution-timeout.js +11 -0
  52. package/dist/src/rules/manager.d.ts +20 -0
  53. package/dist/src/rules/manager.js +475 -0
  54. package/dist/src/skills/manager.d.ts +18 -0
  55. package/dist/src/skills/manager.js +346 -0
  56. package/dist/src/skills/materialization.d.ts +54 -0
  57. package/dist/src/skills/materialization.js +158 -0
  58. package/dist/src/skills/operations/disable.d.ts +31 -0
  59. package/dist/src/skills/operations/disable.js +110 -0
  60. package/dist/src/skills/operations/enable.d.ts +31 -0
  61. package/dist/src/skills/operations/enable.js +113 -0
  62. package/dist/src/skills/operations/install-result.d.ts +33 -0
  63. package/dist/src/skills/operations/install-result.js +10 -0
  64. package/dist/src/skills/operations/install.d.ts +67 -0
  65. package/dist/src/skills/operations/install.js +590 -0
  66. package/dist/src/skills/operations/source-hash.d.ts +2 -0
  67. package/dist/src/skills/operations/source-hash.js +6 -0
  68. package/dist/src/skills/operations/uninstall.d.ts +40 -0
  69. package/dist/src/skills/operations/uninstall.js +157 -0
  70. package/dist/src/skills/utils.d.ts +11 -0
  71. package/dist/src/skills/utils.js +29 -0
  72. package/dist/src/subagents/manager.d.ts +18 -0
  73. package/dist/src/subagents/manager.js +677 -0
  74. package/dist/src/subagents/operations/artifact.d.ts +18 -0
  75. package/dist/src/subagents/operations/artifact.js +43 -0
  76. package/dist/src/subagents/operations/disable.d.ts +32 -0
  77. package/dist/src/subagents/operations/disable.js +116 -0
  78. package/dist/src/subagents/operations/enable.d.ts +30 -0
  79. package/dist/src/subagents/operations/enable.js +160 -0
  80. package/dist/src/workflows/install-command/workflow.d.ts +57 -0
  81. package/dist/src/workflows/install-command/workflow.js +41 -0
  82. package/dist/src/workflows/uninstall-command/workflow.d.ts +42 -0
  83. package/dist/src/workflows/uninstall-command/workflow.js +29 -0
  84. package/package.json +62 -0
@@ -0,0 +1,723 @@
1
+ import * as DateTime from "effect/DateTime";
2
+ import * as Effect from "effect/Effect";
3
+ import * as Option from "effect/Option";
4
+ import { parseRegistrySourceRef, parseSourceQualifiedRegistrySourcePatternParts, } from "@agentxm/extension-model/unstable/extensions";
5
+ import { parseMinimumReleaseAge } from "@agentxm/registry-protocol/unstable/registry/release-age-policy";
6
+ import { resolveSource, SourceHostProviders, WorkspaceCatalog } from "@agentxm/extension-sources";
7
+ import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
8
+ import { WorkspaceMutations } from "@agentxm/workspace-state";
9
+ import { ExtensionLifecycleFailed } from "./errors.js";
10
+ import { LifecycleFailureAdapter } from "./failure-adapter.js";
11
+ import { acceptedResolutionRef } from "@agentxm/workspace-state";
12
+ import { resolveWorkspaceExtensionRef } from "@agentxm/workspace-state";
13
+ export const makeConfiguredReleaseAgeEvaluation = (mode) => Effect.gen(function* () {
14
+ const ws = yield* WorkspaceMutations;
15
+ const configured = yield* ws.getMinimumReleaseAge();
16
+ const minimumReleaseAge = parseMinimumReleaseAge(configured);
17
+ if (Option.isNone(minimumReleaseAge)) {
18
+ return yield* new ExtensionLifecycleFailed({
19
+ category: "validation",
20
+ detail: `Invalid minimumReleaseAge "${configured}"`,
21
+ recover: "Use a duration such as 24h, 1440m, or 0s.",
22
+ });
23
+ }
24
+ const evaluatedAt = yield* DateTime.now;
25
+ const exclude = yield* ws.getMinimumReleaseAgeExclude();
26
+ return {
27
+ minimumReleaseAge: minimumReleaseAge.value,
28
+ evaluatedAt,
29
+ mode,
30
+ exclude,
31
+ };
32
+ });
33
+ const releaseAgeRecord = (args) => ({
34
+ reason: "minimum-release-age",
35
+ target: args.target,
36
+ dependencyPath: [args.target],
37
+ ...(Option.isSome(args.versionRange) ? { requestedRange: args.versionRange.value } : {}),
38
+ ...(args.selectedVersion === undefined ? {} : { selectedVersion: args.selectedVersion }),
39
+ candidateVersion: args.evidence.version,
40
+ publishedAt: args.evidence.publishedAt,
41
+ eligibleAt: args.evidence.eligibleAt,
42
+ minimumReleaseAgeSeconds: args.evidence.minimumReleaseAgeSeconds,
43
+ });
44
+ const configuredRegistryResolution = (resolution) => Effect.gen(function* () {
45
+ if (resolution.kind === "not_found") {
46
+ return yield* new ExtensionLifecycleFailed({
47
+ category: "not_found",
48
+ detail: `Configured extension "${resolution.target}" could not be found in its source`,
49
+ suggestions: [{ description: "Verify the configured source or update axm.json." }],
50
+ });
51
+ }
52
+ if (resolution.kind === "version_unsatisfied") {
53
+ return yield* new ExtensionLifecycleFailed({
54
+ category: "conflict",
55
+ title: "No compatible version",
56
+ detail: `${resolution.target} has no visible version satisfying ${resolution.requestedRange}`,
57
+ });
58
+ }
59
+ if (resolution.kind === "policy_held") {
60
+ return yield* new ExtensionLifecycleFailed({
61
+ category: "conflict",
62
+ title: "Release held by minimum release age",
63
+ detail: `${resolution.target}@${resolution.candidate.version} is held by the minimum release age until ${resolution.candidate.eligibleAt}`,
64
+ });
65
+ }
66
+ const holdbacks = resolution.kind === "exempted" || resolution.newerHeld === undefined
67
+ ? []
68
+ : [
69
+ releaseAgeRecord({
70
+ target: resolution.target,
71
+ versionRange: resolution.versionRange,
72
+ evidence: resolution.newerHeld,
73
+ selectedVersion: resolution.ref.version,
74
+ }),
75
+ ];
76
+ const bypasses = resolution.kind === "selected"
77
+ ? []
78
+ : [
79
+ {
80
+ ...releaseAgeRecord({
81
+ target: resolution.target,
82
+ versionRange: resolution.versionRange,
83
+ evidence: resolution.bypassed,
84
+ selectedVersion: resolution.ref.version,
85
+ }),
86
+ ...resolution.exemption,
87
+ },
88
+ ];
89
+ return {
90
+ ref: resolution.ref,
91
+ versionRange: resolution.versionRange,
92
+ ...(holdbacks.length === 0 && bypasses.length === 0
93
+ ? {}
94
+ : { releaseAge: { holdbacks, bypasses } }),
95
+ };
96
+ });
97
+ const resolveConfiguredRegistryRef = (name, source, expectedType, releaseAgeEvaluation) => resolveConfiguredRegistryEntry(name, source, expectedType, releaseAgeEvaluation).pipe(Effect.flatMap(Option.match({
98
+ onNone: () => Effect.succeed(Option.none()),
99
+ onSome: (resolution) => configuredRegistryResolution(resolution).pipe(Effect.map(Option.some)),
100
+ })));
101
+ export const resolveConfiguredRegistryEntry = (name, source, expectedType, releaseAgeEvaluation) => Effect.gen(function* () {
102
+ if (isWorkspaceSourceLocator(source))
103
+ return Option.none();
104
+ const adapter = yield* LifecycleFailureAdapter;
105
+ const resolvedSource = yield* resolveSource(source, { expectedType }).pipe(Effect.mapError((failure) => new ExtensionLifecycleFailed({
106
+ category: "validation",
107
+ detail: `Invalid ${expectedType} source for ${name}: ${adapter.describeFailure(failure)}`,
108
+ cause: failure,
109
+ })));
110
+ if (resolvedSource.type !== "registry")
111
+ return Option.none();
112
+ const parsedPattern = parseSourceQualifiedRegistrySourcePatternParts(source);
113
+ const pluralType = parsedPattern?.type;
114
+ const expectedPlural = expectedType === "mcp-server"
115
+ ? "mcps"
116
+ : expectedType === "knowledge"
117
+ ? "knowledge"
118
+ : `${expectedType}s`;
119
+ if (pluralType !== undefined && pluralType !== expectedPlural) {
120
+ return yield* new ExtensionLifecycleFailed({
121
+ category: "validation",
122
+ detail: `Configured ${expectedType} "${name}" uses a ${pluralType} Registry source`,
123
+ });
124
+ }
125
+ if (parsedPattern?.name !== undefined && parsedPattern.name !== name) {
126
+ return yield* new ExtensionLifecycleFailed({
127
+ category: "validation",
128
+ detail: `Configured ${expectedType} "${name}" points to Registry extension "${parsedPattern.name}"`,
129
+ });
130
+ }
131
+ const owner = parsedPattern?.owner ?? Option.getOrUndefined(resolvedSource.owner);
132
+ if (owner === undefined) {
133
+ return yield* new ExtensionLifecycleFailed({
134
+ category: "validation",
135
+ detail: `Configured Registry source for ${expectedType} "${name}" must include an owner`,
136
+ });
137
+ }
138
+ const versionRange = Option.fromUndefinedOr(parsedPattern?.versionRange);
139
+ const workspace = yield* WorkspaceMutations;
140
+ const acceptedRef = yield* acceptedResolutionRef({
141
+ workspace,
142
+ type: expectedType,
143
+ name,
144
+ });
145
+ const accepted = Option.flatMap(acceptedRef, (ref) => ref.refType === "registry" && ref.owner === owner && ref.name === name
146
+ ? Option.some({
147
+ version: ref.version,
148
+ publisherBindingId: ref.publisherBindingId,
149
+ })
150
+ : Option.none());
151
+ const providers = yield* SourceHostProviders;
152
+ const resolution = yield* providers.resolveNamedRegistry(resolvedSource, {
153
+ name,
154
+ type: expectedType,
155
+ owner,
156
+ versionRange,
157
+ releaseAgeEvaluation,
158
+ ...(Option.isSome(accepted) ? { accepted: accepted.value } : {}),
159
+ });
160
+ const acceptedVersion = Option.isSome(accepted) &&
161
+ (resolution.kind === "selected" || resolution.kind === "exempted") &&
162
+ resolution.ref.version === accepted.value.version &&
163
+ resolution.ref.publisherBindingId === accepted.value.publisherBindingId
164
+ ? accepted.value.version
165
+ : undefined;
166
+ return Option.some({
167
+ ...resolution,
168
+ versionRange,
169
+ ...(acceptedVersion === undefined ? {} : { acceptedVersion }),
170
+ });
171
+ });
172
+ export const resolveConfiguredSkill = (name, source, releaseAgeEvaluation) => Effect.gen(function* () {
173
+ if (isWorkspaceSourceLocator(source)) {
174
+ const ws = yield* WorkspaceMutations;
175
+ const ref = yield* resolveWorkspaceExtensionRef({
176
+ settingsName: name,
177
+ source,
178
+ expectedType: "skill",
179
+ layout: ws.layout,
180
+ scope: ws.scope,
181
+ });
182
+ if (ref.type !== "skill") {
183
+ return yield* new ExtensionLifecycleFailed({
184
+ category: "internal",
185
+ detail: `Workspace skill resolution returned ${ref.type}`,
186
+ });
187
+ }
188
+ return { ref, versionRange: Option.none() };
189
+ }
190
+ const registry = yield* resolveConfiguredRegistryRef(name, source, "skill", releaseAgeEvaluation);
191
+ if (Option.isSome(registry)) {
192
+ if (registry.value.ref.type !== "skill") {
193
+ return yield* new ExtensionLifecycleFailed({
194
+ category: "internal",
195
+ detail: "Registry returned a non-skill",
196
+ });
197
+ }
198
+ return { ...registry.value, ref: registry.value.ref };
199
+ }
200
+ const providers = yield* SourceHostProviders;
201
+ const resolvedSource = yield* resolveSource(source, { expectedType: "skill" }).pipe(Effect.mapError((cause) => new ExtensionLifecycleFailed({
202
+ category: "validation",
203
+ detail: `Invalid skill source for ${name}: ${cause.detail}`,
204
+ cause,
205
+ })));
206
+ const parsedPattern = parseSourceQualifiedRegistrySourcePatternParts(source);
207
+ const requestedOwner = parsedPattern?.type === "skills"
208
+ ? Option.some(parsedPattern.owner)
209
+ : resolvedSource.type === "registry"
210
+ ? resolvedSource.owner
211
+ : Option.none();
212
+ const versionRange = resolvedSource.type === "registry" && parsedPattern?.type === "skills"
213
+ ? Option.fromUndefinedOr(parsedPattern.versionRange)
214
+ : Option.none();
215
+ const refs = yield* providers
216
+ .find(resolvedSource, {
217
+ names: [name],
218
+ type: "skill",
219
+ owner: requestedOwner,
220
+ versionRange,
221
+ })
222
+ .pipe(Effect.map((entries) => entries.filter((entry) => entry.type === "skill")), Effect.mapError((cause) => new ExtensionLifecycleFailed({
223
+ category: "internal",
224
+ detail: `Failed to resolve configured skill "${name}"`,
225
+ suggestions: [
226
+ {
227
+ description: `Verify the configured source is reachable and still contains the skill.`,
228
+ },
229
+ ],
230
+ cause,
231
+ })));
232
+ const ref = refs.find((entry) => entry.skill.name === name);
233
+ if (ref === undefined) {
234
+ return yield* new ExtensionLifecycleFailed({
235
+ category: "not_found",
236
+ detail: `Configured skill "${name}" could not be found in its source`,
237
+ suggestions: [
238
+ {
239
+ description: `Verify the configured source still contains the skill or update axm.json.`,
240
+ },
241
+ ],
242
+ });
243
+ }
244
+ return {
245
+ ref,
246
+ versionRange: ref.refType === "registry" ? versionRange : Option.none(),
247
+ };
248
+ });
249
+ export const resolveConfiguredSubagent = (name, source, releaseAgeEvaluation) => Effect.gen(function* () {
250
+ if (isWorkspaceSourceLocator(source)) {
251
+ const ws = yield* WorkspaceMutations;
252
+ const ref = yield* resolveWorkspaceExtensionRef({
253
+ settingsName: name,
254
+ source,
255
+ expectedType: "subagent",
256
+ layout: ws.layout,
257
+ scope: ws.scope,
258
+ });
259
+ if (ref.type !== "subagent") {
260
+ return yield* new ExtensionLifecycleFailed({
261
+ category: "internal",
262
+ detail: `Workspace subagent resolution returned ${ref.type}`,
263
+ });
264
+ }
265
+ return { ref, versionRange: Option.none() };
266
+ }
267
+ const registry = yield* resolveConfiguredRegistryRef(name, source, "subagent", releaseAgeEvaluation);
268
+ if (Option.isSome(registry)) {
269
+ if (registry.value.ref.type !== "subagent") {
270
+ return yield* new ExtensionLifecycleFailed({
271
+ category: "internal",
272
+ detail: "Registry returned a non-subagent",
273
+ });
274
+ }
275
+ return { ...registry.value, ref: registry.value.ref };
276
+ }
277
+ const providers = yield* SourceHostProviders;
278
+ const resolvedSource = yield* resolveSource(source, { expectedType: "subagent" }).pipe(Effect.mapError((cause) => new ExtensionLifecycleFailed({
279
+ category: "validation",
280
+ detail: `Invalid subagent source for ${name}: ${cause.detail}`,
281
+ cause,
282
+ })));
283
+ const parsedPattern = parseSourceQualifiedRegistrySourcePatternParts(source);
284
+ const requestedOwner = parsedPattern?.type === "subagents"
285
+ ? Option.some(parsedPattern.owner)
286
+ : resolvedSource.type === "registry"
287
+ ? resolvedSource.owner
288
+ : Option.none();
289
+ const versionRange = resolvedSource.type === "registry" && parsedPattern?.type === "subagents"
290
+ ? Option.fromUndefinedOr(parsedPattern.versionRange)
291
+ : Option.none();
292
+ const refs = yield* providers
293
+ .find(resolvedSource, {
294
+ names: [name],
295
+ type: "subagent",
296
+ owner: requestedOwner,
297
+ versionRange,
298
+ })
299
+ .pipe(Effect.map((entries) => entries.filter((entry) => entry.type === "subagent")), Effect.mapError((cause) => new ExtensionLifecycleFailed({
300
+ category: "internal",
301
+ detail: `Failed to resolve configured subagent "${name}"`,
302
+ suggestions: [
303
+ {
304
+ description: `Verify the configured source is reachable and still contains the subagent.`,
305
+ },
306
+ ],
307
+ cause,
308
+ })));
309
+ const ref = refs.find((entry) => entry.subagent.name === name);
310
+ if (ref === undefined) {
311
+ return yield* new ExtensionLifecycleFailed({
312
+ category: "not_found",
313
+ detail: `Configured subagent "${name}" could not be found in its source`,
314
+ suggestions: [
315
+ {
316
+ description: `Verify the configured source still contains the subagent or update axm.json.`,
317
+ },
318
+ ],
319
+ });
320
+ }
321
+ return {
322
+ ref,
323
+ versionRange: ref.refType === "registry" ? versionRange : Option.none(),
324
+ };
325
+ });
326
+ export const resolveConfiguredRule = (name, source, releaseAgeEvaluation) => Effect.gen(function* () {
327
+ if (isWorkspaceSourceLocator(source)) {
328
+ const ws = yield* WorkspaceMutations;
329
+ const ref = yield* resolveWorkspaceExtensionRef({
330
+ settingsName: name,
331
+ source,
332
+ expectedType: "rule",
333
+ layout: ws.layout,
334
+ scope: ws.scope,
335
+ });
336
+ if (ref.type !== "rule") {
337
+ return yield* new ExtensionLifecycleFailed({
338
+ category: "internal",
339
+ detail: `Workspace rule resolution returned ${ref.type}`,
340
+ });
341
+ }
342
+ return { ref, versionRange: Option.none() };
343
+ }
344
+ const registry = yield* resolveConfiguredRegistryRef(name, source, "rule", releaseAgeEvaluation);
345
+ if (Option.isSome(registry)) {
346
+ if (registry.value.ref.type !== "rule") {
347
+ return yield* new ExtensionLifecycleFailed({
348
+ category: "internal",
349
+ detail: "Registry returned a non-rule",
350
+ });
351
+ }
352
+ return { ...registry.value, ref: registry.value.ref };
353
+ }
354
+ const providers = yield* SourceHostProviders;
355
+ const resolvedSource = yield* resolveSource(source, { expectedType: "rule" }).pipe(Effect.mapError((cause) => new ExtensionLifecycleFailed({
356
+ category: "validation",
357
+ detail: `Invalid rule source for ${name}: ${cause.detail}`,
358
+ cause,
359
+ })));
360
+ const parsedPattern = parseSourceQualifiedRegistrySourcePatternParts(source);
361
+ const requestedOwner = parsedPattern?.type === "rules"
362
+ ? Option.some(parsedPattern.owner)
363
+ : resolvedSource.type === "registry"
364
+ ? resolvedSource.owner
365
+ : Option.none();
366
+ const versionRange = resolvedSource.type === "registry" && parsedPattern?.type === "rules"
367
+ ? Option.fromUndefinedOr(parsedPattern.versionRange)
368
+ : Option.none();
369
+ const refs = yield* providers
370
+ .find(resolvedSource, {
371
+ names: [name],
372
+ type: "rule",
373
+ owner: requestedOwner,
374
+ versionRange,
375
+ })
376
+ .pipe(Effect.map((entries) => entries.filter((entry) => entry.type === "rule")), Effect.mapError((cause) => new ExtensionLifecycleFailed({
377
+ category: "internal",
378
+ detail: `Failed to resolve configured rule "${name}"`,
379
+ suggestions: [
380
+ {
381
+ description: "Verify the configured source is reachable and still contains the rule.",
382
+ },
383
+ ],
384
+ cause,
385
+ })));
386
+ const ref = refs.find((entry) => entry.rule.name === name);
387
+ if (ref === undefined) {
388
+ return yield* new ExtensionLifecycleFailed({
389
+ category: "not_found",
390
+ detail: `Configured rule "${name}" could not be found in its source`,
391
+ suggestions: [
392
+ {
393
+ description: "Verify the configured source still contains the rule or update axm.json.",
394
+ },
395
+ ],
396
+ });
397
+ }
398
+ return {
399
+ ref,
400
+ versionRange: ref.refType === "registry" ? versionRange : Option.none(),
401
+ };
402
+ });
403
+ export const resolveConfiguredHook = (name, source, releaseAgeEvaluation) => Effect.gen(function* () {
404
+ if (isWorkspaceSourceLocator(source)) {
405
+ const ws = yield* WorkspaceMutations;
406
+ const ref = yield* resolveWorkspaceExtensionRef({
407
+ settingsName: name,
408
+ source,
409
+ expectedType: "hook",
410
+ layout: ws.layout,
411
+ scope: ws.scope,
412
+ });
413
+ if (ref.type !== "hook") {
414
+ return yield* new ExtensionLifecycleFailed({
415
+ category: "internal",
416
+ detail: `Workspace hook resolution returned ${ref.type}`,
417
+ });
418
+ }
419
+ return { ref, versionRange: Option.none() };
420
+ }
421
+ const registry = yield* resolveConfiguredRegistryRef(name, source, "hook", releaseAgeEvaluation);
422
+ if (Option.isSome(registry)) {
423
+ if (registry.value.ref.type !== "hook") {
424
+ return yield* new ExtensionLifecycleFailed({
425
+ category: "internal",
426
+ detail: "Registry returned a non-hook",
427
+ });
428
+ }
429
+ return { ...registry.value, ref: registry.value.ref };
430
+ }
431
+ const providers = yield* SourceHostProviders;
432
+ const resolvedSource = yield* resolveSource(source, { expectedType: "hook" }).pipe(Effect.mapError((cause) => new ExtensionLifecycleFailed({
433
+ category: "validation",
434
+ detail: `Invalid hook source for ${name}: ${cause.detail}`,
435
+ cause,
436
+ })));
437
+ const parsedPattern = parseSourceQualifiedRegistrySourcePatternParts(source);
438
+ const requestedOwner = parsedPattern?.type === "hooks"
439
+ ? Option.some(parsedPattern.owner)
440
+ : resolvedSource.type === "registry"
441
+ ? resolvedSource.owner
442
+ : Option.none();
443
+ const versionRange = resolvedSource.type === "registry" && parsedPattern?.type === "hooks"
444
+ ? Option.fromUndefinedOr(parsedPattern.versionRange)
445
+ : Option.none();
446
+ const refs = yield* providers
447
+ .find(resolvedSource, {
448
+ names: [name],
449
+ type: "hook",
450
+ owner: requestedOwner,
451
+ versionRange,
452
+ })
453
+ .pipe(Effect.map((entries) => entries.filter((entry) => entry.type === "hook")), Effect.mapError((cause) => new ExtensionLifecycleFailed({
454
+ category: "internal",
455
+ detail: `Failed to resolve configured hook "${name}"`,
456
+ suggestions: [
457
+ {
458
+ description: "Verify the configured source is reachable and still contains the hook.",
459
+ },
460
+ ],
461
+ cause,
462
+ })));
463
+ const ref = refs.find((entry) => entry.hook.name === name);
464
+ if (ref === undefined) {
465
+ return yield* new ExtensionLifecycleFailed({
466
+ category: "not_found",
467
+ detail: `Configured hook "${name}" could not be found in its source`,
468
+ suggestions: [
469
+ {
470
+ description: "Verify the configured source still contains the hook or update axm.json.",
471
+ },
472
+ ],
473
+ });
474
+ }
475
+ return {
476
+ ref,
477
+ versionRange: ref.refType === "registry" ? versionRange : Option.none(),
478
+ };
479
+ });
480
+ export const resolveConfiguredKnowledge = (name, source, releaseAgeEvaluation) => Effect.gen(function* () {
481
+ if (isWorkspaceSourceLocator(source)) {
482
+ const ws = yield* WorkspaceMutations;
483
+ const ref = yield* resolveWorkspaceExtensionRef({
484
+ settingsName: name,
485
+ source,
486
+ expectedType: "knowledge",
487
+ layout: ws.layout,
488
+ scope: ws.scope,
489
+ });
490
+ if (ref.type !== "knowledge") {
491
+ return yield* new ExtensionLifecycleFailed({
492
+ category: "internal",
493
+ detail: `Workspace knowledge resolution returned ${ref.type}`,
494
+ });
495
+ }
496
+ return { ref, versionRange: Option.none() };
497
+ }
498
+ const registry = yield* resolveConfiguredRegistryRef(name, source, "knowledge", releaseAgeEvaluation);
499
+ if (Option.isSome(registry)) {
500
+ if (registry.value.ref.type !== "knowledge") {
501
+ return yield* new ExtensionLifecycleFailed({
502
+ category: "internal",
503
+ detail: "Registry returned non-knowledge content",
504
+ });
505
+ }
506
+ return { ...registry.value, ref: registry.value.ref };
507
+ }
508
+ const providers = yield* SourceHostProviders;
509
+ const resolvedSource = yield* resolveSource(source, { expectedType: "knowledge" }).pipe(Effect.mapError((cause) => new ExtensionLifecycleFailed({
510
+ category: "validation",
511
+ detail: `Invalid knowledge source for ${name}: ${cause.detail}`,
512
+ cause,
513
+ })));
514
+ const parsedPattern = parseSourceQualifiedRegistrySourcePatternParts(source);
515
+ const requestedOwner = parsedPattern?.type === "knowledge"
516
+ ? Option.some(parsedPattern.owner)
517
+ : resolvedSource.type === "registry"
518
+ ? resolvedSource.owner
519
+ : Option.none();
520
+ const versionRange = resolvedSource.type === "registry" && parsedPattern?.type === "knowledge"
521
+ ? Option.fromUndefinedOr(parsedPattern.versionRange)
522
+ : Option.none();
523
+ const refs = yield* providers
524
+ .find(resolvedSource, {
525
+ names: [name],
526
+ type: "knowledge",
527
+ owner: requestedOwner,
528
+ versionRange,
529
+ })
530
+ .pipe(Effect.map((entries) => entries.filter((entry) => entry.type === "knowledge")), Effect.mapError((cause) => new ExtensionLifecycleFailed({
531
+ category: "internal",
532
+ detail: `Failed to resolve configured knowledge bundle "${name}"`,
533
+ cause,
534
+ })));
535
+ const ref = refs.find((entry) => entry.knowledge.name === name);
536
+ if (ref === undefined) {
537
+ return yield* new ExtensionLifecycleFailed({
538
+ category: "not_found",
539
+ detail: `Configured knowledge bundle "${name}" could not be found in its source`,
540
+ });
541
+ }
542
+ return {
543
+ ref,
544
+ versionRange: ref.refType === "registry" ? versionRange : Option.none(),
545
+ };
546
+ });
547
+ export const resolveConfiguredMcpServer = (name, source, releaseAgeEvaluation) => Effect.gen(function* () {
548
+ if (isWorkspaceSourceLocator(source)) {
549
+ const ws = yield* WorkspaceMutations;
550
+ const ref = yield* resolveWorkspaceExtensionRef({
551
+ settingsName: name,
552
+ source,
553
+ expectedType: "mcp-server",
554
+ layout: ws.layout,
555
+ scope: ws.scope,
556
+ });
557
+ if (ref.type !== "mcp-server") {
558
+ return yield* new ExtensionLifecycleFailed({
559
+ category: "internal",
560
+ detail: `Workspace MCP server resolution returned ${ref.type}`,
561
+ });
562
+ }
563
+ return { ref, versionRange: Option.none() };
564
+ }
565
+ const registry = yield* resolveConfiguredRegistryRef(name, source, "mcp-server", releaseAgeEvaluation);
566
+ if (Option.isSome(registry)) {
567
+ if (registry.value.ref.type !== "mcp-server") {
568
+ return yield* new ExtensionLifecycleFailed({
569
+ category: "internal",
570
+ detail: "Registry returned a non-MCP-server",
571
+ });
572
+ }
573
+ return { ...registry.value, ref: registry.value.ref };
574
+ }
575
+ const parsed = parseRegistrySourceRef(source);
576
+ if (parsed === undefined || parsed.type !== "mcps" || parsed.name !== name) {
577
+ return yield* new ExtensionLifecycleFailed({
578
+ category: "validation",
579
+ detail: `The configured MCP server entry "${name}" is invalid.`,
580
+ suggestions: [{ description: `Use a name like "@owner/mcps/name".` }],
581
+ });
582
+ }
583
+ const providers = yield* SourceHostProviders;
584
+ const versionRange = Option.fromUndefinedOr(parsed.versionRange);
585
+ const resolvedSource = yield* resolveSource(source, { expectedType: "mcp-server" }).pipe(Effect.mapError((cause) => new ExtensionLifecycleFailed({
586
+ category: "validation",
587
+ detail: `Invalid MCP server source for ${name}: ${cause.detail}`,
588
+ cause,
589
+ })));
590
+ const refs = yield* providers
591
+ .find(resolvedSource, {
592
+ names: [name],
593
+ type: "mcp-server",
594
+ owner: Option.some(parsed.owner),
595
+ versionRange,
596
+ })
597
+ .pipe(Effect.map((entries) => entries.filter((entry) => entry.type === "mcp-server")), Effect.mapError((cause) => new ExtensionLifecycleFailed({
598
+ category: "internal",
599
+ detail: `Failed to resolve configured MCP server "${name}"`,
600
+ suggestions: [
601
+ {
602
+ description: `Verify the configured registry source is reachable and still contains the MCP server.`,
603
+ },
604
+ ],
605
+ cause,
606
+ })));
607
+ const ref = refs.find((entry) => entry.server.name === name);
608
+ if (ref === undefined) {
609
+ return yield* new ExtensionLifecycleFailed({
610
+ category: "not_found",
611
+ detail: `Configured MCP server "${name}" could not be found in its source`,
612
+ suggestions: [
613
+ {
614
+ description: `Verify the configured source still contains the MCP server or update axm.json.`,
615
+ },
616
+ ],
617
+ });
618
+ }
619
+ return {
620
+ ref,
621
+ versionRange,
622
+ };
623
+ });
624
+ export const resolveConfiguredPack = (name, source, releaseAgeEvaluation) => Effect.gen(function* () {
625
+ if (isWorkspaceSourceLocator(source)) {
626
+ const ws = yield* WorkspaceMutations;
627
+ const ref = yield* resolveWorkspaceExtensionRef({
628
+ settingsName: name,
629
+ source,
630
+ expectedType: "pack",
631
+ layout: ws.layout,
632
+ scope: ws.scope,
633
+ });
634
+ if (ref.type !== "pack") {
635
+ return yield* new ExtensionLifecycleFailed({
636
+ category: "internal",
637
+ detail: `Workspace pack resolution returned ${ref.type}`,
638
+ });
639
+ }
640
+ return { ref, versionRange: Option.none() };
641
+ }
642
+ const registry = yield* resolveConfiguredRegistryRef(name, source, "pack", releaseAgeEvaluation);
643
+ if (Option.isSome(registry)) {
644
+ if (registry.value.ref.type !== "pack") {
645
+ return yield* new ExtensionLifecycleFailed({
646
+ category: "internal",
647
+ detail: "Registry returned a non-pack",
648
+ });
649
+ }
650
+ return { ...registry.value, ref: registry.value.ref };
651
+ }
652
+ const parsed = parseRegistrySourceRef(source);
653
+ if (parsed === undefined || parsed.type !== "packs" || parsed.name !== name) {
654
+ return yield* new ExtensionLifecycleFailed({
655
+ category: "validation",
656
+ detail: `The configured pack entry "${name}" is invalid.`,
657
+ suggestions: [{ description: `Use a name like "@owner/packs/name".` }],
658
+ });
659
+ }
660
+ const providers = yield* SourceHostProviders;
661
+ const versionRange = Option.fromUndefinedOr(parsed.versionRange);
662
+ const resolvedSource = yield* resolveSource(source, { expectedType: "pack" }).pipe(Effect.mapError((cause) => new ExtensionLifecycleFailed({
663
+ category: "validation",
664
+ detail: `Invalid pack source for ${name}: ${cause.detail}`,
665
+ cause,
666
+ })));
667
+ const findWith = (candidate) => providers.find(candidate, {
668
+ names: [name],
669
+ type: "pack",
670
+ owner: Option.some(parsed.owner),
671
+ versionRange,
672
+ });
673
+ const refs = yield* findWith(resolvedSource).pipe(Effect.map((entries) => entries.filter((entry) => entry.type === "pack")), Effect.catch((error) => resolvedSource.type === "registry"
674
+ ? Effect.gen(function* () {
675
+ const ws = yield* WorkspaceMutations;
676
+ const registryHosts = yield* ws.getRegistrySourceHosts();
677
+ const fallbackSources = registryHosts
678
+ .filter((host) => host.location.protocol === "file:")
679
+ .map((host) => ({
680
+ type: "registry",
681
+ name: host.name,
682
+ location: host.location,
683
+ owner: Option.some(parsed.owner),
684
+ }));
685
+ for (const fallback of fallbackSources) {
686
+ if (fallback.location.href === resolvedSource.location.href) {
687
+ continue;
688
+ }
689
+ const fallbackResult = yield* findWith(fallback).pipe(Effect.result);
690
+ if (fallbackResult._tag === "Success" && fallbackResult.success.length > 0) {
691
+ return fallbackResult.success.filter((entry) => entry.type === "pack");
692
+ }
693
+ }
694
+ return yield* error;
695
+ })
696
+ : Effect.fail(error)), Effect.mapError((cause) => new ExtensionLifecycleFailed({
697
+ category: "internal",
698
+ detail: `Failed to resolve configured pack "${name}"`,
699
+ suggestions: [
700
+ {
701
+ description: "Verify the configured registry source is reachable and still contains the pack.",
702
+ },
703
+ ],
704
+ cause,
705
+ })));
706
+ const ref = refs.find((entry) => entry.pack.name === name);
707
+ if (ref === undefined) {
708
+ return yield* new ExtensionLifecycleFailed({
709
+ category: "not_found",
710
+ detail: `Configured pack "${name}" could not be found in its source`,
711
+ suggestions: [
712
+ {
713
+ description: "Verify the configured source still contains the pack or update axm.json.",
714
+ },
715
+ ],
716
+ });
717
+ }
718
+ return {
719
+ ref,
720
+ versionRange,
721
+ };
722
+ });
723
+ //# sourceMappingURL=configured-entry-resolution.js.map