@agentxm/extension-model 0.30.2 → 0.31.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.
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ExtensionFqnParts, ExtensionType, ExtensionVisibility } from "../extensions/common.js";
|
|
2
|
+
import type { DeprecationView } from "../extensions/deprecation.js";
|
|
3
|
+
import { type Version, type VersionRange } from "../version-constraints/version-constraints.js";
|
|
4
|
+
export interface PackDependencyTarget extends ExtensionFqnParts {
|
|
5
|
+
readonly type: Exclude<ExtensionType, "pack">;
|
|
6
|
+
}
|
|
7
|
+
export interface PackDependency extends PackDependencyTarget {
|
|
8
|
+
readonly range: VersionRange;
|
|
9
|
+
}
|
|
10
|
+
/** Registry facts are independent of the constraint chosen by any one pack. */
|
|
11
|
+
export interface PackDependencySnapshot {
|
|
12
|
+
readonly target: PackDependencyTarget;
|
|
13
|
+
readonly exists: boolean;
|
|
14
|
+
readonly visibility: ExtensionVisibility | null;
|
|
15
|
+
readonly lifecycleState: "active" | "unavailable" | null;
|
|
16
|
+
readonly deprecation: DeprecationView | null;
|
|
17
|
+
readonly versions: ReadonlyArray<{
|
|
18
|
+
readonly version: Version;
|
|
19
|
+
readonly status: "available" | "unavailable";
|
|
20
|
+
readonly yanked: boolean;
|
|
21
|
+
readonly purged: boolean;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
export type PackPublicationCandidate = {
|
|
25
|
+
readonly target: ExtensionFqnParts;
|
|
26
|
+
readonly kind: "unavailable";
|
|
27
|
+
} | {
|
|
28
|
+
readonly target: ExtensionFqnParts & {
|
|
29
|
+
readonly version: Version;
|
|
30
|
+
};
|
|
31
|
+
readonly kind: "resolved";
|
|
32
|
+
readonly participation: "publish" | "verified-existing";
|
|
33
|
+
readonly visibility: ExtensionVisibility | null;
|
|
34
|
+
};
|
|
35
|
+
/** Findings contain only disclosable domain facts; interfaces own their wording. */
|
|
36
|
+
export interface PackDependencyPolicyFinding {
|
|
37
|
+
readonly dependency: PackDependency;
|
|
38
|
+
readonly severity: "error" | "warning";
|
|
39
|
+
readonly reason: "missing" | "not-public" | "selected-unavailable" | "selected-new-private" | "selected-existing-private" | "lifecycle-unavailable" | "no-installable-version" | "range-unsatisfied" | "deprecated";
|
|
40
|
+
readonly effectiveVisibility?: ExtensionVisibility;
|
|
41
|
+
readonly lifecycle?: "active" | "unavailable";
|
|
42
|
+
readonly deprecation?: DeprecationView;
|
|
43
|
+
}
|
|
44
|
+
export interface PackDependencyPolicyResult {
|
|
45
|
+
readonly findings: ReadonlyArray<PackDependencyPolicyFinding>;
|
|
46
|
+
readonly resolutions: ReadonlyArray<{
|
|
47
|
+
readonly dependency: PackDependency;
|
|
48
|
+
readonly effectiveVersion: Version;
|
|
49
|
+
}>;
|
|
50
|
+
}
|
|
51
|
+
/** Evaluate admission and version selection once against the same prospective facts. */
|
|
52
|
+
export declare const evaluatePackDependencies: (input: {
|
|
53
|
+
readonly packVisibility: ExtensionVisibility;
|
|
54
|
+
readonly dependencies: ReadonlyArray<PackDependency>;
|
|
55
|
+
readonly snapshots: ReadonlyArray<PackDependencySnapshot>;
|
|
56
|
+
readonly candidates?: ReadonlyArray<PackPublicationCandidate>;
|
|
57
|
+
}) => PackDependencyPolicyResult;
|
|
58
|
+
//# sourceMappingURL=dependency-policy.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import * as semver from "semver";
|
|
2
|
+
import { formatFqn } from "../extensions/fqn.js";
|
|
3
|
+
import { decodeVersionSync, } from "../version-constraints/version-constraints.js";
|
|
4
|
+
const identityKey = (target) => `${target.owner}\u0000${target.type}\u0000${target.name}`;
|
|
5
|
+
const disclosedState = (snapshot) => ({
|
|
6
|
+
...(snapshot.visibility === null ? {} : { effectiveVisibility: snapshot.visibility }),
|
|
7
|
+
...(snapshot.lifecycleState === null ? {} : { lifecycle: snapshot.lifecycleState }),
|
|
8
|
+
});
|
|
9
|
+
const evaluateDependency = (dependency, current, selected, packVisibility) => {
|
|
10
|
+
const reject = (reason, state = {}) => ({
|
|
11
|
+
findings: [{ dependency, severity: "error", reason, ...state }],
|
|
12
|
+
resolutions: [],
|
|
13
|
+
});
|
|
14
|
+
if (selected?.kind === "unavailable")
|
|
15
|
+
return reject("selected-unavailable");
|
|
16
|
+
if (packVisibility === "public" && selected?.visibility === "private") {
|
|
17
|
+
return reject(current.exists ? "selected-existing-private" : "selected-new-private", {
|
|
18
|
+
...disclosedState(current),
|
|
19
|
+
effectiveVisibility: "private",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
const prospective = selected === undefined
|
|
23
|
+
? current
|
|
24
|
+
: {
|
|
25
|
+
...current,
|
|
26
|
+
exists: true,
|
|
27
|
+
visibility: selected.visibility ?? current.visibility,
|
|
28
|
+
lifecycleState: current.exists ? current.lifecycleState : "active",
|
|
29
|
+
versions: selected.participation === "publish"
|
|
30
|
+
? [
|
|
31
|
+
...current.versions,
|
|
32
|
+
{
|
|
33
|
+
version: selected.target.version,
|
|
34
|
+
status: "available",
|
|
35
|
+
yanked: false,
|
|
36
|
+
purged: false,
|
|
37
|
+
},
|
|
38
|
+
]
|
|
39
|
+
: current.versions,
|
|
40
|
+
};
|
|
41
|
+
if (!prospective.exists)
|
|
42
|
+
return reject("missing");
|
|
43
|
+
if (packVisibility === "public" && prospective.visibility !== "public")
|
|
44
|
+
return reject("not-public");
|
|
45
|
+
const state = disclosedState(prospective);
|
|
46
|
+
if (prospective.lifecycleState !== "active")
|
|
47
|
+
return reject("lifecycle-unavailable", state);
|
|
48
|
+
const installable = prospective.versions.filter((version) => version.status === "available" && !version.yanked && !version.purged);
|
|
49
|
+
if (installable.length === 0)
|
|
50
|
+
return reject("no-installable-version", state);
|
|
51
|
+
const effectiveVersion = semver.maxSatisfying(installable.map((version) => version.version), dependency.range);
|
|
52
|
+
if (effectiveVersion === null)
|
|
53
|
+
return reject("range-unsatisfied", state);
|
|
54
|
+
return {
|
|
55
|
+
findings: prospective.deprecation === null
|
|
56
|
+
? []
|
|
57
|
+
: [
|
|
58
|
+
{
|
|
59
|
+
dependency,
|
|
60
|
+
severity: "warning",
|
|
61
|
+
reason: "deprecated",
|
|
62
|
+
effectiveVisibility: prospective.visibility === "private" ? "private" : "public",
|
|
63
|
+
lifecycle: "active",
|
|
64
|
+
deprecation: prospective.deprecation,
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
resolutions: [{ dependency, effectiveVersion: decodeVersionSync(effectiveVersion) }],
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
/** Evaluate admission and version selection once against the same prospective facts. */
|
|
71
|
+
export const evaluatePackDependencies = (input) => {
|
|
72
|
+
const snapshots = new Map(input.snapshots.map((snapshot) => [identityKey(snapshot.target), snapshot]));
|
|
73
|
+
const candidates = new Map((input.candidates ?? []).map((candidate) => [identityKey(candidate.target), candidate]));
|
|
74
|
+
const compare = (left, right) => (left < right ? -1 : left > right ? 1 : 0);
|
|
75
|
+
const evaluated = [...input.dependencies]
|
|
76
|
+
.sort((left, right) => compare(formatFqn(left), formatFqn(right)) || compare(left.range, right.range))
|
|
77
|
+
.map((dependency) => evaluateDependency(dependency, snapshots.get(identityKey(dependency)) ?? {
|
|
78
|
+
target: dependency,
|
|
79
|
+
exists: false,
|
|
80
|
+
visibility: null,
|
|
81
|
+
lifecycleState: null,
|
|
82
|
+
deprecation: null,
|
|
83
|
+
versions: [],
|
|
84
|
+
}, candidates.get(identityKey(dependency)), input.packVisibility));
|
|
85
|
+
return {
|
|
86
|
+
findings: evaluated.flatMap((result) => result.findings),
|
|
87
|
+
resolutions: evaluated.flatMap((result) => result.resolutions),
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=dependency-policy.js.map
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"description": "Shared AgentXM extension model: identities, manifests, version constraints, and agent capabilities. Unstable and unsupported — use the axm.sh CLI.",
|
|
13
13
|
"devDependencies": {
|
|
14
|
-
"@agentxm/specification-metadata": "0.
|
|
14
|
+
"@agentxm/specification-metadata": "0.31.0",
|
|
15
15
|
"@effect/vitest": "4.0.0-rc.115",
|
|
16
16
|
"@fast-check/vitest": "^0.5.0",
|
|
17
17
|
"@types/semver": "^7.7.1",
|
|
@@ -196,6 +196,10 @@
|
|
|
196
196
|
"types": "./dist/src/unstable/packaging/package-url.d.ts",
|
|
197
197
|
"default": "./dist/src/unstable/packaging/package-url.js"
|
|
198
198
|
},
|
|
199
|
+
"./unstable/packs/dependency-policy": {
|
|
200
|
+
"types": "./dist/src/unstable/packs/dependency-policy.d.ts",
|
|
201
|
+
"default": "./dist/src/unstable/packs/dependency-policy.js"
|
|
202
|
+
},
|
|
199
203
|
"./unstable/packs/manifest-schema": {
|
|
200
204
|
"types": "./dist/src/unstable/packs/manifest-schema.d.ts",
|
|
201
205
|
"default": "./dist/src/unstable/packs/manifest-schema.js"
|
|
@@ -293,5 +297,5 @@
|
|
|
293
297
|
},
|
|
294
298
|
"sideEffects": false,
|
|
295
299
|
"type": "module",
|
|
296
|
-
"version": "0.
|
|
300
|
+
"version": "0.31.0"
|
|
297
301
|
}
|