@hmanlab/hl-plugins 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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/commands/uninstall.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,148 @@
1
+ // update [plugin] -- re-copy files, bump dependencies, re-merge config.
2
+ // Does NOT touch auth (credentials are managed by the plugin's own CLI).
3
+ // Symmetric with install: same copy + config-merge logic.
4
+ import { copyFileSync, existsSync, mkdirSync, statSync } from "node:fs";
5
+ import { basename, dirname, join } from "node:path";
6
+ import { discoverPlugins, getPlugin } from "../lib/registry.js";
7
+ import { run } from "../lib/shell.js";
8
+ import { ui } from "../lib/ui.js";
9
+ import { opencodePluginDir, opencodeSkillDir, tilde } from "../lib/paths.js";
10
+ import { addBashPermission, addPluginToConfig } from "../lib/config.js";
11
+ /** Derive `npm update -g` from `npm install -g` if the contract omits `update`. */
12
+ function deriveUpdate(req) {
13
+ if (req.update)
14
+ return req.update;
15
+ return req.install.replace(/npm install/i, "npm update");
16
+ }
17
+ async function updateRequirement(req) {
18
+ const cmd = deriveUpdate(req);
19
+ const res = await run(cmd, { throwOnError: false });
20
+ if (res.code !== 0) {
21
+ throw new Error(`Update failed: ${cmd}\n ${(res.stderr || res.stdout).trim() || "(no output)"}`);
22
+ }
23
+ // Re-probe
24
+ const verify = await run(req.check, { throwOnError: false });
25
+ if (verify.code === 0) {
26
+ return firstNonEmptyLine(verify.stdout) || "updated";
27
+ }
28
+ return "update command ran, but probe still fails";
29
+ }
30
+ function firstNonEmptyLine(s) {
31
+ for (const line of s.split("\n")) {
32
+ const t = line.trim();
33
+ if (t)
34
+ return t;
35
+ }
36
+ return "";
37
+ }
38
+ async function copyPluginFiles(plugin) {
39
+ const copied = [];
40
+ if (plugin.contract.opencodePlugin) {
41
+ const src = join(plugin.packageDir, plugin.contract.opencodePlugin);
42
+ const dest = join(opencodePluginDir(), basename(plugin.contract.opencodePlugin));
43
+ if (!existsSync(src))
44
+ throw new Error(`Plugin source missing: ${src}`);
45
+ mkdirSync(dirname(dest), { recursive: true });
46
+ copyFileSync(src, dest);
47
+ copied.push(tilde(dest));
48
+ }
49
+ if (plugin.contract.opencodeSkill) {
50
+ const src = join(plugin.packageDir, plugin.contract.opencodeSkill);
51
+ if (!existsSync(src))
52
+ throw new Error(`Skill source missing: ${src}`);
53
+ const parts = plugin.contract.opencodeSkill.split("/");
54
+ const skillIdx = parts.lastIndexOf("skill");
55
+ const rel = skillIdx >= 0 ? parts.slice(skillIdx + 1).join("/") : basename(src);
56
+ const dest = join(opencodeSkillDir(), rel);
57
+ if (statSync(src).isDirectory()) {
58
+ mkdirSync(dest, { recursive: true });
59
+ await run(`cp -R ${JSON.stringify(src + "/.")} ${JSON.stringify(dest)}`);
60
+ }
61
+ else {
62
+ mkdirSync(dirname(dest), { recursive: true });
63
+ copyFileSync(src, dest);
64
+ }
65
+ copied.push(tilde(dest));
66
+ }
67
+ return copied;
68
+ }
69
+ function mergeConfig(plugin) {
70
+ const changes = [];
71
+ if (plugin.contract.opencodePlugin) {
72
+ const filename = basename(plugin.contract.opencodePlugin);
73
+ const entry = `./plugin/${filename}`;
74
+ if (addPluginToConfig(entry))
75
+ changes.push(`added ${entry} to plugin[]`);
76
+ else
77
+ changes.push(`plugin[] already has ${entry}`);
78
+ }
79
+ if (plugin.contract.permission) {
80
+ if (addBashPermission(plugin.contract.permission, "allow")) {
81
+ changes.push(`added bash.${plugin.contract.permission} = "allow"`);
82
+ }
83
+ else {
84
+ changes.push(`bash.${plugin.contract.permission} = "allow" already set`);
85
+ }
86
+ }
87
+ return changes;
88
+ }
89
+ async function updateOne(plugin, step, total) {
90
+ ui.info(ui.bold(`\n[${step}/${total}] ${plugin.name}`));
91
+ const copied = await ui.spinner("Re-copy files", () => copyPluginFiles(plugin));
92
+ for (const p of copied)
93
+ ui.info(` ${ui.dim("→")} ${p}`);
94
+ for (const req of plugin.contract.requires ?? []) {
95
+ const note = await ui.spinner(`Bump dependency: ${req.name}`, () => updateRequirement(req));
96
+ if (note)
97
+ ui.info(` ${ui.dim(note)}`);
98
+ }
99
+ const configChanges = await ui.spinner("Re-merge opencode config", () => Promise.resolve(mergeConfig(plugin)));
100
+ for (const c of configChanges)
101
+ ui.info(` ${ui.dim("•")} ${c}`);
102
+ if (plugin.contract.postInstall?.length) {
103
+ for (const cmd of plugin.contract.postInstall) {
104
+ await ui.spinner(`Verify: ${cmd}`, async () => {
105
+ const res = await run(cmd, { throwOnError: false });
106
+ if (res.code !== 0) {
107
+ throw new Error(`${cmd} failed (exit ${res.code})`);
108
+ }
109
+ });
110
+ }
111
+ }
112
+ }
113
+ function parseArgs(args) {
114
+ const names = [];
115
+ for (const a of args) {
116
+ if (a.startsWith("-"))
117
+ ui.warn(`unknown flag: ${a}`);
118
+ else
119
+ names.push(a);
120
+ }
121
+ return { names };
122
+ }
123
+ export async function update(args) {
124
+ const { names } = parseArgs(args);
125
+ // update without args: bump every installed plugin.
126
+ const installed = discoverPlugins().filter((p) => {
127
+ if (!p.contract.opencodePlugin)
128
+ return false;
129
+ return existsSync(join(opencodePluginDir(), basename(p.contract.opencodePlugin)));
130
+ });
131
+ const targets = names.length > 0 ? names.map((n) => getPlugin(n)) : installed;
132
+ if (targets.length === 0) {
133
+ ui.info("No plugins to update.");
134
+ return 0;
135
+ }
136
+ for (let i = 0; i < targets.length; i++) {
137
+ try {
138
+ await updateOne(targets[i], i + 1, targets.length);
139
+ }
140
+ catch (err) {
141
+ ui.error(`${targets[i].name}: ${err.message}`);
142
+ return 1;
143
+ }
144
+ }
145
+ ui.info(ui.green(`\n✓ Updated ${targets.length} plugin${targets.length === 1 ? "" : "s"}.`));
146
+ return 0;
147
+ }
148
+ //# sourceMappingURL=update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env -S node --no-warnings
2
+ // Entry point for the hl-plugins CLI.
3
+ // Dispatches subcommands. See docs/commands.md for the full reference.
4
+ import { help } from "./commands/help.js";
5
+ import { install } from "./commands/install.js";
6
+ import { uninstall } from "./commands/uninstall.js";
7
+ import { list } from "./commands/list.js";
8
+ import { status } from "./commands/status.js";
9
+ import { update } from "./commands/update.js";
10
+ import { ui } from "./lib/ui.js";
11
+ const commands = [
12
+ { name: "install", summary: "Install one or more plugins", run: install },
13
+ { name: "uninstall", summary: "Remove one or more plugins", run: uninstall },
14
+ { name: "list", summary: "Show known plugins and their install state", run: list },
15
+ { name: "status", summary: "Per-plugin diagnostic report", run: status },
16
+ { name: "update", summary: "Re-copy plugin files and bump dependencies", run: update },
17
+ { name: "help", summary: "Show this help text", run: help },
18
+ ];
19
+ function resolveCommand(raw) {
20
+ if (!raw)
21
+ return null;
22
+ return commands.find((c) => c.name === raw) ?? null;
23
+ }
24
+ async function main() {
25
+ const [, , sub, ...rest] = process.argv;
26
+ const cmd = resolveCommand(sub);
27
+ if (!cmd) {
28
+ if (sub && sub !== "help") {
29
+ ui.error(`unknown command: ${sub}`);
30
+ }
31
+ process.exit(await help(rest));
32
+ }
33
+ try {
34
+ process.exit(await cmd.run(rest));
35
+ }
36
+ catch (err) {
37
+ ui.error(err.message);
38
+ if (process.env["HL_PLUGINS_DEBUG"]) {
39
+ console.error(err.stack);
40
+ }
41
+ process.exit(1);
42
+ }
43
+ }
44
+ main();
45
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,sCAAsC;AACtC,uEAAuE;AAEvE,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAA;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAA;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAC7C,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAA;AAQhC,MAAM,QAAQ,GAAc;IAC1B,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,6BAA6B,EAAE,GAAG,EAAE,OAAO,EAAE;IACzE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,4BAA4B,EAAE,GAAG,EAAE,SAAS,EAAE;IAC5E,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,4CAA4C,EAAE,GAAG,EAAE,IAAI,EAAE;IAClF,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,8BAA8B,EAAE,GAAG,EAAE,MAAM,EAAE;IACxE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,4CAA4C,EAAE,GAAG,EAAE,MAAM,EAAE;IACtF,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAAE,GAAG,EAAE,IAAI,EAAE;CAC5D,CAAA;AAED,SAAS,cAAc,CAAC,GAAuB;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,CAAA;AACrD,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,EAAE,AAAD,EAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAA;IACvC,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC,CAAA;IAE/B,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,IAAI,GAAG,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YAC1B,EAAE,CAAC,KAAK,CAAC,oBAAoB,GAAG,EAAE,CAAC,CAAA;QACrC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAChC,CAAC;IAED,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;IACnC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,EAAE,CAAC,KAAK,CAAE,GAAa,CAAC,OAAO,CAAC,CAAA;QAChC,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,KAAK,CAAE,GAAa,CAAC,KAAK,CAAC,CAAA;QACrC,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAA"}
@@ -0,0 +1,79 @@
1
+ // Read / merge / write ~/.opencode/config.json.
2
+ // All merges are additive — never destroy other plugins, MCP servers, or settings.
3
+ import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
4
+ import { dirname } from "node:path";
5
+ import { opencodeConfigFile } from "./paths.js";
6
+ export function readOpencodeConfig() {
7
+ const file = opencodeConfigFile();
8
+ if (!existsSync(file))
9
+ return {};
10
+ try {
11
+ const text = readFileSync(file, "utf8");
12
+ return JSON.parse(text);
13
+ }
14
+ catch (err) {
15
+ throw new Error(`Failed to parse ${file}: ${err.message}\n` +
16
+ `Fix or remove the file, then retry.`);
17
+ }
18
+ }
19
+ export function writeOpencodeConfig(cfg) {
20
+ const file = opencodeConfigFile();
21
+ mkdirSync(dirname(file), { recursive: true });
22
+ writeFileSync(file, JSON.stringify(cfg, null, 2) + "\n", "utf8");
23
+ }
24
+ /**
25
+ * Add a plugin entry to the `plugin` array. Idempotent.
26
+ * Returns true if the array was actually modified.
27
+ */
28
+ export function addPluginToConfig(pluginPath) {
29
+ const cfg = readOpencodeConfig();
30
+ const list = (cfg.plugin ??= []);
31
+ if (list.includes(pluginPath))
32
+ return false;
33
+ list.push(pluginPath);
34
+ writeOpencodeConfig(cfg);
35
+ return true;
36
+ }
37
+ /**
38
+ * Remove a plugin entry from the `plugin` array. Idempotent.
39
+ * Returns true if the array was actually modified.
40
+ */
41
+ export function removePluginFromConfig(pluginPath) {
42
+ const cfg = readOpencodeConfig();
43
+ const list = cfg.plugin;
44
+ if (!list)
45
+ return false;
46
+ const idx = list.indexOf(pluginPath);
47
+ if (idx === -1)
48
+ return false;
49
+ list.splice(idx, 1);
50
+ if (list.length === 0)
51
+ delete cfg.plugin;
52
+ writeOpencodeConfig(cfg);
53
+ return true;
54
+ }
55
+ /**
56
+ * Add a permission pattern (e.g. `"mmx *"` → `"allow"`) under
57
+ * `permission.bash`. Idempotent — won't downgrade an existing entry.
58
+ */
59
+ export function addBashPermission(pattern, value) {
60
+ const cfg = readOpencodeConfig();
61
+ cfg.permission ??= {};
62
+ cfg.permission.bash ??= {};
63
+ const bash = cfg.permission.bash;
64
+ if (bash[pattern] === value)
65
+ return false;
66
+ bash[pattern] = value;
67
+ writeOpencodeConfig(cfg);
68
+ return true;
69
+ }
70
+ export function removeBashPermission(pattern) {
71
+ const cfg = readOpencodeConfig();
72
+ const bash = cfg.permission?.bash;
73
+ if (!bash || !(pattern in bash))
74
+ return false;
75
+ delete bash[pattern];
76
+ writeOpencodeConfig(cfg);
77
+ return true;
78
+ }
79
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ // Resolves filesystem paths the CLI cares about.
2
+ // All paths are tilde-expanded so they survive the
3
+ // `~/Desktop` vs `/Users/<u>/Desktop` macOS split described in AGENTS.md.
4
+ import { homedir, platform } from "node:os";
5
+ import { fileURLToPath } from "node:url";
6
+ import { dirname, join } from "node:path";
7
+ import { existsSync, readFileSync } from "node:fs";
8
+ const HOME = homedir();
9
+ /** The user's OpenCode config directory. */
10
+ export function opencodeConfigDir() {
11
+ // macOS / Linux default per OpenCode docs. Add XDG/Windows later if needed.
12
+ if (platform() === "darwin" || platform() === "linux") {
13
+ return join(HOME, ".opencode");
14
+ }
15
+ return join(HOME, ".opencode");
16
+ }
17
+ export function opencodePluginDir() {
18
+ return join(opencodeConfigDir(), "plugin");
19
+ }
20
+ export function opencodeSkillDir() {
21
+ return join(opencodeConfigDir(), "skill");
22
+ }
23
+ export function opencodeConfigFile() {
24
+ return join(opencodeConfigDir(), "config.json");
25
+ }
26
+ /** Where generated mmx assets land. */
27
+ export function mmxOutputDir() {
28
+ return join(HOME, "Desktop", "mmx-output");
29
+ }
30
+ // Memoized: finding the monorepo root scans the filesystem, so do it once.
31
+ let _monorepoRoot = null;
32
+ /**
33
+ * Walk up from this file's directory until we find a package.json with
34
+ * a `workspaces` field — that's the monorepo root. Works regardless of
35
+ * how deeply nested the CLI source is.
36
+ */
37
+ export function monorepoRoot() {
38
+ if (_monorepoRoot)
39
+ return _monorepoRoot;
40
+ const here = dirname(fileURLToPath(import.meta.url));
41
+ let dir = here;
42
+ for (let i = 0; i < 12; i++) {
43
+ const pkg = join(dir, "package.json");
44
+ if (existsSync(pkg)) {
45
+ try {
46
+ const json = JSON.parse(readFileSync(pkg, "utf8"));
47
+ if (Array.isArray(json["workspaces"])) {
48
+ _monorepoRoot = dir;
49
+ return dir;
50
+ }
51
+ }
52
+ catch {
53
+ // ignore unreadable package.json
54
+ }
55
+ }
56
+ const parent = dirname(dir);
57
+ if (parent === dir)
58
+ break;
59
+ dir = parent;
60
+ }
61
+ throw new Error(`Could not find monorepo root (no package.json with "workspaces" found walking up from ${here}).`);
62
+ }
63
+ /** Where this CLI package lives. */
64
+ export function cliPackageDir() {
65
+ return join(monorepoRoot(), "packages", "cli");
66
+ }
67
+ /** Expand a leading `~` to $HOME. */
68
+ export function expandHome(p) {
69
+ if (p === "~")
70
+ return HOME;
71
+ if (p.startsWith("~/"))
72
+ return join(HOME, p.slice(2));
73
+ return p;
74
+ }
75
+ /** Shorten a path for display by replacing $HOME with `~`. */
76
+ export function tilde(p) {
77
+ if (p === HOME)
78
+ return "~";
79
+ if (p.startsWith(HOME + "/"))
80
+ return "~" + p.slice(HOME.length);
81
+ return p;
82
+ }
83
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,112 @@
1
+ // Plugin discovery. Two sources, deduped by short name:
2
+ //
3
+ // 1. Dev mode -- `packages/plugin-*/package.json` in the monorepo.
4
+ // 2. Pub'd mode -- `node_modules/@hl-plugins/*/package.json` walked up
5
+ // from the CLI's own location.
6
+ //
7
+ // The CLI stays generic -- it never imports a plugin by name. Adding a
8
+ // plugin is "drop a folder" in dev, or `npm install -g @hl-plugins/<name>`
9
+ // in published mode.
10
+ import { readdirSync, readFileSync, existsSync } from "node:fs";
11
+ import { fileURLToPath } from "node:url";
12
+ import { dirname, join, basename, resolve } from "node:path";
13
+ import { monorepoRoot } from "./paths.js";
14
+ function readJson(p) {
15
+ return JSON.parse(readFileSync(p, "utf8"));
16
+ }
17
+ function tryReadPlugin(dir, source) {
18
+ const pkgPath = join(dir, "package.json");
19
+ if (!existsSync(pkgPath))
20
+ return null;
21
+ const pkg = readJson(pkgPath);
22
+ const contract = pkg["hl-plugins"];
23
+ if (!contract)
24
+ return null;
25
+ return {
26
+ name: pkg.name?.toString().replace(/^@[^/]+\//, "") ?? basename(dir),
27
+ version: pkg.version ?? "0.0.0",
28
+ description: pkg.description ?? "",
29
+ packageDir: resolve(dir),
30
+ source,
31
+ contract,
32
+ };
33
+ }
34
+ /** Walk up from a directory looking for ancestor `node_modules` dirs. */
35
+ function findAncestorNodeModules(start, maxLevels = 8) {
36
+ const found = [];
37
+ let dir = start;
38
+ for (let i = 0; i < maxLevels; i++) {
39
+ const nm = join(dir, "node_modules");
40
+ if (existsSync(nm))
41
+ found.push(nm);
42
+ const parent = dirname(dir);
43
+ if (parent === dir)
44
+ break;
45
+ dir = parent;
46
+ }
47
+ return found;
48
+ }
49
+ /** Plugins from `packages/plugin-<name>/` in the monorepo. */
50
+ function discoverInMonorepo() {
51
+ let root;
52
+ try {
53
+ root = monorepoRoot();
54
+ }
55
+ catch {
56
+ return [];
57
+ }
58
+ const pkgsDir = join(root, "packages");
59
+ if (!existsSync(pkgsDir))
60
+ return [];
61
+ return readdirSync(pkgsDir)
62
+ .filter((d) => d.startsWith("plugin-"))
63
+ .map((d) => tryReadPlugin(join(pkgsDir, d), "monorepo"))
64
+ .filter((p) => p !== null);
65
+ }
66
+ // (the comment above uses angle brackets; if tsc chokes on the JSDoc,
67
+ // that's why this fix is in a sibling line comment)
68
+ function discoverInNodeModules() {
69
+ const here = dirname(fileURLToPath(import.meta.url));
70
+ const found = [];
71
+ for (const nm of findAncestorNodeModules(here)) {
72
+ const scopeDir = join(nm, "@hl-plugins");
73
+ if (!existsSync(scopeDir))
74
+ continue;
75
+ for (const d of readdirSync(scopeDir)) {
76
+ const plugin = tryReadPlugin(join(scopeDir, d), "node_modules");
77
+ if (plugin && !found.some((p) => p.name === plugin.name)) {
78
+ found.push(plugin);
79
+ }
80
+ }
81
+ }
82
+ return found;
83
+ }
84
+ /**
85
+ * Discover all plugins, deduped by short name.
86
+ * Monorepo wins over node_modules when both have the same name
87
+ * (so local source beats installed package).
88
+ */
89
+ export function discoverPlugins() {
90
+ const monorepo = discoverInMonorepo();
91
+ const installed = discoverInNodeModules().filter((p) => !monorepo.some((m) => m.name === p.name));
92
+ return [...monorepo, ...installed].sort((a, b) => a.name.localeCompare(b.name));
93
+ }
94
+ /** Look up one plugin by short name (e.g. "mmx"). Throws if not found. */
95
+ export function getPlugin(name) {
96
+ const all = discoverPlugins();
97
+ const match = all.find((p) => p.name === name);
98
+ if (!match) {
99
+ const known = all.map((p) => p.name).join(", ");
100
+ const hint = match === null && !known
101
+ ? `\nIf you're using the published CLI, run \`npm install -g @hl-plugins/${name}\` first.`
102
+ : "";
103
+ throw new Error(`Unknown plugin: "${name}".\n` +
104
+ `Known plugins: ${known || "(none discovered)"}.` +
105
+ hint);
106
+ }
107
+ return match;
108
+ }
109
+ export function defaultInstallPlugins() {
110
+ return discoverPlugins().filter((p) => p.contract.defaultInstall !== false);
111
+ }
112
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/lib/registry.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAC1E,kDAAkD;AAClD,EAAE;AACF,uEAAuE;AACvE,2EAA2E;AAC3E,qBAAqB;AAErB,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AA4CzC,SAAS,QAAQ,CAAI,CAAS;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAM,CAAA;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,GAAW,EAAE,MAAmC;IACrE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;IACzC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAA;IACrC,MAAM,GAAG,GAAG,QAAQ,CAA0B,OAAO,CAAC,CAAA;IACtD,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAA2C,CAAA;IAC5E,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAC1B,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC;QACpE,OAAO,EAAG,GAAG,CAAC,OAAkB,IAAI,OAAO;QAC3C,WAAW,EAAG,GAAG,CAAC,WAAsB,IAAI,EAAE;QAC9C,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC;QACxB,MAAM;QACN,QAAQ;KACT,CAAA;AACH,CAAC;AAED,yEAAyE;AACzE,SAAS,uBAAuB,CAAC,KAAa,EAAE,SAAS,GAAG,CAAC;IAC3D,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,GAAG,GAAG,KAAK,CAAA;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;QACpC,IAAI,UAAU,CAAC,EAAE,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,MAAM,KAAK,GAAG;YAAE,MAAK;QACzB,GAAG,GAAG,MAAM,CAAA;IACd,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,8DAA8D;AAC9D,SAAS,kBAAkB;IACzB,IAAI,IAAY,CAAA;IAChB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,EAAE,CAAA;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;IACtC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAA;IACnC,OAAO,WAAW,CAAC,OAAO,CAAC;SACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;SACtC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;SACvD,MAAM,CAAC,CAAC,CAAC,EAAuB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;AACnD,CAAC;AAED,sEAAsE;AACtE,qDAAqD;AACrD,SAAS,qBAAqB;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IACpD,MAAM,KAAK,GAAqB,EAAE,CAAA;IAClC,KAAK,MAAM,EAAE,IAAI,uBAAuB,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,EAAE,EAAE,aAAa,CAAC,CAAA;QACxC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAQ;QACnC,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,cAAc,CAAC,CAAA;YAC/D,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,QAAQ,GAAG,kBAAkB,EAAE,CAAA;IACrC,MAAM,SAAS,GAAG,qBAAqB,EAAE,CAAC,MAAM,CAC9C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,CAChD,CAAA;IACD,OAAO,CAAC,GAAG,QAAQ,EAAE,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AACjF,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,GAAG,GAAG,eAAe,EAAE,CAAA;IAC7B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;IAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC/C,MAAM,IAAI,GAAG,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK;YACnC,CAAC,CAAC,yEAAyE,IAAI,WAAW;YAC1F,CAAC,CAAC,EAAE,CAAA;QACN,MAAM,IAAI,KAAK,CACb,oBAAoB,IAAI,MAAM;YAC5B,kBAAkB,KAAK,IAAI,mBAAmB,GAAG;YACjD,IAAI,CACP,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,MAAM,UAAU,qBAAqB;IACnC,OAAO,eAAe,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,KAAK,KAAK,CAAC,CAAA;AAC7E,CAAC"}
@@ -0,0 +1,58 @@
1
+ // Thin shell-out helper. No third-party deps; spawns `sh -c` so we can
2
+ // chain, pipe, and use shell builtins the way the contract strings expect.
3
+ import { spawn } from "node:child_process";
4
+ const spawnShell = (cmd, opts = {}) => spawn("sh", ["-c", cmd], {
5
+ cwd: opts.cwd,
6
+ env: { ...process.env, ...(opts.env ?? {}) },
7
+ stdio: ["ignore", "pipe", "pipe"],
8
+ });
9
+ export async function run(cmd, opts = {}) {
10
+ const throwOnError = opts.throwOnError ?? true;
11
+ return new Promise((resolve, reject) => {
12
+ const proc = spawnShell(cmd, opts);
13
+ let stdout = "";
14
+ let stderr = "";
15
+ proc.stdout.on("data", (d) => (stdout += d.toString()));
16
+ proc.stderr.on("data", (d) => (stderr += d.toString()));
17
+ proc.on("error", (err) => {
18
+ if (throwOnError)
19
+ reject(err);
20
+ else
21
+ resolve({ code: 127, stdout, stderr: stderr + String(err) });
22
+ });
23
+ proc.on("close", (code) => {
24
+ const result = { code: code ?? 1, stdout, stderr };
25
+ if (throwOnError && result.code !== 0) {
26
+ reject(new ShellError(cmd, result));
27
+ }
28
+ else {
29
+ resolve(result);
30
+ }
31
+ });
32
+ });
33
+ }
34
+ /** Run a command, return null on any failure (non-zero, ENOENT, etc.). */
35
+ export async function tryRun(cmd, opts = {}) {
36
+ return run(cmd, { ...opts, throwOnError: false }).catch(() => null);
37
+ }
38
+ export class ShellError extends Error {
39
+ cmd;
40
+ result;
41
+ constructor(cmd, result) {
42
+ super(`Command failed (exit ${result.code}): ${cmd}\n` +
43
+ (result.stderr.trim() || result.stdout.trim() || "(no output)"));
44
+ this.name = "ShellError";
45
+ this.cmd = cmd;
46
+ this.result = result;
47
+ }
48
+ }
49
+ /** Substitute `{key}` placeholders in a contract command string. */
50
+ export function fillTemplate(tpl, vars) {
51
+ return tpl.replace(/\{(\w+)\}/g, (_, k) => {
52
+ const v = vars[k];
53
+ if (v === undefined)
54
+ throw new Error(`Template variable {${k}} not provided in: ${tpl}`);
55
+ return v;
56
+ });
57
+ }
58
+ //# sourceMappingURL=shell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/lib/shell.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,2EAA2E;AAE3E,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAe1C,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,OAAgB,EAAE,EAAE,EAAE,CACrD,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE;IACvB,GAAG,EAAE,IAAI,CAAC,GAAG;IACb,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE;IAC5C,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;CAClC,CAAC,CAAA;AAEJ,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,GAAW,EAAE,OAAgB,EAAE;IACvD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAA;IAC9C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAA;QAClC,IAAI,MAAM,GAAG,EAAE,CAAA;QACf,IAAI,MAAM,GAAG,EAAE,CAAA;QACf,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QACvD,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QACvD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACvB,IAAI,YAAY;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAA;;gBACxB,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACnE,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,MAAM,MAAM,GAAgB,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;YAC/D,IAAI,YAAY,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACtC,MAAM,CAAC,IAAI,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAA;YACrC,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,CAAA;YACjB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,GAAW,EAAE,OAAgB,EAAE;IAC1D,OAAO,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;AACrE,CAAC;AAED,MAAM,OAAO,UAAW,SAAQ,KAAK;IAC1B,GAAG,CAAQ;IACX,MAAM,CAAa;IAC5B,YAAY,GAAW,EAAE,MAAmB;QAC1C,KAAK,CACH,wBAAwB,MAAM,CAAC,IAAI,MAAM,GAAG,IAAI;YAC9C,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,aAAa,CAAC,CAClE,CAAA;QACD,IAAI,CAAC,IAAI,GAAG,YAAY,CAAA;QACxB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;CACF;AAED,oEAAoE;AACpE,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,IAA4B;IACpE,OAAO,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACxC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,IAAI,CAAC,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAA;QACxF,OAAO,CAAC,CAAA;IACV,CAAC,CAAC,CAAA;AACJ,CAAC"}