@agentxm/registry-protocol 0.31.1-preview.35463507166.59e3bf3d74da → 0.33.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.
package/README.md CHANGED
@@ -1,20 +1,70 @@
1
1
  # @agentxm/registry-protocol
2
2
 
3
- The AgentXM Registry wire contracts that the AXM client and the Registry
4
- implementation must interpret identically: extension index and version entry
5
- schemas (`./unstable/registry/schema`), discovery responses
3
+ The AXM client's typed representation of the public AgentXM Registry HTTP
4
+ contract: extension index and version entry schemas
5
+ (`./unstable/registry/schema`), discovery responses
6
6
  (`./unstable/registry/discover-schema`), publication-set preview and
7
7
  validation (`./unstable/registry/publication-set`), publish visibility
8
8
  (`./unstable/publish`), and the shared suggested-action and
9
9
  human-handoff error vocabulary (`./unstable/suggested-action`,
10
10
  `./unstable/human-handoff`).
11
11
 
12
+ ## Batch resolution metadata
13
+
14
+ `./unstable/registry/resolution-metadata` defines the versioned contract for a
15
+ repeat-safe `POST /v1/resolutions/metadata` query. The Registry owns the HTTP
16
+ route and authorization; AXM keeps version selection, release-age policy, and
17
+ dependency graph decisions. A request groups up to 100 items in one trusted
18
+ Registry and credential context. Each item has a unique caller key, extension
19
+ identity, and a `select` or `restore-exact` purpose. Exact restoration supplies
20
+ the accepted version and integrity. The caller may also supply an expected
21
+ publisher binding, a known representation revision, or a continuation bound to
22
+ the previous revision.
23
+
24
+ The response has exactly one outcome per submitted key in request order:
25
+
26
+ | Outcome | Meaning |
27
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
28
+ | `metadata` | An authorized page of version descriptors, dependency and package compatibility data, lifecycle information, and an opaque revision. A `null` continuation means the candidate list is complete. |
29
+ | `unchanged` | Current authorization and lifecycle still admit a matching complete representation already held by the client. A client without that representation repeats the item without `knownRevision`. |
30
+ | `unavailable` | The identity is absent or inaccessible; the response deliberately does not distinguish those cases. |
31
+ | `binding-conflict` | An authorized identity no longer has the expected publisher binding. |
32
+ | `exact-conflict` | An authorized exact version or integrity no longer matches the accepted identity. |
33
+ | `restart-required` | A continued page crossed a representation revision; discard the earlier pages and restart. |
34
+
35
+ A metadata page contains at most 100 versions. Clients must follow every
36
+ continuation and check the revision and result keys before selecting a version;
37
+ truncated pages are never complete selection input. Continuation tokens are
38
+ opaque and must be bound by the Registry to the request identity, credential
39
+ context, and revision. A changed binding, hold, visibility, yank, archival or
40
+ deprecation fact must invalidate an `unchanged` result. Backend failures are
41
+ envelope errors, never invented per-item absence. The query is private and
42
+ non-cacheable across commands; its POST method does not make publish mutations
43
+ retryable.
44
+
45
+ The schema exports the item, version-page, request-body, and response-body
46
+ limits. A server checks encoded body size before decoding and returns the
47
+ declared `request-too-large` error when exceeded. Request keys correlate results
48
+ only; they confer no identity or access.
49
+
50
+ The exported `./unstable/registry/resolution-metadata.vectors.json` records
51
+ selection examples for ordinary and exact yanks, release age, direct and pack
52
+ constraints, package compatibility, and publisher-binding changes. Producer and
53
+ consumer tests can use the same cases without moving selection to the server.
54
+
55
+ The byte-vendorable
56
+ `./unstable/registry/publication-set.vectors.json` export pins digest
57
+ conformance examples for independent implementations of the public protocol.
58
+ Its metadata describes the canonicalization and optional-field rules; changing
59
+ the digest algorithm requires a new contract identifier and vector format
60
+ rather than editing the meaning of existing vectors.
61
+
12
62
  Content parsing, Knowledge inspection, the lint catalog, and archive and
13
63
  manifest validation live in `@agentxm/extension-content`; version selection
14
64
  and release-age policy live in `@agentxm/workspace/resolution`.
15
65
 
