@skillsmith/core 0.12.1 → 0.12.2

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 (280) hide show
  1. package/CHANGELOG.md +155 -0
  2. package/README.md +2 -2
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/src/api/client.d.ts +5 -3
  5. package/dist/src/api/client.d.ts.map +1 -1
  6. package/dist/src/api/client.js +23 -33
  7. package/dist/src/api/client.js.map +1 -1
  8. package/dist/src/api/client.registry-sync.d.ts +28 -0
  9. package/dist/src/api/client.registry-sync.d.ts.map +1 -0
  10. package/dist/src/api/client.registry-sync.js +36 -0
  11. package/dist/src/api/client.registry-sync.js.map +1 -0
  12. package/dist/src/api/client.test.js +185 -0
  13. package/dist/src/api/client.test.js.map +1 -1
  14. package/dist/src/api/client.toSkill.d.ts +16 -0
  15. package/dist/src/api/client.toSkill.d.ts.map +1 -0
  16. package/dist/src/api/client.toSkill.js +46 -0
  17. package/dist/src/api/client.toSkill.js.map +1 -0
  18. package/dist/src/api/client.types.d.ts +22 -0
  19. package/dist/src/api/client.types.d.ts.map +1 -1
  20. package/dist/src/api/index.d.ts +1 -1
  21. package/dist/src/api/index.d.ts.map +1 -1
  22. package/dist/src/api/index.js.map +1 -1
  23. package/dist/src/api/schemas.d.ts +28 -0
  24. package/dist/src/api/schemas.d.ts.map +1 -1
  25. package/dist/src/api/schemas.js +13 -0
  26. package/dist/src/api/schemas.js.map +1 -1
  27. package/dist/src/audit/remote-audit.d.ts +85 -0
  28. package/dist/src/audit/remote-audit.d.ts.map +1 -1
  29. package/dist/src/audit/remote-audit.js +126 -3
  30. package/dist/src/audit/remote-audit.js.map +1 -1
  31. package/dist/src/audit/remote-audit.test.js +217 -1
  32. package/dist/src/audit/remote-audit.test.js.map +1 -1
  33. package/dist/src/config/index.d.ts +1 -0
  34. package/dist/src/config/index.d.ts.map +1 -1
  35. package/dist/src/config/index.js.map +1 -1
  36. package/dist/src/db/migration-runner.d.ts.map +1 -1
  37. package/dist/src/db/migration-runner.js +6 -0
  38. package/dist/src/db/migration-runner.js.map +1 -1
  39. package/dist/src/db/migrations/v18-skill-versions-real-content-hash.d.ts +36 -0
  40. package/dist/src/db/migrations/v18-skill-versions-real-content-hash.d.ts.map +1 -0
  41. package/dist/src/db/migrations/v18-skill-versions-real-content-hash.js +38 -0
  42. package/dist/src/db/migrations/v18-skill-versions-real-content-hash.js.map +1 -0
  43. package/dist/src/db/schema.d.ts +1 -1
  44. package/dist/src/db/schema.d.ts.map +1 -1
  45. package/dist/src/db/schema.js +3 -1
  46. package/dist/src/db/schema.js.map +1 -1
  47. package/dist/src/exports/services.d.ts +3 -7
  48. package/dist/src/exports/services.d.ts.map +1 -1
  49. package/dist/src/exports/services.install.d.ts +18 -0
  50. package/dist/src/exports/services.install.d.ts.map +1 -0
  51. package/dist/src/exports/services.install.js +62 -0
  52. package/dist/src/exports/services.install.js.map +1 -0
  53. package/dist/src/exports/services.js +12 -32
  54. package/dist/src/exports/services.js.map +1 -1
  55. package/dist/src/exports/types.d.ts +1 -1
  56. package/dist/src/exports/types.d.ts.map +1 -1
  57. package/dist/src/index.d.ts +5 -5
  58. package/dist/src/index.d.ts.map +1 -1
  59. package/dist/src/index.js +7 -4
  60. package/dist/src/index.js.map +1 -1
  61. package/dist/src/install/agent-config-merge.json.d.ts +5 -4
  62. package/dist/src/install/agent-config-merge.json.d.ts.map +1 -1
  63. package/dist/src/install/agent-config-merge.json.js +10 -9
  64. package/dist/src/install/agent-config-merge.json.js.map +1 -1
  65. package/dist/src/install/agent-config-merge.types.d.ts +11 -1
  66. package/dist/src/install/agent-config-merge.types.d.ts.map +1 -1
  67. package/dist/src/install/agent-config-merge.types.js.map +1 -1
  68. package/dist/src/install/agent-harness-targets.d.ts +30 -2
  69. package/dist/src/install/agent-harness-targets.d.ts.map +1 -1
  70. package/dist/src/install/agent-harness-targets.js +17 -0
  71. package/dist/src/install/agent-harness-targets.js.map +1 -1
  72. package/dist/src/install/agent-manifest-path-guard.d.ts +28 -3
  73. package/dist/src/install/agent-manifest-path-guard.d.ts.map +1 -1
  74. package/dist/src/install/agent-manifest-path-guard.js +59 -3
  75. package/dist/src/install/agent-manifest-path-guard.js.map +1 -1
  76. package/dist/src/install/agent-manifest-path-guard.test.js +27 -1
  77. package/dist/src/install/agent-manifest-path-guard.test.js.map +1 -1
  78. package/dist/src/install/agent-pack-installer.antigravity-mcp.d.ts +74 -0
  79. package/dist/src/install/agent-pack-installer.antigravity-mcp.d.ts.map +1 -0
  80. package/dist/src/install/agent-pack-installer.antigravity-mcp.js +106 -0
  81. package/dist/src/install/agent-pack-installer.antigravity-mcp.js.map +1 -0
  82. package/dist/src/install/agent-pack-installer.antigravity-mcp.test.d.ts +2 -0
  83. package/dist/src/install/agent-pack-installer.antigravity-mcp.test.d.ts.map +1 -0
  84. package/dist/src/install/agent-pack-installer.antigravity-mcp.test.js +157 -0
  85. package/dist/src/install/agent-pack-installer.antigravity-mcp.test.js.map +1 -0
  86. package/dist/src/install/agent-pack-installer.cursor-mcp.d.ts +53 -0
  87. package/dist/src/install/agent-pack-installer.cursor-mcp.d.ts.map +1 -0
  88. package/dist/src/install/agent-pack-installer.cursor-mcp.js +207 -0
  89. package/dist/src/install/agent-pack-installer.cursor-mcp.js.map +1 -0
  90. package/dist/src/install/agent-pack-installer.cursor-mcp.test.d.ts +2 -0
  91. package/dist/src/install/agent-pack-installer.cursor-mcp.test.d.ts.map +1 -0
  92. package/dist/src/install/agent-pack-installer.cursor-mcp.test.js +285 -0
  93. package/dist/src/install/agent-pack-installer.cursor-mcp.test.js.map +1 -0
  94. package/dist/src/install/agent-pack-installer.d.ts +8 -0
  95. package/dist/src/install/agent-pack-installer.d.ts.map +1 -1
  96. package/dist/src/install/agent-pack-installer.entry.d.ts +120 -3
  97. package/dist/src/install/agent-pack-installer.entry.d.ts.map +1 -1
  98. package/dist/src/install/agent-pack-installer.entry.js +166 -3
  99. package/dist/src/install/agent-pack-installer.entry.js.map +1 -1
  100. package/dist/src/install/agent-pack-installer.js +97 -3
  101. package/dist/src/install/agent-pack-installer.js.map +1 -1
  102. package/dist/src/install/agent-pack-installer.types.d.ts +27 -0
  103. package/dist/src/install/agent-pack-installer.types.d.ts.map +1 -1
  104. package/dist/src/install/agent-pack-installer.types.js +6 -0
  105. package/dist/src/install/agent-pack-installer.types.js.map +1 -1
  106. package/dist/src/install/agent-pack-installer.workspace-scope.test.d.ts +2 -0
  107. package/dist/src/install/agent-pack-installer.workspace-scope.test.d.ts.map +1 -0
  108. package/dist/src/install/agent-pack-installer.workspace-scope.test.js +148 -0
  109. package/dist/src/install/agent-pack-installer.workspace-scope.test.js.map +1 -0
  110. package/dist/src/install/agent-pack-uninstaller.d.ts +18 -7
  111. package/dist/src/install/agent-pack-uninstaller.d.ts.map +1 -1
  112. package/dist/src/install/agent-pack-uninstaller.js +59 -9
  113. package/dist/src/install/agent-pack-uninstaller.js.map +1 -1
  114. package/dist/src/install/agent-pack-uninstaller.test.js +74 -1
  115. package/dist/src/install/agent-pack-uninstaller.test.js.map +1 -1
  116. package/dist/src/install/fan-out.d.ts.map +1 -1
  117. package/dist/src/install/fan-out.js +6 -0
  118. package/dist/src/install/fan-out.js.map +1 -1
  119. package/dist/src/install/index.d.ts +2 -0
  120. package/dist/src/install/index.d.ts.map +1 -1
  121. package/dist/src/install/index.js +2 -0
  122. package/dist/src/install/index.js.map +1 -1
  123. package/dist/src/install/workspace-scope.d.ts +207 -0
  124. package/dist/src/install/workspace-scope.d.ts.map +1 -0
  125. package/dist/src/install/workspace-scope.js +275 -0
  126. package/dist/src/install/workspace-scope.js.map +1 -0
  127. package/dist/src/install/workspace-scope.test.d.ts +2 -0
  128. package/dist/src/install/workspace-scope.test.d.ts.map +1 -0
  129. package/dist/src/install/workspace-scope.test.js +378 -0
  130. package/dist/src/install/workspace-scope.test.js.map +1 -0
  131. package/dist/src/security/__tests__/pathValidation.test.js +30 -1
  132. package/dist/src/security/__tests__/pathValidation.test.js.map +1 -1
  133. package/dist/src/services/SubagentGenerator.client-profiles.d.ts +258 -0
  134. package/dist/src/services/SubagentGenerator.client-profiles.d.ts.map +1 -0
  135. package/dist/src/services/SubagentGenerator.client-profiles.js +260 -0
  136. package/dist/src/services/SubagentGenerator.client-profiles.js.map +1 -0
  137. package/dist/src/services/SubagentGenerator.d.ts +19 -41
  138. package/dist/src/services/SubagentGenerator.d.ts.map +1 -1
  139. package/dist/src/services/SubagentGenerator.helpers.d.ts +64 -0
  140. package/dist/src/services/SubagentGenerator.helpers.d.ts.map +1 -0
  141. package/dist/src/services/SubagentGenerator.helpers.js +228 -0
  142. package/dist/src/services/SubagentGenerator.helpers.js.map +1 -0
  143. package/dist/src/services/SubagentGenerator.js +66 -208
  144. package/dist/src/services/SubagentGenerator.js.map +1 -1
  145. package/dist/src/services/SubagentGenerator.types.d.ts +45 -0
  146. package/dist/src/services/SubagentGenerator.types.d.ts.map +1 -0
  147. package/dist/src/services/SubagentGenerator.types.js +14 -0
  148. package/dist/src/services/SubagentGenerator.types.js.map +1 -0
  149. package/dist/src/services/TransformationService.d.ts +18 -61
  150. package/dist/src/services/TransformationService.d.ts.map +1 -1
  151. package/dist/src/services/TransformationService.js +29 -17
  152. package/dist/src/services/TransformationService.js.map +1 -1
  153. package/dist/src/services/TransformationService.types.d.ts +74 -0
  154. package/dist/src/services/TransformationService.types.d.ts.map +1 -0
  155. package/dist/src/services/TransformationService.types.js +8 -0
  156. package/dist/src/services/TransformationService.types.js.map +1 -0
  157. package/dist/src/services/__tests__/SubagentGenerator.client-profiles.test.d.ts +5 -0
  158. package/dist/src/services/__tests__/SubagentGenerator.client-profiles.test.d.ts.map +1 -0
  159. package/dist/src/services/__tests__/SubagentGenerator.client-profiles.test.js +72 -0
  160. package/dist/src/services/__tests__/SubagentGenerator.client-profiles.test.js.map +1 -0
  161. package/dist/src/services/__tests__/SubagentGenerator.helpers.test.d.ts +2 -0
  162. package/dist/src/services/__tests__/SubagentGenerator.helpers.test.d.ts.map +1 -0
  163. package/dist/src/services/__tests__/SubagentGenerator.helpers.test.js +61 -0
  164. package/dist/src/services/__tests__/SubagentGenerator.helpers.test.js.map +1 -0
  165. package/dist/src/services/__tests__/SubagentGenerator.test.js +155 -0
  166. package/dist/src/services/__tests__/SubagentGenerator.test.js.map +1 -1
  167. package/dist/src/services/__tests__/TransformationService.test.js +48 -0
  168. package/dist/src/services/__tests__/TransformationService.test.js.map +1 -1
  169. package/dist/src/services/agent-pack/agent-pack.test.js +1 -0
  170. package/dist/src/services/agent-pack/agent-pack.test.js.map +1 -1
  171. package/dist/src/services/agent-pack/prompt-source.d.ts +1 -1
  172. package/dist/src/services/agent-pack/prompt-source.d.ts.map +1 -1
  173. package/dist/src/services/agent-pack/prompt-source.js +10 -3
  174. package/dist/src/services/agent-pack/prompt-source.js.map +1 -1
  175. package/dist/src/services/agent-pack/types.d.ts +26 -2
  176. package/dist/src/services/agent-pack/types.d.ts.map +1 -1
  177. package/dist/src/services/agent-pack/types.js +13 -0
  178. package/dist/src/services/agent-pack/types.js.map +1 -1
  179. package/dist/src/services/agent-tool-profile.d.ts.map +1 -1
  180. package/dist/src/services/agent-tool-profile.js +7 -0
  181. package/dist/src/services/agent-tool-profile.js.map +1 -1
  182. package/dist/src/services/agent-tool-profile.test.js +2 -2
  183. package/dist/src/services/skill-content-comparison.d.ts +71 -0
  184. package/dist/src/services/skill-content-comparison.d.ts.map +1 -0
  185. package/dist/src/services/skill-content-comparison.js +90 -0
  186. package/dist/src/services/skill-content-comparison.js.map +1 -0
  187. package/dist/src/services/skill-content-comparison.test.d.ts +6 -0
  188. package/dist/src/services/skill-content-comparison.test.d.ts.map +1 -0
  189. package/dist/src/services/skill-content-comparison.test.js +83 -0
  190. package/dist/src/services/skill-content-comparison.test.js.map +1 -0
  191. package/dist/src/services/skill-identity-classification.d.ts +202 -0
  192. package/dist/src/services/skill-identity-classification.d.ts.map +1 -0
  193. package/dist/src/services/skill-identity-classification.js +295 -0
  194. package/dist/src/services/skill-identity-classification.js.map +1 -0
  195. package/dist/src/services/skill-identity-classification.test.d.ts +6 -0
  196. package/dist/src/services/skill-identity-classification.test.d.ts.map +1 -0
  197. package/dist/src/services/skill-identity-classification.test.js +314 -0
  198. package/dist/src/services/skill-identity-classification.test.js.map +1 -0
  199. package/dist/src/services/skill-installation.content.d.ts.map +1 -1
  200. package/dist/src/services/skill-installation.content.js +6 -1
  201. package/dist/src/services/skill-installation.content.js.map +1 -1
  202. package/dist/src/services/skill-installation.helpers.d.ts +8 -15
  203. package/dist/src/services/skill-installation.helpers.d.ts.map +1 -1
  204. package/dist/src/services/skill-installation.helpers.js +11 -105
  205. package/dist/src/services/skill-installation.helpers.js.map +1 -1
  206. package/dist/src/services/skill-installation.helpers.test.js +106 -1
  207. package/dist/src/services/skill-installation.helpers.test.js.map +1 -1
  208. package/dist/src/services/skill-installation.service.js +1 -1
  209. package/dist/src/services/skill-installation.service.js.map +1 -1
  210. package/dist/src/services/skill-installation.types.d.ts +33 -0
  211. package/dist/src/services/skill-installation.types.d.ts.map +1 -1
  212. package/dist/src/services/skill-installation.types.js.map +1 -1
  213. package/dist/src/services/skill-installation.uninstall.d.ts +84 -0
  214. package/dist/src/services/skill-installation.uninstall.d.ts.map +1 -0
  215. package/dist/src/services/skill-installation.uninstall.js +252 -0
  216. package/dist/src/services/skill-installation.uninstall.js.map +1 -0
  217. package/dist/src/services/skill-manifest.d.ts +41 -0
  218. package/dist/src/services/skill-manifest.d.ts.map +1 -1
  219. package/dist/src/services/skill-manifest.js +93 -0
  220. package/dist/src/services/skill-manifest.js.map +1 -1
  221. package/dist/src/services/skill-manifest.test.js +27 -0
  222. package/dist/src/services/skill-manifest.test.js.map +1 -1
  223. package/dist/src/sync/SyncEngine.d.ts.map +1 -1
  224. package/dist/src/sync/SyncEngine.js +69 -77
  225. package/dist/src/sync/SyncEngine.js.map +1 -1
  226. package/dist/src/telemetry/agent-marker.d.ts +8 -0
  227. package/dist/src/telemetry/agent-marker.d.ts.map +1 -1
  228. package/dist/src/telemetry/agent-marker.js +7 -0
  229. package/dist/src/telemetry/agent-marker.js.map +1 -1
  230. package/dist/src/telemetry/agent-marker.test.js +7 -1
  231. package/dist/src/telemetry/agent-marker.test.js.map +1 -1
  232. package/dist/src/telemetry/index.d.ts +1 -1
  233. package/dist/src/telemetry/index.d.ts.map +1 -1
  234. package/dist/src/telemetry/index.js +1 -1
  235. package/dist/src/telemetry/index.js.map +1 -1
  236. package/dist/src/telemetry/wrap.d.ts +6 -0
  237. package/dist/src/telemetry/wrap.d.ts.map +1 -1
  238. package/dist/src/telemetry/wrap.js +65 -10
  239. package/dist/src/telemetry/wrap.js.map +1 -1
  240. package/dist/src/telemetry/wrap.test.js +81 -1
  241. package/dist/src/telemetry/wrap.test.js.map +1 -1
  242. package/dist/src/telemetry/wrap.tool-call-sink.test.d.ts +26 -0
  243. package/dist/src/telemetry/wrap.tool-call-sink.test.d.ts.map +1 -0
  244. package/dist/src/telemetry/wrap.tool-call-sink.test.js +162 -0
  245. package/dist/src/telemetry/wrap.tool-call-sink.test.js.map +1 -0
  246. package/dist/src/types/skill.d.ts +9 -1
  247. package/dist/src/types/skill.d.ts.map +1 -1
  248. package/dist/src/utils/index.d.ts +1 -1
  249. package/dist/src/utils/index.d.ts.map +1 -1
  250. package/dist/src/utils/index.js +1 -1
  251. package/dist/src/utils/index.js.map +1 -1
  252. package/dist/src/utils/version-check.d.ts +61 -0
  253. package/dist/src/utils/version-check.d.ts.map +1 -1
  254. package/dist/src/utils/version-check.js +78 -1
  255. package/dist/src/utils/version-check.js.map +1 -1
  256. package/dist/src/utils/version-check.test.js +130 -1
  257. package/dist/src/utils/version-check.test.js.map +1 -1
  258. package/dist/tests/db/migration-runner-race.test.js +19 -9
  259. package/dist/tests/db/migration-runner-race.test.js.map +1 -1
  260. package/dist/tests/install/fan-out.test.js +27 -0
  261. package/dist/tests/install/fan-out.test.js.map +1 -1
  262. package/dist/tests/sync/SyncEngine.abort.test.js +15 -11
  263. package/dist/tests/sync/SyncEngine.abort.test.js.map +1 -1
  264. package/dist/tests/sync/SyncEngine.status.test.js +1 -1
  265. package/dist/tests/sync/SyncEngine.status.test.js.map +1 -1
  266. package/dist/tests/sync/SyncEngine.test.d.ts +11 -2
  267. package/dist/tests/sync/SyncEngine.test.d.ts.map +1 -1
  268. package/dist/tests/sync/SyncEngine.test.js +164 -13
  269. package/dist/tests/sync/SyncEngine.test.js.map +1 -1
  270. package/dist/tests/unit/migrations/migration-v18.test.d.ts +16 -0
  271. package/dist/tests/unit/migrations/migration-v18.test.d.ts.map +1 -0
  272. package/dist/tests/unit/migrations/migration-v18.test.js +192 -0
  273. package/dist/tests/unit/migrations/migration-v18.test.js.map +1 -0
  274. package/dist/tests/unit/services/skill-installation.content.test.js +65 -1
  275. package/dist/tests/unit/services/skill-installation.content.test.js.map +1 -1
  276. package/dist/tests/unit/services/skill-installation.service.test.js +9 -8
  277. package/dist/tests/unit/services/skill-installation.service.test.js.map +1 -1
  278. package/dist/tests/unit/sync-engine.source-aware.test.js +5 -5
  279. package/dist/tests/unit/sync-engine.source-aware.test.js.map +1 -1
  280. package/package.json +2 -2
