@rbbtsn0w/adg 0.3.0-beta.4 → 0.3.0-beta.5

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.
@@ -31,6 +31,8 @@ export function toAnthropicManifest(pluginDir, manifest, selection) {
31
31
  out.hooks = manifest.hooks;
32
32
  if (manifest.mcp && isExposed(selection, "mcp"))
33
33
  out.mcp = manifest.mcp;
34
+ if (manifest.apps && isExposed(selection, "apps"))
35
+ out.apps = manifest.apps;
34
36
  // Claude's array form is already `./skills/<id>` paths, so a strict array is
35
37
  // passed through verbatim; an explicit id list (selection or strict:false) is
36
38
  // mapped to paths and marks the manifest non-strict.
@@ -16,14 +16,14 @@ export const ADAPTER_TARGETS = ["claude", "codex", "antigravity"];
16
16
  /**
17
17
  * Component categories each adapter target can actually express, mirroring what
18
18
  * the adapters emit: the Claude manifest carries skills/agents/commands/hooks/mcp
19
- * (`toAnthropicManifest`), while Codex only consumes skills (`toCodexManifest`).
20
- * Antigravity (`agy`) discovers the same superset as Claude via convention
21
- * (skills/agents/commands/hooks dirs + mcp_config.json). `apps` is emitted by
22
- * none, so it maps to no target. Used to derive which agents a plugin is
23
- * adaptable to from its exposed component types.
19
+ * plus apps (`toAnthropicManifest`), while Codex only consumes skills
20
+ * (`toCodexManifest`). Antigravity (`agy`) discovers components by convention
21
+ * (skills/agents/commands/hooks dirs + mcp_config.json) and does not surface
22
+ * apps, so apps maps only to the Claude target. Used to derive which agents a
23
+ * plugin is adaptable to from its exposed component types.
24
24
  */
25
25
  export const ADAPTER_COMPONENTS = {
26
- claude: ["skills", "agents", "commands", "hooks", "mcp"],
26
+ claude: ["skills", "agents", "commands", "hooks", "mcp", "apps"],
27
27
  codex: ["skills"],
28
28
  antigravity: ["skills", "agents", "commands", "hooks", "mcp"],
29
29
  };
@@ -36,6 +36,7 @@ export function fromNativeManifest(raw, kind) {
36
36
  copyIfString(n, out, "agents");
37
37
  copyIfString(n, out, "hooks");
38
38
  copyIfString(n, out, "mcp");
39
+ copyIfString(n, out, "apps");
39
40
  if (typeof n.author === "object" && n.author !== null) {
40
41
  manifest.author = n.author;
41
42
  }
@@ -1,4 +1,3 @@
1
- import { spawnSync } from "node:child_process";
2
1
  import { cpSync, existsSync, rmSync, statSync, symlinkSync } from "node:fs";
3
2
  import { homedir } from "node:os";
4
3
  import { dirname, join, relative } from "node:path";
@@ -9,6 +8,7 @@ import { isExposed } from "../components.js";
9
8
  import { installedPluginDir, lockPath } from "../paths.js";
10
9
  import { readLock } from "../lock.js";
11
10
  import { ANTIGRAVITY_PROJECTION_DIR } from "../adapters/antigravity.js";
11
+ import { makeCli } from "./base.js";
12
12
  /**
13
13
  * Antigravity (`agy`) agent.
14
14
  *
@@ -41,19 +41,10 @@ function geminiHome(env) {
41
41
  export function antigravityHome(env = process.env) {
42
42
  return join(geminiHome(env), "antigravity-cli");
43
43
  }
44
- function available() {
45
- // `--help` is rejected by `install` (it parses it as a target), so probe the
46
- // plugin command group with its own `help` subcommand instead.
47
- return spawnSync("agy", ["plugin", "help"], { stdio: "ignore" }).status === 0;
48
- }
49
- function run(args) {
50
- const r = spawnSync("agy", args, { encoding: "utf8" });
51
- const ok = r.status === 0;
52
- // Surface the CLI's own diagnostics on failure instead of swallowing them.
53
- if (!ok && r.stderr)
54
- console.error(r.stderr.trim());
55
- return { ok, out: `${r.stdout ?? ""}${r.stderr ?? ""}` };
56
- }
44
+ // `--help` is rejected by `agy plugin install` (it parses it as a target), so
45
+ // probe the plugin command group with its own `help` subcommand instead.
46
+ // `echoStderr` surfaces the CLI's own diagnostics on failure.
47
+ const { available, run } = makeCli("agy", { probeArgs: ["plugin", "help"], echoStderr: true });
57
48
  /** Resolve a plugin's on-disk store directory and selection from the lock's provenance. */
58
49
  function pluginStore(pluginsDir, name) {
59
50
  const entry = readLock(lockPath(pluginsDir)).plugins[name];
@@ -0,0 +1,26 @@
1
+ import { spawnSync } from "node:child_process";
2
+ /**
3
+ * Build the shared `available()` / `run()` pair for an agent that drives an
4
+ * external plugin CLI. Centralizing the `spawnSync` here keeps error handling,
5
+ * output capture, and (future) timeout/env-forwarding changes in one place
6
+ * rather than copied across every agent.
7
+ */
8
+ export function makeCli(bin, opts) {
9
+ return {
10
+ available: () => spawnSync(bin, opts.probeArgs, { stdio: "ignore" }).status === 0,
11
+ run: (args) => {
12
+ const r = spawnSync(bin, args, { encoding: "utf8" });
13
+ // A launch failure (e.g. ENOENT for a missing binary, EACCES) leaves
14
+ // `status` null and `stderr` empty, exposing the cause only via `error`;
15
+ // treat that as a failure and keep its message instead of swallowing it.
16
+ const ok = r.status === 0 && !r.error;
17
+ if (!ok && opts.echoStderr) {
18
+ if (r.error)
19
+ console.error(r.error.message);
20
+ else if (r.stderr)
21
+ console.error(r.stderr.trim());
22
+ }
23
+ return { ok, out: `${r.stdout ?? ""}${r.stderr ?? ""}${r.error ? r.error.message : ""}` };
24
+ },
25
+ };
26
+ }
@@ -1,4 +1,3 @@
1
- import { spawnSync } from "node:child_process";
2
1
  import { existsSync } from "node:fs";
3
2
  import { homedir } from "node:os";
4
3
  import { join, relative } from "node:path";
@@ -6,6 +5,7 @@ import { toPosix, writeJson } from "../fsutil.js";
6
5
  import { readManifest } from "../manifest.js";
7
6
  import { installedPluginDir, lockPath } from "../paths.js";
8
7
  import { readLock } from "../lock.js";
8
+ import { makeCli } from "./base.js";
9
9
  /**
10
10
  * Claude Code agent.
11
11
  *
@@ -18,13 +18,7 @@ const MARKETPLACE = "adg";
18
18
  function claudeHome(env) {
19
19
  return env.CLAUDE_CONFIG_DIR?.trim() || join(homedir(), ".claude");
20
20
  }
21
- function available() {
22
- return spawnSync("claude", ["plugin", "--help"], { stdio: "ignore" }).status === 0;
23
- }
24
- function run(args) {
25
- const r = spawnSync("claude", args, { encoding: "utf8" });
26
- return { ok: r.status === 0, out: `${r.stdout ?? ""}${r.stderr ?? ""}` };
27
- }
21
+ const { available, run } = makeCli("claude", { probeArgs: ["plugin", "--help"] });
28
22
  /**
29
23
  * Write a Claude marketplace catalog listing every installed plugin, each
30
24
  * `source` pointing at its on-disk directory (relative to the catalog).
@@ -1,9 +1,9 @@
1
- import { spawnSync } from "node:child_process";
2
1
  import { existsSync } from "node:fs";
3
2
  import { homedir } from "node:os";
4
3
  import { join } from "node:path";
5
4
  import { marketplacePath } from "../paths.js";
6
5
  import { readMarketplace } from "../marketplace.js";
6
+ import { makeCli } from "./base.js";
7
7
  /**
8
8
  * Codex agent.
9
9
  *
@@ -14,13 +14,7 @@ import { readMarketplace } from "../marketplace.js";
14
14
  function codexHome(env) {
15
15
  return env.CODEX_HOME?.trim() || join(homedir(), ".codex");
16
16
  }
17
- function available() {
18
- return spawnSync("codex", ["plugin", "--help"], { stdio: "ignore" }).status === 0;
19
- }
20
- function run(args) {
21
- const r = spawnSync("codex", args, { encoding: "utf8" });
22
- return { ok: r.status === 0, out: `${r.stdout ?? ""}${r.stderr ?? ""}` };
23
- }
17
+ const { available, run } = makeCli("codex", { probeArgs: ["plugin", "--help"] });
24
18
  /** The marketplace name Codex sees, read from the generated marketplace.json. */
25
19
  function marketplaceName(pluginsDir) {
26
20
  return readMarketplace(marketplacePath(pluginsDir), "").name;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbbtsn0w/adg",
3
- "version": "0.3.0-beta.4",
3
+ "version": "0.3.0-beta.5",
4
4
  "description": "Agent Directory Group (ADG) toolkit — two domains: plugins and skills.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,9 +26,10 @@
26
26
  "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json --noCheck && node -e \"require('fs').chmodSync('dist/bin/adg.js',0o755)\"",
27
27
  "test": "node --test 'test/**/*.test.ts'",
28
28
  "check:vendor-deps": "node scripts/check-vendor-deps.mjs",
29
+ "audit:prod": "npm audit --omit=dev",
29
30
  "typecheck": "tsc --noEmit",
30
31
  "prepare": "npm run typecheck",
31
- "prepack": "npm run build"
32
+ "prepack": "npm run typecheck && npm run build"
32
33
  },
33
34
  "files": [
34
35
  "dist",