opencode-skill-autodiscovery 1.6.1 → 2.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.
Files changed (42) hide show
  1. package/README.md +345 -45
  2. package/dist/agents.d.ts +3 -1
  3. package/dist/agents.d.ts.map +1 -1
  4. package/dist/agents.js +111 -27
  5. package/dist/agents.js.map +1 -1
  6. package/dist/cache.d.ts +5 -0
  7. package/dist/cache.d.ts.map +1 -0
  8. package/dist/cache.js +94 -0
  9. package/dist/cache.js.map +1 -0
  10. package/dist/discovery-cache.d.ts +9 -0
  11. package/dist/discovery-cache.d.ts.map +1 -0
  12. package/dist/discovery-cache.js +161 -0
  13. package/dist/discovery-cache.js.map +1 -0
  14. package/dist/discovery.d.ts +31 -9
  15. package/dist/discovery.d.ts.map +1 -1
  16. package/dist/discovery.js +531 -178
  17. package/dist/discovery.js.map +1 -1
  18. package/dist/index.d.ts +5 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +64 -10
  21. package/dist/index.js.map +1 -1
  22. package/dist/mcp.d.ts +6 -2
  23. package/dist/mcp.d.ts.map +1 -1
  24. package/dist/mcp.js +104 -17
  25. package/dist/mcp.js.map +1 -1
  26. package/dist/schema.d.ts +1 -0
  27. package/dist/schema.d.ts.map +1 -1
  28. package/dist/schema.js +10 -0
  29. package/dist/schema.js.map +1 -1
  30. package/dist/schemas/mcp-schema-1.0.0.d.ts +117 -0
  31. package/dist/schemas/mcp-schema-1.0.0.d.ts.map +1 -0
  32. package/dist/schemas/mcp-schema-1.0.0.js +139 -0
  33. package/dist/schemas/mcp-schema-1.0.0.js.map +1 -0
  34. package/dist/schemas/plugin-schema-1.0.0.d.ts +66 -0
  35. package/dist/schemas/plugin-schema-1.0.0.d.ts.map +1 -0
  36. package/dist/schemas/plugin-schema-1.0.0.js +72 -0
  37. package/dist/schemas/plugin-schema-1.0.0.js.map +1 -0
  38. package/dist/spec-schema.d.ts +12 -0
  39. package/dist/spec-schema.d.ts.map +1 -0
  40. package/dist/spec-schema.js +71 -0
  41. package/dist/spec-schema.js.map +1 -0
  42. package/package.json +50 -47
package/dist/agents.js CHANGED
@@ -1,6 +1,10 @@
1
1
  import { readFileSync, readdirSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { cachedRead } from "./cache.js";
4
+ import { fingerprintTree, getCachedValue, setCachedValue } from "./discovery-cache.js";
3
5
  import { log } from "./log.js";
6
+ import { validateName } from "./schema.js";
7
+ import { resolveContained } from "./discovery.js";
4
8
  // Reverse-DNS namespace this plugin (and opencode, by convention) owns for
5
9
  // client-specific manifest data and extension directories (Agent Plugins 5.6/8).
6
10
  const OPENCODE_NS = "dev.opencode";
@@ -90,10 +94,25 @@ function readJson(path) {
90
94
  return null;
91
95
  }
92
96
  }
97
+ // Package-supplied JSON that feeds agent config (the plugin manifests and the
98
+ // dev.opencode/agents/*.json extension files) is read only when it resolves
99
+ // inside the package root. A symlinked manifest would otherwise let an outside
100
+ // file's `description`/`prompt`/`systemPrompt` fields become model prompt
101
+ // material. Missing files resolve to null silently; an escaping symlink is
102
+ // logged once by resolveContained.
103
+ function readContainedJson(root, path) {
104
+ const contained = resolveContained(root, path);
105
+ if (!contained)
106
+ return null;
107
+ return readJson(contained);
108
+ }
93
109
  // Converts a raw, package-supplied agent object into an opencode AgentConfig.
