agenticros 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/menu.js CHANGED
@@ -13,8 +13,10 @@ import { doctorCommand, hasRedChecks } from "./commands/doctor.js";
13
13
  import { statusCommand } from "./commands/status.js";
14
14
  import { logsCommand } from "./commands/logs.js";
15
15
  import { configCommand } from "./commands/config.js";
16
+ import { skillsCommand } from "./commands/skills.js";
16
17
  import { header, info, isTty, dim } from "./util/logger.js";
17
18
  import { readState, formatAge } from "./util/state.js";
19
+ import { listSkills } from "./util/skills.js";
18
20
  export async function runMenu() {
19
21
  if (!isTty) {
20
22
  info("Interactive menu requires a TTY. Use a subcommand (e.g. `agenticros up real`) or `agenticros --help`.");
@@ -28,10 +30,13 @@ export async function runMenu() {
28
30
  }
29
31
  // Need-setup detection. Doctor returns a count; we use that to reorder.
30
32
  const setupNeeded = await hasRedChecks();
33
+ const skillsListing = safeListSkills();
34
+ const skillsSuffix = formatSkillsSuffix(skillsListing);
31
35
  const baseChoices = [
32
36
  { name: "Launch with real robot", value: "real" },
33
37
  { name: "Launch with simulation", value: "sim" },
34
38
  { name: "First-time setup (workspace + OpenClaw plugin + API key)", value: "init" },
39
+ { name: `Manage skills${skillsSuffix}`, value: "skills" },
35
40
  { name: "Stop everything", value: "down" },
36
41
  { name: "Doctor (health check)", value: "doctor" },
37
42
  { name: "Configure (API keys, namespace, transport)", value: "config" },
@@ -82,6 +87,9 @@ export async function runMenu() {
82
87
  case "config":
83
88
  await configCommand({ action: "show" });
84
89
  break;
90
+ case "skills":
91
+ await skillsSubmenu();
92
+ break;
85
93
  case "logs":
86
94
  await logsCommand({ target: undefined });
87
95
  break;
@@ -93,4 +101,59 @@ export async function runMenu() {
93
101
  break;
94
102
  }
95
103
  }
104
+ /**
105
+ * Skills sub-menu. Reads the OpenClaw config so the prompt can show how many
106
+ * skills are registered and offer the right next step (discover when nothing
107
+ * is registered yet, otherwise list-first).
108
+ */
109
+ async function skillsSubmenu() {
110
+ const listing = safeListSkills();
111
+ const hasAvailable = listing && listing.available.length > 0;
112
+ const hasRegistered = listing && listing.registered.length > 0;
113
+ const action = await select({
114
+ message: "Skills:",
115
+ choices: [
116
+ { name: "List registered + available", value: "list" },
117
+ {
118
+ name: hasAvailable
119
+ ? `Discover & register (${listing.available.length} unregistered found)`
120
+ : "Discover & register (interactive picker)",
121
+ value: "discover",
122
+ },
123
+ { name: "Add a skill by path or package name", value: "add" },
124
+ { name: "Remove a skill", value: "remove" },
125
+ { name: "Sync OpenClaw contracts.tools allowlist", value: "sync" },
126
+ { name: "Back", value: "back" },
127
+ ],
128
+ default: hasRegistered ? "list" : "discover",
129
+ });
130
+ if (action === "back")
131
+ return;
132
+ await skillsCommand({ action });
133
+ }
134
+ /** Read skills without throwing; the menu must keep working even if the config is broken. */
135
+ function safeListSkills() {
136
+ try {
137
+ return listSkills();
138
+ }
139
+ catch {
140
+ return undefined;
141
+ }
142
+ }
143
+ /** Inline summary attached to the "Manage skills" menu label. */
144
+ function formatSkillsSuffix(listing) {
145
+ if (!listing)
146
+ return "";
147
+ const parts = [];
148
+ if (listing.registered.length > 0) {
149
+ parts.push(`${listing.registered.length} registered`);
150
+ }
151
+ if (listing.available.length > 0) {
152
+ parts.push(`${listing.available.length} available`);
153
+ }
154
+ if (listing.brokenPaths.length > 0) {
155
+ parts.push(`${listing.brokenPaths.length} broken`);
156
+ }
157
+ return parts.length > 0 ? ` (${parts.join(", ")})` : "";
158
+ }
96
159
  //# sourceMappingURL=menu.js.map
package/dist/menu.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"menu.js","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQvD,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CACF,uGAAuG,CACxG,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,CAAC,gDAAgD,CAAC,CAAC;IAEzD,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtC,GAAG,CAAC,cAAc,KAAK,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,wEAAwE;IACxE,MAAM,WAAW,GAAG,MAAM,YAAY,EAAE,CAAC;IAEzC,MAAM,WAAW,GAAiB;QAChC,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,MAAM,EAAE;QACjD,EAAE,IAAI,EAAE,wBAAwB,EAAE,KAAK,EAAE,KAAK,EAAE;QAChD,EAAE,IAAI,EAAE,0DAA0D,EAAE,KAAK,EAAE,MAAM,EAAE;QACnF,EAAE,IAAI,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE;QAC1C,EAAE,IAAI,EAAE,uBAAuB,EAAE,KAAK,EAAE,QAAQ,EAAE;QAClD,EAAE,IAAI,EAAE,4CAA4C,EAAE,KAAK,EAAE,QAAQ,EAAE;QACvE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE;QACpC,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE;QACxC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;KAChC,CAAC;IAEF,MAAM,OAAO,GAAiB,WAAW;QACvC,CAAC,CAAC;YACE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAE;YAC5C,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC;SACjD;QACH,CAAC,CAAC,WAAW,CAAC;IAEhB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAS;QAClC,OAAO,EAAE,4BAA4B;QACrC,OAAO;QACP,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;KAC9G,CAAC,CAAC;IAEH,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,MAAM;YACT,MAAM,SAAS,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YACpC,MAAM;QACR,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,MAAM,GAAG,GAAG,MAAM,MAAM,CAAwB;gBAC9C,OAAO,EAAE,wBAAwB;gBACjC,OAAO,EAAE;oBACP,EAAE,IAAI,EAAE,sCAAsC,EAAE,KAAK,EAAE,SAAS,EAAE;oBAClE;wBACE,IAAI,EAAE,qDAAqD;wBAC3D,KAAK,EAAE,SAAS;qBACjB;iBACF;gBACD,OAAO,EAAE,SAAS;aACnB,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YACtE,MAAM,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;YACvC,MAAM;QACR,CAAC;QACD,KAAK,MAAM;YACT,MAAM,WAAW,CAAC,EAAE,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,MAAM;YACT,MAAM,WAAW,CAAC,EAAE,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;YACxB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YACxC,MAAM;QACR,KAAK,MAAM;YACT,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;YACzC,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;YACxB,MAAM;QACR,KAAK,MAAM,CAAC;QACZ;YACE,MAAM;IACV,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../src/menu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Safe read/write helper for the OpenClaw gateway config file.
3
+ *
4
+ * The OpenClaw config (default: `~/.openclaw/openclaw.json`) is the source of
5
+ * truth for the AgenticROS *plugin*'s skill configuration —
6
+ * `plugins.entries.agenticros.config.skillPaths` and `.skillPackages` decide
7
+ * which skill packages the plugin loads at gateway start. The MCP server and
8
+ * the Gemini CLI read their config from `~/.agenticros/config.json` instead;
9
+ * neither currently loads skills.
10
+ *
11
+ * This module exists so the rest of the CLI can mutate that nested
12
+ * `plugins.entries.agenticros.config` slice without round-tripping the entire
13
+ * JSON document or accidentally clobbering unrelated keys (gateway auth,
14
+ * other plugins, etc). Every write goes through the full JSON parse → mutate
15
+ * → stringify cycle to keep the file valid; comments are not supported in the
16
+ * source JSON either way.
17
+ */
18
+ /** Default location of the OpenClaw config. Overridable via `$OPENCLAW_CONFIG`. */
19
+ export declare function openclawConfigPath(): string;
20
+ export declare function openclawConfigExists(): boolean;
21
+ /**
22
+ * Read the OpenClaw config or return `undefined` if it doesn't exist / is
23
+ * not valid JSON. We never throw — callers can decide how loudly to fail.
24
+ */
25
+ export declare function readOpenclawConfig(): Record<string, unknown> | undefined;
26
+ /** Write the config back, pretty-printed (2-space indent), with a trailing newline. */
27
+ export declare function writeOpenclawConfig(cfg: Record<string, unknown>): void;
28
+ /**
29
+ * Locate (and lazily create) the `plugins.entries.agenticros.config` subtree.
30
+ * Mutates `cfg` in place and returns the inner config object so callers can
31
+ * read/modify its `skillPaths`, `skillPackages`, `skills`, etc.
32
+ */
33
+ export declare function getAgenticrosPluginConfig(cfg: Record<string, unknown>): Record<string, unknown>;
34
+ /**
35
+ * Ensure `obj[key]` is an array of strings and return it (creating an empty
36
+ * array if needed). Non-string entries in an existing array are preserved so
37
+ * we don't silently drop opaque values, but lookups still operate on strings.
38
+ */
39
+ export declare function ensureStringArray(obj: Record<string, unknown>, key: string): unknown[];
40
+ //# sourceMappingURL=openclaw-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-config.d.ts","sourceRoot":"","sources":["../../src/util/openclaw-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,mFAAmF;AACnF,wBAAgB,kBAAkB,IAAI,MAAM,CAI3C;AAED,wBAAgB,oBAAoB,IAAI,OAAO,CAE9C;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAYxE;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAItE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAK/F;AAYD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,GAAG,EAAE,MAAM,GACV,OAAO,EAAE,CAMX"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Safe read/write helper for the OpenClaw gateway config file.
3
+ *
4
+ * The OpenClaw config (default: `~/.openclaw/openclaw.json`) is the source of
5
+ * truth for the AgenticROS *plugin*'s skill configuration —
6
+ * `plugins.entries.agenticros.config.skillPaths` and `.skillPackages` decide
7
+ * which skill packages the plugin loads at gateway start. The MCP server and
8
+ * the Gemini CLI read their config from `~/.agenticros/config.json` instead;
9
+ * neither currently loads skills.
10
+ *
11
+ * This module exists so the rest of the CLI can mutate that nested
12
+ * `plugins.entries.agenticros.config` slice without round-tripping the entire
13
+ * JSON document or accidentally clobbering unrelated keys (gateway auth,
14
+ * other plugins, etc). Every write goes through the full JSON parse → mutate
15
+ * → stringify cycle to keep the file valid; comments are not supported in the
16
+ * source JSON either way.
17
+ */
18
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
19
+ import { dirname, join } from "node:path";
20
+ import { homedir } from "node:os";
21
+ /** Default location of the OpenClaw config. Overridable via `$OPENCLAW_CONFIG`. */
22
+ export function openclawConfigPath() {
23
+ const env = process.env["OPENCLAW_CONFIG"];
24
+ if (env && env.trim().length > 0)
25
+ return env;
26
+ return join(homedir(), ".openclaw", "openclaw.json");
27
+ }
28
+ export function openclawConfigExists() {
29
+ return existsSync(openclawConfigPath());
30
+ }
31
+ /**
32
+ * Read the OpenClaw config or return `undefined` if it doesn't exist / is
33
+ * not valid JSON. We never throw — callers can decide how loudly to fail.
34
+ */
35
+ export function readOpenclawConfig() {
36
+ const p = openclawConfigPath();
37
+ if (!existsSync(p))
38
+ return undefined;
39
+ try {
40
+ const parsed = JSON.parse(readFileSync(p, "utf8"));
41
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
42
+ return parsed;
43
+ }
44
+ return undefined;
45
+ }
46
+ catch {
47
+ return undefined;
48
+ }
49
+ }
50
+ /** Write the config back, pretty-printed (2-space indent), with a trailing newline. */
51
+ export function writeOpenclawConfig(cfg) {
52
+ const p = openclawConfigPath();
53
+ mkdirSync(dirname(p), { recursive: true });
54
+ writeFileSync(p, `${JSON.stringify(cfg, null, 2)}\n`);
55
+ }
56
+ /**
57
+ * Locate (and lazily create) the `plugins.entries.agenticros.config` subtree.
58
+ * Mutates `cfg` in place and returns the inner config object so callers can
59
+ * read/modify its `skillPaths`, `skillPackages`, `skills`, etc.
60
+ */
61
+ export function getAgenticrosPluginConfig(cfg) {
62
+ const plugins = asObject(cfg, "plugins");
63
+ const entries = asObject(plugins, "entries");
64
+ const agenticros = asObject(entries, "agenticros");
65
+ return asObject(agenticros, "config");
66
+ }
67
+ function asObject(parent, key) {
68
+ const cur = parent[key];
69
+ if (cur && typeof cur === "object" && !Array.isArray(cur)) {
70
+ return cur;
71
+ }
72
+ const fresh = {};
73
+ parent[key] = fresh;
74
+ return fresh;
75
+ }
76
+ /**
77
+ * Ensure `obj[key]` is an array of strings and return it (creating an empty
78
+ * array if needed). Non-string entries in an existing array are preserved so
79
+ * we don't silently drop opaque values, but lookups still operate on strings.
80
+ */
81
+ export function ensureStringArray(obj, key) {
82
+ const cur = obj[key];
83
+ if (Array.isArray(cur))
84
+ return cur;
85
+ const fresh = [];
86
+ obj[key] = fresh;
87
+ return fresh;
88
+ }
89
+ //# sourceMappingURL=openclaw-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openclaw-config.js","sourceRoot":"","sources":["../../src/util/openclaw-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Skill discovery, validation, and config-file mutation primitives.
3
+ *
4
+ * An AgenticROS skill is a Node package whose `package.json` carries
5
+ * `"agenticrosSkill": true` and exports a `registerSkill(api, config, context)`
6
+ * function from its `main` entry. The OpenClaw AgenticROS plugin loads them
7
+ * at gateway start by walking two arrays in its config:
8
+ *
9
+ * - `skillPaths[]` — absolute directories to scan (validate `package.json`)
10
+ * - `skillPackages[]` — npm-resolvable names (e.g. `agenticros-skill-find`)
11
+ *
12
+ * This module is the single place the CLI talks to those arrays. It also
13
+ * encapsulates discovery (where on disk users typically clone skill repos)
14
+ * and the `deriveSkillId` convention shared with `@agenticros/agenticros`'s
15
+ * skill-loader so menu / list output uses the same short ids the plugin
16
+ * surfaces (e.g. `followme`, `find`).
17
+ */
18
+ export interface SkillRef {
19
+ /** Short id (matches what the OpenClaw plugin uses for `config.skills.<id>`). */
20
+ id: string;
21
+ /** npm package name (from `package.json.name`). */
22
+ packageName: string;
23
+ /** Absolute directory containing `package.json`, when known. */
24
+ dir?: string;
25
+ /** Where the skill is currently registered with the gateway. */
26
+ registeredAs: ("path" | "package")[];
27
+ /**
28
+ * Absolute path the skill's `package.json` declares as its entry (`main`),
29
+ * resolved against `dir`. Only set when we inspected the directory.
30
+ */
31
+ entry?: string;
32
+ /** True when `entry` exists on disk; false when the skill needs `pnpm build`. */
33
+ built?: boolean;
34
+ }
35
+ /**
36
+ * Apply the same short-id transform the OpenClaw plugin's skill-loader uses,
37
+ * so menu output and the plugin's `config.skills.<id>` keys line up exactly.
38
+ * `agenticros-skill-followme` → `followme`; scoped packages drop the scope.
39
+ */
40
+ export declare function deriveSkillId(packageName: string): string;
41
+ /**
42
+ * Inspect a directory and decide whether it's a valid AgenticROS skill clone.
43
+ * Returns a partial `SkillRef` (no `registeredAs`) or `undefined` when the
44
+ * directory is missing, lacks `package.json`, or doesn't opt in via the
45
+ * `agenticrosSkill: true` flag.
46
+ */
47
+ export declare function inspectSkillDir(dir: string): Omit<SkillRef, "registeredAs"> | undefined;
48
+ /**
49
+ * Return a deduped list of "places we should look for skill clones" — the
50
+ * directories whose children the CLI scans on `agenticros skills discover`.
51
+ *
52
+ * We include both the parent of the active repo / install dir (so siblings
53
+ * of `agenticros/` work, e.g. `../agenticros-skill-find`) and `$HOME` /
54
+ * `$HOME/Projects/` / `$HOME/Code/` so a vanilla clone-into-Projects flow
55
+ * is found without configuration.
56
+ */
57
+ export declare function discoveryRoots(extra?: string[]): string[];
58
+ /**
59
+ * Walk every directory in `roots`, returning a `SkillRef` for each child
60
+ * directory that passes `inspectSkillDir`. Used by both `discover` and
61
+ * `list` (which uses it to render orphaned-but-cloned skills).
62
+ */
63
+ export declare function scanForSkills(extra?: string[]): SkillRef[];
64
+ export interface SkillsListing {
65
+ /** Skills currently registered in the OpenClaw config (path-loaded or package-loaded). */
66
+ registered: SkillRef[];
67
+ /** Skill clones that exist on disk in known discovery roots but aren't registered. */
68
+ available: SkillRef[];
69
+ /** `skillPaths` entries that refer to a directory that no longer exists. */
70
+ brokenPaths: string[];
71
+ }
72
+ /**
73
+ * Build a snapshot of the user's current skill state: what's registered,
74
+ * what's available-but-not-registered, and what registrations are broken.
75
+ * The single source of truth for the `agenticros skills` (list) view.
76
+ */
77
+ export declare function listSkills(): SkillsListing;
78
+ export interface AddResult {
79
+ ok: boolean;
80
+ /** Human-readable summary of what changed (or why nothing changed). */
81
+ message: string;
82
+ skill?: SkillRef;
83
+ }
84
+ /**
85
+ * Add a skill to the OpenClaw plugin config by absolute directory path.
86
+ * Idempotent: re-adding an existing entry is a no-op and returns `ok: true`
87
+ * with an explanatory message. The directory must contain a valid
88
+ * `package.json` with `agenticrosSkill: true`.
89
+ */
90
+ export declare function addSkillByPath(dir: string): AddResult;
91
+ /**
92
+ * Add a skill by npm package name (must be resolvable on the gateway's
93
+ * Node search path). Mainly intended for skills published to a registry —
94
+ * for local clones, prefer `addSkillByPath` so the absolute directory is
95
+ * recorded.
96
+ */
97
+ export declare function addSkillByPackage(name: string): AddResult;
98
+ export interface RemoveResult {
99
+ ok: boolean;
100
+ message: string;
101
+ removedPaths: string[];
102
+ removedPackages: string[];
103
+ }
104
+ /**
105
+ * Remove every registration that matches `idOrName` — either a derived skill
106
+ * id (e.g. `find`), a full package name (e.g. `agenticros-skill-find`), or an
107
+ * absolute path that appears in `skillPaths`. Both `skillPaths` (matched by
108
+ * resolving each path back through `inspectSkillDir`) and `skillPackages`
109
+ * are cleaned in a single pass.
110
+ */
111
+ export declare function removeSkill(idOrName: string): RemoveResult;
112
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/util/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAgBH,MAAM,WAAW,QAAQ;IACvB,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,YAAY,EAAE,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,CAAC;IACrC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMzD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,GAAG,SAAS,CA6BvF;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,KAAK,GAAE,MAAM,EAAO,GAAG,MAAM,EAAE,CAuB7D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE,MAAM,EAAO,GAAG,QAAQ,EAAE,CAqB9D;AA0BD,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,sFAAsF;IACtF,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAyC1C;AAED,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAuCrD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CA6BzD;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CA+D1D"}