@link-assistant/hive-mind 2.8.3 → 2.8.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 2.8.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 4373bc8: Stop treating JSON Schema, structured-data values, and package selectors as required Codex capabilities while preserving explicit skill and catalog plugin discovery.
8
+
3
9
  ## 2.8.3
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "2.8.3",
3
+ "version": "2.8.4",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -21,6 +21,9 @@ const NEGATED_REQUIREMENT = /\b(?:does\s+not\s+require|not\s+required|optional)\
21
21
  const PLUGIN_SELECTOR = /\b([a-z0-9][a-z0-9-]*@[a-z0-9][a-z0-9-]*(?:-remote)?)\b(?!\.[a-z])/gi;
22
22
  const NAMESPACED_SKILL = /\b([a-z0-9][a-z0-9-]*:[a-z0-9][a-z0-9-]*)\b/gi;
23
23
  const EXPLICIT_BARE_SKILL = /\$([a-z0-9][a-z0-9-]*)|`([a-z0-9][a-z0-9-]*)`\s+(?:agent\s+)?skill/gi;
24
+ const CAPABILITY_PREFIX = /\b(?:depend(?:s|ed)?\s+on|install|invoke|must\s+(?:install|invoke|use)|need(?:ed|s)?(?:\s+to)?(?:\s+(?:install|invoke|use))?|require(?:d|s)?(?:\s+to)?(?:\s+(?:install|invoke|use))?|use)\s+(?:(?:the|an?)\s+)?(?:(?:agent\s+)?skill\s+)?(?:named\s+)?[`$]?$/i;
25
+ const CAPABILITY_SUFFIX = /^`?\s+(?:agent\s+)?(?:skill|capability)\b/i;
26
+ const STRUCTURED_DATA_VALUES = new Set(['array', 'boolean', 'false', 'integer', 'null', 'number', 'object', 'string', 'true']);
24
27
 
25
28
  // Issue #2077: a capability name must contain at least one letter.
26
29
  //
@@ -44,6 +47,21 @@ const PROSE_TOKENS = new Set(['agent', 'caution', 'codex', 'default', 'error', '
44
47
 
45
48
  const isCapabilityToken = value => CAPABILITY_TOKEN.test(value) && !PROSE_TOKENS.has(value);
46
49
 
50
+ const hasExplicitCapabilityContext = (line, match) => {
51
+ const before = line.slice(0, match.index);
52
+ const after = line.slice(match.index + match[0].length);
53
+ if (CAPABILITY_SUFFIX.test(after) || before.endsWith('$')) return true;
54
+ const value = match[1].slice(match[1].indexOf(':') + 1).toLowerCase();
55
+ return !STRUCTURED_DATA_VALUES.has(value) && CAPABILITY_PREFIX.test(before);
56
+ };
57
+
58
+ const hasExplicitPluginContext = (line, match) => {
59
+ const before = line.slice(0, match.index);
60
+ const after = line.slice(match.index + match[0].length);
61
+ const marketplace = match[1].slice(match[1].indexOf('@') + 1);
62
+ return /(?:^|-)(?:bundled|curated|marketplace|remote)(?:-|$)/iu.test(marketplace) || /\bplugin\s+[`$]?$/iu.test(before) || /^`?\s+plugin\b/iu.test(after);
63
+ };
64
+
47
65
  export function isCapabilityName(value) {
48
66
  const token = String(value || '').toLowerCase();
49
67
  const separator = /[:@]/u.exec(token);
@@ -90,8 +108,16 @@ export function detectRequiredCodexCapabilities(text) {
90
108
  const line = rawLine.trim();
91
109
  if (!line || !REQUIREMENT_WORDS.test(line) || NEGATED_REQUIREMENT.test(line)) continue;
92
110
 
93
- for (const match of line.matchAll(PLUGIN_SELECTOR)) accept(plugins, normalizePluginSelector(match[1]), line);
94
- for (const match of line.matchAll(NAMESPACED_SKILL)) accept(skills, match[1].toLowerCase(), line);
111
+ for (const match of line.matchAll(PLUGIN_SELECTOR)) {
112
+ const selector = normalizePluginSelector(match[1]);
113
+ if (hasExplicitPluginContext(line, match)) accept(plugins, selector, line);
114
+ else rejected.push({ capability: selector, line });
115
+ }
116
+ for (const match of line.matchAll(NAMESPACED_SKILL)) {
117
+ const skill = match[1].toLowerCase();
118
+ if (hasExplicitCapabilityContext(line, match)) accept(skills, skill, line);
119
+ else rejected.push({ capability: skill, line });
120
+ }
95
121
  for (const match of line.matchAll(EXPLICIT_BARE_SKILL)) accept(skills, (match[1] || match[2]).toLowerCase(), line);
96
122
  }
97
123
 
@@ -310,6 +336,9 @@ async function provisionCodexCapabilities({ owner, repo, issueNumber, projectDir
310
336
  const baseCatalog = parseJsonCommand(baseCatalogResult, 'Codex plugin catalog discovery');
311
337
  const skillDirectories = [path.join(os.homedir(), '.agents', 'skills'), projectDir && path.join(projectDir, '.agents', 'skills')].filter(Boolean);
312
338
  const plugins = await resolveRequiredPlugins({ requirements, catalog: baseCatalog, skillDirectories });
339
+ for (const plugin of plugins) {
340
+ await log(` ✅ Verified ${plugin} in the Codex plugin catalog`, { verbose: true });
341
+ }
313
342
  if (plugins.length === 0) {
314
343
  await log(' ✅ Required Agent Skills are already available from standard skill directories');
315
344
  return { required: true, plugins, skills: requirements.skills, codexHome: null, baseCodexHome };