@@ -0,0 +1,64 @@
1
+ /**
2
+ * SMI-1788: Pure helper functions for SubagentGenerator — tool detection,
3
+ * trigger-phrase extraction, model selection, and Claude-tool-named
4
+ * guidance text. Split out under the 500-line standard (SMI-6276) following
5
+ * this directory's existing `.helpers.ts` convention (see
6
+ * SkillAnalyzer.helpers.ts / SkillDecomposer.helpers.ts).
7
+ */
8
+ import type { ToolUsageAnalysis } from './SkillAnalyzer.js';
9
+ import { type ClaudeModel } from './SubagentGenerator.types.js';
10
+ /**
11
+ * Tool detection patterns for analyzing skill content
12
+ */
13
+ export declare const TOOL_PATTERNS: Record<string, {
14
+ patterns: string[];
15
+ priority: number;
16
+ }>;
17
+ /**
18
+ * Minimum tools that most subagents need
19
+ */
20
+ export declare const BASE_TOOLS: string[];
21
+ /**
22
+ * SMI-1819: Maximum length for subagent names to prevent overly long identifiers
23
+ */
24
+ export declare const MAX_SUBAGENT_NAME_LENGTH = 100;
25
+ /**
26
+ * Generate tool usage guidelines for a subagent (Claude-named tools).
27
+ * Only used for clients whose `toolsPolicy` is `'claude-native'` — see
28
+ * `SubagentGenerator.client-profiles.ts` and `OMITTED_TOOLS_GUIDANCE`.
29
+ */
30
+ export declare function generateToolGuidelines(tools: string[]): string;
31
+ /**
32
+ * SMI-6276: fallback tool-usage guidance for any client whose companion
33
+ * subagent file does not carry Claude-named tools in its `tools:`
34
+ * frontmatter — either because the field is omitted entirely, or because it
35
+ * was translated into that client's OWN vocabulary (`mapped-array`, e.g.
36
+ * AntiGravity's `view_file`/`run_command`). Naming Claude-specific tool
37
+ * identifiers in this prose body would be misleading either way, so this
38
+ * stays generic. See `SubagentGenerator.client-profiles.ts`.
39
+ */
40
+ export declare const OMITTED_TOOLS_GUIDANCE = "- Use the tools available on this platform minimally and efficiently";
41
+ /**
42
+ * Generate CLAUDE.md integration snippet
43
+ *
44
+ * NOTE (SMI-6276): deliberately NOT client-parameterized — CLAUDE.md is
45
+ * inherently a Claude Code artifact regardless of which client the
46
+ * companion-agent FILE itself targets, so this always describes the
47
+ * Claude-side delegation recommendation. Out of this wave's scope; see
48
+ * `SubagentGenerator.client-profiles.ts`'s header for what IS in scope.
49
+ */
50
+ export declare function generateClaudeMdSnippet(skillName: string, description: string, triggerPhrases: string[], tools: string[], model: ClaudeModel): string;
51
+ /**
52
+ * Extract trigger phrases from skill description and content
53
+ */
54
+ export declare function extractTriggerPhrases(description: string, content: string): string[];
55
+ /**
56
+ * Determine optimal model for subagent
57
+ * SMI-1795: Uses CLAUDE_MODELS constants for type safety
58
+ */
59
+ export declare function determineModel(toolUsage: ToolUsageAnalysis, lineCount: number): ClaudeModel;
60
+ /**
61
+ * Detect tools needed from skill content
62
+ */
63
+ export declare function detectTools(content: string): string[];
64
+ //# sourceMappingURL=SubagentGenerator.helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubagentGenerator.helpers.d.ts","sourceRoot":"","sources":["../../../src/services/SubagentGenerator.helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAE9E;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAoDlF,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,UAAW,CAAA;AAElC;;GAEG;AACH,eAAO,MAAM,wBAAwB,MAAM,CAAA;AAE3C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CA6B9D;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,yEACqC,CAAA;AAExE;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EAAE,EACxB,KAAK,EAAE,MAAM,EAAE,EACf,KAAK,EAAE,WAAW,GACjB,MAAM,CA0BR;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAwDpF;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,CAgB3F;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAcrD"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * SMI-1788: Pure helper functions for SubagentGenerator — tool detection,
3
+ * trigger-phrase extraction, model selection, and Claude-tool-named
4
+ * guidance text. Split out under the 500-line standard (SMI-6276) following
5
+ * this directory's existing `.helpers.ts` convention (see
6
+ * SkillAnalyzer.helpers.ts / SkillDecomposer.helpers.ts).
7
+ */
8
+ import { CLAUDE_MODELS } from './SubagentGenerator.types.js';
9
+ /**
10
+ * Tool detection patterns for analyzing skill content
11
+ */
12
+ export const TOOL_PATTERNS = {
13
+ Read: {
14
+ patterns: ['read file', 'read the', 'examine', 'view file', 'Read tool', 'check file'],
15
+ priority: 1,
16
+ },
17
+ Write: {
18
+ patterns: ['write file', 'create file', 'save to', 'output to', 'Write tool', 'generate file'],
19
+ priority: 2,
20
+ },
21
+ Edit: {
22
+ patterns: [
23
+ 'edit file',
24
+ 'modify',
25
+ 'update file',
26
+ 'patch',
27
+ 'Edit tool',
28
+ 'change file',
29
+ 'refactor',
30
+ ],
31
+ priority: 2,
32
+ },
33
+ Bash: {
34
+ patterns: [
35
+ 'bash',
36
+ 'npm',
37
+ 'npx',
38
+ 'git',
39
+ 'docker',
40
+ 'yarn',
41
+ 'pnpm',
42
+ 'terminal',
43
+ 'shell',
44
+ 'command',
45
+ ],
46
+ priority: 3,
47
+ },
48
+ Grep: {
49
+ patterns: ['grep', 'search for', 'find text', 'pattern match', 'Grep tool', 'search in'],
50
+ priority: 1,
51
+ },
52
+ Glob: {
53
+ patterns: ['glob', 'find file', 'file pattern', 'list files', 'Glob tool', 'locate'],
54
+ priority: 1,
55
+ },
56
+ WebFetch: {
57
+ patterns: ['fetch', 'http', 'api call', 'url', 'WebFetch', 'download', 'request'],
58
+ priority: 2,
59
+ },
60
+ WebSearch: {
61
+ patterns: ['web search', 'search online', 'lookup online', 'WebSearch', 'search the web'],
62
+ priority: 2,
63
+ },
64
+ };
65
+ /**
66
+ * Minimum tools that most subagents need
67
+ */
68
+ export const BASE_TOOLS = ['Read'];
69
+ /**
70
+ * SMI-1819: Maximum length for subagent names to prevent overly long identifiers
71
+ */
72
+ export const MAX_SUBAGENT_NAME_LENGTH = 100;
73
+ /**
74
+ * Generate tool usage guidelines for a subagent (Claude-named tools).
75
+ * Only used for clients whose `toolsPolicy` is `'claude-native'` — see
76
+ * `SubagentGenerator.client-profiles.ts` and `OMITTED_TOOLS_GUIDANCE`.
77
+ */
78
+ export function generateToolGuidelines(tools) {
79
+ const guidelines = [];
80
+ if (tools.includes('Read')) {
81
+ guidelines.push('- **Read**: Use to examine files before modifications');
82
+ }
83
+ if (tools.includes('Write')) {
84
+ guidelines.push('- **Write**: Use for creating new files only');
85
+ }
86
+ if (tools.includes('Edit')) {
87
+ guidelines.push('- **Edit**: Use for modifying existing files');
88
+ }
89
+ if (tools.includes('Bash')) {
90
+ guidelines.push('- **Bash**: Use for command execution, prefer non-destructive commands');
91
+ }
92
+ if (tools.includes('Grep')) {
93
+ guidelines.push('- **Grep**: Use for searching file contents');
94
+ }
95
+ if (tools.includes('Glob')) {
96
+ guidelines.push('- **Glob**: Use for finding files by pattern');
97
+ }
98
+ if (tools.includes('WebFetch')) {
99
+ guidelines.push('- **WebFetch**: Use for fetching web content');
100
+ }
101
+ if (tools.includes('WebSearch')) {
102
+ guidelines.push('- **WebSearch**: Use for searching the web');
103
+ }
104
+ return guidelines.length > 0 ? guidelines.join('\n') : '- Use tools minimally and efficiently';
105
+ }
106
+ /**
107
+ * SMI-6276: fallback tool-usage guidance for any client whose companion
108
+ * subagent file does not carry Claude-named tools in its `tools:`
109
+ * frontmatter — either because the field is omitted entirely, or because it
110
+ * was translated into that client's OWN vocabulary (`mapped-array`, e.g.
111
+ * AntiGravity's `view_file`/`run_command`). Naming Claude-specific tool
112
+ * identifiers in this prose body would be misleading either way, so this
113
+ * stays generic. See `SubagentGenerator.client-profiles.ts`.
114
+ */
115
+ export const OMITTED_TOOLS_GUIDANCE = '- Use the tools available on this platform minimally and efficiently';
116
+ /**
117
+ * Generate CLAUDE.md integration snippet
118
+ *
119
+ * NOTE (SMI-6276): deliberately NOT client-parameterized — CLAUDE.md is
120
+ * inherently a Claude Code artifact regardless of which client the
121
+ * companion-agent FILE itself targets, so this always describes the
122
+ * Claude-side delegation recommendation. Out of this wave's scope; see
123
+ * `SubagentGenerator.client-profiles.ts`'s header for what IS in scope.
124
+ */
125
+ export function generateClaudeMdSnippet(skillName, description, triggerPhrases, tools, model) {
126
+ const triggerPatterns = triggerPhrases.length > 0
127
+ ? triggerPhrases.map((p) => `- "${p}"`).join('\n')
128
+ : '- [add trigger patterns]';
129
+ const exampleTask = triggerPhrases.length > 0 ? triggerPhrases[0] : `execute ${skillName} task`;
130
+ return `
131
+ ### Subagent Delegation: ${skillName}
132
+
133
+ When tasks match ${skillName} triggers, delegate to the ${skillName}-specialist
134
+ subagent instead of executing directly. This provides context isolation and
135
+ ~37-97% token savings.
136
+
137
+ **Trigger Patterns:**
138
+ ${triggerPatterns}
139
+
140
+ **Delegation Example:**
141
+ \`\`\`
142
+ Task("${skillName}-specialist", "${exampleTask}", "${skillName}-specialist")
143
+ \`\`\`
144
+
145
+ **Model:** ${model}
146
+ **Tools:** ${tools.join(', ')}
147
+ `;
148
+ }
149
+ /**
150
+ * Extract trigger phrases from skill description and content
151
+ */
152
+ export function extractTriggerPhrases(description, content) {
153
+ const phrases = [];
154
+ // Common trigger phrase patterns. CodeQL finding (SMI-6276, polynomial
155
+ // regex / ReDoS): the original patterns paired an optional word group
156
+ // (e.g. `(?:you\s+)?`) directly against a lazy wildcard capture
157
+ // (`(.+?)`) — since `.` also matches the letters/spaces the optional
158
+ // group matches, the engine has exponentially many ways to split
159
+ // ambiguous input (long runs of repeated words/spaces) between "the
160
+ // optional group matched" and "the wildcard consumed it instead".
161
+ // `textToSearch` includes up to 2000 chars of externally-authored
162
+ // SKILL.md content (a real untrusted-input path in a skill registry).
163
+ // Fix: bound each capture group to a small fixed max length instead of
164
+ // an unbounded lazy wildcard — extracted phrases are truncated to <=50
165
+ // chars a few lines below regardless, so this changes no real-world
166
+ // behavior, but caps worst-case backtracking work to a small constant
167
+ // instead of growing with input length.
168
+ const MAX_CANDIDATE_PHRASE_LENGTH = 60;
169
+ const patterns = [
170
+ new RegExp(`when\\s+(?:you\\s+)?(?:need\\s+to\\s+)?([^.,]{1,${MAX_CANDIDATE_PHRASE_LENGTH}})(?:[.,]|$)`, 'gi'),
171
+ new RegExp(`use\\s+(?:this\\s+)?(?:when|for)\\s+([^.,]{1,${MAX_CANDIDATE_PHRASE_LENGTH}})(?:[.,]|$)`, 'gi'),
172
+ new RegExp(`(?:helps?\\s+(?:you\\s+)?(?:to\\s+)?)?([^\\n]{1,${MAX_CANDIDATE_PHRASE_LENGTH}}?)(?:\\s+tasks?|\\s+operations?)`, 'gi'),
173
+ ];
174
+ const textToSearch = description + ' ' + content.slice(0, 2000); // Search first 2000 chars
175
+ for (const pattern of patterns) {
176
+ for (const match of textToSearch.matchAll(pattern)) {
177
+ const phrase = match[1].trim().toLowerCase();
178
+ if (phrase.length >= 5 && phrase.length <= 50 && !phrases.includes(phrase)) {
179
+ phrases.push(phrase);
180
+ }
181
+ }
182
+ }
183
+ // Extract from "trigger" or "invoke" mentions
184
+ const triggerMatch = content.match(/trigger[s]?\s*[:=]\s*["`']([^"`']+)["`']/gi);
185
+ if (triggerMatch) {
186
+ for (const match of triggerMatch) {
187
+ const phrase = match.replace(/trigger[s]?\s*[:=]\s*["`']/i, '').replace(/["`']$/, '');
188
+ if (!phrases.includes(phrase.toLowerCase())) {
189
+ phrases.push(phrase.toLowerCase());
190
+ }
191
+ }
192
+ }
193
+ return phrases.slice(0, 5); // Limit to 5 phrases
194
+ }
195
+ /**
196
+ * Determine optimal model for subagent
197
+ * SMI-1795: Uses CLAUDE_MODELS constants for type safety
198
+ */
199
+ export function determineModel(toolUsage, lineCount) {
200
+ // Haiku for simple, fast operations
201
+ if (toolUsage.detectedTools.length <= 2 && lineCount < 200) {
202
+ return CLAUDE_MODELS.HAIKU;
203
+ }
204
+ // Opus for complex, reasoning-heavy tasks
205
+ if (toolUsage.bashCommandCount > 5 ||
206
+ (toolUsage.fileReadCount > 3 && toolUsage.fileWriteCount > 3)) {
207
+ return CLAUDE_MODELS.OPUS;
208
+ }
209
+ // Sonnet for balanced workloads (default)
210
+ return CLAUDE_MODELS.SONNET;
211
+ }
212
+ /**
213
+ * Detect tools needed from skill content
214
+ */
215
+ export function detectTools(content) {
216
+ const lowerContent = content.toLowerCase();
217
+ const detectedTools = new Set(BASE_TOOLS);
218
+ for (const [tool, config] of Object.entries(TOOL_PATTERNS)) {
219
+ for (const pattern of config.patterns) {
220
+ if (lowerContent.includes(pattern.toLowerCase())) {
221
+ detectedTools.add(tool);
222
+ break;
223
+ }
224
+ }
225
+ }
226
+ return Array.from(detectedTools);
227
+ }
228
+ //# sourceMappingURL=SubagentGenerator.helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubagentGenerator.helpers.js","sourceRoot":"","sources":["../../../src/services/SubagentGenerator.helpers.ts"],"names":[],"mappings":"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"}
@@ -9,125 +9,69 @@
9
9
  *
10
10
  * Part of the Skillsmith Optimization Layer for transforming
11
11
  * community skills into more performant versions.
12
+ *
13
+ * SMI-6276 (Wave 6 Step 1): companion-agent frontmatter is now generated
14
+ * per TARGET CLIENT via `SubagentGenerator.client-profiles.ts` — this file
15
+ * no longer emits Claude-native tool names / a Claude `model:` value
16
+ * unconditionally for every client `COMPANION_AGENT_TARGETS` writes a
17
+ * companion file for. Types split to `.types.ts`, pure helpers split to
18
+ * `.helpers.ts` (500-line standard).
12
19
  */
13
- /**
14
- * SMI-1795: Claude model constants for type safety and consistency
15
- */
16
- export const CLAUDE_MODELS = {
17
- HAIKU: 'haiku',
18
- SONNET: 'sonnet',
19
- OPUS: 'opus',
20
- };
21
- /**
22
- * Tool detection patterns for analyzing skill content
23
- */
24
- const TOOL_PATTERNS = {
25
- Read: {
26
- patterns: ['read file', 'read the', 'examine', 'view file', 'Read tool', 'check file'],
27
- priority: 1,
28
- },
29
- Write: {
30
- patterns: ['write file', 'create file', 'save to', 'output to', 'Write tool', 'generate file'],
31
- priority: 2,
32
- },
33
- Edit: {
34
- patterns: [
35
- 'edit file',
36
- 'modify',
37
- 'update file',
38
- 'patch',
39
- 'Edit tool',
40
- 'change file',
41
- 'refactor',
42
- ],
43
- priority: 2,
44
- },
45
- Bash: {
46
- patterns: [
47
- 'bash',
48
- 'npm',
49
- 'npx',
50
- 'git',
51
- 'docker',
52
- 'yarn',
53
- 'pnpm',
54
- 'terminal',
55
- 'shell',
56
- 'command',
57
- ],
58
- priority: 3,
59
- },
60
- Grep: {
61
- patterns: ['grep', 'search for', 'find text', 'pattern match', 'Grep tool', 'search in'],
62
- priority: 1,
63
- },
64
- Glob: {
65
- patterns: ['glob', 'find file', 'file pattern', 'list files', 'Glob tool', 'locate'],
66
- priority: 1,
67
- },
68
- WebFetch: {
69
- patterns: ['fetch', 'http', 'api call', 'url', 'WebFetch', 'download', 'request'],
70
- priority: 2,
71
- },
72
- WebSearch: {
73
- patterns: ['web search', 'search online', 'lookup online', 'WebSearch', 'search the web'],
74
- priority: 2,
75
- },
76
- };
77
- /**
78
- * Minimum tools that most subagents need
79
- */
80
- const BASE_TOOLS = ['Read'];
81
- /**
82
- * SMI-1819: Maximum length for subagent names to prevent overly long identifiers
83
- */
84
- const MAX_SUBAGENT_NAME_LENGTH = 100;
85
- /**
86
- * Generate tool usage guidelines for a subagent
87
- */
88
- function generateToolGuidelines(tools) {
89
- const guidelines = [];
90
- if (tools.includes('Read')) {
91
- guidelines.push('- **Read**: Use to examine files before modifications');
92
- }
93
- if (tools.includes('Write')) {
94
- guidelines.push('- **Write**: Use for creating new files only');
95
- }
96
- if (tools.includes('Edit')) {
97
- guidelines.push('- **Edit**: Use for modifying existing files');
98
- }
99
- if (tools.includes('Bash')) {
100
- guidelines.push('- **Bash**: Use for command execution, prefer non-destructive commands');
101
- }
102
- if (tools.includes('Grep')) {
103
- guidelines.push('- **Grep**: Use for searching file contents');
104
- }
105
- if (tools.includes('Glob')) {
106
- guidelines.push('- **Glob**: Use for finding files by pattern');
107
- }
108
- if (tools.includes('WebFetch')) {
109
- guidelines.push('- **WebFetch**: Use for fetching web content');
110
- }
111
- if (tools.includes('WebSearch')) {
112
- guidelines.push('- **WebSearch**: Use for searching the web');
113
- }
114
- return guidelines.length > 0 ? guidelines.join('\n') : '- Use tools minimally and efficiently';
115
- }
20
+ export { CLAUDE_MODELS } from './SubagentGenerator.types.js';
21
+ import { CANONICAL_CLIENT } from '../install/paths.js';
22
+ import { getSubagentGenerationProfile, mapToolNames } from './SubagentGenerator.client-profiles.js';
23
+ import { CLAUDE_MODELS, } from './SubagentGenerator.types.js';
24
+ import { MAX_SUBAGENT_NAME_LENGTH, generateToolGuidelines, OMITTED_TOOLS_GUIDANCE, generateClaudeMdSnippet, extractTriggerPhrases, determineModel, detectTools, } from './SubagentGenerator.helpers.js';
116
25
  /**
117
26
  * Generate subagent markdown content
27
+ *
28
+ * SMI-6276 (Wave 6 Step 1): frontmatter shape is now driven by the target
29
+ * client's generation profile (`SubagentGenerator.client-profiles.ts`) —
30
+ * `Read, Write, Bash, WebFetch, Grep, Glob, WebSearch` plus a Claude
31
+ * `model:` value are no longer emitted unconditionally for every client.
118
32
  */
119
- function generateSubagentContent(name, description, triggerPhrases, tools, model) {
33
+ function generateSubagentContent(name, description, triggerPhrases, tools, model, client) {
120
34
  const triggerString = triggerPhrases.length > 0
121
35
  ? triggerPhrases.map((p) => `"${p}"`).join(', ')
122
36
  : '[describe trigger conditions]';
123
- const toolGuidelines = generateToolGuidelines(tools);
124
- return `---
125
- name: ${name}
126
- description: ${description} Use when ${triggerString}.
127
- skills: ${name.replace('-specialist', '')}
128
- tools: ${tools.join(', ')}
129
- model: ${model}
130
- ---
37
+ const profile = getSubagentGenerationProfile(client);
38
+ // SMI-6276 pr-reviewer finding: `description` is free text sourced from
39
+ // the SKILL.md being transformed — an unquoted plain YAML scalar breaks
40
+ // if it contains `: ` (reinterpreted as a nested key) or ` #` (truncated
41
+ // as a comment). JSON.stringify() produces a valid YAML double-quoted
42
+ // scalar (YAML's double-quote escaping is a superset of JSON's), so this
43
+ // composes the full description+trigger text as a plain JS string FIRST,
44
+ // then quotes the whole thing once — not per-field — so the result is
45
+ // safe regardless of what the source content contains.
46
+ const frontmatterLines = [
47
+ '---',
48
+ `name: ${name}`,
49
+ `description: ${JSON.stringify(`${description} Use when ${triggerString}.`)}`,
50
+ ];
51
+ if (profile.includeSkillsField) {
52
+ frontmatterLines.push(`skills: ${name.replace('-specialist', '')}`);
53
+ }
54
+ if (profile.toolsPolicy === 'claude-native') {
55
+ frontmatterLines.push(`tools: ${tools.join(', ')}`);
56
+ }
57
+ else if (profile.toolsPolicy === 'mapped-array') {
58
+ // SMI-6276: this client expects a YAML array of ITS OWN tool names, not
59
+ // a Claude-shaped comma list — never emit the unmapped/mis-shaped value
60
+ // (the AntiGravity docs' own "Known Issue" warns an unmapped name can
61
+ // hang the subagent process on invocation). Omit the key entirely when
62
+ // nothing maps, rather than an empty `tools: []` that says nothing.
63
+ const mappedTools = mapToolNames(tools, profile);
64
+ if (mappedTools.length > 0) {
65
+ frontmatterLines.push('tools:', ...mappedTools.map((tool) => ` - ${tool}`));
66
+ }
67
+ }
68
+ frontmatterLines.push(...profile.extraFrontmatterLines);
69
+ if (profile.modelPolicy === 'claude-enum') {
70
+ frontmatterLines.push(`model: ${model}`);
71
+ }
72
+ frontmatterLines.push('---');
73
+ const toolGuidelines = profile.toolsPolicy === 'claude-native' ? generateToolGuidelines(tools) : OMITTED_TOOLS_GUIDANCE;
74
+ return `${frontmatterLines.join('\n')}
131
75
 
132
76
  ## Operating Protocol
133
77
 
@@ -160,98 +104,6 @@ If the task cannot be completed:
160
104
  *Generated by Skillsmith Optimization Layer*
161
105
  `;
162
106
  }
163
- /**
164
- * Generate CLAUDE.md integration snippet
165
- */
166
- function generateClaudeMdSnippet(skillName, description, triggerPhrases, tools, model) {
167
- const triggerPatterns = triggerPhrases.length > 0
168
- ? triggerPhrases.map((p) => `- "${p}"`).join('\n')
169
- : '- [add trigger patterns]';
170
- const exampleTask = triggerPhrases.length > 0 ? triggerPhrases[0] : `execute ${skillName} task`;
171
- return `
172
- ### Subagent Delegation: ${skillName}
173
-
174
- When tasks match ${skillName} triggers, delegate to the ${skillName}-specialist
175
- subagent instead of executing directly. This provides context isolation and
176
- ~37-97% token savings.
177
-
178
- **Trigger Patterns:**
179
- ${triggerPatterns}
180
-
181
- **Delegation Example:**
182
- \`\`\`
183
- Task("${skillName}-specialist", "${exampleTask}", "${skillName}-specialist")
184
- \`\`\`
185
-
186
- **Model:** ${model}
187
- **Tools:** ${tools.join(', ')}
188
- `;
189
- }
190
- /**
191
- * Extract trigger phrases from skill description and content
192
- */
193
- function extractTriggerPhrases(description, content) {
194
- const phrases = [];
195
- // Common trigger phrase patterns
196
- const patterns = [
197
- /when\s+(?:you\s+)?(?:need\s+to\s+)?(.+?)(?:[.,]|$)/gi,
198
- /use\s+(?:this\s+)?(?:when|for)\s+(.+?)(?:[.,]|$)/gi,
199
- /(?:helps?\s+(?:you\s+)?(?:to\s+)?)?(.+?)(?:\s+tasks?|\s+operations?)/gi,
200
- ];
201
- const textToSearch = description + ' ' + content.slice(0, 2000); // Search first 2000 chars
202
- for (const pattern of patterns) {
203
- for (const match of textToSearch.matchAll(pattern)) {
204
- const phrase = match[1].trim().toLowerCase();
205
- if (phrase.length >= 5 && phrase.length <= 50 && !phrases.includes(phrase)) {
206
- phrases.push(phrase);
207
- }
208
- }
209
- }
210
- // Extract from "trigger" or "invoke" mentions
211
- const triggerMatch = content.match(/trigger[s]?\s*[:=]\s*["`']([^"`']+)["`']/gi);
212
- if (triggerMatch) {
213
- for (const match of triggerMatch) {
214
- const phrase = match.replace(/trigger[s]?\s*[:=]\s*["`']/i, '').replace(/["`']$/, '');
215
- if (!phrases.includes(phrase.toLowerCase())) {
216
- phrases.push(phrase.toLowerCase());
217
- }
218
- }
219
- }
220
- return phrases.slice(0, 5); // Limit to 5 phrases
221
- }
222
- /**
223
- * Determine optimal model for subagent
224
- * SMI-1795: Uses CLAUDE_MODELS constants for type safety
225
- */
226
- function determineModel(toolUsage, lineCount) {
227
- // Haiku for simple, fast operations
228
- if (toolUsage.detectedTools.length <= 2 && lineCount < 200) {
229
- return CLAUDE_MODELS.HAIKU;
230
- }
231
- // Opus for complex, reasoning-heavy tasks
232
- if (toolUsage.bashCommandCount > 5 ||
233
- (toolUsage.fileReadCount > 3 && toolUsage.fileWriteCount > 3)) {
234
- return CLAUDE_MODELS.OPUS;
235
- }
236
- // Sonnet for balanced workloads (default)
237
- return CLAUDE_MODELS.SONNET;
238
- }
239
- /**
240
- * Detect tools needed from skill content
241
- */
242
- function detectTools(content) {
243
- const lowerContent = content.toLowerCase();
244
- const detectedTools = new Set(BASE_TOOLS);
245
- for (const [tool, config] of Object.entries(TOOL_PATTERNS)) {
246
- for (const pattern of config.patterns) {
247
- if (lowerContent.includes(pattern.toLowerCase())) {
248
- detectedTools.add(tool);
249
- break;
250
- }
251
- }
252
- }
253
- return Array.from(detectedTools);
254
- }
255
107
  /**
256
108
  * Generate a companion subagent for a skill
257
109
  *
@@ -259,9 +111,12 @@ function detectTools(content) {
259
111
  * @param description - The skill's description
260
112
  * @param content - The full SKILL.md content
261
113
  * @param analysis - Analysis from SkillAnalyzer
114
+ * @param client - SMI-6276: target client for the generated companion-agent
115
+ * frontmatter shape (default: canonical / `claude-code`, preserving prior
116
+ * behavior for every existing caller). See `SubagentGenerator.client-profiles.ts`.
262
117
  * @returns Subagent generation result
263
118
  */
264
- export function generateSubagent(skillName, description, content, analysis) {
119
+ export function generateSubagent(skillName, description, content, analysis, client = CANONICAL_CLIENT) {
265
120
  // SMI-1815: Validate skill name is non-empty
266
121
  if (!skillName || skillName.trim() === '') {
267
122
  return {
@@ -291,7 +146,7 @@ export function generateSubagent(skillName, description, content, analysis) {
291
146
  // Generate subagent description
292
147
  const subagentDescription = description || `Specialist agent for ${skillName} operations`;
293
148
  // Generate content
294
- const subagentContent = generateSubagentContent(subagentName, subagentDescription, triggerPhrases, allTools, model);
149
+ const subagentContent = generateSubagentContent(subagentName, subagentDescription, triggerPhrases, allTools, model, client);
295
150
  // Generate CLAUDE.md snippet
296
151
  const claudeMdSnippet = generateClaudeMdSnippet(skillName, subagentDescription, triggerPhrases, allTools, model);
297
152
  return {
@@ -313,9 +168,12 @@ export function generateSubagent(skillName, description, content, analysis) {
313
168
  * @param skillName - The name of the skill
314
169
  * @param description - The skill's description
315
170
  * @param content - The full SKILL.md content
171
+ * @param client - SMI-6276: target client for the generated companion-agent
172
+ * frontmatter shape (default: canonical / `claude-code`, preserving prior
173
+ * behavior for every existing caller). See `SubagentGenerator.client-profiles.ts`.
316
174
  * @returns Subagent generation result
317
175
  */
318
- export function generateMinimalSubagent(skillName, description, content) {
176
+ export function generateMinimalSubagent(skillName, description, content, client = CANONICAL_CLIENT) {
319
177
  // SMI-1815: Validate skill name is non-empty
320
178
  if (!skillName || skillName.trim() === '') {
321
179
  return {
@@ -333,7 +191,7 @@ export function generateMinimalSubagent(skillName, description, content) {
333
191
  const baseName = skillName.length > maxBaseLength ? skillName.slice(0, maxBaseLength) : skillName;
334
192
  const subagentName = `${baseName}${suffix}`;
335
193
  const subagentDescription = description || `Specialist agent for ${skillName} operations`;
336
- const subagentContent = generateSubagentContent(subagentName, subagentDescription, triggerPhrases, detectedTools, model);
194
+ const subagentContent = generateSubagentContent(subagentName, subagentDescription, triggerPhrases, detectedTools, model, client);
337
195
  const claudeMdSnippet = generateClaudeMdSnippet(skillName, subagentDescription, triggerPhrases, detectedTools, model);
338
196
  return {
339
197
  generated: true,