codehere 0.2.1 → 0.3.0-rc.1

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 (235) hide show
  1. package/README.md +88 -68
  2. package/dist/domain/entities/task.js +4 -4
  3. package/dist/error-handler.js +4 -9
  4. package/dist/index.js +253 -1219
  5. package/dist/infrastructure/config/product-context.js +7 -6
  6. package/dist/infrastructure/hooks/claude-sdk-hook.js +335 -63
  7. package/dist/infrastructure/observability/execution-tracer.js +11 -6
  8. package/dist/infrastructure/orchestration/agent-adapter.js +13 -0
  9. package/dist/infrastructure/orchestration/agent-installer.js +101 -0
  10. package/dist/infrastructure/orchestration/agents-config-seed.js +56 -0
  11. package/dist/infrastructure/orchestration/aider-adapter.js +319 -0
  12. package/dist/infrastructure/orchestration/artifacts-extractor.js +175 -0
  13. package/dist/infrastructure/orchestration/claude-code-adapter.js +352 -0
  14. package/dist/infrastructure/orchestration/codex-adapter.js +310 -0
  15. package/dist/infrastructure/orchestration/generic-cli-adapter.js +553 -0
  16. package/dist/infrastructure/orchestration/opencode-adapter.js +275 -0
  17. package/dist/infrastructure/orchestration/progress-aggregator.js +189 -0
  18. package/dist/infrastructure/orchestration/readiness.js +106 -0
  19. package/dist/infrastructure/orchestration/session-manager.js +272 -0
  20. package/dist/infrastructure/orchestration/session-persistence.js +109 -0
  21. package/dist/infrastructure/protocols/mcp-helpers.js +10 -30
  22. package/dist/infrastructure/protocols/mcp-server-impl.js +359 -21
  23. package/dist/infrastructure/protocols/ui-page.js +1827 -0
  24. package/dist/infrastructure/security/file-collection.js +115 -0
  25. package/dist/infrastructure/security/trust-scorer.js +301 -56
  26. package/dist/infrastructure/storage/task-repository.js +8 -7
  27. package/dist/monitoring.js +10 -49
  28. package/dist/presentation/cli/commands/help-command.js +96 -139
  29. package/dist/presentation/cli/commands/hook-command.js +17 -24
  30. package/dist/presentation/cli/commands/report-command.js +59 -72
  31. package/dist/presentation/cli/commands/setup-command.js +4 -4
  32. package/dist/presentation/cli/commands/status-command.js +334 -43
  33. package/dist/presentation/cli/commands/trust-command.js +115 -99
  34. package/dist/presentation/cli/error-display.js +17 -21
  35. package/dist/ui.js +17 -12
  36. package/package.json +35 -67
  37. package/dist/agents/base.js +0 -101
  38. package/dist/agents/orchestrator-model-driven.js +0 -141
  39. package/dist/agents/react-orchestrator-agent.js +0 -54
  40. package/dist/application/agents/execution-agent.js +0 -508
  41. package/dist/application/agents/multi-agent-orchestrator.js +0 -295
  42. package/dist/application/agents/planning-agent.js +0 -433
  43. package/dist/application/agents/validation-agent.js +0 -317
  44. package/dist/application/architectures/plan-and-act.js +0 -242
  45. package/dist/application/index.js +0 -12
  46. package/dist/application/services/agent-factory.js +0 -28
  47. package/dist/application/services/dependency-container.js +0 -596
  48. package/dist/application/services/git-context-service.js +0 -83
  49. package/dist/application/services/intelligent-router.js +0 -934
  50. package/dist/application/services/tool-executor-service.js +0 -94
  51. package/dist/application/use-cases/ask-question-use-case.js +0 -338
  52. package/dist/application/use-cases/edit-file-use-case.js +0 -830
  53. package/dist/application/use-cases/explain-file-use-case.js +0 -50
  54. package/dist/application/use-cases/index-codebase-use-case.js +0 -113
  55. package/dist/application/use-cases/planning-use-case.js +0 -276
  56. package/dist/application/use-cases/react-orchestration-use-case.js +0 -329
  57. package/dist/application/use-cases/reflexion-use-case.js +0 -30
  58. package/dist/application/workflows/deterministic-workflows.js +0 -189
  59. package/dist/ast-parser.js +0 -331
  60. package/dist/cache.js +0 -180
  61. package/dist/chat.js +0 -251
  62. package/dist/code-analysis.js +0 -327
  63. package/dist/context.js +0 -187
  64. package/dist/docs.js +0 -146
  65. package/dist/domain/entities/code-chunk.js +0 -6
  66. package/dist/domain/entities/decision.js +0 -9
  67. package/dist/domain/entities/edit.js +0 -6
  68. package/dist/domain/entities/knowledge-node.js +0 -9
  69. package/dist/domain/entities/knowledge-preservation.js +0 -10
  70. package/dist/domain/entities/memory.js +0 -6
  71. package/dist/domain/entities/pattern.js +0 -7
  72. package/dist/domain/entities/plan.js +0 -6
  73. package/dist/domain/entities/query.js +0 -6
  74. package/dist/domain/errors/embeddings-not-found-error.js +0 -13
  75. package/dist/domain/index.js +0 -19
  76. package/dist/domain/interfaces/ai-service.interface.js +0 -6
  77. package/dist/domain/interfaces/code-analyzer.interface.js +0 -6
  78. package/dist/domain/interfaces/decision-repository.interface.js +0 -9
  79. package/dist/domain/interfaces/embedding-repository.interface.js +0 -6
  80. package/dist/domain/interfaces/knowledge-graph-repository.interface.js +0 -9
  81. package/dist/domain/interfaces/knowledge-preservation-repository.interface.js +0 -8
  82. package/dist/domain/interfaces/memory-repository.interface.js +0 -6
  83. package/dist/domain/interfaces/pattern-repository.interface.js +0 -6
  84. package/dist/domain/interfaces/verification-service.interface.js +0 -6
  85. package/dist/domain/services/cross-team-pattern-sharing.js +0 -125
  86. package/dist/domain/services/decision-recorder.js +0 -223
  87. package/dist/domain/services/decision-retriever.js +0 -133
  88. package/dist/domain/services/environment-mode-manager.js +0 -22
  89. package/dist/domain/services/graded-memory-activation.js +0 -69
  90. package/dist/domain/services/knowledge-access.js +0 -132
  91. package/dist/domain/services/knowledge-extractor.js +0 -247
  92. package/dist/domain/services/knowledge-graph-builder.js +0 -268
  93. package/dist/domain/services/knowledge-graph-query.js +0 -187
  94. package/dist/domain/services/memory-retriever.js +0 -82
  95. package/dist/domain/services/memory-synthesizer.js +0 -91
  96. package/dist/domain/services/pattern-extractor.js +0 -442
  97. package/dist/domain/services/query-intent-classifier.js +0 -140
  98. package/dist/domain/services/react-loop.js +0 -186
  99. package/dist/domain/services/risk-tier-detector.js +0 -78
  100. package/dist/edit.js +0 -319
  101. package/dist/embed.js +0 -459
  102. package/dist/formatter.js +0 -168
  103. package/dist/git.js +0 -198
  104. package/dist/infrastructure/ai/cohere-ai-service.js +0 -607
  105. package/dist/infrastructure/ai/command-r-evaluation.js +0 -206
  106. package/dist/infrastructure/ai/model-config.js +0 -84
  107. package/dist/infrastructure/ai/provider-ai-service.js +0 -477
  108. package/dist/infrastructure/cache/embedding-cache.js +0 -175
  109. package/dist/infrastructure/cache/query-result-cache.js +0 -66
  110. package/dist/infrastructure/cache/response-cache.js +0 -48
  111. package/dist/infrastructure/cache/security-scan-cache.js +0 -47
  112. package/dist/infrastructure/chunking/ast-code-chunker.js +0 -19
  113. package/dist/infrastructure/chunking/code-aware-chunker.js +0 -397
  114. package/dist/infrastructure/context/context-compressor.js +0 -329
  115. package/dist/infrastructure/context/conversation-context.js +0 -128
  116. package/dist/infrastructure/context/session-manager.js +0 -94
  117. package/dist/infrastructure/cost/cost-tracker.js +0 -360
  118. package/dist/infrastructure/file-scanner/file-scanner.js +0 -106
  119. package/dist/infrastructure/governance/nist-ai-rmf.js +0 -292
  120. package/dist/infrastructure/governance/policy-as-code.js +0 -258
  121. package/dist/infrastructure/governance/prompt-to-code-lineage.js +0 -239
  122. package/dist/infrastructure/index.js +0 -7
  123. package/dist/infrastructure/observability/prompt-versioner.js +0 -145
  124. package/dist/infrastructure/protocols/a2a-metadata.js +0 -137
  125. package/dist/infrastructure/protocols/a2a-protocol.js +0 -314
  126. package/dist/infrastructure/protocols/mcp-oauth.js +0 -184
  127. package/dist/infrastructure/protocols/mcp-server.js +0 -333
  128. package/dist/infrastructure/protocols/streaming-handler.js +0 -103
  129. package/dist/infrastructure/providers/cohere-provider.js +0 -444
  130. package/dist/infrastructure/providers/fake-provider.js +0 -130
  131. package/dist/infrastructure/providers/local-llm-provider.js +0 -330
  132. package/dist/infrastructure/providers/model-config.types.js +0 -9
  133. package/dist/infrastructure/providers/model-provider.interface.js +0 -8
  134. package/dist/infrastructure/providers/openai-provider.js +0 -413
  135. package/dist/infrastructure/providers/openrouter-provider.js +0 -399
  136. package/dist/infrastructure/providers/operation-provider-resolver.js +0 -105
  137. package/dist/infrastructure/providers/provider-config-loader.js +0 -120
  138. package/dist/infrastructure/providers/provider-registry.js +0 -88
  139. package/dist/infrastructure/safety/pattern-detector.js +0 -133
  140. package/dist/infrastructure/security/ai-sast-scanner.js +0 -290
  141. package/dist/infrastructure/security/docker-sandbox.js +0 -178
  142. package/dist/infrastructure/security/enhanced-security-gate.js +0 -151
  143. package/dist/infrastructure/security/license-scanner.js +0 -167
  144. package/dist/infrastructure/security/provider-bias-detector.js +0 -164
  145. package/dist/infrastructure/security/sandbox-executor.js +0 -64
  146. package/dist/infrastructure/serialization/toon-serializer.js +0 -119
  147. package/dist/infrastructure/storage/memory-stream-service.js +0 -204
  148. package/dist/infrastructure/storage/plan-repository.js +0 -96
  149. package/dist/infrastructure/storage/sqlite-decision-repository.js +0 -232
  150. package/dist/infrastructure/storage/sqlite-embedding-repository.js +0 -311
  151. package/dist/infrastructure/storage/sqlite-knowledge-graph-repository.js +0 -417
  152. package/dist/infrastructure/storage/sqlite-knowledge-preservation-repository.js +0 -230
  153. package/dist/infrastructure/storage/sqlite-memory-repository.js +0 -229
  154. package/dist/infrastructure/storage/sqlite-pattern-repository.js +0 -249
  155. package/dist/infrastructure/storage/task-helpers.js +0 -197
  156. package/dist/infrastructure/telemetry/telemetry-service.js +0 -167
  157. package/dist/infrastructure/ux/appropriate-friction.js +0 -213
  158. package/dist/infrastructure/ux/bi-directional-learning.js +0 -337
  159. package/dist/infrastructure/ux/capability-boundaries.js +0 -42
  160. package/dist/infrastructure/ux/comprehensive-formatter.js +0 -117
  161. package/dist/infrastructure/ux/contextual-feature-discovery.js +0 -10
  162. package/dist/infrastructure/ux/expectation-management.js +0 -327
  163. package/dist/infrastructure/ux/feature-discovery.js +0 -14
  164. package/dist/infrastructure/ux/feedback-prompt.js +0 -45
  165. package/dist/infrastructure/ux/hitl-validation.js +0 -297
  166. package/dist/infrastructure/ux/progress-indicator.js +0 -116
  167. package/dist/infrastructure/ux/progressive-disclosure.js +0 -236
  168. package/dist/infrastructure/ux/review-checkpoint.js +0 -72
  169. package/dist/infrastructure/ux/staged-feature-intro.js +0 -24
  170. package/dist/infrastructure/ux/stream-markdown.js +0 -151
  171. package/dist/infrastructure/ux/syntax-highlighter.js +0 -91
  172. package/dist/infrastructure/ux/team-standards.js +0 -196
  173. package/dist/infrastructure/ux/transparency.js +0 -71
  174. package/dist/infrastructure/validation/agent-feedback.js +0 -55
  175. package/dist/infrastructure/validation/agent-validation-helper.js +0 -137
  176. package/dist/infrastructure/validation/review-handler.js +0 -40
  177. package/dist/infrastructure/validation/summary-aggregator.js +0 -70
  178. package/dist/infrastructure/validation/summary-extractor.js +0 -45
  179. package/dist/infrastructure/validation/trace-summary.js +0 -52
  180. package/dist/infrastructure/verification/verification-service.js +0 -47
  181. package/dist/infrastructure/xai/attention-visualizer.js +0 -172
  182. package/dist/infrastructure/xai/cot-visualizer.js +0 -283
  183. package/dist/infrastructure/xai/decision-tree-log.js +0 -212
  184. package/dist/infrastructure/xai/interactive-xai.js +0 -260
  185. package/dist/infrastructure/xai/uncertainty-quantifier.js +0 -198
  186. package/dist/intelligent-retrieval.js +0 -272
  187. package/dist/intent/classifier.js +0 -2
  188. package/dist/intent/context.js +0 -2
  189. package/dist/iterative-refinement.js +0 -189
  190. package/dist/learning.js +0 -232
  191. package/dist/log.js +0 -31
  192. package/dist/migrate.js +0 -133
  193. package/dist/parallel-processor.js +0 -530
  194. package/dist/planner.js +0 -198
  195. package/dist/policy.js +0 -26
  196. package/dist/presentation/cli/commands/ask-command.js +0 -314
  197. package/dist/presentation/cli/commands/cost-command.js +0 -191
  198. package/dist/presentation/cli/commands/decision-command.js +0 -207
  199. package/dist/presentation/cli/commands/docs-command.js +0 -25
  200. package/dist/presentation/cli/commands/fix-command.js +0 -53
  201. package/dist/presentation/cli/commands/knowledge-command.js +0 -129
  202. package/dist/presentation/cli/commands/learning-dashboard-command.js +0 -183
  203. package/dist/presentation/cli/commands/models-command.js +0 -194
  204. package/dist/presentation/cli/commands/orchestrate-command.js +0 -207
  205. package/dist/presentation/cli/commands/plan-command.js +0 -246
  206. package/dist/presentation/cli/commands/product-command.js +0 -199
  207. package/dist/presentation/cli/commands/react-command.js +0 -181
  208. package/dist/presentation/cli/commands/review-command.js +0 -154
  209. package/dist/presentation/cli/commands/run-command.js +0 -188
  210. package/dist/presentation/cli/commands/smart-command.js +0 -395
  211. package/dist/presentation/cli/commands/suggest-command.js +0 -138
  212. package/dist/presentation/cli/commands/trace-command.js +0 -129
  213. package/dist/presentation/cli/commands/undo-command.js +0 -150
  214. package/dist/query-optimizer.js +0 -205
  215. package/dist/refactor.js +0 -116
  216. package/dist/review.js +0 -206
  217. package/dist/search.js +0 -163
  218. package/dist/session.js +0 -652
  219. package/dist/task-verification.js +0 -336
  220. package/dist/testgen.js +0 -166
  221. package/dist/token-optimizer.js +0 -277
  222. package/dist/tools/bash.js +0 -213
  223. package/dist/tools/edit.js +0 -235
  224. package/dist/tools/executor.js +0 -153
  225. package/dist/tools/git-tool.js +0 -292
  226. package/dist/tools/parser.js +0 -158
  227. package/dist/tools/registry.js +0 -302
  228. package/dist/tools/search.js +0 -100
  229. package/dist/types.js +0 -2
  230. package/dist/utils/check-api-status.js +0 -100
  231. package/dist/utils/diff-parser.js +0 -162
  232. package/dist/verification/backup.js +0 -259
  233. package/dist/verification/compiler.js +0 -264
  234. package/dist/verification/index.js +0 -273
  235. package/dist/verification/test-runner.js +0 -379
