neuro-cli 4.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 (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +510 -0
  3. package/dist/advisor/advisor.d.ts +50 -0
  4. package/dist/advisor/advisor.js +178 -0
  5. package/dist/agents/base.d.ts +62 -0
  6. package/dist/agents/base.js +215 -0
  7. package/dist/agents/orchestrator.d.ts +46 -0
  8. package/dist/agents/orchestrator.js +192 -0
  9. package/dist/agents/team.d.ts +51 -0
  10. package/dist/agents/team.js +210 -0
  11. package/dist/api/models.d.ts +23 -0
  12. package/dist/api/models.js +514 -0
  13. package/dist/api/ollama.d.ts +153 -0
  14. package/dist/api/ollama.js +751 -0
  15. package/dist/api/openrouter.d.ts +55 -0
  16. package/dist/api/openrouter.js +223 -0
  17. package/dist/commands/commands.d.ts +43 -0
  18. package/dist/commands/commands.js +308 -0
  19. package/dist/config/config.d.ts +8 -0
  20. package/dist/config/config.js +311 -0
  21. package/dist/context/compaction.d.ts +54 -0
  22. package/dist/context/compaction.js +251 -0
  23. package/dist/context/custom-agents.d.ts +107 -0
  24. package/dist/context/custom-agents.js +397 -0
  25. package/dist/context/custom-tools.d.ts +120 -0
  26. package/dist/context/custom-tools.js +564 -0
  27. package/dist/context/git-checkpoint.d.ts +52 -0
  28. package/dist/context/git-checkpoint.js +240 -0
  29. package/dist/context/neuro-md.d.ts +48 -0
  30. package/dist/context/neuro-md.js +202 -0
  31. package/dist/context/neuroignore.d.ts +102 -0
  32. package/dist/context/neuroignore.js +441 -0
  33. package/dist/context/repo-map.d.ts +38 -0
  34. package/dist/context/repo-map.js +220 -0
  35. package/dist/context/skill-standard.d.ts +262 -0
  36. package/dist/context/skill-standard.js +1156 -0
  37. package/dist/context/skill-system.d.ts +75 -0
  38. package/dist/context/skill-system.js +578 -0
  39. package/dist/context/tree-sitter.d.ts +99 -0
  40. package/dist/context/tree-sitter.js +1956 -0
  41. package/dist/core/acp.d.ts +325 -0
  42. package/dist/core/acp.js +1498 -0
  43. package/dist/core/api-server.d.ts +143 -0
  44. package/dist/core/api-server.js +550 -0
  45. package/dist/core/approval.d.ts +81 -0
  46. package/dist/core/approval.js +432 -0
  47. package/dist/core/auto-compact.d.ts +127 -0
  48. package/dist/core/auto-compact.js +436 -0
  49. package/dist/core/auto-mode.d.ts +232 -0
  50. package/dist/core/auto-mode.js +831 -0
  51. package/dist/core/background-session.d.ts +166 -0
  52. package/dist/core/background-session.js +696 -0
  53. package/dist/core/cicd.d.ts +257 -0
  54. package/dist/core/cicd.js +1443 -0
  55. package/dist/core/cloud-sync.d.ts +156 -0
  56. package/dist/core/cloud-sync.js +582 -0
  57. package/dist/core/code-review.d.ts +132 -0
  58. package/dist/core/code-review.js +1191 -0
  59. package/dist/core/completion.d.ts +49 -0
  60. package/dist/core/completion.js +384 -0
  61. package/dist/core/context.d.ts +38 -0
  62. package/dist/core/context.js +144 -0
  63. package/dist/core/diff-preview.d.ts +35 -0
  64. package/dist/core/diff-preview.js +173 -0
  65. package/dist/core/doom-loop.d.ts +51 -0
  66. package/dist/core/doom-loop.js +179 -0
  67. package/dist/core/engine.d.ts +183 -0
  68. package/dist/core/engine.js +942 -0
  69. package/dist/core/extended-thinking.d.ts +103 -0
  70. package/dist/core/extended-thinking.js +269 -0
  71. package/dist/core/fallback.d.ts +54 -0
  72. package/dist/core/fallback.js +104 -0
  73. package/dist/core/git-worktree.d.ts +139 -0
  74. package/dist/core/git-worktree.js +614 -0
  75. package/dist/core/headless.d.ts +30 -0
  76. package/dist/core/headless.js +101 -0
  77. package/dist/core/i18n.d.ts +83 -0
  78. package/dist/core/i18n.js +739 -0
  79. package/dist/core/linting.d.ts +129 -0
  80. package/dist/core/linting.js +699 -0
  81. package/dist/core/model-router.d.ts +109 -0
  82. package/dist/core/model-router.js +581 -0
  83. package/dist/core/multi-model.d.ts +243 -0
  84. package/dist/core/multi-model.js +1099 -0
  85. package/dist/core/multi-session.d.ts +144 -0
  86. package/dist/core/multi-session.js +442 -0
  87. package/dist/core/multimodal.d.ts +125 -0
  88. package/dist/core/multimodal.js +286 -0
  89. package/dist/core/observability.d.ts +93 -0
  90. package/dist/core/observability.js +737 -0
  91. package/dist/core/os-sandbox.d.ts +122 -0
  92. package/dist/core/os-sandbox.js +1193 -0
  93. package/dist/core/outcome-grading.d.ts +228 -0
  94. package/dist/core/outcome-grading.js +1123 -0
  95. package/dist/core/output-styles.d.ts +57 -0
  96. package/dist/core/output-styles.js +382 -0
  97. package/dist/core/parallel-agents.d.ts +183 -0
  98. package/dist/core/parallel-agents.js +563 -0
  99. package/dist/core/plugin-bundle.d.ts +236 -0
  100. package/dist/core/plugin-bundle.js +887 -0
  101. package/dist/core/plugin-sdk.d.ts +139 -0
  102. package/dist/core/plugin-sdk.js +273 -0
  103. package/dist/core/prompt-cache.d.ts +163 -0
  104. package/dist/core/prompt-cache.js +599 -0
  105. package/dist/core/sandbox.d.ts +127 -0
  106. package/dist/core/sandbox.js +369 -0
  107. package/dist/core/scheduled-tasks.d.ts +151 -0
  108. package/dist/core/scheduled-tasks.js +502 -0
  109. package/dist/core/security-scanner.d.ts +160 -0
  110. package/dist/core/security-scanner.js +1494 -0
  111. package/dist/core/session.d.ts +83 -0
  112. package/dist/core/session.js +269 -0
  113. package/dist/core/shell-completion.d.ts +51 -0
  114. package/dist/core/shell-completion.js +674 -0
  115. package/dist/core/smart-monitor.d.ts +146 -0
  116. package/dist/core/smart-monitor.js +1199 -0
  117. package/dist/core/spec-driven.d.ts +233 -0
  118. package/dist/core/spec-driven.js +1485 -0
  119. package/dist/core/spending-warnings.d.ts +123 -0
  120. package/dist/core/spending-warnings.js +456 -0
  121. package/dist/core/sub-agent.d.ts +298 -0
  122. package/dist/core/sub-agent.js +1023 -0
  123. package/dist/core/telemetry.d.ts +157 -0
  124. package/dist/core/telemetry.js +412 -0
  125. package/dist/core/terminal-ux.d.ts +134 -0
  126. package/dist/core/terminal-ux.js +649 -0
  127. package/dist/core/testing.d.ts +146 -0
  128. package/dist/core/testing.js +1200 -0
  129. package/dist/core/types.d.ts +439 -0
  130. package/dist/core/types.js +6 -0
  131. package/dist/core/undo-redo.d.ts +112 -0
  132. package/dist/core/undo-redo.js +290 -0
  133. package/dist/core/updater.d.ts +159 -0
  134. package/dist/core/updater.js +608 -0
  135. package/dist/core/vim-mode.d.ts +151 -0
  136. package/dist/core/vim-mode.js +771 -0
  137. package/dist/core/voice.d.ts +137 -0
  138. package/dist/core/voice.js +538 -0
  139. package/dist/core/web-dashboard.d.ts +109 -0
  140. package/dist/core/web-dashboard.js +484 -0
  141. package/dist/hooks/hooks.d.ts +74 -0
  142. package/dist/hooks/hooks.js +160 -0
  143. package/dist/hooks/llm-evaluator.d.ts +165 -0
  144. package/dist/hooks/llm-evaluator.js +560 -0
  145. package/dist/index.d.ts +3 -0
  146. package/dist/index.js +1186 -0
  147. package/dist/lsp/lsp-manager.d.ts +63 -0
  148. package/dist/lsp/lsp-manager.js +351 -0
  149. package/dist/mcp/client.d.ts +133 -0
  150. package/dist/mcp/client.js +684 -0
  151. package/dist/mcp/mcp-apps.d.ts +70 -0
  152. package/dist/mcp/mcp-apps.js +1007 -0
  153. package/dist/tools/bash.d.ts +5 -0
  154. package/dist/tools/bash.js +195 -0
  155. package/dist/tools/browser.d.ts +92 -0
  156. package/dist/tools/browser.js +1570 -0
  157. package/dist/tools/extended.d.ts +6 -0
  158. package/dist/tools/extended.js +191 -0
  159. package/dist/tools/file.d.ts +10 -0
  160. package/dist/tools/file.js +382 -0
  161. package/dist/tools/github.d.ts +389 -0
  162. package/dist/tools/github.js +759 -0
  163. package/dist/tools/index.d.ts +9 -0
  164. package/dist/tools/index.js +40 -0
  165. package/dist/tools/memory.d.ts +6 -0
  166. package/dist/tools/memory.js +197 -0
  167. package/dist/tools/registry.d.ts +29 -0
  168. package/dist/tools/registry.js +64 -0
  169. package/dist/tools/web.d.ts +6 -0
  170. package/dist/tools/web.js +150 -0
  171. package/dist/ui/renderer.d.ts +97 -0
  172. package/dist/ui/renderer.js +279 -0
  173. package/dist/ui/theme.d.ts +27 -0
  174. package/dist/ui/theme.js +106 -0
  175. package/package.json +83 -0
@@ -0,0 +1,75 @@
1
+ export interface SkillDefinition {
2
+ name: string;
3
+ description: string;
4
+ triggers: string[];
5
+ systemPromptAddition: string;
6
+ tools?: string[];
7
+ priority: number;
8
+ autoActivate: boolean;
9
+ source: string;
10
+ tags?: string[];
11
+ }
12
+ export interface ActiveSkill {
13
+ skill: SkillDefinition;
14
+ activatedAt: number;
15
+ activatedBy: 'auto' | 'manual';
16
+ matchReason?: string;
17
+ }
18
+ export declare class SkillSystem {
19
+ private skills;
20
+ private activeSkills;
21
+ private skillsDir;
22
+ private globalSkillsDir;
23
+ private projectRoot;
24
+ constructor(projectRoot: string);
25
+ /** Discover and load all skills (builtin + global + project). */
26
+ discover(): SkillDefinition[];
27
+ /** Auto-activate skills whose trigger patterns match the given prompt. */
28
+ autoActivate(prompt: string): ActiveSkill[];
29
+ /** Manually activate a skill by name. */
30
+ activate(name: string): ActiveSkill | null;
31
+ /** Deactivate a skill by name. Returns true if it was active. */
32
+ deactivate(name: string): boolean;
33
+ /** Deactivate all active skills. */
34
+ deactivateAll(): void;
35
+ /** Return all currently active skills, sorted by priority descending. */
36
+ getActiveSkills(): ActiveSkill[];
37
+ /** Return all discovered skill definitions. */
38
+ getAllSkills(): SkillDefinition[];
39
+ /** Build the concatenated system prompt addition from all active skills. */
40
+ getSystemPromptAdditions(): string;
41
+ /** Print a human-readable list of available and active skills. */
42
+ listSkills(): void;
43
+ /** Check whether a skill is currently active. */
44
+ isSkillActive(name: string): boolean;
45
+ /** Load skill markdown files from a directory. */
46
+ private loadFromDirectory;
47
+ /** Register the builtin skill definitions. */
48
+ private loadBuiltinSkills;
49
+ /**
50
+ * Parse a markdown skill file.
51
+ *
52
+ * Expected front-matter-like format:
53
+ *
54
+ * ---
55
+ * name: my-skill
56
+ * description: A short description
57
+ * triggers: pattern1, pattern2, pattern3
58
+ * priority: 50
59
+ * autoActivate: true
60
+ * tags: tag1, tag2
61
+ * tools: tool1, tool2
62
+ * ---
63
+ *
64
+ * The rest of the file becomes the systemPromptAddition.
65
+ */
66
+ private parseSkillFile;
67
+ /**
68
+ * Test whether any trigger pattern matches the prompt.
69
+ * Returns the first matching pattern string, or null if none match.
70
+ */
71
+ private matchTriggers;
72
+ /** Log skill activation to the console. */
73
+ private logActivation;
74
+ }
75
+ //# sourceMappingURL=skill-system.d.ts.map
@@ -0,0 +1,578 @@
1
+ import { readFileSync, readdirSync, existsSync, statSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+ // ---------------------------------------------------------------------------
5
+ // Built-in skill definitions
6
+ // ---------------------------------------------------------------------------
7
+ const BUILTIN_SKILLS = [
8
+ {
9
+ name: 'react',
10
+ description: 'React/Next.js development patterns, component architecture, hooks, and state management',
11
+ triggers: [
12
+ '\\breact\\b',
13
+ '\\bnext\\.?js\\b',
14
+ '\\bjsx\\b',
15
+ '\\btsx\\b',
16
+ '\\bcomponent\\b',
17
+ '\\bhook\\b',
18
+ '\\busestate\\b',
19
+ '\\buseeffect\\b',
20
+ 'state management',
21
+ 'server component',
22
+ 'client component',
23
+ ],
24
+ systemPromptAddition: [
25
+ 'When working on React/Next.js code, follow these guidelines:',
26
+ '- Prefer function components with hooks over class components.',
27
+ '- Use TypeScript for all new component files (.tsx).',
28
+ '- Colocate state as close to where it is used as possible.',
29
+ '- Extract reusable logic into custom hooks.',
30
+ '- Use React.memo, useMemo, and useCallback only when profiling shows a real need.',
31
+ '- Follow the Next.js App Router conventions for routing, layouts, and server components.',
32
+ '- Prefer server components by default; add "use client" only when browser APIs or hooks are required.',
33
+ '- Use streaming and Suspense boundaries for data-loading pages.',
34
+ '- Keep component files focused; extract sub-components when a file exceeds 200 lines.',
35
+ ].join('\n'),
36
+ tools: ['file-editor', 'terminal', 'browser'],
37
+ priority: 80,
38
+ autoActivate: true,
39
+ source: 'builtin',
40
+ tags: ['frontend', 'framework', 'react'],
41
+ },
42
+ {
43
+ name: 'api-design',
44
+ description: 'REST API design and implementation, endpoint modeling, and HTTP best practices',
45
+ triggers: [
46
+ '\\bapi\\b',
47
+ '\\brest\\b',
48
+ '\\bendpoint\\b',
49
+ '\\broute\\b',
50
+ 'http method',
51
+ '\\bcrud\\b',
52
+ '\\bopenapi\\b',
53
+ '\\bswagger\\b',
54
+ '\\bgraphql\\b',
55
+ 'request response',
56
+ '\\bmiddleware\\b',
57
+ ],
58
+ systemPromptAddition: [
59
+ 'When designing or implementing APIs, follow these guidelines:',
60
+ '- Use plural noun resource names (e.g. /users, /orders).',
61
+ '- Return appropriate HTTP status codes (201 for creation, 204 for deletion, etc.).',
62
+ '- Include pagination for list endpoints (cursor-based preferred).',
63
+ '- Version APIs via URL path prefix (/v1/) or header.',
64
+ '- Validate request bodies with a schema layer before handler logic.',
65
+ '- Document every endpoint with request/response examples.',
66
+ '- Handle errors with a consistent JSON error envelope.',
67
+ '- Prefer idempotent designs for PUT and DELETE operations.',
68
+ '- Use middleware for cross-cutting concerns (auth, logging, rate-limiting).',
69
+ ].join('\n'),
70
+ tools: ['file-editor', 'terminal', 'http-client'],
71
+ priority: 70,
72
+ autoActivate: true,
73
+ source: 'builtin',
74
+ tags: ['backend', 'api', 'http'],
75
+ },
76
+ {
77
+ name: 'database',
78
+ description: 'Database schema design, query optimization, and data modeling',
79
+ triggers: [
80
+ '\\bdatabase\\b',
81
+ '\\bschema\\b',
82
+ '\\bsql\\b',
83
+ '\\bprisma\\b',
84
+ '\\bdrizzle\\b',
85
+ '\\bmigration\\b',
86
+ '\\btable\\b',
87
+ '\\bquery\\b',
88
+ '\\bindex\\b',
89
+ '\\borm\\b',
90
+ '\\bpostgres\\b',
91
+ '\\bmongodb\\b',
92
+ '\\bsqlite\\b',
93
+ ],
94
+ systemPromptAddition: [
95
+ 'When working with databases, follow these guidelines:',
96
+ '- Normalize to 3NF by default; denormalize only with measured justification.',
97
+ '- Always write migrations as reversible (up + down).',
98
+ '- Add indexes for columns used in WHERE, JOIN, and ORDER BY clauses.',
99
+ '- Use foreign key constraints with appropriate ON DELETE actions.',
100
+ '- Prefer parameterized queries; never interpolate user input into SQL.',
101
+ '- Model soft deletes with a deleted_at column rather than removing rows.',
102
+ '- Use transactions for multi-step writes that must succeed or fail together.',
103
+ '- Document the purpose of each table and non-obvious column in comments.',
104
+ '- Keep migration files small and focused on one logical change.',
105
+ ].join('\n'),
106
+ tools: ['file-editor', 'terminal', 'database-client'],
107
+ priority: 70,
108
+ autoActivate: true,
109
+ source: 'builtin',
110
+ tags: ['backend', 'database', 'data'],
111
+ },
112
+ {
113
+ name: 'testing',
114
+ description: 'Test-driven development, test strategy, and quality assurance',
115
+ triggers: [
116
+ '\\btest\\b',
117
+ '\\btesting\\b',
118
+ '\\bunit test\\b',
119
+ '\\bintegration test\\b',
120
+ '\\be2e\\b',
121
+ '\\bjest\\b',
122
+ '\\bvitest\\b',
123
+ '\\bplaywright\\b',
124
+ '\\bpytest\\b',
125
+ '\\bcoverage\\b',
126
+ '\\bmock\\b',
127
+ '\\bstub\\b',
128
+ '\\btdd\\b',
129
+ ],
130
+ systemPromptAddition: [
131
+ 'When writing tests, follow these guidelines:',
132
+ '- Write tests before implementation when practicing TDD; otherwise write them alongside.',
133
+ '- Structure tests with Arrange-Act-Assert (Given-When-Then).',
134
+ '- Test behavior, not implementation details.',
135
+ '- Aim for meaningful coverage of business logic (>80%); do not chase 100% on trivial code.',
136
+ '- Use descriptive test names that read as a specification.',
137
+ '- Prefer integration tests for API routes; unit tests for pure functions.',
138
+ '- Use test fixtures and factories instead of duplicating setup code.',
139
+ '- Isolate external dependencies with mocks/stubs; avoid mocking internal modules.',
140
+ '- Run the full suite before declaring work complete.',
141
+ ].join('\n'),
142
+ tools: ['file-editor', 'terminal', 'test-runner'],
143
+ priority: 75,
144
+ autoActivate: true,
145
+ source: 'builtin',
146
+ tags: ['testing', 'quality', 'tdd'],
147
+ },
148
+ {
149
+ name: 'security',
150
+ description: 'Security-first coding practices, vulnerability prevention, and hardening',
151
+ triggers: [
152
+ '\\bsecurity\\b',
153
+ '\\bvulnerability\\b',
154
+ '\\bauth\\b',
155
+ '\\bauthentication\\b',
156
+ '\\bauthorization\\b',
157
+ '\\bcsrf\\b',
158
+ '\\bxss\\b',
159
+ '\\binjection\\b',
160
+ '\\bencryption\\b',
161
+ '\\bjwt\\b',
162
+ '\\boauth\\b',
163
+ '\\bsanitize\\b',
164
+ '\\bcsp\\b',
165
+ ],
166
+ systemPromptAddition: [
167
+ 'When writing security-sensitive code, follow these guidelines:',
168
+ '- Never trust user input; validate and sanitize at every trust boundary.',
169
+ '- Use parameterized queries for all database operations.',
170
+ '- Store passwords with bcrypt/argon2; never with plain hashes.',
171
+ '- Apply the principle of least privilege to service accounts and API tokens.',
172
+ '- Enable CSRF protection for all state-changing requests from browsers.',
173
+ '- Set security headers: Content-Security-Policy, X-Content-Type-Options, Strict-Transport-Security.',
174
+ '- Use environment variables for secrets; never commit them to source control.',
175
+ '- Rotate secrets and API keys on a regular schedule.',
176
+ '- Log security-relevant events but never log sensitive data (passwords, tokens).',
177
+ '- Keep dependencies updated and audit for known vulnerabilities.',
178
+ ].join('\n'),
179
+ tools: ['file-editor', 'terminal'],
180
+ priority: 90,
181
+ autoActivate: true,
182
+ source: 'builtin',
183
+ tags: ['security', 'hardening', 'auth'],
184
+ },
185
+ {
186
+ name: 'performance',
187
+ description: 'Performance optimization, profiling, and efficient coding patterns',
188
+ triggers: [
189
+ '\\bperformance\\b',
190
+ '\\boptimize\\b',
191
+ '\\boptimization\\b',
192
+ '\\bprofiling\\b',
193
+ '\\bbottleneck\\b',
194
+ '\\blatency\\b',
195
+ '\\bthroughput\\b',
196
+ '\\bcaching\\b',
197
+ '\\blazy load\\b',
198
+ '\\bcode splitting\\b',
199
+ '\\bdebounce\\b',
200
+ '\\bthrottle\\b',
201
+ ],
202
+ systemPromptAddition: [
203
+ 'When optimizing for performance, follow these guidelines:',
204
+ '- Measure before and after every optimization; never optimize blindly.',
205
+ '- Profile to identify actual bottlenecks rather than assumed ones.',
206
+ '- Prefer algorithmic improvements over micro-optimizations.',
207
+ '- Cache expensive computations and I/O; invalidate caches on data change.',
208
+ '- Use lazy loading and code splitting for large front-end bundles.',
209
+ '- Debounce or throttle high-frequency event handlers.',
210
+ '- Batch database writes and network requests where possible.',
211
+ '- Use connection pooling for database and HTTP clients.',
212
+ '- Avoid premature optimization; write clear code first, then optimize hot paths.',
213
+ ].join('\n'),
214
+ tools: ['file-editor', 'terminal', 'profiler'],
215
+ priority: 65,
216
+ autoActivate: true,
217
+ source: 'builtin',
218
+ tags: ['performance', 'optimization', 'profiling'],
219
+ },
220
+ {
221
+ name: 'debugging',
222
+ description: 'Systematic debugging approach, root cause analysis, and troubleshooting',
223
+ triggers: [
224
+ '\\bdebug\\b',
225
+ '\\bdebugging\\b',
226
+ '\\berror\\b',
227
+ '\\bbug\\b',
228
+ '\\bcrash\\b',
229
+ '\\bstack trace\\b',
230
+ '\\btraceback\\b',
231
+ '\\bfix\\b',
232
+ '\\bissue\\b',
233
+ '\\btroubleshoot\\b',
234
+ '\\breproduce\\b',
235
+ '\\broot cause\\b',
236
+ ],
237
+ systemPromptAddition: [
238
+ 'When debugging issues, follow these guidelines:',
239
+ '- Reproduce the issue first; a reliable reproduction is half the fix.',
240
+ '- Read the error message and stack trace carefully before making changes.',
241
+ '- Form a hypothesis, test it with the smallest possible change, then iterate.',
242
+ '- Use binary search (comment out half the code) to narrow down root cause.',
243
+ '- Add logging around the failure point rather than changing logic speculatively.',
244
+ '- Check recent changes (git log, git diff) for likely regressions.',
245
+ '- Verify the fix with a test that reproduces the original issue.',
246
+ '- Document the root cause and the fix in the PR description or a post-mortem.',
247
+ ].join('\n'),
248
+ tools: ['file-editor', 'terminal', 'debugger'],
249
+ priority: 60,
250
+ autoActivate: true,
251
+ source: 'builtin',
252
+ tags: ['debugging', 'troubleshooting', 'analysis'],
253
+ },
254
+ {
255
+ name: 'devops',
256
+ description: 'CI/CD pipelines, deployment strategies, and infrastructure automation',
257
+ triggers: [
258
+ '\\bci\\b\\/\\bcd\\b',
259
+ '\\bcicd\\b',
260
+ '\\bdeploy\\b',
261
+ '\\bdeployment\\b',
262
+ '\\bdocker\\b',
263
+ '\\bkubernetes\\b',
264
+ '\\bk8s\\b',
265
+ '\\bpipeline\\b',
266
+ '\\bgithub actions\\b',
267
+ '\\bterraform\\b',
268
+ '\\binfrastructure\\b',
269
+ '\\bcontainer\\b',
270
+ '\\bhelm\\b',
271
+ ],
272
+ systemPromptAddition: [
273
+ 'When working on CI/CD and deployment, follow these guidelines:',
274
+ '- Treat infrastructure as code; version all config in the repository.',
275
+ '- Keep pipelines fast: cache dependencies, parallelize independent steps.',
276
+ '- Use separate stages for lint, test, build, deploy with clear gate conditions.',
277
+ '- Deploy to staging before production; require manual approval for prod.',
278
+ '- Use blue/green or canary deployments for zero-downtime releases.',
279
+ '- Tag Docker images with both the git SHA and a semantic version.',
280
+ '- Store secrets in a vault or secret manager, not in pipeline YAML.',
281
+ '- Monitor deployment health; auto-rollback on error-rate spikes.',
282
+ '- Document runbooks for common operational procedures.',
283
+ ].join('\n'),
284
+ tools: ['file-editor', 'terminal', 'docker', 'kubernetes'],
285
+ priority: 65,
286
+ autoActivate: true,
287
+ source: 'builtin',
288
+ tags: ['devops', 'ci-cd', 'infrastructure'],
289
+ },
290
+ ];
291
+ // ---------------------------------------------------------------------------
292
+ // SkillSystem
293
+ // ---------------------------------------------------------------------------
294
+ export class SkillSystem {
295
+ skills;
296
+ activeSkills;
297
+ skillsDir;
298
+ globalSkillsDir;
299
+ projectRoot;
300
+ constructor(projectRoot) {
301
+ this.projectRoot = projectRoot;
302
+ this.skillsDir = join(projectRoot, '.neuro', 'skills');
303
+ this.globalSkillsDir = join(homedir(), '.neuro', 'skills');
304
+ this.skills = new Map();
305
+ this.activeSkills = new Map();
306
+ }
307
+ // -------------------------------------------------------------------------
308
+ // Public API
309
+ // -------------------------------------------------------------------------
310
+ /** Discover and load all skills (builtin + global + project). */
311
+ discover() {
312
+ this.skills.clear();
313
+ // Load in order: builtin -> global -> project (later loads override earlier)
314
+ this.loadBuiltinSkills();
315
+ this.loadFromDirectory(this.globalSkillsDir);
316
+ this.loadFromDirectory(this.skillsDir);
317
+ return this.getAllSkills();
318
+ }
319
+ /** Auto-activate skills whose trigger patterns match the given prompt. */
320
+ autoActivate(prompt) {
321
+ const activated = [];
322
+ const lowerPrompt = prompt.toLowerCase();
323
+ for (const skill of this.skills.values()) {
324
+ // Skip skills already active
325
+ if (this.activeSkills.has(skill.name)) {
326
+ continue;
327
+ }
328
+ // Skip skills that are not auto-activatable
329
+ if (!skill.autoActivate) {
330
+ continue;
331
+ }
332
+ const matchReason = this.matchTriggers(lowerPrompt, skill.triggers);
333
+ if (matchReason !== null) {
334
+ const active = {
335
+ skill,
336
+ activatedAt: Date.now(),
337
+ activatedBy: 'auto',
338
+ matchReason,
339
+ };
340
+ this.activeSkills.set(skill.name, active);
341
+ activated.push(active);
342
+ this.logActivation(active);
343
+ }
344
+ }
345
+ // Sort by priority descending so callers see highest-priority first
346
+ activated.sort((a, b) => b.skill.priority - a.skill.priority);
347
+ return activated;
348
+ }
349
+ /** Manually activate a skill by name. */
350
+ activate(name) {
351
+ const skill = this.skills.get(name);
352
+ if (!skill) {
353
+ return null;
354
+ }
355
+ const active = {
356
+ skill,
357
+ activatedAt: Date.now(),
358
+ activatedBy: 'manual',
359
+ };
360
+ this.activeSkills.set(name, active);
361
+ this.logActivation(active);
362
+ return active;
363
+ }
364
+ /** Deactivate a skill by name. Returns true if it was active. */
365
+ deactivate(name) {
366
+ return this.activeSkills.delete(name);
367
+ }
368
+ /** Deactivate all active skills. */
369
+ deactivateAll() {
370
+ this.activeSkills.clear();
371
+ }
372
+ /** Return all currently active skills, sorted by priority descending. */
373
+ getActiveSkills() {
374
+ return Array.from(this.activeSkills.values()).sort((a, b) => b.skill.priority - a.skill.priority);
375
+ }
376
+ /** Return all discovered skill definitions. */
377
+ getAllSkills() {
378
+ return Array.from(this.skills.values()).sort((a, b) => b.priority - a.priority);
379
+ }
380
+ /** Build the concatenated system prompt addition from all active skills. */
381
+ getSystemPromptAdditions() {
382
+ const active = this.getActiveSkills();
383
+ if (active.length === 0) {
384
+ return '';
385
+ }
386
+ const sections = active.map((entry) => {
387
+ const divider = '---';
388
+ return [
389
+ divider,
390
+ `Skill: ${entry.skill.name} (priority ${entry.skill.priority})`,
391
+ divider,
392
+ entry.skill.systemPromptAddition,
393
+ ].join('\n');
394
+ });
395
+ return sections.join('\n\n');
396
+ }
397
+ /** Print a human-readable list of available and active skills. */
398
+ listSkills() {
399
+ const all = this.getAllSkills();
400
+ // eslint-disable-next-line no-console
401
+ console.log('\n=== Available Skills ===\n');
402
+ for (const skill of all) {
403
+ const activeTag = this.activeSkills.has(skill.name)
404
+ ? ' [ACTIVE]'
405
+ : '';
406
+ const autoTag = skill.autoActivate ? ' (auto)' : ' (manual)';
407
+ // eslint-disable-next-line no-console
408
+ console.log(` ${skill.name}${activeTag}${autoTag} - ${skill.description}`);
409
+ // eslint-disable-next-line no-console
410
+ console.log(` priority: ${skill.priority} | source: ${skill.source} | triggers: ${skill.triggers.length}`);
411
+ if (skill.tags && skill.tags.length > 0) {
412
+ // eslint-disable-next-line no-console
413
+ console.log(` tags: ${skill.tags.join(', ')}`);
414
+ }
415
+ }
416
+ // eslint-disable-next-line no-console
417
+ console.log('');
418
+ }
419
+ /** Check whether a skill is currently active. */
420
+ isSkillActive(name) {
421
+ return this.activeSkills.has(name);
422
+ }
423
+ // -------------------------------------------------------------------------
424
+ // Private helpers
425
+ // -------------------------------------------------------------------------
426
+ /** Load skill markdown files from a directory. */
427
+ loadFromDirectory(dir) {
428
+ if (!existsSync(dir)) {
429
+ return;
430
+ }
431
+ let entries;
432
+ try {
433
+ const stat = statSync(dir);
434
+ if (!stat.isDirectory()) {
435
+ return;
436
+ }
437
+ entries = readdirSync(dir);
438
+ }
439
+ catch {
440
+ return;
441
+ }
442
+ for (const entry of entries) {
443
+ const filePath = join(dir, entry);
444
+ try {
445
+ const fileStat = statSync(filePath);
446
+ if (!fileStat.isFile()) {
447
+ continue;
448
+ }
449
+ if (!entry.endsWith('.md')) {
450
+ continue;
451
+ }
452
+ const content = readFileSync(filePath, 'utf-8');
453
+ const skill = this.parseSkillFile(content, filePath);
454
+ if (skill) {
455
+ // Later loads override earlier ones (project overrides global)
456
+ this.skills.set(skill.name, skill);
457
+ }
458
+ }
459
+ catch {
460
+ // Skip unreadable files
461
+ }
462
+ }
463
+ }
464
+ /** Register the builtin skill definitions. */
465
+ loadBuiltinSkills() {
466
+ for (const skill of BUILTIN_SKILLS) {
467
+ this.skills.set(skill.name, { ...skill });
468
+ }
469
+ }
470
+ /**
471
+ * Parse a markdown skill file.
472
+ *
473
+ * Expected front-matter-like format:
474
+ *
475
+ * ---
476
+ * name: my-skill
477
+ * description: A short description
478
+ * triggers: pattern1, pattern2, pattern3
479
+ * priority: 50
480
+ * autoActivate: true
481
+ * tags: tag1, tag2
482
+ * tools: tool1, tool2
483
+ * ---
484
+ *
485
+ * The rest of the file becomes the systemPromptAddition.
486
+ */
487
+ parseSkillFile(content, filePath) {
488
+ const trimmed = content.trim();
489
+ // Extract front-matter between --- delimiters
490
+ const fmRegex = /^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/;
491
+ const match = trimmed.match(fmRegex);
492
+ if (!match) {
493
+ return null;
494
+ }
495
+ const frontMatter = match[1];
496
+ const body = match[2].trim();
497
+ // Parse front-matter lines
498
+ const fm = {};
499
+ for (const line of frontMatter.split('\n')) {
500
+ const colonIndex = line.indexOf(':');
501
+ if (colonIndex === -1) {
502
+ continue;
503
+ }
504
+ const key = line.slice(0, colonIndex).trim().toLowerCase();
505
+ const value = line.slice(colonIndex + 1).trim();
506
+ fm[key] = value;
507
+ }
508
+ if (!fm.name) {
509
+ return null;
510
+ }
511
+ const name = fm.name;
512
+ const description = fm.description || `Custom skill: ${name}`;
513
+ const triggers = fm.triggers
514
+ ? fm.triggers
515
+ .split(',')
516
+ .map((t) => t.trim())
517
+ .filter((t) => t.length > 0)
518
+ : [];
519
+ const priority = fm.priority ? parseInt(fm.priority, 10) : 50;
520
+ const autoActivate = fm.autoactivate !== 'false';
521
+ const tags = fm.tags
522
+ ? fm.tags
523
+ .split(',')
524
+ .map((t) => t.trim())
525
+ .filter((t) => t.length > 0)
526
+ : undefined;
527
+ const tools = fm.tools
528
+ ? fm.tools
529
+ .split(',')
530
+ .map((t) => t.trim())
531
+ .filter((t) => t.length > 0)
532
+ : undefined;
533
+ const systemPromptAddition = body || '';
534
+ // Derive a default trigger from the skill name if none provided
535
+ if (triggers.length === 0) {
536
+ triggers.push(`\\b${name.replace(/[-_]/g, '[-_ ]?')}\\b`);
537
+ }
538
+ return {
539
+ name,
540
+ description,
541
+ triggers,
542
+ systemPromptAddition,
543
+ tools,
544
+ priority: Number.isNaN(priority) ? 50 : priority,
545
+ autoActivate,
546
+ source: filePath,
547
+ tags,
548
+ };
549
+ }
550
+ /**
551
+ * Test whether any trigger pattern matches the prompt.
552
+ * Returns the first matching pattern string, or null if none match.
553
+ */
554
+ matchTriggers(prompt, triggers) {
555
+ for (const pattern of triggers) {
556
+ try {
557
+ const regex = new RegExp(pattern, 'i');
558
+ if (regex.test(prompt)) {
559
+ return pattern;
560
+ }
561
+ }
562
+ catch {
563
+ // Invalid regex -- skip
564
+ }
565
+ }
566
+ return null;
567
+ }
568
+ /** Log skill activation to the console. */
569
+ logActivation(active) {
570
+ const by = active.activatedBy === 'auto' ? 'auto' : 'manual';
571
+ const reason = active.matchReason
572
+ ? ` (matched: ${active.matchReason})`
573
+ : '';
574
+ // eslint-disable-next-line no-console
575
+ console.log(`[skill-system] Activated skill "${active.skill.name}" via ${by}${reason}`);
576
+ }
577
+ }
578
+ //# sourceMappingURL=skill-system.js.map