@agentxm/extension-lifecycle 0.28.12 → 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,72 +0,0 @@
1
- /**
2
- * Registry-backed canonical package materialization.
3
- *
4
- * The canonical-directory staging/swap machinery lives in
5
- * `@agentxm/extension-workspace`; this module owns only the registry
6
- * fetch/verify/extract path.
7
- *
8
- * @experimental This API is unstable and may change without notice.
9
- */
10
- import * as Effect from "effect/Effect";
11
- import * as FileSystem from "effect/FileSystem";
12
- import * as Option from "effect/Option";
13
- import * as Path from "effect/Path";
14
- import * as HttpClient from "effect/unstable/http/HttpClient";
15
- import { createRegistryClient, extractZip } from "@agentxm/registry-client";
16
- import { computeIntegrity } from "./internal/integrity.js";
17
- import { ArchiveIntegrityMismatch, recoverCanonicalDirectory, replaceCanonicalDirectoryWithInspection, } from "@agentxm/extension-workspace";
18
- import { CoupledDependencyFailure } from "@agentxm/extension-workspace";
19
- import { coupleLifecycleDependencyFailure } from "./errors.js";
20
- import { makeThrottledUnitProgress } from "@agentxm/workspace-operations";
21
- import { computeMaterializedTreeIntegrity, } from "@agentxm/workspace-state";
22
- const registryLocationForClient = (location) => location.protocol === "file:" ? location.pathname : location.href;
23
- /**
24
- * Fetch, verify, and extract a registry package into `destinationPath`.
25
- *
26
- * Always writes. Whether new bytes are needed at all is
27
- * `canReuseInstalledPackage`'s decision, which the caller makes against the
28
- * canonical installed path before choosing a destination.
29
- *
30
- * Registry client and archive-extraction failures travel opaquely as coupled
31
- * dependency failures; the application boundary restores and converts them.
32
- */
33
- export const materializeRegistryPackageWithTreeIntegrity = (args) => Effect.gen(function* () {
34
- yield* recoverCanonicalDirectory({
35
- baseDir: args.baseDir,
36
- canonicalPath: args.destinationPath,
37
- });
38
- const client = yield* createRegistryClient(registryLocationForClient(args.sourceLocation));
39
- // Continuous download progress reaches the lifecycle broadcast throttled:
40
- // tens of events per archive, attributed to the unit that is running.
41
- const reportProgress = yield* makeThrottledUnitProgress({ unit: "bytes" });
42
- const { archive } = yield* client
43
- .getExtensionPackage({
44
- owner: args.owner,
45
- type: args.type,
46
- name: args.name,
47
- version: Option.some(args.version),
48
- onProgress: (progress) => reportProgress(progress.done, progress.total),
49
- })
50
- .pipe(Effect.mapError(coupleLifecycleDependencyFailure));
51
- if (Option.isSome(args.integrity)) {
52
- const actualIntegrity = yield* computeIntegrity(archive);
53
- if (actualIntegrity !== args.integrity.value) {
54
- return yield* new ArchiveIntegrityMismatch({
55
- subject: args.messages.integrityMismatchDetail,
56
- });
57
- }
58
- }
59
- const result = yield* replaceCanonicalDirectoryWithInspection({
60
- baseDir: args.baseDir,
61
- canonicalPath: args.destinationPath,
62
- populate: (stagingPath) => extractZip(archive, stagingPath).pipe(Effect.mapError(coupleLifecycleDependencyFailure)),
63
- ...(args.validate === undefined ? {} : { validate: args.validate }),
64
- inspect: computeMaterializedTreeIntegrity,
65
- });
66
- return {
67
- canonicalPath: result.canonicalPath,
68
- treeIntegrity: result.inspection,
69
- };
70
- });
71
- export const materializeRegistryPackage = (args) => materializeRegistryPackageWithTreeIntegrity(args).pipe(Effect.map(({ canonicalPath }) => canonicalPath));
72
- //# sourceMappingURL=registry-materialization.js.map
@@ -1,23 +0,0 @@
1
- /**
2
- * The minimum-release-age gate's posture for one invocation.
3
- *
4
- * A leaf cannot invent this value: `makeConfiguredReleaseAgeEvaluation` reads
5
- * it from context, so every gated code path carries the requirement up to the
6
- * command boundary that owns the operator's decision. A command is
7
- * gate-blockable precisely when its execution requests this service, which is
8
- * what the conformance specification reads instead of a hand-copied list.
9
- *
10
- * @experimental This API is unstable and may change without notice.
11
- */
12
- import * as ServiceMap from "effect/Context";
13
- /**
14
- * `"enforce"` withholds a candidate that has not reached the configured
15
- * minimum release age; `"ignore"` takes it for this run only. Neither value
16
- * changes settings, and a declared exemption outranks both.
17
- */
18
- export type ReleaseAgePostureValue = "enforce" | "ignore";
19
- declare const ReleaseAgePosture_base: ServiceMap.ServiceClass<ReleaseAgePosture, "axm.sh/extension-lifecycle/ReleaseAgePosture", ReleaseAgePostureValue>;
20
- export declare class ReleaseAgePosture extends ReleaseAgePosture_base {
21
- }
22
- export {};
23
- //# sourceMappingURL=release-age-posture.d.ts.map
@@ -1,15 +0,0 @@
1
- /**
2
- * The minimum-release-age gate's posture for one invocation.
3
- *
4
- * A leaf cannot invent this value: `makeConfiguredReleaseAgeEvaluation` reads
5
- * it from context, so every gated code path carries the requirement up to the
6
- * command boundary that owns the operator's decision. A command is
7
- * gate-blockable precisely when its execution requests this service, which is
8
- * what the conformance specification reads instead of a hand-copied list.
9
- *
10
- * @experimental This API is unstable and may change without notice.
11
- */
12
- import * as ServiceMap from "effect/Context";
13
- export class ReleaseAgePosture extends ServiceMap.Service()("axm.sh/extension-lifecycle/ReleaseAgePosture") {
14
- }
15
- //# sourceMappingURL=release-age-posture.js.map
@@ -1,5 +0,0 @@
1
- import * as Effect from "effect/Effect";
2
- import { ExtensionLifecycleFailed } from "./errors.js";
3
- export declare const CONFIGURED_ENTRY_RESOLUTION_TIMEOUT = "2 seconds";
4
- export declare const withConfiguredEntryResolutionTimeout: (_source: string) => <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, ExtensionLifecycleFailed | E, R>;
5
- //# sourceMappingURL=resolution-timeout.d.ts.map
@@ -1,11 +0,0 @@
1
- import * as Effect from "effect/Effect";
2
- import { ExtensionLifecycleFailed } from "./errors.js";
3
- export const CONFIGURED_ENTRY_RESOLUTION_TIMEOUT = "2 seconds";
4
- export const withConfiguredEntryResolutionTimeout = (_source) => (effect) => effect.pipe(Effect.timeoutOrElse({
5
- duration: CONFIGURED_ENTRY_RESOLUTION_TIMEOUT,
6
- orElse: () => Effect.fail(new ExtensionLifecycleFailed({
7
- category: "network",
8
- detail: "Timed out while resolving a configured extension source",
9
- })),
10
- }));
11
- //# sourceMappingURL=resolution-timeout.js.map
@@ -1,20 +0,0 @@
1
- /**
2
- * Rule manager service.
3
- *
4
- * @experimental This API is unstable and may change without notice.
5
- */
6
- import * as FileSystem from "effect/FileSystem";
7
- import * as HttpClient from "effect/unstable/http/HttpClient";
8
- import * as Layer from "effect/Layer";
9
- import * as Path from "effect/Path";
10
- import { RuleManager } from "@agentxm/extension-workspace";
11
- import { SourceHostProviders, WorkspaceCatalog } from "@agentxm/extension-sources";
12
- import type { MaterializationObservation } from "@agentxm/extension-workspace";
13
- import { WorkspaceMutations } from "@agentxm/workspace-state";
14
- import { LifecycleFailureAdapter } from "../failure-adapter.js";
15
- export declare const ruleMaterializationObservation: (managedTarget: string, instructionItems: ReadonlyArray<{
16
- readonly agentId: string;
17
- readonly health: string;
18
- }>) => MaterializationObservation;
19
- export declare const RuleManagerLive: Layer.Layer<RuleManager, never, LifecycleFailureAdapter | SourceHostProviders | WorkspaceCatalog | WorkspaceMutations | FileSystem.FileSystem | HttpClient.HttpClient | Path.Path>;
20
- //# sourceMappingURL=manager.d.ts.map
@@ -1,480 +0,0 @@
1
- /**
2
- * Rule manager service.
3
- *
4
- * @experimental This API is unstable and may change without notice.
5
- */
6
- import * as Effect from "effect/Effect";
7
- import * as FileSystem from "effect/FileSystem";
8
- import * as HttpClient from "effect/unstable/http/HttpClient";
9
- import * as Layer from "effect/Layer";
10
- import * as Option from "effect/Option";
11
- import * as Path from "effect/Path";
12
- import * as Schema from "effect/Schema";
13
- import { RuleDefinitionInvalid, RuleInstallStateMissing, activeContributors, applyProjectionPlans, planAggregateProjection, reconcileManagedRegionFile, projectionGeneration, MARKER_KIND_POINT, MARKER_VERSION, serializeMarker, assertInstructionTargetsSafe, assertInstructionsGitignoreSafe, observeInstructionProjection, reconcileInstructionTargets, resolveInstructionsConfig, } from "@agentxm/extension-workspace";
14
- import { decodeExtensionNameSync, formatFqn } from "@agentxm/extension-model/unstable/extensions";
15
- import { canReuseInstalledPackage, enabledConfiguredEntries, materializeExternalPackageWithTreeIntegrity, } from "@agentxm/extension-workspace";
16
- import { materializeRegistryPackageWithTreeIntegrity } from "../registry-materialization.js";
17
- import { computeExtensionPathsForLayout } from "@agentxm/workspace-state";
18
- import { RULES_REGION_OWNER, RuleManager } from "@agentxm/extension-workspace";
19
- import { parseFrontmatterEffect } from "@agentxm/registry-protocol/unstable/content/frontmatter";
20
- import { computePackageContentHash } from "@agentxm/workspace-state";
21
- import { computeMaterializedTreeIntegrity } from "@agentxm/workspace-state";
22
- import {} from "@agentxm/extension-model/unstable/sources/source-hash";
23
- import { acceptedRegistryVersionForRef, validateExactResolvedVersion, } from "@agentxm/workspace-state";
24
- import { MaterializedFileTargetSchema } from "@agentxm/workspace-state";
25
- import { gitSourceLockFields } from "@agentxm/workspace-state";
26
- import { SourceHostProviders, WorkspaceCatalog } from "@agentxm/extension-sources";
27
- import { stripFileProtocol } from "../internal/fs-helpers.js";
28
- import { makeWorkspaceRelativeSourcePath } from "@agentxm/extension-model/unstable/path-types";
29
- import { removeIfExists } from "@agentxm/workspace-state";
30
- import { makeWorkspaceRelativePath } from "@agentxm/extension-model/unstable/path-types";
31
- import { decodeVersionSync } from "@agentxm/extension-model/unstable/version-constraints";
32
- import { WorkspaceMutations } from "@agentxm/workspace-state";
33
- import { usableAcceptedCanonicalRef } from "@agentxm/workspace-state";
34
- import { LifecycleFailureAdapter } from "../failure-adapter.js";
35
- import { isObservedInstalled } from "@agentxm/workspace-state";
36
- import { acceptedCanonicalObservation, prepareAcceptedCanonicalTransition, removableAcceptedCanonicalPath, } from "@agentxm/workspace-state";
37
- import { RULE_BODY_FILENAME, RULE_EXTENSION_DIR, RULE_MANIFEST_FILENAME, RuleManifestSchema, } from "@agentxm/extension-model/unstable/rules/manifest-schema";
38
- import {} from "@agentxm/extension-model/unstable/extensions/refs/rule";
39
- const RULES_REGION = "rules";
40
- const decodeRuleManifest = Schema.decodeUnknownEffect(RuleManifestSchema);
41
- const decodeMaterializedTarget = Schema.decodeUnknownSync(MaterializedFileTargetSchema);
42
- const registryRuleLockEntry = (ref, treeIntegrity) => ({
43
- type: "registry",
44
- sourceType: "registry",
45
- packageFormat: "agentxm",
46
- endpoint: ref.source.location,
47
- extensionType: "rule",
48
- workspaceName: ref.rule.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 gitRuleLockEntry = (ref, contentIdentity, treeIntegrity) => ({
58
- ...gitSourceLockFields(ref.source, "rule", ref.rule.name, Option.fromUndefinedOr(ref.sourcePath), ref.gitCommitSha, ref.gitTreeSha, contentIdentity, ref.owner, ref.name, treeIntegrity),
59
- });
60
- const localRuleLockEntry = (ref, workspaceRelativeLocalSourcePath, contentIdentity, treeIntegrity) => ({
61
- type: "local",
62
- sourceType: "local",
63
- sourceName: "local",
64
- extensionType: "rule",
65
- workspaceName: ref.rule.name,
66
- packageFormat: "agentxm",
67
- packageOwner: ref.owner,
68
- packageName: ref.name,
69
- path: Option.getOrElse(workspaceRelativeLocalSourcePath, () => ref.source.path),
70
- contentIdentity,
71
- treeIntegrity,
72
- });
73
- const normalizeMarkdown = (content) => content
74
- .replace(/\r\n?/g, "\n")
75
- .split("\n")
76
- .map((line) => line.trimEnd())
77
- .join("\n")
78
- .trim();
79
- export const ruleMaterializationObservation = (managedTarget, instructionItems) => {
80
- const agents = Array.from(new Set(instructionItems
81
- .filter(({ agentId, health }) => health === "ok" && agentId !== "universal")
82
- .map(({ agentId }) => agentId)));
83
- return {
84
- agents,
85
- targets: [
86
- {
87
- path: managedTarget,
88
- ...(agents.length === 0 ? {} : { agentIds: agents }),
89
- },
90
- ],
91
- };
92
- };
93
- export const RuleManagerLive = Layer.effect(RuleManager, Effect.gen(function* () {
94
- const ws = yield* WorkspaceMutations;
95
- const fs = yield* FileSystem.FileSystem;
96
- const httpClient = yield* HttpClient.HttpClient;
97
- const path = yield* Path.Path;
98
- const sources = yield* SourceHostProviders;
99
- const catalog = yield* WorkspaceCatalog;
100
- const adapter = yield* LifecycleFailureAdapter;
101
- const baseDir = ws.baseDir;
102
- const workspaceScope = ws.scope;
103
- const fsPathLayer = Layer.mergeAll(Layer.succeed(FileSystem.FileSystem, fs), Layer.succeed(HttpClient.HttpClient, httpClient), Layer.succeed(Path.Path, path));
104
- const envLayer = Layer.mergeAll(fsPathLayer, Layer.succeed(WorkspaceMutations, ws), Layer.succeed(SourceHostProviders, sources), Layer.succeed(WorkspaceCatalog, catalog), Layer.succeed(LifecycleFailureAdapter, adapter));
105
- const provide = (effect) => Effect.provide(effect, envLayer);
106
- const lastInstallState = new Map();
107
- let lastProjection;
108
- const materializeFromRegistry = (ref, force) => Effect.gen(function* () {
109
- const canonicalPath = computeExtensionPathsForLayout(path.join, ws.layout, ref, RULE_EXTENSION_DIR, ref.name).canonicalPath;
110
- const lockedEntry = yield* ws.getLockedRuleEntry(ref.rule.name);
111
- const lockedVersion = acceptedRegistryVersionForRef(lockedEntry, ref);
112
- const reuse = yield* provide(canReuseInstalledPackage({
113
- installedPath: canonicalPath,
114
- force,
115
- refVersion: ref.version,
116
- hasIntegrity: Option.isSome(ref.integrity),
117
- ...(lockedVersion === undefined ? {} : { lockedVersion }),
118
- existsFailureDetail: (target) => `Failed to check if canonical rule package path exists: ${target}`,
119
- }));
120
- if (reuse && Option.isSome(lockedEntry)) {
121
- const observedTree = yield* provide(computeMaterializedTreeIntegrity(canonicalPath));
122
- if (observedTree === lockedEntry.value.treeIntegrity) {
123
- return { packageRoot: canonicalPath, treeIntegrity: lockedEntry.value.treeIntegrity };
124
- }
125
- }
126
- const materialized = yield* provide(materializeRegistryPackageWithTreeIntegrity({
127
- baseDir,
128
- destinationPath: canonicalPath,
129
- sourceLocation: ref.source.location,
130
- owner: ref.owner,
131
- type: "rule",
132
- name: ref.name,
133
- version: ref.version,
134
- integrity: ref.integrity,
135
- messages: {
136
- integrityMismatchDetail: `Integrity mismatch for rule:${ref.name}@${ref.version}`,
137
- },
138
- }));
139
- return {
140
- packageRoot: materialized.canonicalPath,
141
- treeIntegrity: materialized.treeIntegrity,
142
- };
143
- });
144
- const materializeFromExternal = (ref) => provide(materializeExternalPackageWithTreeIntegrity({
145
- baseDir,
146
- canonicalPath: computeExtensionPathsForLayout(path.join, ws.layout, ref, RULE_EXTENSION_DIR, ref.rule.name).canonicalPath,
147
- sourceLocation: ref.location,
148
- copyFailureCode: "validation",
149
- copyFailureDetail: (canonicalPath) => `Failed to copy rule package files to ${canonicalPath}`,
150
- }).pipe(Effect.map((materialized) => ({
151
- packageRoot: materialized.canonicalPath,
152
- treeIntegrity: materialized.treeIntegrity,
153
- }))));
154
- const materializePackage = (ref, force = false) => Effect.gen(function* () {
155
- switch (ref.refType) {
156
- case "registry":
157
- return yield* materializeFromRegistry(ref, force);
158
- case "git-hosted":
159
- case "local":
160
- return yield* materializeFromExternal(ref);
161
- case "workspace": {
162
- const expectedPath = computeExtensionPathsForLayout(path.join, ws.layout, ref, RULE_EXTENSION_DIR, ref.name).canonicalPath;
163
- if (ref.scope !== ws.scope ||
164
- path.resolve(ref.location) !== path.resolve(expectedPath)) {
165
- return yield* new RuleDefinitionInvalid({
166
- detail: `Invalid workspace rule source location: ${ref.location}`,
167
- });
168
- }
169
- return {
170
- packageRoot: ref.location,
171
- treeIntegrity: yield* provide(computeMaterializedTreeIntegrity(ref.location)),
172
- };
173
- }
174
- }
175
- });
176
- const readManifest = (packageRoot) => fs.readFileString(path.join(packageRoot, RULE_MANIFEST_FILENAME)).pipe(Effect.flatMap((content) => Effect.try({
177
- try: () => JSON.parse(content),
178
- catch: (error) => new RuleDefinitionInvalid({
179
- detail: `Failed to parse ${RULE_MANIFEST_FILENAME}`,
180
- cause: error,
181
- }),
182
- })), Effect.flatMap((content) => decodeRuleManifest(content)), Effect.mapError((error) => new RuleDefinitionInvalid({
183
- detail: `Failed to read ${RULE_MANIFEST_FILENAME}`,
184
- cause: error,
185
- })));
186
- const sourceFileTarget = () => Effect.gen(function* () {
187
- const config = yield* ws.getInstructionsConfig();
188
- const resolved = resolveInstructionsConfig(Option.isSome(config) && config.value !== false ? config.value : undefined);
189
- const relative = makeWorkspaceRelativePath(path, baseDir, resolved.fileName);
190
- if (Option.isNone(relative)) {
191
- return yield* new RuleDefinitionInvalid({
192
- detail: `Rule instruction source escapes workspace: ${resolved.fileName}`,
193
- });
194
- }
195
- return {
196
- relative: relative.value,
197
- absolute: path.resolve(baseDir, relative.value),
198
- };
199
- });
200
- const activeInstructions = () => Effect.gen(function* () {
201
- const config = yield* ws.getInstructionsConfig();
202
- if (Option.isNone(config) || config.value === false) {
203
- return Option.none();
204
- }
205
- return Option.some({
206
- config: resolveInstructionsConfig(config.value),
207
- agents: yield* ws.getConfiguredAgents(),
208
- });
209
- });
210
- const readRuleBody = (packageRoot) => fs.readFileString(path.join(packageRoot, "src", RULE_BODY_FILENAME)).pipe(Effect.flatMap((content) => parseFrontmatterEffect(content)), Effect.map((parsed) => normalizeMarkdown(parsed.body)), Effect.mapError((error) => new RuleDefinitionInvalid({
211
- detail: `Failed to read src/${RULE_BODY_FILENAME}`,
212
- cause: error,
213
- })));
214
- const renderRuleBlock = (args) => {
215
- const header = args.manifest.title !== undefined && !args.body.startsWith("#")
216
- ? `# ${args.manifest.title}\n\n`
217
- : "";
218
- const marker = serializeMarker({
219
- kind: MARKER_KIND_POINT,
220
- v: MARKER_VERSION,
221
- pointKind: "rule",
222
- ext: `${args.marker}@${args.manifest.version}`,
223
- }, { kind: "block", open: "<!--", close: "-->" });
224
- return `${marker}\n\n${header}${args.body}`;
225
- };
226
- const selectRuleContributors = (args) => provide(activeContributors({
227
- layout: ws.layout,
228
- path,
229
- type: "rule",
230
- extensionDir: RULE_EXTENSION_DIR,
231
- graph: args.graph,
232
- locked: args.locked,
233
- })).pipe(Effect.flatMap((contributors) => Effect.forEach(contributors, (contributor) => Effect.gen(function* () {
234
- const manifest = yield* readManifest(contributor.packageRoot);
235
- const body = yield* readRuleBody(contributor.packageRoot);
236
- const marker = Option.match(contributor.identityOwner, {
237
- onSome: (owner) => formatFqn({
238
- owner,
239
- type: "rule",
240
- name: decodeExtensionNameSync(contributor.node.name),
241
- }),
242
- onNone: () => formatFqn({ owner: manifest.owner, type: "rule", name: manifest.name }),
243
- });
244
- return { name: contributor.node.name, marker, manifest, body };
245
- }), { concurrency: "unbounded" })), Effect.map((resolved) => {
246
- const sorted = [...resolved].sort((a, b) => {
247
- const byPriority = (a.manifest.priority ?? 100) - (b.manifest.priority ?? 100);
248
- if (byPriority !== 0)
249
- return byPriority;
250
- return a.marker.localeCompare(b.marker);
251
- });
252
- return sorted;
253
- }));
254
- const reconcileRulesRegion = (args) => Effect.gen(function* () {
255
- const { target } = args;
256
- const contributors = args.input.contributors;
257
- const rendered = contributors.map(renderRuleBlock).join("\n\n");
258
- const generation = projectionGeneration([
259
- "rule-instructions-region-v1",
260
- target.relative,
261
- RULES_REGION_OWNER,
262
- ...contributors.flatMap((contributor) => [
263
- contributor.name,
264
- contributor.marker,
265
- contributor.body,
266
- JSON.stringify(contributor.manifest),
267
- ]),
268
- ]);
269
- const instructions = args.instructions;
270
- if (args.dryRun !== true && Option.isSome(instructions)) {
271
- yield* provide(Effect.gen(function* () {
272
- const snapshot = yield* observeInstructionProjection({
273
- workspaceRoot: baseDir,
274
- scope: workspaceScope,
275
- configuredAgents: instructions.value.agents,
276
- config: instructions.value.config,
277
- });
278
- yield* assertInstructionTargetsSafe(snapshot.status);
279
- yield* assertInstructionsGitignoreSafe(baseDir);
280
- }));
281
- }
282
- const reconciliation = yield* provide(reconcileManagedRegionFile({
283
- targetPath: target.absolute,
284
- displayPath: target.relative,
285
- region: RULES_REGION,
286
- owner: RULES_REGION_OWNER,
287
- rendered,
288
- generation,
289
- ...(args.dryRun === undefined ? {} : { dryRun: args.dryRun }),
290
- writeWhenMissing: true,
291
- unsupportedTargetDetail: `Instruction source does not support managed regions: ${target.relative}`,
292
- }));
293
- const { changed, observedRegion } = reconciliation;
294
- const materializedTarget = decodeMaterializedTarget({
295
- target: target.relative,
296
- mode: "managed-region",
297
- region: RULES_REGION,
298
- });
299
- const projectionUnitObservation = {
300
- unitId: "rule:instructions-region",
301
- path: `${target.relative}#${RULES_REGION}`,
302
- owner: RULES_REGION_OWNER,
303
- present: Option.isSome(observedRegion),
304
- current: !changed,
305
- expectedContributors: contributors.map(({ marker }) => marker),
306
- };
307
- if (args.dryRun === true) {
308
- return {
309
- materializedTarget,
310
- materialization: ruleMaterializationObservation(target.relative, []),
311
- changed,
312
- projectionUnitObservation,
313
- };
314
- }
315
- const instructionItems = Option.isSome(instructions)
316
- ? (yield* provide(reconcileInstructionTargets({
317
- workspaceRoot: baseDir,
318
- scope: workspaceScope,
319
- configuredAgents: instructions.value.agents,
320
- config: instructions.value.config,
321
- }))).snapshot.status.items
322
- : [];
323
- const materialization = ruleMaterializationObservation(target.relative, instructionItems);
324
- lastProjection = materialization;
325
- return { materializedTarget, materialization, changed, projectionUnitObservation };
326
- });
327
- const makeRulesProjectionPlan = () => Effect.gen(function* () {
328
- const target = yield* sourceFileTarget();
329
- const instructions = yield* activeInstructions();
330
- const graph = yield* ws.getDesiredStateGraph();
331
- const locked = yield* ws.getLockedRules();
332
- return yield* planAggregateProjection({
333
- unitId: "rule:instructions-region",
334
- targetFile: target.absolute,
335
- graph,
336
- // Rule contributors are decided from desired state alone, so the
337
- // instructions region never excludes one.
338
- select: (completeGraph) => selectRuleContributors({ graph: completeGraph, locked }).pipe(Effect.map((contributors) => ({ contributors, exclusions: [] }))),
339
- adapter: {
340
- observe: (input) => reconcileRulesRegion({ input, target, instructions, dryRun: true }).pipe(Effect.map(({ projectionUnitObservation }) => projectionUnitObservation)),
341
- apply: (input) => reconcileRulesRegion({ input, target, instructions }).pipe(Effect.asVoid),
342
- },
343
- });
344
- });
345
- const projectionPlans = () => makeRulesProjectionPlan().pipe(Effect.map((plan) => [plan]));
346
- const applyRulesProjection = projectionPlans().pipe(Effect.flatMap(applyProjectionPlans));
347
- const materializeInstall = Effect.fn("RuleManager.materializeInstall")(function* ({ ref, force }) {
348
- const materialized = yield* materializePackage(ref, force === true);
349
- const packageRoot = materialized.packageRoot;
350
- yield* readManifest(packageRoot);
351
- const workspaceRelativeLocalSourcePath = ref.refType === "local"
352
- ? makeWorkspaceRelativeSourcePath(path, baseDir, ref.sourcePath ?? stripFileProtocol(ref.location))
353
- : Option.none();
354
- if (ref.refType === "local" && Option.isNone(workspaceRelativeLocalSourcePath)) {
355
- return yield* new RuleDefinitionInvalid({
356
- detail: `Local rule source path must stay within the workspace root: ${ref.source.path}`,
357
- });
358
- }
359
- const sourceHash = yield* provide(computePackageContentHash(packageRoot));
360
- lastInstallState.set(ref.rule.name, {
361
- ref,
362
- workspaceRelativeLocalSourcePath,
363
- sourceHash,
364
- treeIntegrity: materialized.treeIntegrity,
365
- });
366
- }, Effect.asVoid);
367
- const buildLockEntry = (ref) => Effect.gen(function* () {
368
- const state = lastInstallState.get(ref.rule.name);
369
- switch (ref.refType) {
370
- case "registry":
371
- return state === undefined
372
- ? yield* new RuleInstallStateMissing({ name: ref.rule.name, kind: "tree-integrity" })
373
- : Option.some(registryRuleLockEntry(ref, state.treeIntegrity));
374
- case "git-hosted":
375
- return state === undefined
376
- ? yield* new RuleInstallStateMissing({
377
- name: ref.rule.name,
378
- kind: "content-identity",
379
- })
380
- : Option.some(gitRuleLockEntry(ref, state.sourceHash, state.treeIntegrity));
381
- case "local":
382
- return state === undefined
383
- ? yield* new RuleInstallStateMissing({
384
- name: ref.rule.name,
385
- kind: "content-identity",
386
- })
387
- : Option.some(localRuleLockEntry(ref, state.workspaceRelativeLocalSourcePath, state.sourceHash, state.treeIntegrity));
388
- case "workspace":
389
- return Option.none();
390
- }
391
- });
392
- // Canonical removal only. The shared operation flow re-renders the region
393
- // after settings and lock removal, once the target has left the graph.
394
- const materializeUninstall = Effect.fn("RuleManager.materializeUninstall")(function* ({ target }) {
395
- const canonical = yield* provide(acceptedCanonicalObservation({
396
- workspace: ws,
397
- type: "rule",
398
- name: target.name,
399
- }));
400
- const packageRoot = removableAcceptedCanonicalPath(canonical);
401
- if (Option.isSome(packageRoot)) {
402
- yield* removeIfExists(fs, packageRoot.value);
403
- }
404
- }, Effect.asVoid);
405
- // Deactivation retains canonical content; the caller updates settings
406
- // first, so re-rendering the whole region drops this rule's contribution.
407
- const materializeDeactivate = Effect.fn("RuleManager.materializeDeactivate")(() => applyRulesProjection);
408
- return {
409
- type: "rule",
410
- projectionPlans,
411
- runTransaction: ws.runTransaction,
412
- isInstalled: ({ target }) => isObservedInstalled(ws, "rule", target.name).pipe(Effect.withSpan("RuleManager.isInstalled")),
413
- materializeInstall,
414
- prepareSourceTransition: ({ ref }) => provide(prepareAcceptedCanonicalTransition({
415
- workspace: ws,
416
- type: "rule",
417
- name: ref.rule.name,
418
- ref,
419
- })),
420
- getLastMaterialization: () => Effect.succeed(lastProjection ?? { agents: [], targets: [] }),
421
- getConfiguredSource: Effect.fn("RuleManager.getConfiguredSource")(function* ({ target }) {
422
- const configured = yield* ws.getConfiguredRuleEntries();
423
- return Option.fromUndefinedOr(configured[target.name]?.source);
424
- }),
425
- /**
426
- * Every enabled entry's accepted canonical package, read from accepted
427
- * resolution rather than re-resolved from source. Materialization
428
- * realizes what the workspace already accepted; going back to the
429
- * source would put an unrelated configured entry's release age between
430
- * an operator and the extension they are authoring.
431
- */
432
- listMaterializable: Effect.fn("RuleManager.listMaterializable")(function* () {
433
- const configured = yield* ws.getConfiguredRuleEntries();
434
- const refs = yield* Effect.forEach(enabledConfiguredEntries(configured), ([name]) => provide(usableAcceptedCanonicalRef({ workspace: ws, type: "rule", name }).pipe(Effect.map(Option.filter((ref) => ref.type === "rule")))), { concurrency: "unbounded" });
435
- return refs.flatMap((ref) => (Option.isSome(ref) ? [ref.value] : []));
436
- }),
437
- materializeUninstall,
438
- materializeDeactivate,
439
- upsertSettingsEntry: Effect.fn("RuleManager.upsertSettingsEntry")(function* ({ ref, versionRange, }) {
440
- const lockEntry = yield* buildLockEntry(ref);
441
- if (Option.isNone(lockEntry)) {
442
- yield* ws.setRuleEntry(ref.rule.name, {
443
- source: "workspace",
444
- enabled: true,
445
- });
446
- return;
447
- }
448
- if (lockEntry.value.type === "registry") {
449
- yield* validateExactResolvedVersion(`rules.${ref.rule.name}.resolvedVersion`, lockEntry.value.resolvedVersion);
450
- }
451
- yield* ws.setRule({
452
- name: ref.rule.name,
453
- lockEntry: lockEntry.value,
454
- versionRange,
455
- });
456
- }),
457
- removeSettingsEntry: Effect.fn("RuleManager.removeSettingsEntry")(function* ({ target }) {
458
- yield* ws.removeRuleSettings(target.name);
459
- }),
460
- upsertLockfileEntry: Effect.fn("RuleManager.upsertLockfileEntry")(function* ({ ref }) {
461
- const lockEntry = yield* buildLockEntry(ref);
462
- if (Option.isNone(lockEntry)) {
463
- yield* ws.removeRuleLock(ref.rule.name);
464
- return;
465
- }
466
- if (lockEntry.value.type === "registry") {
467
- yield* validateExactResolvedVersion(`rules.${ref.rule.name}.resolvedVersion`, lockEntry.value.resolvedVersion);
468
- }
469
- yield* ws.setRuleLock({
470
- name: ref.rule.name,
471
- lockEntry: lockEntry.value,
472
- versionRange: Option.none(),
473
- });
474
- }),
475
- removeLockfileEntry: Effect.fn("RuleManager.removeLockfileEntry")(function* ({ target }) {
476
- yield* ws.removeRuleLock(target.name);
477
- }),
478
- };
479
- }));
480
- //# sourceMappingURL=manager.js.map
@@ -1,18 +0,0 @@
1
- /**
2
- * Skill extension manager service.
3
- *
4
- * Implements ExtensionManager<SkillExtensionRef> with native/non-native
5
- * branching in materializeInstall and agent symlink creation for all
6
- * configured agents.
7
- *
8
- * @experimental This API is unstable and may change without notice.
9
- */
10
- import * as FileSystem from "effect/FileSystem";
11
- import * as HttpClient from "effect/unstable/http/HttpClient";
12
- import * as Path from "effect/Path";
13
- import * as Layer from "effect/Layer";
14
- import { SourceHostProviders } from "@agentxm/extension-sources";
15
- import { WorkspaceMutations } from "@agentxm/workspace-state";
16
- import { CodingAgentRepository, SkillManager } from "@agentxm/extension-workspace";
17
- export declare const SkillManagerLive: Layer.Layer<SkillManager, never, SourceHostProviders | WorkspaceMutations | FileSystem.FileSystem | HttpClient.HttpClient | Path.Path | CodingAgentRepository>;
18
- //# sourceMappingURL=manager.d.ts.map