@@ -18,40 +18,27 @@
18
18
  * codehere trust --diff HEAD # equivalent using git directly
19
19
  * codehere trust --badge # output badge markdown
20
20
  */
21
- import { readFileSync, existsSync, statSync, readdirSync } from 'fs';
22
- import { join, extname, relative, isAbsolute } from 'path';
23
- import { execSync } from 'child_process';
21
+ import { existsSync } from 'fs';
22
+ import { join, relative, isAbsolute } from 'path';
23
+ import { execFileSync } from 'child_process';
24
24
  import { scoreFile } from '../../../infrastructure/security/trust-scorer.js';
25
+ import { collectCodeFiles } from '../../../infrastructure/security/file-collection.js';
25
26
  import { colors, sectionHeader, error, newline, info, randomCleanScan } from '../../../ui.js';
26
27
  import { loadProductContext, adjustRecommendation } from '../../../infrastructure/config/product-context.js';
27
28
  // ── File collection ──────────────────────────────────────────────────────────
28
- const CODE_EXTENSIONS = new Set([
29
- '.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
30
- '.py', '.rb', '.go', '.java', '.cs', '.php',
31
- '.sh', '.bash', '.zsh',
32
- '.sql', '.html', '.vue', '.svelte',
33
- ]);
34
- const IGNORE_DIRS = new Set(['node_modules', '.git', 'dist', 'build', '.next', 'coverage', '.cache', '.codehere', '.codehere-cache']);
35
- function collectFiles(target) {
36
- const stat = statSync(target);
37
- if (stat.isFile())
38
- return [target];
39
- const files = [];
40
- function walk(dir) {
41
- for (const entry of readdirSync(dir, { withFileTypes: true })) {
42
- if (IGNORE_DIRS.has(entry.name))
43
- continue;
44
- const full = join(dir, entry.name);
45
- if (entry.isDirectory()) {
46
- walk(full);
47
- }
48
- else if (CODE_EXTENSIONS.has(extname(entry.name))) {
49
- files.push(full);
50
- }
51
- }
29
+ // See src/infrastructure/security/file-collection.ts for exclusion rules.
30
+ /**
31
+ * Read a file safely — handles iCloud-evicted files on macOS.
32
+ * readFileSync blocks forever on iCloud-evicted files (dehydrated placeholders in ~/Documents).
33
+ * We use cat with a timeout as a subprocess so the main thread never blocks.
34
+ */
35
+ function safeReadFile(filepath) {
36
+ try {
37
+ return execFileSync('cat', [filepath], { encoding: 'utf-8', timeout: 2000, maxBuffer: 5 * 1024 * 1024 });
38
+ }
39
+ catch {
40
+ return null; // File unreadable (iCloud-evicted, permissions, too large) — skip silently
52
41
  }
53
- walk(target);
54
- return files;
55
42
  }
56
43
  // ── Git diff mode ────────────────────────────────────────────────────────────
57
44
  function parseDiffFiles(diff) {
@@ -68,8 +55,8 @@ function parseDiffFiles(diff) {
68
55
  // Extract added lines only (lines starting with +, excluding +++)
69
56
  const addedLines = block
70
57
  .split('\n')
71
- .filter(l => l.startsWith('+') && !l.startsWith('+++'))
72
- .map(l => l.substring(1))
58
+ .filter((l) => l.startsWith('+') && !l.startsWith('+++'))
59
+ .map((l) => l.substring(1))
73
60
  .join('\n');
74
61
  if (addedLines.trim()) {
75
62
  files.push({ filepath, code: addedLines });
@@ -80,12 +67,18 @@ function parseDiffFiles(diff) {
80
67
  // ── Report formatting ────────────────────────────────────────────────────────
81
68
  function gradeColor(grade) {
82
69
  switch (grade) {
83
- case 'A': return colors.green(grade);
84
- case 'B': return colors.cyan(grade);
85
- case 'C': return colors.yellow(grade);
86
- case 'D': return colors.red(grade);
87
- case 'F': return colors.red(colors.bold(grade));
88
- default: return grade;
70
+ case 'A':
71
+ return colors.green(grade);
72
+ case 'B':
73
+ return colors.cyan(grade);
74
+ case 'C':
75
+ return colors.yellow(grade);
76
+ case 'D':
77
+ return colors.red(grade);
78
+ case 'F':
79
+ return colors.red(colors.bold(grade));
80
+ default:
81
+ return grade;
89
82
  }
90
83
  }
91
84
  function scoreBar(score, width = 20) {
@@ -98,10 +91,14 @@ function scoreBar(score, width = 20) {
98
91
  return colors.red(bar);
99
92
  }
100
93
  function badgeMarkdown(report) {
101
- const color = report.grade === 'A' ? 'brightgreen'
102
- : report.grade === 'B' ? 'green'
103
- : report.grade === 'C' ? 'yellow'
104
- : report.grade === 'D' ? 'orange'
94
+ const color = report.grade === 'A'
95
+ ? 'brightgreen'
96
+ : report.grade === 'B'
97
+ ? 'green'
98
+ : report.grade === 'C'
99
+ ? 'yellow'
100
+ : report.grade === 'D'
101
+ ? 'orange'
105
102
  : 'red';
106
103
  return `![codehere trust](https://img.shields.io/badge/codehere%20trust-${report.overallScore}%25%20${report.grade}-${color}?logo=shield)`;
107
104
  }
@@ -113,8 +110,12 @@ export async function executeTrustCommand(target, options = {}) {
113
110
  if (options.diff !== undefined) {
114
111
  // Run git diff and scan added lines
115
112
  try {
113
+ // THREAT-2 fix · ref comes from a user-supplied CLI flag. Using template-
114
+ // string interpolation with execSync allows shell metacharacters in `ref`
115
+ // (e.g. `--diff "main; rm -rf /"`) to escape the git invocation. Use the
116
+ // execFileSync array form so the shell is never invoked.
116
117
  const ref = options.diff || 'HEAD';
117
- const diffOutput = execSync(`git diff ${ref}`, { cwd, encoding: 'utf-8' });
118
+ const diffOutput = execFileSync('git', ['diff', ref], { cwd, encoding: 'utf-8' });
118
119
  filesToScan = parseDiffFiles(diffOutput);
119
120
  if (filesToScan.length === 0) {
120
121
  console.log(info('No changed files to scan'));
@@ -151,30 +152,42 @@ export async function executeTrustCommand(target, options = {}) {
151
152
  console.error(error(`Not found: ${resolved}`));
152
153
  process.exit(1);
153
154
  }
154
- const paths = collectFiles(resolved);
155
- filesToScan = paths.map(p => ({
156
- filepath: relative(cwd, p),
157
- code: readFileSync(p, 'utf-8'),
158
- }));
155
+ const paths = collectCodeFiles(resolved);
156
+ let skippedCount = 0;
157
+ for (const p of paths) {
158
+ const code = safeReadFile(p);
159
+ if (code !== null) {
160
+ filesToScan.push({ filepath: relative(cwd, p), code });
161
+ }
162
+ else {
163
+ skippedCount++;
164
+ }
165
+ }
166
+ if (skippedCount > 0) {
167
+ console.log(colors.dim(` Skipped ${skippedCount} unreadable file${skippedCount > 1 ? 's' : ''}`));
168
+ }
169
+ if (filesToScan.length === 0 && skippedCount > 0) {
170
+ console.log(info('No readable files to scan.'));
171
+ console.log(colors.dim(' Check file permissions or availability and retry.'));
172
+ return;
173
+ }
159
174
  }
160
175
  // ── Scan ──────────────────────────────────────────────────────────────────
161
- const results = filesToScan.map(f => scoreFile(f.filepath, f.code));
176
+ const results = filesToScan.map((f) => scoreFile(f.filepath, f.code));
162
177
  const totalFindings = results.reduce((s, r) => s + r.findings.length, 0);
163
- const criticalCount = results.reduce((s, r) => s + r.findings.filter(f => f.severity === 'critical').length, 0);
164
- const highCount = results.reduce((s, r) => s + r.findings.filter(f => f.severity === 'high').length, 0);
165
- const mediumCount = results.reduce((s, r) => s + r.findings.filter(f => f.severity === 'medium').length, 0);
166
- const lowCount = results.reduce((s, r) => s + r.findings.filter(f => f.severity === 'low').length, 0);
167
- const overallScore = results.length > 0
168
- ? Math.round(results.reduce((s, r) => s + r.score, 0) / results.length)
169
- : 100;
178
+ const criticalCount = results.reduce((s, r) => s + r.findings.filter((f) => f.severity === 'critical').length, 0);
179
+ const highCount = results.reduce((s, r) => s + r.findings.filter((f) => f.severity === 'high').length, 0);
180
+ const mediumCount = results.reduce((s, r) => s + r.findings.filter((f) => f.severity === 'medium').length, 0);
181
+ const lowCount = results.reduce((s, r) => s + r.findings.filter((f) => f.severity === 'low').length, 0);
182
+ const overallScore = results.length > 0 ? Math.round(results.reduce((s, r) => s + r.score, 0) / results.length) : 100;
170
183
  const grade = overallScore >= 90 ? 'A' : overallScore >= 75 ? 'B' : overallScore >= 60 ? 'C' : overallScore >= 40 ? 'D' : 'F';
171
184
  const baseRecommendation = criticalCount > 0
172
185
  ? `${criticalCount} critical ${criticalCount === 1 ? 'issue' : 'issues'} — worth sorting before this merges.`
173
186
  : highCount > 0
174
187
  ? `Nothing critical, but ${highCount} high-severity ${highCount === 1 ? 'pattern' : 'patterns'} worth a look.`
175
- : overallScore >= 75
176
- ? 'Clean scan. Nothing blocking a merge.'
177
- : 'A few things to look at — nothing critical, but worth a pass.';
188
+ : mediumCount + lowCount > 0
189
+ ? `${mediumCount + lowCount} low-priority ${mediumCount + lowCount === 1 ? 'finding' : 'findings'} — nothing blocking, but worth a pass.`
190
+ : 'Clean scan. Nothing blocking a merge.';
178
191
  const productCtx = loadProductContext(process.cwd());
179
192
  const recommendation = adjustRecommendation(baseRecommendation, criticalCount, highCount, overallScore, productCtx);
180
193
  const report = {
@@ -206,70 +219,72 @@ export async function executeTrustCommand(target, options = {}) {
206
219
  newline();
207
220
  sectionHeader('codehere Trust Report');
208
221
  newline();
222
+ // Score
209
223
  console.log(` Score ${scoreBar(overallScore)} ${colors.bold(String(overallScore))}/100 ${gradeColor(grade)}`);
210
224
  newline();
211
- // Findings summary
212
- const rows = [
213
- criticalCount > 0 ? ` ${colors.red('●')} ${colors.red(String(criticalCount) + ' critical')}` : null,
214
- highCount > 0 ? ` ${colors.yellow('●')} ${colors.yellow(String(highCount) + ' high')}` : null,
215
- mediumCount > 0 ? ` ${colors.dim('●')} ${mediumCount} medium` : null,
216
- lowCount > 0 ? ` ${colors.dim('●')} ${lowCount} low` : null,
225
+ // Findings summary (inline, compact)
226
+ const parts = [
227
+ criticalCount > 0 ? colors.red(`${criticalCount} critical`) : null,
228
+ highCount > 0 ? colors.yellow(`${highCount} high`) : null,
229
+ mediumCount > 0 ? colors.dim(`${mediumCount} medium`) : null,
230
+ lowCount > 0 ? colors.dim(`${lowCount} low`) : null,
217
231
  ].filter(Boolean);
218
- if (rows.length === 0) {
232
+ if (parts.length === 0) {
219
233
  console.log(` ${colors.green('✓')} ${randomCleanScan()}`);
220
234
  }
221
235
  else {
222
- rows.forEach(r => console.log(r));
236
+ console.log(` ${parts.join(colors.dim(' · '))}`);
223
237
  }
224
238
  newline();
225
239
  // Per-file results (show worst first)
226
240
  if (results.length > 1) {
227
241
  const sorted = [...results].sort((a, b) => a.score - b.score);
228
- console.log(colors.bold('Files:'));
242
+ console.log(colors.dim(' FILES'));
229
243
  for (const r of sorted.slice(0, 10)) {
230
- const icon = r.score >= 75 ? colors.green('✓') : r.score >= 60 ? colors.yellow('⚠') : colors.red('✗');
231
- console.log(` ${icon} ${gradeColor(r.grade)} ${String(r.score).padStart(3)}/100 ${colors.dim(r.filepath)}`);
244
+ const icon = r.score >= 75 ? colors.green('✓') : r.score >= 60 ? colors.yellow('!') : colors.red('✗');
245
+ console.log(` ${icon} ${gradeColor(r.grade)} ${String(r.score).padStart(3)}/100 ${r.filepath}`);
232
246
  }
233
247
  if (sorted.length > 10) {
234
- console.log(colors.dim(` ... and ${sorted.length - 10} more files`));
248
+ console.log(colors.dim(` + ${sorted.length - 10} more files`));
235
249
  }
236
250
  newline();
237
251
  }
238
- // Verbose: show all findings
252
+ // Findings detail
239
253
  if (options.verbose) {
254
+ console.log(colors.dim(' FINDINGS'));
240
255
  for (const r of results) {
241
256
  if (r.findings.length === 0)
242
257
  continue;
243
- console.log(colors.bold(r.filepath) + ':');
258
+ console.log(` ${colors.bold(r.filepath)}`);
244
259
  for (const f of r.findings) {
245
- const sev = f.severity === 'critical' ? colors.red(f.severity)
246
- : f.severity === 'high' ? colors.yellow(f.severity)
247
- : colors.dim(f.severity);
248
- const line = f.line ? colors.dim(`:${f.line}`) : '';
249
- const cwe = f.cwe ? colors.dim(` [${f.cwe}]`) : '';
250
- console.log(` ${sev} ${f.category}${cwe}${line} — ${f.description}`);
260
+ const sev = f.severity === 'critical'
261
+ ? colors.red('crit')
262
+ : f.severity === 'high'
263
+ ? colors.yellow('high')
264
+ : colors.dim(f.severity.slice(0, 4));
265
+ const ln = f.line ? colors.dim(`L${f.line}`) : '';
266
+ console.log(` ${sev} ${ln.padEnd(6)} ${f.description}`);
251
267
  }
252
- newline();
253
268
  }
269
+ newline();
254
270
  }
255
- else if (criticalCount + highCount > 0) {
256
- // Show only critical/high findings without verbose flag
257
- console.log(colors.bold('Top findings:'));
258
- const allFindings = results.flatMap(r => r.findings
259
- .filter(f => f.severity === 'critical' || f.severity === 'high')
260
- .map(f => ({ ...f, filepath: r.filepath })));
261
- // Show critical first, then high
262
- const sorted = allFindings.sort((a, b) => {
263
- if (a.severity === 'critical' && b.severity !== 'critical')
264
- return -1;
265
- if (a.severity !== 'critical' && b.severity === 'critical')
266
- return 1;
267
- return 0;
268
- });
271
+ else if (totalFindings > 0) {
272
+ console.log(colors.dim(' FINDINGS'));
273
+ const severityRank = { critical: 0, high: 1, medium: 2, low: 3 };
274
+ const allFindings = results.flatMap((r) => r.findings.map((f) => ({ ...f, filepath: r.filepath })));
275
+ const sorted = allFindings.sort((a, b) => severityRank[a.severity] - severityRank[b.severity]);
269
276
  for (const f of sorted.slice(0, 5)) {
270
- const sev = f.severity === 'critical' ? colors.red(f.severity) : colors.yellow(f.severity);
271
- const line = f.line ? `:${f.line}` : '';
272
- console.log(` ${sev} ${f.filepath}${line} — ${f.description}`);
277
+ const sev = f.severity === 'critical'
278
+ ? colors.red('crit')
279
+ : f.severity === 'high'
280
+ ? colors.yellow('high')
281
+ : colors.dim(f.severity.slice(0, 4));
282
+ const ln = f.line ? `:${f.line}` : '';
283
+ console.log(` ${sev} ${f.filepath}${ln}`);
284
+ console.log(` ${colors.dim(f.description)}`);
285
+ }
286
+ if (sorted.length > 5) {
287
+ console.log(colors.dim(` + ${sorted.length - 5} more findings (use --verbose to see all)`));
273
288
  }
274
289
  newline();
275
290
  }
@@ -277,10 +292,11 @@ export async function executeTrustCommand(target, options = {}) {
277
292
  const recColor = criticalCount > 0 ? colors.red : highCount > 0 ? colors.yellow : colors.green;
278
293
  console.log(recColor(recommendation));
279
294
  newline();
280
- // Helpful tips
295
+ // Tips footer (quiet, separated)
281
296
  if (results.length > 0 && !options.ci) {
282
- console.log(colors.dim(' codehere trust --badge') + colors.dim(' Add a badge to your README'));
283
- console.log(colors.dim(' codehere trust --ci') + colors.dim(' Exit 1 on critical findings (for CI)'));
297
+ console.log(colors.dim(' ─────'));
298
+ console.log(colors.dim(' trust --badge Add a badge to your README'));
299
+ console.log(colors.dim(' trust --ci Exit 1 on critical findings'));
284
300
  newline();
285
301
  }
286
302
  if (ciFailed) {
@@ -63,11 +63,7 @@ function extractFilePath(errorMessage) {
63
63
  */
64
64
  function extractLineNumber(errorMessage) {
65
65
  // Patterns: "line 42", ":42", "at line 42"
66
- const patterns = [
67
- /(?:line|Line)\s+(\d+)/i,
68
- /:(\d+):/,
69
- /\((\d+)\)/,
70
- ];
66
+ const patterns = [/(?:line|Line)\s+(\d+)/i, /:(\d+):/, /\((\d+)\)/];
71
67
  for (const pattern of patterns) {
72
68
  const match = errorMessage.match(pattern);
73
69
  if (match && match[1]) {
@@ -89,9 +85,8 @@ function getRecoveryCommands(errorType, errorMessage, context) {
89
85
  case ErrorType.VALIDATION:
90
86
  if (lowerMessage.includes('file') || lowerMessage.includes('not found')) {
91
87
  if (context.filepath) {
92
- commands.push(`codehere explain ${context.filepath}${context.lineNumber ? `:${context.lineNumber}` : ''}`);
88
+ commands.push(`codehere trust ${context.filepath}`);
93
89
  }
94
- commands.push('codehere index');
95
90
  }
96
91
  break;
97
92
  case ErrorType.API_ERROR:
@@ -102,7 +97,7 @@ function getRecoveryCommands(errorType, errorMessage, context) {
102
97
  break;
103
98
  case ErrorType.POLICY:
104
99
  if (context.filepath) {
105
- commands.push(`codehere explain ${context.filepath}`);
100
+ commands.push(`codehere trust ${context.filepath}`);
106
101
  commands.push('codehere config policies');
107
102
  }
108
103
  break;
@@ -174,7 +169,7 @@ function getDocumentationLink(errorType) {
174
169
  function generateErrorCode(errorType, errorMessage) {
175
170
  const prefix = errorType.toUpperCase().substring(0, 3);
176
171
  const hash = errorMessage.split('').reduce((acc, char) => {
177
- return ((acc << 5) - acc) + char.charCodeAt(0);
172
+ return (acc << 5) - acc + char.charCodeAt(0);
178
173
  }, 0);
179
174
  const code = Math.abs(hash).toString(16).substring(0, 4).toUpperCase();
180
175
  return `${prefix}-${code}`;
@@ -183,7 +178,7 @@ function generateErrorCode(errorType, errorMessage) {
183
178
  * Display error with helpful context and recovery suggestions
184
179
  */
185
180
  export function displayError(error, options = {}) {
186
- const { operation = 'operation', query, showSuggestions = true, showStack = false, } = options;
181
+ const { operation = 'operation', query, showSuggestions = true, showStack = false } = options;
187
182
  const errorType = classifyError(error);
188
183
  const errorMessage = error instanceof Error ? error.message : String(error);
189
184
  const isEnterpriseError = error instanceof EnterpriseError;
@@ -227,16 +222,21 @@ export function displayError(error, options = {}) {
227
222
  const suggestions = getErrorSuggestions(errorType, errorMessage, { operation, query, filepath: fileContext });
228
223
  if (suggestions.length > 0) {
229
224
  console.log(colors.bold('Suggestions:'));
230
- suggestions.forEach(suggestion => {
225
+ suggestions.forEach((suggestion) => {
231
226
  console.log(colors.dim(` ${symbols.bullet} ${suggestion}`));
232
227
  });
233
228
  newline();
234
229
  }
235
230
  // Show recovery commands for certain error types
236
- const recoveryCommands = getRecoveryCommands(errorType, errorMessage, { operation, query, filepath: fileContext, lineNumber: lineContext });
231
+ const recoveryCommands = getRecoveryCommands(errorType, errorMessage, {
232
+ operation,
233
+ query,
234
+ filepath: fileContext,
235
+ lineNumber: lineContext,
236
+ });
237
237
  if (recoveryCommands.length > 0) {
238
238
  console.log(colors.bold('Recovery Commands:'));
239
- recoveryCommands.forEach(cmd => {
239
+ recoveryCommands.forEach((cmd) => {
240
240
  console.log(colors.cyan(` $ ${cmd}`));
241
241
  });
242
242
  newline();
@@ -271,7 +271,7 @@ function getErrorSuggestions(errorType, errorMessage, context) {
271
271
  const lowerMessage = errorMessage.toLowerCase();
272
272
  switch (errorType) {
273
273
  case ErrorType.RATE_LIMIT:
274
- suggestions.push('You\'ve reached the API rate limit or monthly quota');
274
+ suggestions.push("You've reached the API rate limit or monthly quota");
275
275
  suggestions.push('Wait a moment and try again');
276
276
  suggestions.push('Check your API key limits at: https://dashboard.cohere.com/api-keys');
277
277
  suggestions.push('Consider upgrading your API key for higher limits');
@@ -286,11 +286,8 @@ function getErrorSuggestions(errorType, errorMessage, context) {
286
286
  suggestions.push('For troubleshooting, include the error code when reporting issues');
287
287
  }
288
288
  else if (lowerMessage.includes('not found') || lowerMessage.includes('missing')) {
289
- if (context.query) {
290
- suggestions.push(`Try searching: codehere "find ${context.query.split(' ').slice(0, 3).join(' ')}"`);
291
- }
292
- suggestions.push('Make sure you\'re in the correct directory');
293
- suggestions.push('Run "codehere index" to build search index');
289
+ suggestions.push("Make sure you're in the correct directory");
290
+ suggestions.push('Run "codehere trust ." to verify the path is scanned');
294
291
  }
295
292
  else {
296
293
  suggestions.push('Check the error message above for specific details');
@@ -319,8 +316,7 @@ function getErrorSuggestions(errorType, errorMessage, context) {
319
316
  suggestions.push('Check file permissions');
320
317
  }
321
318
  else if (lowerMessage.includes('memory') || lowerMessage.includes('database')) {
322
- suggestions.push('The memory system may need initialization');
323
- suggestions.push('Try running "codehere index" to rebuild the index');
319
+ suggestions.push('Run "codehere health" to inspect runtime state');
324
320
  }
325
321
  else {
326
322
  suggestions.push('This error may be temporary - try again');
package/dist/ui.js CHANGED
@@ -19,7 +19,12 @@ export function isMinimalStyle() {
19
19
  }
20
20
  // Minimal header for commands (used in minimal style)
21
21
  export function printMinimalHeader(command, query) {
22
- console.log(colors.cyan(`codehere ${command}`) + colors.dim(' ▸ ') + query);
22
+ if (query) {
23
+ console.log(colors.cyan(`codehere ${command}`) + colors.dim(' ▸ ') + query);
24
+ }
25
+ else {
26
+ console.log(colors.cyan(`codehere ${command}`));
27
+ }
23
28
  console.log();
24
29
  }
25
30
  // Minimal safety note (used at end of AI responses)
@@ -34,7 +39,7 @@ export function printContextSummary(files, maxShow = 3) {
34
39
  const shown = unique.slice(0, maxShow);
35
40
  const more = unique.length - maxShow;
36
41
  console.log(colors.dim('Context:'));
37
- shown.forEach(f => console.log(colors.dim(` - ${f}`)));
42
+ shown.forEach((f) => console.log(colors.dim(` - ${f}`)));
38
43
  if (more > 0) {
39
44
  console.log(colors.dim(` ... and ${more} more file${more > 1 ? 's' : ''}`));
40
45
  }
@@ -142,35 +147,35 @@ export function info(message) {
142
147
  // Create professional table - minimal styling
143
148
  export function createTable(headers, rows) {
144
149
  const table = new Table({
145
- head: headers.map(h => colors.bold(h)),
150
+ head: headers.map((h) => colors.bold(h)),
146
151
  style: {
147
152
  head: [],
148
153
  border: ['gray'],
149
154
  compact: false,
150
155
  },
151
156
  chars: {
152
- 'top': '─',
157
+ top: '─',
153
158
  'top-mid': '┬',
154
159
  'top-left': '┌',
155
160
  'top-right': '┐',
156
- 'bottom': '─',
161
+ bottom: '─',
157
162
  'bottom-mid': '┴',
158
163
  'bottom-left': '└',
159
164
  'bottom-right': '┘',
160
- 'left': '│',
165
+ left: '│',
161
166
  'left-mid': '├',
162
- 'mid': '─',
167
+ mid: '─',
163
168
  'mid-mid': '┼',
164
- 'right': '│',
169
+ right: '│',
165
170
  'right-mid': '┤',
166
- 'middle': '│',
171
+ middle: '│',
167
172
  },
168
173
  colWidths: headers.map((_, i) => {
169
- const maxWidth = Math.max(headers[i].length, ...rows.map(row => (row[i] || '').length));
174
+ const maxWidth = Math.max(headers[i].length, ...rows.map((row) => (row[i] || '').length));
170
175
  return Math.min(maxWidth + 2, 50);
171
176
  }),
172
177
  });
173
- rows.forEach(row => table.push(row));
178
+ rows.forEach((row) => table.push(row));
174
179
  return table;
175
180
  }
176
181
  // Format file path - subtle
@@ -431,7 +436,7 @@ export function showSlashCommandMenu() {
431
436
  newline();
432
437
  console.log(colors.bold(' Slash commands'));
433
438
  newline();
434
- const maxNameLen = Math.max(...SLASH_COMMANDS.map(c => c.name.length + c.args.length)) + 1;
439
+ const maxNameLen = Math.max(...SLASH_COMMANDS.map((c) => c.name.length + c.args.length)) + 1;
435
440
  for (const cmd of SLASH_COMMANDS) {
436
441
  const signature = `/${cmd.name}${cmd.args ? ' ' + cmd.args : ''}`;
437
442
  const pad = ' '.repeat(Math.max(0, maxNameLen + 2 - signature.length + 8));
package/package.json CHANGED
@@ -1,112 +1,80 @@
1
1
  {
2
2
  "name": "codehere",
3
- "version": "0.2.1",
4
- "description": "Know what your AI agent actually did — scans every AI write before it touches your codebase",
3
+ "version": "0.3.0-rc.1",
4
+ "description": "A PM for your AI coding agents. Delegate, orchestrate, and audit Claude Code, Codex, Aider, and OpenCode from one local web UI — every AI action traced, every file scored.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
7
7
  "bin": {
8
- "codehere": "dist/index.js"
8
+ "codehere": "dist/index.js",
9
+ "ch": "dist/index.js"
9
10
  },
10
11
  "files": [
11
12
  "dist",
12
13
  "README.md",
13
14
  "LICENSE"
14
15
  ],
16
+ "engines": {
17
+ "node": ">=20"
18
+ },
15
19
  "scripts": {
20
+ "prebuild": "rm -rf dist",
16
21
  "build": "tsc",
17
- "prepublishOnly": "npm run build && find dist -name '*.map' -delete && find dist -name '*.d.ts' -delete",
22
+ "postbuild": "chmod +x dist/index.js",
23
+ "repomap": "node scripts/gen-repo-map.mjs",
24
+ "prepublishOnly": "npm run build && find dist -name '*.map' -delete && find dist -name '*.d.ts' -delete && find dist -name '*.d.ts.map' -delete",
18
25
  "start": "node dist/index.js",
19
- "start:api": "npm run build && node dist/api/server.js",
20
26
  "dev": "tsx src/index.ts",
21
- "dev:api": "tsx api/server.ts",
22
- "test": "npm run build && tsx ./test/run-tests.ts",
23
- "test:comprehensive": "npm run build && RUN_COMPREHENSIVE_TESTS=true tsx ./test/comprehensive-use-cases.test.ts",
24
- "test:execution": "npm run build && tsx ./test/run-comprehensive-test-execution.ts",
25
- "test:suite": "npm run build && tsx test/test-suite.ts",
26
- "test:integration": "npm run build && tsx test/integration/run-integration-tests.ts",
27
- "test:cli": "npm run build && tsx test/integration/run-cli-tests.ts",
28
- "test:scenarios": "npm run build && tsx test/scenarios/real-world-scenarios.ts",
29
- "test:security": "npm run build && tsx test/security/sast-scanner.test.ts",
30
- "test:security-gate": "npm run build && tsx test/security/security-gate.test.ts",
31
- "test:git-workflow": "npm run build && tsx test/git/git-workflow.test.ts",
32
- "test:git-react": "npm run build && tsx test/git/react-git-integration.test.ts",
33
- "test:memory": "npm run build && tsx test/memory/memory-system.test.ts",
34
- "test:performance": "npm run build && tsx test/performance/performance-analysis.test.ts",
35
- "test:context-depth": "npm run build && tsx test/context-depth/context-depth.test.ts",
36
- "test:compound-instruction": "npm run build && tsx test/compound-instruction/compound-instruction.test.ts",
37
- "check-api": "npm run build && tsx -e \"import('./dist/utils/check-api-status.js').then(m => m.checkAPIStatus().then(s => { console.log(s.canProceed ? '✅ ' + s.message : '❌ ' + s.message); process.exit(s.canProceed ? 0 : 1); }))\"",
38
- "test:all": "npm run build && npm run test:integration && npm run test:scenarios && npm run test:security && npm run test:security-gate && npm run test:git-workflow && npm run test:memory && npm run test:performance",
39
- "test:unit": "npm run build && tsx test/unit/run-unit-tests.ts",
40
- "test:coverage": "c8 npm run test:unit && c8 report --reporter=text --reporter=html",
41
- "test:rerank": "tsx test/rerank-integration.test.ts",
42
- "eval:command-r": "tsx test/command-a-evaluation.test.ts",
43
- "test:verification": "npm run build && node test-verification-simple.js",
44
- "measure:metrics": "npm run build && node test/measure-metrics.js",
45
- "analyze:feedback": "tsx scripts/analyze-feedback.ts",
46
- "check:trust": "tsx scripts/check-trust-thresholds.ts",
47
- "smoke:cohere": "npm run build && tsx scripts/smoke-cohere.ts",
48
- "smoke:openai": "npm run build && tsx scripts/smoke-openai.ts",
49
- "test:real-providers": "npm run build && tsx test/integration/real-provider-comprehensive.test.ts",
50
- "test:user-flows": "npm run build && tsx test/integration/user-flow-validation.test.ts"
27
+ "test": "npm run build && vitest run",
28
+ "test:watch": "vitest",
29
+ "lint": "eslint src/ --ext .ts",
30
+ "format": "prettier --write 'src/**/*.ts' 'test/**/*.ts'",
31
+ "format:check": "prettier --check 'src/**/*.ts' 'test/**/*.ts'",
32
+ "sbom": "npm sbom --sbom-format=spdx --omit=dev"
51
33
  },
52
34
  "keywords": [
53
- "ai-coding-agent",
54
- "code-security",
55
- "sast",
35
+ "ai-coding-agents",
36
+ "agent-orchestration",
37
+ "audit-trail",
56
38
  "trust-scoring",
57
39
  "ai-safety",
58
- "multi-agent",
59
- "orchestration",
40
+ "ai-governance",
60
41
  "claude-code",
61
- "cursor",
62
- "coding-assistant",
63
- "cli-tool",
64
- "code-review",
42
+ "codex",
43
+ "aider",
44
+ "opencode",
65
45
  "hook-system",
66
- "audit-trail",
46
+ "sast",
47
+ "cli-tool",
67
48
  "typescript"
68
49
  ],
69
- "author": "Muhammad Ega",
50
+ "author": "The codehere authors",
70
51
  "license": "MIT",
71
52
  "repository": {
72
53
  "type": "git",
73
- "url": "https://github.com/muhammadegaa/codehere.git"
54
+ "url": "git+https://github.com/muhammadegaa/codehere.git"
74
55
  },
75
56
  "bugs": {
76
57
  "url": "https://github.com/muhammadegaa/codehere/issues"
77
58
  },
78
59
  "homepage": "https://codehere.uk",
79
- "logo": "https://codehere.uk/icon.svg",
80
60
  "dependencies": {
81
61
  "boxen": "^8.0.1",
82
62
  "chalk": "^5.3.0",
83
63
  "cli-progress": "^3.12.0",
84
64
  "cli-table3": "^0.6.5",
85
- "cohere-ai": "^7.7.0",
86
65
  "commander": "^11.1.0",
87
- "cors": "^2.8.5",
88
- "diff": "^5.1.0",
89
66
  "dotenv": "^16.3.1",
90
- "express": "^5.1.0",
91
- "get-tsconfig": "^4.13.0",
92
- "inquirer": "^13.0.1",
93
- "ora": "^7.0.1",
94
- "resolve-pkg-maps": "^1.0.0",
95
- "sql.js": "^1.10.3",
96
- "tiktoken": "^1.0.10",
97
- "wrap-ansi": "^9.0.2"
67
+ "ora": "^7.0.1"
98
68
  },
99
69
  "devDependencies": {
70
+ "@eslint/js": "^10.0.1",
100
71
  "@types/cli-progress": "^3.11.5",
101
- "@types/cors": "^2.8.19",
102
- "@types/diff": "^5.0.8",
103
- "@types/express": "^5.0.5",
104
72
  "@types/node": "^20.19.25",
105
- "@types/sql.js": "^1.4.8",
106
- "@types/supertest": "^6.0.3",
107
- "c8": "^10.1.3",
108
- "supertest": "^7.1.4",
73
+ "eslint": "^10.2.0",
74
+ "prettier": "^3.8.3",
109
75
  "tsx": "^4.21.0",
110
- "typescript": "^5.9.3"
76
+ "typescript": "^5.9.3",
77
+ "typescript-eslint": "^8.58.2",
78
+ "vitest": "^4.1.4"
111
79
  }
112
80
  }