@ggui-ai/artifact-manifest 0.2.0-alpha.4 → 0.3.0-rc.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 +8 -8
- package/dist/artifact-manifest.d.ts +2 -5
- package/dist/artifact-manifest.d.ts.map +1 -1
- package/dist/artifact-manifest.js +0 -7
- package/dist/base.d.ts +8 -8
- package/dist/base.js +8 -8
- package/dist/blueprint-manifest.d.ts +18 -18
- package/dist/blueprint-manifest.d.ts.map +1 -1
- package/dist/blueprint-manifest.js +30 -24
- package/dist/gadget-manifest.d.ts +2 -9
- package/dist/gadget-manifest.d.ts.map +1 -1
- package/dist/gadget-manifest.js +2 -11
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -3
- package/dist/pool-artifact.d.ts +101 -0
- package/dist/pool-artifact.d.ts.map +1 -0
- package/dist/pool-artifact.js +144 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -34,14 +34,14 @@ const artifact = parseArtifactManifest(json);
|
|
|
34
34
|
|
|
35
35
|
## Exports
|
|
36
36
|
|
|
37
|
-
| Symbol
|
|
38
|
-
|
|
|
39
|
-
| `gadgetManifestSchema`, `parseGadgetManifest`, `safeParseGadgetManifest
|
|
40
|
-
| `blueprintManifestSchema`, `parseBlueprintManifest`, `safeParseBlueprintManifest
|
|
41
|
-
| `artifactManifestSchema`, `parseArtifactManifest`, `safeParseArtifactManifest
|
|
42
|
-
| `manifestToRegistryEntry`
|
|
43
|
-
| `GADGET_NAME_RE`, `BLUEPRINT_NAME_RE`, `ArtifactScopeSchema`, `ArtifactVersionSchema`
|
|
44
|
-
| `GGUI_GADGET_JSON_FILENAME`, `GGUI_BLUEPRINT_JSON_FILENAME`
|
|
37
|
+
| Symbol | What it is |
|
|
38
|
+
| ------------------------------------------------------------------------------------- | ------------------------------------------ |
|
|
39
|
+
| `gadgetManifestSchema`, `parseGadgetManifest`, `safeParseGadgetManifest` | Gadget manifest schema + parsers |
|
|
40
|
+
| `blueprintManifestSchema`, `parseBlueprintManifest`, `safeParseBlueprintManifest` | Blueprint manifest schema + parsers |
|
|
41
|
+
| `artifactManifestSchema`, `parseArtifactManifest`, `safeParseArtifactManifest` | Discriminated union over both kinds |
|
|
42
|
+
| `manifestToRegistryEntry` | Translate a manifest into a registry entry |
|
|
43
|
+
| `GADGET_NAME_RE`, `BLUEPRINT_NAME_RE`, `ArtifactScopeSchema`, `ArtifactVersionSchema` | Shared name + version validators |
|
|
44
|
+
| `GGUI_GADGET_JSON_FILENAME`, `GGUI_BLUEPRINT_JSON_FILENAME` | Canonical manifest filenames |
|
|
45
45
|
|
|
46
46
|
`GadgetManifest`, `BlueprintManifest`, and `ArtifactManifest` types are exported alongside their schemas.
|
|
47
47
|
|
|
@@ -89,6 +89,8 @@ export declare const artifactManifestSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
|
|
|
89
89
|
contract: z.ZodOptional<z.ZodType<import("@ggui-ai/protocol").DataContract, unknown, z.core.$ZodTypeInternals<import("@ggui-ai/protocol").DataContract, unknown>>>;
|
|
90
90
|
fixtureProps: z.ZodOptional<z.ZodUnknown>;
|
|
91
91
|
variance: z.ZodOptional<z.ZodType<import("@ggui-ai/protocol").BlueprintVariance, unknown, z.core.$ZodTypeInternals<import("@ggui-ai/protocol").BlueprintVariance, unknown>>>;
|
|
92
|
+
generatorProtocolVersion: z.ZodOptional<z.ZodString>;
|
|
93
|
+
toolIdentityCatalogHash: z.ZodOptional<z.ZodString>;
|
|
92
94
|
}, z.core.$strict>], "kind">;
|
|
93
95
|
/**
|
|
94
96
|
* Static TypeScript type derived from {@link artifactManifestSchema}.
|
|
@@ -104,11 +106,6 @@ export type ArtifactManifest = z.infer<typeof artifactManifestSchema>;
|
|
|
104
106
|
* including unknown / missing `kind` discriminator at `path: ["kind"]`.
|
|
105
107
|
*/
|
|
106
108
|
export declare function parseArtifactManifest(raw: unknown): ArtifactManifest;
|
|
107
|
-
/**
|
|
108
|
-
* Assertion helper — narrows `raw` to {@link ArtifactManifest} on
|
|
109
|
-
* success, throws `ZodError` on failure.
|
|
110
|
-
*/
|
|
111
|
-
export declare function assertArtifactManifestValid(raw: unknown): asserts raw is ArtifactManifest;
|
|
112
109
|
/**
|
|
113
110
|
* Safe-parse variant — returns a `z.safeParse` result. Prefer this
|
|
114
111
|
* inside CLI tooling where you want to render the issue list without
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"artifact-manifest.d.ts","sourceRoot":"","sources":["../src/artifact-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"artifact-manifest.d.ts","sourceRoot":"","sources":["../src/artifact-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAGjC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAatE;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAEpE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,sBAAsB,CAAC,SAAS,CAAC,CAErD"}
|
|
@@ -52,13 +52,6 @@ void _artifactUnionTypeCheck;
|
|
|
52
52
|
export function parseArtifactManifest(raw) {
|
|
53
53
|
return artifactManifestSchema.parse(raw);
|
|
54
54
|
}
|
|
55
|
-
/**
|
|
56
|
-
* Assertion helper — narrows `raw` to {@link ArtifactManifest} on
|
|
57
|
-
* success, throws `ZodError` on failure.
|
|
58
|
-
*/
|
|
59
|
-
export function assertArtifactManifestValid(raw) {
|
|
60
|
-
artifactManifestSchema.parse(raw);
|
|
61
|
-
}
|
|
62
55
|
/**
|
|
63
56
|
* Safe-parse variant — returns a `z.safeParse` result. Prefer this
|
|
64
57
|
* inside CLI tooling where you want to render the issue list without
|
package/dist/base.d.ts
CHANGED
|
@@ -52,17 +52,17 @@ export declare const BLUEPRINT_NAME_RE: RegExp;
|
|
|
52
52
|
*/
|
|
53
53
|
export declare const ArtifactVersionSchema: z.ZodString;
|
|
54
54
|
/**
|
|
55
|
-
* Visibility — controls how the artifact is
|
|
55
|
+
* Visibility — controls how the artifact is signed + distributed:
|
|
56
56
|
*
|
|
57
|
-
* - `public` — sigstore-signed,
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* with signed CloudFront URLs, only visible to the
|
|
61
|
-
* publisher's Cognito org.
|
|
57
|
+
* - `public` — sigstore-signed, publicly listable via `/search`.
|
|
58
|
+
* - `private` — Ed25519-signed, scoped to the publisher's org;
|
|
59
|
+
* never publicly listable.
|
|
62
60
|
*
|
|
63
61
|
* Both paths land in the same registry stack; the visibility flag
|
|
64
|
-
* picks the signing trust chain
|
|
65
|
-
*
|
|
62
|
+
* picks the signing trust chain at publish time. How a registry
|
|
63
|
+
* implementation partitions storage or gates download URLs per
|
|
64
|
+
* visibility is the storage adapter's concern. No "internal" /
|
|
65
|
+
* "team" third option in MVP.
|
|
66
66
|
*/
|
|
67
67
|
export declare const ArtifactVisibilitySchema: z.ZodEnum<{
|
|
68
68
|
public: "public";
|
package/dist/base.js
CHANGED
|
@@ -60,17 +60,17 @@ export const ArtifactVersionSchema = z
|
|
|
60
60
|
message: 'version must be valid semver (MAJOR.MINOR.PATCH with optional `-pre` / `+build`).',
|
|
61
61
|
});
|
|
62
62
|
/**
|
|
63
|
-
* Visibility — controls how the artifact is
|
|
63
|
+
* Visibility — controls how the artifact is signed + distributed:
|
|
64
64
|
*
|
|
65
|
-
* - `public` — sigstore-signed,
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* with signed CloudFront URLs, only visible to the
|
|
69
|
-
* publisher's Cognito org.
|
|
65
|
+
* - `public` — sigstore-signed, publicly listable via `/search`.
|
|
66
|
+
* - `private` — Ed25519-signed, scoped to the publisher's org;
|
|
67
|
+
* never publicly listable.
|
|
70
68
|
*
|
|
71
69
|
* Both paths land in the same registry stack; the visibility flag
|
|
72
|
-
* picks the signing trust chain
|
|
73
|
-
*
|
|
70
|
+
* picks the signing trust chain at publish time. How a registry
|
|
71
|
+
* implementation partitions storage or gates download URLs per
|
|
72
|
+
* visibility is the storage adapter's concern. No "internal" /
|
|
73
|
+
* "team" third option in MVP.
|
|
74
74
|
*/
|
|
75
75
|
export const ArtifactVisibilitySchema = z.enum(['public', 'private']);
|
|
76
76
|
/**
|
|
@@ -14,21 +14,24 @@
|
|
|
14
14
|
* hints that drive the LLM-driven variant selector when multiple
|
|
15
15
|
* blueprints share a `(appId, contractHash)` group.
|
|
16
16
|
*
|
|
17
|
-
* ##
|
|
17
|
+
* ## Relation to `ggui_ops_register_blueprint`
|
|
18
18
|
*
|
|
19
|
-
* The
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* `contract` / `fixtureProps` fields mirror that envelope exactly
|
|
24
|
-
* — round-tripping a blueprint through
|
|
25
|
-
* `ggui_ops_register_blueprint` then exporting it back into a
|
|
26
|
-
* `ggui.blueprint.json` must not require any field rewriting beyond
|
|
27
|
-
* adding the marketplace identity (`scope`, `name`, `version`,
|
|
28
|
-
* `kind`, `visibility`) and optional variance tags.
|
|
19
|
+
* The operator registration tool `ggui_ops_register_blueprint`
|
|
20
|
+
* (`@ggui-ai/mcp-server-handlers`) takes `{contract, componentCode,
|
|
21
|
+
* generator?, persona?, aesthetic?, context?, seedPrompt?,
|
|
22
|
+
* setAsOperatorDefault?}`. Mapping a manifest onto that envelope:
|
|
29
23
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
24
|
+
* - `source` → `componentCode` (verbatim TSX body).
|
|
25
|
+
* - `contract` → `contract` (optional on the manifest,
|
|
26
|
+
* REQUIRED by the tool — a contract-less
|
|
27
|
+
* manifest cannot be registered as-is).
|
|
28
|
+
* - `variance` → the flat `persona` / `aesthetic` /
|
|
29
|
+
* `context` / `seedPrompt` fields.
|
|
30
|
+
* - `fixtureProps` → no counterpart. Conformance-gate-only:
|
|
31
|
+
* consumed by the registry's runtime probe,
|
|
32
|
+
* never sent on the register envelope.
|
|
33
|
+
* - marketplace identity (`scope`, `name`, `version`, `kind`,
|
|
34
|
+
* `visibility`) → no counterpart; registry-side only.
|
|
32
35
|
*
|
|
33
36
|
* ## Why no `matchers` field
|
|
34
37
|
*
|
|
@@ -88,6 +91,8 @@ export declare const blueprintManifestSchema: z.ZodObject<{
|
|
|
88
91
|
contract: z.ZodOptional<z.ZodType<DataContract, unknown, z.core.$ZodTypeInternals<DataContract, unknown>>>;
|
|
89
92
|
fixtureProps: z.ZodOptional<z.ZodUnknown>;
|
|
90
93
|
variance: z.ZodOptional<z.ZodType<BlueprintVariance, unknown, z.core.$ZodTypeInternals<BlueprintVariance, unknown>>>;
|
|
94
|
+
generatorProtocolVersion: z.ZodOptional<z.ZodString>;
|
|
95
|
+
toolIdentityCatalogHash: z.ZodOptional<z.ZodString>;
|
|
91
96
|
}, z.core.$strict>;
|
|
92
97
|
/**
|
|
93
98
|
* Static TypeScript type derived from {@link blueprintManifestSchema}.
|
|
@@ -113,11 +118,6 @@ export declare const GGUI_BLUEPRINT_JSON_FILENAME = "ggui.blueprint.json";
|
|
|
113
118
|
* decoded the JSON (`JSON.parse(source)`).
|
|
114
119
|
*/
|
|
115
120
|
export declare function parseBlueprintManifest(raw: unknown): BlueprintManifest;
|
|
116
|
-
/**
|
|
117
|
-
* Assertion helper — narrows `raw` to {@link BlueprintManifest} on
|
|
118
|
-
* success, throws `ZodError` on failure.
|
|
119
|
-
*/
|
|
120
|
-
export declare function assertBlueprintManifestValid(raw: unknown): asserts raw is BlueprintManifest;
|
|
121
121
|
/**
|
|
122
122
|
* Safe-parse variant — returns a discriminated `z.safeParse` result
|
|
123
123
|
* (`{ success: true, data }` vs `{ success: false, error }`).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blueprint-manifest.d.ts","sourceRoot":"","sources":["../src/blueprint-manifest.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"blueprint-manifest.d.ts","sourceRoot":"","sources":["../src/blueprint-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAGlB,MAAM,mBAAmB,CAAC;AA+B3B;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;kBAiElC,CAAC;AAEH;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAmBxE;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,wBAAwB,CAAC;AAElE;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,iBAAiB,CAEtE;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,uBAAuB,CAAC,SAAS,CAAC,CAEtD"}
|
|
@@ -14,21 +14,24 @@
|
|
|
14
14
|
* hints that drive the LLM-driven variant selector when multiple
|
|
15
15
|
* blueprints share a `(appId, contractHash)` group.
|
|
16
16
|
*
|
|
17
|
-
* ##
|
|
17
|
+
* ## Relation to `ggui_ops_register_blueprint`
|
|
18
18
|
*
|
|
19
|
-
* The
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* `contract` / `fixtureProps` fields mirror that envelope exactly
|
|
24
|
-
* — round-tripping a blueprint through
|
|
25
|
-
* `ggui_ops_register_blueprint` then exporting it back into a
|
|
26
|
-
* `ggui.blueprint.json` must not require any field rewriting beyond
|
|
27
|
-
* adding the marketplace identity (`scope`, `name`, `version`,
|
|
28
|
-
* `kind`, `visibility`) and optional variance tags.
|
|
19
|
+
* The operator registration tool `ggui_ops_register_blueprint`
|
|
20
|
+
* (`@ggui-ai/mcp-server-handlers`) takes `{contract, componentCode,
|
|
21
|
+
* generator?, persona?, aesthetic?, context?, seedPrompt?,
|
|
22
|
+
* setAsOperatorDefault?}`. Mapping a manifest onto that envelope:
|
|
29
23
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
24
|
+
* - `source` → `componentCode` (verbatim TSX body).
|
|
25
|
+
* - `contract` → `contract` (optional on the manifest,
|
|
26
|
+
* REQUIRED by the tool — a contract-less
|
|
27
|
+
* manifest cannot be registered as-is).
|
|
28
|
+
* - `variance` → the flat `persona` / `aesthetic` /
|
|
29
|
+
* `context` / `seedPrompt` fields.
|
|
30
|
+
* - `fixtureProps` → no counterpart. Conformance-gate-only:
|
|
31
|
+
* consumed by the registry's runtime probe,
|
|
32
|
+
* never sent on the register envelope.
|
|
33
|
+
* - marketplace identity (`scope`, `name`, `version`, `kind`,
|
|
34
|
+
* `visibility`) → no counterpart; registry-side only.
|
|
32
35
|
*
|
|
33
36
|
* ## Why no `matchers` field
|
|
34
37
|
*
|
|
@@ -70,8 +73,7 @@ const BlueprintNameSchema = z.string().min(2).max(64).regex(BLUEPRINT_NAME_RE, {
|
|
|
70
73
|
* runtime probe round-trips it through `JSON.stringify` and feeds it
|
|
71
74
|
* as `props` to the rendered TSX. Any JSON-safe shape rides through;
|
|
72
75
|
* the blueprint's own `contract.propsSchema` (when present) is what
|
|
73
|
-
* actually validates the shape at runtime probe time.
|
|
74
|
-
* in-process register-blueprint's `fixtureProps: z.unknown().optional()`.
|
|
76
|
+
* actually validates the shape at runtime probe time.
|
|
75
77
|
*
|
|
76
78
|
* `z.unknown()` is permitted here (not `Record<string, unknown>`)
|
|
77
79
|
* because the value is genuinely shape-unknown at THIS layer — only
|
|
@@ -94,13 +96,13 @@ export const blueprintManifestSchema = z.strictObject({
|
|
|
94
96
|
.describe('Discriminator — picks the blueprint variant of the artifact-manifest union. MUST be the literal string `"blueprint"`.'),
|
|
95
97
|
// ---- Identity (required) ----
|
|
96
98
|
scope: ArtifactScopeSchema.describe('Blueprint scope. Must start with `@` (e.g. `@my-org`). Disambiguates the `<scope>/<name>` install identifier.'),
|
|
97
|
-
name: BlueprintNameSchema.describe('Blueprint slug. 2-64 chars, `^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$` — kebab-case, no underscores, no single-character names. Unified with the gadget naming rule under LOCKED-25 (2026-05-18).
|
|
99
|
+
name: BlueprintNameSchema.describe('Blueprint slug. 2-64 chars, `^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$` — kebab-case, no underscores, no single-character names. Unified with the gadget naming rule under LOCKED-25 (2026-05-18).'),
|
|
98
100
|
version: ArtifactVersionSchema.describe('SemVer. `MAJOR.MINOR.PATCH` with optional `-pre` / `+build` suffixes. Per-version immutable once published.'),
|
|
99
101
|
// ---- Core blueprint shape (required: source) ----
|
|
100
102
|
source: z
|
|
101
103
|
.string()
|
|
102
104
|
.min(1)
|
|
103
|
-
.describe('TSX source body with a default-exported React component.
|
|
105
|
+
.describe('TSX source body with a default-exported React component. Maps to `ggui_ops_register_blueprint`’s `componentCode` field; the conformance gate compiles + runtime-probes this string before the registry accepts the upload.'),
|
|
104
106
|
visibility: ArtifactVisibilitySchema.describe('Storage + signing posture. `public` = sigstore-signed, listable; `private` = Ed25519-signed, visible only within publisher org.'),
|
|
105
107
|
// ---- Optional core blueprint shape ----
|
|
106
108
|
contract: dataContractSchema
|
|
@@ -112,6 +114,17 @@ export const blueprintManifestSchema = z.strictObject({
|
|
|
112
114
|
variance: blueprintVarianceSchema
|
|
113
115
|
.optional()
|
|
114
116
|
.describe("Persona + aesthetic + context + seedPrompt hints that drive the LLM-driven variant selector when multiple blueprints share a `(appId, contractHash)` group. Mirrors `Blueprint.variance` in `@ggui-ai/protocol`."),
|
|
117
|
+
// ---- Persistence-contract stamps (mirrors `PortableBlueprint`) ----
|
|
118
|
+
generatorProtocolVersion: z
|
|
119
|
+
.string()
|
|
120
|
+
.min(1)
|
|
121
|
+
.optional()
|
|
122
|
+
.describe('PROTOCOL_VERSION of the toolchain that authored + signed this manifest. Import gates compare it against the importing deployment’s era before admitting the blueprint into a reuse pool — an era mismatch (or a missing stamp) drops the row loudly instead of serving code generated against a different protocol shape. Publishing tools stamp this automatically right before signing; deployments that consume installed blueprints into a matcher pool require it.'),
|
|
123
|
+
toolIdentityCatalogHash: z
|
|
124
|
+
.string()
|
|
125
|
+
.min(1)
|
|
126
|
+
.optional()
|
|
127
|
+
.describe('SHA256(16) of the tool-identity catalog used to canonicalize `contract` at authoring time. Importers re-canonicalize against their own catalog and recompute the key; a divergence means the same intent would mis-key and silently cold-gen, so it is rejected. Optional — most marketplace blueprints are authored without a live tool catalog, which leaves the import gate’s re-key check inert.'),
|
|
115
128
|
// ---- Shared metadata ----
|
|
116
129
|
...sharedMetadataShape,
|
|
117
130
|
});
|
|
@@ -143,13 +156,6 @@ export const GGUI_BLUEPRINT_JSON_FILENAME = 'ggui.blueprint.json';
|
|
|
143
156
|
export function parseBlueprintManifest(raw) {
|
|
144
157
|
return blueprintManifestSchema.parse(raw);
|
|
145
158
|
}
|
|
146
|
-
/**
|
|
147
|
-
* Assertion helper — narrows `raw` to {@link BlueprintManifest} on
|
|
148
|
-
* success, throws `ZodError` on failure.
|
|
149
|
-
*/
|
|
150
|
-
export function assertBlueprintManifestValid(raw) {
|
|
151
|
-
blueprintManifestSchema.parse(raw);
|
|
152
|
-
}
|
|
153
159
|
/**
|
|
154
160
|
* Safe-parse variant — returns a discriminated `z.safeParse` result
|
|
155
161
|
* (`{ success: true, data }` vs `{ success: false, error }`).
|
|
@@ -130,8 +130,8 @@ export declare const gadgetManifestSchema: z.ZodObject<{
|
|
|
130
130
|
* 3. THIS field — gadget author's default
|
|
131
131
|
* 4. spec default `registry.ggui.ai`
|
|
132
132
|
*
|
|
133
|
-
* Most wrappers omit this (they publish to the
|
|
134
|
-
* the spec default covers them). Set this only when the wrapper ships
|
|
133
|
+
* Most wrappers omit this (they publish to the default registry,
|
|
134
|
+
* and the spec default covers them). Set this only when the wrapper ships
|
|
135
135
|
* via a non-default registry (private org registry, sandbox-only
|
|
136
136
|
* fixture, …). The operator override remains the right knob for
|
|
137
137
|
* sandbox-vs-prod swaps.
|
|
@@ -163,13 +163,6 @@ export declare const GGUI_GADGET_JSON_FILENAME = "ggui.gadget.json";
|
|
|
163
163
|
* decoded the JSON (`JSON.parse(source)`).
|
|
164
164
|
*/
|
|
165
165
|
export declare function parseGadgetManifest(raw: unknown): GadgetManifest;
|
|
166
|
-
/**
|
|
167
|
-
* Assertion helper — narrows `raw` to {@link GadgetManifest} on
|
|
168
|
-
* success, throws `ZodError` on failure. Useful when the caller wants
|
|
169
|
-
* to keep the original reference (rather than the parsed copy
|
|
170
|
-
* `parseGadgetManifest` returns).
|
|
171
|
-
*/
|
|
172
|
-
export declare function assertGadgetManifestValid(raw: unknown): asserts raw is GadgetManifest;
|
|
173
166
|
/**
|
|
174
167
|
* Safe-parse variant — returns a discriminated `z.safeParse` result
|
|
175
168
|
* (`{ success: true, data }` vs `{ success: false, error }`). Prefer
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gadget-manifest.d.ts","sourceRoot":"","sources":["../src/gadget-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsFxB;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;oBAwB7B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4D/B;;;;;OAKG;;;IAcH;;;;;;;;;;;;;;;;;OAiBG;;kBAwBH,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAE5D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,
|
|
1
|
+
{"version":3,"file":"gadget-manifest.d.ts","sourceRoot":"","sources":["../src/gadget-manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAsFxB;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;oBAwB7B,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4D/B;;;;;OAKG;;;IAcH;;;;;;;;;;;;;;;;;OAiBG;;kBAwBH,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,qBAAqB,CAAC;AAE5D;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAEhE;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,GACX,UAAU,CAAC,OAAO,oBAAoB,CAAC,SAAS,CAAC,CAEnD"}
|
package/dist/gadget-manifest.js
CHANGED
|
@@ -207,8 +207,8 @@ export const gadgetManifestSchema = z.strictObject({
|
|
|
207
207
|
* 3. THIS field — gadget author's default
|
|
208
208
|
* 4. spec default `registry.ggui.ai`
|
|
209
209
|
*
|
|
210
|
-
* Most wrappers omit this (they publish to the
|
|
211
|
-
* the spec default covers them). Set this only when the wrapper ships
|
|
210
|
+
* Most wrappers omit this (they publish to the default registry,
|
|
211
|
+
* and the spec default covers them). Set this only when the wrapper ships
|
|
212
212
|
* via a non-default registry (private org registry, sandbox-only
|
|
213
213
|
* fixture, …). The operator override remains the right knob for
|
|
214
214
|
* sandbox-vs-prod swaps.
|
|
@@ -250,15 +250,6 @@ export const GGUI_GADGET_JSON_FILENAME = 'ggui.gadget.json';
|
|
|
250
250
|
export function parseGadgetManifest(raw) {
|
|
251
251
|
return gadgetManifestSchema.parse(raw);
|
|
252
252
|
}
|
|
253
|
-
/**
|
|
254
|
-
* Assertion helper — narrows `raw` to {@link GadgetManifest} on
|
|
255
|
-
* success, throws `ZodError` on failure. Useful when the caller wants
|
|
256
|
-
* to keep the original reference (rather than the parsed copy
|
|
257
|
-
* `parseGadgetManifest` returns).
|
|
258
|
-
*/
|
|
259
|
-
export function assertGadgetManifestValid(raw) {
|
|
260
|
-
gadgetManifestSchema.parse(raw);
|
|
261
|
-
}
|
|
262
253
|
/**
|
|
263
254
|
* Safe-parse variant — returns a discriminated `z.safeParse` result
|
|
264
255
|
* (`{ success: true, data }` vs `{ success: false, error }`). Prefer
|
package/dist/index.d.ts
CHANGED
|
@@ -11,14 +11,19 @@
|
|
|
11
11
|
* kinds for tooling that handles them generically (signing, registry
|
|
12
12
|
* upload, search-index ingestion).
|
|
13
13
|
*
|
|
14
|
+
* Also the single owner of the seed-pool wrapper-artifact format
|
|
15
|
+
* (`pool-artifact.ts`) — the `manifest.json` + `codes/` directory
|
|
16
|
+
* layout that pool exporters write and seed-pool readers consume.
|
|
17
|
+
*
|
|
14
18
|
* Browser-safe (no Node dependencies) — pure schema + parsers.
|
|
15
19
|
*/
|
|
16
|
-
export { GGUI_GADGET_JSON_FILENAME,
|
|
20
|
+
export { GGUI_GADGET_JSON_FILENAME, parseGadgetManifest, gadgetManifestSchema, gadgetExportSchema, safeParseGadgetManifest, } from './gadget-manifest.js';
|
|
17
21
|
export type { GadgetManifest } from './gadget-manifest.js';
|
|
18
|
-
export { GGUI_BLUEPRINT_JSON_FILENAME,
|
|
22
|
+
export { GGUI_BLUEPRINT_JSON_FILENAME, blueprintManifestSchema, parseBlueprintManifest, safeParseBlueprintManifest, } from './blueprint-manifest.js';
|
|
19
23
|
export type { BlueprintManifest } from './blueprint-manifest.js';
|
|
20
|
-
export { artifactManifestSchema,
|
|
24
|
+
export { artifactManifestSchema, parseArtifactManifest, safeParseArtifactManifest, } from './artifact-manifest.js';
|
|
21
25
|
export type { ArtifactManifest } from './artifact-manifest.js';
|
|
22
26
|
export { GADGET_NAME_RE, BLUEPRINT_NAME_RE, ArtifactScopeSchema, ArtifactVersionSchema, } from './base.js';
|
|
23
27
|
export { manifestToRegistryEntry, type ManifestToRegistryEntryFields, } from './manifest-to-registry-entry.js';
|
|
28
|
+
export { POOL_ARTIFACT_CODES_DIR, POOL_ARTIFACT_CODE_REF_PATTERN, POOL_ARTIFACT_MANIFEST_FILENAME, POOL_ARTIFACT_SCHEMA_VERSION, POOL_ARTIFACT_V1_REJECTION, buildPoolArtifactManifest, parsePoolArtifactManifest, poolArtifactCodeRef, serializePoolArtifactManifest, type ParsePoolArtifactManifestResult, type PoolArtifactManifest, type PoolArtifactManifestEntry, } from './pool-artifact.js';
|
|
24
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAGjE,OAAO,EACL,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAS/D,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAMnB,OAAO,EACL,uBAAuB,EACvB,KAAK,6BAA6B,GACnC,MAAM,iCAAiC,CAAC;AAMzC,OAAO,EACL,uBAAuB,EACvB,8BAA8B,EAC9B,+BAA+B,EAC/B,4BAA4B,EAC5B,0BAA0B,EAC1B,yBAAyB,EACzB,yBAAyB,EACzB,mBAAmB,EACnB,6BAA6B,EAC7B,KAAK,+BAA+B,EACpC,KAAK,oBAAoB,EACzB,KAAK,yBAAyB,GAC/B,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -11,14 +11,18 @@
|
|
|
11
11
|
* kinds for tooling that handles them generically (signing, registry
|
|
12
12
|
* upload, search-index ingestion).
|
|
13
13
|
*
|
|
14
|
+
* Also the single owner of the seed-pool wrapper-artifact format
|
|
15
|
+
* (`pool-artifact.ts`) — the `manifest.json` + `codes/` directory
|
|
16
|
+
* layout that pool exporters write and seed-pool readers consume.
|
|
17
|
+
*
|
|
14
18
|
* Browser-safe (no Node dependencies) — pure schema + parsers.
|
|
15
19
|
*/
|
|
16
20
|
// Gadget manifest — narrow surface.
|
|
17
|
-
export { GGUI_GADGET_JSON_FILENAME,
|
|
21
|
+
export { GGUI_GADGET_JSON_FILENAME, parseGadgetManifest, gadgetManifestSchema, gadgetExportSchema, safeParseGadgetManifest, } from './gadget-manifest.js';
|
|
18
22
|
// Blueprint manifest — narrow surface.
|
|
19
|
-
export { GGUI_BLUEPRINT_JSON_FILENAME,
|
|
23
|
+
export { GGUI_BLUEPRINT_JSON_FILENAME, blueprintManifestSchema, parseBlueprintManifest, safeParseBlueprintManifest, } from './blueprint-manifest.js';
|
|
20
24
|
// Discriminated union — top-level surface.
|
|
21
|
-
export { artifactManifestSchema,
|
|
25
|
+
export { artifactManifestSchema, parseArtifactManifest, safeParseArtifactManifest, } from './artifact-manifest.js';
|
|
22
26
|
// Shared name regexes — a single kebab-case rule unified across
|
|
23
27
|
// gadget and blueprint kinds. External callers (registry tooling,
|
|
24
28
|
// ops tools) import these instead of re-defining the regex inline so
|
|
@@ -32,3 +36,8 @@ export { GADGET_NAME_RE, BLUEPRINT_NAME_RE, ArtifactScopeSchema, ArtifactVersion
|
|
|
32
36
|
// through this one function. Round-trip validated in the companion
|
|
33
37
|
// test file.
|
|
34
38
|
export { manifestToRegistryEntry, } from './manifest-to-registry-entry.js';
|
|
39
|
+
// Seed-pool wrapper-artifact codec — single owner of the artifact
|
|
40
|
+
// byte format (version literal, layout names, codeRef shape,
|
|
41
|
+
// rejection messages). Pool writers and seed-pool readers both
|
|
42
|
+
// import from here; they own only their IO.
|
|
43
|
+
export { POOL_ARTIFACT_CODES_DIR, POOL_ARTIFACT_CODE_REF_PATTERN, POOL_ARTIFACT_MANIFEST_FILENAME, POOL_ARTIFACT_SCHEMA_VERSION, POOL_ARTIFACT_V1_REJECTION, buildPoolArtifactManifest, parsePoolArtifactManifest, poolArtifactCodeRef, serializePoolArtifactManifest, } from './pool-artifact.js';
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool-artifact wrapper codec — the SINGLE owner of the seed-pool
|
|
3
|
+
* artifact byte format (schemaVersion 2).
|
|
4
|
+
*
|
|
5
|
+
* A seed-pool artifact is a directory-shaped bundle of exported
|
|
6
|
+
* blueprints that one deployment writes and another reads:
|
|
7
|
+
*
|
|
8
|
+
* - `manifest.json` — `{ schemaVersion: 2, blueprints: [{ record:
|
|
9
|
+
* <PortableBlueprint minus componentCode>, codeRef:
|
|
10
|
+
* "<sha256hex>.tsx" }] }`, UTF-8.
|
|
11
|
+
* - `codes/<codeRef>` — raw UTF-8 component-code body (NOT
|
|
12
|
+
* JSON-wrapped). Readers reconstruct each record as
|
|
13
|
+
* `{ ...entry.record, componentCode }`.
|
|
14
|
+
*
|
|
15
|
+
* This module owns everything FORMAT: the schema-version literal, the
|
|
16
|
+
* layout names (`manifest.json`, `codes/`), the codeRef filename
|
|
17
|
+
* shape, the manifest types, the (de)serializers, and the canonical
|
|
18
|
+
* rejection/issue messages. Writers and readers — whatever transport
|
|
19
|
+
* they sit on (local filesystem, object storage) — import from here
|
|
20
|
+
* and own ONLY their IO: byte fetch/store and code-body splice. A
|
|
21
|
+
* future schemaVersion bump is therefore a single-point change; a
|
|
22
|
+
* writer and a reader can never disagree on the format.
|
|
23
|
+
*
|
|
24
|
+
* Records stay UNVALIDATED here (`record: object`): artifact bytes are
|
|
25
|
+
* an untrusted input, and the trust boundary for record shape is the
|
|
26
|
+
* protocol's `fromPortableBlueprint` inside the seed-pool builder
|
|
27
|
+
* (skip-with-log on rejection — a rejected seed entry is just a
|
|
28
|
+
* cold-gen). This codec validates only the wrapper: version, layout,
|
|
29
|
+
* entry shape, codeRef shape.
|
|
30
|
+
*
|
|
31
|
+
* Versioning: the wrapper version is bumped in lockstep with the
|
|
32
|
+
* record schema (`PORTABLE_BLUEPRINT_SCHEMA_VERSION`). v1 artifacts
|
|
33
|
+
* are rejected on read with {@link POOL_ARTIFACT_V1_REJECTION} — a
|
|
34
|
+
* blueprint pool is a cache, so the fix is a re-export, never a
|
|
35
|
+
* migration shim.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* Wrapper-artifact schema version. Bumped 1 → 2 in lockstep with
|
|
39
|
+
* PortableBlueprint v2 (records now carry required provenance).
|
|
40
|
+
*/
|
|
41
|
+
export declare const POOL_ARTIFACT_SCHEMA_VERSION = 2;
|
|
42
|
+
/** Manifest filename inside the artifact directory/prefix. */
|
|
43
|
+
export declare const POOL_ARTIFACT_MANIFEST_FILENAME = "manifest.json";
|
|
44
|
+
/** Code-body directory name inside the artifact directory/prefix. */
|
|
45
|
+
export declare const POOL_ARTIFACT_CODES_DIR = "codes";
|
|
46
|
+
/**
|
|
47
|
+
* The codec's code-body filename shape: `<sha256 hex>.tsx`. Readers
|
|
48
|
+
* MUST honour only refs matching this pattern so a crafted manifest
|
|
49
|
+
* value like `../../etc/passwd` can never escape `codes/`.
|
|
50
|
+
*/
|
|
51
|
+
export declare const POOL_ARTIFACT_CODE_REF_PATTERN: RegExp;
|
|
52
|
+
/** Rejection message for schemaVersion-1 wrapper artifacts. */
|
|
53
|
+
export declare const POOL_ARTIFACT_V1_REJECTION = "re-export the pool: artifact schemaVersion 2 records carry complete provenance (PortableBlueprint v2)";
|
|
54
|
+
/**
|
|
55
|
+
* One manifest entry. `record` is deliberately untyped beyond "an
|
|
56
|
+
* object": the inner record is untrusted artifact bytes readers
|
|
57
|
+
* forward verbatim; `fromPortableBlueprint` at the pool builder is
|
|
58
|
+
* the validating narrower.
|
|
59
|
+
*/
|
|
60
|
+
export interface PoolArtifactManifestEntry {
|
|
61
|
+
readonly record: object;
|
|
62
|
+
readonly codeRef: string;
|
|
63
|
+
}
|
|
64
|
+
export interface PoolArtifactManifest {
|
|
65
|
+
readonly schemaVersion: typeof POOL_ARTIFACT_SCHEMA_VERSION;
|
|
66
|
+
readonly blueprints: readonly PoolArtifactManifestEntry[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Build the codeRef filename for a code body's sha256 hex digest.
|
|
70
|
+
* Throws when the input is not a 64-char lowercase hex digest — a
|
|
71
|
+
* writer must never produce a ref its own reader would reject.
|
|
72
|
+
*/
|
|
73
|
+
export declare function poolArtifactCodeRef(sha256Hex: string): string;
|
|
74
|
+
/** Stamp the current schema version onto a manifest. Writer-side. */
|
|
75
|
+
export declare function buildPoolArtifactManifest(blueprints: readonly PoolArtifactManifestEntry[]): PoolArtifactManifest;
|
|
76
|
+
/** Canonical manifest bytes (pretty-printed JSON + trailing newline). */
|
|
77
|
+
export declare function serializePoolArtifactManifest(manifest: PoolArtifactManifest): string;
|
|
78
|
+
/**
|
|
79
|
+
* Parse + validate raw manifest bytes.
|
|
80
|
+
*
|
|
81
|
+
* Failure modes (the codec's contract, shared by every reader):
|
|
82
|
+
* - Manifest-level problems — invalid JSON, non-object root, an
|
|
83
|
+
* unsupported `schemaVersion` (v1 included), a missing/non-array
|
|
84
|
+
* `blueprints` — return `{ok: false, reason}`. Readers THROW,
|
|
85
|
+
* prefixing their transport context.
|
|
86
|
+
* - Entry-level problems — a malformed entry or a codeRef failing
|
|
87
|
+
* {@link POOL_ARTIFACT_CODE_REF_PATTERN} — DROP the entry and
|
|
88
|
+
* append a canonical message to `issues`. Readers surface issues
|
|
89
|
+
* (warn/collect), never throw on them: a single bad row is a
|
|
90
|
+
* skipped blueprint, not a dead pool.
|
|
91
|
+
*/
|
|
92
|
+
export type ParsePoolArtifactManifestResult = {
|
|
93
|
+
readonly ok: true;
|
|
94
|
+
readonly manifest: PoolArtifactManifest;
|
|
95
|
+
readonly issues: readonly string[];
|
|
96
|
+
} | {
|
|
97
|
+
readonly ok: false;
|
|
98
|
+
readonly reason: string;
|
|
99
|
+
};
|
|
100
|
+
export declare function parsePoolArtifactManifest(raw: string): ParsePoolArtifactManifestResult;
|
|
101
|
+
//# sourceMappingURL=pool-artifact.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pool-artifact.d.ts","sourceRoot":"","sources":["../src/pool-artifact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH;;;GAGG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,8DAA8D;AAC9D,eAAO,MAAM,+BAA+B,kBAAkB,CAAC;AAE/D,qEAAqE;AACrE,eAAO,MAAM,uBAAuB,UAAU,CAAC;AAE/C;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,QAAwB,CAAC;AAEpE,+DAA+D;AAC/D,eAAO,MAAM,0BAA0B,0GACkE,CAAC;AAE1G;;;;;GAKG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,aAAa,EAAE,OAAO,4BAA4B,CAAC;IAC5D,QAAQ,CAAC,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAC;CAC3D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAED,qEAAqE;AACrE,wBAAgB,yBAAyB,CACvC,UAAU,EAAE,SAAS,yBAAyB,EAAE,GAC/C,oBAAoB,CAEtB;AAED,yEAAyE;AACzE,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,oBAAoB,GAC7B,MAAM,CAER;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,+BAA+B,GACvC;IACE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,GACV,+BAA+B,CAwDjC"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pool-artifact wrapper codec — the SINGLE owner of the seed-pool
|
|
3
|
+
* artifact byte format (schemaVersion 2).
|
|
4
|
+
*
|
|
5
|
+
* A seed-pool artifact is a directory-shaped bundle of exported
|
|
6
|
+
* blueprints that one deployment writes and another reads:
|
|
7
|
+
*
|
|
8
|
+
* - `manifest.json` — `{ schemaVersion: 2, blueprints: [{ record:
|
|
9
|
+
* <PortableBlueprint minus componentCode>, codeRef:
|
|
10
|
+
* "<sha256hex>.tsx" }] }`, UTF-8.
|
|
11
|
+
* - `codes/<codeRef>` — raw UTF-8 component-code body (NOT
|
|
12
|
+
* JSON-wrapped). Readers reconstruct each record as
|
|
13
|
+
* `{ ...entry.record, componentCode }`.
|
|
14
|
+
*
|
|
15
|
+
* This module owns everything FORMAT: the schema-version literal, the
|
|
16
|
+
* layout names (`manifest.json`, `codes/`), the codeRef filename
|
|
17
|
+
* shape, the manifest types, the (de)serializers, and the canonical
|
|
18
|
+
* rejection/issue messages. Writers and readers — whatever transport
|
|
19
|
+
* they sit on (local filesystem, object storage) — import from here
|
|
20
|
+
* and own ONLY their IO: byte fetch/store and code-body splice. A
|
|
21
|
+
* future schemaVersion bump is therefore a single-point change; a
|
|
22
|
+
* writer and a reader can never disagree on the format.
|
|
23
|
+
*
|
|
24
|
+
* Records stay UNVALIDATED here (`record: object`): artifact bytes are
|
|
25
|
+
* an untrusted input, and the trust boundary for record shape is the
|
|
26
|
+
* protocol's `fromPortableBlueprint` inside the seed-pool builder
|
|
27
|
+
* (skip-with-log on rejection — a rejected seed entry is just a
|
|
28
|
+
* cold-gen). This codec validates only the wrapper: version, layout,
|
|
29
|
+
* entry shape, codeRef shape.
|
|
30
|
+
*
|
|
31
|
+
* Versioning: the wrapper version is bumped in lockstep with the
|
|
32
|
+
* record schema (`PORTABLE_BLUEPRINT_SCHEMA_VERSION`). v1 artifacts
|
|
33
|
+
* are rejected on read with {@link POOL_ARTIFACT_V1_REJECTION} — a
|
|
34
|
+
* blueprint pool is a cache, so the fix is a re-export, never a
|
|
35
|
+
* migration shim.
|
|
36
|
+
*/
|
|
37
|
+
/**
|
|
38
|
+
* Wrapper-artifact schema version. Bumped 1 → 2 in lockstep with
|
|
39
|
+
* PortableBlueprint v2 (records now carry required provenance).
|
|
40
|
+
*/
|
|
41
|
+
export const POOL_ARTIFACT_SCHEMA_VERSION = 2;
|
|
42
|
+
/** Manifest filename inside the artifact directory/prefix. */
|
|
43
|
+
export const POOL_ARTIFACT_MANIFEST_FILENAME = 'manifest.json';
|
|
44
|
+
/** Code-body directory name inside the artifact directory/prefix. */
|
|
45
|
+
export const POOL_ARTIFACT_CODES_DIR = 'codes';
|
|
46
|
+
/**
|
|
47
|
+
* The codec's code-body filename shape: `<sha256 hex>.tsx`. Readers
|
|
48
|
+
* MUST honour only refs matching this pattern so a crafted manifest
|
|
49
|
+
* value like `../../etc/passwd` can never escape `codes/`.
|
|
50
|
+
*/
|
|
51
|
+
export const POOL_ARTIFACT_CODE_REF_PATTERN = /^[0-9a-f]{64}\.tsx$/;
|
|
52
|
+
/** Rejection message for schemaVersion-1 wrapper artifacts. */
|
|
53
|
+
export const POOL_ARTIFACT_V1_REJECTION = 're-export the pool: artifact schemaVersion 2 records carry complete provenance (PortableBlueprint v2)';
|
|
54
|
+
/**
|
|
55
|
+
* Build the codeRef filename for a code body's sha256 hex digest.
|
|
56
|
+
* Throws when the input is not a 64-char lowercase hex digest — a
|
|
57
|
+
* writer must never produce a ref its own reader would reject.
|
|
58
|
+
*/
|
|
59
|
+
export function poolArtifactCodeRef(sha256Hex) {
|
|
60
|
+
const ref = `${sha256Hex}.tsx`;
|
|
61
|
+
if (!POOL_ARTIFACT_CODE_REF_PATTERN.test(ref)) {
|
|
62
|
+
throw new Error(`pool artifact: codeRef input is not a sha256 hex digest: ${sha256Hex}`);
|
|
63
|
+
}
|
|
64
|
+
return ref;
|
|
65
|
+
}
|
|
66
|
+
/** Stamp the current schema version onto a manifest. Writer-side. */
|
|
67
|
+
export function buildPoolArtifactManifest(blueprints) {
|
|
68
|
+
return { schemaVersion: POOL_ARTIFACT_SCHEMA_VERSION, blueprints };
|
|
69
|
+
}
|
|
70
|
+
/** Canonical manifest bytes (pretty-printed JSON + trailing newline). */
|
|
71
|
+
export function serializePoolArtifactManifest(manifest) {
|
|
72
|
+
return `${JSON.stringify(manifest, null, 2)}\n`;
|
|
73
|
+
}
|
|
74
|
+
export function parsePoolArtifactManifest(raw) {
|
|
75
|
+
let parsed;
|
|
76
|
+
try {
|
|
77
|
+
parsed = JSON.parse(raw);
|
|
78
|
+
}
|
|
79
|
+
catch (cause) {
|
|
80
|
+
return {
|
|
81
|
+
ok: false,
|
|
82
|
+
reason: `${POOL_ARTIFACT_MANIFEST_FILENAME} is not valid JSON: ${cause instanceof Error ? cause.message : String(cause)}`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
86
|
+
return {
|
|
87
|
+
ok: false,
|
|
88
|
+
reason: `${POOL_ARTIFACT_MANIFEST_FILENAME} is not an object`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const m = parsed;
|
|
92
|
+
if (m.schemaVersion !== POOL_ARTIFACT_SCHEMA_VERSION) {
|
|
93
|
+
if (m.schemaVersion === 1) {
|
|
94
|
+
return { ok: false, reason: POOL_ARTIFACT_V1_REJECTION };
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
ok: false,
|
|
98
|
+
reason: `unsupported manifest schemaVersion ${String(m.schemaVersion)} (expected ${POOL_ARTIFACT_SCHEMA_VERSION})`,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
if (!Array.isArray(m.blueprints)) {
|
|
102
|
+
return {
|
|
103
|
+
ok: false,
|
|
104
|
+
reason: 'manifest.blueprints is missing or not an array',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const blueprints = [];
|
|
108
|
+
const issues = [];
|
|
109
|
+
for (const entry of m.blueprints) {
|
|
110
|
+
if (!isPoolArtifactManifestEntry(entry)) {
|
|
111
|
+
issues.push('malformed manifest entry (missing record/codeRef); skipping blueprint');
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (!POOL_ARTIFACT_CODE_REF_PATTERN.test(entry.codeRef)) {
|
|
115
|
+
issues.push(`invalid code reference ${entry.codeRef}; skipping blueprint`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
blueprints.push(entry);
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
ok: true,
|
|
122
|
+
manifest: { schemaVersion: POOL_ARTIFACT_SCHEMA_VERSION, blueprints },
|
|
123
|
+
issues,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Structural guard for a manifest entry: `codeRef` is a string and
|
|
128
|
+
* `record` is an object readers can splice `componentCode` back into.
|
|
129
|
+
* The record's inner fields are deliberately NOT validated here — see
|
|
130
|
+
* the module docstring's trust-boundary note.
|
|
131
|
+
*/
|
|
132
|
+
function isPoolArtifactManifestEntry(value) {
|
|
133
|
+
if (typeof value !== 'object' || value === null)
|
|
134
|
+
return false;
|
|
135
|
+
if (!('codeRef' in value) || typeof value.codeRef !== 'string')
|
|
136
|
+
return false;
|
|
137
|
+
if (!('record' in value) ||
|
|
138
|
+
typeof value.record !== 'object' ||
|
|
139
|
+
value.record === null ||
|
|
140
|
+
Array.isArray(value.record)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/artifact-manifest",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-rc.0",
|
|
4
4
|
"description": "Strict zod schemas + parsers for ggui marketplace artifact manifests — ggui.gadget.json (gadget bundles) and ggui.blueprint.json (cached UI blueprints).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"keywords": [
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"zod": "^4.3.6",
|
|
30
|
-
"@ggui-ai/protocol": "0.
|
|
30
|
+
"@ggui-ai/protocol": "0.3.0-rc.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"typescript": "^5.0.0",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"author": "ggui contributors <hello@ggui.ai>",
|
|
52
52
|
"scripts": {
|
|
53
|
-
"build": "tsc -p tsconfig.build.json",
|
|
53
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json",
|
|
54
54
|
"dev": "tsc --watch",
|
|
55
55
|
"typecheck": "tsc --noEmit",
|
|
56
56
|
"test": "vitest run",
|