opencode-skill-autodiscovery 1.1.4 → 1.2.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/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # opencode-skill-autodiscovery
2
2
 
3
3
  An [opencode](https://opencode.ai) plugin that auto-discovers skills installed by
4
- VS Code agent plugins and Claude Code plugins on the current machine, and
5
- registers them with opencode's `skills.paths` so they appear in every session.
6
- Each discovered skill is also exposed as a `/skill-name` slash command that
7
- loads the skill and routes the rest of your message through it.
4
+ VS Code agent plugins, Claude Code plugins, and [Agent Plugins
5
+ 1.0.0](https://agent-plugins.org) conformant packages on the current machine,
6
+ and registers them with opencode's `skills.paths` so they appear in every
7
+ session. Each discovered skill is also exposed as a `/skill-name` slash command
8
+ that loads the skill and routes the rest of your message through it.
8
9
 
9
10
  ## Why
10
11
 
@@ -26,10 +27,40 @@ setup:
26
27
  - Claude Code plugins: `~/.claude/plugins/installed_plugins.json`
27
28
  - Claude Code plugins on a remote host (SSH/remote sessions):
28
29
  `~/.claude/remote/plugins/installed_plugins.json`
30
+ - **Agent Plugins 1.0.0 packages** distributed via npm. opencode installs npm
31
+ plugins into its own cache (`~/.cache/opencode/packages/...`), not the
32
+ project's `node_modules`, and a `skills.paths` entry relative to the project
33
+ dir silently resolves to nothing. This plugin scans both the opencode plugin
34
+ cache and the project's `node_modules` for packages carrying a root
35
+ `plugin.json` whose `$schema` is `https://agent-plugins.org/schemas/...`,
36
+ and registers their `skills/` with **absolute** paths — so an npm-distributed
37
+ Agent Plugins package (e.g. `@dodopayments/opencode-plugin`) just works with
38
+ `"plugin": ["opencode-skill-autodiscovery"]` and nothing else.
29
39
 
30
40
  Each points at plugin directories that contain `SKILL.md` files. This plugin
31
41
  reads the manifests (including the remote `cache.json` LRU), resolves each
32
42
  entry to its on-disk skill directories, and registers them with opencode.
43
+ When a discovered package carries a conformant root `plugin.json`, that manifest
44
+ is preferred (its `skills/` children are registered as-is); otherwise the plugin
45
+ falls back to a tree walk so legacy layouts keep working.
46
+
47
+ ### MCP servers (opt-in)
48
+
49
+ With the `mcp` option, the plugin also reads each discovered package's `mcp.json`
50
+ and maps it onto opencode's `config.mcp`:
51
+
52
+ | Agent Plugins server | opencode entry |
53
+ |---|---|
54
+ | `{ "type": "stdio", "command", "args", "env" }` | `{ "type": "local", "command": [...], "environment": {...} }` |
55
+ | `{ "type": "streamable-http", "url" }` | `{ "type": "remote", "url" }` |
56
+ | `{ "type": "sse" }` | skipped (opencode has no SSE transport) |
57
+
58
+ `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` placeholders are expanded in `args`/`env`,
59
+ and both variables are injected into each stdio server's environment
60
+ (`PLUGIN_DATA` points at
61
+ `{opencode state}/plugin-data/{packageName}`). Invalid entries are skipped
62
+ per-entry, never fatally. `sse` servers and stdio `cwd` (which opencode cannot
63
+ represent) are dropped with a log line.
33
64
 
34
65
  ### Slash commands
35
66
 
@@ -45,7 +76,8 @@ Context: $ARGUMENTS
45
76
 
46
77
  So `/spec plan the migration` loads the `spec` skill and runs it against
47
78
  `plan the migration`. The command's description is taken from the skill's
48
- frontmatter; existing commands with the same name are left untouched.
79
+ frontmatter; existing commands with the same name are never overwritten (a
80
+ colliding skill from a different source is registered as `/package-skill`).
49
81
 
50
82
  ## Install
51
83
 
@@ -57,20 +89,31 @@ Add the package name to the `plugin` array in your `opencode.json`:
57
89
  }
58
90
  ```
59
91
 
60
- Use the tuple form to add extra root directories to scan (e.g. a non-standard
61
- VS Code data location on a remote host):
92
+ Use the tuple form to configure options:
62
93
 
63
94
  ```json
64
95
  {
65
96
  "plugin": [
66
97
  [
67
98
  "opencode-skill-autodiscovery",
68
- { "extraRoots": ["/home/user/.vscode-server"] }
99
+ {
100
+ "extraRoots": ["/home/user/.vscode-server"],
101
+ "scanCache": true,
102
+ "scanNodeModules": true,
103
+ "mcp": false
104
+ }
69
105
  ]
70
106
  ]
71
107
  }
72
108
  ```
73
109
 
110
+ | Option | Default | Meaning |
111
+ |---|---|---|
112
+ | `extraRoots` | `[]` | Extra root directories to scan (e.g. a non-standard VS Code data location on a remote host). |
113
+ | `scanCache` | `true` | Scan opencode's plugin cache (`~/.cache/opencode/packages/*`) for Agent Plugins packages. |
114
+ | `scanNodeModules` | `true` | Scan the project's `node_modules` (incl. `@scope/*`) for Agent Plugins packages. |
115
+ | `mcp` | `false` | Also register MCP servers from discovered packages' `mcp.json`. |
116
+
74
117
  ## Notes
75
118
 
76
119
  - Discovery is inherently **machine-local**: it reads manifests from the home
@@ -89,14 +132,23 @@ VS Code data location on a remote host):
89
132
  cloned-but-uninstalled marketplaces on setups that do have a manifest.
90
133
  - VS Code account sync only syncs your marketplace extension list; each machine
91
134
  still has its own `installed.json`/`cache.json` that this plugin reads.
92
- - The plugin is a no-op when no VS Code or Claude plugin manifests exist, or
93
- when they contain no skills.
135
+ - A package is only treated as an Agent Plugins package when its root
136
+ `plugin.json` declares a `$schema` under `https://agent-plugins.org/schemas/`.
137
+ Everything else is ignored by the cache/node_modules scanners and falls back
138
+ to the tree walk elsewhere.
139
+ - The same plugin can be materialised in several VS Code layouts at once
140
+ (local clone + synced bundle + marketplace clone). `skills.paths` keeps all
141
+ paths; slash commands and MCP servers are de-duplicated so mirrors don't
142
+ create a wall of `/mirror-of-...` junk.
143
+ - The plugin is a no-op when no manifests or conformant packages exist, or when
144
+ they contain no skills.
94
145
 
95
146
  ## Development
96
147
 
97
148
  ```sh
98
149
  npm install
99
150
  npm run build # tsc -> dist/
151
+ npm test # build + node --test (fixture-based unit tests)
100
152
  ```
101
153
 
102
154
  Publish:
@@ -0,0 +1,59 @@
1
+ export type PackageSource = "claude" | "vscode" | "opencode-cache" | "node_modules" | "extra";
2
+ export type PluginPackage = {
3
+ source: PackageSource;
4
+ name: string;
5
+ root: string;
6
+ skillDirs: string[];
7
+ mcpPath?: string;
8
+ /** Agent Plugins version declared by plugin.json, e.g. "1.0.0". */
9
+ schemaVersion?: string;
10
+ };
11
+ export type SkillInfo = {
12
+ dir: string;
13
+ name: string;
14
+ description: string;
15
+ };
16
+ export type McpEntry = {
17
+ type: "local";
18
+ command: string[];
19
+ environment?: Record<string, string>;
20
+ enabled?: boolean;
21
+ } | {
22
+ type: "remote";
23
+ url: string;
24
+ headers?: Record<string, string>;
25
+ enabled?: boolean;
26
+ };
27
+ export type ConfigPatch = {
28
+ skillPaths: string[];
29
+ commands: Array<{
30
+ name: string;
31
+ description: string;
32
+ template: string;
33
+ }>;
34
+ mcp: Array<{
35
+ key: string;
36
+ entry: McpEntry;
37
+ }>;
38
+ };
39
+ export declare function log(message: string): void;
40
+ export declare function contains(parent: string, child: string): boolean;
41
+ export declare function readSkillInfo(dir: string): SkillInfo | null;
42
+ export declare function readPackage(root: string, source: PackageSource): PluginPackage | null;
43
+ export declare function findSkillDirs(root: string, out: Set<string>, seen: Set<string>): void;
44
+ export declare function packageFromDir(root: string, source: PackageSource): PluginPackage | null;
45
+ export declare function collectVscode(out: PluginPackage[], extra: string[]): void;
46
+ export declare function collectClaude(out: PluginPackage[]): void;
47
+ export declare function opencodeCacheRoot(): string;
48
+ export declare function collectOpencodeCache(packagesRoot: string, out: PluginPackage[]): void;
49
+ export declare function collectNodeModules(nodeModulesRoot: string, out: PluginPackage[]): void;
50
+ export declare function pluginDataRoot(name: string): string;
51
+ export declare function readMcp(pkg: PluginPackage, out: Array<{
52
+ key: string;
53
+ entry: McpEntry;
54
+ }>): void;
55
+ export declare function planConfig(packages: PluginPackage[], taken?: {
56
+ commands?: Iterable<string>;
57
+ mcp?: Iterable<string>;
58
+ }): ConfigPatch;
59
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,665 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, isAbsolute, join, relative, sep } from "node:path";
4
+ const PLUGIN_SCHEMA = /^https:\/\/agent-plugins\.org\/schemas\/1\.\d+\.\d+\/plugin\.schema\.json$/;
5
+ const MCP_SCHEMA = /^https:\/\/agent-plugins\.org\/schemas\/1\.\d+\.\d+\/mcp\.schema\.json$/;
6
+ const VERSION = /^https:\/\/agent-plugins\.org\/schemas\/(\d+\.\d+\.\d+)\//;
7
+ const STDIO_KEYS = new Set(["type", "command", "args", "env", "cwd"]);
8
+ const HTTP_KEYS = new Set(["type", "url", "headers"]);
9
+ export function log(message) {
10
+ console.error(`[opencode-skill-autodiscovery] ${message}`);
11
+ }
12
+ function isDirectory(p) {
13
+ try {
14
+ return statSync(p).isDirectory();
15
+ }
16
+ catch {
17
+ return false;
18
+ }
19
+ }
20
+ function isRegularFile(p) {
21
+ try {
22
+ return statSync(p).isFile();
23
+ }
24
+ catch {
25
+ return false;
26
+ }
27
+ }
28
+ // True when `child` resolves (through symlinks) inside `parent`.
29
+ export function contains(parent, child) {
30
+ const p = realpathSync(parent);
31
+ const c = realpathSync(child);
32
+ if (p === c)
33
+ return true;
34
+ const rel = relative(p, c);
35
+ return rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
36
+ }
37
+ // Parses the YAML frontmatter of a SKILL.md (name, description). Returns null
38
+ // when the file is unreadable or lacks a valid `name`.
39
+ export function readSkillInfo(dir) {
40
+ const skillMd = join(dir, "SKILL.md");
41
+ let content;
42
+ try {
43
+ content = readFileSync(skillMd, "utf8");
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ const frontmatter = /^---\s*\n([\s\S]*?)\n---/.exec(content)?.[1];
49
+ if (!frontmatter)
50
+ return null;
51
+ const field = (key) => {
52
+ const m = new RegExp(`^${key}:[ \\t]*(.*)$`, "m").exec(frontmatter);
53
+ if (!m)
54
+ return undefined;
55
+ return m[1].trim().replace(/^["']|["']$/g, "");
56
+ };
57
+ const name = field("name");
58
+ if (!name)
59
+ return null;
60
+ return { dir, name, description: field("description") ?? "" };
61
+ }
62
+ // Reads a conformant Agent Plugins 1.0.0 package from a directory root.
63
+ // Returns null when the root has no valid plugin.json, so callers can fall
64
+ // back to legacy discovery. The $schema URL is the discriminator that makes
65
+ // scanning untrusted directories safe.
66
+ export function readPackage(root, source) {
67
+ const manifestPath = join(root, "plugin.json");
68
+ if (!isRegularFile(manifestPath))
69
+ return null;
70
+ let manifest;
71
+ try {
72
+ manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ if (typeof manifest !== "object" || manifest === null)
78
+ return null;
79
+ if (typeof manifest.$schema !== "string" || !PLUGIN_SCHEMA.test(manifest.$schema)) {
80
+ return null;
81
+ }
82
+ if (typeof manifest.name !== "string" || manifest.name.length === 0) {
83
+ return null;
84
+ }
85
+ const skillDirs = [];
86
+ const skillsRoot = join(root, "skills");
87
+ if (isDirectory(skillsRoot)) {
88
+ let entries;
89
+ try {
90
+ entries = readdirSync(skillsRoot);
91
+ }
92
+ catch {
93
+ entries = [];
94
+ }
95
+ for (const entry of entries) {
96
+ const dir = join(skillsRoot, entry);
97
+ if (!isDirectory(dir))
98
+ continue;
99
+ if (!isRegularFile(join(dir, "SKILL.md")))
100
+ continue;
101
+ let resolved;
102
+ try {
103
+ resolved = realpathSync(dir);
104
+ }
105
+ catch {
106
+ continue;
107
+ }
108
+ if (!contains(root, resolved))
109
+ continue;
110
+ skillDirs.push(resolved);
111
+ }
112
+ }
113
+ const mcpPath = isRegularFile(join(root, "mcp.json"))
114
+ ? join(root, "mcp.json")
115
+ : undefined;
116
+ return {
117
+ source,
118
+ name: manifest.name,
119
+ root,
120
+ skillDirs,
121
+ mcpPath,
122
+ schemaVersion: VERSION.exec(manifest.$schema)?.[1],
123
+ };
124
+ }
125
+ // Legacy tree walk: every directory containing a SKILL.md, at any depth.
126
+ export function findSkillDirs(root, out, seen) {
127
+ const resolved = join(root);
128
+ if (seen.has(resolved))
129
+ return;
130
+ seen.add(resolved);
131
+ let entries;
132
+ try {
133
+ entries = readdirSync(resolved);
134
+ }
135
+ catch {
136
+ return;
137
+ }
138
+ for (const entry of entries) {
139
+ if (entry === ".git")
140
+ continue;
141
+ const full = join(resolved, entry);
142
+ if (!isDirectory(full))
143
+ continue;
144
+ if (isRegularFile(join(full, "SKILL.md"))) {
145
+ out.add(full);
146
+ }
147
+ else {
148
+ findSkillDirs(full, out, seen);
149
+ }
150
+ }
151
+ }
152
+ // Prefers a conformant package manifest; falls back to a legacy tree walk so
153
+ // non-conformant layouts keep working. Returns null when nothing is found.
154
+ export function packageFromDir(root, source) {
155
+ const pkg = readPackage(root, source);
156
+ if (pkg)
157
+ return pkg;
158
+ const skillDirs = new Set();
159
+ findSkillDirs(root, skillDirs, new Set());
160
+ if (skillDirs.size === 0)
161
+ return null;
162
+ return {
163
+ source,
164
+ name: root.split(/[\\/]/).pop() || root,
165
+ root,
166
+ skillDirs: [...skillDirs],
167
+ };
168
+ }
169
+ // --- VS Code agent plugin discovery ---------------------------------------
170
+ // VS Code keeps agent plugins in a per-platform "data dir". The holding
171
+ // folder is named `agent-plugins` on older builds (e.g. ~/.vscode) and
172
+ // `agentPlugins` on newer builds; remote servers nest theirs under `data/`
173
+ // (~/.vscode-server/data/agentPlugins). We list every known candidate so the
174
+ // discovery works regardless of OS, build channel, or local/remote setup.
175
+ function vsCodeDataRoots(extra) {
176
+ const home = homedir();
177
+ const roots = new Set([
178
+ join(home, ".vscode"),
179
+ // Linux
180
+ join(home, ".config", "Code"),
181
+ join(home, ".config", "Code - Insiders"),
182
+ // macOS
183
+ join(home, "Library", "Application Support", "Code"),
184
+ join(home, "Library", "Application Support", "Code - Insiders"),
185
+ // Windows
186
+ ...(process.env.APPDATA
187
+ ? [
188
+ join(process.env.APPDATA, "Code"),
189
+ join(process.env.APPDATA, "Code - Insiders"),
190
+ ]
191
+ : []),
192
+ // Remote hosts (Remote-SSH, Dev Containers, Codespaces, WSL)
193
+ join(home, ".vscode-server"),
194
+ join(home, ".vscode-server-insiders"),
195
+ join(home, ".vscode-remote"),
196
+ ]);
197
+ for (const root of extra)
198
+ roots.add(root);
199
+ return [...roots];
200
+ }
201
+ function agentPluginDirs(roots) {
202
+ const dirs = new Set();
203
+ for (const root of roots) {
204
+ dirs.add(join(root, "agent-plugins"));
205
+ dirs.add(join(root, "agentPlugins"));
206
+ dirs.add(join(root, "data", "agent-plugins"));
207
+ dirs.add(join(root, "data", "agentPlugins"));
208
+ }
209
+ return [...dirs];
210
+ }
211
+ function vscodePluginPath(pluginUri) {
212
+ const m = /^file:\/\/(.+)$/.exec(pluginUri);
213
+ if (!m)
214
+ return pluginUri;
215
+ let raw;
216
+ try {
217
+ raw = decodeURIComponent(m[1]);
218
+ }
219
+ catch {
220
+ raw = m[1];
221
+ }
222
+ if (raw.startsWith("/"))
223
+ raw = raw.slice(1);
224
+ return raw;
225
+ }
226
+ function collectVscodeManifest(out, installedJson) {
227
+ if (!existsSync(installedJson))
228
+ return;
229
+ let manifest;
230
+ try {
231
+ manifest = JSON.parse(readFileSync(installedJson, "utf8"));
232
+ }
233
+ catch {
234
+ return;
235
+ }
236
+ for (const plugin of manifest.installed ?? []) {
237
+ if (!plugin.pluginUri)
238
+ continue;
239
+ const dir = vscodePluginPath(plugin.pluginUri);
240
+ if (dir) {
241
+ const pkg = packageFromDir(dir, "vscode");
242
+ if (pkg)
243
+ out.push(pkg);
244
+ }
245
+ }
246
+ }
247
+ // Remote hosts: VS Code syncs client skills into
248
+ // {data}/agentPlugins/{sanitizedUri}/{nonce}/ and records the LRU in
249
+ // cache.json. Resolve each entry so the materialized synced-customization
250
+ // bundle ("VS Code Synced Data" Open Plugin, skills/<name>/SKILL.md) is
251
+ // discovered.
252
+ function collectVscodeCache(out, cacheJson) {
253
+ if (!existsSync(cacheJson))
254
+ return;
255
+ let entries;
256
+ try {
257
+ entries = JSON.parse(readFileSync(cacheJson, "utf8"));
258
+ }
259
+ catch {
260
+ return;
261
+ }
262
+ if (!Array.isArray(entries))
263
+ return;
264
+ const parent = dirname(cacheJson);
265
+ for (const entry of entries) {
266
+ if (typeof entry?.uri !== "string")
267
+ continue;
268
+ const key = sanitizeKey(entry.uri) || "default";
269
+ const nonce = typeof entry.nonce === "string" && entry.nonce
270
+ ? sanitizeKey(entry.nonce)
271
+ : "default";
272
+ for (const dir of [join(parent, key, nonce), join(parent, key)]) {
273
+ const pkg = packageFromDir(dir, "vscode");
274
+ if (pkg)
275
+ out.push(pkg);
276
+ }
277
+ }
278
+ }
279
+ // Mirrors the server-side AgentPluginManager sanitizer so we can resolve the
280
+ // cache.json entries to their on-disk directories.
281
+ function sanitizeKey(value) {
282
+ return value
283
+ .replace(/[^a-zA-Z0-9]/g, "-")
284
+ .replace(/-+/g, "-")
285
+ .replace(/^-|-$/g, "")
286
+ .substring(0, 128);
287
+ }
288
+ function collectAgentPluginRoot(out, root) {
289
+ const installedJson = join(root, "installed.json");
290
+ const cacheJson = join(root, "cache.json");
291
+ const hasManifest = existsSync(installedJson) || existsSync(cacheJson);
292
+ collectVscodeManifest(out, installedJson);
293
+ collectVscodeCache(out, cacheJson);
294
+ // Newer VS Code installs marketplaces directly as {host}/{org}/{repo}
295
+ // subdirectories with no manifest file at all. Fall back to a full tree walk
296
+ // only when no metadata exists, so we don't surface skills from cloned-but-
297
+ // not-installed marketplaces on setups that do have a manifest.
298
+ if (!hasManifest) {
299
+ const pkg = packageFromDir(root, "vscode");
300
+ if (pkg)
301
+ out.push(pkg);
302
+ }
303
+ }
304
+ export function collectVscode(out, extra) {
305
+ for (const dir of agentPluginDirs(vsCodeDataRoots(extra))) {
306
+ collectAgentPluginRoot(out, dir);
307
+ }
308
+ }
309
+ // --- Claude Code plugin discovery ------------------------------------------
310
+ function collectClaudeManifest(out, installedJson) {
311
+ if (!existsSync(installedJson))
312
+ return;
313
+ let manifest;
314
+ try {
315
+ manifest = JSON.parse(readFileSync(installedJson, "utf8"));
316
+ }
317
+ catch {
318
+ return;
319
+ }
320
+ for (const versions of Object.values(manifest.plugins ?? {})) {
321
+ for (const plugin of versions) {
322
+ if (plugin.installPath) {
323
+ const pkg = packageFromDir(plugin.installPath, "claude");
324
+ if (pkg)
325
+ out.push(pkg);
326
+ }
327
+ }
328
+ }
329
+ }
330
+ export function collectClaude(out) {
331
+ const home = homedir();
332
+ const installedJsons = [
333
+ join(home, ".claude", "plugins", "installed_plugins.json"),
334
+ join(home, ".claude", "remote", "plugins", "installed_plugins.json"),
335
+ ];
336
+ let found = false;
337
+ for (const installedJson of installedJsons) {
338
+ if (existsSync(installedJson)) {
339
+ found = true;
340
+ collectClaudeManifest(out, installedJson);
341
+ }
342
+ }
343
+ // Remote hosts sync Claude plugins as {nonce}/ dirs with per-plugin
344
+ // manifest.json but no installed_plugins.json; tree-walk the remote plugins
345
+ // dir as a fallback so those skills are discovered too.
346
+ if (!found) {
347
+ const remoteRoot = join(home, ".claude", "remote", "plugins");
348
+ if (existsSync(remoteRoot)) {
349
+ const pkg = packageFromDir(remoteRoot, "claude");
350
+ if (pkg)
351
+ out.push(pkg);
352
+ }
353
+ }
354
+ }
355
+ // --- npm-distributed Agent Plugins packages --------------------------------
356
+ export function opencodeCacheRoot() {
357
+ const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
358
+ return join(base, "opencode");
359
+ }
360
+ // opencode installs npm plugins into its own cache, not the project's
361
+ // node_modules: {cache}/packages/{name}@{version}/node_modules/{name}. Scanning
362
+ // it is what makes an npm-distributed Agent Plugins package work without any
363
+ // manual skills.paths entry.
364
+ export function collectOpencodeCache(packagesRoot, out) {
365
+ let pkgEntries;
366
+ try {
367
+ pkgEntries = readdirSync(packagesRoot);
368
+ }
369
+ catch {
370
+ return;
371
+ }
372
+ for (const pkgEntry of pkgEntries) {
373
+ const nodeModules = join(packagesRoot, pkgEntry, "node_modules");
374
+ if (!isDirectory(nodeModules))
375
+ continue;
376
+ collectNodeModules(nodeModules, out);
377
+ }
378
+ }
379
+ // Enumerates immediate package roots of a node_modules dir, including scoped
380
+ // packages (@scope/*). Only conformant packages (root plugin.json) are read;
381
+ // nothing else is walked.
382
+ export function collectNodeModules(nodeModulesRoot, out) {
383
+ if (!isDirectory(nodeModulesRoot))
384
+ return;
385
+ let entries;
386
+ try {
387
+ entries = readdirSync(nodeModulesRoot);
388
+ }
389
+ catch {
390
+ return;
391
+ }
392
+ for (const entry of entries) {
393
+ if (entry === ".bin" || entry.startsWith("."))
394
+ continue;
395
+ const candidate = join(nodeModulesRoot, entry);
396
+ if (!isDirectory(candidate))
397
+ continue;
398
+ if (entry.startsWith("@")) {
399
+ let scoped;
400
+ try {
401
+ scoped = readdirSync(candidate);
402
+ }
403
+ catch {
404
+ continue;
405
+ }
406
+ for (const sub of scoped) {
407
+ if (sub.startsWith("."))
408
+ continue;
409
+ const pkg = readPackage(join(candidate, sub), "node_modules");
410
+ if (pkg)
411
+ out.push(pkg);
412
+ }
413
+ }
414
+ else {
415
+ const pkg = readPackage(candidate, "node_modules");
416
+ if (pkg)
417
+ out.push(pkg);
418
+ }
419
+ }
420
+ }
421
+ // --- MCP servers (mcp.json) -------------------------------------------------
422
+ function opencodeStateRoot() {
423
+ const base = process.env.XDG_STATE_HOME || join(homedir(), ".local", "state");
424
+ return join(base, "opencode");
425
+ }
426
+ export function pluginDataRoot(name) {
427
+ return join(opencodeStateRoot(), "plugin-data", name);
428
+ }
429
+ function expandPluginVars(value, root, dataDir) {
430
+ return value
431
+ .split("${PLUGIN_ROOT}")
432
+ .join(root)
433
+ .split("${PLUGIN_DATA}")
434
+ .join(dataDir);
435
+ }
436
+ function collectHeaders(value) {
437
+ const headers = {};
438
+ if (typeof value === "object" && value !== null) {
439
+ for (const [k, v] of Object.entries(value)) {
440
+ if (typeof v === "string")
441
+ headers[k] = v;
442
+ }
443
+ }
444
+ return headers;
445
+ }
446
+ function hasUnknownKeys(server, allowed) {
447
+ return Object.keys(server).some((k) => !allowed.has(k));
448
+ }
449
+ // Maps the portable mcp.json shape onto opencode's native config.mcp. Per the
450
+ // Agent Plugins spec, failures are per-entry (and per-package for an invalid
451
+ // mcp.json): a bad server never blocks other servers or the package's skills.
452
+ export function readMcp(pkg, out) {
453
+ if (!pkg.mcpPath)
454
+ return;
455
+ let raw;
456
+ try {
457
+ raw = readFileSync(pkg.mcpPath, "utf8");
458
+ }
459
+ catch {
460
+ return;
461
+ }
462
+ let parsed;
463
+ try {
464
+ parsed = JSON.parse(raw);
465
+ }
466
+ catch {
467
+ log(`ignoring mcp.json for package "${pkg.name}": not valid JSON`);
468
+ return;
469
+ }
470
+ if (typeof parsed !== "object" || parsed === null) {
471
+ log(`ignoring mcp.json for package "${pkg.name}": not an object`);
472
+ return;
473
+ }
474
+ if (typeof parsed.$schema !== "string" || !MCP_SCHEMA.test(parsed.$schema)) {
475
+ log(`ignoring mcp.json for package "${pkg.name}": unsupported or missing $schema`);
476
+ return;
477
+ }
478
+ const mcpVersion = VERSION.exec(parsed.$schema)?.[1];
479
+ if (pkg.schemaVersion && mcpVersion && mcpVersion !== pkg.schemaVersion) {
480
+ log(`ignoring mcp.json for package "${pkg.name}": schema version ${mcpVersion} does not match plugin.json (${pkg.schemaVersion})`);
481
+ return;
482
+ }
483
+ if (typeof parsed.mcpServers !== "object" || parsed.mcpServers === null) {
484
+ log(`ignoring mcp.json for package "${pkg.name}": missing mcpServers`);
485
+ return;
486
+ }
487
+ const dataDir = pluginDataRoot(pkg.name);
488
+ const servers = parsed.mcpServers;
489
+ for (const [name, serverValue] of Object.entries(servers)) {
490
+ if (typeof serverValue !== "object" || serverValue === null) {
491
+ log(`skipping MCP server "${pkg.name}/${name}": invalid entry`);
492
+ continue;
493
+ }
494
+ const server = serverValue;
495
+ if (server.type === "stdio") {
496
+ if (hasUnknownKeys(server, STDIO_KEYS)) {
497
+ log(`skipping MCP server "${pkg.name}/${name}": unknown fields in stdio entry`);
498
+ continue;
499
+ }
500
+ if (typeof server.command !== "string" || server.command.length === 0) {
501
+ log(`skipping MCP server "${pkg.name}/${name}": stdio requires a string command`);
502
+ continue;
503
+ }
504
+ const command = server.command.startsWith("./")
505
+ ? join(pkg.root, server.command)
506
+ : server.command;
507
+ const args = Array.isArray(server.args)
508
+ ? server.args
509
+ .filter((a) => typeof a === "string")
510
+ .map((a) => expandPluginVars(a, pkg.root, dataDir))
511
+ : [];
512
+ const environment = {};
513
+ if (typeof server.env === "object" && server.env !== null) {
514
+ for (const [k, v] of Object.entries(server.env)) {
515
+ if (k === "PLUGIN_ROOT" || k === "PLUGIN_DATA") {
516
+ log(`dropping reserved env key "${k}" for MCP server "${pkg.name}/${name}"`);
517
+ continue;
518
+ }
519
+ if (typeof v === "string") {
520
+ environment[k] = expandPluginVars(v, pkg.root, dataDir);
521
+ }
522
+ }
523
+ }
524
+ environment.PLUGIN_ROOT = pkg.root;
525
+ environment.PLUGIN_DATA = dataDir;
526
+ if (server.cwd !== undefined) {
527
+ const cwd = typeof server.cwd === "string"
528
+ ? expandPluginVars(server.cwd, pkg.root, dataDir)
529
+ : String(server.cwd);
530
+ log(`dropping cwd "${cwd}" for MCP server "${pkg.name}/${name}": opencode has no cwd support`);
531
+ }
532
+ try {
533
+ mkdirSync(dataDir, { recursive: true });
534
+ }
535
+ catch {
536
+ // Non-fatal: the subprocess env still points at the (uncreated) dir.
537
+ }
538
+ out.push({
539
+ key: name,
540
+ entry: { type: "local", command: [command, ...args], environment, enabled: true },
541
+ });
542
+ }
543
+ else if (server.type === "streamable-http") {
544
+ if (hasUnknownKeys(server, HTTP_KEYS)) {
545
+ log(`skipping MCP server "${pkg.name}/${name}": unknown fields in streamable-http entry`);
546
+ continue;
547
+ }
548
+ if (typeof server.url !== "string" || server.url.length === 0) {
549
+ log(`skipping MCP server "${pkg.name}/${name}": streamable-http requires a string url`);
550
+ continue;
551
+ }
552
+ out.push({
553
+ key: name,
554
+ entry: {
555
+ type: "remote",
556
+ url: server.url,
557
+ headers: collectHeaders(server.headers),
558
+ enabled: true,
559
+ },
560
+ });
561
+ }
562
+ else if (server.type === "sse") {
563
+ if (hasUnknownKeys(server, HTTP_KEYS)) {
564
+ log(`skipping MCP server "${pkg.name}/${name}": unknown fields in sse entry`);
565
+ continue;
566
+ }
567
+ log(`skipping MCP server "${pkg.name}/${name}": opencode does not support the sse transport`);
568
+ }
569
+ else {
570
+ log(`skipping MCP server "${pkg.name}/${name}": unknown transport "${String(server.type)}"`);
571
+ }
572
+ }
573
+ }
574
+ // --- Merge logic ------------------------------------------------------------
575
+ // Computes the config contribution from the discovered packages: every unique
576
+ // skill path, slash commands keyed by frontmatter name with collisions
577
+ // namespaced by package name, and MCP servers keyed by server name with
578
+ // collisions namespaced by package name. `taken` seeds the reserved names from
579
+ // the user's existing config so user-defined entries are never overwritten.
580
+ export function planConfig(packages, taken = {}) {
581
+ const skillPaths = [];
582
+ const seenDir = new Set();
583
+ for (const pkg of packages) {
584
+ for (const dir of pkg.skillDirs) {
585
+ if (seenDir.has(dir))
586
+ continue;
587
+ seenDir.add(dir);
588
+ skillPaths.push(dir);
589
+ }
590
+ }
591
+ const commands = [];
592
+ const usedCommands = new Set(taken.commands ?? []);
593
+ const commandOwner = new Map();
594
+ for (const name of taken.commands ?? [])
595
+ commandOwner.set(name, "user");
596
+ const seenCommandDir = new Set();
597
+ for (const pkg of packages) {
598
+ for (const dir of pkg.skillDirs) {
599
+ if (seenCommandDir.has(dir))
600
+ continue;
601
+ seenCommandDir.add(dir);
602
+ const info = readSkillInfo(dir);
603
+ if (!info)
604
+ continue;
605
+ let name = info.name;
606
+ const owner = commandOwner.get(name);
607
+ if (owner !== undefined) {
608
+ if (owner === pkg.source) {
609
+ // Same client layout mirroring one plugin (e.g. a VS Code synced
610
+ // bundle next to the local clone): redundant, keep the first.
611
+ continue;
612
+ }
613
+ const namespaced = `${pkg.name}-${info.name}`;
614
+ if (usedCommands.has(namespaced)) {
615
+ log(`skipping slash command for skill "${info.name}": name already taken`);
616
+ continue;
617
+ }
618
+ name = namespaced;
619
+ }
620
+ commandOwner.set(name, pkg.source);
621
+ usedCommands.add(name);
622
+ commands.push({
623
+ name,
624
+ description: info.description || `Run the ${info.name} skill`,
625
+ template: [
626
+ `Load the \`${info.name}\` skill and follow its instructions.`,
627
+ `Context: $ARGUMENTS`,
628
+ ].join("\n"),
629
+ });
630
+ }
631
+ }
632
+ const mcp = [];
633
+ const usedMcp = new Set(taken.mcp ?? []);
634
+ const mcpOwner = new Map();
635
+ for (const name of taken.mcp ?? [])
636
+ mcpOwner.set(name, "user");
637
+ const seenMcpEntry = new Set();
638
+ for (const pkg of packages) {
639
+ const entries = [];
640
+ readMcp(pkg, entries);
641
+ for (const { key, entry } of entries) {
642
+ const dedupeKey = `${pkg.root}\u0000${key}`;
643
+ if (seenMcpEntry.has(dedupeKey))
644
+ continue;
645
+ seenMcpEntry.add(dedupeKey);
646
+ let k = key;
647
+ const owner = mcpOwner.get(k);
648
+ if (owner !== undefined) {
649
+ if (owner === pkg.source)
650
+ continue;
651
+ const namespaced = `${pkg.name}/${key}`;
652
+ if (usedMcp.has(namespaced)) {
653
+ log(`skipping MCP server "${pkg.name}/${key}": name already taken`);
654
+ continue;
655
+ }
656
+ k = namespaced;
657
+ }
658
+ mcpOwner.set(k, pkg.source);
659
+ usedMcp.add(k);
660
+ mcp.push({ key: k, entry });
661
+ }
662
+ }
663
+ return { skillPaths, commands, mcp };
664
+ }
665
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAU,MAAM,EAAE,MAAM,qBAAqB,CAAC;;kBA6OlC,MAAM;;AAF9B,wBA4CoB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAU,MAAM,EAAE,MAAM,qBAAqB,CAAC;;kBAoBlC,MAAM;;AAF9B,wBAwDoB"}
package/dist/index.js CHANGED
@@ -1,284 +1,56 @@
1
- import { readFileSync, existsSync, readdirSync, statSync } from "node:fs";
2
- import { homedir } from "node:os";
3
- import { dirname, join } from "node:path";
4
- // Parses the YAML frontmatter of a SKILL.md (name, description). Returns null
5
- // when the file is unreadable or lacks a valid `name`.
6
- function readSkillInfo(dir) {
7
- const skillMd = join(dir, "SKILL.md");
8
- let content;
9
- try {
10
- content = readFileSync(skillMd, "utf8");
11
- }
12
- catch {
13
- return null;
14
- }
15
- const frontmatter = /^---\s*\n([\s\S]*?)\n---/.exec(content)?.[1];
16
- if (!frontmatter)
17
- return null;
18
- const field = (key) => {
19
- const m = new RegExp(`^${key}:[ \\t]*(.*)$`, "m").exec(frontmatter);
20
- if (!m)
21
- return undefined;
22
- return m[1].trim().replace(/^["']|["']$/g, "");
23
- };
24
- const name = field("name");
25
- if (!name)
26
- return null;
27
- return { dir, name, description: field("description") ?? "" };
28
- }
29
- // VS Code keeps agent plugins in a per-platform "data dir". The holding
30
- // folder is named `agent-plugins` on older builds (e.g. ~/.vscode) and
31
- // `agentPlugins` on newer builds; remote servers nest theirs under `data/`
32
- // (~/.vscode-server/data/agentPlugins). We list every known candidate so the
33
- // discovery works regardless of OS, build channel, or local/remote setup.
34
- function vsCodeDataRoots(extra) {
35
- const home = homedir();
36
- const roots = new Set([
37
- join(home, ".vscode"),
38
- // Linux
39
- join(home, ".config", "Code"),
40
- join(home, ".config", "Code - Insiders"),
41
- // macOS
42
- join(home, "Library", "Application Support", "Code"),
43
- join(home, "Library", "Application Support", "Code - Insiders"),
44
- // Windows
45
- ...(process.env.APPDATA
46
- ? [
47
- join(process.env.APPDATA, "Code"),
48
- join(process.env.APPDATA, "Code - Insiders"),
49
- ]
50
- : []),
51
- // Remote hosts (Remote-SSH, Dev Containers, Codespaces, WSL)
52
- join(home, ".vscode-server"),
53
- join(home, ".vscode-server-insiders"),
54
- join(home, ".vscode-remote"),
55
- ]);
56
- for (const root of extra)
57
- roots.add(root);
58
- return [...roots];
59
- }
60
- function agentPluginDirs(roots) {
61
- const dirs = new Set();
62
- for (const root of roots) {
63
- dirs.add(join(root, "agent-plugins"));
64
- dirs.add(join(root, "agentPlugins"));
65
- dirs.add(join(root, "data", "agent-plugins"));
66
- dirs.add(join(root, "data", "agentPlugins"));
67
- }
68
- return [...dirs];
69
- }
70
- function findSkillDirs(root, out, seen) {
71
- const resolved = join(root);
72
- if (seen.has(resolved))
73
- return;
74
- seen.add(resolved);
75
- let entries;
76
- try {
77
- entries = readdirSync(resolved);
78
- }
79
- catch {
80
- return;
81
- }
82
- for (const entry of entries) {
83
- if (entry === ".git")
84
- continue;
85
- const full = join(resolved, entry);
86
- let isDir = false;
87
- try {
88
- isDir = statSync(full).isDirectory();
89
- }
90
- catch {
91
- continue;
92
- }
93
- if (isDir) {
94
- if (existsSync(join(full, "SKILL.md"))) {
95
- out.add(full);
96
- }
97
- else {
98
- findSkillDirs(full, out, seen);
99
- }
100
- }
101
- }
102
- }
103
- function vscodePluginPath(pluginUri) {
104
- const m = /^file:\/\/(.+)$/.exec(pluginUri);
105
- if (!m)
106
- return pluginUri;
107
- let raw;
108
- try {
109
- raw = decodeURIComponent(m[1]);
110
- }
111
- catch {
112
- raw = m[1];
113
- }
114
- if (raw.startsWith("/"))
115
- raw = raw.slice(1);
116
- return raw;
117
- }
118
- function collectVscodeManifest(out, installedJson) {
119
- if (!existsSync(installedJson))
120
- return;
121
- let manifest;
122
- try {
123
- manifest = JSON.parse(readFileSync(installedJson, "utf8"));
124
- }
125
- catch {
126
- return;
127
- }
128
- for (const plugin of manifest.installed ?? []) {
129
- if (!plugin.pluginUri)
130
- continue;
131
- const dir = vscodePluginPath(plugin.pluginUri);
132
- if (dir)
133
- findSkillDirs(dir, out, new Set());
134
- }
135
- }
136
- // Remote hosts: VS Code syncs client skills into
137
- // {data}/agentPlugins/{sanitizedUri}/{nonce}/ and records the LRU in
138
- // cache.json. Resolve each entry so the materialized synced-customization
139
- // bundle ("VS Code Synced Data" Open Plugin, skills/<name>/SKILL.md) is
140
- // discovered.
141
- function collectVscodeCache(out, cacheJson) {
142
- if (!existsSync(cacheJson))
143
- return;
144
- let entries;
145
- try {
146
- entries = JSON.parse(readFileSync(cacheJson, "utf8"));
147
- }
148
- catch {
149
- return;
150
- }
151
- if (!Array.isArray(entries))
152
- return;
153
- const parent = dirname(cacheJson);
154
- for (const entry of entries) {
155
- if (typeof entry?.uri !== "string")
156
- continue;
157
- const key = sanitizeKey(entry.uri) || "default";
158
- const nonce = typeof entry.nonce === "string" && entry.nonce
159
- ? sanitizeKey(entry.nonce)
160
- : "default";
161
- findSkillDirs(join(parent, key, nonce), out, new Set());
162
- // Some remote builds materialize the synced bundle directly as
163
- // {parent}/{key}/skills/... without the {nonce} subdirectory.
164
- findSkillDirs(join(parent, key), out, new Set());
165
- }
166
- }
167
- // Mirrors the server-side AgentPluginManager sanitizer so we can resolve the
168
- // cache.json entries to their on-disk directories.
169
- function sanitizeKey(value) {
170
- return value
171
- .replace(/[^a-zA-Z0-9]/g, "-")
172
- .replace(/-+/g, "-")
173
- .replace(/^-|-$/g, "")
174
- .substring(0, 128);
175
- }
176
- function collectAgentPluginRoot(out, root) {
177
- const installedJson = join(root, "installed.json");
178
- const cacheJson = join(root, "cache.json");
179
- const hasManifest = existsSync(installedJson) || existsSync(cacheJson);
180
- collectVscodeManifest(out, installedJson);
181
- collectVscodeCache(out, cacheJson);
182
- // Newer VS Code installs marketplaces directly as {host}/{org}/{repo}
183
- // subdirectories with no manifest file at all. Fall back to a full tree walk
184
- // only when no metadata exists, so we don't surface skills from cloned-but-
185
- // not-installed marketplaces on setups that do have a manifest.
186
- if (!hasManifest) {
187
- findSkillDirs(root, out, new Set());
188
- }
189
- }
190
- function collectVscode(out, extra) {
191
- for (const dir of agentPluginDirs(vsCodeDataRoots(extra))) {
192
- collectAgentPluginRoot(out, dir);
193
- }
194
- }
195
- function collectClaudeManifest(out, installedJson) {
196
- if (!existsSync(installedJson))
197
- return;
198
- let manifest;
199
- try {
200
- manifest = JSON.parse(readFileSync(installedJson, "utf8"));
201
- }
202
- catch {
203
- return;
204
- }
205
- for (const versions of Object.values(manifest.plugins ?? {})) {
206
- for (const plugin of versions) {
207
- if (plugin.installPath) {
208
- findSkillDirs(plugin.installPath, out, new Set());
209
- }
210
- }
211
- }
212
- }
213
- function collectClaude(out) {
214
- const home = homedir();
215
- const installedJsons = [
216
- join(home, ".claude", "plugins", "installed_plugins.json"),
217
- join(home, ".claude", "remote", "plugins", "installed_plugins.json"),
218
- ];
219
- let found = false;
220
- for (const installedJson of installedJsons) {
221
- if (existsSync(installedJson)) {
222
- found = true;
223
- collectClaudeManifest(out, installedJson);
224
- }
225
- }
226
- // Remote hosts sync Claude plugins as {nonce}/ dirs with per-plugin
227
- // manifest.json but no installed_plugins.json; tree-walk the remote plugins
228
- // dir as a fallback so those skills are discovered too.
229
- if (!found) {
230
- const remoteRoot = join(home, ".claude", "remote", "plugins");
231
- if (existsSync(remoteRoot)) {
232
- findSkillDirs(remoteRoot, out, new Set());
233
- }
234
- }
235
- }
1
+ import { join } from "node:path";
2
+ import { collectClaude, collectNodeModules, collectOpencodeCache, collectVscode, opencodeCacheRoot, planConfig, } from "./discovery.js";
236
3
  export default (async (_input, options) => {
237
4
  return {
238
5
  config: async (cfg) => {
239
6
  const config = cfg;
240
- const extra = Array.isArray(options?.extraRoots) ? options.extraRoots : [];
241
- const dirs = new Set();
242
- collectVscode(dirs, extra);
243
- collectClaude(dirs);
244
- if (dirs.size === 0)
245
- return;
246
- const seen = new Set();
247
- const unique = [];
248
- for (const dir of dirs) {
249
- const name = dir.split(/[\\/]/).pop();
250
- if (seen.has(name))
251
- continue;
252
- seen.add(name);
253
- unique.push(dir);
7
+ const extra = Array.isArray(options?.extraRoots)
8
+ ? options.extraRoots
9
+ : [];
10
+ const scanCache = options?.scanCache !== false;
11
+ const scanNodeModules = options?.scanNodeModules !== false;
12
+ const mcpEnabled = options?.mcp === true;
13
+ const packages = [];
14
+ collectClaude(packages);
15
+ collectVscode(packages, extra);
16
+ if (scanCache) {
17
+ collectOpencodeCache(join(opencodeCacheRoot(), "packages"), packages);
254
18
  }
255
- config.skills ??= {};
256
- config.skills.paths ??= [];
257
- for (const dir of unique) {
258
- if (!config.skills.paths.includes(dir)) {
259
- config.skills.paths.push(dir);
19
+ if (scanNodeModules) {
20
+ collectNodeModules(join(process.cwd(), "node_modules"), packages);
21
+ }
22
+ const plan = planConfig(packages, {
23
+ commands: Object.keys(config.command ?? {}),
24
+ mcp: Object.keys(config.mcp ?? {}),
25
+ });
26
+ if (plan.skillPaths.length === 0 && !mcpEnabled)
27
+ return;
28
+ if (plan.skillPaths.length > 0) {
29
+ config.skills ??= {};
30
+ config.skills.paths ??= [];
31
+ for (const dir of plan.skillPaths) {
32
+ if (!config.skills.paths.includes(dir)) {
33
+ config.skills.paths.push(dir);
34
+ }
260
35
  }
261
36
  }
262
- // Expose each discovered skill as a `/name` slash command. opencode
263
- // treats skills and commands as separate mechanisms: a skill is only
264
- // loaded via the `skill` tool, so without this a discovered skill is
265
- // never invocable as `/name`. The command body tells the agent to load
266
- // the skill and route the user's arguments through it.
267
37
  config.command ??= {};
268
- for (const dir of unique) {
269
- const info = readSkillInfo(dir);
270
- if (!info)
271
- continue;
272
- if (config.command[info.name])
38
+ for (const cmd of plan.commands) {
39
+ if (config.command[cmd.name])
273
40
  continue;
274
- config.command[info.name] = {
275
- description: info.description || `Run the ${info.name} skill`,
276
- template: [
277
- `Load the \`${info.name}\` skill and follow its instructions.`,
278
- `Context: $ARGUMENTS`,
279
- ].join("\n"),
41
+ config.command[cmd.name] = {
42
+ description: cmd.description,
43
+ template: cmd.template,
280
44
  };
281
45
  }
46
+ if (mcpEnabled) {
47
+ config.mcp ??= {};
48
+ for (const { key, entry } of plan.mcp) {
49
+ if (config.mcp[key])
50
+ continue;
51
+ config.mcp[key] = entry;
52
+ }
53
+ }
282
54
  },
283
55
  };
284
56
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "opencode-skill-autodiscovery",
3
- "version": "1.1.4",
4
- "description": "OpenCode plugin that auto-discovers skills installed by VS Code agent plugins and Claude Code plugins, and registers them with the local opencode config.",
3
+ "version": "1.2.0",
4
+ "description": "OpenCode plugin that auto-discovers skills installed by VS Code agent plugins, Claude Code plugins, and Agent Plugins 1.0.0 packages, and registers them with the local opencode config.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -28,6 +28,7 @@
28
28
  },
29
29
  "scripts": {
30
30
  "build": "tsc -p tsconfig.json",
31
+ "test": "npm run build && node --test",
31
32
  "prepublishOnly": "npm run build"
32
33
  },
33
34
  "keywords": [