@ai-plugin-marketplace/core 0.1.0 → 0.3.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/dist/config.d.ts +112 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +56 -0
- package/dist/config.js.map +1 -1
- package/dist/core.d.ts +187 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/pipeline/build.d.ts +159 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +413 -9
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/discover.d.ts +20 -13
- package/dist/pipeline/discover.d.ts.map +1 -1
- package/dist/pipeline/discover.js +53 -32
- package/dist/pipeline/discover.js.map +1 -1
- package/dist/pipeline/init-template.d.ts +16 -5
- package/dist/pipeline/init-template.d.ts.map +1 -1
- package/dist/pipeline/init-template.js +65 -21
- package/dist/pipeline/init-template.js.map +1 -1
- package/dist/pipeline/init.d.ts +17 -14
- package/dist/pipeline/init.d.ts.map +1 -1
- package/dist/pipeline/init.js +23 -15
- package/dist/pipeline/init.js.map +1 -1
- package/dist/pipeline/load-config.d.ts +62 -2
- package/dist/pipeline/load-config.d.ts.map +1 -1
- package/dist/pipeline/load-config.js +147 -30
- package/dist/pipeline/load-config.js.map +1 -1
- package/dist/pipeline/operations.d.ts +15 -3
- package/dist/pipeline/operations.d.ts.map +1 -1
- package/dist/pipeline/operations.js +25 -4
- package/dist/pipeline/operations.js.map +1 -1
- package/dist/pipeline/scaffold-refresh.d.ts +80 -0
- package/dist/pipeline/scaffold-refresh.d.ts.map +1 -0
- package/dist/pipeline/scaffold-refresh.js +152 -0
- package/dist/pipeline/scaffold-refresh.js.map +1 -0
- package/dist/pipeline/scaffold.d.ts.map +1 -1
- package/dist/pipeline/scaffold.js +55 -26
- package/dist/pipeline/scaffold.js.map +1 -1
- package/dist/pipeline/types.d.ts +51 -3
- package/dist/pipeline/types.d.ts.map +1 -1
- package/dist/pipeline/types.js +1 -0
- package/dist/pipeline/types.js.map +1 -1
- package/dist/pipeline/validate.d.ts +12 -2
- package/dist/pipeline/validate.d.ts.map +1 -1
- package/dist/pipeline/validate.js +342 -38
- package/dist/pipeline/validate.js.map +1 -1
- package/dist/targets/codex/scaffold.d.ts +31 -0
- package/dist/targets/codex/scaffold.d.ts.map +1 -0
- package/dist/targets/codex/scaffold.js +47 -0
- package/dist/targets/codex/scaffold.js.map +1 -0
- package/dist/targets/codex/schemas.d.ts +70 -0
- package/dist/targets/codex/schemas.d.ts.map +1 -0
- package/dist/targets/codex/schemas.js +153 -0
- package/dist/targets/codex/schemas.js.map +1 -0
- package/dist/targets/codex/validate.d.ts +25 -0
- package/dist/targets/codex/validate.d.ts.map +1 -0
- package/dist/targets/codex/validate.js +117 -0
- package/dist/targets/codex/validate.js.map +1 -0
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -18,6 +18,18 @@ export interface AipmConfigInput {
|
|
|
18
18
|
version: string;
|
|
19
19
|
/** Targets this plugin supports. See §6 of the spec. */
|
|
20
20
|
targets: readonly TargetId[];
|
|
21
|
+
/**
|
|
22
|
+
* Optional one-line description of the plugin. When the repo opts into registry generation (an
|
|
23
|
+
* `aipm.workspace.ts` is present), this becomes the plugin entry's `description` (Claude/Cursor)
|
|
24
|
+
* in the generated `marketplace.json`. Optional so existing configs stay valid.
|
|
25
|
+
*/
|
|
26
|
+
description?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Optional discovery keywords for the plugin. When the repo opts into registry generation, these
|
|
29
|
+
* become the plugin entry's `tags` (Claude/Cursor) in the generated `marketplace.json`. Optional
|
|
30
|
+
* so existing configs stay valid.
|
|
31
|
+
*/
|
|
32
|
+
keywords?: readonly string[];
|
|
21
33
|
}
|
|
22
34
|
/**
|
|
23
35
|
* Module-private brand marker. Intentionally never exported (§8.1: "The brand symbol is
|
|
@@ -43,5 +55,105 @@ export type AipmConfig = AipmConfigInput & {
|
|
|
43
55
|
* @public
|
|
44
56
|
*/
|
|
45
57
|
export declare function defineConfig(config: AipmConfigInput): AipmConfig;
|
|
58
|
+
/**
|
|
59
|
+
* Raw input shape accepted by `defineRepoConfig`. Authored as `aipm.repo.ts` at the **repo
|
|
60
|
+
* root** of a project that hosts a marketplace inside a larger software repo. The file is
|
|
61
|
+
* optional: when absent, the toolkit behaves as if `defineRepoConfig({})` was used, reproducing
|
|
62
|
+
* the historical "repo root == marketplace root, fixed `plugins/`" topology.
|
|
63
|
+
*
|
|
64
|
+
* Both paths are repo-root-relative and must stay within the repo (no absolute paths, no `..`
|
|
65
|
+
* segments), because host platforms resolve a plugin's `source` relative to the repo root.
|
|
66
|
+
*
|
|
67
|
+
* @public
|
|
68
|
+
*/
|
|
69
|
+
export interface AipmRepoConfigInput {
|
|
70
|
+
/**
|
|
71
|
+
* Directory (relative to the repo root) that holds plugin folders. Relocate this when the host
|
|
72
|
+
* software already owns a top-level `plugins/` directory. Default: `'plugins'`.
|
|
73
|
+
*/
|
|
74
|
+
pluginsRoot?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Directory (relative to the repo root) for generated `dist/` bundles. Relocate this when the
|
|
77
|
+
* host software already owns a top-level `dist/`. Default: `'dist'`.
|
|
78
|
+
*/
|
|
79
|
+
distDir?: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Module-private brand marker for {@link AipmRepoConfig}. Never exported.
|
|
83
|
+
*
|
|
84
|
+
* @internal
|
|
85
|
+
*/
|
|
86
|
+
declare const aipmRepoConfigBrand: unique symbol;
|
|
87
|
+
/**
|
|
88
|
+
* Validated repo configuration. Carries a module-private brand indicating `defineRepoConfig`
|
|
89
|
+
* validated it; unlike the input, both fields are always present (defaults applied).
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
export type AipmRepoConfig = {
|
|
94
|
+
readonly pluginsRoot: string;
|
|
95
|
+
readonly distDir: string;
|
|
96
|
+
} & {
|
|
97
|
+
readonly [aipmRepoConfigBrand]: 'AipmRepoConfig';
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Validate and brand a repo configuration, applying defaults for any omitted field. Throws a
|
|
101
|
+
* `ZodError` on invalid input (unknown keys, absolute paths, `..` escapes).
|
|
102
|
+
*
|
|
103
|
+
* @public
|
|
104
|
+
*/
|
|
105
|
+
export declare function defineRepoConfig(config?: AipmRepoConfigInput): AipmRepoConfig;
|
|
106
|
+
/**
|
|
107
|
+
* Raw input shape accepted by `defineWorkspace`. Authored as `aipm.workspace.ts` at the **repo
|
|
108
|
+
* root**. Its presence opts the repo into **marketplace-registry generation**: the toolkit
|
|
109
|
+
* generates the per-target `marketplace.json` registries from this workspace metadata plus the
|
|
110
|
+
* discovered plugins, commits them, and freshness-checks them. When the file is **absent**, the
|
|
111
|
+
* toolkit behaves exactly as before (registries are hand-authored and `validateMarketplaceRegistration`
|
|
112
|
+
* runs).
|
|
113
|
+
*
|
|
114
|
+
* @public
|
|
115
|
+
*/
|
|
116
|
+
export interface AipmWorkspaceInput {
|
|
117
|
+
/** Marketplace-level metadata shared across all generated registries. */
|
|
118
|
+
marketplace: {
|
|
119
|
+
/** Marketplace name — the registry's top-level `name`. */
|
|
120
|
+
name: string;
|
|
121
|
+
/**
|
|
122
|
+
* Optional owner block written to the Claude/Cursor registries' top-level `owner`. The Codex
|
|
123
|
+
* registry has no owner concept, so this is ignored there.
|
|
124
|
+
*/
|
|
125
|
+
owner?: {
|
|
126
|
+
name: string;
|
|
127
|
+
email?: string;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Optional marketplace description. For Claude/Cursor it becomes `metadata.description`; for
|
|
131
|
+
* Codex it is currently unused (the Codex registry has no marketplace-level description field).
|
|
132
|
+
*/
|
|
133
|
+
description?: string;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Module-private brand marker for {@link AipmWorkspace}. Never exported.
|
|
138
|
+
*
|
|
139
|
+
* @internal
|
|
140
|
+
*/
|
|
141
|
+
declare const aipmWorkspaceBrand: unique symbol;
|
|
142
|
+
/**
|
|
143
|
+
* Validated workspace configuration. Structurally identical to {@link AipmWorkspaceInput} but
|
|
144
|
+
* carries a module-private brand indicating `defineWorkspace` validated it at runtime.
|
|
145
|
+
*
|
|
146
|
+
* @public
|
|
147
|
+
*/
|
|
148
|
+
export type AipmWorkspace = AipmWorkspaceInput & {
|
|
149
|
+
readonly [aipmWorkspaceBrand]: 'AipmWorkspace';
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Validate and brand a workspace configuration. Throws a `ZodError` on invalid input (unknown
|
|
153
|
+
* keys, missing `marketplace.name`).
|
|
154
|
+
*
|
|
155
|
+
* @public
|
|
156
|
+
*/
|
|
157
|
+
export declare function defineWorkspace(config: AipmWorkspaceInput): AipmWorkspace;
|
|
46
158
|
export {};
|
|
47
159
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC7B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;;;GAOG;AACH,OAAO,CAAC,MAAM,eAAe,EAAE,OAAO,MAAM,CAAC;AAE7C;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG;IACzC,QAAQ,CAAC,CAAC,eAAe,CAAC,EAAE,YAAY,CAAC;CAC1C,CAAC;AAuBF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,UAAU,CAKhE;AAMD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,OAAO,CAAC,MAAM,mBAAmB,EAAE,OAAO,MAAM,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,GAAG;IAAE,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAuBzD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,GAAE,mBAAwB,GAAG,cAAc,CAGjF;AAMD;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,WAAW,EAAE;QACX,0DAA0D;QAC1D,IAAI,EAAE,MAAM,CAAC;QACb;;;WAGG;QACH,KAAK,CAAC,EAAE;YACN,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;QACF;;;WAGG;QACH,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;CACH;AAED;;;;GAIG;AACH,OAAO,CAAC,MAAM,kBAAkB,EAAE,OAAO,MAAM,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,kBAAkB,GAAG;IAC/C,QAAQ,CAAC,CAAC,kBAAkB,CAAC,EAAE,eAAe,CAAC;CAChD,CAAC;AAoBF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,kBAAkB,GAAG,aAAa,CAGzE"}
|
package/dist/config.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* `AipmConfig` as `AipmConfigInput` plus a structural marker proving `defineConfig` validated
|
|
7
7
|
* the value.
|
|
8
8
|
*/
|
|
9
|
+
import * as path from 'node:path';
|
|
9
10
|
import { z } from 'zod';
|
|
10
11
|
import { TARGET_IDS } from './pipeline/types.js';
|
|
11
12
|
/**
|
|
@@ -22,6 +23,8 @@ const aipmConfigSchema = z
|
|
|
22
23
|
.array(z.enum(TARGET_IDS))
|
|
23
24
|
.min(1, 'targets must contain at least one target')
|
|
24
25
|
.refine((arr) => new Set(arr).size === arr.length, 'targets must not contain duplicates'),
|
|
26
|
+
description: z.string().optional(),
|
|
27
|
+
keywords: z.array(z.string()).optional(),
|
|
25
28
|
})
|
|
26
29
|
.strict();
|
|
27
30
|
/**
|
|
@@ -35,4 +38,57 @@ export function defineConfig(config) {
|
|
|
35
38
|
// type-only marker proving validation ran. Cast through `unknown` per TS guidance.
|
|
36
39
|
return parsed;
|
|
37
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* A repo-relative path that is safe to join onto the repo root: non-empty, not absolute, and
|
|
43
|
+
* containing no `..` segment that could escape the repo. Host platforms resolve plugin `source`
|
|
44
|
+
* paths relative to the repo root, so an escaping root would be unrepresentable.
|
|
45
|
+
*/
|
|
46
|
+
const repoRelativePath = z
|
|
47
|
+
.string()
|
|
48
|
+
.min(1, 'path must not be empty')
|
|
49
|
+
.refine((p) => !path.isAbsolute(p), 'path must be relative to the repo root, not absolute')
|
|
50
|
+
.refine((p) => !p.split(/[\\/]/).includes('..'), "path must not contain a '..' segment (it must stay within the repo root)");
|
|
51
|
+
const aipmRepoConfigSchema = z
|
|
52
|
+
.object({
|
|
53
|
+
pluginsRoot: repoRelativePath.default('plugins'),
|
|
54
|
+
distDir: repoRelativePath.default('dist'),
|
|
55
|
+
})
|
|
56
|
+
.strict();
|
|
57
|
+
/**
|
|
58
|
+
* Validate and brand a repo configuration, applying defaults for any omitted field. Throws a
|
|
59
|
+
* `ZodError` on invalid input (unknown keys, absolute paths, `..` escapes).
|
|
60
|
+
*
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
export function defineRepoConfig(config = {}) {
|
|
64
|
+
const parsed = aipmRepoConfigSchema.parse(config);
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
const aipmWorkspaceSchema = z
|
|
68
|
+
.object({
|
|
69
|
+
marketplace: z
|
|
70
|
+
.object({
|
|
71
|
+
name: z.string().min(1, 'marketplace.name must not be empty'),
|
|
72
|
+
owner: z
|
|
73
|
+
.object({
|
|
74
|
+
name: z.string().min(1, 'marketplace.owner.name must not be empty'),
|
|
75
|
+
email: z.string().optional(),
|
|
76
|
+
})
|
|
77
|
+
.strict()
|
|
78
|
+
.optional(),
|
|
79
|
+
description: z.string().optional(),
|
|
80
|
+
})
|
|
81
|
+
.strict(),
|
|
82
|
+
})
|
|
83
|
+
.strict();
|
|
84
|
+
/**
|
|
85
|
+
* Validate and brand a workspace configuration. Throws a `ZodError` on invalid input (unknown
|
|
86
|
+
* keys, missing `marketplace.name`).
|
|
87
|
+
*
|
|
88
|
+
* @public
|
|
89
|
+
*/
|
|
90
|
+
export function defineWorkspace(config) {
|
|
91
|
+
const parsed = aipmWorkspaceSchema.parse(config);
|
|
92
|
+
return parsed;
|
|
93
|
+
}
|
|
38
94
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AA+CjD;;;;;GAKG;AACH,MAAM,aAAa,GACjB,qFAAqF,CAAC;AAExF,MAAM,gBAAgB,GAAG,CAAC;KACvB,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE,uCAAuC,CAAC;IACjF,OAAO,EAAE,CAAC;SACP,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SACzB,GAAG,CAAC,CAAC,EAAE,0CAA0C,CAAC;SAClD,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,qCAAqC,CAAC;IAC3F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACzC,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9C,oFAAoF;IACpF,mFAAmF;IACnF,OAAO,MAA+B,CAAC;AACzC,CAAC;AAgDD;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,CAAC;KACvB,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;KAChC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,sDAAsD,CAAC;KAC1F,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EACvC,0EAA0E,CAC3E,CAAC;AAEJ,MAAM,oBAAoB,GAAG,CAAC;KAC3B,MAAM,CAAC;IACN,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC;IAChD,OAAO,EAAE,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC;CAC1C,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAA8B,EAAE;IAC/D,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClD,OAAO,MAAmC,CAAC;AAC7C,CAAC;AAsDD,MAAM,mBAAmB,GAAG,CAAC;KAC1B,MAAM,CAAC;IACN,WAAW,EAAE,CAAC;SACX,MAAM,CAAC;QACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,oCAAoC,CAAC;QAC7D,KAAK,EAAE,CAAC;aACL,MAAM,CAAC;YACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,0CAA0C,CAAC;YACnE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC7B,CAAC;aACD,MAAM,EAAE;aACR,QAAQ,EAAE;QACb,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KACnC,CAAC;SACD,MAAM,EAAE;CACZ,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,MAA0B;IACxD,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjD,OAAO,MAAkC,CAAC;AAC5C,CAAC"}
|
package/dist/core.d.ts
CHANGED
|
@@ -47,6 +47,110 @@ export declare interface AipmConfigInput {
|
|
|
47
47
|
version: string;
|
|
48
48
|
/** Targets this plugin supports. See §6 of the spec. */
|
|
49
49
|
targets: readonly TargetId[];
|
|
50
|
+
/**
|
|
51
|
+
* Optional one-line description of the plugin. When the repo opts into registry generation (an
|
|
52
|
+
* `aipm.workspace.ts` is present), this becomes the plugin entry's `description` (Claude/Cursor)
|
|
53
|
+
* in the generated `marketplace.json`. Optional so existing configs stay valid.
|
|
54
|
+
*/
|
|
55
|
+
description?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Optional discovery keywords for the plugin. When the repo opts into registry generation, these
|
|
58
|
+
* become the plugin entry's `tags` (Claude/Cursor) in the generated `marketplace.json`. Optional
|
|
59
|
+
* so existing configs stay valid.
|
|
60
|
+
*/
|
|
61
|
+
keywords?: readonly string[];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Validated repo configuration. Carries a module-private brand indicating `defineRepoConfig`
|
|
66
|
+
* validated it; unlike the input, both fields are always present (defaults applied).
|
|
67
|
+
*
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
export declare type AipmRepoConfig = {
|
|
71
|
+
readonly pluginsRoot: string;
|
|
72
|
+
readonly distDir: string;
|
|
73
|
+
} & {
|
|
74
|
+
readonly [aipmRepoConfigBrand]: 'AipmRepoConfig';
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Module-private brand marker for {@link AipmRepoConfig}. Never exported.
|
|
79
|
+
*
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
declare const aipmRepoConfigBrand: unique symbol;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Raw input shape accepted by `defineRepoConfig`. Authored as `aipm.repo.ts` at the **repo
|
|
86
|
+
* root** of a project that hosts a marketplace inside a larger software repo. The file is
|
|
87
|
+
* optional: when absent, the toolkit behaves as if `defineRepoConfig({})` was used, reproducing
|
|
88
|
+
* the historical "repo root == marketplace root, fixed `plugins/`" topology.
|
|
89
|
+
*
|
|
90
|
+
* Both paths are repo-root-relative and must stay within the repo (no absolute paths, no `..`
|
|
91
|
+
* segments), because host platforms resolve a plugin's `source` relative to the repo root.
|
|
92
|
+
*
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
95
|
+
export declare interface AipmRepoConfigInput {
|
|
96
|
+
/**
|
|
97
|
+
* Directory (relative to the repo root) that holds plugin folders. Relocate this when the host
|
|
98
|
+
* software already owns a top-level `plugins/` directory. Default: `'plugins'`.
|
|
99
|
+
*/
|
|
100
|
+
pluginsRoot?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Directory (relative to the repo root) for generated `dist/` bundles. Relocate this when the
|
|
103
|
+
* host software already owns a top-level `dist/`. Default: `'dist'`.
|
|
104
|
+
*/
|
|
105
|
+
distDir?: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Validated workspace configuration. Structurally identical to {@link AipmWorkspaceInput} but
|
|
110
|
+
* carries a module-private brand indicating `defineWorkspace` validated it at runtime.
|
|
111
|
+
*
|
|
112
|
+
* @public
|
|
113
|
+
*/
|
|
114
|
+
export declare type AipmWorkspace = AipmWorkspaceInput & {
|
|
115
|
+
readonly [aipmWorkspaceBrand]: 'AipmWorkspace';
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Module-private brand marker for {@link AipmWorkspace}. Never exported.
|
|
120
|
+
*
|
|
121
|
+
* @internal
|
|
122
|
+
*/
|
|
123
|
+
declare const aipmWorkspaceBrand: unique symbol;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Raw input shape accepted by `defineWorkspace`. Authored as `aipm.workspace.ts` at the **repo
|
|
127
|
+
* root**. Its presence opts the repo into **marketplace-registry generation**: the toolkit
|
|
128
|
+
* generates the per-target `marketplace.json` registries from this workspace metadata plus the
|
|
129
|
+
* discovered plugins, commits them, and freshness-checks them. When the file is **absent**, the
|
|
130
|
+
* toolkit behaves exactly as before (registries are hand-authored and `validateMarketplaceRegistration`
|
|
131
|
+
* runs).
|
|
132
|
+
*
|
|
133
|
+
* @public
|
|
134
|
+
*/
|
|
135
|
+
export declare interface AipmWorkspaceInput {
|
|
136
|
+
/** Marketplace-level metadata shared across all generated registries. */
|
|
137
|
+
marketplace: {
|
|
138
|
+
/** Marketplace name — the registry's top-level `name`. */
|
|
139
|
+
name: string;
|
|
140
|
+
/**
|
|
141
|
+
* Optional owner block written to the Claude/Cursor registries' top-level `owner`. The Codex
|
|
142
|
+
* registry has no owner concept, so this is ignored there.
|
|
143
|
+
*/
|
|
144
|
+
owner?: {
|
|
145
|
+
name: string;
|
|
146
|
+
email?: string;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Optional marketplace description. For Claude/Cursor it becomes `metadata.description`; for
|
|
150
|
+
* Codex it is currently unused (the Codex registry has no marketplace-level description field).
|
|
151
|
+
*/
|
|
152
|
+
description?: string;
|
|
153
|
+
};
|
|
50
154
|
}
|
|
51
155
|
|
|
52
156
|
/**
|
|
@@ -98,6 +202,22 @@ export declare function checkSupport(pluginDir: string): Promise<SupportReport>;
|
|
|
98
202
|
*/
|
|
99
203
|
export declare function defineConfig(config: AipmConfigInput): AipmConfig;
|
|
100
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Validate and brand a repo configuration, applying defaults for any omitted field. Throws a
|
|
207
|
+
* `ZodError` on invalid input (unknown keys, absolute paths, `..` escapes).
|
|
208
|
+
*
|
|
209
|
+
* @public
|
|
210
|
+
*/
|
|
211
|
+
export declare function defineRepoConfig(config?: AipmRepoConfigInput): AipmRepoConfig;
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Validate and brand a workspace configuration. Throws a `ZodError` on invalid input (unknown
|
|
215
|
+
* keys, missing `marketplace.name`).
|
|
216
|
+
*
|
|
217
|
+
* @public
|
|
218
|
+
*/
|
|
219
|
+
export declare function defineWorkspace(config: AipmWorkspaceInput): AipmWorkspace;
|
|
220
|
+
|
|
101
221
|
/**
|
|
102
222
|
* A single validation finding.
|
|
103
223
|
*
|
|
@@ -118,9 +238,19 @@ export declare interface Finding {
|
|
|
118
238
|
* Enumerated finding codes. Additive — new codes arrive in toolkit MINOR releases; removing
|
|
119
239
|
* or renaming a code is MAJOR. Consumers SHOULD handle unknown codes gracefully.
|
|
120
240
|
*
|
|
241
|
+
* `single-artifact-host` — a "single-artifact host" (`gemini` or `kiro`), which installs ONE
|
|
242
|
+
* extension/power per repo from the repo ROOT and has no marketplace concept, is declared by MORE
|
|
243
|
+
* THAN ONE plugin in the repo. The root artifact for that host is NOT emitted while the ambiguity
|
|
244
|
+
* stands (the toolkit can't choose which plugin owns the single root slot).
|
|
245
|
+
*
|
|
246
|
+
* `root-artifact-collision` — a generated repo-root path the toolkit would write is already
|
|
247
|
+
* occupied by a file the toolkit does NOT track as previously-generated (i.e. it belongs to the
|
|
248
|
+
* host software / the author). Generation refuses to overwrite it rather than clobber repo-root
|
|
249
|
+
* state.
|
|
250
|
+
*
|
|
121
251
|
* @public
|
|
122
252
|
*/
|
|
123
|
-
export declare type FindingCode = 'envelope-invalid' | 'envelope-adherence' | 'schema-invalid' | 'name-consistency' | 'mcp-key-sync' | 'marketplace-registration' | 'freshness';
|
|
253
|
+
export declare type FindingCode = 'envelope-invalid' | 'repo-config-invalid' | 'envelope-adherence' | 'schema-invalid' | 'name-consistency' | 'mcp-key-sync' | 'marketplace-registration' | 'freshness' | 'single-artifact-host' | 'root-artifact-collision';
|
|
124
254
|
|
|
125
255
|
/**
|
|
126
256
|
* A file produced or verified by the build.
|
|
@@ -157,6 +287,13 @@ export declare interface InitOptions {
|
|
|
157
287
|
* directory.
|
|
158
288
|
*/
|
|
159
289
|
name?: string;
|
|
290
|
+
/**
|
|
291
|
+
* Version of `@ai-plugin-marketplace/cli` to pin the generated `package.json`'s `cli`
|
|
292
|
+
* dev dependency to (as `^<cliVersion>`). The cli entrypoint supplies its own version here; cli
|
|
293
|
+
* and core ship independently and may differ (e.g. `cli 0.1.1` ships with `core 0.2.0`). When
|
|
294
|
+
* omitted, falls back to core's own version (the historical lockstep assumption).
|
|
295
|
+
*/
|
|
296
|
+
cliVersion?: string;
|
|
160
297
|
}
|
|
161
298
|
|
|
162
299
|
/**
|
|
@@ -203,8 +340,54 @@ export declare interface MigrateResult {
|
|
|
203
340
|
}
|
|
204
341
|
|
|
205
342
|
/**
|
|
206
|
-
*
|
|
207
|
-
*
|
|
343
|
+
* Options for {@link refreshScaffold}.
|
|
344
|
+
*
|
|
345
|
+
* @public
|
|
346
|
+
*/
|
|
347
|
+
export declare interface RefreshOptions {
|
|
348
|
+
/**
|
|
349
|
+
* Overwrite toolkit-owned scaffold files even when their on-disk content has diverged from what
|
|
350
|
+
* the toolkit last wrote (i.e. the user edited them). Without this, diverged files are reported
|
|
351
|
+
* as conflicts and left untouched.
|
|
352
|
+
*/
|
|
353
|
+
force?: boolean;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Per-file outcome of a {@link refreshScaffold} run. Returned (one per managed scaffold file) so
|
|
358
|
+
* the CLI can report what changed without re-deriving it.
|
|
359
|
+
*
|
|
360
|
+
* @public
|
|
361
|
+
*/
|
|
362
|
+
export declare interface RefreshOutcome {
|
|
363
|
+
/** Repo-relative POSIX path of the managed scaffold file. */
|
|
364
|
+
path: string;
|
|
365
|
+
/**
|
|
366
|
+
* - `updated` — content changed and was rewritten (file was pristine or `--force`).
|
|
367
|
+
* - `unchanged` — already matched the current render; nothing written.
|
|
368
|
+
* - `recreated` — file was missing and was written from the render.
|
|
369
|
+
* - `conflict` — on-disk content diverged from the recorded hash; left untouched (no `--force`).
|
|
370
|
+
* - `overwritten` — diverged but rewritten because `--force` was set.
|
|
371
|
+
*/
|
|
372
|
+
status: 'updated' | 'unchanged' | 'recreated' | 'conflict' | 'overwritten';
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Refresh the toolkit-owned scaffold files (CI workflow, `.gitignore`) of an existing marketplace
|
|
377
|
+
* repo at `targetDir` to match the installed tooling — the upgrade path after
|
|
378
|
+
* `pnpm up @ai-plugin-marketplace/*`. Guarded by the `.aipm/scaffold.json` content-hash sidecar:
|
|
379
|
+
* user-modified files are reported as conflicts and left untouched unless `opts.force` is set.
|
|
380
|
+
* Returns one outcome per managed file; never rejects on conflict.
|
|
381
|
+
*
|
|
382
|
+
* @public
|
|
383
|
+
*/
|
|
384
|
+
export declare function refreshScaffold(targetDir: string, opts?: RefreshOptions): Promise<RefreshOutcome[]>;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Scaffold a new plugin under the cwd's configured plugins root (`<cwd>/plugins/<name>` by
|
|
388
|
+
* default, or the relocated `pluginsRoot` from an `aipm.repo.ts`). The plugins directory is
|
|
389
|
+
* derived from the current working directory, matching how `aipm scaffold` is invoked from a repo
|
|
390
|
+
* root.
|
|
208
391
|
*
|
|
209
392
|
* @public
|
|
210
393
|
*/
|
|
@@ -257,7 +440,7 @@ export declare interface SupportReport {
|
|
|
257
440
|
*
|
|
258
441
|
* @public
|
|
259
442
|
*/
|
|
260
|
-
export declare type TargetId = 'claude' | 'cursor' | 'gemini' | 'kiro' | 'vercel';
|
|
443
|
+
export declare type TargetId = 'claude' | 'codex' | 'cursor' | 'gemini' | 'kiro' | 'vercel';
|
|
261
444
|
|
|
262
445
|
/**
|
|
263
446
|
* Validate a single plugin or every plugin under a repo root, in the order defined by §10.1.
|
package/dist/index.d.ts
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @packageDocumentation
|
|
10
10
|
*/
|
|
11
|
-
export { defineConfig } from './config.js';
|
|
12
|
-
export type { AipmConfig, AipmConfigInput } from './config.js';
|
|
13
|
-
export { build, validate, scaffold, init, migrate, checkSupport, addTarget, listTargets, } from './pipeline/operations.js';
|
|
14
|
-
export type { TargetId, BuildOptions, BuildResult, GeneratedFile, ValidateOptions, ValidationResult, Finding, FindingCode, ScaffoldOptions, InitOptions, MigrateOptions, MigrateResult, SupportReport, } from './pipeline/types.js';
|
|
11
|
+
export { defineConfig, defineRepoConfig, defineWorkspace } from './config.js';
|
|
12
|
+
export type { AipmConfig, AipmConfigInput, AipmRepoConfig, AipmRepoConfigInput, AipmWorkspace, AipmWorkspaceInput, } from './config.js';
|
|
13
|
+
export { build, validate, scaffold, init, refreshScaffold, migrate, checkSupport, addTarget, listTargets, } from './pipeline/operations.js';
|
|
14
|
+
export type { TargetId, BuildOptions, BuildResult, GeneratedFile, ValidateOptions, ValidationResult, Finding, FindingCode, ScaffoldOptions, InitOptions, RefreshOptions, RefreshOutcome, MigrateOptions, MigrateResult, SupportReport, } from './pipeline/types.js';
|
|
15
15
|
//# 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;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9E,YAAY,EACV,UAAU,EACV,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,eAAe,EACf,OAAO,EACP,YAAY,EACZ,SAAS,EACT,WAAW,GACZ,MAAM,0BAA0B,CAAC;AAElC,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,OAAO,EACP,WAAW,EACX,eAAe,EACf,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,EACd,aAAa,EACb,aAAa,GACd,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @packageDocumentation
|
|
10
10
|
*/
|
|
11
|
-
export { defineConfig } from './config.js';
|
|
12
|
-
export { build, validate, scaffold, init, migrate, checkSupport, addTarget, listTargets, } from './pipeline/operations.js';
|
|
11
|
+
export { defineConfig, defineRepoConfig, defineWorkspace } from './config.js';
|
|
12
|
+
export { build, validate, scaffold, init, refreshScaffold, migrate, checkSupport, addTarget, listTargets, } from './pipeline/operations.js';
|
|
13
13
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAU9E,OAAO,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,IAAI,EACJ,eAAe,EACf,OAAO,EACP,YAAY,EACZ,SAAS,EACT,WAAW,GACZ,MAAM,0BAA0B,CAAC"}
|
package/dist/pipeline/build.d.ts
CHANGED
|
@@ -14,8 +14,10 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @see docs/specs/architecture.md §5.2 (build phase), §5.4 (phase invariants), §7.2, §10.5
|
|
16
16
|
*/
|
|
17
|
+
import type { AipmWorkspace } from '../config.js';
|
|
18
|
+
import type { ConfigCache } from './load-config.js';
|
|
17
19
|
import type { SentinelMode } from './sentinel.js';
|
|
18
|
-
import type { BuildOptions, BuildResult, TargetId } from './types.js';
|
|
20
|
+
import type { BuildOptions, BuildResult, Finding, TargetId } from './types.js';
|
|
19
21
|
/**
|
|
20
22
|
* A toolkit-generated file that lives **inside the plugin directory** and carries a sentinel.
|
|
21
23
|
* Both the build (which writes `expectedContent`) and the freshness check (which compares the
|
|
@@ -64,6 +66,161 @@ export interface DistBundle {
|
|
|
64
66
|
* build (calls `regenerate(destDir)`) and freshness (calls `regenerate(tempDir)` then compares).
|
|
65
67
|
*/
|
|
66
68
|
export declare function computeDistBundles(pluginDir: string, distDir: string, envelope: readonly TargetId[]): DistBundle[];
|
|
69
|
+
/**
|
|
70
|
+
* One discovered plugin's contribution to registry generation. The repo-level
|
|
71
|
+
* {@link computeRegistryArtifacts} step assembles these (loading each plugin's `aipm.config.ts`
|
|
72
|
+
* for `description`/`keywords` and its envelope) so the registry generator never re-reads disk.
|
|
73
|
+
*/
|
|
74
|
+
export interface RegistryPluginInfo {
|
|
75
|
+
/** Plugin directory basename (the registry entry `name`). */
|
|
76
|
+
name: string;
|
|
77
|
+
/**
|
|
78
|
+
* The plugin directory relative to the repo root, `./`-prefixed and POSIX-separated (e.g.
|
|
79
|
+
* `./plugins/<name>`). This is the registry entry's `source` (string for Claude/Cursor, the
|
|
80
|
+
* `source.path` for Codex). Honors a relocated `pluginsRoot`.
|
|
81
|
+
*/
|
|
82
|
+
source: string;
|
|
83
|
+
/** The plugin's declared support envelope (`config.targets`). */
|
|
84
|
+
envelope: readonly TargetId[];
|
|
85
|
+
/** Optional one-line description from `aipm.config.ts`; maps to the entry `description`/`tags` host. */
|
|
86
|
+
description?: string;
|
|
87
|
+
/** Optional keywords from `aipm.config.ts`; maps to the entry `tags` (Claude/Cursor). */
|
|
88
|
+
keywords?: readonly string[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* A generated marketplace registry file. Like `dist/` bundles, registries are **sentinel-less**:
|
|
92
|
+
* the host schemas are strict and there is no companion sidecar, so freshness is a whole-file
|
|
93
|
+
* regenerate-and-byte-compare against `expectedContent`. Both `runBuild` (which writes the bytes)
|
|
94
|
+
* and the freshness check (which compares disk to the bytes) derive these from one place.
|
|
95
|
+
*/
|
|
96
|
+
export interface RegistryArtifact {
|
|
97
|
+
/** The registry-backed target this file serves. */
|
|
98
|
+
target: TargetId;
|
|
99
|
+
/** Absolute path of the registry file (always at the repo root). */
|
|
100
|
+
absPath: string;
|
|
101
|
+
/** Exact bytes the build writes (2-space JSON + trailing newline). */
|
|
102
|
+
expectedContent: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Absolute paths of every registry the toolkit MANAGES under a repo root (one per registry-backed
|
|
106
|
+
* target), regardless of whether the current envelope produces it. Used to detect **orphaned**
|
|
107
|
+
* registries — a committed `marketplace.json` for a target no longer declared by any plugin —
|
|
108
|
+
* which `runBuild` removes and the validator flags as stale. Shared so build and validate agree
|
|
109
|
+
* on exactly which files generation owns (and never touch anything else).
|
|
110
|
+
*/
|
|
111
|
+
export declare function managedRegistryPaths(repoRoot: string): string[];
|
|
112
|
+
/**
|
|
113
|
+
* Compute the generated marketplace registries for a repo, **without writing**. The single source
|
|
114
|
+
* of truth shared by `runBuild` (which writes `expectedContent`) and the freshness check (which
|
|
115
|
+
* compares the on-disk bytes against it).
|
|
116
|
+
*
|
|
117
|
+
* A registry file is produced for each registry-backed target (`claude` → `.claude-plugin/`,
|
|
118
|
+
* `cursor` → `.cursor-plugin/`, `codex` → `.agents/plugins/`) that appears in **at least one**
|
|
119
|
+
* plugin's envelope. Each registry lists exactly the plugins whose envelope includes that target,
|
|
120
|
+
* in the order given (callers pass plugins sorted by discovery). Registries are sentinel-less.
|
|
121
|
+
*
|
|
122
|
+
* @param repoRoot - Absolute repo root (where the registries live).
|
|
123
|
+
* @param plugins - Discovered plugins with name/source/envelope/description/keywords.
|
|
124
|
+
* @param workspace - The validated `aipm.workspace.ts` metadata.
|
|
125
|
+
*/
|
|
126
|
+
export declare function computeRegistryArtifacts(repoRoot: string, plugins: readonly RegistryPluginInfo[], workspace: AipmWorkspace): RegistryArtifact[];
|
|
127
|
+
/**
|
|
128
|
+
* Assemble the {@link RegistryPluginInfo} for every discovered plugin under `repoRoot`, loading
|
|
129
|
+
* each plugin's `aipm.config.ts` for its envelope, description, and keywords. Shared by `runBuild`
|
|
130
|
+
* and the freshness check so both feed `computeRegistryArtifacts` identical input.
|
|
131
|
+
*
|
|
132
|
+
* @param repoRoot - Absolute repo root (the base for the `./`-prefixed `source`).
|
|
133
|
+
* @param pluginDirs - Absolute plugin directories (already discovery-sorted).
|
|
134
|
+
*/
|
|
135
|
+
export declare function collectRegistryPlugins(repoRoot: string, pluginDirs: readonly string[], cache?: ConfigCache): Promise<RegistryPluginInfo[]>;
|
|
136
|
+
/**
|
|
137
|
+
* The hosts that have NO multi-plugin marketplace concept: each installs exactly ONE
|
|
138
|
+
* extension/power per repo, read from the **repo root**. `gemini extensions install <git>` reads a
|
|
139
|
+
* root `gemini-extension.json`; Kiro "Add from GitHub" reads a root `POWER.md`. Because the repo
|
|
140
|
+
* root has a single slot per host, at most one plugin may declare each — see the N=1 gate below.
|
|
141
|
+
*/
|
|
142
|
+
declare const SINGLE_ARTIFACT_HOSTS: readonly ["gemini", "kiro"];
|
|
143
|
+
/** A single-artifact host (`gemini` | `kiro`). */
|
|
144
|
+
type SingleArtifactHost = (typeof SINGLE_ARTIFACT_HOSTS)[number];
|
|
145
|
+
/** Absolute path of the generated-root sidecar manifest under `repoRoot`. */
|
|
146
|
+
export declare function rootManifestPath(repoRoot: string): string;
|
|
147
|
+
/**
|
|
148
|
+
* A single repo-root file the toolkit generates for a single-artifact host. `relPath` is the path
|
|
149
|
+
* relative to the repo root (POSIX-separated, the tracked-set form); `content` is the exact bytes.
|
|
150
|
+
*/
|
|
151
|
+
interface RootArtifactFile {
|
|
152
|
+
/** Repo-root-relative POSIX path (e.g. `gemini-extension.json`, `commands/foo.toml`). */
|
|
153
|
+
relPath: string;
|
|
154
|
+
/** The host whose bundle produced this file. */
|
|
155
|
+
host: SingleArtifactHost;
|
|
156
|
+
/** Exact bytes to write at the repo root. */
|
|
157
|
+
content: Buffer;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Result of {@link computeRootArtifacts}: the repo-root files to emit (across all single-artifact
|
|
161
|
+
* hosts that passed the N=1 gate), the set of repo-root-relative paths generation owns, and any
|
|
162
|
+
* `single-artifact-host` findings for hosts that more than one plugin declared (whose root artifact
|
|
163
|
+
* is suppressed).
|
|
164
|
+
*/
|
|
165
|
+
export interface RootArtifacts {
|
|
166
|
+
/** Files to write at the repo root (empty if no host is emittable). */
|
|
167
|
+
files: RootArtifactFile[];
|
|
168
|
+
/** Repo-root-relative POSIX paths the toolkit generated this run (the tracked set). Sorted. */
|
|
169
|
+
trackedPaths: string[];
|
|
170
|
+
/** Hard `single-artifact-host` findings — one per host declared by more than one plugin. */
|
|
171
|
+
findings: Finding[];
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Compute the repo-root native artifacts for the single-artifact hosts (`gemini`, `kiro`),
|
|
175
|
+
* **without writing**. The single source of truth shared by `runBuild` (which writes the files,
|
|
176
|
+
* applies the collision guard, and orphan-removes) and the freshness check (which compares disk to
|
|
177
|
+
* these bytes). Bundling happens into a throwaway temp dir — the repo root is never passed to a
|
|
178
|
+
* bundler, so the bundlers' `rmSync(destDir)` can never touch repo-root state.
|
|
179
|
+
*
|
|
180
|
+
* **N=1 gate (`single-artifact-host`).** For each host, count the plugins whose envelope declares
|
|
181
|
+
* it. Exactly one declarer → emit that plugin's bundled files at the repo root. More than one →
|
|
182
|
+
* emit a hard `single-artifact-host` finding and emit NOTHING for that host (the toolkit can't pick
|
|
183
|
+
* which plugin owns the single root slot). Zero → nothing to emit (and no finding). The two hosts
|
|
184
|
+
* are independent: a repo where plugin A declares `gemini` and plugin B declares `kiro` emits both
|
|
185
|
+
* (a root `gemini-extension.json` and a root `POWER.md` — distinct files).
|
|
186
|
+
*
|
|
187
|
+
* @param repoRoot - Absolute repo root (where the artifacts live). Accepted for signature
|
|
188
|
+
* parallelism with {@link computeRegistryArtifacts}; the bundlers read only the plugin dir.
|
|
189
|
+
* @param plugins - Discovered plugins with name/source/envelope (the registry plugin infos already
|
|
190
|
+
* collected for {@link computeRegistryArtifacts}). Each `source` resolves the plugin dir.
|
|
191
|
+
* @param _workspace - The validated workspace metadata. Unused by the bundlers today; accepted for
|
|
192
|
+
* parallelism with the registry compute signature and to future-proof host metadata injection.
|
|
193
|
+
*/
|
|
194
|
+
export declare function computeRootArtifacts(repoRoot: string, plugins: readonly RegistryPluginInfo[], _workspace: AipmWorkspace): RootArtifacts;
|
|
195
|
+
/**
|
|
196
|
+
* Detect repo-root collisions for the freshly computed {@link RootArtifacts}, given the PRIOR
|
|
197
|
+
* tracked set. A file collides when it exists on disk AND its repo-root-relative path is NOT in the
|
|
198
|
+
* prior tracked set — i.e. it is not something the toolkit previously created, so it belongs to the
|
|
199
|
+
* host/author and must not be clobbered (safety guard 3). A clean repo (no pre-existing root files)
|
|
200
|
+
* never collides. Collision is evaluated PER HOST: if any of a host's files collide, that host is
|
|
201
|
+
* suppressed entirely (no partial writes) and a single finding names the first offending path.
|
|
202
|
+
*
|
|
203
|
+
* Returns the collision findings plus the set of hosts that collided (so the caller can skip
|
|
204
|
+
* writing/tracking their files). Pure — no I/O beyond `existsSync`.
|
|
205
|
+
*/
|
|
206
|
+
export declare function detectRootCollisions(repoRoot: string, artifacts: RootArtifacts, priorTracked: readonly string[]): {
|
|
207
|
+
findings: Finding[];
|
|
208
|
+
collidedHosts: Set<SingleArtifactHost>;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* Serialize the generated-root sidecar manifest. Shape: `{ version: 1, paths: string[] }` where
|
|
212
|
+
* `paths` is the sorted set of repo-root-relative POSIX paths the toolkit generated (the sidecar
|
|
213
|
+
* itself is NOT listed — it is tracked separately and always lives at {@link rootManifestPath}).
|
|
214
|
+
* 2-space JSON + trailing newline, byte-stable so the freshness compare is exact.
|
|
215
|
+
*/
|
|
216
|
+
export declare function serializeRootManifest(trackedPaths: readonly string[]): string;
|
|
217
|
+
/**
|
|
218
|
+
* Read the prior generated-root sidecar manifest, returning the tracked-path set it recorded.
|
|
219
|
+
* Returns an empty array when the sidecar is absent or unparseable — a missing/corrupt sidecar is
|
|
220
|
+
* treated as "nothing tracked yet" (a clean first build), and the collision guard then protects any
|
|
221
|
+
* pre-existing root files. POSIX-separated paths are returned as-is.
|
|
222
|
+
*/
|
|
223
|
+
export declare function readRootManifestPaths(repoRoot: string): string[];
|
|
67
224
|
/** Collect every file path under `dir`, relative to `dir`. Returns `[]` if `dir` is absent. */
|
|
68
225
|
export declare function collectFilesRelative(dir: string): string[];
|
|
69
226
|
/**
|
|
@@ -87,4 +244,5 @@ export declare function runBuild(targetPath: string, opts?: BuildOptions): Promi
|
|
|
87
244
|
* on-disk bundle without disturbing it.
|
|
88
245
|
*/
|
|
89
246
|
export declare function regenerateBundleToTemp(bundle: DistBundle): string;
|
|
247
|
+
export {};
|
|
90
248
|
//# sourceMappingURL=build.d.ts.map
|