16
- Every export lives under an explicit `./unstable/*` subpath: the surface is
17
- unsupported and may change in any release. Ordinary users should use the
18
- [`axm` CLI](https://axm.sh) instead.
66
+ This package is bundled into `axm.sh`; it is not an independently published
67
+ API. Its `./unstable/*` subpaths are workspace-internal boundaries. Ordinary
68
+ users should use the [`axm` CLI](https://axm.sh) instead.
19
69
 
20
70
  FSL-1.1-MIT © 2025-2026 AgentXM, Inc.
@@ -4,6 +4,7 @@
4
4
  * @experimental This API is unstable and may change without notice.
5
5
  */
6
6
  export { type DiscoverPackageInput, DiscoverPackageInputSchema, type DiscoverPackagesRequest, DiscoverPackagesRequestSchema, type DiscoverPackagesResponse, DiscoverPackagesResponseSchema, type DiscoveryDeclaredExtension, DiscoveryDeclaredExtensionSchema, type DiscoveryExtensionResult, DiscoveryExtensionResultSchema, DiscoveryGitResolutionSchema, DiscoveryGitResolvedExtensionSchema, type DiscoveryPackageResult, DiscoveryPackageResultSchema, DiscoveryPathResolutionSchema, DiscoveryPathResolvedExtensionSchema, DiscoveryRegistryResolutionSchema, DiscoveryRegistryResolvedExtensionSchema, type DiscoveryResolvedExtension, DiscoveryResolvedExtensionSchema, } from "./discover-schema.js";
7
+ export { MAX_RESOLUTION_METADATA_ITEMS, MAX_RESOLUTION_METADATA_REQUEST_BYTES, MAX_RESOLUTION_METADATA_RESPONSE_BYTES, MAX_RESOLUTION_METADATA_VERSIONS_PER_PAGE, RESOLUTION_METADATA_SCHEMA_VERSION, RESOLUTION_SELECTION_POLICY_VERSION, decodeResolutionMetadataRequestBody, type ResolutionMetadataError, ResolutionMetadataErrorSchema, ResolutionMetadataIdentitySchema, ResolutionMetadataItemSchema, type ResolutionMetadataOutcome, ResolutionMetadataOutcomeSchema, type ResolutionMetadataRequest, ResolutionMetadataRequestSchema, type ResolutionMetadataResponse, ResolutionMetadataResponseSchema, resolutionMetadataResponseMatchesRequest, } from "./resolution-metadata.js";
7
8
  export { MAX_PUBLICATION_SET_CANDIDATES, PUBLICATION_SET_CONTRACT, type PackDependencyDescriptor, type PackDependencyFinding, PackDependencyFindingSchema, type PreviewPublicationSetRequest, PreviewPublicationSetRequestSchema, type PreviewPublicationSetResponse, PreviewPublicationSetResponseSchema, type PublicationCandidateResult, type PublicationDescriptor, type PublicationPackResult, type PublicationTarget, type PublicationVisibilityInput, PublicationVisibilityInputSchema, type Sha256Hex, Sha256HexSchema, archiveSha256Hex, formatPackDependencyFinding, comparePublicationTargets, normalizePublicationDescriptor, normalizePublicationSet, publicationDescriptorDigest, publicationSetDigest, publicationTargetKey, validatePublicationDescriptors, validatePublicationSetResponse, } from "./publication-set.js";
8
9
  export { type ArchivalManagementView, ArchivalManagementViewSchema, ArchivalRevisionSchema, type ArchivalTransition, ArchivalTransitionSchema, type DeprecationManagementView, DeprecationManagementViewSchema, type DeprecationReplacementIntent, DeprecationReplacementIntentSchema, DeprecationRevisionSchema, type DeprecationTransition, DeprecationTransitionSchema, type ExtensionIndex, ExtensionIndexSchema, type VersionEntry, VersionEntrySchema, packagesToPackageUrlParts, } from "./schema.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -4,6 +4,7 @@
4
4
  * @experimental This API is unstable and may change without notice.
5
5
  */
6
6
  export { DiscoverPackageInputSchema, DiscoverPackagesRequestSchema, DiscoverPackagesResponseSchema, DiscoveryDeclaredExtensionSchema, DiscoveryExtensionResultSchema, DiscoveryGitResolutionSchema, DiscoveryGitResolvedExtensionSchema, DiscoveryPackageResultSchema, DiscoveryPathResolutionSchema, DiscoveryPathResolvedExtensionSchema, DiscoveryRegistryResolutionSchema, DiscoveryRegistryResolvedExtensionSchema, DiscoveryResolvedExtensionSchema, } from "./discover-schema.js";
7
+ export { MAX_RESOLUTION_METADATA_ITEMS, MAX_RESOLUTION_METADATA_REQUEST_BYTES, MAX_RESOLUTION_METADATA_RESPONSE_BYTES, MAX_RESOLUTION_METADATA_VERSIONS_PER_PAGE, RESOLUTION_METADATA_SCHEMA_VERSION, RESOLUTION_SELECTION_POLICY_VERSION, decodeResolutionMetadataRequestBody, ResolutionMetadataErrorSchema, ResolutionMetadataIdentitySchema, ResolutionMetadataItemSchema, ResolutionMetadataOutcomeSchema, ResolutionMetadataRequestSchema, ResolutionMetadataResponseSchema, resolutionMetadataResponseMatchesRequest, } from "./resolution-metadata.js";
7
8
  export { MAX_PUBLICATION_SET_CANDIDATES, PUBLICATION_SET_CONTRACT, PackDependencyFindingSchema, PreviewPublicationSetRequestSchema, PreviewPublicationSetResponseSchema, PublicationVisibilityInputSchema, Sha256HexSchema, archiveSha256Hex, formatPackDependencyFinding, comparePublicationTargets, normalizePublicationDescriptor, normalizePublicationSet, publicationDescriptorDigest, publicationSetDigest, publicationTargetKey, validatePublicationDescriptors, validatePublicationSetResponse, } from "./publication-set.js";
8
9
  export { ArchivalManagementViewSchema, ArchivalRevisionSchema, ArchivalTransitionSchema, DeprecationManagementViewSchema, DeprecationReplacementIntentSchema, DeprecationRevisionSchema, DeprecationTransitionSchema, ExtensionIndexSchema, VersionEntrySchema, packagesToPackageUrlParts, } from "./schema.js";
9
10
  //# sourceMappingURL=index.js.map
@@ -29,6 +29,36 @@ export declare const PublicationVisibilityInputSchema: Schema.Struct<{
29
29
  readonly request: Schema.NullOr<Schema.Literals<readonly ["public", "private"]>>;
30
30
  }>;
31
31
  export type PublicationVisibilityInput = typeof PublicationVisibilityInputSchema.Type;
32
+ export declare const PublicationDescriptorSchema: Schema.Struct<{
33
+ readonly target: Schema.Struct<{
34
+ readonly owner: Schema.brand<Schema.String, "Handle">;
35
+ readonly type: Schema.Literals<readonly ("skill" | "mcp-server" | "subagent" | "rule" | "hook" | "knowledge" | "pack")[]>;
36
+ readonly name: Schema.brand<Schema.NonEmptyString, "ExtensionName">;
37
+ readonly version: Schema.brand<Schema.String, "Version">;
38
+ }>;
39
+ readonly participation: Schema.Literals<readonly ["publish", "verified-existing"]>;
40
+ readonly archiveSha256Hex: Schema.optional<Schema.String>;
41
+ readonly visibility: Schema.Struct<{
42
+ readonly intent: Schema.NullOr<Schema.Struct<{
43
+ readonly value: Schema.Literals<readonly ["public", "private"]>;
44
+ readonly source: Schema.Literals<readonly ["manifest", "workspace"]>;
45
+ readonly fingerprint: Schema.String;
46
+ }>>;
47
+ readonly request: Schema.NullOr<Schema.Literals<readonly ["public", "private"]>>;
48
+ }>;
49
+ readonly pack: Schema.optional<Schema.Struct<{
50
+ readonly dependencies: Schema.$Array<Schema.Struct<{
51
+ readonly owner: Schema.brand<Schema.String, "Handle">;
52
+ readonly type: Schema.Literals<readonly ["hook", "knowledge", "mcp-server", "rule", "skill", "subagent"]>;
53
+ readonly name: Schema.brand<Schema.NonEmptyString, "ExtensionName">;
54
+ readonly range: Schema.brand<Schema.NonEmptyString, "VersionRange">;
55
+ readonly source: Schema.optional<Schema.Struct<{
56
+ readonly type: Schema.Literal<"registry">;
57
+ readonly url: Schema.URLFromString;
58
+ }>>;
59
+ }>>;
60
+ }>>;
61
+ }>;
32
62
  export interface PublicationDescriptor {
33
63
  readonly target: PublicationTarget;
34
64
  readonly participation: "publish" | "verified-existing";
@@ -267,10 +297,10 @@ export type PreviewPublicationSetResponse = typeof PreviewPublicationSetResponse
267
297
  export type PublicationCandidateResult = PreviewPublicationSetResponse["candidates"][number];
268
298
  export type PublicationPackResult = PreviewPublicationSetResponse["packs"][number];
269
299
  export declare const comparePublicationTargets: (left: PublicationTarget, right: PublicationTarget) => number;
270
- export declare const normalizePublicationDescriptor: (descriptor: PublicationDescriptor) => PublicationDescriptor;
271
- export declare const normalizePublicationSet: (descriptors: ReadonlyArray<PublicationDescriptor>) => ReadonlyArray<PublicationDescriptor>;
272
- export declare const publicationDescriptorDigest: (descriptor: PublicationDescriptor) => Sha256Hex;
273
- export declare const publicationSetDigest: (descriptors: ReadonlyArray<PublicationDescriptor>) => Sha256Hex;
300
+ export declare const normalizePublicationDescriptor: (input: unknown) => PublicationDescriptor;
301
+ export declare const normalizePublicationSet: (descriptors: ReadonlyArray<unknown>) => ReadonlyArray<PublicationDescriptor>;
302
+ export declare const publicationDescriptorDigest: (descriptor: unknown) => Sha256Hex;
303
+ export declare const publicationSetDigest: (descriptors: ReadonlyArray<unknown>) => Sha256Hex;
274
304
  export declare const archiveSha256Hex: (archive: Uint8Array) => Sha256Hex;
275
305
  export declare const publicationTargetKey: (target: PublicationTarget) => string;
276
306
  export declare const validatePublicationDescriptors: (descriptors: ReadonlyArray<PublicationDescriptor>) => ReadonlyArray<PublicationDescriptor>;
@@ -30,7 +30,7 @@ export const PublicationVisibilityInputSchema = Schema.Struct({
30
30
  intent: Schema.NullOr(VisibilityIntentSchema),
31
31
  request: Schema.NullOr(ExtensionVisibilitySchema),
32
32
  }).annotate({ identifier: "PublicationVisibilityInput" });
33
- const PublicationDescriptorSchema = Schema.Struct({
33
+ export const PublicationDescriptorSchema = Schema.Struct({
34
34
  target: PublicationTargetSchema,
35
35
  participation: Schema.Literals(["publish", "verified-existing"]),
36
36
  archiveSha256Hex: Schema.optional(Sha256HexSchema),
@@ -39,6 +39,10 @@ const PublicationDescriptorSchema = Schema.Struct({
39
39
  dependencies: Schema.Array(PackDependencyDescriptorSchema),
40
40
  })),
41
41
  }).annotate({ identifier: "PublicationDescriptor" });
42
+ const PublicationDescriptorInputSchema = Schema.Union([
43
+ PublicationDescriptorSchema,
44
+ Schema.toType(PublicationDescriptorSchema),
45
+ ]);
42
46
  export const PreviewPublicationSetRequestSchema = Schema.Struct({
43
47
  contract: Schema.Literal(PUBLICATION_SET_CONTRACT),
44
48
  candidates: Schema.Array(PublicationDescriptorSchema),
@@ -208,33 +212,88 @@ const compareDependencies = (left, right) => compareText(left.owner, right.owner
208
212
  compareText(left.name, right.name) ||
209
213
  compareText(left.range, right.range) ||
210
214
  compareText(left.source?.url.href ?? "", right.source?.url.href ?? "");
211
- export const normalizePublicationDescriptor = (descriptor) => ({
212
- target: descriptor.target,
213
- participation: descriptor.participation,
214
- visibility: descriptor.visibility,
215
- ...(descriptor.archiveSha256Hex === undefined
216
- ? {}
217
- : { archiveSha256Hex: descriptor.archiveSha256Hex }),
218
- ...(descriptor.pack === undefined
219
- ? {}
220
- : {
221
- pack: {
222
- dependencies: [...descriptor.pack.dependencies].sort(compareDependencies),
223
- },
224
- }),
225
- });
215
+ export const normalizePublicationDescriptor = (input) => {
216
+ const descriptor = Schema.decodeUnknownSync(PublicationDescriptorInputSchema)(input);
217
+ return {
218
+ target: {
219
+ owner: descriptor.target.owner,
220
+ type: descriptor.target.type,
221
+ name: descriptor.target.name,
222
+ version: descriptor.target.version,
223
+ },
224
+ participation: descriptor.participation,
225
+ visibility: {
226
+ intent: descriptor.visibility.intent === null
227
+ ? null
228
+ : {
229
+ value: descriptor.visibility.intent.value,
230
+ source: descriptor.visibility.intent.source,
231
+ fingerprint: descriptor.visibility.intent.fingerprint,
232
+ },
233
+ request: descriptor.visibility.request,
234
+ },
235
+ ...(descriptor.archiveSha256Hex === undefined
236
+ ? {}
237
+ : { archiveSha256Hex: descriptor.archiveSha256Hex }),
238
+ ...(descriptor.pack === undefined
239
+ ? {}
240
+ : {
241
+ pack: {
242
+ dependencies: descriptor.pack.dependencies
243
+ .map((dependency) => ({
244
+ owner: dependency.owner,
245
+ type: dependency.type,
246
+ name: dependency.name,
247
+ range: dependency.range,
248
+ ...(dependency.source === undefined
249
+ ? {}
250
+ : {
251
+ source: {
252
+ type: dependency.source.type,
253
+ url: dependency.source.url,
254
+ },
255
+ }),
256
+ }))
257
+ .sort(compareDependencies),
258
+ },
259
+ }),
260
+ };
261
+ };
226
262
  export const normalizePublicationSet = (descriptors) => descriptors
227
263
  .map(normalizePublicationDescriptor)
228
264
  .sort((left, right) => comparePublicationTargets(left.target, right.target));
229
265
  const canonicalBytes = (value) => new TextEncoder().encode(JSON.stringify(value));
266
+ const canonicalPublicationDescriptor = (input) => {
267
+ const descriptor = normalizePublicationDescriptor(input);
268
+ return {
269
+ ...descriptor,
270
+ ...(descriptor.pack === undefined
271
+ ? {}
272
+ : {
273
+ pack: {
274
+ dependencies: descriptor.pack.dependencies.map((dependency) => ({
275
+ ...dependency,
276
+ ...(dependency.source === undefined
277
+ ? {}
278
+ : {
279
+ source: {
280
+ type: dependency.source.type,
281
+ url: dependency.source.url.href,
282
+ },
283
+ }),
284
+ })),
285
+ },
286
+ }),
287
+ };
288
+ };
230
289
  const sha256Hex = (bytes) => Schema.decodeUnknownSync(Sha256HexSchema)(createHash("sha256").update(bytes).digest("hex"));
231
290
  export const publicationDescriptorDigest = (descriptor) => sha256Hex(canonicalBytes({
232
291
  contract: PUBLICATION_SET_CONTRACT,
233
- descriptor: normalizePublicationDescriptor(descriptor),
292
+ descriptor: canonicalPublicationDescriptor(descriptor),
234
293
  }));
235
294
  export const publicationSetDigest = (descriptors) => sha256Hex(canonicalBytes({
236
295
  contract: PUBLICATION_SET_CONTRACT,
237
- candidates: normalizePublicationSet(descriptors),
296
+ candidates: normalizePublicationSet(descriptors).map(canonicalPublicationDescriptor),
238
297
  }));
239
298
  export const archiveSha256Hex = (archive) => sha256Hex(archive);
240
299
  export const publicationTargetKey = (target) => JSON.stringify([target.owner, target.type, target.name, target.version]);
@@ -243,12 +302,9 @@ export const validatePublicationDescriptors = (descriptors) => {
243
302
  if (descriptors.length > MAX_PUBLICATION_SET_CANDIDATES) {
244
303
  throw new RangeError(`Publication sets accept at most ${MAX_PUBLICATION_SET_CANDIDATES} candidates.`);
245
304
  }
246
- Schema.decodeUnknownSync(Schema.toType(PreviewPublicationSetRequestSchema))({
247
- contract: PUBLICATION_SET_CONTRACT,
248
- candidates: descriptors,
249
- });
305
+ const normalized = normalizePublicationSet(descriptors);
250
306
  const identities = new Set();
251
- for (const descriptor of descriptors) {
307
+ for (const descriptor of normalized) {
252
308
  const key = publicationIdentityKey(descriptor.target);
253
309
  if (identities.has(key)) {
254
310
  throw new TypeError(`Duplicate publication target ${key}.`);
@@ -261,7 +317,7 @@ export const validatePublicationDescriptors = (descriptors) => {
261
317
  throw new TypeError("Pack declarations are required exactly for pack candidates.");
262
318
  }
263
319
  }
264
- return normalizePublicationSet(descriptors);
320
+ return normalized;
265
321
  };
266
322
  const dependencyIdentityKey = (dependency) => `${dependency.owner}\u0000${dependency.type}\u0000${dependency.name}`;
267
323
  export const validatePublicationSetResponse = (descriptors, response) => {
@@ -0,0 +1,351 @@
1
+ /**
2
+ * Repeat-safe Registry metadata query contract. Selection stays with the client;
3
+ * each response page is evidence for one authorized identity and revision.
4
+ *
5
+ * @experimental This API is unstable and may change without notice.
6
+ */
7
+ import * as Schema from "effect/Schema";
8
+ import * as Result from "effect/Result";
9
+ export declare const RESOLUTION_METADATA_SCHEMA_VERSION = 1;
10
+ export declare const RESOLUTION_SELECTION_POLICY_VERSION = "1";
11
+ export declare const MAX_RESOLUTION_METADATA_ITEMS = 100;
12
+ export declare const MAX_RESOLUTION_METADATA_VERSIONS_PER_PAGE = 100;
13
+ export declare const MAX_RESOLUTION_METADATA_REQUEST_BYTES: number;
14
+ export declare const MAX_RESOLUTION_METADATA_RESPONSE_BYTES: number;
15
+ export declare const ResolutionMetadataIdentitySchema: Schema.Struct<{
16
+ readonly owner: Schema.brand<Schema.String, "Handle">;
17
+ readonly type: Schema.Literals<readonly ("skill" | "mcp-server" | "subagent" | "rule" | "hook" | "knowledge" | "pack")[]>;
18
+ readonly name: Schema.brand<Schema.NonEmptyString, "ExtensionName">;
19
+ }>;
20
+ export declare const ResolutionMetadataItemSchema: Schema.Union<readonly [Schema.Struct<{
21
+ readonly purpose: Schema.Literal<"select">;
22
+ readonly key: Schema.NonEmptyString;
23
+ readonly identity: Schema.Struct<{
24
+ readonly owner: Schema.brand<Schema.String, "Handle">;
25
+ readonly type: Schema.Literals<readonly ("skill" | "mcp-server" | "subagent" | "rule" | "hook" | "knowledge" | "pack")[]>;
26
+ readonly name: Schema.brand<Schema.NonEmptyString, "ExtensionName">;
27
+ }>;
28
+ readonly expectedPublisherBinding: Schema.optional<Schema.NonEmptyString>;
29
+ readonly knownRevision: Schema.optional<Schema.NonEmptyString>;
30
+ readonly continuation: Schema.optional<Schema.Struct<{
31
+ readonly token: Schema.NonEmptyString;
32
+ readonly revision: Schema.NonEmptyString;
33
+ }>>;
34
+ }>, Schema.Struct<{
35
+ readonly purpose: Schema.Literal<"restore-exact">;
36
+ readonly accepted: Schema.Struct<{
37
+ readonly version: Schema.brand<Schema.String, "Version">;
38
+ readonly integrity: Schema.NonEmptyString;
39
+ }>;
40
+ readonly key: Schema.NonEmptyString;
41
+ readonly identity: Schema.Struct<{
42
+ readonly owner: Schema.brand<Schema.String, "Handle">;
43
+ readonly type: Schema.Literals<readonly ("skill" | "mcp-server" | "subagent" | "rule" | "hook" | "knowledge" | "pack")[]>;
44
+ readonly name: Schema.brand<Schema.NonEmptyString, "ExtensionName">;
45
+ }>;
46
+ readonly expectedPublisherBinding: Schema.optional<Schema.NonEmptyString>;
47
+ readonly knownRevision: Schema.optional<Schema.NonEmptyString>;
48
+ readonly continuation: Schema.optional<Schema.Struct<{
49
+ readonly token: Schema.NonEmptyString;
50
+ readonly revision: Schema.NonEmptyString;
51
+ }>>;
52
+ }>]>;
53
+ export declare const ResolutionMetadataRequestSchema: Schema.Struct<{
54
+ readonly schemaVersion: Schema.Literal<1>;
55
+ readonly selectionPolicyVersion: Schema.Literal<"1">;
56
+ readonly items: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
57
+ readonly purpose: Schema.Literal<"select">;
58
+ readonly key: Schema.NonEmptyString;
59
+ readonly identity: Schema.Struct<{
60
+ readonly owner: Schema.brand<Schema.String, "Handle">;
61
+ readonly type: Schema.Literals<readonly ("skill" | "mcp-server" | "subagent" | "rule" | "hook" | "knowledge" | "pack")[]>;
62
+ readonly name: Schema.brand<Schema.NonEmptyString, "ExtensionName">;
63
+ }>;
64
+ readonly expectedPublisherBinding: Schema.optional<Schema.NonEmptyString>;
65
+ readonly knownRevision: Schema.optional<Schema.NonEmptyString>;
66
+ readonly continuation: Schema.optional<Schema.Struct<{
67
+ readonly token: Schema.NonEmptyString;
68
+ readonly revision: Schema.NonEmptyString;
69
+ }>>;
70
+ }>, Schema.Struct<{
71
+ readonly purpose: Schema.Literal<"restore-exact">;
72
+ readonly accepted: Schema.Struct<{
73
+ readonly version: Schema.brand<Schema.String, "Version">;
74
+ readonly integrity: Schema.NonEmptyString;
75
+ }>;
76
+ readonly key: Schema.NonEmptyString;
77
+ readonly identity: Schema.Struct<{
78
+ readonly owner: Schema.brand<Schema.String, "Handle">;
79
+ readonly type: Schema.Literals<readonly ("skill" | "mcp-server" | "subagent" | "rule" | "hook" | "knowledge" | "pack")[]>;
80
+ readonly name: Schema.brand<Schema.NonEmptyString, "ExtensionName">;
81
+ }>;
82
+ readonly expectedPublisherBinding: Schema.optional<Schema.NonEmptyString>;
83
+ readonly knownRevision: Schema.optional<Schema.NonEmptyString>;
84
+ readonly continuation: Schema.optional<Schema.Struct<{
85
+ readonly token: Schema.NonEmptyString;
86
+ readonly revision: Schema.NonEmptyString;
87
+ }>>;
88
+ }>]>>;
89
+ }>;
90
+ export type ResolutionMetadataRequest = typeof ResolutionMetadataRequestSchema.Type;
91
+ export declare const ResolutionMetadataOutcomeSchema: Schema.Union<readonly [Schema.Struct<{
92
+ readonly key: Schema.NonEmptyString;
93
+ readonly outcome: Schema.Literal<"metadata">;
94
+ readonly page: Schema.Struct<{
95
+ readonly versions: Schema.$Array<Schema.Struct<{
96
+ readonly version: Schema.brand<Schema.String, "Version">;
97
+ readonly published: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
98
+ readonly dependencies: Schema.optional<Schema.$Record<Schema.String, Schema.brand<Schema.NonEmptyString, "VersionRange">>>;
99
+ readonly packages: Schema.optional<Schema.$Array<Schema.Struct<{
100
+ readonly purl: Schema.brand<Schema.NonEmptyString, "PackageIdentityPurl">;
101
+ readonly versionRange: Schema.optional<Schema.brand<Schema.decodeTo<Schema.toType<Schema.Struct<{
102
+ readonly raw: Schema.NonEmptyString;
103
+ readonly scheme: Schema.NonEmptyString;
104
+ readonly constraints: Schema.$Array<Schema.Struct<{
105
+ readonly comparator: Schema.Literals<readonly ["=", "!=", "<", "<=", ">", ">="]>;
106
+ readonly version: Schema.NonEmptyString;
107
+ }>>;
108
+ }>>, Schema.NonEmptyString, never, never>, "VersRange">>;
109
+ }>>>;
110
+ readonly integrity: Schema.String;
111
+ readonly yankedAt: Schema.optional<Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>>;
112
+ readonly yankCategory: Schema.optional<Schema.String>;
113
+ readonly yankNotice: Schema.optional<Schema.String>;
114
+ }>>;
115
+ readonly continuation: Schema.NullOr<Schema.NonEmptyString>;
116
+ readonly description: Schema.optional<Schema.String>;
117
+ readonly repository: Schema.optional<Schema.Union<readonly [Schema.String, Schema.Struct<{
118
+ readonly type: Schema.optional<Schema.NonEmptyString>;
119
+ readonly url: Schema.NonEmptyString;
120
+ readonly directory: Schema.optional<Schema.NonEmptyString>;
121
+ }>]>>;
122
+ readonly bugs: Schema.optional<Schema.Union<readonly [Schema.String, Schema.Struct<{
123
+ readonly url: Schema.optional<Schema.NonEmptyString>;
124
+ readonly email: Schema.optional<Schema.NonEmptyString>;
125
+ }>]>>;
126
+ readonly license: Schema.optional<Schema.String>;
127
+ readonly authors: Schema.optional<Schema.$Array<Schema.Struct<{
128
+ readonly name: Schema.String;
129
+ readonly email: Schema.optional<Schema.String>;
130
+ readonly url: Schema.optional<Schema.String>;
131
+ }>>>;
132
+ readonly publisherBindingId: Schema.NonEmptyString;
133
+ readonly visibility: Schema.Literals<readonly ["public", "private"]>;
134
+ readonly archival: Schema.NullOr<Schema.Struct<{
135
+ readonly archivedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
136
+ readonly reason: Schema.optional<Schema.String>;
137
+ }>>;
138
+ readonly deprecation: Schema.NullOr<Schema.Union<readonly [Schema.Struct<{
139
+ readonly deprecatedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
140
+ readonly message: Schema.String;
141
+ readonly replacement: Schema.optional<Schema.Union<readonly [Schema.Struct<{
142
+ readonly status: Schema.Literal<"available">;
143
+ readonly fqn: Schema.String;
144
+ }>, Schema.Struct<{
145
+ readonly status: Schema.Literal<"unavailable">;
146
+ readonly fqn: Schema.optional<Schema.String>;
147
+ }>]>>;
148
+ }>, Schema.Struct<{
149
+ readonly deprecatedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
150
+ readonly message: Schema.optional<Schema.String>;
151
+ readonly replacement: Schema.Union<readonly [Schema.Struct<{
152
+ readonly status: Schema.Literal<"available">;
153
+ readonly fqn: Schema.String;
154
+ }>, Schema.Struct<{
155
+ readonly status: Schema.Literal<"unavailable">;
156
+ readonly fqn: Schema.optional<Schema.String>;
157
+ }>]>;
158
+ }>]>>;
159
+ readonly revision: Schema.NonEmptyString;
160
+ readonly observedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
161
+ readonly validUntil: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
162
+ }>;
163
+ }>, Schema.Struct<{
164
+ readonly exactVersion: Schema.optional<Schema.brand<Schema.String, "Version">>;
165
+ readonly publisherBindingId: Schema.NonEmptyString;
166
+ readonly visibility: Schema.Literals<readonly ["public", "private"]>;
167
+ readonly archival: Schema.NullOr<Schema.Struct<{
168
+ readonly archivedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
169
+ readonly reason: Schema.optional<Schema.String>;
170
+ }>>;
171
+ readonly deprecation: Schema.NullOr<Schema.Union<readonly [Schema.Struct<{
172
+ readonly deprecatedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
173
+ readonly message: Schema.String;
174
+ readonly replacement: Schema.optional<Schema.Union<readonly [Schema.Struct<{
175
+ readonly status: Schema.Literal<"available">;
176
+ readonly fqn: Schema.String;
177
+ }>, Schema.Struct<{
178
+ readonly status: Schema.Literal<"unavailable">;
179
+ readonly fqn: Schema.optional<Schema.String>;
180
+ }>]>>;
181
+ }>, Schema.Struct<{
182
+ readonly deprecatedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
183
+ readonly message: Schema.optional<Schema.String>;
184
+ readonly replacement: Schema.Union<readonly [Schema.Struct<{
185
+ readonly status: Schema.Literal<"available">;
186
+ readonly fqn: Schema.String;
187
+ }>, Schema.Struct<{
188
+ readonly status: Schema.Literal<"unavailable">;
189
+ readonly fqn: Schema.optional<Schema.String>;
190
+ }>]>;
191
+ }>]>>;
192
+ readonly revision: Schema.NonEmptyString;
193
+ readonly observedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
194
+ readonly validUntil: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
195
+ readonly key: Schema.NonEmptyString;
196
+ readonly outcome: Schema.Literal<"unchanged">;
197
+ }>, Schema.Struct<{
198
+ readonly key: Schema.NonEmptyString;
199
+ readonly outcome: Schema.Literal<"unavailable">;
200
+ }>, Schema.Struct<{
201
+ readonly key: Schema.NonEmptyString;
202
+ readonly outcome: Schema.Literal<"binding-conflict">;
203
+ readonly publisherBindingId: Schema.NonEmptyString;
204
+ }>, Schema.Struct<{
205
+ readonly key: Schema.NonEmptyString;
206
+ readonly outcome: Schema.Literal<"exact-conflict">;
207
+ readonly reason: Schema.Literals<readonly ["version-unavailable", "integrity-mismatch"]>;
208
+ }>, Schema.Struct<{
209
+ readonly key: Schema.NonEmptyString;
210
+ readonly outcome: Schema.Literal<"restart-required">;
211
+ readonly revision: Schema.NonEmptyString;
212
+ }>]>;
213
+ export type ResolutionMetadataOutcome = typeof ResolutionMetadataOutcomeSchema.Type;
214
+ export declare const ResolutionMetadataResponseSchema: Schema.Struct<{
215
+ readonly schemaVersion: Schema.Literal<1>;
216
+ readonly selectionPolicyVersion: Schema.Literal<"1">;
217
+ readonly observedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
218
+ readonly results: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
219
+ readonly key: Schema.NonEmptyString;
220
+ readonly outcome: Schema.Literal<"metadata">;
221
+ readonly page: Schema.Struct<{
222
+ readonly versions: Schema.$Array<Schema.Struct<{
223
+ readonly version: Schema.brand<Schema.String, "Version">;
224
+ readonly published: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
225
+ readonly dependencies: Schema.optional<Schema.$Record<Schema.String, Schema.brand<Schema.NonEmptyString, "VersionRange">>>;
226
+ readonly packages: Schema.optional<Schema.$Array<Schema.Struct<{
227
+ readonly purl: Schema.brand<Schema.NonEmptyString, "PackageIdentityPurl">;
228
+ readonly versionRange: Schema.optional<Schema.brand<Schema.decodeTo<Schema.toType<Schema.Struct<{
229
+ readonly raw: Schema.NonEmptyString;
230
+ readonly scheme: Schema.NonEmptyString;
231
+ readonly constraints: Schema.$Array<Schema.Struct<{
232
+ readonly comparator: Schema.Literals<readonly ["=", "!=", "<", "<=", ">", ">="]>;
233
+ readonly version: Schema.NonEmptyString;
234
+ }>>;
235
+ }>>, Schema.NonEmptyString, never, never>, "VersRange">>;
236
+ }>>>;
237
+ readonly integrity: Schema.String;
238
+ readonly yankedAt: Schema.optional<Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>>;
239
+ readonly yankCategory: Schema.optional<Schema.String>;
240
+ readonly yankNotice: Schema.optional<Schema.String>;
241
+ }>>;
242
+ readonly continuation: Schema.NullOr<Schema.NonEmptyString>;
243
+ readonly description: Schema.optional<Schema.String>;
244
+ readonly repository: Schema.optional<Schema.Union<readonly [Schema.String, Schema.Struct<{
245
+ readonly type: Schema.optional<Schema.NonEmptyString>;
246
+ readonly url: Schema.NonEmptyString;
247
+ readonly directory: Schema.optional<Schema.NonEmptyString>;
248
+ }>]>>;
249
+ readonly bugs: Schema.optional<Schema.Union<readonly [Schema.String, Schema.Struct<{
250
+ readonly url: Schema.optional<Schema.NonEmptyString>;
251
+ readonly email: Schema.optional<Schema.NonEmptyString>;
252
+ }>]>>;
253
+ readonly license: Schema.optional<Schema.String>;
254
+ readonly authors: Schema.optional<Schema.$Array<Schema.Struct<{
255
+ readonly name: Schema.String;
256
+ readonly email: Schema.optional<Schema.String>;
257
+ readonly url: Schema.optional<Schema.String>;
258
+ }>>>;
259
+ readonly publisherBindingId: Schema.NonEmptyString;
260
+ readonly visibility: Schema.Literals<readonly ["public", "private"]>;
261
+ readonly archival: Schema.NullOr<Schema.Struct<{
262
+ readonly archivedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
263
+ readonly reason: Schema.optional<Schema.String>;
264
+ }>>;
265
+ readonly deprecation: Schema.NullOr<Schema.Union<readonly [Schema.Struct<{
266
+ readonly deprecatedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
267
+ readonly message: Schema.String;
268
+ readonly replacement: Schema.optional<Schema.Union<readonly [Schema.Struct<{
269
+ readonly status: Schema.Literal<"available">;
270
+ readonly fqn: Schema.String;
271
+ }>, Schema.Struct<{
272
+ readonly status: Schema.Literal<"unavailable">;
273
+ readonly fqn: Schema.optional<Schema.String>;
274
+ }>]>>;
275
+ }>, Schema.Struct<{
276
+ readonly deprecatedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
277
+ readonly message: Schema.optional<Schema.String>;
278
+ readonly replacement: Schema.Union<readonly [Schema.Struct<{
279
+ readonly status: Schema.Literal<"available">;
280
+ readonly fqn: Schema.String;
281
+ }>, Schema.Struct<{
282
+ readonly status: Schema.Literal<"unavailable">;
283
+ readonly fqn: Schema.optional<Schema.String>;
284
+ }>]>;
285
+ }>]>>;
286
+ readonly revision: Schema.NonEmptyString;
287
+ readonly observedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
288
+ readonly validUntil: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
289
+ }>;
290
+ }>, Schema.Struct<{
291
+ readonly exactVersion: Schema.optional<Schema.brand<Schema.String, "Version">>;
292
+ readonly publisherBindingId: Schema.NonEmptyString;
293
+ readonly visibility: Schema.Literals<readonly ["public", "private"]>;
294
+ readonly archival: Schema.NullOr<Schema.Struct<{
295
+ readonly archivedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
296
+ readonly reason: Schema.optional<Schema.String>;
297
+ }>>;
298
+ readonly deprecation: Schema.NullOr<Schema.Union<readonly [Schema.Struct<{
299
+ readonly deprecatedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
300
+ readonly message: Schema.String;
301
+ readonly replacement: Schema.optional<Schema.Union<readonly [Schema.Struct<{
302
+ readonly status: Schema.Literal<"available">;
303
+ readonly fqn: Schema.String;
304
+ }>, Schema.Struct<{
305
+ readonly status: Schema.Literal<"unavailable">;
306
+ readonly fqn: Schema.optional<Schema.String>;
307
+ }>]>>;
308
+ }>, Schema.Struct<{
309
+ readonly deprecatedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
310
+ readonly message: Schema.optional<Schema.String>;
311
+ readonly replacement: Schema.Union<readonly [Schema.Struct<{
312
+ readonly status: Schema.Literal<"available">;
313
+ readonly fqn: Schema.String;
314
+ }>, Schema.Struct<{
315
+ readonly status: Schema.Literal<"unavailable">;
316
+ readonly fqn: Schema.optional<Schema.String>;
317
+ }>]>;
318
+ }>]>>;
319
+ readonly revision: Schema.NonEmptyString;
320
+ readonly observedAt: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
321
+ readonly validUntil: Schema.decodeTo<Schema.DateTimeUtc, Schema.String, never, never>;
322
+ readonly key: Schema.NonEmptyString;
323
+ readonly outcome: Schema.Literal<"unchanged">;
324
+ }>, Schema.Struct<{
325
+ readonly key: Schema.NonEmptyString;
326
+ readonly outcome: Schema.Literal<"unavailable">;
327
+ }>, Schema.Struct<{
328
+ readonly key: Schema.NonEmptyString;
329
+ readonly outcome: Schema.Literal<"binding-conflict">;
330
+ readonly publisherBindingId: Schema.NonEmptyString;
331
+ }>, Schema.Struct<{
332
+ readonly key: Schema.NonEmptyString;
333
+ readonly outcome: Schema.Literal<"exact-conflict">;
334
+ readonly reason: Schema.Literals<readonly ["version-unavailable", "integrity-mismatch"]>;
335
+ }>, Schema.Struct<{
336
+ readonly key: Schema.NonEmptyString;
337
+ readonly outcome: Schema.Literal<"restart-required">;
338
+ readonly revision: Schema.NonEmptyString;
339
+ }>]>>;
340
+ }>;
341
+ export type ResolutionMetadataResponse = typeof ResolutionMetadataResponseSchema.Type;
342
+ /** Validate the response against the submitted keys before consuming any page. */
343
+ export declare const resolutionMetadataResponseMatchesRequest: (request: ResolutionMetadataRequest, response: ResolutionMetadataResponse) => boolean;
344
+ export declare const ResolutionMetadataErrorSchema: Schema.Struct<{
345
+ readonly code: Schema.Literals<readonly ["invalid-request", "unsupported-schema-version", "unsupported-selection-policy-version", "request-too-large", "response-too-large", "backend-unavailable"]>;
346
+ readonly detail: Schema.String;
347
+ }>;
348
+ export type ResolutionMetadataError = typeof ResolutionMetadataErrorSchema.Type;
349
+ /** Apply the encoded body limit before parsing an untrusted request. */
350
+ export declare const decodeResolutionMetadataRequestBody: (body: Uint8Array) => Result.Result<ResolutionMetadataRequest, ResolutionMetadataError>;
351
+ //# sourceMappingURL=resolution-metadata.d.ts.map
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Repeat-safe Registry metadata query contract. Selection stays with the client;
3
+ * each response page is evidence for one authorized identity and revision.
4
+ *
5
+ * @experimental This API is unstable and may change without notice.
6
+ */
7
+ import * as Schema from "effect/Schema";
8
+ import * as Result from "effect/Result";
9
+ import { DateTimeUtcSchema } from "@agentxm/extension-model/unstable/date-time";
10
+ import { AuthorSchema, BugsSchema, ExtensionNameSchema, ExtensionTypeSchema, RepositorySchema, } from "@agentxm/extension-model/unstable/extensions/common";
11
+ import { HandleSchema } from "@agentxm/extension-model/unstable/extensions/handle";
12
+ import { VersionSchema } from "@agentxm/extension-model/unstable/version-constraints";
13
+ import { ArchivalViewSchema } from "@agentxm/extension-model/unstable/extensions/archival";
14
+ import { DeprecationViewSchema } from "@agentxm/extension-model/unstable/extensions/deprecation";
15
+ import { VersionEntrySchema } from "./schema.js";
16
+ export const RESOLUTION_METADATA_SCHEMA_VERSION = 1;
17
+ export const RESOLUTION_SELECTION_POLICY_VERSION = "1";
18
+ export const MAX_RESOLUTION_METADATA_ITEMS = 100;
19
+ export const MAX_RESOLUTION_METADATA_VERSIONS_PER_PAGE = 100;
20
+ export const MAX_RESOLUTION_METADATA_REQUEST_BYTES = 256 * 1024;
21
+ export const MAX_RESOLUTION_METADATA_RESPONSE_BYTES = 1024 * 1024;
22
+ export const ResolutionMetadataIdentitySchema = Schema.Struct({
23
+ owner: HandleSchema,
24
+ type: ExtensionTypeSchema,
25
+ name: ExtensionNameSchema,
26
+ }).annotate({ identifier: "ResolutionMetadataIdentity" });
27
+ const CallerKeySchema = Schema.NonEmptyString.check(Schema.isMaxLength(128)).annotate({
28
+ identifier: "ResolutionMetadataCallerKey",
29
+ description: "Opaque caller correlation key. It grants no identity or authority.",
30
+ });
31
+ const RevisionSchema = Schema.NonEmptyString.check(Schema.isMaxLength(256)).annotate({
32
+ identifier: "ResolutionMetadataRevision",
33
+ });
34
+ const ContinuationSchema = Schema.NonEmptyString.check(Schema.isMaxLength(2048)).annotate({
35
+ identifier: "ResolutionMetadataContinuation",
36
+ description: "Opaque token bound by the server to the request context and revision.",
37
+ });
38
+ const RequestEvidenceSchema = {
39
+ key: CallerKeySchema,
40
+ identity: ResolutionMetadataIdentitySchema,
41
+ expectedPublisherBinding: Schema.optional(Schema.NonEmptyString),
42
+ knownRevision: Schema.optional(RevisionSchema),
43
+ continuation: Schema.optional(Schema.Struct({ token: ContinuationSchema, revision: RevisionSchema })),
44
+ };
45
+ const SelectItemSchema = Schema.Struct({
46
+ ...RequestEvidenceSchema,
47
+ purpose: Schema.Literal("select"),
48
+ });
49
+ const RestoreExactItemSchema = Schema.Struct({
50
+ ...RequestEvidenceSchema,
51
+ purpose: Schema.Literal("restore-exact"),
52
+ accepted: Schema.Struct({
53
+ version: VersionSchema,
54
+ integrity: Schema.NonEmptyString,
55
+ }),
56
+ });
57
+ export const ResolutionMetadataItemSchema = Schema.Union([
58
+ SelectItemSchema,
59
+ RestoreExactItemSchema,
60
+ ]).check(Schema.makeFilter((item) => item.knownRevision === undefined || item.continuation === undefined
61
+ ? true
62
+ : "A continuation cannot also send a conditional revision"));
63
+ export const ResolutionMetadataRequestSchema = Schema.Struct({
64
+ schemaVersion: Schema.Literal(RESOLUTION_METADATA_SCHEMA_VERSION),
65
+ selectionPolicyVersion: Schema.Literal(RESOLUTION_SELECTION_POLICY_VERSION),
66
+ items: Schema.Array(ResolutionMetadataItemSchema).check(Schema.isMinLength(1), Schema.isMaxLength(MAX_RESOLUTION_METADATA_ITEMS), Schema.makeFilter((items) => new Set(items.map((item) => item.key)).size === items.length
67
+ ? true
68
+ : "Caller keys must be unique within a batch")),
69
+ }).annotate({ identifier: "ResolutionMetadataRequest" });
70
+ const CurrentEvidenceFieldsSchema = {
71
+ publisherBindingId: Schema.NonEmptyString,
72
+ visibility: Schema.Literals(["public", "private"]),
73
+ archival: Schema.NullOr(ArchivalViewSchema),
74
+ deprecation: Schema.NullOr(DeprecationViewSchema),
75
+ revision: RevisionSchema,
76
+ observedAt: DateTimeUtcSchema,
77
+ validUntil: DateTimeUtcSchema,
78
+ };
79
+ const MetadataFieldsSchema = {
80
+ ...CurrentEvidenceFieldsSchema,
81
+ description: Schema.optional(Schema.String),
82
+ repository: Schema.optional(RepositorySchema),
83
+ bugs: Schema.optional(BugsSchema),
84
+ license: Schema.optional(Schema.String),
85
+ authors: Schema.optional(Schema.Array(AuthorSchema)),
86
+ };
87
+ const MetadataPageSchema = Schema.Struct({
88
+ ...MetadataFieldsSchema,
89
+ versions: Schema.Array(VersionEntrySchema).check(Schema.isMinLength(1), Schema.isMaxLength(MAX_RESOLUTION_METADATA_VERSIONS_PER_PAGE)),
90
+ continuation: Schema.NullOr(ContinuationSchema),
91
+ }).annotate({ identifier: "ResolutionMetadataPage" });
92
+ const MetadataOutcomeSchema = Schema.Struct({
93
+ key: CallerKeySchema,
94
+ outcome: Schema.Literal("metadata"),
95
+ page: MetadataPageSchema,
96
+ });
97
+ const UnchangedOutcomeSchema = Schema.Struct({
98
+ key: CallerKeySchema,
99
+ outcome: Schema.Literal("unchanged"),
100
+ ...CurrentEvidenceFieldsSchema,
101
+ exactVersion: Schema.optional(VersionSchema),
102
+ });
103
+ const UnavailableOutcomeSchema = Schema.Struct({
104
+ key: CallerKeySchema,
105
+ outcome: Schema.Literal("unavailable"),
106
+ });
107
+ const BindingConflictOutcomeSchema = Schema.Struct({
108
+ key: CallerKeySchema,
109
+ outcome: Schema.Literal("binding-conflict"),
110
+ publisherBindingId: Schema.NonEmptyString,
111
+ });
112
+ const ExactConflictOutcomeSchema = Schema.Struct({
113
+ key: CallerKeySchema,
114
+ outcome: Schema.Literal("exact-conflict"),
115
+ reason: Schema.Literals(["version-unavailable", "integrity-mismatch"]),
116
+ });
117
+ const RestartRequiredOutcomeSchema = Schema.Struct({
118
+ key: CallerKeySchema,
119
+ outcome: Schema.Literal("restart-required"),
120
+ revision: RevisionSchema,
121
+ });
122
+ export const ResolutionMetadataOutcomeSchema = Schema.Union([
123
+ MetadataOutcomeSchema,
124
+ UnchangedOutcomeSchema,
125
+ UnavailableOutcomeSchema,
126
+ BindingConflictOutcomeSchema,
127
+ ExactConflictOutcomeSchema,
128
+ RestartRequiredOutcomeSchema,
129
+ ]);
130
+ export const ResolutionMetadataResponseSchema = Schema.Struct({
131
+ schemaVersion: Schema.Literal(RESOLUTION_METADATA_SCHEMA_VERSION),
132
+ selectionPolicyVersion: Schema.Literal(RESOLUTION_SELECTION_POLICY_VERSION),
133
+ observedAt: DateTimeUtcSchema,
134
+ results: Schema.Array(ResolutionMetadataOutcomeSchema).check(Schema.isMaxLength(MAX_RESOLUTION_METADATA_ITEMS)),
135
+ }).annotate({ identifier: "ResolutionMetadataResponse" });
136
+ /** Validate the response against the submitted keys before consuming any page. */
137
+ export const resolutionMetadataResponseMatchesRequest = (request, response) => response.results.length === request.items.length &&
138
+ response.results.every((result, index) => {
139
+ const item = request.items[index];
140
+ if (item === undefined || result.key !== item.key)
141
+ return false;
142
+ if (item.continuation === undefined)
143
+ return result.outcome !== "restart-required";
144
+ return (result.outcome !== "unchanged" &&
145
+ (result.outcome !== "metadata" || result.page.revision === item.continuation.revision));
146
+ });
147
+ export const ResolutionMetadataErrorSchema = Schema.Struct({
148
+ code: Schema.Literals([
149
+ "invalid-request",
150
+ "unsupported-schema-version",
151
+ "unsupported-selection-policy-version",
152
+ "request-too-large",
153
+ "response-too-large",
154
+ "backend-unavailable",
155
+ ]),
156
+ detail: Schema.String,
157
+ });
158
+ const decodeRequest = Schema.decodeUnknownResult(ResolutionMetadataRequestSchema);
159
+ const strictUtf8 = new TextDecoder("utf-8", { fatal: true });
160
+ /** Apply the encoded body limit before parsing an untrusted request. */
161
+ export const decodeResolutionMetadataRequestBody = (body) => {
162
+ if (body.byteLength > MAX_RESOLUTION_METADATA_REQUEST_BYTES) {
163
+ return Result.fail({
164
+ code: "request-too-large",
165
+ detail: "Resolution metadata request exceeds the encoded body limit.",
166
+ });
167
+ }
168
+ let input;
169
+ try {
170
+ input = JSON.parse(strictUtf8.decode(body));
171
+ }
172
+ catch {
173
+ return Result.fail({
174
+ code: "invalid-request",
175
+ detail: "Resolution metadata request is not valid UTF-8 JSON.",
176
+ });
177
+ }
178
+ if (typeof input === "object" && input !== null) {
179
+ if ("schemaVersion" in input && input.schemaVersion !== RESOLUTION_METADATA_SCHEMA_VERSION) {
180
+ return Result.fail({
181
+ code: "unsupported-schema-version",
182
+ detail: "Resolution metadata schema version is unsupported.",
183
+ });
184
+ }
185
+ if ("selectionPolicyVersion" in input &&
186
+ input.selectionPolicyVersion !== RESOLUTION_SELECTION_POLICY_VERSION) {
187
+ return Result.fail({
188
+ code: "unsupported-selection-policy-version",
189
+ detail: "Resolution selection policy version is unsupported.",
190
+ });
191
+ }
192
+ }
193
+ const decoded = decodeRequest(input, { onExcessProperty: "error" });
194
+ return Result.isFailure(decoded)
195
+ ? Result.fail({ code: "invalid-request", detail: "Resolution metadata request is invalid." })
196
+ : Result.succeed(decoded.success);
197
+ };
198
+ //# sourceMappingURL=resolution-metadata.js.map
package/package.json CHANGED
@@ -4,20 +4,21 @@
4
4
  "url": "https://github.com/agentxm/axm/issues"
5
5
  },
6
6
  "dependencies": {
7
- "@agentxm/extension-model": "0.31.1-preview.35463507166.59e3bf3d74da",
8
- "effect": "4.0.0-rc.115",
7
+ "@agentxm/extension-model": "^0.33.0",
8
+ "effect": "4.0.0-rc.117",
9
9
  "semver": "^7.8.5"
10
10
  },
11
11
  "description": "AgentXM Registry wire contracts: index, discovery, publication-set, visibility, authorization, and suggested-action schemas. Unstable and unsupported — use the axm.sh CLI.",
12
12
  "devDependencies": {
13
- "@effect/vitest": "4.0.0-rc.115",
13
+ "@agentxm/specification-metadata": "0.33.0",
14
+ "@effect/vitest": "4.0.0-rc.117",
14
15
  "@types/semver": "^7.7.1",
15
16
  "@typescript/native": "npm:typescript@^7.0.2",
16
17
  "typescript": "npm:@typescript/typescript6@^6.0.2",
17
18
  "vitest": "^5.0.0"
18
19
  },
19
20
  "engines": {
20
- "node": ">=22.19.0"
21
+ "node": ">=24.19.0"
21
22
  },
22
23
  "exports": {
23
24
  "./unstable/publish": {
@@ -36,6 +37,12 @@
36
37
  "types": "./dist/src/unstable/registry/publication-set.d.ts",
37
38
  "default": "./dist/src/unstable/registry/publication-set.js"
38
39
  },
40
+ "./unstable/registry/resolution-metadata": {
41
+ "types": "./dist/src/unstable/registry/resolution-metadata.d.ts",
42
+ "default": "./dist/src/unstable/registry/resolution-metadata.js"
43
+ },
44
+ "./unstable/registry/publication-set.vectors.json": "./publication-set.vectors.json",
45
+ "./unstable/registry/resolution-metadata.vectors.json": "./resolution-metadata.vectors.json",
39
46
  "./unstable/registry/schema": {
40
47
  "types": "./dist/src/unstable/registry/schema.d.ts",
41
48
  "default": "./dist/src/unstable/registry/schema.js"
@@ -51,6 +58,8 @@
51
58
  },
52
59
  "files": [
53
60
  "dist/src/",
61
+ "publication-set.vectors.json",
62
+ "resolution-metadata.vectors.json",
54
63
  "!**/*.map"
55
64
  ],
56
65
  "homepage": "https://axm.sh",
@@ -68,5 +77,5 @@
68
77
  "url": "https://github.com/agentxm/axm.git"
69
78
  },
70
79
  "type": "module",
71
- "version": "0.31.1-preview.35463507166.59e3bf3d74da"
80
+ "version": "0.33.0"
72
81
  }
@@ -0,0 +1,212 @@
1
+ {
2
+ "format": "agentxm-publication-set-digest-vectors-v1",
3
+ "contract": "publication-set-v2",
4
+ "canonicalization": {
5
+ "encoding": "Hash the UTF-8 bytes of JSON.stringify over the canonical object described by publication-set-v2.",
6
+ "objectKeys": "Reconstruct descriptor, target, visibility, intent, pack, dependency, and source objects in the contract's declared key order before hashing.",
7
+ "candidateOrder": "Sort candidates by owner, type, name, then version using ascending code-unit order.",
8
+ "dependencyOrder": "Sort pack dependencies by owner, type, name, range, then source URL using ascending code-unit order.",
9
+ "optionalFields": "Omit archiveSha256Hex and pack when absent. null is invalid for either optional field and must be rejected before hashing.",
10
+ "evolution": "A future digest algorithm must mint a new publication-set contract identifier and vector format; do not change these vectors in place."
11
+ },
12
+ "vectors": [
13
+ {
14
+ "name": "optional-fields-omitted",
15
+ "candidates": [
16
+ {
17
+ "descriptor": {
18
+ "target": {
19
+ "owner": "@acme",
20
+ "type": "skill",
21
+ "name": "existing",
22
+ "version": "1.0.0"
23
+ },
24
+ "participation": "verified-existing",
25
+ "visibility": {
26
+ "intent": null,
27
+ "request": null
28
+ }
29
+ },
30
+ "descriptorDigest": "b7aeb666fa2e467bbbf6e28e9b5299e3d3b5f3f9dce5f7a9dc7222df4aa6316a"
31
+ }
32
+ ],
33
+ "publicationSetDigest": "ef0e42506c66afc3d522df6179b3c6c4c12240f3a57c57f9d64ad2bffb19cef5"
34
+ },
35
+ {
36
+ "name": "visibility-input",
37
+ "candidates": [
38
+ {
39
+ "descriptor": {
40
+ "target": {
41
+ "owner": "@acme",
42
+ "type": "rule",
43
+ "name": "guard",
44
+ "version": "2.1.0"
45
+ },
46
+ "participation": "publish",
47
+ "visibility": {
48
+ "intent": {
49
+ "value": "private",
50
+ "source": "workspace",
51
+ "fingerprint": "2222222222222222222222222222222222222222222222222222222222222222"
52
+ },
53
+ "request": "public"
54
+ },
55
+ "archiveSha256Hex": "1111111111111111111111111111111111111111111111111111111111111111"
56
+ },
57
+ "descriptorDigest": "d6934f76c10be57d7ab7099e880ef28a5dfbecfe4eb706b1199e141901176a2b"
58
+ }
59
+ ],
60
+ "publicationSetDigest": "ad643e51e182bc14772ea42c8b6d3805a27d0657aac98ed45274bfa107581106"
61
+ },
62
+ {
63
+ "name": "pack-dependencies-and-candidate-order",
64
+ "candidates": [
65
+ {
66
+ "descriptor": {
67
+ "target": {
68
+ "owner": "@zeta",
69
+ "type": "pack",
70
+ "name": "team",
71
+ "version": "3.0.0"
72
+ },
73
+ "participation": "publish",
74
+ "visibility": {
75
+ "intent": null,
76
+ "request": null
77
+ },
78
+ "archiveSha256Hex": "3333333333333333333333333333333333333333333333333333333333333333",
79
+ "pack": {
80
+ "dependencies": [
81
+ {
82
+ "owner": "@zeta",
83
+ "type": "skill",
84
+ "name": "last",
85
+ "range": "^2.0.0"
86
+ },
87
+ {
88
+ "owner": "@acme",
89
+ "type": "rule",
90
+ "name": "guard",
91
+ "range": "^2.1.0"
92
+ }
93
+ ]
94
+ }
95
+ },
96
+ "descriptorDigest": "34ebd67ef59afc296b921716ca98bbdd48548466896ca636bd16499e333d7273"
97
+ },
98
+ {
99
+ "descriptor": {
100
+ "target": {
101
+ "owner": "@acme",
102
+ "type": "skill",
103
+ "name": "review",
104
+ "version": "1.2.0"
105
+ },
106
+ "participation": "publish",
107
+ "visibility": {
108
+ "intent": null,
109
+ "request": "public"
110
+ },
111
+ "archiveSha256Hex": "4444444444444444444444444444444444444444444444444444444444444444"
112
+ },
113
+ "descriptorDigest": "a480ea68a556dc3e00e8b037c43a97a2ea385a45ab0fad28262d555f1393133b"
114
+ }
115
+ ],
116
+ "publicationSetDigest": "2fd0aa0d5e79a03feceb16307aa87e79d0f8056e87a59678ec9675b638f6016e"
117
+ },
118
+ {
119
+ "name": "explicit-registry-pack-member-source",
120
+ "candidates": [
121
+ {
122
+ "descriptor": {
123
+ "target": {
124
+ "owner": "@acme",
125
+ "type": "pack",
126
+ "name": "sourced",
127
+ "version": "1.0.0"
128
+ },
129
+ "participation": "publish",
130
+ "visibility": {
131
+ "intent": null,
132
+ "request": null
133
+ },
134
+ "archiveSha256Hex": "5555555555555555555555555555555555555555555555555555555555555555",
135
+ "pack": {
136
+ "dependencies": [
137
+ {
138
+ "owner": "@agentxm",
139
+ "type": "skill",
140
+ "name": "axm",
141
+ "range": "^0.30.0",
142
+ "source": {
143
+ "type": "registry",
144
+ "url": "https://registry.agentxm.ai/"
145
+ }
146
+ }
147
+ ]
148
+ }
149
+ },
150
+ "descriptorDigest": "900b5e53eaa7dfb07e67d84d068c31219994ee5c26851a6953f438dbcdd0199d"
151
+ }
152
+ ],
153
+ "publicationSetDigest": "5ca9029cd0220ff349925a7872a6e7a9422fc2f0ab185f7c5d87fecd2e707828"
154
+ },
155
+ {
156
+ "name": "original-publication-set-v2-pins",
157
+ "candidates": [
158
+ {
159
+ "descriptor": {
160
+ "target": {
161
+ "owner": "@acme",
162
+ "type": "pack",
163
+ "name": "team",
164
+ "version": "2.0.0"
165
+ },
166
+ "participation": "publish",
167
+ "visibility": {
168
+ "intent": null,
169
+ "request": null
170
+ },
171
+ "archiveSha256Hex": "4862f447f2c7f272fa2f4aaf89dadb3b1ac09105bd5864f8d1a0c9452bb0a226",
172
+ "pack": {
173
+ "dependencies": [
174
+ {
175
+ "owner": "@zeta",
176
+ "type": "skill",
177
+ "name": "last",
178
+ "range": "^1.0.0"
179
+ },
180
+ {
181
+ "owner": "@acme",
182
+ "type": "skill",
183
+ "name": "review",
184
+ "range": "^1.2.0"
185
+ }
186
+ ]
187
+ }
188
+ },
189
+ "descriptorDigest": "f7ee37ff8488e6b4ef99514496ad85f40153fb6defee0e511f9d5342cb60f50d"
190
+ },
191
+ {
192
+ "descriptor": {
193
+ "target": {
194
+ "owner": "@acme",
195
+ "type": "skill",
196
+ "name": "review",
197
+ "version": "1.2.0"
198
+ },
199
+ "participation": "publish",
200
+ "visibility": {
201
+ "intent": null,
202
+ "request": "public"
203
+ },
204
+ "archiveSha256Hex": "9c53c074d7ac6a2728b638ac1f376c5fa9eb8f71603017c3ea638c2fd40548df"
205
+ },
206
+ "descriptorDigest": "7700a3c2b2ff0caffd0d3da12a4c5c13b338b0adb557979ce9cbceb899670c5b"
207
+ }
208
+ ],
209
+ "publicationSetDigest": "a7d28ff4005c1596cd373060c13279a58469573e49685fe17b8d767b4c210c6c"
210
+ }
211
+ ]
212
+ }
@@ -0,0 +1,177 @@
1
+ {
2
+ "format": "agentxm-resolution-metadata-vectors-v1",
3
+ "selectionPolicyVersion": "1",
4
+ "evaluatedAt": "2026-09-22T12:00:00Z",
5
+ "cases": [
6
+ {
7
+ "name": "ordinary-range-excludes-yanked-release",
8
+ "source": "direct",
9
+ "index": {
10
+ "owner": "@acme",
11
+ "type": "skill",
12
+ "name": "review",
13
+ "publisherBindingId": "hbnd_acme",
14
+ "archival": null,
15
+ "deprecation": null,
16
+ "versions": [
17
+ {
18
+ "version": "1.1.0",
19
+ "published": "2026-09-18T12:00:00Z",
20
+ "integrity": "sha512-yanked",
21
+ "yankedAt": "2026-09-19T12:00:00Z"
22
+ },
23
+ { "version": "1.0.0", "published": "2026-09-15T12:00:00Z", "integrity": "sha512-stable" }
24
+ ]
25
+ },
26
+ "request": { "purpose": "select", "range": "^1.0.0", "minimumReleaseAgeSeconds": 0 },
27
+ "expected": { "kind": "selected", "version": "1.0.0" }
28
+ },
29
+ {
30
+ "name": "exact-pin-retains-yank-warning",
31
+ "source": "direct",
32
+ "index": {
33
+ "owner": "@acme",
34
+ "type": "skill",
35
+ "name": "review",
36
+ "publisherBindingId": "hbnd_acme",
37
+ "archival": null,
38
+ "deprecation": null,
39
+ "versions": [
40
+ {
41
+ "version": "1.1.0",
42
+ "published": "2026-09-18T12:00:00Z",
43
+ "integrity": "sha512-yanked",
44
+ "yankedAt": "2026-09-19T12:00:00Z",
45
+ "yankedCategory": "superseded"
46
+ },
47
+ { "version": "1.0.0", "published": "2026-09-15T12:00:00Z", "integrity": "sha512-stable" }
48
+ ]
49
+ },
50
+ "request": {
51
+ "purpose": "restore-exact",
52
+ "range": "1.1.0",
53
+ "acceptedIntegrity": "sha512-yanked",
54
+ "minimumReleaseAgeSeconds": 0
55
+ },
56
+ "expected": { "kind": "selected", "version": "1.1.0", "warning": "yanked" }
57
+ },
58
+ {
59
+ "name": "minimum-release-age-holds-newer-release",
60
+ "source": "direct",
61
+ "index": {
62
+ "owner": "@acme",
63
+ "type": "skill",
64
+ "name": "review",
65
+ "publisherBindingId": "hbnd_acme",
66
+ "archival": null,
67
+ "deprecation": null,
68
+ "versions": [
69
+ { "version": "2.0.0", "published": "2026-09-22T00:00:00Z", "integrity": "sha512-new" },
70
+ { "version": "1.0.0", "published": "2026-09-15T12:00:00Z", "integrity": "sha512-stable" }
71
+ ]
72
+ },
73
+ "request": { "purpose": "select", "range": "*", "minimumReleaseAgeSeconds": 86400 },
74
+ "expected": { "kind": "selected", "version": "1.0.0", "newerHeld": "2.0.0" }
75
+ },
76
+ {
77
+ "name": "direct-constraint-selects-highest-satisfying-release",
78
+ "source": "direct",
79
+ "index": {
80
+ "owner": "@acme",
81
+ "type": "skill",
82
+ "name": "review",
83
+ "publisherBindingId": "hbnd_acme",
84
+ "archival": null,
85
+ "deprecation": null,
86
+ "versions": [
87
+ { "version": "2.0.0", "published": "2026-09-15T12:00:00Z", "integrity": "sha512-two" },
88
+ { "version": "1.2.0", "published": "2026-09-14T12:00:00Z", "integrity": "sha512-one-two" }
89
+ ]
90
+ },
91
+ "request": { "purpose": "select", "range": "^1.0.0", "minimumReleaseAgeSeconds": 0 },
92
+ "expected": { "kind": "selected", "version": "1.2.0" }
93
+ },
94
+ {
95
+ "name": "pack-member-constraint-keeps-member-range",
96
+ "source": "pack-member",
97
+ "index": {
98
+ "owner": "@acme",
99
+ "type": "skill",
100
+ "name": "review",
101
+ "publisherBindingId": "hbnd_acme",
102
+ "archival": null,
103
+ "deprecation": null,
104
+ "versions": [
105
+ {
106
+ "version": "1.1.0",
107
+ "published": "2026-09-15T12:00:00Z",
108
+ "integrity": "sha512-one-one"
109
+ },
110
+ {
111
+ "version": "1.0.5",
112
+ "published": "2026-09-14T12:00:00Z",
113
+ "integrity": "sha512-one-zero-five"
114
+ }
115
+ ]
116
+ },
117
+ "request": { "purpose": "select", "range": "~1.0.0", "minimumReleaseAgeSeconds": 0 },
118
+ "expected": { "kind": "selected", "version": "1.0.5" }
119
+ },
120
+ {
121
+ "name": "package-compatibility-remains-version-scoped",
122
+ "source": "direct",
123
+ "index": {
124
+ "owner": "@acme",
125
+ "type": "skill",
126
+ "name": "review",
127
+ "publisherBindingId": "hbnd_acme",
128
+ "archival": null,
129
+ "deprecation": null,
130
+ "versions": [
131
+ {
132
+ "version": "1.1.0",
133
+ "published": "2026-09-15T12:00:00Z",
134
+ "integrity": "sha512-one-one",
135
+ "packages": [{ "purl": "pkg:npm/%40acme/core", "versionRange": "vers:npm/>=2.0.0" }]
136
+ },
137
+ {
138
+ "version": "1.0.0",
139
+ "published": "2026-09-14T12:00:00Z",
140
+ "integrity": "sha512-one-zero",
141
+ "packages": [{ "purl": "pkg:npm/%40acme/core", "versionRange": "vers:npm/<2.0.0" }]
142
+ }
143
+ ]
144
+ },
145
+ "request": {
146
+ "purpose": "select",
147
+ "range": "^1.0.0",
148
+ "minimumReleaseAgeSeconds": 0,
149
+ "compatiblePackage": { "purl": "pkg:npm/%40acme/core", "version": "2.1.0" }
150
+ },
151
+ "expected": { "kind": "selected", "version": "1.1.0" }
152
+ },
153
+ {
154
+ "name": "publisher-binding-change-refuses-accepted-identity",
155
+ "source": "direct",
156
+ "index": {
157
+ "owner": "@acme",
158
+ "type": "skill",
159
+ "name": "review",
160
+ "publisherBindingId": "hbnd_current",
161
+ "archival": null,
162
+ "deprecation": null,
163
+ "versions": [
164
+ { "version": "1.0.0", "published": "2026-09-15T12:00:00Z", "integrity": "sha512-stable" }
165
+ ]
166
+ },
167
+ "request": {
168
+ "purpose": "restore-exact",
169
+ "range": "1.0.0",
170
+ "acceptedIntegrity": "sha512-stable",
171
+ "expectedPublisherBinding": "hbnd_previous",
172
+ "minimumReleaseAgeSeconds": 0
173
+ },
174
+ "expected": { "kind": "binding-conflict" }
175
+ }
176
+ ]
177
+ }