@ai-plugin-marketplace/core 0.1.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/LICENSE +21 -0
- package/README.md +67 -0
- package/dist/config.d.ts +47 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/core.d.ts +291 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/pipeline/build.d.ts +90 -0
- package/dist/pipeline/build.d.ts.map +1 -0
- package/dist/pipeline/build.js +224 -0
- package/dist/pipeline/build.js.map +1 -0
- package/dist/pipeline/discover.d.ts +37 -0
- package/dist/pipeline/discover.d.ts.map +1 -0
- package/dist/pipeline/discover.js +71 -0
- package/dist/pipeline/discover.js.map +1 -0
- package/dist/pipeline/init-template.d.ts +33 -0
- package/dist/pipeline/init-template.d.ts.map +1 -0
- package/dist/pipeline/init-template.js +142 -0
- package/dist/pipeline/init-template.js.map +1 -0
- package/dist/pipeline/init.d.ts +39 -0
- package/dist/pipeline/init.d.ts.map +1 -0
- package/dist/pipeline/init.js +84 -0
- package/dist/pipeline/init.js.map +1 -0
- package/dist/pipeline/load-config.d.ts +47 -0
- package/dist/pipeline/load-config.d.ts.map +1 -0
- package/dist/pipeline/load-config.js +106 -0
- package/dist/pipeline/load-config.js.map +1 -0
- package/dist/pipeline/operations.d.ts +70 -0
- package/dist/pipeline/operations.d.ts.map +1 -0
- package/dist/pipeline/operations.js +100 -0
- package/dist/pipeline/operations.js.map +1 -0
- package/dist/pipeline/scaffold.d.ts +105 -0
- package/dist/pipeline/scaffold.d.ts.map +1 -0
- package/dist/pipeline/scaffold.js +422 -0
- package/dist/pipeline/scaffold.js.map +1 -0
- package/dist/pipeline/sentinel.d.ts +127 -0
- package/dist/pipeline/sentinel.d.ts.map +1 -0
- package/dist/pipeline/sentinel.js +263 -0
- package/dist/pipeline/sentinel.js.map +1 -0
- package/dist/pipeline/types.d.ts +178 -0
- package/dist/pipeline/types.d.ts.map +1 -0
- package/dist/pipeline/types.js +26 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/pipeline/validate.d.ts +90 -0
- package/dist/pipeline/validate.d.ts.map +1 -0
- package/dist/pipeline/validate.js +617 -0
- package/dist/pipeline/validate.js.map +1 -0
- package/dist/targets/claude/scaffold.d.ts +32 -0
- package/dist/targets/claude/scaffold.d.ts.map +1 -0
- package/dist/targets/claude/scaffold.js +48 -0
- package/dist/targets/claude/scaffold.js.map +1 -0
- package/dist/targets/claude/schemas.d.ts +119 -0
- package/dist/targets/claude/schemas.d.ts.map +1 -0
- package/dist/targets/claude/schemas.js +204 -0
- package/dist/targets/claude/schemas.js.map +1 -0
- package/dist/targets/claude/transform.d.ts +40 -0
- package/dist/targets/claude/transform.d.ts.map +1 -0
- package/dist/targets/claude/transform.js +48 -0
- package/dist/targets/claude/transform.js.map +1 -0
- package/dist/targets/claude/validate.d.ts +25 -0
- package/dist/targets/claude/validate.d.ts.map +1 -0
- package/dist/targets/claude/validate.js +263 -0
- package/dist/targets/claude/validate.js.map +1 -0
- package/dist/targets/cursor/scaffold.d.ts +29 -0
- package/dist/targets/cursor/scaffold.d.ts.map +1 -0
- package/dist/targets/cursor/scaffold.js +45 -0
- package/dist/targets/cursor/scaffold.js.map +1 -0
- package/dist/targets/cursor/schemas.d.ts +49 -0
- package/dist/targets/cursor/schemas.d.ts.map +1 -0
- package/dist/targets/cursor/schemas.js +125 -0
- package/dist/targets/cursor/schemas.js.map +1 -0
- package/dist/targets/cursor/validate.d.ts +28 -0
- package/dist/targets/cursor/validate.d.ts.map +1 -0
- package/dist/targets/cursor/validate.js +181 -0
- package/dist/targets/cursor/validate.js.map +1 -0
- package/dist/targets/gemini/bundle.d.ts +25 -0
- package/dist/targets/gemini/bundle.d.ts.map +1 -0
- package/dist/targets/gemini/bundle.js +149 -0
- package/dist/targets/gemini/bundle.js.map +1 -0
- package/dist/targets/gemini/scaffold.d.ts +28 -0
- package/dist/targets/gemini/scaffold.d.ts.map +1 -0
- package/dist/targets/gemini/scaffold.js +57 -0
- package/dist/targets/gemini/scaffold.js.map +1 -0
- package/dist/targets/gemini/schemas.d.ts +53 -0
- package/dist/targets/gemini/schemas.d.ts.map +1 -0
- package/dist/targets/gemini/schemas.js +72 -0
- package/dist/targets/gemini/schemas.js.map +1 -0
- package/dist/targets/gemini/transform.d.ts +106 -0
- package/dist/targets/gemini/transform.d.ts.map +1 -0
- package/dist/targets/gemini/transform.js +137 -0
- package/dist/targets/gemini/transform.js.map +1 -0
- package/dist/targets/gemini/validate.d.ts +26 -0
- package/dist/targets/gemini/validate.d.ts.map +1 -0
- package/dist/targets/gemini/validate.js +146 -0
- package/dist/targets/gemini/validate.js.map +1 -0
- package/dist/targets/kiro/bundle.d.ts +32 -0
- package/dist/targets/kiro/bundle.d.ts.map +1 -0
- package/dist/targets/kiro/bundle.js +106 -0
- package/dist/targets/kiro/bundle.js.map +1 -0
- package/dist/targets/kiro/scaffold.d.ts +28 -0
- package/dist/targets/kiro/scaffold.d.ts.map +1 -0
- package/dist/targets/kiro/scaffold.js +55 -0
- package/dist/targets/kiro/scaffold.js.map +1 -0
- package/dist/targets/kiro/schemas.d.ts +100 -0
- package/dist/targets/kiro/schemas.d.ts.map +1 -0
- package/dist/targets/kiro/schemas.js +147 -0
- package/dist/targets/kiro/schemas.js.map +1 -0
- package/dist/targets/kiro/transform.d.ts +53 -0
- package/dist/targets/kiro/transform.d.ts.map +1 -0
- package/dist/targets/kiro/transform.js +113 -0
- package/dist/targets/kiro/transform.js.map +1 -0
- package/dist/targets/kiro/validate.d.ts +36 -0
- package/dist/targets/kiro/validate.d.ts.map +1 -0
- package/dist/targets/kiro/validate.js +232 -0
- package/dist/targets/kiro/validate.js.map +1 -0
- package/dist/targets/scaffold-kit.d.ts +56 -0
- package/dist/targets/scaffold-kit.d.ts.map +1 -0
- package/dist/targets/scaffold-kit.js +33 -0
- package/dist/targets/scaffold-kit.js.map +1 -0
- package/dist/targets/vercel/scaffold.d.ts +34 -0
- package/dist/targets/vercel/scaffold.d.ts.map +1 -0
- package/dist/targets/vercel/scaffold.js +58 -0
- package/dist/targets/vercel/scaffold.js.map +1 -0
- package/dist/targets/vercel/schemas.d.ts +42 -0
- package/dist/targets/vercel/schemas.d.ts.map +1 -0
- package/dist/targets/vercel/schemas.js +69 -0
- package/dist/targets/vercel/schemas.js.map +1 -0
- package/dist/targets/vercel/validate.d.ts +28 -0
- package/dist/targets/vercel/validate.d.ts.map +1 -0
- package/dist/targets/vercel/validate.js +180 -0
- package/dist/targets/vercel/validate.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure mechanical transformations for the Gemini CLI target.
|
|
3
|
+
*
|
|
4
|
+
* Per spec §7.1, the transform layer is a pure function driven by a committed lookup table,
|
|
5
|
+
* bounded to a single target. No I/O is performed here.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/specs/architecture.md §7 (mechanical transformations)
|
|
8
|
+
* @see docs/specs/architecture.md §12.4 (transform step + per-target folder layout)
|
|
9
|
+
* @see docs/specs/architecture.md §12.5 (internal module shape)
|
|
10
|
+
*/
|
|
11
|
+
import type { GeminiToolName } from './schemas.js';
|
|
12
|
+
/**
|
|
13
|
+
* Committed lookup table mapping Claude Code tool names (PascalCase) to Gemini CLI
|
|
14
|
+
* tool names (snake_case). Per spec §7.1, the mechanical-transformation definition
|
|
15
|
+
* requires the table be committed in source.
|
|
16
|
+
*
|
|
17
|
+
* Exact port of CLAUDE_TO_GEMINI_TOOLS from the template's build-standalone.ts.
|
|
18
|
+
*/
|
|
19
|
+
export declare const CLAUDE_TO_GEMINI_TOOLS: Readonly<Record<string, GeminiToolName>>;
|
|
20
|
+
/**
|
|
21
|
+
* Translate a single Claude Code tool name to its Gemini CLI equivalent.
|
|
22
|
+
* Returns the Gemini tool name or `undefined` if there is no mapping.
|
|
23
|
+
*/
|
|
24
|
+
export declare function translateToolName(claudeToolName: string): GeminiToolName | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Rewrite the `tools:` list in an agent `.md` file's YAML frontmatter from Claude Code
|
|
27
|
+
* tool names to Gemini CLI equivalents. Tools with no mapping are dropped.
|
|
28
|
+
*
|
|
29
|
+
* Pure: takes a string, returns a string + metadata. No I/O.
|
|
30
|
+
*
|
|
31
|
+
* @param mdContent - Full content of the agent `.md` file.
|
|
32
|
+
* @returns Rewritten content and the list of dropped Claude tool names (for diagnostics).
|
|
33
|
+
*/
|
|
34
|
+
export declare function rewriteAgentFrontmatterTools(mdContent: string): {
|
|
35
|
+
content: string;
|
|
36
|
+
droppedTools: string[];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Minimal local type for a single hook entry (command runner).
|
|
40
|
+
* Defined here rather than imported from claude/ to honour the cross-target-import
|
|
41
|
+
* prohibition enforced by ESLint (§3.4).
|
|
42
|
+
*/
|
|
43
|
+
interface GeminiHookEntry {
|
|
44
|
+
type?: string;
|
|
45
|
+
command?: string;
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Minimal local type for a single hook matcher block.
|
|
50
|
+
*/
|
|
51
|
+
interface GeminiHookMatcher {
|
|
52
|
+
matcher?: string;
|
|
53
|
+
description?: string;
|
|
54
|
+
hooks?: GeminiHookEntry[];
|
|
55
|
+
[key: string]: unknown;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Minimal local type for the top-level hooks file object.
|
|
59
|
+
* Mirrors the shape used by `build-hooks.ts` in the template repo — a plain
|
|
60
|
+
* object whose optional `hooks` key maps event names to arrays of matchers.
|
|
61
|
+
*
|
|
62
|
+
* @see /Users/mnorth/Development/ai-plugin-marketplace-template/src/build-hooks.ts
|
|
63
|
+
* `HooksFile` interface (reference)
|
|
64
|
+
*/
|
|
65
|
+
interface GeminiHooksFile {
|
|
66
|
+
hooks?: Record<string, GeminiHookMatcher[]>;
|
|
67
|
+
[key: string]: unknown;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Deep-clone a parsed hooks object and translate `matcher` tool-name strings from
|
|
71
|
+
* Claude Code PascalCase names to Gemini CLI snake_case equivalents via
|
|
72
|
+
* {@link CLAUDE_TO_GEMINI_TOOLS}.
|
|
73
|
+
*
|
|
74
|
+
* Matchers that have no entry in the table (e.g. glob patterns, non-tool identifiers)
|
|
75
|
+
* are preserved unchanged — exact port of `translateHooksForGemini` in `build-hooks.ts`.
|
|
76
|
+
*
|
|
77
|
+
* Pure: no I/O, no side-effects. The input object is never mutated.
|
|
78
|
+
*
|
|
79
|
+
* @param source - Parsed hooks object (as returned by the `yaml` package's `parse`).
|
|
80
|
+
* @returns A new hooks object with matcher strings translated for Gemini CLI.
|
|
81
|
+
*
|
|
82
|
+
* @see https://geminicli.com/docs/extensions/reference/ — Gemini CLI hooks format
|
|
83
|
+
* @see /Users/mnorth/Development/ai-plugin-marketplace-template/src/build-hooks.ts
|
|
84
|
+
* `translateHooksForGemini` (reference implementation)
|
|
85
|
+
*/
|
|
86
|
+
export declare function translateHooksForGemini(source: GeminiHooksFile): GeminiHooksFile;
|
|
87
|
+
/**
|
|
88
|
+
* One-shot conversion: parse a `hooks/claude.yaml` string, translate all tool-name
|
|
89
|
+
* matchers for Gemini CLI, and serialize as pretty-printed JSON.
|
|
90
|
+
*
|
|
91
|
+
* Output format: 2-space indent, trailing newline — byte-identical to the output of
|
|
92
|
+
* `convertHookFile(hooksDir, yamlFile, "gemini")` in the template's `build-hooks.ts`.
|
|
93
|
+
*
|
|
94
|
+
* Pure: no I/O. Throws if the YAML is malformed.
|
|
95
|
+
*
|
|
96
|
+
* @param yamlContent - Raw YAML string (contents of `hooks/claude.yaml` or `.yml`).
|
|
97
|
+
* @returns Pretty-printed JSON string with trailing newline.
|
|
98
|
+
* @throws {Error} If the YAML is malformed.
|
|
99
|
+
*
|
|
100
|
+
* @see https://geminicli.com/docs/extensions/reference/ — Gemini CLI hooks format
|
|
101
|
+
* @see /Users/mnorth/Development/ai-plugin-marketplace-template/src/build-hooks.ts
|
|
102
|
+
* `convertHookFile` (reference implementation, gemini branch)
|
|
103
|
+
*/
|
|
104
|
+
export declare function convertClaudeHooksYamlToGeminiJson(yamlContent: string): string;
|
|
105
|
+
export {};
|
|
106
|
+
//# sourceMappingURL=transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/targets/gemini/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAMnD;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAQ3E,CAAC;AAMF;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,cAAc,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAEpF;AAMD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,GAAG;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAgCA;AAMD;;;;GAIG;AACH,UAAU,eAAe;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,eAAe,EAAE,CAAC;IAC1B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,UAAU,eAAe;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC5C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,eAAe,CAmBhF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kCAAkC,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAI9E"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure mechanical transformations for the Gemini CLI target.
|
|
3
|
+
*
|
|
4
|
+
* Per spec §7.1, the transform layer is a pure function driven by a committed lookup table,
|
|
5
|
+
* bounded to a single target. No I/O is performed here.
|
|
6
|
+
*
|
|
7
|
+
* @see docs/specs/architecture.md §7 (mechanical transformations)
|
|
8
|
+
* @see docs/specs/architecture.md §12.4 (transform step + per-target folder layout)
|
|
9
|
+
* @see docs/specs/architecture.md §12.5 (internal module shape)
|
|
10
|
+
*/
|
|
11
|
+
import { parse as parseYaml } from 'yaml';
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Tool name lookup table
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
/**
|
|
16
|
+
* Committed lookup table mapping Claude Code tool names (PascalCase) to Gemini CLI
|
|
17
|
+
* tool names (snake_case). Per spec §7.1, the mechanical-transformation definition
|
|
18
|
+
* requires the table be committed in source.
|
|
19
|
+
*
|
|
20
|
+
* Exact port of CLAUDE_TO_GEMINI_TOOLS from the template's build-standalone.ts.
|
|
21
|
+
*/
|
|
22
|
+
export const CLAUDE_TO_GEMINI_TOOLS = {
|
|
23
|
+
Read: 'read_file',
|
|
24
|
+
Write: 'write_file',
|
|
25
|
+
Edit: 'replace',
|
|
26
|
+
Glob: 'glob',
|
|
27
|
+
Grep: 'search_file_content',
|
|
28
|
+
Bash: 'run_shell_command',
|
|
29
|
+
Agent: 'activate_skill',
|
|
30
|
+
};
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Single-tool translation
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
/**
|
|
35
|
+
* Translate a single Claude Code tool name to its Gemini CLI equivalent.
|
|
36
|
+
* Returns the Gemini tool name or `undefined` if there is no mapping.
|
|
37
|
+
*/
|
|
38
|
+
export function translateToolName(claudeToolName) {
|
|
39
|
+
return CLAUDE_TO_GEMINI_TOOLS[claudeToolName];
|
|
40
|
+
}
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
// Agent frontmatter rewriting
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
/**
|
|
45
|
+
* Rewrite the `tools:` list in an agent `.md` file's YAML frontmatter from Claude Code
|
|
46
|
+
* tool names to Gemini CLI equivalents. Tools with no mapping are dropped.
|
|
47
|
+
*
|
|
48
|
+
* Pure: takes a string, returns a string + metadata. No I/O.
|
|
49
|
+
*
|
|
50
|
+
* @param mdContent - Full content of the agent `.md` file.
|
|
51
|
+
* @returns Rewritten content and the list of dropped Claude tool names (for diagnostics).
|
|
52
|
+
*/
|
|
53
|
+
export function rewriteAgentFrontmatterTools(mdContent) {
|
|
54
|
+
const droppedTools = [];
|
|
55
|
+
// Regex matches YAML frontmatter with a tools: block (exact port from build-standalone.ts)
|
|
56
|
+
const rewritten = mdContent.replace(/^(---\n[\s\S]*?)(tools:\n)((?:\s+-\s+\S+\n)+)([\s\S]*?---)/m, (_match, before, toolsKey, toolsList, after) => {
|
|
57
|
+
const translatedLines = [];
|
|
58
|
+
for (const line of toolsList.split('\n')) {
|
|
59
|
+
const toolMatch = /^\s+-\s+(\S+)/.exec(line);
|
|
60
|
+
if (!toolMatch?.[1])
|
|
61
|
+
continue;
|
|
62
|
+
const claudeTool = toolMatch[1];
|
|
63
|
+
const geminiTool = CLAUDE_TO_GEMINI_TOOLS[claudeTool];
|
|
64
|
+
if (geminiTool) {
|
|
65
|
+
translatedLines.push(` - ${geminiTool}`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
droppedTools.push(claudeTool);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (translatedLines.length === 0) {
|
|
72
|
+
return `${before}tools: []\n${after}`;
|
|
73
|
+
}
|
|
74
|
+
return `${before}${toolsKey}${translatedLines.join('\n')}\n${after}`;
|
|
75
|
+
});
|
|
76
|
+
return { content: rewritten, droppedTools };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Deep-clone a parsed hooks object and translate `matcher` tool-name strings from
|
|
80
|
+
* Claude Code PascalCase names to Gemini CLI snake_case equivalents via
|
|
81
|
+
* {@link CLAUDE_TO_GEMINI_TOOLS}.
|
|
82
|
+
*
|
|
83
|
+
* Matchers that have no entry in the table (e.g. glob patterns, non-tool identifiers)
|
|
84
|
+
* are preserved unchanged — exact port of `translateHooksForGemini` in `build-hooks.ts`.
|
|
85
|
+
*
|
|
86
|
+
* Pure: no I/O, no side-effects. The input object is never mutated.
|
|
87
|
+
*
|
|
88
|
+
* @param source - Parsed hooks object (as returned by the `yaml` package's `parse`).
|
|
89
|
+
* @returns A new hooks object with matcher strings translated for Gemini CLI.
|
|
90
|
+
*
|
|
91
|
+
* @see https://geminicli.com/docs/extensions/reference/ — Gemini CLI hooks format
|
|
92
|
+
* @see /Users/mnorth/Development/ai-plugin-marketplace-template/src/build-hooks.ts
|
|
93
|
+
* `translateHooksForGemini` (reference implementation)
|
|
94
|
+
*/
|
|
95
|
+
export function translateHooksForGemini(source) {
|
|
96
|
+
const cloned = JSON.parse(JSON.stringify(source));
|
|
97
|
+
const { hooks } = cloned;
|
|
98
|
+
if (!hooks)
|
|
99
|
+
return cloned;
|
|
100
|
+
for (const event of Object.keys(hooks)) {
|
|
101
|
+
const matchers = hooks[event];
|
|
102
|
+
if (!Array.isArray(matchers))
|
|
103
|
+
continue;
|
|
104
|
+
for (const m of matchers) {
|
|
105
|
+
if (typeof m.matcher === 'string') {
|
|
106
|
+
const translated = CLAUDE_TO_GEMINI_TOOLS[m.matcher];
|
|
107
|
+
if (translated !== undefined) {
|
|
108
|
+
m.matcher = translated;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return cloned;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* One-shot conversion: parse a `hooks/claude.yaml` string, translate all tool-name
|
|
117
|
+
* matchers for Gemini CLI, and serialize as pretty-printed JSON.
|
|
118
|
+
*
|
|
119
|
+
* Output format: 2-space indent, trailing newline — byte-identical to the output of
|
|
120
|
+
* `convertHookFile(hooksDir, yamlFile, "gemini")` in the template's `build-hooks.ts`.
|
|
121
|
+
*
|
|
122
|
+
* Pure: no I/O. Throws if the YAML is malformed.
|
|
123
|
+
*
|
|
124
|
+
* @param yamlContent - Raw YAML string (contents of `hooks/claude.yaml` or `.yml`).
|
|
125
|
+
* @returns Pretty-printed JSON string with trailing newline.
|
|
126
|
+
* @throws {Error} If the YAML is malformed.
|
|
127
|
+
*
|
|
128
|
+
* @see https://geminicli.com/docs/extensions/reference/ — Gemini CLI hooks format
|
|
129
|
+
* @see /Users/mnorth/Development/ai-plugin-marketplace-template/src/build-hooks.ts
|
|
130
|
+
* `convertHookFile` (reference implementation, gemini branch)
|
|
131
|
+
*/
|
|
132
|
+
export function convertClaudeHooksYamlToGeminiJson(yamlContent) {
|
|
133
|
+
const parsed = parseYaml(yamlContent);
|
|
134
|
+
const translated = translateHooksForGemini(parsed);
|
|
135
|
+
return JSON.stringify(translated, null, 2) + '\n';
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../src/targets/gemini/transform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-target validators for the Gemini CLI target.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities per §13 Phase A:
|
|
5
|
+
* 1. Agent tool-name translation warnings — soft `schema-invalid` findings for
|
|
6
|
+
* Claude tool names that have no Gemini equivalent.
|
|
7
|
+
* 2. gemini-extension.json schema validation — hard `schema-invalid` finding if
|
|
8
|
+
* the file exists but fails Zod parse.
|
|
9
|
+
*
|
|
10
|
+
* What is NOT validated here:
|
|
11
|
+
* - Envelope adherence (cross-target concern).
|
|
12
|
+
* - Shared agents/ frontmatter shape (Claude validator owns that).
|
|
13
|
+
* - dist/gemini/ freshness (cross-target freshness check).
|
|
14
|
+
*
|
|
15
|
+
* @see docs/specs/architecture.md §10 (validation contract)
|
|
16
|
+
* @see docs/specs/architecture.md §8.1 (Finding types)
|
|
17
|
+
*/
|
|
18
|
+
import type { Finding } from '../../pipeline/types.js';
|
|
19
|
+
/**
|
|
20
|
+
* Run Gemini-specific validators against a plugin directory.
|
|
21
|
+
*
|
|
22
|
+
* `pluginDir` is the absolute path to a `plugins/<name>/` directory.
|
|
23
|
+
* All findings use `plugin: path.basename(pluginDir)`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function validateGeminiPlugin(pluginDir: string): Finding[];
|
|
26
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../../src/targets/gemini/validate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AA6HvD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE,CAMjE"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-target validators for the Gemini CLI target.
|
|
3
|
+
*
|
|
4
|
+
* Responsibilities per §13 Phase A:
|
|
5
|
+
* 1. Agent tool-name translation warnings — soft `schema-invalid` findings for
|
|
6
|
+
* Claude tool names that have no Gemini equivalent.
|
|
7
|
+
* 2. gemini-extension.json schema validation — hard `schema-invalid` finding if
|
|
8
|
+
* the file exists but fails Zod parse.
|
|
9
|
+
*
|
|
10
|
+
* What is NOT validated here:
|
|
11
|
+
* - Envelope adherence (cross-target concern).
|
|
12
|
+
* - Shared agents/ frontmatter shape (Claude validator owns that).
|
|
13
|
+
* - dist/gemini/ freshness (cross-target freshness check).
|
|
14
|
+
*
|
|
15
|
+
* @see docs/specs/architecture.md §10 (validation contract)
|
|
16
|
+
* @see docs/specs/architecture.md §8.1 (Finding types)
|
|
17
|
+
*/
|
|
18
|
+
import * as fs from 'node:fs';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import { parse as parseYaml } from 'yaml';
|
|
21
|
+
import { geminiExtensionManifestSchema } from './schemas.js';
|
|
22
|
+
import { CLAUDE_TO_GEMINI_TOOLS } from './transform.js';
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// YAML frontmatter parsing
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
/**
|
|
27
|
+
* Extract the YAML frontmatter block from a Markdown file's content.
|
|
28
|
+
* Returns the parsed object or `undefined` if no frontmatter is present.
|
|
29
|
+
*/
|
|
30
|
+
function parseFrontmatter(content) {
|
|
31
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---/m.exec(content);
|
|
32
|
+
if (!match?.[1])
|
|
33
|
+
return undefined;
|
|
34
|
+
const parsed = parseYaml(match[1]);
|
|
35
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
36
|
+
return undefined;
|
|
37
|
+
return parsed;
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Check: agent tool-name translation warnings
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
/**
|
|
43
|
+
* For each `.md` file directly under `plugins/<name>/agents/`, parse the YAML
|
|
44
|
+
* frontmatter `tools` array. Any Claude tool name that has no entry in
|
|
45
|
+
* `CLAUDE_TO_GEMINI_TOOLS` produces a soft `schema-invalid` finding indicating
|
|
46
|
+
* it will be dropped from the Gemini bundle.
|
|
47
|
+
*
|
|
48
|
+
* Per §10.2 soft findings do not flip `ValidationResult.passed`.
|
|
49
|
+
*/
|
|
50
|
+
function checkAgentToolTranslations(pluginDir, pluginName) {
|
|
51
|
+
const findings = [];
|
|
52
|
+
const agentsDir = path.join(pluginDir, 'agents');
|
|
53
|
+
if (!fs.existsSync(agentsDir))
|
|
54
|
+
return findings;
|
|
55
|
+
const entries = fs.readdirSync(agentsDir, { withFileTypes: true });
|
|
56
|
+
for (const entry of entries) {
|
|
57
|
+
if (!entry.isFile() || !entry.name.endsWith('.md'))
|
|
58
|
+
continue;
|
|
59
|
+
const agentPath = path.join(agentsDir, entry.name);
|
|
60
|
+
const content = fs.readFileSync(agentPath, 'utf-8');
|
|
61
|
+
const frontmatter = parseFrontmatter(content);
|
|
62
|
+
if (!frontmatter)
|
|
63
|
+
continue;
|
|
64
|
+
const tools = frontmatter['tools'];
|
|
65
|
+
if (!Array.isArray(tools))
|
|
66
|
+
continue;
|
|
67
|
+
const agentLabel = path.basename(entry.name, '.md');
|
|
68
|
+
for (const tool of tools) {
|
|
69
|
+
if (typeof tool !== 'string')
|
|
70
|
+
continue;
|
|
71
|
+
if (!(tool in CLAUDE_TO_GEMINI_TOOLS)) {
|
|
72
|
+
findings.push({
|
|
73
|
+
severity: 'soft',
|
|
74
|
+
code: 'schema-invalid',
|
|
75
|
+
plugin: pluginName,
|
|
76
|
+
message: `agent '${agentLabel}' uses Claude tool '${tool}' which has no Gemini equivalent — it will be dropped from the Gemini bundle`,
|
|
77
|
+
hint: `Remove '${tool}' from the agent's frontmatter tools list, or add a mapping in CLAUDE_TO_GEMINI_TOOLS if Gemini gains an equivalent tool.`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return findings;
|
|
83
|
+
}
|
|
84
|
+
// ---------------------------------------------------------------------------
|
|
85
|
+
// Check: gemini-extension.json schema validation
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
/**
|
|
88
|
+
* If `plugins/<name>/gemini-extension.json` exists, parse and validate it against
|
|
89
|
+
* `geminiExtensionManifestSchema`. A parse failure produces a hard `schema-invalid`
|
|
90
|
+
* finding. Absence of the file produces no finding (cross-target envelope-adherence
|
|
91
|
+
* handles the missing-file case).
|
|
92
|
+
*/
|
|
93
|
+
function checkGeminiExtensionJson(pluginDir, pluginName) {
|
|
94
|
+
const manifestPath = path.join(pluginDir, 'gemini-extension.json');
|
|
95
|
+
if (!fs.existsSync(manifestPath))
|
|
96
|
+
return [];
|
|
97
|
+
let raw;
|
|
98
|
+
try {
|
|
99
|
+
raw = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
103
|
+
return [
|
|
104
|
+
{
|
|
105
|
+
severity: 'hard',
|
|
106
|
+
code: 'schema-invalid',
|
|
107
|
+
plugin: pluginName,
|
|
108
|
+
message: `gemini-extension.json is not valid JSON: ${msg}`,
|
|
109
|
+
hint: 'Ensure gemini-extension.json is valid JSON.',
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
const result = geminiExtensionManifestSchema.safeParse(raw);
|
|
114
|
+
if (!result.success) {
|
|
115
|
+
const issues = result.error.issues
|
|
116
|
+
.map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`)
|
|
117
|
+
.join('; ');
|
|
118
|
+
return [
|
|
119
|
+
{
|
|
120
|
+
severity: 'hard',
|
|
121
|
+
code: 'schema-invalid',
|
|
122
|
+
plugin: pluginName,
|
|
123
|
+
message: `gemini-extension.json failed schema validation: ${issues}`,
|
|
124
|
+
hint: 'Ensure gemini-extension.json has a required string "name" field.',
|
|
125
|
+
},
|
|
126
|
+
];
|
|
127
|
+
}
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// Public API
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
/**
|
|
134
|
+
* Run Gemini-specific validators against a plugin directory.
|
|
135
|
+
*
|
|
136
|
+
* `pluginDir` is the absolute path to a `plugins/<name>/` directory.
|
|
137
|
+
* All findings use `plugin: path.basename(pluginDir)`.
|
|
138
|
+
*/
|
|
139
|
+
export function validateGeminiPlugin(pluginDir) {
|
|
140
|
+
const pluginName = path.basename(pluginDir);
|
|
141
|
+
return [
|
|
142
|
+
...checkAgentToolTranslations(pluginDir, pluginName),
|
|
143
|
+
...checkGeminiExtensionJson(pluginDir, pluginName),
|
|
144
|
+
];
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/targets/gemini/validate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kiro plugin bundler (I/O layer).
|
|
3
|
+
*
|
|
4
|
+
* Reads from a plugin source directory and writes a Kiro-compatible standalone
|
|
5
|
+
* export to a destination directory. Matches the output of `buildKiroStandalone`
|
|
6
|
+
* in build-standalone.ts of the template repository.
|
|
7
|
+
*
|
|
8
|
+
* @see docs/specs/architecture.md §12.4, §12.5
|
|
9
|
+
*/
|
|
10
|
+
/** Return type for `bundleKiroPlugin`. */
|
|
11
|
+
export interface BundleKiroPluginResult {
|
|
12
|
+
/** Relative paths of all files/directories emitted (same semantics as build-standalone.ts). */
|
|
13
|
+
emitted: string[];
|
|
14
|
+
/** Names of agents generated (without the .json extension). */
|
|
15
|
+
agentsGenerated: string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build the Kiro standalone export for a single plugin.
|
|
19
|
+
*
|
|
20
|
+
* Copies canonical files and directories from `pluginDir` to `destDir`, and
|
|
21
|
+
* generates `.kiro/agents/<name>.json` from any agent `.md` files found in
|
|
22
|
+
* `pluginDir/agents/`. Clears `destDir` before writing.
|
|
23
|
+
*
|
|
24
|
+
* Files copied (if present): `POWER.md`, `mcp.json`, `README.md`, `LICENSE`.
|
|
25
|
+
* Dirs copied (if present): `steering/`, `skills/`.
|
|
26
|
+
* Agent `.md` files are compiled to `.kiro/agents/<name>.json` via
|
|
27
|
+
* `buildKiroAgentConfig`, serialised with 2-space indent + trailing newline.
|
|
28
|
+
*
|
|
29
|
+
* Impure (I/O): reads from `pluginDir`, writes to `destDir`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function bundleKiroPlugin(pluginDir: string, destDir: string): BundleKiroPluginResult;
|
|
32
|
+
//# sourceMappingURL=bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../../../src/targets/kiro/bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2CH,0CAA0C;AAC1C,MAAM,WAAW,sBAAsB;IACrC,+FAA+F;IAC/F,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+DAA+D;IAC/D,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,sBAAsB,CAoD3F"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kiro plugin bundler (I/O layer).
|
|
3
|
+
*
|
|
4
|
+
* Reads from a plugin source directory and writes a Kiro-compatible standalone
|
|
5
|
+
* export to a destination directory. Matches the output of `buildKiroStandalone`
|
|
6
|
+
* in build-standalone.ts of the template repository.
|
|
7
|
+
*
|
|
8
|
+
* @see docs/specs/architecture.md §12.4, §12.5
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import * as path from 'node:path';
|
|
12
|
+
import { buildKiroAgentConfig } from './transform.js';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Internal helpers
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
function copyFile(src, dest) {
|
|
17
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
18
|
+
fs.copyFileSync(src, dest);
|
|
19
|
+
}
|
|
20
|
+
function copyDir(src, dest) {
|
|
21
|
+
if (!fs.existsSync(src))
|
|
22
|
+
return;
|
|
23
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
24
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
25
|
+
const srcPath = path.join(src, entry.name);
|
|
26
|
+
const destPath = path.join(dest, entry.name);
|
|
27
|
+
if (entry.isDirectory()) {
|
|
28
|
+
copyDir(srcPath, destPath);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
copyFile(srcPath, destPath);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function copyIfExists(src, dest) {
|
|
36
|
+
if (!fs.existsSync(src))
|
|
37
|
+
return false;
|
|
38
|
+
if (fs.statSync(src).isDirectory()) {
|
|
39
|
+
copyDir(src, dest);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
copyFile(src, dest);
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build the Kiro standalone export for a single plugin.
|
|
48
|
+
*
|
|
49
|
+
* Copies canonical files and directories from `pluginDir` to `destDir`, and
|
|
50
|
+
* generates `.kiro/agents/<name>.json` from any agent `.md` files found in
|
|
51
|
+
* `pluginDir/agents/`. Clears `destDir` before writing.
|
|
52
|
+
*
|
|
53
|
+
* Files copied (if present): `POWER.md`, `mcp.json`, `README.md`, `LICENSE`.
|
|
54
|
+
* Dirs copied (if present): `steering/`, `skills/`.
|
|
55
|
+
* Agent `.md` files are compiled to `.kiro/agents/<name>.json` via
|
|
56
|
+
* `buildKiroAgentConfig`, serialised with 2-space indent + trailing newline.
|
|
57
|
+
*
|
|
58
|
+
* Impure (I/O): reads from `pluginDir`, writes to `destDir`.
|
|
59
|
+
*/
|
|
60
|
+
export function bundleKiroPlugin(pluginDir, destDir) {
|
|
61
|
+
// Clear dest first, matching buildKiroStandalone's cleanDir behaviour.
|
|
62
|
+
if (fs.existsSync(destDir)) {
|
|
63
|
+
fs.rmSync(destDir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
const emitted = [];
|
|
66
|
+
const agentsGenerated = [];
|
|
67
|
+
// Canonical files
|
|
68
|
+
const files = ['POWER.md', 'mcp.json', 'README.md', 'LICENSE'];
|
|
69
|
+
for (const file of files) {
|
|
70
|
+
if (copyIfExists(path.join(pluginDir, file), path.join(destDir, file))) {
|
|
71
|
+
emitted.push(file);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Canonical directories
|
|
75
|
+
const dirs = ['steering', 'skills'];
|
|
76
|
+
for (const dir of dirs) {
|
|
77
|
+
if (copyIfExists(path.join(pluginDir, dir), path.join(destDir, dir))) {
|
|
78
|
+
emitted.push(`${dir}/`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// Generate .kiro/agents/<name>.json from agent .md files
|
|
82
|
+
const agentsSrc = path.join(pluginDir, 'agents');
|
|
83
|
+
if (fs.existsSync(agentsSrc)) {
|
|
84
|
+
const kiroAgentsDir = path.join(destDir, '.kiro', 'agents');
|
|
85
|
+
let anyGenerated = false;
|
|
86
|
+
for (const file of fs.readdirSync(agentsSrc)) {
|
|
87
|
+
if (!file.endsWith('.md'))
|
|
88
|
+
continue;
|
|
89
|
+
const mdContent = fs.readFileSync(path.join(agentsSrc, file), 'utf-8');
|
|
90
|
+
const fallbackName = file.replace(/\.md$/, '');
|
|
91
|
+
const config = buildKiroAgentConfig(mdContent, fallbackName);
|
|
92
|
+
if (!config)
|
|
93
|
+
continue;
|
|
94
|
+
fs.mkdirSync(kiroAgentsDir, { recursive: true });
|
|
95
|
+
const jsonName = file.replace(/\.md$/, '.json');
|
|
96
|
+
fs.writeFileSync(path.join(kiroAgentsDir, jsonName), JSON.stringify(config, null, 2) + '\n');
|
|
97
|
+
agentsGenerated.push(fallbackName);
|
|
98
|
+
anyGenerated = true;
|
|
99
|
+
}
|
|
100
|
+
if (anyGenerated) {
|
|
101
|
+
emitted.push('.kiro/agents/');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return { emitted, agentsGenerated };
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bundle.js","sourceRoot":"","sources":["../../../src/targets/kiro/bundle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scaffold templates for the Kiro target.
|
|
3
|
+
*
|
|
4
|
+
* `scaffoldKiroFiles` is a pure function returning the skeleton files this target contributes to
|
|
5
|
+
* a new plugin: `POWER.md`, a Markdown file whose YAML frontmatter is Kiro's plugin manifest.
|
|
6
|
+
* The frontmatter carries `schemaVersion: "0.1.0"` (§12.2). No generated-file sentinels — this is
|
|
7
|
+
* an author-authored skeleton file (§4.3).
|
|
8
|
+
*
|
|
9
|
+
* This module must not import from any sibling targets/<other>/ folder (§3.4).
|
|
10
|
+
*
|
|
11
|
+
* @see docs/specs/architecture.md §4 (plugin source layout)
|
|
12
|
+
* @see docs/specs/architecture.md §6.4 (compatibility-assist)
|
|
13
|
+
* @see docs/specs/architecture.md §12.2 (schemaVersion on every manifest)
|
|
14
|
+
* @see docs/specs/architecture.md §12.5 (per-target scaffold.ts)
|
|
15
|
+
*/
|
|
16
|
+
import { type ScaffoldedFile, type TargetScaffoldOptions } from '../scaffold-kit.js';
|
|
17
|
+
/**
|
|
18
|
+
* Produce the Kiro skeleton files for a plugin.
|
|
19
|
+
*
|
|
20
|
+
* The minimum required artifact (`TARGET_MIN_REQUIRED.kiro`) is `POWER.md`. Its frontmatter
|
|
21
|
+
* satisfies `kiroPowerMdFrontmatterSchema` (`name`, `description`, `version` all required).
|
|
22
|
+
*
|
|
23
|
+
* @param pluginName - Plugin identity; written verbatim as the frontmatter `name`.
|
|
24
|
+
* @param opts - Optional description and add-target placeholder behaviour.
|
|
25
|
+
* @returns Files contributed by this target, with paths relative to the plugin directory.
|
|
26
|
+
*/
|
|
27
|
+
export declare function scaffoldKiroFiles(pluginName: string, opts?: TargetScaffoldOptions): ScaffoldedFile[];
|
|
28
|
+
//# sourceMappingURL=scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../src/targets/kiro/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,qBAAqB,EAC3B,MAAM,oBAAoB,CAAC;AAK5B;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,qBAA0B,GAC/B,cAAc,EAAE,CA2BlB"}
|