@g3nomaly/skills 0.3.0 → 1.0.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 +95 -0
- package/dist/cli/adapter.d.ts +30 -0
- package/dist/cli/adapter.d.ts.map +1 -0
- package/dist/cli/adapter.js +86 -0
- package/dist/cli/adapter.js.map +1 -0
- package/dist/cli/commands/add.d.ts +17 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +108 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/hook.d.ts +6 -0
- package/dist/cli/commands/hook.d.ts.map +1 -0
- package/dist/cli/commands/hook.js +18 -0
- package/dist/cli/commands/hook.js.map +1 -0
- package/dist/cli/commands/init.d.ts +22 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +119 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/ls.d.ts +4 -0
- package/dist/cli/commands/ls.d.ts.map +1 -0
- package/dist/cli/commands/ls.js +8 -0
- package/dist/cli/commands/ls.js.map +1 -0
- package/dist/cli/commands/remove.d.ts +12 -0
- package/dist/cli/commands/remove.d.ts.map +1 -0
- package/dist/cli/commands/remove.js +60 -0
- package/dist/cli/commands/remove.js.map +1 -0
- package/dist/cli/commands/update.d.ts +13 -0
- package/dist/cli/commands/update.d.ts.map +1 -0
- package/dist/cli/commands/update.js +49 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +72 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/decisions/index.d.ts +6 -0
- package/dist/decisions/index.d.ts.map +1 -0
- package/dist/decisions/index.js +5 -0
- package/dist/decisions/index.js.map +1 -0
- package/dist/decisions/paths.d.ts +4 -0
- package/dist/decisions/paths.d.ts.map +1 -0
- package/dist/decisions/paths.js +12 -0
- package/dist/decisions/paths.js.map +1 -0
- package/dist/decisions/read.d.ts +18 -0
- package/dist/decisions/read.d.ts.map +1 -0
- package/dist/decisions/read.js +45 -0
- package/dist/decisions/read.js.map +1 -0
- package/dist/decisions/write.d.ts +20 -0
- package/dist/decisions/write.d.ts.map +1 -0
- package/dist/decisions/write.js +48 -0
- package/dist/decisions/write.js.map +1 -0
- package/dist/filetree/ensure.d.ts +7 -0
- package/dist/filetree/ensure.d.ts.map +1 -0
- package/dist/filetree/ensure.js +36 -0
- package/dist/filetree/ensure.js.map +1 -0
- package/dist/filetree/entries.d.ts +9 -0
- package/dist/filetree/entries.d.ts.map +1 -0
- package/dist/filetree/entries.js +49 -0
- package/dist/filetree/entries.js.map +1 -0
- package/dist/filetree/frontmatter.d.ts +16 -0
- package/dist/filetree/frontmatter.d.ts.map +1 -0
- package/dist/filetree/frontmatter.js +43 -0
- package/dist/filetree/frontmatter.js.map +1 -0
- package/dist/filetree/generate.d.ts +16 -0
- package/dist/filetree/generate.d.ts.map +1 -0
- package/dist/filetree/generate.js +62 -0
- package/dist/filetree/generate.js.map +1 -0
- package/dist/filetree/index.d.ts +17 -0
- package/dist/filetree/index.d.ts.map +1 -0
- package/dist/filetree/index.js +13 -0
- package/dist/filetree/index.js.map +1 -0
- package/dist/filetree/levels.d.ts +25 -0
- package/dist/filetree/levels.d.ts.map +1 -0
- package/dist/filetree/levels.js +45 -0
- package/dist/filetree/levels.js.map +1 -0
- package/dist/filetree/locate.d.ts +44 -0
- package/dist/filetree/locate.d.ts.map +1 -0
- package/dist/filetree/locate.js +76 -0
- package/dist/filetree/locate.js.map +1 -0
- package/dist/filetree/paths.d.ts +15 -0
- package/dist/filetree/paths.d.ts.map +1 -0
- package/dist/filetree/paths.js +38 -0
- package/dist/filetree/paths.js.map +1 -0
- package/dist/filetree/read.d.ts +23 -0
- package/dist/filetree/read.d.ts.map +1 -0
- package/dist/filetree/read.js +36 -0
- package/dist/filetree/read.js.map +1 -0
- package/dist/filetree/remove.d.ts +9 -0
- package/dist/filetree/remove.d.ts.map +1 -0
- package/dist/filetree/remove.js +17 -0
- package/dist/filetree/remove.js.map +1 -0
- package/dist/filetree/root.d.ts +9 -0
- package/dist/filetree/root.d.ts.map +1 -0
- package/dist/filetree/root.js +15 -0
- package/dist/filetree/root.js.map +1 -0
- package/dist/filetree/status.d.ts +21 -0
- package/dist/filetree/status.d.ts.map +1 -0
- package/dist/filetree/status.js +55 -0
- package/dist/filetree/status.js.map +1 -0
- package/dist/hooks/cli.d.ts +29 -0
- package/dist/hooks/cli.d.ts.map +1 -0
- package/dist/hooks/cli.js +65 -0
- package/dist/hooks/cli.js.map +1 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +3 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/grilling/.claude-plugin/plugin.json +7 -0
- package/dist/plugins/grilling/skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/dist/plugins/grilling/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/dist/plugins/grilling/skills/domain-modeling/SKILL.md +74 -0
- package/dist/plugins/grilling/skills/domain-modeling/agents/openai.yaml +3 -0
- package/dist/plugins/grilling/skills/grill-me/SKILL.md +7 -0
- package/dist/plugins/grilling/skills/grill-me/agents/openai.yaml +5 -0
- package/dist/plugins/grilling/skills/grill-with-docs/SKILL.md +7 -0
- package/dist/plugins/grilling/skills/grill-with-docs/agents/openai.yaml +5 -0
- package/dist/plugins/grilling/skills/grilling/SKILL.md +12 -0
- package/dist/plugins/grilling/skills/grilling/agents/openai.yaml +3 -0
- package/dist/plugins/speech/.claude-plugin/plugin.json +7 -0
- package/dist/plugins/speech/skills/emphasise/SKILL.md +49 -0
- package/dist/plugins/speech/skills/emphasise/agents/openai.yaml +5 -0
- package/dist/plugins/speech/skills/unslop/SKILL.md +80 -0
- package/dist/plugins/task-manager/.claude-plugin/plugin.json +11 -0
- package/dist/plugins/task-manager/hooks/hooks.json +19 -0
- package/dist/plugins/task-manager/skills/decisions/SKILL.md +39 -0
- package/dist/plugins/task-manager/skills/decisions/agents/openai.yaml +5 -0
- package/dist/plugins/task-manager/skills/decisions/references/usage.md +26 -0
- package/dist/plugins/task-manager/skills/task-manager/SKILL.md +99 -0
- package/dist/plugins/task-manager/skills/vocabulary/SKILL.md +42 -0
- package/dist/plugins/task-manager/skills/vocabulary/agents/openai.yaml +5 -0
- package/dist/plugins/task-manager/skills/vocabulary/references/usage.md +26 -0
- package/dist/plugins/using-hooks/.claude-plugin/plugin.json +7 -0
- package/dist/plugins/using-hooks/skills/hook-post-tool-use/SKILL.md +79 -0
- package/dist/plugins/using-hooks/skills/hook-post-tool-use/agents/openai.yaml +5 -0
- package/dist/plugins/using-hooks/skills/hook-pre-tool-use/SKILL.md +84 -0
- package/dist/plugins/using-hooks/skills/hook-pre-tool-use/agents/openai.yaml +5 -0
- package/dist/plugins/using-hooks/skills/hook-stop/SKILL.md +69 -0
- package/dist/plugins/using-hooks/skills/hook-stop/agents/openai.yaml +5 -0
- package/dist/plugins/using-hooks/skills/hook-user-prompt-submit/SKILL.md +64 -0
- package/dist/plugins/using-hooks/skills/hook-user-prompt-submit/agents/openai.yaml +5 -0
- package/dist/plugins/workflow/.claude-plugin/plugin.json +16 -0
- package/dist/plugins/workflow/agents/reviewer.md +9 -0
- package/dist/plugins/workflow/skills/execute/SKILL.md +21 -0
- package/dist/plugins/workflow/skills/execute/agents/openai.yaml +5 -0
- package/dist/plugins/workflow/skills/orchestrator/SKILL.md +27 -0
- package/dist/plugins/workflow/skills/orchestrator/agents/openai.yaml +5 -0
- package/dist/plugins/workflow/skills/plan/SKILL.md +18 -0
- package/dist/plugins/workflow/skills/plan/agents/openai.yaml +5 -0
- package/dist/plugins/workflow/skills/plan/references/task-frontmatter.md +33 -0
- package/dist/plugins/workflow/skills/review/SKILL.md +25 -0
- package/dist/plugins/workflow/skills/review/agents/openai.yaml +5 -0
- package/dist/plugins/workflow/skills/run/SKILL.md +33 -0
- package/dist/plugins/workflow/skills/run/agents/openai.yaml +5 -0
- package/dist/plugins/workflow/skills/run/references/sub-agents.md +46 -0
- package/dist/plugins/workflow/skills/sync/SKILL.md +18 -0
- package/dist/plugins/workflow/skills/sync/agents/openai.yaml +5 -0
- package/dist/plugins/workflow/skills/worktree/SKILL.md +38 -0
- package/dist/plugins/workflow/skills/worktree/agents/openai.yaml +5 -0
- package/dist/plugins/workflow/skills/worktree/references/git-commands.md +27 -0
- package/dist/plugins/writing/.claude-plugin/plugin.json +7 -0
- package/dist/plugins/writing/skills/writing-great-hooks/SKILL.md +192 -0
- package/dist/plugins/writing/skills/writing-great-hooks/agents/openai.yaml +5 -0
- package/dist/plugins/writing/skills/writing-great-skills/GLOSSARY.md +201 -0
- package/dist/plugins/writing/skills/writing-great-skills/SKILL.md +92 -0
- package/dist/plugins/writing/skills/writing-great-skills/agents/openai.yaml +5 -0
- package/dist/plugins/writing/skills/writing-great-tasks/SKILL.md +136 -0
- package/dist/plugins/writing/skills/writing-great-tasks/agents/openai.yaml +5 -0
- package/dist/plugins/writing/skills/writing-great-tasks/templates/template_task.md +108 -0
- package/dist/registry/index.d.ts +5 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +6 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/loadPackageRegistry.d.ts +14 -0
- package/dist/registry/loadPackageRegistry.d.ts.map +1 -0
- package/dist/registry/loadPackageRegistry.js +59 -0
- package/dist/registry/loadPackageRegistry.js.map +1 -0
- package/dist/registry/readSkillDir.d.ts +12 -0
- package/dist/registry/readSkillDir.d.ts.map +1 -0
- package/dist/registry/readSkillDir.js +59 -0
- package/dist/registry/readSkillDir.js.map +1 -0
- package/dist/registry/types.d.ts +53 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +35 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/registry/userManifest.d.ts +7 -0
- package/dist/registry/userManifest.d.ts.map +1 -0
- package/dist/registry/userManifest.js +21 -0
- package/dist/registry/userManifest.js.map +1 -0
- package/dist/remote/fetch.d.ts +16 -0
- package/dist/remote/fetch.d.ts.map +1 -0
- package/dist/remote/fetch.js +41 -0
- package/dist/remote/fetch.js.map +1 -0
- package/dist/remote/index.d.ts +7 -0
- package/dist/remote/index.d.ts.map +1 -0
- package/dist/remote/index.js +5 -0
- package/dist/remote/index.js.map +1 -0
- package/dist/remote/manifest.d.ts +23 -0
- package/dist/remote/manifest.d.ts.map +1 -0
- package/dist/remote/manifest.js +116 -0
- package/dist/remote/manifest.js.map +1 -0
- package/dist/remote/registry.d.ts +18 -0
- package/dist/remote/registry.d.ts.map +1 -0
- package/dist/remote/registry.js +58 -0
- package/dist/remote/registry.js.map +1 -0
- package/dist/schemas/config.d.ts +3 -0
- package/dist/schemas/config.d.ts.map +1 -0
- package/dist/schemas/config.js +3 -0
- package/dist/schemas/config.js.map +1 -0
- package/dist/schemas/decision.d.ts +43 -0
- package/dist/schemas/decision.d.ts.map +1 -0
- package/dist/schemas/decision.js +24 -0
- package/dist/schemas/decision.js.map +1 -0
- package/dist/schemas/index.d.ts +17 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +10 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/phase.d.ts +46 -0
- package/dist/schemas/phase.d.ts.map +1 -0
- package/dist/schemas/phase.js +16 -0
- package/dist/schemas/phase.js.map +1 -0
- package/dist/schemas/plan.d.ts +44 -0
- package/dist/schemas/plan.d.ts.map +1 -0
- package/dist/schemas/plan.js +15 -0
- package/dist/schemas/plan.js.map +1 -0
- package/dist/schemas/primitives.d.ts +38 -0
- package/dist/schemas/primitives.d.ts.map +1 -0
- package/dist/schemas/primitives.js +33 -0
- package/dist/schemas/primitives.js.map +1 -0
- package/dist/schemas/task.d.ts +70 -0
- package/dist/schemas/task.d.ts.map +1 -0
- package/dist/schemas/task.js +19 -0
- package/dist/schemas/task.js.map +1 -0
- package/dist/schemas/term.d.ts +17 -0
- package/dist/schemas/term.d.ts.map +1 -0
- package/dist/schemas/term.js +22 -0
- package/dist/schemas/term.js.map +1 -0
- package/dist/schemas/validation.d.ts +24 -0
- package/dist/schemas/validation.d.ts.map +1 -0
- package/dist/schemas/validation.js +39 -0
- package/dist/schemas/validation.js.map +1 -0
- package/dist/task-manager/hooks/add-decision.d.ts +2 -0
- package/dist/task-manager/hooks/add-decision.d.ts.map +1 -0
- package/dist/task-manager/hooks/add-decision.js +19 -0
- package/dist/task-manager/hooks/add-decision.js.map +1 -0
- package/dist/task-manager/hooks/cleanup.d.ts +2 -0
- package/dist/task-manager/hooks/cleanup.d.ts.map +1 -0
- package/dist/task-manager/hooks/cleanup.js +27 -0
- package/dist/task-manager/hooks/cleanup.js.map +1 -0
- package/dist/task-manager/hooks/get-decision.d.ts +2 -0
- package/dist/task-manager/hooks/get-decision.d.ts.map +1 -0
- package/dist/task-manager/hooks/get-decision.js +11 -0
- package/dist/task-manager/hooks/get-decision.js.map +1 -0
- package/dist/task-manager/hooks/get-entry.d.ts +2 -0
- package/dist/task-manager/hooks/get-entry.d.ts.map +1 -0
- package/dist/task-manager/hooks/get-entry.js +20 -0
- package/dist/task-manager/hooks/get-entry.js.map +1 -0
- package/dist/task-manager/hooks/get-term.d.ts +2 -0
- package/dist/task-manager/hooks/get-term.d.ts.map +1 -0
- package/dist/task-manager/hooks/get-term.js +13 -0
- package/dist/task-manager/hooks/get-term.js.map +1 -0
- package/dist/task-manager/hooks/guard-tree.d.ts +2 -0
- package/dist/task-manager/hooks/guard-tree.d.ts.map +1 -0
- package/dist/task-manager/hooks/guard-tree.js +63 -0
- package/dist/task-manager/hooks/guard-tree.js.map +1 -0
- package/dist/task-manager/hooks/index.d.ts +4 -0
- package/dist/task-manager/hooks/index.d.ts.map +1 -0
- package/dist/task-manager/hooks/index.js +32 -0
- package/dist/task-manager/hooks/index.js.map +1 -0
- package/dist/task-manager/hooks/list-decisions.d.ts +2 -0
- package/dist/task-manager/hooks/list-decisions.d.ts.map +1 -0
- package/dist/task-manager/hooks/list-decisions.js +20 -0
- package/dist/task-manager/hooks/list-decisions.js.map +1 -0
- package/dist/task-manager/hooks/list-entries.d.ts +2 -0
- package/dist/task-manager/hooks/list-entries.d.ts.map +1 -0
- package/dist/task-manager/hooks/list-entries.js +19 -0
- package/dist/task-manager/hooks/list-entries.js.map +1 -0
- package/dist/task-manager/hooks/list-terms.d.ts +2 -0
- package/dist/task-manager/hooks/list-terms.d.ts.map +1 -0
- package/dist/task-manager/hooks/list-terms.js +8 -0
- package/dist/task-manager/hooks/list-terms.js.map +1 -0
- package/dist/task-manager/hooks/next-entry.d.ts +2 -0
- package/dist/task-manager/hooks/next-entry.d.ts.map +1 -0
- package/dist/task-manager/hooks/next-entry.js +23 -0
- package/dist/task-manager/hooks/next-entry.js.map +1 -0
- package/dist/task-manager/hooks/remove-term.d.ts +2 -0
- package/dist/task-manager/hooks/remove-term.d.ts.map +1 -0
- package/dist/task-manager/hooks/remove-term.js +15 -0
- package/dist/task-manager/hooks/remove-term.js.map +1 -0
- package/dist/task-manager/hooks/set-state.d.ts +2 -0
- package/dist/task-manager/hooks/set-state.d.ts.map +1 -0
- package/dist/task-manager/hooks/set-state.js +15 -0
- package/dist/task-manager/hooks/set-state.js.map +1 -0
- package/dist/task-manager/hooks/set-term.d.ts +2 -0
- package/dist/task-manager/hooks/set-term.d.ts.map +1 -0
- package/dist/task-manager/hooks/set-term.js +27 -0
- package/dist/task-manager/hooks/set-term.js.map +1 -0
- package/dist/task-manager/hooks/sync-tree.d.ts +2 -0
- package/dist/task-manager/hooks/sync-tree.d.ts.map +1 -0
- package/dist/task-manager/hooks/sync-tree.js +28 -0
- package/dist/task-manager/hooks/sync-tree.js.map +1 -0
- package/dist/task-manager/index.d.ts +2 -0
- package/dist/task-manager/index.d.ts.map +1 -0
- package/dist/task-manager/index.js +3 -0
- package/dist/task-manager/index.js.map +1 -0
- package/dist/vocabulary/file.d.ts +15 -0
- package/dist/vocabulary/file.d.ts.map +1 -0
- package/dist/vocabulary/file.js +80 -0
- package/dist/vocabulary/file.js.map +1 -0
- package/dist/vocabulary/index.d.ts +4 -0
- package/dist/vocabulary/index.d.ts.map +1 -0
- package/dist/vocabulary/index.js +4 -0
- package/dist/vocabulary/index.js.map +1 -0
- package/dist/vocabulary/match.d.ts +22 -0
- package/dist/vocabulary/match.d.ts.map +1 -0
- package/dist/vocabulary/match.js +31 -0
- package/dist/vocabulary/match.js.map +1 -0
- package/dist/workflow/gates.d.ts +24 -0
- package/dist/workflow/gates.d.ts.map +1 -0
- package/dist/workflow/gates.js +34 -0
- package/dist/workflow/gates.js.map +1 -0
- package/dist/workflow/hooks/advance-step.d.ts +2 -0
- package/dist/workflow/hooks/advance-step.d.ts.map +1 -0
- package/dist/workflow/hooks/advance-step.js +51 -0
- package/dist/workflow/hooks/advance-step.js.map +1 -0
- package/dist/workflow/hooks/current-step.d.ts +2 -0
- package/dist/workflow/hooks/current-step.d.ts.map +1 -0
- package/dist/workflow/hooks/current-step.js +24 -0
- package/dist/workflow/hooks/current-step.js.map +1 -0
- package/dist/workflow/hooks/index.d.ts +4 -0
- package/dist/workflow/hooks/index.d.ts.map +1 -0
- package/dist/workflow/hooks/index.js +10 -0
- package/dist/workflow/hooks/index.js.map +1 -0
- package/dist/workflow/hooks/ready-phases.d.ts +2 -0
- package/dist/workflow/hooks/ready-phases.d.ts.map +1 -0
- package/dist/workflow/hooks/ready-phases.js +15 -0
- package/dist/workflow/hooks/ready-phases.js.map +1 -0
- package/dist/workflow/index.d.ts +8 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +6 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/phase.d.ts +16 -0
- package/dist/workflow/phase.d.ts.map +1 -0
- package/dist/workflow/phase.js +22 -0
- package/dist/workflow/phase.js.map +1 -0
- package/dist/workflow/steps.d.ts +15 -0
- package/dist/workflow/steps.d.ts.map +1 -0
- package/dist/workflow/steps.js +32 -0
- package/dist/workflow/steps.js.map +1 -0
- package/package.json +62 -3
- package/README.md +0 -3
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// packages/skills/src/registry/loadPackageRegistry.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { createRegistryStore, register } from "@g3nomaly/core/registry";
|
|
6
|
+
import { readSkillDir } from "./readSkillDir";
|
|
7
|
+
const PLUGIN_MANIFEST = path.join(".claude-plugin", "plugin.json");
|
|
8
|
+
/** Folder inside every group that holds its skill directories. */
|
|
9
|
+
const SKILLS_DIR = "skills";
|
|
10
|
+
/** `plugins/` directory shipped beside this module, from `src/` and `dist/` alike. */
|
|
11
|
+
export function resolvePluginsRoot() {
|
|
12
|
+
return path.join(import.meta.dir, "..", "plugins");
|
|
13
|
+
}
|
|
14
|
+
const PluginManifestSchema = z.object({
|
|
15
|
+
name: z.string().min(1),
|
|
16
|
+
version: z.string().optional(),
|
|
17
|
+
skills: z.array(z.string().min(1)).default([]),
|
|
18
|
+
});
|
|
19
|
+
/** Group plugin roots: every direct child of `plugins/` holding a `plugin.json`. */
|
|
20
|
+
export function listGroups(pluginsRoot = resolvePluginsRoot()) {
|
|
21
|
+
return fs.readdirSync(pluginsRoot, { withFileTypes: true })
|
|
22
|
+
.filter((d) => d.isDirectory() && fs.existsSync(path.join(pluginsRoot, d.name, PLUGIN_MANIFEST)))
|
|
23
|
+
.map((d) => d.name)
|
|
24
|
+
.sort();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Scans every group plugin root under `plugins/` and hydrates a store keyed by
|
|
28
|
+
* skill directory name. Run fresh on each CLI invocation; no build step.
|
|
29
|
+
*/
|
|
30
|
+
export async function loadPackageRegistry(pluginsRoot = resolvePluginsRoot()) {
|
|
31
|
+
const store = createRegistryStore();
|
|
32
|
+
for (const group of listGroups(pluginsRoot)) {
|
|
33
|
+
const groupDir = path.join(pluginsRoot, group);
|
|
34
|
+
const manifest = PluginManifestSchema.parse(JSON.parse(fs.readFileSync(path.join(groupDir, PLUGIN_MANIFEST), "utf8")));
|
|
35
|
+
for (const skillRel of manifest.skills) {
|
|
36
|
+
if (path.dirname(path.normalize(skillRel)) !== SKILLS_DIR) {
|
|
37
|
+
throw new Error(`group "${group}" lists skill "${skillRel}", which is not directly under ${SKILLS_DIR}/`);
|
|
38
|
+
}
|
|
39
|
+
const [key, meta] = await readSkillDir(path.join(groupDir, skillRel), group, manifest.version);
|
|
40
|
+
if (store.store.state[key]) {
|
|
41
|
+
throw new Error(`skill "${key}" is defined by more than one group (${store.store.state[key].group}, ${group})`);
|
|
42
|
+
}
|
|
43
|
+
register(store, key, meta);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (const [key, meta] of Object.entries(store.store.state)) {
|
|
47
|
+
for (const dep of meta.registryDependencies ?? []) {
|
|
48
|
+
if (!store.store.state[dep]) {
|
|
49
|
+
throw new Error(`skill "${key}" depends on "${dep}", which no group defines`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return store;
|
|
54
|
+
}
|
|
55
|
+
/** Absolute source path of a registry file; `filePath` is `<skill>/...`, sources live under `<group>/skills/`. */
|
|
56
|
+
export function resolveSkillSourcePath(group, filePath, pluginsRoot = resolvePluginsRoot()) {
|
|
57
|
+
return path.join(pluginsRoot, group, SKILLS_DIR, filePath);
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=loadPackageRegistry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadPackageRegistry.js","sourceRoot":"","sources":["../../src/registry/loadPackageRegistry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SkillMeta } from "./types";
|
|
2
|
+
export declare const SKILL_FILE = "SKILL.md";
|
|
3
|
+
/**
|
|
4
|
+
* Reads one skill directory into its registry entry; the key is the directory
|
|
5
|
+
* name and every file below it becomes a `files[]` entry at `<key>/<file>`.
|
|
6
|
+
* Used by `loadPackageRegistry` for shipped skills and by the remote registry
|
|
7
|
+
* for cloned repositories.
|
|
8
|
+
*
|
|
9
|
+
* @throws when the directory holds no SKILL.md or its frontmatter is invalid
|
|
10
|
+
*/
|
|
11
|
+
export declare function readSkillDir(skillDir: string, group: string, version?: string): Promise<[string, SkillMeta]>;
|
|
12
|
+
//# sourceMappingURL=readSkillDir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readSkillDir.d.ts","sourceRoot":"","sources":["../../src/registry/readSkillDir.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAA4B,SAAS,EAAE,MAAM,SAAS,CAAC;AAEnE,eAAO,MAAM,UAAU,aAAa,CAAC;AAsBrC;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CA0BlH"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// packages/skills/src/registry/readSkillDir.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { hashFile } from "@g3nomaly/core/hash";
|
|
6
|
+
import { readFrontmatter } from "../filetree/frontmatter";
|
|
7
|
+
export const SKILL_FILE = "SKILL.md";
|
|
8
|
+
const SkillFrontmatterSchema = z.object({
|
|
9
|
+
name: z.string().min(1),
|
|
10
|
+
description: z.string().optional(),
|
|
11
|
+
/** Registry keys (skill directory names) of skills this one references */
|
|
12
|
+
registryDependencies: z.array(z.string().min(1)).optional(),
|
|
13
|
+
});
|
|
14
|
+
function fileType(relativeToSkill) {
|
|
15
|
+
if (relativeToSkill === SKILL_FILE)
|
|
16
|
+
return "skill";
|
|
17
|
+
if (relativeToSkill.startsWith(`agents${path.sep}`))
|
|
18
|
+
return "agent";
|
|
19
|
+
return "reference";
|
|
20
|
+
}
|
|
21
|
+
function walk(dir, base = dir) {
|
|
22
|
+
return fs.readdirSync(dir, { withFileTypes: true }).flatMap((d) => {
|
|
23
|
+
const full = path.join(dir, d.name);
|
|
24
|
+
return d.isDirectory() ? walk(full, base) : [path.relative(base, full)];
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Reads one skill directory into its registry entry; the key is the directory
|
|
29
|
+
* name and every file below it becomes a `files[]` entry at `<key>/<file>`.
|
|
30
|
+
* Used by `loadPackageRegistry` for shipped skills and by the remote registry
|
|
31
|
+
* for cloned repositories.
|
|
32
|
+
*
|
|
33
|
+
* @throws when the directory holds no SKILL.md or its frontmatter is invalid
|
|
34
|
+
*/
|
|
35
|
+
export async function readSkillDir(skillDir, group, version) {
|
|
36
|
+
const skillMd = path.join(skillDir, SKILL_FILE);
|
|
37
|
+
if (!fs.existsSync(skillMd)) {
|
|
38
|
+
throw new Error(`${skillDir} holds no ${SKILL_FILE}`);
|
|
39
|
+
}
|
|
40
|
+
const key = path.basename(skillDir);
|
|
41
|
+
const frontmatter = SkillFrontmatterSchema.parse(await readFrontmatter(skillMd));
|
|
42
|
+
const files = [];
|
|
43
|
+
for (const rel of walk(skillDir).sort()) {
|
|
44
|
+
files.push({
|
|
45
|
+
path: path.join(key, rel),
|
|
46
|
+
type: fileType(rel),
|
|
47
|
+
hash: await hashFile(path.join(skillDir, rel)),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return [key, {
|
|
51
|
+
name: frontmatter.name,
|
|
52
|
+
description: frontmatter.description,
|
|
53
|
+
version,
|
|
54
|
+
group,
|
|
55
|
+
registryDependencies: frontmatter.registryDependencies,
|
|
56
|
+
files,
|
|
57
|
+
}];
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=readSkillDir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readSkillDir.js","sourceRoot":"","sources":["../../src/registry/readSkillDir.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAG1D,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;AAErC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,IAAI,EAAS,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,0EAA0E;IAC1E,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC5D,CAAC,CAAC;AAEH,SAAS,QAAQ,CAAC,eAAuB;IACvC,IAAI,eAAe,KAAK,UAAU;QAAE,OAAO,OAAO,CAAC;IACnD,IAAI,eAAe,CAAC,UAAU,CAAC,SAAS,IAAI,CAAC,GAAG,EAAE,CAAC;QAAE,OAAO,OAAO,CAAC;IACpE,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,IAAI,GAAW,GAAG;IAC3C,OAAO,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;QAChE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB,EAAE,KAAa,EAAE,OAAgB;IAClF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,GAAG,QAAQ,aAAa,UAAU,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,GAAG,GAAW,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5C,MAAM,WAAW,GAAG,sBAAsB,CAAC,KAAK,CAAC,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;IAEjF,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC;YACzB,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC;YACnB,IAAI,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,GAAG,EAAE;YACX,IAAI,EAAkB,WAAW,CAAC,IAAI;YACtC,WAAW,EAAW,WAAW,CAAC,WAAW;YAC7C,OAAO;YACP,KAAK;YACL,oBAAoB,EAAE,WAAW,CAAC,oBAAoB;YACtD,KAAK;SACN,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const SkillFileTypeSchema: z.ZodEnum<{
|
|
3
|
+
agent: "agent";
|
|
4
|
+
reference: "reference";
|
|
5
|
+
skill: "skill";
|
|
6
|
+
}>;
|
|
7
|
+
export type SkillFileType = z.infer<typeof SkillFileTypeSchema>;
|
|
8
|
+
export declare const SkillFileSchema: z.ZodObject<{
|
|
9
|
+
path: z.ZodString;
|
|
10
|
+
type: z.ZodEnum<{
|
|
11
|
+
agent: "agent";
|
|
12
|
+
reference: "reference";
|
|
13
|
+
skill: "skill";
|
|
14
|
+
}>;
|
|
15
|
+
hash: z.ZodOptional<z.ZodString>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
export type SkillFile = z.infer<typeof SkillFileSchema>;
|
|
18
|
+
/** Where a remote-installed skill came from; absent on skills shipped in the package. */
|
|
19
|
+
export declare const SkillSourceSchema: z.ZodObject<{
|
|
20
|
+
remote: z.ZodString;
|
|
21
|
+
commit: z.ZodString;
|
|
22
|
+
dir: z.ZodString;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
export type SkillSource = z.infer<typeof SkillSourceSchema>;
|
|
25
|
+
/**
|
|
26
|
+
* One installable skill. Built from a group's `plugin.json` plus the skill's
|
|
27
|
+
* `SKILL.md` frontmatter by `loadPackageRegistry`, and written per install
|
|
28
|
+
* into `skills.json` by the `add` and `update` commands.
|
|
29
|
+
*/
|
|
30
|
+
export declare const SkillMetaSchema: z.ZodObject<{
|
|
31
|
+
name: z.ZodString;
|
|
32
|
+
description: z.ZodOptional<z.ZodString>;
|
|
33
|
+
version: z.ZodOptional<z.ZodString>;
|
|
34
|
+
group: z.ZodString;
|
|
35
|
+
registryDependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
36
|
+
source: z.ZodOptional<z.ZodObject<{
|
|
37
|
+
remote: z.ZodString;
|
|
38
|
+
commit: z.ZodString;
|
|
39
|
+
dir: z.ZodString;
|
|
40
|
+
}, z.core.$strip>>;
|
|
41
|
+
files: z.ZodArray<z.ZodObject<{
|
|
42
|
+
path: z.ZodString;
|
|
43
|
+
type: z.ZodEnum<{
|
|
44
|
+
agent: "agent";
|
|
45
|
+
reference: "reference";
|
|
46
|
+
skill: "skill";
|
|
47
|
+
}>;
|
|
48
|
+
hash: z.ZodOptional<z.ZodString>;
|
|
49
|
+
}, z.core.$strip>>;
|
|
50
|
+
}, z.core.$strip>;
|
|
51
|
+
export type SkillMeta = z.infer<typeof SkillMetaSchema>;
|
|
52
|
+
export type SkillRegistry = Record<string, SkillMeta>;
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,mBAAmB;;;;EAA0C,CAAC;AAE3E,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,eAAe;;;;;;;;iBAK1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,yFAAyF;AACzF,eAAO,MAAM,iBAAiB;;;;iBAO5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;iBAU1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAO,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAC5D,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// packages/skills/src/registry/types.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export const SkillFileTypeSchema = z.enum(["skill", "agent", "reference"]);
|
|
4
|
+
export const SkillFileSchema = z.object({
|
|
5
|
+
/** Relative to the install directory, e.g. `emphasise/SKILL.md`; the source adds the group: `<group>/<path>` */
|
|
6
|
+
path: z.string().min(1),
|
|
7
|
+
type: SkillFileTypeSchema,
|
|
8
|
+
hash: z.string().optional(),
|
|
9
|
+
});
|
|
10
|
+
/** Where a remote-installed skill came from; absent on skills shipped in the package. */
|
|
11
|
+
export const SkillSourceSchema = z.object({
|
|
12
|
+
/** Git URL the skill was installed from */
|
|
13
|
+
remote: z.string().min(1),
|
|
14
|
+
/** Commit the clone resolved to at install time */
|
|
15
|
+
commit: z.string().min(1),
|
|
16
|
+
/** Repo-relative directory holding the skill directory, so `<dir>/<files[].path>` is the source file */
|
|
17
|
+
dir: z.string(),
|
|
18
|
+
});
|
|
19
|
+
/**
|
|
20
|
+
* One installable skill. Built from a group's `plugin.json` plus the skill's
|
|
21
|
+
* `SKILL.md` frontmatter by `loadPackageRegistry`, and written per install
|
|
22
|
+
* into `skills.json` by the `add` and `update` commands.
|
|
23
|
+
*/
|
|
24
|
+
export const SkillMetaSchema = z.object({
|
|
25
|
+
name: z.string().min(1),
|
|
26
|
+
description: z.string().optional(),
|
|
27
|
+
version: z.string().optional(),
|
|
28
|
+
/** Plugin root the skill ships in, e.g. `speech` */
|
|
29
|
+
group: z.string().min(1),
|
|
30
|
+
/** Registry keys (skill directory names) this skill needs installed alongside it */
|
|
31
|
+
registryDependencies: z.array(z.string().min(1)).optional(),
|
|
32
|
+
source: SkillSourceSchema.optional(),
|
|
33
|
+
files: z.array(SkillFileSchema).min(1),
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;AAI3E,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,gHAAgH;IAChH,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC;AAIH,yFAAyF;AACzF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,2CAA2C;IAC3C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,mDAAmD;IACnD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,wGAAwG;IACxG,GAAG,EAAK,CAAC,CAAC,MAAM,EAAE;CACnB,CAAC,CAAC;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,IAAI,EAAS,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,OAAO,EAAM,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,oDAAoD;IACpD,KAAK,EAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,oFAAoF;IACpF,oBAAoB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC3D,MAAM,EAAO,iBAAiB,CAAC,QAAQ,EAAE;IACzC,KAAK,EAAQ,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;CAC7C,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RegistryStore } from "@g3nomaly/core/registry";
|
|
2
|
+
/** `skills.json` sits beside the install directory: `.claude/skills` → `.claude/skills.json`. */
|
|
3
|
+
export declare function manifestPath(projectRoot: string, installDir: string): string;
|
|
4
|
+
/** Store bound to one target's `skills.json`, hydrated when the file exists. */
|
|
5
|
+
export declare function loadUserManifest(projectRoot: string, installDir: string): Promise<RegistryStore>;
|
|
6
|
+
export declare function saveUserManifest(store: RegistryStore): void;
|
|
7
|
+
//# sourceMappingURL=userManifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userManifest.d.ts","sourceRoot":"","sources":["../../src/registry/userManifest.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAI7D,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,gFAAgF;AAChF,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAItG;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAG3D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// packages/skills/src/registry/userManifest.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { createRegistryStore, load, flush, jsonHandler } from "@g3nomaly/core/registry";
|
|
5
|
+
const MANIFEST_FILE = "skills.json";
|
|
6
|
+
/** `skills.json` sits beside the install directory: `.claude/skills` → `.claude/skills.json`. */
|
|
7
|
+
export function manifestPath(projectRoot, installDir) {
|
|
8
|
+
return path.join(projectRoot, path.dirname(installDir), MANIFEST_FILE);
|
|
9
|
+
}
|
|
10
|
+
/** Store bound to one target's `skills.json`, hydrated when the file exists. */
|
|
11
|
+
export async function loadUserManifest(projectRoot, installDir) {
|
|
12
|
+
const store = createRegistryStore({ filePath: manifestPath(projectRoot, installDir), handler: jsonHandler });
|
|
13
|
+
await load(store);
|
|
14
|
+
return store;
|
|
15
|
+
}
|
|
16
|
+
export function saveUserManifest(store) {
|
|
17
|
+
if (store.filePath !== undefined)
|
|
18
|
+
fs.mkdirSync(path.dirname(store.filePath), { recursive: true });
|
|
19
|
+
flush(store);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=userManifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userManifest.js","sourceRoot":"","sources":["../../src/registry/userManifest.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGxF,MAAM,aAAa,GAAG,aAAa,CAAC;AAEpC,iGAAiG;AACjG,MAAM,UAAU,YAAY,CAAC,WAAmB,EAAE,UAAkB;IAClE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC,CAAC;AACzE,CAAC;AAED,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAmB,EAAE,UAAkB;IAC5E,MAAM,KAAK,GAAG,mBAAmB,CAAC,EAAE,QAAQ,EAAE,YAAY,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IAC7G,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC;IAClB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAoB;IACnD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClG,KAAK,CAAC,KAAK,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** One shallow clone of a remote repository, removed on `removeCheckout` and at process exit. */
|
|
2
|
+
export interface RemoteCheckout {
|
|
3
|
+
url: string;
|
|
4
|
+
/** Absolute checkout root */
|
|
5
|
+
dir: string;
|
|
6
|
+
commit: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Shallow-clones `url` into a temporary directory and resolves its HEAD commit.
|
|
10
|
+
* The directory is removed at process exit even when a command bails out early.
|
|
11
|
+
*
|
|
12
|
+
* @throws when the URL is not a git remote or the clone fails
|
|
13
|
+
*/
|
|
14
|
+
export declare function cloneRemote(url: string): Promise<RemoteCheckout>;
|
|
15
|
+
export declare function removeCheckout(checkout: RemoteCheckout): void;
|
|
16
|
+
//# sourceMappingURL=fetch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/remote/fetch.ts"],"names":[],"mappings":"AAKA,iGAAiG;AACjG,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAK,MAAM,CAAC;IACf,6BAA6B;IAC7B,GAAG,EAAK,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAoBD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAWtE;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,cAAc,GAAG,IAAI,CAE7D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// packages/skills/src/remote/fetch.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
const REMOTE_URL = /^(https?:\/\/|ssh:\/\/|git:\/\/|git@)\S+$/;
|
|
6
|
+
async function git(args, cwd) {
|
|
7
|
+
const proc = Bun.spawn(["git", ...args], {
|
|
8
|
+
cwd,
|
|
9
|
+
stdout: "pipe",
|
|
10
|
+
stderr: "pipe",
|
|
11
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
|
|
12
|
+
});
|
|
13
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
14
|
+
new Response(proc.stdout).text(),
|
|
15
|
+
new Response(proc.stderr).text(),
|
|
16
|
+
proc.exited,
|
|
17
|
+
]);
|
|
18
|
+
if (exitCode !== 0)
|
|
19
|
+
throw new Error(stderr.trim() !== "" ? stderr.trim() : `git ${args[0]} failed`);
|
|
20
|
+
return stdout.trim();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Shallow-clones `url` into a temporary directory and resolves its HEAD commit.
|
|
24
|
+
* The directory is removed at process exit even when a command bails out early.
|
|
25
|
+
*
|
|
26
|
+
* @throws when the URL is not a git remote or the clone fails
|
|
27
|
+
*/
|
|
28
|
+
export async function cloneRemote(url) {
|
|
29
|
+
if (!REMOTE_URL.test(url)) {
|
|
30
|
+
throw new Error(`"${url}" is not a git URL (expected https://, ssh://, git:// or git@)`);
|
|
31
|
+
}
|
|
32
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "g3n-skills-remote-"));
|
|
33
|
+
process.once("exit", () => fs.rmSync(dir, { recursive: true, force: true }));
|
|
34
|
+
await git(["clone", "--depth", "1", "--quiet", "--", url, dir]);
|
|
35
|
+
const commit = await git(["rev-parse", "HEAD"], dir);
|
|
36
|
+
return { url, dir, commit };
|
|
37
|
+
}
|
|
38
|
+
export function removeCheckout(checkout) {
|
|
39
|
+
fs.rmSync(checkout.dir, { recursive: true, force: true });
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/remote/fetch.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAU7B,MAAM,UAAU,GAAG,2CAA2C,CAAC;AAE/D,KAAK,UAAU,GAAG,CAAC,IAAc,EAAE,GAAY;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,EAAE;QACvC,GAAG;QACH,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,MAAM;QACd,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,mBAAmB,EAAE,GAAG,EAAE;KAClD,CAAC,CAAC;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnD,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;QAChC,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;QAChC,IAAI,CAAC,MAAM;KACZ,CAAC,CAAC;IACH,IAAI,QAAQ,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpG,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,gEAAgE,CAAC,CAAC;IAC3F,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC;IACzE,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE7E,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAwB;IACrD,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { cloneRemote, removeCheckout } from "./fetch";
|
|
2
|
+
export type { RemoteCheckout } from "./fetch";
|
|
3
|
+
export { locateRemotePlugins } from "./manifest";
|
|
4
|
+
export type { RemotePlugin, RemotePluginScan } from "./manifest";
|
|
5
|
+
export { loadRemoteRegistry, remoteSkillSource } from "./registry";
|
|
6
|
+
export type { RemoteRegistry } from "./registry";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/remote/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACnE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/remote/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** One plugin found in a checked-out repository. */
|
|
2
|
+
export interface RemotePlugin {
|
|
3
|
+
name: string;
|
|
4
|
+
version?: string;
|
|
5
|
+
/** Absolute plugin root inside the checkout */
|
|
6
|
+
dir: string;
|
|
7
|
+
/** Absolute skill directories, each holding a SKILL.md */
|
|
8
|
+
skillDirs: string[];
|
|
9
|
+
}
|
|
10
|
+
export interface RemotePluginScan {
|
|
11
|
+
plugins: RemotePlugin[];
|
|
12
|
+
warnings: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Plugin roots and their skills declared by a repository's manifests. A root
|
|
16
|
+
* `marketplace.json` enumerates plugin directories; a root `plugin.json` makes
|
|
17
|
+
* the repository itself a plugin. Both `.claude-plugin` and `.cursor-plugin`
|
|
18
|
+
* layouts are read.
|
|
19
|
+
*
|
|
20
|
+
* @throws when the repository has neither manifest — plain skill folders are rejected
|
|
21
|
+
*/
|
|
22
|
+
export declare function locateRemotePlugins(repoRoot: string): RemotePluginScan;
|
|
23
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/remote/manifest.ts"],"names":[],"mappings":"AA2BA,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAM,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,GAAG,EAAO,MAAM,CAAC;IACjB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAG,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAoDD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAyCtE"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// packages/skills/src/remote/manifest.ts
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { SKILL_FILE } from "../registry/readSkillDir";
|
|
6
|
+
const MANIFEST_DIRS = [".claude-plugin", ".cursor-plugin"];
|
|
7
|
+
const MARKETPLACE_FILE = "marketplace.json";
|
|
8
|
+
const PLUGIN_FILE = "plugin.json";
|
|
9
|
+
const DEFAULT_SKILLS_DIR = "skills";
|
|
10
|
+
const MarketplaceSchema = z.object({
|
|
11
|
+
plugins: z.array(z.object({
|
|
12
|
+
name: z.string().min(1),
|
|
13
|
+
source: z.unknown(),
|
|
14
|
+
})).default([]),
|
|
15
|
+
});
|
|
16
|
+
const RemotePluginManifestSchema = z.object({
|
|
17
|
+
name: z.string().min(1).optional(),
|
|
18
|
+
version: z.string().optional(),
|
|
19
|
+
/** A list of skill directories, or one directory to scan for them */
|
|
20
|
+
skills: z.union([z.string().min(1), z.array(z.string().min(1))]).optional(),
|
|
21
|
+
});
|
|
22
|
+
/** First existing `.claude-plugin`/`.cursor-plugin` file of the given name under `dir`. */
|
|
23
|
+
function manifestFile(dir, file) {
|
|
24
|
+
for (const manifestDir of MANIFEST_DIRS) {
|
|
25
|
+
const candidate = path.join(dir, manifestDir, file);
|
|
26
|
+
if (fs.existsSync(candidate))
|
|
27
|
+
return candidate;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
function readJson(file) {
|
|
32
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
33
|
+
}
|
|
34
|
+
/** Resolves `rel` against `base`, rejecting paths that escape the checkout at `root`. */
|
|
35
|
+
function resolveInside(root, base, rel) {
|
|
36
|
+
const resolved = path.resolve(base, rel);
|
|
37
|
+
if (resolved !== root && !resolved.startsWith(root + path.sep)) {
|
|
38
|
+
throw new Error(`manifest path "${rel}" points outside the repository`);
|
|
39
|
+
}
|
|
40
|
+
return resolved;
|
|
41
|
+
}
|
|
42
|
+
/** Directories under `dir` holding a SKILL.md; a match is not descended into further. */
|
|
43
|
+
function scanSkillDirs(dir) {
|
|
44
|
+
if (!fs.existsSync(dir))
|
|
45
|
+
return [];
|
|
46
|
+
const found = [];
|
|
47
|
+
const visit = (current) => {
|
|
48
|
+
if (fs.existsSync(path.join(current, SKILL_FILE))) {
|
|
49
|
+
found.push(current);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
for (const d of fs.readdirSync(current, { withFileTypes: true })) {
|
|
53
|
+
if (d.isDirectory() && !d.name.startsWith(".") && d.name !== "node_modules")
|
|
54
|
+
visit(path.join(current, d.name));
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
visit(dir);
|
|
58
|
+
return found.sort();
|
|
59
|
+
}
|
|
60
|
+
/** A plugin's skill directories: the listed ones, or a scan of its skills directory. */
|
|
61
|
+
function pluginSkillDirs(pluginDir, repoRoot, manifest) {
|
|
62
|
+
if (Array.isArray(manifest.skills)) {
|
|
63
|
+
return manifest.skills.map((rel) => resolveInside(repoRoot, pluginDir, rel));
|
|
64
|
+
}
|
|
65
|
+
if (typeof manifest.skills === "string") {
|
|
66
|
+
return scanSkillDirs(resolveInside(repoRoot, pluginDir, manifest.skills));
|
|
67
|
+
}
|
|
68
|
+
return scanSkillDirs(path.join(pluginDir, DEFAULT_SKILLS_DIR));
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Plugin roots and their skills declared by a repository's manifests. A root
|
|
72
|
+
* `marketplace.json` enumerates plugin directories; a root `plugin.json` makes
|
|
73
|
+
* the repository itself a plugin. Both `.claude-plugin` and `.cursor-plugin`
|
|
74
|
+
* layouts are read.
|
|
75
|
+
*
|
|
76
|
+
* @throws when the repository has neither manifest — plain skill folders are rejected
|
|
77
|
+
*/
|
|
78
|
+
export function locateRemotePlugins(repoRoot) {
|
|
79
|
+
const warnings = [];
|
|
80
|
+
const pluginDirs = new Map();
|
|
81
|
+
const marketplacePath = manifestFile(repoRoot, MARKETPLACE_FILE);
|
|
82
|
+
if (marketplacePath !== null) {
|
|
83
|
+
const marketplace = MarketplaceSchema.parse(readJson(marketplacePath));
|
|
84
|
+
for (const plugin of marketplace.plugins) {
|
|
85
|
+
if (typeof plugin.source !== "string") {
|
|
86
|
+
warnings.push(`${plugin.name} — marketplace source is not a local path, skipped`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
pluginDirs.set(resolveInside(repoRoot, repoRoot, plugin.source), plugin.name);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (manifestFile(repoRoot, PLUGIN_FILE) !== null && !pluginDirs.has(path.resolve(repoRoot))) {
|
|
93
|
+
pluginDirs.set(path.resolve(repoRoot), undefined);
|
|
94
|
+
}
|
|
95
|
+
if (pluginDirs.size === 0) {
|
|
96
|
+
throw new Error("no .claude-plugin or .cursor-plugin manifest found — the repository is not a plugin or marketplace");
|
|
97
|
+
}
|
|
98
|
+
const plugins = [];
|
|
99
|
+
const withoutSkills = [];
|
|
100
|
+
for (const [dir, marketplaceName] of pluginDirs) {
|
|
101
|
+
const manifestPath = manifestFile(dir, PLUGIN_FILE);
|
|
102
|
+
const manifest = manifestPath === null ? {} : RemotePluginManifestSchema.parse(readJson(manifestPath));
|
|
103
|
+
const name = manifest.name ?? marketplaceName ?? path.basename(dir);
|
|
104
|
+
const skillDirs = pluginSkillDirs(dir, repoRoot, manifest);
|
|
105
|
+
if (skillDirs.length === 0) {
|
|
106
|
+
withoutSkills.push(name);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
plugins.push({ name, version: manifest.version, dir, skillDirs });
|
|
110
|
+
}
|
|
111
|
+
if (withoutSkills.length > 0) {
|
|
112
|
+
warnings.push(`${withoutSkills.length} plugin(s) without skills skipped: ${withoutSkills.join(", ")}`);
|
|
113
|
+
}
|
|
114
|
+
return { plugins, warnings };
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/remote/manifest.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,MAAM,aAAa,GAAO,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;AAC/D,MAAM,gBAAgB,GAAI,kBAAkB,CAAC;AAC7C,MAAM,WAAW,GAAS,aAAa,CAAC;AACxC,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAEpC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACxB,IAAI,EAAI,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACzB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE;KACpB,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAChB,CAAC,CAAC;AAEH,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,IAAI,EAAK,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACrC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,qEAAqE;IACrE,MAAM,EAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC7E,CAAC,CAAC;AAmBH,2FAA2F;AAC3F,SAAS,YAAY,CAAC,GAAW,EAAE,IAAY;IAC7C,KAAK,MAAM,WAAW,IAAI,aAAa,EAAE,CAAC;QACxC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;QACpD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;IACjD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAY,CAAC;AAC9D,CAAC;AAED,yFAAyF;AACzF,SAAS,aAAa,CAAC,IAAY,EAAE,IAAY,EAAE,GAAW;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzC,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,iCAAiC,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,yFAAyF;AACzF,SAAS,aAAa,CAAC,GAAW;IAChC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,KAAK,GAAG,CAAC,OAAe,EAAQ,EAAE;QACtC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;YAClD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpB,OAAO;QACT,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjH,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,GAAG,CAAC,CAAC;IACX,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,wFAAwF;AACxF,SAAS,eAAe,CAAC,SAAiB,EAAE,QAAgB,EAAE,QAA8B;IAC1F,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACnC,OAAO,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,IAAI,GAAG,EAA8B,CAAC;IAEzD,MAAM,eAAe,GAAG,YAAY,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IACjE,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC;QACvE,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACzC,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;gBACtC,QAAQ,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,oDAAoD,CAAC,CAAC;gBAClF,SAAS;YACX,CAAC;YACD,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IACD,IAAI,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAC5F,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;IACpD,CAAC;IACD,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,oGAAoG,CAAC,CAAC;IACxH,CAAC;IAED,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,MAAM,aAAa,GAAa,EAAE,CAAC;IACnC,KAAK,MAAM,CAAC,GAAG,EAAE,eAAe,CAAC,IAAI,UAAU,EAAE,CAAC;QAChD,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAO,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,0BAA0B,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;QAC3G,MAAM,IAAI,GAAW,QAAQ,CAAC,IAAI,IAAI,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAE5E,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzB,SAAS;QACX,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IACpE,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,QAAQ,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,MAAM,sCAAsC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzG,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { EntrySource } from "@g3nomaly/core/cli";
|
|
2
|
+
import type { SkillRegistry } from "../registry/types";
|
|
3
|
+
import type { RemoteCheckout } from "./fetch";
|
|
4
|
+
export interface RemoteRegistry {
|
|
5
|
+
registry: SkillRegistry;
|
|
6
|
+
warnings: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Hydrates a registry from a checkout's plugin manifests, keyed by skill
|
|
10
|
+
* directory name with the plugin name as group. Each entry records its
|
|
11
|
+
* `source` so the install can resolve files inside the checkout and the user
|
|
12
|
+
* manifest keeps the provenance. `registryDependencies` are dropped with a
|
|
13
|
+
* warning — a remote repository cannot resolve against the package registry.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadRemoteRegistry(checkout: RemoteCheckout): Promise<RemoteRegistry>;
|
|
16
|
+
/** Resolves a remote entry's files inside its checkout via the `source` recorded on it. */
|
|
17
|
+
export declare function remoteSkillSource(checkout: RemoteCheckout): EntrySource;
|
|
18
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/remote/registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAmC1F;AAED,2FAA2F;AAC3F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,cAAc,GAAG,WAAW,CAMvE"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// packages/skills/src/remote/registry.ts
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { copySource } from "@g3nomaly/core/installer";
|
|
4
|
+
import { readSkillDir } from "../registry/readSkillDir";
|
|
5
|
+
import { SkillMetaSchema } from "../registry/types";
|
|
6
|
+
import { locateRemotePlugins } from "./manifest";
|
|
7
|
+
/**
|
|
8
|
+
* Hydrates a registry from a checkout's plugin manifests, keyed by skill
|
|
9
|
+
* directory name with the plugin name as group. Each entry records its
|
|
10
|
+
* `source` so the install can resolve files inside the checkout and the user
|
|
11
|
+
* manifest keeps the provenance. `registryDependencies` are dropped with a
|
|
12
|
+
* warning — a remote repository cannot resolve against the package registry.
|
|
13
|
+
*/
|
|
14
|
+
export async function loadRemoteRegistry(checkout) {
|
|
15
|
+
const { plugins, warnings } = locateRemotePlugins(checkout.dir);
|
|
16
|
+
const registry = {};
|
|
17
|
+
for (const plugin of plugins) {
|
|
18
|
+
for (const skillDir of plugin.skillDirs) {
|
|
19
|
+
let entry;
|
|
20
|
+
try {
|
|
21
|
+
entry = await readSkillDir(skillDir, plugin.name, plugin.version);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
warnings.push(`skipped ${path.relative(checkout.dir, skillDir)} — ${error instanceof Error ? error.message : String(error)}`);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const [key, meta] = entry;
|
|
28
|
+
const existing = registry[key];
|
|
29
|
+
if (existing !== undefined) {
|
|
30
|
+
warnings.push(`skill "${key}" is defined by both ${existing.group} and ${plugin.name} — using the ${existing.group} one`);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const { registryDependencies, ...rest } = meta;
|
|
34
|
+
if (registryDependencies !== undefined) {
|
|
35
|
+
warnings.push(`${key} declares dependencies (${registryDependencies.join(", ")}) — they are not installed from a remote`);
|
|
36
|
+
}
|
|
37
|
+
registry[key] = {
|
|
38
|
+
...rest,
|
|
39
|
+
source: {
|
|
40
|
+
remote: checkout.url,
|
|
41
|
+
commit: checkout.commit,
|
|
42
|
+
dir: path.relative(checkout.dir, path.dirname(skillDir)),
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { registry, warnings };
|
|
48
|
+
}
|
|
49
|
+
/** Resolves a remote entry's files inside its checkout via the `source` recorded on it. */
|
|
50
|
+
export function remoteSkillSource(checkout) {
|
|
51
|
+
return (entry) => {
|
|
52
|
+
const { source } = SkillMetaSchema.pick({ source: true }).parse(entry);
|
|
53
|
+
if (source === undefined)
|
|
54
|
+
throw new Error(`entry "${entry.name}" carries no remote source`);
|
|
55
|
+
return copySource((filePath) => path.join(checkout.dir, source.dir, filePath));
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/remote/registry.ts"],"names":[],"mappings":"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"}
|