k0ntext 3.0.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 (239) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +623 -0
  3. package/bin/k0ntext.js +12 -0
  4. package/dist/agents/cleanup-agent.d.ts +39 -0
  5. package/dist/agents/cleanup-agent.d.ts.map +1 -0
  6. package/dist/agents/cleanup-agent.js +56 -0
  7. package/dist/agents/cleanup-agent.js.map +1 -0
  8. package/dist/agents/performance-agent.d.ts +37 -0
  9. package/dist/agents/performance-agent.d.ts.map +1 -0
  10. package/dist/agents/performance-agent.js +91 -0
  11. package/dist/agents/performance-agent.js.map +1 -0
  12. package/dist/analyzer/index.d.ts +5 -0
  13. package/dist/analyzer/index.d.ts.map +1 -0
  14. package/dist/analyzer/index.js +5 -0
  15. package/dist/analyzer/index.js.map +1 -0
  16. package/dist/analyzer/intelligent-analyzer.d.ts +111 -0
  17. package/dist/analyzer/intelligent-analyzer.d.ts.map +1 -0
  18. package/dist/analyzer/intelligent-analyzer.js +537 -0
  19. package/dist/analyzer/intelligent-analyzer.js.map +1 -0
  20. package/dist/cli/commands/cleanup.d.ts +3 -0
  21. package/dist/cli/commands/cleanup.d.ts.map +1 -0
  22. package/dist/cli/commands/cleanup.js +24 -0
  23. package/dist/cli/commands/cleanup.js.map +1 -0
  24. package/dist/cli/commands/export.d.ts +9 -0
  25. package/dist/cli/commands/export.d.ts.map +1 -0
  26. package/dist/cli/commands/export.js +72 -0
  27. package/dist/cli/commands/export.js.map +1 -0
  28. package/dist/cli/commands/import.d.ts +9 -0
  29. package/dist/cli/commands/import.d.ts.map +1 -0
  30. package/dist/cli/commands/import.js +62 -0
  31. package/dist/cli/commands/import.js.map +1 -0
  32. package/dist/cli/commands/performance.d.ts +9 -0
  33. package/dist/cli/commands/performance.d.ts.map +1 -0
  34. package/dist/cli/commands/performance.js +36 -0
  35. package/dist/cli/commands/performance.js.map +1 -0
  36. package/dist/cli/commands/validate.d.ts +9 -0
  37. package/dist/cli/commands/validate.d.ts.map +1 -0
  38. package/dist/cli/commands/validate.js +82 -0
  39. package/dist/cli/commands/validate.js.map +1 -0
  40. package/dist/cli/commands/watch.d.ts +9 -0
  41. package/dist/cli/commands/watch.d.ts.map +1 -0
  42. package/dist/cli/commands/watch.js +72 -0
  43. package/dist/cli/commands/watch.js.map +1 -0
  44. package/dist/cli/generate.d.ts +3 -0
  45. package/dist/cli/generate.d.ts.map +1 -0
  46. package/dist/cli/generate.js +194 -0
  47. package/dist/cli/generate.js.map +1 -0
  48. package/dist/cli/index.d.ts +9 -0
  49. package/dist/cli/index.d.ts.map +1 -0
  50. package/dist/cli/index.js +448 -0
  51. package/dist/cli/index.js.map +1 -0
  52. package/dist/cli/sync.d.ts +26 -0
  53. package/dist/cli/sync.d.ts.map +1 -0
  54. package/dist/cli/sync.js +163 -0
  55. package/dist/cli/sync.js.map +1 -0
  56. package/dist/config/cleanup-config.d.ts +26 -0
  57. package/dist/config/cleanup-config.d.ts.map +1 -0
  58. package/dist/config/cleanup-config.js +21 -0
  59. package/dist/config/cleanup-config.js.map +1 -0
  60. package/dist/db/client.d.ts +284 -0
  61. package/dist/db/client.d.ts.map +1 -0
  62. package/dist/db/client.js +688 -0
  63. package/dist/db/client.js.map +1 -0
  64. package/dist/db/index.d.ts +6 -0
  65. package/dist/db/index.d.ts.map +1 -0
  66. package/dist/db/index.js +6 -0
  67. package/dist/db/index.js.map +1 -0
  68. package/dist/db/schema.d.ts +41 -0
  69. package/dist/db/schema.d.ts.map +1 -0
  70. package/dist/db/schema.js +226 -0
  71. package/dist/db/schema.js.map +1 -0
  72. package/dist/embeddings/index.d.ts +5 -0
  73. package/dist/embeddings/index.d.ts.map +1 -0
  74. package/dist/embeddings/index.js +5 -0
  75. package/dist/embeddings/index.js.map +1 -0
  76. package/dist/embeddings/openrouter.d.ts +133 -0
  77. package/dist/embeddings/openrouter.d.ts.map +1 -0
  78. package/dist/embeddings/openrouter.js +455 -0
  79. package/dist/embeddings/openrouter.js.map +1 -0
  80. package/dist/index.d.ts +14 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js +18 -0
  83. package/dist/index.js.map +1 -0
  84. package/dist/mcp.d.ts +29 -0
  85. package/dist/mcp.d.ts.map +1 -0
  86. package/dist/mcp.js +257 -0
  87. package/dist/mcp.js.map +1 -0
  88. package/docs/ARCHIVE/MIGRATE_TO_NEW_REPO.md +222 -0
  89. package/docs/ARCHIVE/MIGRATE_TO_UNIFIED.md +220 -0
  90. package/docs/CLEANUP.md +76 -0
  91. package/docs/MCP_QUICKSTART.md +219 -0
  92. package/docs/QUICKSTART.md +119 -0
  93. package/docs/TROUBLESHOOTING.md +611 -0
  94. package/package.json +100 -0
  95. package/skills/context-optimize/SKILL.md +86 -0
  96. package/skills/implement/SKILL.md +150 -0
  97. package/skills/plan/SKILL.md +143 -0
  98. package/skills/research/SKILL.md +103 -0
  99. package/skills/validate/SKILL.md +62 -0
  100. package/skills/verify-docs/SKILL.md +77 -0
  101. package/src/agents/cleanup-agent.ts +96 -0
  102. package/src/agents/performance-agent.ts +117 -0
  103. package/src/analyzer/index.ts +10 -0
  104. package/src/analyzer/intelligent-analyzer.ts +640 -0
  105. package/src/cli/commands/cleanup.ts +26 -0
  106. package/src/cli/commands/export.ts +82 -0
  107. package/src/cli/commands/import.ts +73 -0
  108. package/src/cli/commands/performance.ts +40 -0
  109. package/src/cli/commands/validate.ts +98 -0
  110. package/src/cli/commands/watch.ts +83 -0
  111. package/src/cli/generate.ts +219 -0
  112. package/src/cli/index.ts +510 -0
  113. package/src/cli/sync.ts +194 -0
  114. package/src/config/cleanup-config.ts +42 -0
  115. package/src/db/client.ts +949 -0
  116. package/src/db/index.ts +19 -0
  117. package/src/db/schema.ts +241 -0
  118. package/src/embeddings/index.ts +11 -0
  119. package/src/embeddings/openrouter.ts +592 -0
  120. package/src/index.ts +57 -0
  121. package/src/mcp.ts +354 -0
  122. package/templates/AI_CONTEXT.md.template +245 -0
  123. package/templates/base/README.md +260 -0
  124. package/templates/base/RPI_WORKFLOW_PLAN.md +325 -0
  125. package/templates/base/agents/api-developer.md +76 -0
  126. package/templates/base/agents/context-engineer.md +525 -0
  127. package/templates/base/agents/core-architect.md +76 -0
  128. package/templates/base/agents/database-ops.md +76 -0
  129. package/templates/base/agents/deployment-ops.md +76 -0
  130. package/templates/base/agents/integration-hub.md +76 -0
  131. package/templates/base/analytics/README.md +114 -0
  132. package/templates/base/automation/config.json +58 -0
  133. package/templates/base/automation/generators/code-mapper.js +308 -0
  134. package/templates/base/automation/generators/index-builder.js +321 -0
  135. package/templates/base/automation/hooks/post-commit.sh +83 -0
  136. package/templates/base/automation/hooks/pre-commit.sh +103 -0
  137. package/templates/base/ci-templates/README.md +108 -0
  138. package/templates/base/ci-templates/github-actions/context-check.yml +144 -0
  139. package/templates/base/ci-templates/github-actions/validate-docs.yml +105 -0
  140. package/templates/base/commands/analytics.md +238 -0
  141. package/templates/base/commands/auto-sync.md +172 -0
  142. package/templates/base/commands/collab.md +194 -0
  143. package/templates/base/commands/context-optimize.md +226 -0
  144. package/templates/base/commands/help.md +485 -0
  145. package/templates/base/commands/rpi-implement.md +164 -0
  146. package/templates/base/commands/rpi-plan.md +147 -0
  147. package/templates/base/commands/rpi-research.md +145 -0
  148. package/templates/base/commands/session-resume.md +144 -0
  149. package/templates/base/commands/session-save.md +112 -0
  150. package/templates/base/commands/validate-all.md +77 -0
  151. package/templates/base/commands/verify-docs-current.md +86 -0
  152. package/templates/base/config/base.json +57 -0
  153. package/templates/base/config/environments/development.json +13 -0
  154. package/templates/base/config/environments/production.json +17 -0
  155. package/templates/base/config/environments/staging.json +13 -0
  156. package/templates/base/config/local.json.example +21 -0
  157. package/templates/base/context/.meta/generated-at.json +18 -0
  158. package/templates/base/context/ARCHITECTURE_SNAPSHOT.md +156 -0
  159. package/templates/base/context/CODE_TO_WORKFLOW_MAP.md +94 -0
  160. package/templates/base/context/FILE_OWNERSHIP.md +57 -0
  161. package/templates/base/context/INTEGRATION_POINTS.md +92 -0
  162. package/templates/base/context/KNOWN_GOTCHAS.md +195 -0
  163. package/templates/base/context/TESTING_MAP.md +95 -0
  164. package/templates/base/context/WORKFLOW_INDEX.md +129 -0
  165. package/templates/base/context/workflows/WORKFLOW_TEMPLATE.md +294 -0
  166. package/templates/base/indexes/agents/CAPABILITY_MATRIX.md +255 -0
  167. package/templates/base/indexes/agents/CATEGORY_INDEX.md +44 -0
  168. package/templates/base/indexes/code/CATEGORY_INDEX.md +38 -0
  169. package/templates/base/indexes/routing/CATEGORY_INDEX.md +39 -0
  170. package/templates/base/indexes/search/CATEGORY_INDEX.md +39 -0
  171. package/templates/base/indexes/workflows/CATEGORY_INDEX.md +38 -0
  172. package/templates/base/knowledge/README.md +98 -0
  173. package/templates/base/knowledge/sessions/README.md +88 -0
  174. package/templates/base/knowledge/sessions/TEMPLATE.md +150 -0
  175. package/templates/base/knowledge/shared/decisions/0001-adopt-context-engineering.md +144 -0
  176. package/templates/base/knowledge/shared/decisions/README.md +49 -0
  177. package/templates/base/knowledge/shared/decisions/TEMPLATE.md +123 -0
  178. package/templates/base/knowledge/shared/patterns/README.md +62 -0
  179. package/templates/base/knowledge/shared/patterns/TEMPLATE.md +120 -0
  180. package/templates/base/plans/PLAN_TEMPLATE.md +316 -0
  181. package/templates/base/plans/active/.gitkeep +0 -0
  182. package/templates/base/plans/completed/.gitkeep +0 -0
  183. package/templates/base/research/RESEARCH_TEMPLATE.md +245 -0
  184. package/templates/base/research/active/.gitkeep +0 -0
  185. package/templates/base/research/completed/.gitkeep +0 -0
  186. package/templates/base/schemas/agent.schema.json +141 -0
  187. package/templates/base/schemas/anchors.schema.json +54 -0
  188. package/templates/base/schemas/automation.schema.json +93 -0
  189. package/templates/base/schemas/command.schema.json +134 -0
  190. package/templates/base/schemas/hashes.schema.json +40 -0
  191. package/templates/base/schemas/manifest.schema.json +117 -0
  192. package/templates/base/schemas/plan.schema.json +136 -0
  193. package/templates/base/schemas/research.schema.json +115 -0
  194. package/templates/base/schemas/roles.schema.json +34 -0
  195. package/templates/base/schemas/session.schema.json +77 -0
  196. package/templates/base/schemas/settings.schema.json +244 -0
  197. package/templates/base/schemas/staleness.schema.json +53 -0
  198. package/templates/base/schemas/team-config.schema.json +42 -0
  199. package/templates/base/schemas/workflow.schema.json +126 -0
  200. package/templates/base/session/checkpoints/.gitkeep +2 -0
  201. package/templates/base/session/current/state.json +20 -0
  202. package/templates/base/session/history/.gitkeep +2 -0
  203. package/templates/base/settings.json +3 -0
  204. package/templates/base/standards/COMPATIBILITY.md +219 -0
  205. package/templates/base/standards/EXTENSION_GUIDELINES.md +280 -0
  206. package/templates/base/standards/QUALITY_CHECKLIST.md +211 -0
  207. package/templates/base/standards/README.md +66 -0
  208. package/templates/base/sync/anchors.json +6 -0
  209. package/templates/base/sync/hashes.json +6 -0
  210. package/templates/base/sync/staleness.json +10 -0
  211. package/templates/base/team/README.md +168 -0
  212. package/templates/base/team/config.json +79 -0
  213. package/templates/base/team/roles.json +145 -0
  214. package/templates/base/tools/bin/claude-context.js +151 -0
  215. package/templates/base/tools/lib/anchor-resolver.js +276 -0
  216. package/templates/base/tools/lib/config-loader.js +363 -0
  217. package/templates/base/tools/lib/detector.js +350 -0
  218. package/templates/base/tools/lib/diagnose.js +206 -0
  219. package/templates/base/tools/lib/drift-detector.js +373 -0
  220. package/templates/base/tools/lib/errors.js +199 -0
  221. package/templates/base/tools/lib/index.js +36 -0
  222. package/templates/base/tools/lib/init.js +192 -0
  223. package/templates/base/tools/lib/logger.js +230 -0
  224. package/templates/base/tools/lib/placeholder.js +201 -0
  225. package/templates/base/tools/lib/session-manager.js +354 -0
  226. package/templates/base/tools/lib/validate.js +521 -0
  227. package/templates/base/tools/package.json +49 -0
  228. package/templates/handlebars/aider-config.hbs +146 -0
  229. package/templates/handlebars/antigravity.hbs +377 -0
  230. package/templates/handlebars/claude.hbs +183 -0
  231. package/templates/handlebars/cline.hbs +62 -0
  232. package/templates/handlebars/continue-config.hbs +116 -0
  233. package/templates/handlebars/copilot.hbs +130 -0
  234. package/templates/handlebars/partials/gotcha-list.hbs +11 -0
  235. package/templates/handlebars/partials/header.hbs +3 -0
  236. package/templates/handlebars/partials/workflow-summary.hbs +16 -0
  237. package/templates/handlebars/windsurf-rules.hbs +69 -0
  238. package/templates/hooks/post-commit.hbs +28 -0
  239. package/templates/hooks/pre-commit.hbs +46 -0