94
- // `permission` blocks are dropped (too powerful to inherit by default) and
95
- // unknown/mistyped keys are ignored. Returns null when nothing usable is left.
96
- function toAgentConfig(raw) {
110
+ // Package-supplied capability is deliberately clamped: any declared `mode`
111
+ // other than the conservative "subagent" default is dropped, and `permission`
112
+ // blocks and `tools` grants are never inherited (both too powerful to inherit
113
+ // by default). Each drop is logged naming the package and the agent. Unknown
114
+ // or mistyped keys are ignored. Returns null when nothing usable is left.
115
+ function toAgentConfig(raw, pkgName, agentName) {
97
116
  const src = asRecord(raw);
98
117
  if (!src)
99
118
  return null;
@@ -125,20 +144,25 @@ function toAgentConfig(raw) {
125
144
  agent.maxSteps = maxSteps;
126
145
  if (typeof src.disable === "boolean")
127
146
  agent.disable = src.disable;
147
+ // A declared mode other than "subagent" requests capabilities (a primary
148
+ // agent, or opencode's full "all" surface) that a package should not grant
149
+ // itself. Drop it and clamp to the conservative default. An unset mode
150
+ // falls through to opencode's own "all" default, so it stays unset.
128
151
  if (typeof src.mode === "string" && MODES.has(src.mode)) {
129
- agent.mode = src.mode;
152
+ if (src.mode !== "subagent") {
153
+ log(`dropping mode "${src.mode}" from agent "${agentName}" supplied by package "${pkgName}": clamping to conservative "subagent"`);
154
+ }
155
+ agent.mode = "subagent";
130
156
  }
157
+ // Tools booleans are capability grants and are never inherited from a
158
+ // package (agent.tools is intentionally left unset). The drop is logged so
159
+ // a package cannot silently pretend it carries write access.
131
160
  const tools = asRecord(src.tools);
132
- if (tools) {
133
- const filtered = {};
134
- for (const [name, value] of Object.entries(tools)) {
135
- if (typeof value === "boolean")
136
- filtered[name] = value;
137
- }
138
- agent.tools = filtered;
161
+ if (tools && Object.values(tools).some((value) => typeof value === "boolean")) {
162
+ log(`dropping tools from agent "${agentName}" supplied by package "${pkgName}": too powerful to inherit`);
139
163
  }
140
164
  if (src.permission !== undefined) {
141
- log("dropping permission block from a package-supplied agent: too powerful to inherit");
165
+ log(`dropping permission block from agent "${agentName}" supplied by package "${pkgName}": too powerful to inherit`);
142
166
  }
143
167
  if (!agent.description && !agent.prompt)
144
168
  return null;
@@ -150,17 +174,43 @@ function toAgentConfig(raw) {
150
174
  // 3. a legacy Claude Code plugin shim: `.claude-plugin/plugin.json` `agents`
151
175
  // plus `agents/<name>/AGENTS.md` when no systemPrompt is declared.
152
176
  // Returns a stable, de-duplicated list keyed by agent name.
177
+ //
178
+ // Cached as a whole per package, fingerprinted on pkg.root: this function's
179
+ // own per-file cachedRead calls (below) already skip re-parsing an unchanged
180
+ // *file*, but still pay a readdirSync + containment check (2x realpathSync)
181
+ // per candidate file on every call. A marketplace package that ships many
182
+ // flat agent .md files directly in its root (the agency-agents layout) makes
183
+ // that per-file overhead the dominant remaining cost even on an otherwise
184
+ // fully warm run — skipping the whole function on an unchanged package root
185
+ // avoids it entirely, the same way discovery-cache.ts's walk-skip avoids
186
+ // re-walking an unchanged marketplace tree.
153
187
  export function readAgents(pkg) {
188
+ const fingerprint = fingerprintTree(pkg.root);
189
+ const key = JSON.stringify(["agents", pkg.root]);
190
+ const cached = getCachedValue(key, fingerprint);
191
+ if (cached)
192
+ return cached;
193
+ const result = readAgentsUncached(pkg);
194
+ setCachedValue(key, fingerprint, result);
195
+ return result;
196
+ }
197
+ function readAgentsUncached(pkg) {
154
198
  const out = new Map();
155
- const manifest = asRecord(readJson(join(pkg.root, "plugin.json")));
199
+ const manifest = asRecord(readContainedJson(pkg.root, join(pkg.root, "plugin.json")));
156
200
  const extensions = asRecord(manifest?.extensions);
157
201
  const opencodeExt = asRecord(extensions?.[OPENCODE_NS]);
158
202
  const manifestAgents = asRecord(opencodeExt?.agents);
159
203
  if (manifestAgents) {
160
204
  for (const [name, raw] of Object.entries(manifestAgents)) {
205
+ // Manifest agent keys are package-supplied input: gate the name before
206
+ // it becomes any config key (applyConfigPatch writes config.agent[name]).
207
+ if (!validateName(name)) {
208
+ log(`skipping manifest agent key for package "${pkg.name}" (${pkg.source}): invalid name "${name}" (must match the identifier pattern and not be a prototype-chain key)`);
209
+ continue;
210
+ }
161
211
  if (out.has(name))
162
212
  continue;
163
- const agent = toAgentConfig(raw);
213
+ const agent = toAgentConfig(raw, pkg.name, name);
164
214
  if (agent)
165
215
  out.set(name, agent);
166
216
  }
@@ -177,16 +227,28 @@ export function readAgents(pkg) {
177
227
  if (!entry.endsWith(".json"))
178
228
  continue;
179
229
  const name = entry.slice(0, -".json".length);
230
+ // Extension-dir filenames are package-supplied input: gate the name before
231
+ // it becomes any config key.
232
+ if (!validateName(name)) {
233
+ log(`skipping extension-dir agent file for package "${pkg.name}" (${pkg.source}): invalid name "${name}" (must match the identifier pattern and not be a prototype-chain key)`);
234
+ continue;
235
+ }
180
236
  if (out.has(name))
181
237
  continue;
182
- const agent = toAgentConfig(readJson(join(extDir, entry)));
238
+ const agent = toAgentConfig(readContainedJson(pkg.root, join(extDir, entry)), pkg.name, name);
183
239
  if (agent)
184
240
  out.set(name, agent);
185
241
  }
186
- const claudeManifest = asRecord(readJson(join(pkg.root, ".claude-plugin", "plugin.json")));
242
+ const claudeManifest = asRecord(readContainedJson(pkg.root, join(pkg.root, ".claude-plugin", "plugin.json")));
187
243
  const claudeAgents = asRecord(claudeManifest?.agents);
188
244
  if (claudeAgents) {
189
245
  for (const [name, raw] of Object.entries(claudeAgents)) {
246
+ // Shim manifest agent names are package-supplied legacy input: gate them
247
+ // before they become config keys or path segments (agents/<name>/AGENTS.md).
248
+ if (!validateName(name)) {
249
+ log(`skipping shimmed agent key for package "${pkg.name}" (${pkg.source}): invalid name "${name}" (must match the identifier pattern and not be a prototype-chain key)`);
250
+ continue;
251
+ }
190
252
  if (out.has(name))
191
253
  continue;
192
254
  const src = asRecord(raw);
@@ -197,11 +259,17 @@ export function readAgents(pkg) {
197
259
  agent.prompt = src.systemPrompt;
198
260
  }
199
261
  else {
200
- try {
201
- agent.prompt = readFileSync(join(pkg.root, "agents", name, "AGENTS.md"), "utf8");
202
- }
203
- catch {
204
- // No prompt file; the description alone is enough to register.
262
+ // AGENTS.md is package-supplied prompt content: only read it when it
263
+ // resolves inside the package, so a symlinked shim cannot pull in an
264
+ // outside file's bytes.
265
+ const promptPath = resolveContained(pkg.root, join(pkg.root, "agents", name, "AGENTS.md"));
266
+ if (promptPath) {
267
+ try {
268
+ agent.prompt = readFileSync(promptPath, "utf8");
269
+ }
270
+ catch {
271
+ // No prompt file; the description alone is enough to register.
272
+ }
205
273
  }
206
274
  }
207
275
  if (typeof src.model === "string")
@@ -228,20 +296,36 @@ export function readAgents(pkg) {
228
296
  if (!entry.endsWith(".md"))
229
297
  continue;
230
298
  const name = entry.slice(0, -".md".length);
299
+ // Flat agent filenames are package-supplied input: gate the name before
300
+ // it becomes any config key.
301
+ if (!validateName(name)) {
302
+ log(`skipping flat agent file for package "${pkg.name}" (${pkg.source}): invalid name "${name}" (must match the identifier pattern and not be a prototype-chain key)`);
303
+ continue;
304
+ }
231
305
  if (out.has(name))
232
306
  continue;
233
- let content;
307
+ // Flat agent files are package-supplied prompt content: only read one
308
+ // when it resolves inside the package, so a symlinked .md cannot pull in
309
+ // an outside file's bytes.
310
+ const contained = resolveContained(pkg.root, join(flatAgentsDir, entry));
311
+ if (!contained)
312
+ continue;
313
+ let parsed;
234
314
  try {
235
- content = readFileSync(join(flatAgentsDir, entry), "utf8");
315
+ parsed = cachedRead("flat-agent-md", contained, (content) => {
316
+ // Bare .md files in the package root may be docs (README.md); only
317
+ // treat them as agents when they carry a frontmatter block.
318
+ if (isRoot && !/^---\s*\n/.test(content))
319
+ return null;
320
+ return parseAgentMarkdown(content);
321
+ });
236
322
  }
237
323
  catch {
238
324
  continue;
239
325
  }
240
- // Bare .md files in the package root may be docs (README.md); only treat
241
- // them as agents when they carry a frontmatter block.
242
- if (isRoot && !/^---\s*\n/.test(content))
326
+ if (!parsed)
243
327
  continue;
244
- const { description, color, body } = parseAgentMarkdown(content);
328
+ const { description, color, body } = parsed;
245
329
  if (!description && !body)
246
330
  continue;
247
331
  const agent = {};
@@ -1 +1 @@
1
- {"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACvF,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAkBlD,2EAA2E;AAC3E,iFAAiF;AACjF,MAAM,WAAW,GAAG,cAAc,CAAC;AAEnC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;AAEtD,iFAAiF;AACjF,+EAA+E;AAC/E,gFAAgF;AAChF,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,SAAS;IACT,WAAW;IACX,QAAQ;IACR,SAAS;IACT,SAAS;IACT,OAAO;IACP,MAAM;CACP,CAAC,CAAC;AAEH,6EAA6E;AAC7E,+EAA+E;AAC/E,yDAAyD;AACzD,MAAM,WAAW,GAA2B;IAC1C,GAAG,EAAE,SAAS;IACd,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IACf,SAAS,EAAE,SAAS;IACpB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,SAAS;IACtB,YAAY,EAAE,SAAS;IACvB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,eAAe,EAAE,SAAS;IAC1B,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,SAAS;IAChB,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,KAAK,EAAE,SAAS;CACjB,CAAC;AAEF,8EAA8E;AAC9E,4EAA4E;AAC5E,2CAA2C;AAC3C,SAAS,cAAc,CAAC,GAAuB;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAClD,yEAAyE;IACzE,IAAI,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;IACnE,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,GAAG,CAAC,oCAAoC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACjE,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAChD,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,4EAA4E;AAC5E,+EAA+E;AAC/E,0EAA0E;AAC1E,2EAA2E;AAC3E,mCAAmC;AACnC,SAAS,iBAAiB,CAAC,IAAY,EAAE,IAAY;IACnD,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC;AAC7B,CAAC;AAED,8EAA8E;AAC9E,2EAA2E;AAC3E,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,0EAA0E;AAC1E,SAAS,aAAa,CAAC,GAAY,EAAE,OAAe,EAAE,SAAiB;IACrE,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,KAAK,GAAgB,EAAE,CAAC;IAE9B,MAAM,WAAW,GAAG,CAAC,GAAiD,EAAsB,EAAE,CAC5F,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAE,GAAG,CAAC,GAAG,CAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAClE,MAAM,WAAW,GAAG,CAAC,GAAyC,EAAsB,EAAE,CACpF,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAW,CAAC;QACjE,CAAC,CAAE,GAAG,CAAC,GAAG,CAAY;QACtB,CAAC,CAAC,SAAS,CAAC;IAEhB,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IACzC,IAAI,KAAK;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC/B,IAAI,MAAM;QAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAClC,IAAI,WAAW;QAAE,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IACjD,IAAI,KAAK;QAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC/B,IAAI,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;IAC/D,IAAI,IAAI,KAAK,SAAS;QAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IAC3C,IAAI,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IACtD,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,SAAS;QAAE,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;IAClE,yEAAyE;IACzE,2EAA2E;IAC3E,uEAAuE;IACvE,oEAAoE;IACpE,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACxD,IAAI,GAAG,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC5B,GAAG,CACD,kBAAkB,GAAG,CAAC,IAAI,iBAAiB,SAAS,0BAA0B,OAAO,wCAAwC,CAC9H,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC;IAC1B,CAAC;IACD,sEAAsE;IACtE,2EAA2E;IAC3E,6DAA6D;IAC7D,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,SAAS,CAAC,EAAE,CAAC;QAC9E,GAAG,CACD,8BAA8B,SAAS,0BAA0B,OAAO,4BAA4B,CACrG,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACjC,GAAG,CACD,yCAAyC,SAAS,0BAA0B,OAAO,4BAA4B,CAChH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACrD,OAAO,KAAK,CAAC;AACf,CAAC;AAID,uDAAuD;AACvD,2EAA2E;AAC3E,mFAAmF;AACnF,+EAA+E;AAC/E,wEAAwE;AACxE,4DAA4D;AAC5D,EAAE;AACF,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,0EAA0E;AAC1E,6EAA6E;AAC7E,0EAA0E;AAC1E,4EAA4E;AAC5E,yEAAyE;AACzE,4CAA4C;AAC5C,MAAM,UAAU,UAAU,CAAC,GAAkB;IAC3C,MAAM,WAAW,GAAG,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,cAAc,CAAmB,GAAG,EAAE,WAAW,CAAC,CAAC;IAClE,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACvC,cAAc,CAAC,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,kBAAkB,CAAC,GAAkB;IAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuB,CAAC;IAE3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAClD,MAAM,WAAW,GAAG,QAAQ,CAAC,UAAU,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;IACxD,MAAM,cAAc,GAAG,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IACrD,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;YACzD,uEAAuE;YACvE,0EAA0E;YAC1E,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,GAAG,CACD,4CAA4C,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,MAAM,oBAAoB,IAAI,wEAAwE,CACrK,CAAC;gBACF,SAAS;YACX,CAAC;YACD,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5B,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjD,IAAI,KAAK;gBAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,UAAU,GAAa,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,GAAG,EAAE,CAAC;IAClB,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC7C,2EAA2E;QAC3E,6BAA6B;QAC7B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,GAAG,CACD,kDAAkD,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,MAAM,oBAAoB,IAAI,wEAAwE,CAC3K,CAAC;YACF,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5B,MAAM,KAAK,GAAG,aAAa,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9F,IAAI,KAAK;YAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,cAAc,GAAG,QAAQ,CAC7B,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,gBAAgB,EAAE,aAAa,CAAC,CAAC,CAC7E,CAAC;IACF,MAAM,YAAY,GAAG,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IACtD,IAAI,YAAY,EAAE,CAAC;QACjB,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YACvD,yEAAyE;YACzE,6EAA6E;YAC7E,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,GAAG,CACD,2CAA2C,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,MAAM,oBAAoB,IAAI,wEAAwE,CACpK,CAAC;gBACF,SAAS;YACX,CAAC;YACD,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5B,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC1B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ;gBAAE,SAAS;YAC1D,MAAM,KAAK,GAAgB,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;YAC5D,IAAI,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC;gBAC7D,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,qEAAqE;gBACrE,qEAAqE;gBACrE,wBAAwB;gBACxB,MAAM,UAAU,GAAG,gBAAgB,CACjC,GAAG,CAAC,IAAI,EACR,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,CAAC,CAC5C,CAAC;gBACF,IAAI,UAAU,EAAE,CAAC;oBACf,IAAI,CAAC;wBACH,KAAK,CAAC,MAAM,GAAG,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;oBAClD,CAAC;oBAAC,MAAM,CAAC;wBACP,+DAA+D;oBACjE,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ;gBAAE,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YAC3D,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,WAAW;gBAAE,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,sCAAsC;IACtC,MAAM,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IACvD,KAAK,MAAM,aAAa,IAAI,SAAS,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,aAAa,KAAK,GAAG,CAAC,IAAI,CAAC;QAC1C,IAAI,WAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,WAAW,GAAG,WAAW,CAAC,aAAa,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,SAAS;YACrC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC3C,wEAAwE;YACxE,6BAA6B;YAC7B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,GAAG,CACD,yCAAyC,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC,MAAM,oBAAoB,IAAI,wEAAwE,CAClK,CAAC;gBACF,SAAS;YACX,CAAC;YACD,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5B,sEAAsE;YACtE,yEAAyE;YACzE,2BAA2B;YAC3B,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,CAAC;YACzE,IAAI,CAAC,SAAS;gBAAE,SAAS;YACzB,IAAI,MAAqE,CAAC;YAC1E,IAAI,CAAC;gBACH,MAAM,GAAG,UAAU,CAAC,eAAe,EAAE,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE;oBAC1D,mEAAmE;oBACnE,4DAA4D;oBAC5D,IAAI,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC;wBAAE,OAAO,IAAI,CAAC;oBACtD,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBACrC,CAAC,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,CAAC,MAAM;gBAAE,SAAS;YACtB,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;YAC5C,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpC,MAAM,KAAK,GAAgB,EAAE,CAAC;YAC9B,IAAI,WAAW;gBAAE,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;YACjD,IAAI,KAAK;gBAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;YAC/B,IAAI,IAAI;gBAAE,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;YAC9B,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,8EAA8E;AAC9E,iEAAiE;AACjE,SAAS,kBAAkB,CAAC,OAAe;IAKzC,MAAM,CAAC,GAAG,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,CAAC,GAAW,EAAsB,EAAE;QAChD,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,eAAe,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9D,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,CAAC,CAAC;IACF,MAAM,WAAW,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/C,OAAO,EAAE,WAAW,EAAE,WAAW,IAAI,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAChE,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare function pluginCacheRoot(): string;
2
+ export declare function _resetFileCacheForTests(): void;
3
+ export declare function cachedRead<T>(kind: string, path: string, parse: (content: string) => T): T;
4
+ export declare function flushFileCache(): void;
5
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAqCA,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAyBD,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAgBD,wBAAgB,UAAU,CAAC,CAAC,EAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,GAC5B,CAAC,CAaH;AAMD,wBAAgB,cAAc,IAAI,IAAI,CAWrC"}
package/dist/cache.js ADDED
@@ -0,0 +1,94 @@
1
+ import { mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ const CACHE_FILE_NAME = "discovery-file-cache.json";
5
+ // Bump when the shape of a cached `value` changes, so an old on-disk cache
6
+ // from a prior plugin version is discarded instead of misread.
7
+ const CACHE_VERSION = 1;
8
+ let store = null;
9
+ let dirty = false;
10
+ // Deliberately its own root, separate from {state}/opencode/plugin-data/:
11
+ // that tree is reserved for *discovered* packages' own data (created only
12
+ // when a package's mcp.json is actually processed), and several tests assert
13
+ // it stays untouched when discovery finds nothing that needs it. This cache
14
+ // belongs to the plugin itself, not to anything it discovers. Exported so
15
+ // other plugin-owned caches (discovery-cache.ts) share one root instead of
16
+ // inventing their own convention.
17
+ export function pluginCacheRoot() {
18
+ const base = process.env.XDG_CACHE_HOME || join(homedir(), ".cache");
19
+ return join(base, "opencode-skill-autodiscovery");
20
+ }
21
+ function cacheFilePath() {
22
+ return join(pluginCacheRoot(), CACHE_FILE_NAME);
23
+ }
24
+ function loadStore() {
25
+ if (store)
26
+ return store;
27
+ try {
28
+ const raw = JSON.parse(readFileSync(cacheFilePath(), "utf8"));
29
+ store =
30
+ raw && raw.version === CACHE_VERSION && raw.entries && typeof raw.entries === "object"
31
+ ? raw.entries
32
+ : {};
33
+ }
34
+ catch {
35
+ store = {};
36
+ }
37
+ return store;
38
+ }
39
+ // Test-only seam: drops the in-memory store so the next cachedRead/flush
40
+ // reloads from disk (or starts empty) instead of reusing state left over
41
+ // from a previous test's HOME. Production code never calls this: one
42
+ // opencode process makes exactly one config() call, so a process-lifetime
43
+ // singleton is the right scope there.
44
+ export function _resetFileCacheForTests() {
45
+ store = null;
46
+ dirty = false;
47
+ }
48
+ // Reads `path` and feeds its content to `parse`, reusing a previous result
49
+ // when the file's (mtimeMs, size) match the last successful cachedRead of the
50
+ // same (kind, path) pair. Throws exactly when `readFileSync`/`statSync` would
51
+ // have thrown (missing file, permission error, etc.) — existing callers
52
+ // already wrap those in try/catch, so behavior is unchanged when nothing is
53
+ // cached yet. `parse` must be pure and return a JSON-serializable value: it
54
+ // round-trips through the on-disk cache verbatim.
55
+ //
56
+ // `kind` namespaces the cache entry by what `parse` extracts, not just which
57
+ // file: the same file is read for different purposes at different call sites
58
+ // (e.g. "does this .md have agent frontmatter" vs. "the parsed agent from
59
+ // this .md"), and those must never share one cached value. The key is built
60
+ // with JSON.stringify (not string concatenation) so no separator choice can
61
+ // ever collide with a path or kind that happens to contain it.
62
+ export function cachedRead(kind, path, parse) {
63
+ const st = statSync(path);
64
+ const key = JSON.stringify([kind, path]);
65
+ const s = loadStore();
66
+ const cached = s[key];
67
+ if (cached && cached.mtimeMs === st.mtimeMs && cached.size === st.size) {
68
+ return cached.value;
69
+ }
70
+ const content = readFileSync(path, "utf8");
71
+ const value = parse(content);
72
+ s[key] = { mtimeMs: st.mtimeMs, size: st.size, value };
73
+ dirty = true;
74
+ return value;
75
+ }
76
+ // Persists the in-memory cache to disk when it changed. Best-effort, like
77
+ // every other filesystem side effect in this codebase: a failed write is
78
+ // swallowed rather than surfaced, since caching is an optimization and must
79
+ // never be able to break discovery.
80
+ export function flushFileCache() {
81
+ if (!dirty || !store)
82
+ return;
83
+ try {
84
+ const path = cacheFilePath();
85
+ mkdirSync(dirname(path), { recursive: true });
86
+ const payload = { version: CACHE_VERSION, entries: store };
87
+ writeFileSync(path, JSON.stringify(payload));
88
+ dirty = false;
89
+ }
90
+ catch {
91
+ // Non-fatal: the next run just re-reads everything.
92
+ }
93
+ }
94
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { PluginPackage } from "./discovery.js";
2
+ export declare function _resetDiscoveryCacheForTests(): void;
3
+ export declare function fingerprintTree(root: string): string;
4
+ export declare function getCachedPackages(key: string, fingerprint: string): PluginPackage[] | null;
5
+ export declare function setCachedPackages(key: string, fingerprint: string, packages: PluginPackage[]): void;
6
+ export declare function getCachedValue<T>(key: string, fingerprint: string): T | null;
7
+ export declare function setCachedValue<T>(key: string, fingerprint: string, value: T): void;
8
+ export declare function flushDiscoveryCache(): void;
9
+ //# sourceMappingURL=discovery-cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-cache.d.ts","sourceRoot":"","sources":["../src/discovery-cache.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AA+DpD,wBAAgB,4BAA4B,IAAI,IAAI,CAGnD;AAcD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOpD;AA2BD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,GAAG,IAAI,CAE1F;AAKD,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,aAAa,EAAE,GACxB,IAAI,CAEN;AAWD,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAG5E;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAGlF;AAQD,wBAAgB,mBAAmB,IAAI,IAAI,CAa1C"}
@@ -0,0 +1,161 @@
1
+ import { createHash } from "node:crypto";
2
+ import { mkdirSync, readdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
3
+ import { dirname, join, relative } from "node:path";
4
+ import { pluginCacheRoot } from "./cache.js";
5
+ // findPluginRoots' real walk is the expensive part of a scan: at every
6
+ // directory it calls hasPluginLayout -> hasRootAgentFiles, which reads every
7
+ // flat *.md file's content to check its frontmatter (cache.ts's cachedRead
8
+ // avoids re-parsing an unchanged file's bytes, but the walk still visits
9
+ // every directory and opens every candidate file on every single run). For a
10
+ // large, mostly-unchanged tree (a synced Claude/VS Code plugin marketplace),
11
+ // that per-directory cost dominates opencode's startup time.
12
+ //
13
+ // This module is a second, coarser cache layer in front of the walk itself:
14
+ // fingerprint the subtree cheaply (readdirSync + statSync only, no content
15
+ // reads, no containment/symlink-resolution overhead) and let the caller skip
16
+ // the real walk entirely when the fingerprint matches the last run's. Pure
17
+ // primitives only — no dependency on discovery.ts's walk functions, so
18
+ // discovery.ts can depend on this module without a cycle; the glue that
19
+ // actually runs findPluginRoots on a miss lives in discovery.ts itself.
20
+ const CACHE_FILE_NAME = "discovery-root-cache.json";
21
+ // Bumped from 1 to 2 when the per-entry field storing the cached value was
22
+ // renamed from `packages` (PluginPackage[]-only) to the generic `value`
23
+ // (any JSON-serializable result — readAgents' cache reuses this same store).
24
+ // A version-1 file on disk is now correctly treated as absent rather than
25
+ // misread with the wrong field name.
26
+ const CACHE_VERSION = 2;
27
+ // Mirrors discovery.ts's MAX_WALK_DEPTH: this is a separate, cheaper walk
28
+ // (see fingerprintTree below), but it must bound depth the same way for the
29
+ // same reason — a pathological or cyclic tree must not grow this pass
30
+ // unboundedly, even though (unlike the real walk) it does not resolve
31
+ // symlinks to detect cycles precisely. A cycle just gets fingerprinted up to
32
+ // this depth and then stops, exactly like the real walk's own documented
33
+ // "belt-and-braces, not load-bearing" depth cap.
34
+ const MAX_FINGERPRINT_DEPTH = 16;
35
+ let store = null;
36
+ let dirty = false;
37
+ function cacheFilePath() {
38
+ return join(pluginCacheRoot(), CACHE_FILE_NAME);
39
+ }
40
+ function loadStore() {
41
+ if (store)
42
+ return store;
43
+ try {
44
+ const raw = JSON.parse(readFileSync(cacheFilePath(), "utf8"));
45
+ store =
46
+ raw && raw.version === CACHE_VERSION && raw.entries && typeof raw.entries === "object"
47
+ ? raw.entries
48
+ : {};
49
+ }
50
+ catch {
51
+ store = {};
52
+ }
53
+ return store;
54
+ }
55
+ // Test-only seam, same rationale as cache.ts's _resetFileCacheForTests: one
56
+ // opencode process makes one config() call, so the module-level singleton is
57
+ // the right scope in production; tests need to force a reload between cases
58
+ // that reuse the same HOME.
59
+ export function _resetDiscoveryCacheForTests() {
60
+ store = null;
61
+ dirty = false;
62
+ }
63
+ // A cheap, content-free signature of everything a full walk of `root` would
64
+ // visit: every directory's direct children, keyed by (path relative to root,
65
+ // file-or-dir, mtimeMs, size), hashed. Any add, remove, rename, or content
66
+ // edit anywhere in the subtree changes at least one child's stat (a write
67
+ // changes the file's own mtime/size; an add/remove/rename changes its parent
68
+ // directory's mtime) and so changes this hash — there is no staleness
69
+ // window, only a cheaper way to notice nothing changed.
70
+ //
71
+ // Deliberately skips realpathSync: that is precisely the overhead the real
72
+ // walk pays for its containment/symlink-cycle guarantees, and this pass does
73
+ // not need those guarantees — it only decides whether to trust a cached
74
+ // *result* of the real (fully-guarded) walk, never emits a path itself.
75
+ export function fingerprintTree(root) {
76
+ const parts = [];
77
+ walkFingerprint(root, root, parts, 0);
78
+ parts.sort();
79
+ const hash = createHash("sha1");
80
+ for (const part of parts)
81
+ hash.update(part).update("\n");
82
+ return hash.digest("hex");
83
+ }
84
+ function walkFingerprint(root, dir, parts, depth) {
85
+ if (depth > MAX_FINGERPRINT_DEPTH)
86
+ return;
87
+ let entries;
88
+ try {
89
+ entries = readdirSync(dir);
90
+ }
91
+ catch {
92
+ return;
93
+ }
94
+ for (const entry of entries) {
95
+ if (entry === ".git" || entry === "node_modules")
96
+ continue;
97
+ const full = join(dir, entry);
98
+ let st;
99
+ try {
100
+ st = statSync(full);
101
+ }
102
+ catch {
103
+ continue;
104
+ }
105
+ const isDir = st.isDirectory();
106
+ parts.push(`${relative(root, full)}:${isDir ? "d" : "f"}:${st.mtimeMs}:${st.size}`);
107
+ if (isDir)
108
+ walkFingerprint(root, full, parts, depth + 1);
109
+ }
110
+ }
111
+ // Returns the packages cached for `key` when its stored fingerprint matches
112
+ // `fingerprint`, or null on a miss (not cached yet, or the subtree changed).
113
+ export function getCachedPackages(key, fingerprint) {
114
+ return getCachedValue(key, fingerprint);
115
+ }
116
+ // Records `packages` as the result for `key` at `fingerprint`, so the next
117
+ // call with an unchanged fingerprint gets them back from getCachedPackages
118
+ // without re-walking.
119
+ export function setCachedPackages(key, fingerprint, packages) {
120
+ setCachedValue(key, fingerprint, packages);
121
+ }
122
+ // Generic form of the same fingerprint-gated cache, for any JSON-serializable
123
+ // result of a per-directory computation — not just a package list. Used by
124
+ // readAgents (agents.ts) to cache a whole package's extracted agents keyed by
125
+ // a fingerprint of that package's own root: a marketplace layout with few
126
+ // packages but many flat *.md files per package (the exact shape that caused
127
+ // the original hang) would otherwise re-run readdirSync + the per-file
128
+ // containment check for every file, every run, even once the top-level walk
129
+ // itself is fully cached — package roots are typically far smaller subtrees
130
+ // than the marketplace root, so fingerprinting one is cheap.
131
+ export function getCachedValue(key, fingerprint) {
132
+ const cached = loadStore()[key];
133
+ return cached && cached.fingerprint === fingerprint ? cached.value : null;
134
+ }
135
+ export function setCachedValue(key, fingerprint, value) {
136
+ loadStore()[key] = { fingerprint, value, cachedAt: new Date().toISOString() };
137
+ dirty = true;
138
+ }
139
+ // Persists the in-memory cache to disk when it changed, atomically (write to
140
+ // a pid-suffixed temp file, then rename over the real path) so a process
141
+ // killed mid-write can never leave a half-written cache file behind for the
142
+ // next run to trip over. Best-effort, like every other filesystem side
143
+ // effect in this codebase: a failed write is swallowed, and the next run
144
+ // just re-walks.
145
+ export function flushDiscoveryCache() {
146
+ if (!dirty || !store)
147
+ return;
148
+ try {
149
+ const path = cacheFilePath();
150
+ mkdirSync(dirname(path), { recursive: true });
151
+ const payload = { version: CACHE_VERSION, entries: store };
152
+ const tmp = `${path}.${process.pid}.tmp`;
153
+ writeFileSync(tmp, JSON.stringify(payload));
154
+ renameSync(tmp, path);
155
+ dirty = false;
156
+ }
157
+ catch {
158
+ // Non-fatal: the next run just re-walks and rebuilds the cache.
159
+ }
160
+ }
161
+ //# sourceMappingURL=discovery-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery-cache.js","sourceRoot":"","sources":["../src/discovery-cache.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,14 @@ export type { McpEntry } from "./mcp.js";
7
7
  export type PackageSource = "claude" | "vscode" | "opencode-cache" | "node_modules" | "extra";
8
8
  export type PluginPackage = {
9
9
  source: PackageSource;
10
+ /**
11
+ * Two-tier trust model. True when the content was installed or fetched
12
+ * deliberately via a host tool or opencode itself (claude/vscode manifests
13
+ * under home roots, opencode's package cache). False when present merely as
14
+ * a side effect (project node_modules, manifest-less walks, and any package
15
+ * reached through a user-supplied extra root).
16
+ */
17
+ trusted: boolean;
10
18
  name: string;
11
19
  root: string;
12
20
  skillDirs: string[];
@@ -21,18 +29,25 @@ export type SkillInfo = {
21
29
  };
22
30
  export type ConfigPatch = {
23
31
  skillPaths: string[];
32
+ skillTrust: Array<{
33
+ dir: string;
34
+ trusted: boolean;
35
+ }>;
24
36
  commands: Array<{
25
37
  name: string;
26
38
  description: string;
27
39
  template: string;
40
+ trusted: boolean;
28
41
  }>;
29
42
  mcp: Array<{
30
43
  key: string;
31
44
  entry: McpEntry;
45
+ trusted: boolean;
32
46
  }>;
33
47
  agents: Array<{
34
48
  name: string;
35
49
  agent: AgentConfig;
50
+ trusted: boolean;
36
51
  }>;
37
52
  };
38
53
  export type ConfigLike = {
@@ -47,23 +62,30 @@ export type ConfigLike = {
47
62
  agent?: Record<string, AgentConfig | undefined>;
48
63
  };
49
64
  export declare function contains(parent: string, child: string): boolean;
65
+ export declare function resolveContained(root: string, candidate: string): string | null;
50
66
  export declare function readSkillInfo(dir: string): SkillInfo | null;
51
- export declare function readPackage(root: string, source: PackageSource): PluginPackage | null;
67
+ export declare function readPackage(root: string, source: PackageSource, trusted?: boolean): PluginPackage | null;
52
68
  export declare function findSkillDirs(root: string, out: Set<string>, seen: Set<string>): void;
53
69
  export declare function findPluginRoots(root: string, out: string[]): void;
54
- export declare function packageFromDir(root: string, source: PackageSource): PluginPackage | null;
55
- export declare function collectVscodeManifest(out: PluginPackage[], installedJson: string): void;
56
- export declare function collectVscodeCache(out: PluginPackage[], cacheJson: string): void;
57
- export declare function collectVscode(out: PluginPackage[], extra: string[]): void;
58
- export declare function collectClaudeManifest(out: PluginPackage[], installedJson: string): void;
59
- export declare function collectClaude(out: PluginPackage[]): void;
70
+ export declare function packageFromDir(root: string, source: PackageSource, trusted?: boolean): PluginPackage | null;
71
+ export declare function collectVscodeManifest(out: PluginPackage[], installedJson: string, exclude?: string[], trusted?: boolean): void;
72
+ export declare function collectVscodeCache(out: PluginPackage[], cacheJson: string, exclude?: string[], trusted?: boolean): void;
73
+ export declare function collectVscode(out: PluginPackage[], extra: string[], exclude?: string[]): void;
74
+ export declare function collectClaudeManifest(out: PluginPackage[], installedJson: string, exclude?: string[], trusted?: boolean): void;
75
+ export declare function collectClaude(out: PluginPackage[], exclude?: string[]): void;
60
76
  export declare function opencodeCacheRoot(): string;
61
- export declare function collectOpencodeCache(packagesRoot: string, out: PluginPackage[]): void;
62
- export declare function collectNodeModules(nodeModulesRoot: string, out: PluginPackage[]): void;
77
+ export declare function collectOpencodeCache(packagesRoot: string, out: PluginPackage[], exclude?: string[]): void;
78
+ export declare function collectNodeModules(nodeModulesRoot: string, out: PluginPackage[], trusted?: boolean, exclude?: string[]): void;
63
79
  export declare function planConfig(packages: PluginPackage[], taken?: {
64
80
  commands?: Iterable<string>;
65
81
  mcp?: Iterable<string>;
66
82
  agents?: Iterable<string>;
83
+ }, enabled?: {
84
+ mcp?: boolean;
85
+ agents?: boolean;
86
+ }, consent?: {
87
+ mcp?: Iterable<string>;
88
+ agents?: Iterable<string>;
67
89
  }): ConfigPatch;
68
90
  export declare function applyConfigPatch(config: ConfigLike, plan: ConfigPatch, enabled: {
69
91
  mcp: boolean;