@agentxm/extension-resolution 0.28.14-preview.1789139351.5cd4595aa

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 (47) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +56 -0
  3. package/dist/src/accepted-pack-dependency-resolver.d.ts +23 -0
  4. package/dist/src/accepted-pack-dependency-resolver.js +31 -0
  5. package/dist/src/accepted-pack-hydration.d.ts +33 -0
  6. package/dist/src/accepted-pack-hydration.js +93 -0
  7. package/dist/src/axm-skill-candidate.d.ts +16 -0
  8. package/dist/src/axm-skill-candidate.js +80 -0
  9. package/dist/src/axm-skill-compatibility.d.ts +87 -0
  10. package/dist/src/axm-skill-compatibility.js +248 -0
  11. package/dist/src/axm-skill-workspace-compatibility.d.ts +23 -0
  12. package/dist/src/axm-skill-workspace-compatibility.js +110 -0
  13. package/dist/src/configured-entry-resolution.d.ts +118 -0
  14. package/dist/src/configured-entry-resolution.js +735 -0
  15. package/dist/src/configured-entry.d.ts +38 -0
  16. package/dist/src/configured-entry.js +8 -0
  17. package/dist/src/errors.d.ts +113 -0
  18. package/dist/src/errors.js +71 -0
  19. package/dist/src/index.d.ts +34 -0
  20. package/dist/src/index.js +45 -0
  21. package/dist/src/live.d.ts +25 -0
  22. package/dist/src/live.js +47 -0
  23. package/dist/src/named-registry-resolution.d.ts +26 -0
  24. package/dist/src/named-registry-resolution.js +110 -0
  25. package/dist/src/pack-dependency-resolution.d.ts +73 -0
  26. package/dist/src/pack-dependency-resolution.js +422 -0
  27. package/dist/src/publisher-binding.d.ts +66 -0
  28. package/dist/src/publisher-binding.js +75 -0
  29. package/dist/src/release-age-policy.d.ts +55 -0
  30. package/dist/src/release-age-policy.js +115 -0
  31. package/dist/src/release-age-posture.d.ts +23 -0
  32. package/dist/src/release-age-posture.js +15 -0
  33. package/dist/src/resolution-timeout.d.ts +11 -0
  34. package/dist/src/resolution-timeout.js +17 -0
  35. package/dist/src/resolved-pack-dependency.d.ts +32 -0
  36. package/dist/src/resolved-pack-dependency.js +28 -0
  37. package/dist/src/source-authority.d.ts +60 -0
  38. package/dist/src/source-authority.js +70 -0
  39. package/dist/src/testing.d.ts +40 -0
  40. package/dist/src/testing.js +40 -0
  41. package/dist/src/update/constraint-precedence.d.ts +75 -0
  42. package/dist/src/update/constraint-precedence.js +99 -0
  43. package/dist/src/update/targeted-update-context.d.ts +101 -0
  44. package/dist/src/update/targeted-update-context.js +217 -0
  45. package/dist/src/version-resolution.d.ts +39 -0
  46. package/dist/src/version-resolution.js +76 -0
  47. package/package.json +66 -0
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Ownership, authority, and blocker classification for a targeted update.
3
+ *
4
+ * A person naming one extension asks a question the workspace has to answer
5
+ * before any Registry is contacted: does this workspace desire the extension
6
+ * at all, who owns the declaration that would move (a direct entry, an owning
7
+ * Pack, or both), is the entry active, which version constraint actually
8
+ * governs it once every declared constraint is intersected, and is there a
9
+ * reason the advance may not be made — an authored or bundled source, an
10
+ * incomplete Pack graph, a constraint with no compatible intersection, or a
11
+ * Pack-owned member the request would fork into direct intent.
12
+ *
13
+ * The classification is pure over the desired-state graph plus the configured
14
+ * Pack rows; `resolveTargetedUpdateContext` reads those and adds the accepted
15
+ * Pack evidence the fingerprint covers. The fingerprint is the freshness
16
+ * witness a targeted update rechecks under the workspace transition, so a
17
+ * context that changed between planning and apply stops the operation instead
18
+ * of applying a decision the workspace no longer supports.
19
+ *
20
+ * @experimental This API is unstable and may change without notice.
21
+ */
22
+ import * as Effect from "effect/Effect";
23
+ import type { InstallableExtensionType } from "@agentxm/extension-model/unstable/extensions/installable-types";
24
+ import type { ConfiguredRecordRow, DesiredStateGraph, WorkspaceLockfileReadFailure, WorkspaceSettingsReadFailure, WorkspaceStateReadFailure } from "@agentxm/workspace-state";
25
+ import { WorkspaceMutations } from "@agentxm/workspace-state";
26
+ export type TargetedUpdateBlocker = "not-desired" | "disabled" | "pack-owned-constraint" | "incomplete-graph" | "constraint-conflict" | "bundled-source" | "source-authority" | "stale-plan";
27
+ /** Every type a targeted update may name; a Pack is classified as a closure, not a member. */
28
+ export type TargetedUpdateTargetType = Exclude<InstallableExtensionType, "pack">;
29
+ export type TargetedUpdateAuthority = "direct" | "pack-aware" | "blocked";
30
+ export type TargetedUpdateOwnership = "absent" | "direct-only" | "pack-only" | "combined";
31
+ export type TargetedUpdateEffect = "unchanged" | "may-update";
32
+ export interface TargetedUpdatePublicContext {
33
+ readonly target: {
34
+ readonly type: TargetedUpdateTargetType;
35
+ readonly name: string;
36
+ readonly fqn: string;
37
+ };
38
+ readonly ownership: TargetedUpdateOwnership;
39
+ readonly activation: "enabled" | "disabled";
40
+ readonly authority: TargetedUpdateAuthority;
41
+ readonly direct?: {
42
+ readonly source: "bundled" | "inline" | "registry" | "workspace";
43
+ readonly enabled: boolean;
44
+ readonly constraint?: string;
45
+ };
46
+ readonly packs: ReadonlyArray<{
47
+ readonly fqn: string;
48
+ readonly configuredName?: string;
49
+ readonly source?: "registry" | "workspace";
50
+ readonly memberSource: "registry" | "workspace";
51
+ readonly constraint: string;
52
+ readonly enabled: boolean;
53
+ }>;
54
+ readonly effectiveConstraint?: string;
55
+ readonly memberClosure: ReadonlyArray<{
56
+ readonly type: TargetedUpdateTargetType;
57
+ readonly name: string;
58
+ readonly fqn: string;
59
+ }>;
60
+ readonly effects: {
61
+ readonly settings: TargetedUpdateEffect;
62
+ readonly acceptedResolution: TargetedUpdateEffect;
63
+ readonly canonical: TargetedUpdateEffect;
64
+ readonly projection: TargetedUpdateEffect;
65
+ readonly packRoot: TargetedUpdateEffect;
66
+ readonly packManifest: TargetedUpdateEffect;
67
+ };
68
+ readonly relevantProblems: ReadonlyArray<string>;
69
+ readonly blocker?: TargetedUpdateBlocker;
70
+ }
71
+ export interface TargetedUpdateContext {
72
+ readonly public: TargetedUpdatePublicContext;
73
+ readonly fingerprint: string;
74
+ readonly packEvidenceFingerprint: string;
75
+ }
76
+ export interface TargetedUpdateTarget {
77
+ readonly type: TargetedUpdatePublicContext["target"]["type"];
78
+ readonly name: string;
79
+ readonly fqn: string;
80
+ }
81
+ export interface ClassifyTargetedUpdateArgs {
82
+ readonly target: TargetedUpdateTarget;
83
+ readonly explicitRange?: string;
84
+ readonly graph: DesiredStateGraph;
85
+ readonly configuredPacks: ReadonlyArray<ConfiguredRecordRow>;
86
+ readonly configuredOwner?: string;
87
+ readonly packEvidence?: ReadonlyArray<unknown>;
88
+ }
89
+ export declare const classifyTargetedUpdate: (args: ClassifyTargetedUpdateArgs) => TargetedUpdateContext;
90
+ /** Everything the classifier reads before it can answer. */
91
+ export type TargetedUpdateContextFailure = WorkspaceStateReadFailure | WorkspaceSettingsReadFailure | WorkspaceLockfileReadFailure;
92
+ /**
93
+ * Read the workspace facts a targeted update is classified against, then
94
+ * classify twice: once to learn which Packs own the target, and once more
95
+ * with those Packs' accepted resolutions folded into the fingerprint.
96
+ */
97
+ export declare const resolveTargetedUpdateContext: (args: {
98
+ readonly target: TargetedUpdateTarget;
99
+ readonly explicitRange?: string;
100
+ }) => Effect.Effect<TargetedUpdateContext, TargetedUpdateContextFailure, WorkspaceMutations>;
101
+ //# sourceMappingURL=targeted-update-context.d.ts.map
@@ -0,0 +1,217 @@
1
+ /**
2
+ * Ownership, authority, and blocker classification for a targeted update.
3
+ *
4
+ * A person naming one extension asks a question the workspace has to answer
5
+ * before any Registry is contacted: does this workspace desire the extension
6
+ * at all, who owns the declaration that would move (a direct entry, an owning
7
+ * Pack, or both), is the entry active, which version constraint actually
8
+ * governs it once every declared constraint is intersected, and is there a
9
+ * reason the advance may not be made — an authored or bundled source, an
10
+ * incomplete Pack graph, a constraint with no compatible intersection, or a
11
+ * Pack-owned member the request would fork into direct intent.
12
+ *
13
+ * The classification is pure over the desired-state graph plus the configured
14
+ * Pack rows; `resolveTargetedUpdateContext` reads those and adds the accepted
15
+ * Pack evidence the fingerprint covers. The fingerprint is the freshness
16
+ * witness a targeted update rechecks under the workspace transition, so a
17
+ * context that changed between planning and apply stops the operation instead
18
+ * of applying a decision the workspace no longer supports.
19
+ *
20
+ * @experimental This API is unstable and may change without notice.
21
+ */
22
+ import * as crypto from "node:crypto";
23
+ import * as Effect from "effect/Effect";
24
+ import * as Option from "effect/Option";
25
+ import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
26
+ import { parseSourceQualifiedRegistrySourcePatternParts } from "@agentxm/extension-model/unstable/extensions";
27
+ import { intersectVersionConstraints } from "@agentxm/extension-model/unstable/version-constraints";
28
+ import { WorkspaceMutations, configuredRowsByName, desiredStateProblemText, } from "@agentxm/workspace-state";
29
+ const normalizedIdentity = (identity) => {
30
+ for (const prefix of ["workspace:", "bundled:"]) {
31
+ if (identity.startsWith(prefix))
32
+ return identity.slice(prefix.length);
33
+ }
34
+ return identity;
35
+ };
36
+ const registryFqnFromSource = (source) => {
37
+ if (source === undefined)
38
+ return undefined;
39
+ const parsed = parseSourceQualifiedRegistrySourcePatternParts(source);
40
+ return parsed?.name === undefined ? undefined : `${parsed.owner}/${parsed.type}/${parsed.name}`;
41
+ };
42
+ const sourceAuthority = (source) => isWorkspaceSourceLocator(source) ? "workspace" : "registry";
43
+ const configuredPackFqn = (entry, configuredOwner) => {
44
+ if (entry.source === undefined)
45
+ return undefined;
46
+ if (entry.source === "registry" || isWorkspaceSourceLocator(entry.source)) {
47
+ return configuredOwner === undefined ? undefined : `${configuredOwner}/packs/${entry.name}`;
48
+ }
49
+ const source = normalizedIdentity(entry.source);
50
+ const parsed = parseSourceQualifiedRegistrySourcePatternParts(source);
51
+ return parsed?.type === "packs" && parsed.name !== undefined
52
+ ? `${parsed.owner}/packs/${parsed.name}`
53
+ : undefined;
54
+ };
55
+ const originConstraint = (origin) => origin.type === "settings" && origin.authority === "inline" ? undefined : origin.constraint;
56
+ const blockedEffects = {
57
+ settings: "unchanged",
58
+ acceptedResolution: "unchanged",
59
+ canonical: "unchanged",
60
+ projection: "unchanged",
61
+ packRoot: "unchanged",
62
+ packManifest: "unchanged",
63
+ };
64
+ const plannedEffects = (authority, explicitRange) => ({
65
+ settings: authority === "direct" && explicitRange !== undefined ? "may-update" : "unchanged",
66
+ acceptedResolution: "may-update",
67
+ canonical: "may-update",
68
+ projection: "may-update",
69
+ packRoot: "unchanged",
70
+ packManifest: "unchanged",
71
+ });
72
+ const publicFingerprint = (value) => crypto.createHash("sha256").update(JSON.stringify(value)).digest("hex");
73
+ export const classifyTargetedUpdate = (args) => {
74
+ const node = args.graph.nodes.find((candidate) => candidate.type === args.target.type &&
75
+ (normalizedIdentity(candidate.identity) === args.target.fqn ||
76
+ (candidate.type === "mcp-server" &&
77
+ registryFqnFromSource(candidate.source) === args.target.fqn)));
78
+ const targetProblems = args.graph.problems.filter((problem) => (problem.type === "projection-collision" || problem.type === "constraint-conflict") &&
79
+ problem.extensionType === args.target.type &&
80
+ problem.name === args.target.name);
81
+ const relevantProblems = args.graph.problems.filter((problem) => problem.type.startsWith("pack-") ||
82
+ problem.type === "constraint-conflict" ||
83
+ targetProblems.includes(problem));
84
+ const directOrigin = node?.origins.find((origin) => origin.type === "settings");
85
+ const bundled = node?.identity.startsWith("bundled:") === true;
86
+ const packOrigins = (node?.origins ?? [])
87
+ .filter((origin) => origin.type === "pack")
88
+ .sort((left, right) => left.pack.localeCompare(right.pack));
89
+ const ownership = directOrigin === undefined
90
+ ? packOrigins.length === 0
91
+ ? "absent"
92
+ : "pack-only"
93
+ : packOrigins.length === 0
94
+ ? "direct-only"
95
+ : "combined";
96
+ const packs = packOrigins.map((origin) => {
97
+ const configured = args.configuredPacks.find((entry) => configuredPackFqn(entry, args.configuredOwner) === normalizedIdentity(origin.pack));
98
+ return {
99
+ fqn: normalizedIdentity(origin.pack),
100
+ ...(configured === undefined ? {} : { configuredName: configured.name }),
101
+ ...(configured?.source === undefined
102
+ ? {}
103
+ : {
104
+ source: sourceAuthority(configured.source),
105
+ }),
106
+ memberSource: sourceAuthority(origin.source),
107
+ constraint: origin.constraint,
108
+ enabled: origin.enabled,
109
+ };
110
+ });
111
+ const direct = directOrigin === undefined
112
+ ? undefined
113
+ : {
114
+ source: directOrigin.source === undefined
115
+ ? "inline"
116
+ : bundled
117
+ ? "bundled"
118
+ : sourceAuthority(directOrigin.source),
119
+ enabled: directOrigin.enabled,
120
+ ...(directOrigin.constraint === undefined ? {} : { constraint: directOrigin.constraint }),
121
+ };
122
+ const constraints = [
123
+ ...(directOrigin === undefined
124
+ ? []
125
+ : [args.explicitRange ?? originConstraint(directOrigin)].filter((constraint) => constraint !== undefined)),
126
+ ...packOrigins.map((origin) => origin.constraint),
127
+ ];
128
+ const intersection = intersectVersionConstraints(constraints);
129
+ const activation = node?.enabled === true ? "enabled" : "disabled";
130
+ let blocker;
131
+ if (relevantProblems.length > 0) {
132
+ blocker = targetProblems.some((problem) => problem.type === "constraint-conflict")
133
+ ? "constraint-conflict"
134
+ : "incomplete-graph";
135
+ }
136
+ else if (node === undefined) {
137
+ blocker = "not-desired";
138
+ }
139
+ else if (!node.enabled) {
140
+ blocker = "disabled";
141
+ }
142
+ else if (direct?.source === "bundled") {
143
+ blocker = "bundled-source";
144
+ }
145
+ else if (direct?.source === "inline" ||
146
+ direct?.source === "workspace" ||
147
+ packOrigins.some((origin) => isWorkspaceSourceLocator(origin.source))) {
148
+ blocker = "source-authority";
149
+ }
150
+ else if (ownership === "pack-only" && args.explicitRange !== undefined) {
151
+ blocker = "pack-owned-constraint";
152
+ }
153
+ else if (intersection === undefined) {
154
+ blocker = "constraint-conflict";
155
+ }
156
+ const authority = blocker !== undefined ? "blocked" : directOrigin === undefined ? "pack-aware" : "direct";
157
+ const publicContext = {
158
+ target: args.target,
159
+ ownership,
160
+ activation,
161
+ authority,
162
+ ...(direct === undefined ? {} : { direct }),
163
+ packs,
164
+ ...(intersection === undefined || intersection.length === 0
165
+ ? {}
166
+ : { effectiveConstraint: intersection }),
167
+ memberClosure: node === undefined ? [] : [args.target],
168
+ effects: authority === "blocked" ? blockedEffects : plannedEffects(authority, args.explicitRange),
169
+ relevantProblems: relevantProblems
170
+ .map((problem) => `${problem.type}: ${desiredStateProblemText(problem)}`)
171
+ .sort((left, right) => left.localeCompare(right)),
172
+ ...(blocker === undefined ? {} : { blocker }),
173
+ };
174
+ return {
175
+ public: publicContext,
176
+ fingerprint: publicFingerprint({
177
+ publicContext,
178
+ directSource: directOrigin?.source,
179
+ packSources: packOrigins.map((origin) => origin.source),
180
+ packEvidence: args.packEvidence ?? [],
181
+ }),
182
+ packEvidenceFingerprint: publicFingerprint(args.packEvidence ?? []),
183
+ };
184
+ };
185
+ /**
186
+ * Read the workspace facts a targeted update is classified against, then
187
+ * classify twice: once to learn which Packs own the target, and once more
188
+ * with those Packs' accepted resolutions folded into the fingerprint.
189
+ */
190
+ export const resolveTargetedUpdateContext = Effect.fn("TargetedUpdate.resolveContext")(function* (args) {
191
+ const workspace = yield* WorkspaceMutations;
192
+ const graph = yield* workspace.getDesiredStateGraph();
193
+ const configuredPacks = yield* workspace.records
194
+ .rows("pack")
195
+ .pipe(Effect.map((rows) => Object.values(configuredRowsByName(rows))));
196
+ const configuredOwner = yield* workspace.getConfiguredOwner();
197
+ const baseArgs = {
198
+ target: args.target,
199
+ ...(args.explicitRange === undefined ? {} : { explicitRange: args.explicitRange }),
200
+ graph,
201
+ configuredPacks,
202
+ ...(Option.isNone(configuredOwner) ? {} : { configuredOwner: configuredOwner.value }),
203
+ };
204
+ const preliminary = classifyTargetedUpdate(baseArgs);
205
+ const packEvidence = yield* Effect.all(preliminary.public.packs.map((pack) => Effect.gen(function* () {
206
+ const packNode = graph.nodes.find((candidate) => candidate.type === "pack" && normalizedIdentity(candidate.identity) === pack.fqn);
207
+ if (packNode === undefined)
208
+ return { fqn: pack.fqn, accepted: "absent" };
209
+ const accepted = yield* workspace.getLockedPack(packNode.name);
210
+ return {
211
+ fqn: pack.fqn,
212
+ accepted: Option.getOrUndefined(accepted) ?? "absent",
213
+ };
214
+ })));
215
+ return classifyTargetedUpdate({ ...baseArgs, packEvidence });
216
+ });
217
+ //# sourceMappingURL=targeted-update-context.js.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Version selection under the minimum-release-age policy.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ * @packageDocumentation
6
+ */
7
+ import * as Duration from "effect/Duration";
8
+ import * as Effect from "effect/Effect";
9
+ import * as Option from "effect/Option";
10
+ import type { ReleaseAgeEvaluation, ReleaseAgeEvidence, ReleaseAgeExemption } from "@agentxm/extension-model/unstable/extensions/release-age";
11
+ import type { VersionEntry } from "@agentxm/registry-protocol/unstable/registry/schema";
12
+ /**
13
+ * Resolve a version request against the versions that have reached the
14
+ * minimum release age, reading the clock through the Effect environment.
15
+ */
16
+ export declare const resolveVersionEntryWithReleaseAge: (versions: ReadonlyArray<VersionEntry>, versionRange: Option.Option<string>, minimumReleaseAge: Option.Option<Duration.Duration>) => Effect.Effect<Option.Option<VersionEntry>>;
17
+ export type ReleaseAgeVersionResolution = {
18
+ readonly kind: "selected";
19
+ readonly version: VersionEntry;
20
+ readonly newerHeld?: ReleaseAgeEvidence;
21
+ } | {
22
+ readonly kind: "exempted";
23
+ readonly version: VersionEntry;
24
+ readonly bypassed: ReleaseAgeEvidence;
25
+ readonly exemption: ReleaseAgeExemption;
26
+ } | {
27
+ readonly kind: "version_unsatisfied";
28
+ } | {
29
+ readonly kind: "policy_held";
30
+ readonly candidate: ReleaseAgeEvidence;
31
+ };
32
+ /**
33
+ * Resolve one visible Registry index under one caller-supplied release-age
34
+ * evaluation. The supplied timestamp makes a complete operation deterministic.
35
+ * An accepted version that satisfies the requested range is a lower bound for
36
+ * unattended selection, even while that version is itself under age.
37
+ */
38
+ export declare const resolveVersionEntryForReleaseAge: (versions: ReadonlyArray<VersionEntry>, versionRange: Option.Option<string>, evaluation: ReleaseAgeEvaluation, exemption?: ReleaseAgeExemption, acceptedVersion?: string) => ReleaseAgeVersionResolution;
39
+ //# sourceMappingURL=version-resolution.d.ts.map
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Version selection under the minimum-release-age policy.
3
+ *
4
+ * @experimental This API is unstable and may change without notice.
5
+ * @packageDocumentation
6
+ */
7
+ import * as Duration from "effect/Duration";
8
+ import * as Effect from "effect/Effect";
9
+ import * as Option from "effect/Option";
10
+ import * as semver from "semver";
11
+ import { resolveVersionEntry } from "@agentxm/registry-protocol/unstable/registry/version-selection";
12
+ import { filterMatureVersions, isVersionEntryEligibleAt, releaseAgeEvidence, } from "./release-age-policy.js";
13
+ /**
14
+ * Resolve a version request against the versions that have reached the
15
+ * minimum release age, reading the clock through the Effect environment.
16
+ */
17
+ export const resolveVersionEntryWithReleaseAge = (versions, versionRange, minimumReleaseAge) => {
18
+ if (Option.isNone(minimumReleaseAge)) {
19
+ return Effect.succeed(resolveVersionEntry(versions, versionRange));
20
+ }
21
+ return filterMatureVersions(versions, minimumReleaseAge.value).pipe(Effect.map((mature) => resolveVersionEntry(mature, versionRange)));
22
+ };
23
+ /**
24
+ * Resolve one visible Registry index under one caller-supplied release-age
25
+ * evaluation. The supplied timestamp makes a complete operation deterministic.
26
+ * An accepted version that satisfies the requested range is a lower bound for
27
+ * unattended selection, even while that version is itself under age.
28
+ */
29
+ export const resolveVersionEntryForReleaseAge = (versions, versionRange, evaluation, exemption, acceptedVersion) => {
30
+ const otherwiseSelected = resolveVersionEntry(versions, versionRange);
31
+ if (Option.isNone(otherwiseSelected)) {
32
+ return { kind: "version_unsatisfied" };
33
+ }
34
+ const candidate = otherwiseSelected.value;
35
+ const candidateEligible = isVersionEntryEligibleAt(candidate, evaluation);
36
+ if (!candidateEligible && exemption !== undefined) {
37
+ return {
38
+ kind: "exempted",
39
+ version: candidate,
40
+ bypassed: releaseAgeEvidence(candidate, evaluation),
41
+ exemption,
42
+ };
43
+ }
44
+ const eligible = versions.filter((entry) => isVersionEntryEligibleAt(entry, evaluation));
45
+ const eligibleSelection = resolveVersionEntry(eligible, versionRange);
46
+ const accepted = versions.find((entry) => {
47
+ if (entry.version !== acceptedVersion)
48
+ return false;
49
+ if (Option.isNone(versionRange))
50
+ return true;
51
+ return semver.valid(versionRange.value) === versionRange.value
52
+ ? entry.version === versionRange.value
53
+ : semver.satisfies(entry.version, versionRange.value);
54
+ });
55
+ const selected = accepted !== undefined &&
56
+ (Option.isNone(eligibleSelection) ||
57
+ semver.compareBuild(accepted.version, eligibleSelection.value.version) > 0)
58
+ ? Option.some(accepted)
59
+ : eligibleSelection;
60
+ if (Option.isNone(selected)) {
61
+ return {
62
+ kind: "policy_held",
63
+ candidate: releaseAgeEvidence(candidate, evaluation),
64
+ };
65
+ }
66
+ const selectedAcceptedFloor = accepted?.version === selected.value.version && !candidateEligible;
67
+ return {
68
+ kind: "selected",
69
+ version: selected.value,
70
+ ...(candidateEligible ||
71
+ (candidate.version === selected.value.version && !selectedAcceptedFloor)
72
+ ? {}
73
+ : { newerHeld: releaseAgeEvidence(candidate, evaluation) }),
74
+ };
75
+ };
76
+ //# sourceMappingURL=version-resolution.js.map
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "author": "AgentXM <hello@agentxm.ai> (https://agentxm.ai)",
3
+ "bugs": {
4
+ "url": "https://github.com/agentxm/axm/issues"
5
+ },
6
+ "dependencies": {
7
+ "@agentxm/extension-content": "^0.28.14-preview.1789139351.5cd4595aa",
8
+ "@agentxm/extension-model": "^0.28.14-preview.1789139351.5cd4595aa",
9
+ "@agentxm/extension-sources": "^0.28.14-preview.1789139351.5cd4595aa",
10
+ "@agentxm/registry-protocol": "^0.28.14-preview.1789139351.5cd4595aa",
11
+ "@agentxm/workspace-state": "^0.28.14-preview.1789139351.5cd4595aa",
12
+ "effect": "4.0.0-rc.112",
13
+ "semver": "^7.8.5"
14
+ },
15
+ "description": "AXM extension resolution policy: what a configured or requested extension resolves to and whether that resolution may be accepted — release-age policy, version selection, configured-entry and Pack dependency resolution, workspace source authority, publisher-binding trust, and official AXM skill compatibility. Unstable and unsupported — use the axm.sh CLI.",
16
+ "devDependencies": {
17
+ "@agentxm/specification-metadata": "^0.28.14-preview.1789139351.5cd4595aa",
18
+ "@effect/platform-node": "4.0.0-rc.112",
19
+ "@effect/vitest": "4.0.0-rc.112",
20
+ "@types/semver": "^7.7.1",
21
+ "@typescript/native": "npm:typescript@^7.0.2",
22
+ "typescript": "npm:@typescript/typescript6@^6.0.2",
23
+ "vitest": "^4.1.10"
24
+ },
25
+ "engines": {
26
+ "node": ">=22.19.0"
27
+ },
28
+ "exports": {
29
+ ".": {
30
+ "axm-source": "./src/index.ts",
31
+ "default": "./dist/src/index.js",
32
+ "types": "./dist/src/index.d.ts"
33
+ },
34
+ "./live": {
35
+ "axm-source": "./src/live.ts",
36
+ "default": "./dist/src/live.js",
37
+ "types": "./dist/src/live.d.ts"
38
+ },
39
+ "./testing": {
40
+ "axm-source": "./src/testing.ts",
41
+ "default": "./dist/src/testing.js",
42
+ "types": "./dist/src/testing.d.ts"
43
+ }
44
+ },
45
+ "files": [
46
+ "dist/src/",
47
+ "!**/*.map"
48
+ ],
49
+ "homepage": "https://axm.sh",
50
+ "license": "FSL-1.1-MIT",
51
+ "name": "@agentxm/extension-resolution",
52
+ "nx": {
53
+ "includedScripts": []
54
+ },
55
+ "publishConfig": {
56
+ "access": "public"
57
+ },
58
+ "repository": {
59
+ "directory": "packages/core/extension-resolution",
60
+ "type": "git",
61
+ "url": "https://github.com/agentxm/axm.git"
62
+ },
63
+ "sideEffects": false,
64
+ "type": "module",
65
+ "version": "0.28.14-preview.1789139351.5cd4595aa"
66
+ }