@@ -0,0 +1,640 @@
1
+ /**
2
+ * Intelligent Analyzer
3
+ *
4
+ * Uses OpenRouter API to intelligently analyze codebases, docs, and tool configurations.
5
+ * This is the core of the "forcefully intelligent" initialization.
6
+ */
7
+
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import { glob } from 'glob';
11
+ import { OpenRouterClient, createOpenRouterClient, hasOpenRouterKey } from '../embeddings/openrouter.js';
12
+ import { AI_TOOLS, AI_TOOL_FOLDERS, type AITool } from '../db/schema.js';
13
+
14
+ /**
15
+ * Discovery result for a file
16
+ */
17
+ export interface DiscoveredFile {
18
+ path: string;
19
+ relativePath: string;
20
+ type: 'doc' | 'code' | 'config' | 'tool_config';
21
+ tool?: AITool;
22
+ size: number;
23
+ content?: string;
24
+ }
25
+
26
+ /**
27
+ * Analysis result
28
+ */
29
+ export interface AnalysisResult {
30
+ summary: string;
31
+ techStack: {
32
+ languages: string[];
33
+ frameworks: string[];
34
+ tools: string[];
35
+ };
36
+ workflows: Array<{
37
+ name: string;
38
+ description: string;
39
+ entryPoint: string;
40
+ steps: string[];
41
+ }>;
42
+ architecture: {
43
+ pattern: string;
44
+ components: string[];
45
+ integrations: string[];
46
+ };
47
+ existingContext: {
48
+ tools: AITool[];
49
+ files: DiscoveredFile[];
50
+ };
51
+ suggestions: {
52
+ contextFiles: string[];
53
+ workflows: string[];
54
+ agents: string[];
55
+ commands: string[];
56
+ };
57
+ }
58
+
59
+ /**
60
+ * Default ignore patterns
61
+ */
62
+ const DEFAULT_IGNORE = [
63
+ '**/node_modules/**',
64
+ '**/dist/**',
65
+ '**/build/**',
66
+ '**/.git/**',
67
+ '**/vendor/**',
68
+ '**/__pycache__/**',
69
+ '**/target/**',
70
+ '**/bin/**',
71
+ '**/obj/**',
72
+ '**/.next/**',
73
+ '**/.nuxt/**',
74
+ '**/*.min.js',
75
+ '**/*.map',
76
+ '**/package-lock.json',
77
+ '**/yarn.lock',
78
+ '**/pnpm-lock.yaml'
79
+ ];
80
+
81
+ /**
82
+ * Intelligent analyzer using OpenRouter
83
+ */
84
+ export class IntelligentAnalyzer {
85
+ private client: OpenRouterClient | null = null;
86
+ private projectRoot: string;
87
+
88
+ constructor(projectRoot: string) {
89
+ this.projectRoot = projectRoot;
90
+
91
+ // Try to create client if API key available
92
+ if (hasOpenRouterKey()) {
93
+ try {
94
+ this.client = createOpenRouterClient();
95
+ } catch (error) {
96
+ console.warn('OpenRouter client initialization failed:', error);
97
+ }
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Check if intelligent analysis is available
103
+ */
104
+ isIntelligentModeAvailable(): boolean {
105
+ return this.client !== null;
106
+ }
107
+
108
+ /**
109
+ * Discover all documentation files (.md files)
110
+ */
111
+ async discoverDocs(): Promise<DiscoveredFile[]> {
112
+ const files: DiscoveredFile[] = [];
113
+
114
+ const mdFiles = await glob('**/*.md', {
115
+ cwd: this.projectRoot,
116
+ ignore: DEFAULT_IGNORE,
117
+ absolute: true
118
+ });
119
+
120
+ for (const filePath of mdFiles) {
121
+ const stats = fs.statSync(filePath);
122
+ files.push({
123
+ path: filePath,
124
+ relativePath: path.relative(this.projectRoot, filePath),
125
+ type: 'doc',
126
+ size: stats.size
127
+ });
128
+ }
129
+
130
+ return files;
131
+ }
132
+
133
+ /**
134
+ * Discover AI tool configurations
135
+ */
136
+ async discoverToolConfigs(): Promise<DiscoveredFile[]> {
137
+ const files: DiscoveredFile[] = [];
138
+
139
+ for (const tool of AI_TOOLS) {
140
+ const patterns = AI_TOOL_FOLDERS[tool];
141
+
142
+ for (const pattern of patterns) {
143
+ const fullPath = path.join(this.projectRoot, pattern);
144
+
145
+ if (fs.existsSync(fullPath)) {
146
+ const stats = fs.statSync(fullPath);
147
+
148
+ if (stats.isDirectory()) {
149
+ // Scan directory contents
150
+ const dirFiles = await glob('**/*', {
151
+ cwd: fullPath,
152
+ nodir: true,
153
+ absolute: true
154
+ });
155
+
156
+ for (const filePath of dirFiles) {
157
+ const fileStats = fs.statSync(filePath);
158
+ files.push({
159
+ path: filePath,
160
+ relativePath: path.relative(this.projectRoot, filePath),
161
+ type: 'tool_config',
162
+ tool,
163
+ size: fileStats.size
164
+ });
165
+ }
166
+ } else {
167
+ files.push({
168
+ path: fullPath,
169
+ relativePath: pattern,
170
+ type: 'tool_config',
171
+ tool,
172
+ size: stats.size
173
+ });
174
+ }
175
+ }
176
+ }
177
+ }
178
+
179
+ return files;
180
+ }
181
+
182
+ /**
183
+ * Discover source code files
184
+ */
185
+ async discoverCode(): Promise<DiscoveredFile[]> {
186
+ const files: DiscoveredFile[] = [];
187
+
188
+ const codePatterns = [
189
+ '**/*.js', '**/*.ts', '**/*.tsx', '**/*.jsx',
190
+ '**/*.py', '**/*.go', '**/*.rs', '**/*.java',
191
+ '**/*.cs', '**/*.rb', '**/*.php'
192
+ ];
193
+
194
+ for (const pattern of codePatterns) {
195
+ const codeFiles = await glob(pattern, {
196
+ cwd: this.projectRoot,
197
+ ignore: DEFAULT_IGNORE,
198
+ absolute: true
199
+ });
200
+
201
+ for (const filePath of codeFiles) {
202
+ const stats = fs.statSync(filePath);
203
+ files.push({
204
+ path: filePath,
205
+ relativePath: path.relative(this.projectRoot, filePath),
206
+ type: 'code',
207
+ size: stats.size
208
+ });
209
+ }
210
+ }
211
+
212
+ return files;
213
+ }
214
+
215
+ /**
216
+ * Read file content safely
217
+ */
218
+ private readFileContent(filePath: string, maxBytes: number = 50000): string | null {
219
+ let fd: number | null = null;
220
+ try {
221
+ const stats = fs.statSync(filePath);
222
+ if (stats.size > maxBytes) {
223
+ // Read only first part of large files
224
+ fd = fs.openSync(filePath, 'r');
225
+ const buffer = Buffer.alloc(maxBytes);
226
+ fs.readSync(fd, buffer, 0, maxBytes, 0);
227
+ return buffer.toString('utf-8') + '\n\n... [truncated]';
228
+ }
229
+ return fs.readFileSync(filePath, 'utf-8');
230
+ } catch {
231
+ return null;
232
+ } finally {
233
+ if (fd !== null) {
234
+ try {
235
+ fs.closeSync(fd);
236
+ } catch {
237
+ // Ignore errors when closing the file descriptor
238
+ }
239
+ }
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Perform full intelligent analysis
245
+ */
246
+ async analyze(): Promise<AnalysisResult> {
247
+ // Discover all files
248
+ const [docs, toolConfigs, codeFiles] = await Promise.all([
249
+ this.discoverDocs(),
250
+ this.discoverToolConfigs(),
251
+ this.discoverCode()
252
+ ]);
253
+
254
+ // Determine which AI tools are already configured
255
+ const configuredTools = new Set<AITool>();
256
+ for (const config of toolConfigs) {
257
+ if (config.tool) {
258
+ configuredTools.add(config.tool);
259
+ }
260
+ }
261
+
262
+ // Basic analysis (without AI)
263
+ const basicResult: AnalysisResult = {
264
+ summary: '',
265
+ techStack: this.detectTechStackBasic(codeFiles),
266
+ workflows: [],
267
+ architecture: {
268
+ pattern: 'unknown',
269
+ components: [],
270
+ integrations: []
271
+ },
272
+ existingContext: {
273
+ tools: Array.from(configuredTools),
274
+ files: [...docs, ...toolConfigs]
275
+ },
276
+ suggestions: {
277
+ contextFiles: [],
278
+ workflows: [],
279
+ agents: [],
280
+ commands: []
281
+ }
282
+ };
283
+
284
+ // If OpenRouter is available, perform intelligent analysis
285
+ if (this.client) {
286
+ try {
287
+ const intelligentResult = await this.performIntelligentAnalysis(docs, toolConfigs, codeFiles);
288
+ return {
289
+ ...basicResult,
290
+ ...intelligentResult,
291
+ existingContext: basicResult.existingContext
292
+ };
293
+ } catch (error) {
294
+ console.warn('Intelligent analysis failed, falling back to basic:', error);
295
+ }
296
+ }
297
+
298
+ // Generate basic summary
299
+ basicResult.summary = this.generateBasicSummary(docs, toolConfigs, codeFiles, basicResult.techStack);
300
+
301
+ return basicResult;
302
+ }
303
+
304
+ /**
305
+ * Detect tech stack without AI
306
+ */
307
+ private detectTechStackBasic(codeFiles: DiscoveredFile[]): AnalysisResult['techStack'] {
308
+ const languages = new Set<string>();
309
+ const frameworks = new Set<string>();
310
+ const tools = new Set<string>();
311
+
312
+ // Detect languages from file extensions
313
+ for (const file of codeFiles) {
314
+ const ext = path.extname(file.relativePath).toLowerCase();
315
+ switch (ext) {
316
+ case '.js':
317
+ case '.mjs':
318
+ case '.cjs':
319
+ languages.add('JavaScript');
320
+ break;
321
+ case '.ts':
322
+ case '.tsx':
323
+ languages.add('TypeScript');
324
+ break;
325
+ case '.py':
326
+ languages.add('Python');
327
+ break;
328
+ case '.go':
329
+ languages.add('Go');
330
+ break;
331
+ case '.rs':
332
+ languages.add('Rust');
333
+ break;
334
+ case '.java':
335
+ languages.add('Java');
336
+ break;
337
+ case '.cs':
338
+ languages.add('C#');
339
+ break;
340
+ case '.rb':
341
+ languages.add('Ruby');
342
+ break;
343
+ case '.php':
344
+ languages.add('PHP');
345
+ break;
346
+ }
347
+ }
348
+
349
+ // Check for common framework indicators
350
+ const packageJsonPath = path.join(this.projectRoot, 'package.json');
351
+ if (fs.existsSync(packageJsonPath)) {
352
+ try {
353
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
354
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
355
+
356
+ if (deps.react) frameworks.add('React');
357
+ if (deps.vue) frameworks.add('Vue');
358
+ if (deps.angular || deps['@angular/core']) frameworks.add('Angular');
359
+ if (deps.express) frameworks.add('Express');
360
+ if (deps.fastify) frameworks.add('Fastify');
361
+ if (deps.next) frameworks.add('Next.js');
362
+ if (deps.nest || deps['@nestjs/core']) frameworks.add('NestJS');
363
+
364
+ tools.add('npm');
365
+ } catch {
366
+ // Ignore parse errors
367
+ }
368
+ }
369
+
370
+ // Check for Python indicators
371
+ const requirementsTxtPath = path.join(this.projectRoot, 'requirements.txt');
372
+ const pyprojectPath = path.join(this.projectRoot, 'pyproject.toml');
373
+ if (fs.existsSync(requirementsTxtPath) || fs.existsSync(pyprojectPath)) {
374
+ tools.add('pip');
375
+ if (fs.existsSync(pyprojectPath)) {
376
+ tools.add('poetry');
377
+ }
378
+ }
379
+
380
+ return {
381
+ languages: Array.from(languages),
382
+ frameworks: Array.from(frameworks),
383
+ tools: Array.from(tools)
384
+ };
385
+ }
386
+
387
+ /**
388
+ * Perform intelligent analysis using OpenRouter
389
+ */
390
+ private async performIntelligentAnalysis(
391
+ docs: DiscoveredFile[],
392
+ toolConfigs: DiscoveredFile[],
393
+ codeFiles: DiscoveredFile[]
394
+ ): Promise<Partial<AnalysisResult>> {
395
+ if (!this.client) {
396
+ throw new Error('OpenRouter client not available');
397
+ }
398
+
399
+ // Gather sample content for analysis
400
+ const sampleContent: string[] = [];
401
+
402
+ // Add README and main docs
403
+ const importantDocs = docs.filter(d =>
404
+ d.relativePath.toLowerCase().includes('readme') ||
405
+ d.relativePath.toLowerCase().includes('claude') ||
406
+ d.relativePath.toLowerCase().includes('context')
407
+ ).slice(0, 5);
408
+
409
+ for (const doc of importantDocs) {
410
+ const content = this.readFileContent(doc.path, 10000);
411
+ if (content) {
412
+ sampleContent.push(`## File: ${doc.relativePath}\n\n${content}`);
413
+ }
414
+ }
415
+
416
+ // Add tool configs
417
+ for (const config of toolConfigs.slice(0, 5)) {
418
+ const content = this.readFileContent(config.path, 5000);
419
+ if (content) {
420
+ sampleContent.push(`## Tool Config (${config.tool}): ${config.relativePath}\n\n${content}`);
421
+ }
422
+ }
423
+
424
+ // Add sample code files (entry points)
425
+ const entryPoints = codeFiles.filter(f =>
426
+ f.relativePath.includes('index.') ||
427
+ f.relativePath.includes('main.') ||
428
+ f.relativePath.includes('app.') ||
429
+ f.relativePath.includes('server.')
430
+ ).slice(0, 5);
431
+
432
+ for (const code of entryPoints) {
433
+ const content = this.readFileContent(code.path, 8000);
434
+ if (content) {
435
+ sampleContent.push(`## Code: ${code.relativePath}\n\n${content}`);
436
+ }
437
+ }
438
+
439
+ // Create analysis prompt
440
+ const analysisPrompt = `
441
+ Analyze this codebase content and provide a structured analysis:
442
+
443
+ ${sampleContent.join('\n\n---\n\n')}
444
+
445
+ Provide your analysis in the following JSON format:
446
+ {
447
+ "summary": "Brief description of what this project does",
448
+ "techStack": {
449
+ "languages": ["list of programming languages"],
450
+ "frameworks": ["list of frameworks"],
451
+ "tools": ["list of tools and libraries"]
452
+ },
453
+ "workflows": [
454
+ {
455
+ "name": "workflow name",
456
+ "description": "what it does",
457
+ "entryPoint": "file:line",
458
+ "steps": ["step 1", "step 2"]
459
+ }
460
+ ],
461
+ "architecture": {
462
+ "pattern": "architectural pattern (e.g., MVC, microservices)",
463
+ "components": ["main components"],
464
+ "integrations": ["external integrations"]
465
+ },
466
+ "suggestions": {
467
+ "contextFiles": ["suggested context files to create"],
468
+ "workflows": ["workflows to document"],
469
+ "agents": ["agents that would be useful"],
470
+ "commands": ["commands to implement"]
471
+ }
472
+ }
473
+
474
+ Return ONLY valid JSON, no markdown formatting.
475
+ `;
476
+
477
+ let response: string = '';
478
+ try {
479
+ response = await this.client.chat([
480
+ {
481
+ role: 'system',
482
+ content: 'You are an expert code analyzer and AI context engineer. Analyze codebases to understand their structure, workflows, and suggest optimal AI context configurations. Always return valid JSON.'
483
+ },
484
+ { role: 'user', content: analysisPrompt }
485
+ ], { temperature: 0.2, maxTokens: 4096 });
486
+
487
+ // First, try to parse the whole response as JSON.
488
+ try {
489
+ return JSON.parse(response);
490
+ } catch {
491
+ // If that fails, attempt to extract the JSON substring between the
492
+ // first '{' and the last '}' and parse that.
493
+ if (typeof response === 'string') {
494
+ const start = response.indexOf('{');
495
+ const end = response.lastIndexOf('}');
496
+
497
+ if (start !== -1 && end !== -1 && end > start) {
498
+ const jsonSubstring = response.slice(start, end + 1);
499
+ return JSON.parse(jsonSubstring);
500
+ }
501
+ }
502
+ }
503
+ } catch (error) {
504
+ console.warn('Failed to parse intelligent analysis response.');
505
+ // Log a preview of the raw response to aid debugging of malformed JSON.
506
+ try {
507
+ const preview = typeof response === 'string'
508
+ ? response.slice(0, 1000)
509
+ : JSON.stringify(response).slice(0, 1000);
510
+ console.warn('Raw response preview (truncated to 1000 chars):', preview);
511
+ } catch {
512
+ // If preview logging fails for any reason, ignore and just log the error.
513
+ }
514
+ console.warn('Error details:', error);
515
+ }
516
+
517
+ return {};
518
+ }
519
+
520
+ /**
521
+ * Generate basic summary without AI
522
+ */
523
+ private generateBasicSummary(
524
+ docs: DiscoveredFile[],
525
+ toolConfigs: DiscoveredFile[],
526
+ codeFiles: DiscoveredFile[],
527
+ techStack: AnalysisResult['techStack']
528
+ ): string {
529
+ const parts: string[] = [];
530
+
531
+ parts.push(`Project Analysis Summary`);
532
+ parts.push(`========================`);
533
+ parts.push(``);
534
+ parts.push(`**Files Discovered:**`);
535
+ parts.push(`- Documentation: ${docs.length} files`);
536
+ parts.push(`- Source Code: ${codeFiles.length} files`);
537
+ parts.push(`- AI Tool Configs: ${toolConfigs.length} files`);
538
+ parts.push(``);
539
+ parts.push(`**Tech Stack:**`);
540
+ if (techStack.languages.length > 0) {
541
+ parts.push(`- Languages: ${techStack.languages.join(', ')}`);
542
+ }
543
+ if (techStack.frameworks.length > 0) {
544
+ parts.push(`- Frameworks: ${techStack.frameworks.join(', ')}`);
545
+ }
546
+ if (techStack.tools.length > 0) {
547
+ parts.push(`- Tools: ${techStack.tools.join(', ')}`);
548
+ }
549
+
550
+ return parts.join('\n');
551
+ }
552
+
553
+ /**
554
+ * Generate embeddings for discovered content
555
+ */
556
+ async generateEmbeddings(files: DiscoveredFile[]): Promise<Map<string, number[]>> {
557
+ if (!this.client) {
558
+ throw new Error('OpenRouter client not available for embeddings');
559
+ }
560
+
561
+ const embeddings = new Map<string, number[]>();
562
+
563
+ // Process in batches
564
+ const batchSize = 10;
565
+ for (let i = 0; i < files.length; i += batchSize) {
566
+ const batch = files.slice(i, i + batchSize);
567
+ const texts: string[] = [];
568
+ const paths: string[] = [];
569
+
570
+ for (const file of batch) {
571
+ const content = this.readFileContent(file.path, 8000);
572
+ if (content) {
573
+ texts.push(`File: ${file.relativePath}\n\n${content}`);
574
+ paths.push(file.relativePath);
575
+ }
576
+ }
577
+
578
+ if (texts.length > 0) {
579
+ const batchEmbeddings = await this.client.embedBatch(texts);
580
+ for (let j = 0; j < paths.length; j++) {
581
+ embeddings.set(paths[j], batchEmbeddings[j]);
582
+ }
583
+ }
584
+ }
585
+
586
+ return embeddings;
587
+ }
588
+
589
+ /**
590
+ * Generate embedding for a single text string (e.g., search query)
591
+ */
592
+ async embedText(text: string): Promise<number[]> {
593
+ if (!this.client) {
594
+ throw new Error('OpenRouter client not available for embeddings');
595
+ }
596
+ return this.client.embed(text);
597
+ }
598
+
599
+ /**
600
+ * Set up file watcher for automatic re-indexing
601
+ */
602
+ setupFileWatcher(onChange: (filePath: string) => Promise<void>): () => void {
603
+ // Check if chokidar is available
604
+ let chokidar: unknown;
605
+ try {
606
+ chokidar = require('chokidar');
607
+ } catch {
608
+ console.warn('chokidar not available. File watching disabled. Install with: npm install chokidar');
609
+ return () => {};
610
+ }
611
+
612
+ const watchPaths = [
613
+ path.join(this.projectRoot, 'src'),
614
+ path.join(this.projectRoot, 'lib'),
615
+ path.join(this.projectRoot, '.claude'),
616
+ path.join(this.projectRoot, 'CLAUDE.md'),
617
+ path.join(this.projectRoot, 'README.md'),
618
+ path.join(this.projectRoot, 'docs')
619
+ ];
620
+
621
+ const watcher = (chokidar as any).watch(watchPaths, {
622
+ ignored: /node_modules|\.git|dist/,
623
+ persistent: true,
624
+ ignoreInitial: true
625
+ });
626
+
627
+ watcher.on('change', async (filePath: string) => {
628
+ await onChange(filePath);
629
+ });
630
+
631
+ return () => watcher.close();
632
+ }
633
+ }
634
+
635
+ /**
636
+ * Create an intelligent analyzer
637
+ */
638
+ export function createIntelligentAnalyzer(projectRoot: string): IntelligentAnalyzer {
639
+ return new IntelligentAnalyzer(projectRoot);
640
+ }
@@ -0,0 +1,26 @@
1
+ import { Command } from 'commander';
2
+ import { CleanupAgent } from '../../agents/cleanup-agent.js';
3
+
4
+ export const cleanupCommand = new Command('cleanup')
5
+ .description('Clean up context folders from other AI tools')
6
+ .option('--dry-run', 'Show what would be removed')
7
+ .option('--keep <folders>', 'Folders to keep (comma-separated)')
8
+ .option('-v, --verbose', 'Show detailed output')
9
+ .action(async (options) => {
10
+ const agent = new CleanupAgent();
11
+ // Pass only the options that have values
12
+ const result = await agent.cleanup({
13
+ dryRun: !!options.dryRun,
14
+ keep: options.keep ? options.keep.split(',') : undefined,
15
+ verbose: !!options.verbose,
16
+ });
17
+
18
+ console.log(`\nCleanup complete:`);
19
+ console.log(` Scanned: ${result.scanned} tool folders`);
20
+ console.log(` Removed: ${result.removed.length}`);
21
+ console.log(` Kept: ${result.kept.length}`);
22
+
23
+ if (result.errors.length > 0) {
24
+ console.log(` Errors: ${result.errors.length}`);
25
+ }
26
+ });