@peakinfer/cli 1.0.133

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 (367) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/.env.example +6 -0
  3. package/.github/workflows/peakinfer.yml +64 -0
  4. package/CHANGELOG.md +31 -0
  5. package/LICENSE +190 -0
  6. package/README.md +335 -0
  7. package/data/inferencemax.json +274 -0
  8. package/dist/agent-analyzer.d.ts +45 -0
  9. package/dist/agent-analyzer.d.ts.map +1 -0
  10. package/dist/agent-analyzer.js +374 -0
  11. package/dist/agent-analyzer.js.map +1 -0
  12. package/dist/agent.d.ts +76 -0
  13. package/dist/agent.d.ts.map +1 -0
  14. package/dist/agent.js +965 -0
  15. package/dist/agent.js.map +1 -0
  16. package/dist/agents/correlation-analyzer.d.ts +34 -0
  17. package/dist/agents/correlation-analyzer.d.ts.map +1 -0
  18. package/dist/agents/correlation-analyzer.js +261 -0
  19. package/dist/agents/correlation-analyzer.js.map +1 -0
  20. package/dist/agents/index.d.ts +91 -0
  21. package/dist/agents/index.d.ts.map +1 -0
  22. package/dist/agents/index.js +111 -0
  23. package/dist/agents/index.js.map +1 -0
  24. package/dist/agents/runtime-analyzer.d.ts +38 -0
  25. package/dist/agents/runtime-analyzer.d.ts.map +1 -0
  26. package/dist/agents/runtime-analyzer.js +244 -0
  27. package/dist/agents/runtime-analyzer.js.map +1 -0
  28. package/dist/analysis-types.d.ts +500 -0
  29. package/dist/analysis-types.d.ts.map +1 -0
  30. package/dist/analysis-types.js +11 -0
  31. package/dist/analysis-types.js.map +1 -0
  32. package/dist/analytics.d.ts +25 -0
  33. package/dist/analytics.d.ts.map +1 -0
  34. package/dist/analytics.js +94 -0
  35. package/dist/analytics.js.map +1 -0
  36. package/dist/analyzer.d.ts +48 -0
  37. package/dist/analyzer.d.ts.map +1 -0
  38. package/dist/analyzer.js +547 -0
  39. package/dist/analyzer.js.map +1 -0
  40. package/dist/artifacts.d.ts +44 -0
  41. package/dist/artifacts.d.ts.map +1 -0
  42. package/dist/artifacts.js +165 -0
  43. package/dist/artifacts.js.map +1 -0
  44. package/dist/benchmarks/index.d.ts +88 -0
  45. package/dist/benchmarks/index.d.ts.map +1 -0
  46. package/dist/benchmarks/index.js +205 -0
  47. package/dist/benchmarks/index.js.map +1 -0
  48. package/dist/cli.d.ts +3 -0
  49. package/dist/cli.d.ts.map +1 -0
  50. package/dist/cli.js +427 -0
  51. package/dist/cli.js.map +1 -0
  52. package/dist/commands/ci.d.ts +19 -0
  53. package/dist/commands/ci.d.ts.map +1 -0
  54. package/dist/commands/ci.js +253 -0
  55. package/dist/commands/ci.js.map +1 -0
  56. package/dist/commands/config.d.ts +16 -0
  57. package/dist/commands/config.d.ts.map +1 -0
  58. package/dist/commands/config.js +249 -0
  59. package/dist/commands/config.js.map +1 -0
  60. package/dist/commands/demo.d.ts +15 -0
  61. package/dist/commands/demo.d.ts.map +1 -0
  62. package/dist/commands/demo.js +106 -0
  63. package/dist/commands/demo.js.map +1 -0
  64. package/dist/commands/export.d.ts +14 -0
  65. package/dist/commands/export.d.ts.map +1 -0
  66. package/dist/commands/export.js +209 -0
  67. package/dist/commands/export.js.map +1 -0
  68. package/dist/commands/history.d.ts +15 -0
  69. package/dist/commands/history.d.ts.map +1 -0
  70. package/dist/commands/history.js +389 -0
  71. package/dist/commands/history.js.map +1 -0
  72. package/dist/commands/template.d.ts +14 -0
  73. package/dist/commands/template.d.ts.map +1 -0
  74. package/dist/commands/template.js +341 -0
  75. package/dist/commands/template.js.map +1 -0
  76. package/dist/commands/validate-map.d.ts +12 -0
  77. package/dist/commands/validate-map.d.ts.map +1 -0
  78. package/dist/commands/validate-map.js +274 -0
  79. package/dist/commands/validate-map.js.map +1 -0
  80. package/dist/commands/whatif.d.ts +17 -0
  81. package/dist/commands/whatif.d.ts.map +1 -0
  82. package/dist/commands/whatif.js +206 -0
  83. package/dist/commands/whatif.js.map +1 -0
  84. package/dist/comparison.d.ts +38 -0
  85. package/dist/comparison.d.ts.map +1 -0
  86. package/dist/comparison.js +223 -0
  87. package/dist/comparison.js.map +1 -0
  88. package/dist/config.d.ts +42 -0
  89. package/dist/config.d.ts.map +1 -0
  90. package/dist/config.js +158 -0
  91. package/dist/config.js.map +1 -0
  92. package/dist/connectors/helicone.d.ts +9 -0
  93. package/dist/connectors/helicone.d.ts.map +1 -0
  94. package/dist/connectors/helicone.js +106 -0
  95. package/dist/connectors/helicone.js.map +1 -0
  96. package/dist/connectors/index.d.ts +37 -0
  97. package/dist/connectors/index.d.ts.map +1 -0
  98. package/dist/connectors/index.js +65 -0
  99. package/dist/connectors/index.js.map +1 -0
  100. package/dist/connectors/langsmith.d.ts +9 -0
  101. package/dist/connectors/langsmith.d.ts.map +1 -0
  102. package/dist/connectors/langsmith.js +122 -0
  103. package/dist/connectors/langsmith.js.map +1 -0
  104. package/dist/connectors/types.d.ts +83 -0
  105. package/dist/connectors/types.d.ts.map +1 -0
  106. package/dist/connectors/types.js +98 -0
  107. package/dist/connectors/types.js.map +1 -0
  108. package/dist/cost-estimator.d.ts +46 -0
  109. package/dist/cost-estimator.d.ts.map +1 -0
  110. package/dist/cost-estimator.js +104 -0
  111. package/dist/cost-estimator.js.map +1 -0
  112. package/dist/costs.d.ts +57 -0
  113. package/dist/costs.d.ts.map +1 -0
  114. package/dist/costs.js +251 -0
  115. package/dist/costs.js.map +1 -0
  116. package/dist/counterfactuals.d.ts +29 -0
  117. package/dist/counterfactuals.d.ts.map +1 -0
  118. package/dist/counterfactuals.js +448 -0
  119. package/dist/counterfactuals.js.map +1 -0
  120. package/dist/enhancement-prompts.d.ts +41 -0
  121. package/dist/enhancement-prompts.d.ts.map +1 -0
  122. package/dist/enhancement-prompts.js +88 -0
  123. package/dist/enhancement-prompts.js.map +1 -0
  124. package/dist/envelopes.d.ts +20 -0
  125. package/dist/envelopes.d.ts.map +1 -0
  126. package/dist/envelopes.js +790 -0
  127. package/dist/envelopes.js.map +1 -0
  128. package/dist/format-normalizer.d.ts +71 -0
  129. package/dist/format-normalizer.d.ts.map +1 -0
  130. package/dist/format-normalizer.js +1331 -0
  131. package/dist/format-normalizer.js.map +1 -0
  132. package/dist/history.d.ts +79 -0
  133. package/dist/history.d.ts.map +1 -0
  134. package/dist/history.js +313 -0
  135. package/dist/history.js.map +1 -0
  136. package/dist/html.d.ts +11 -0
  137. package/dist/html.d.ts.map +1 -0
  138. package/dist/html.js +463 -0
  139. package/dist/html.js.map +1 -0
  140. package/dist/impact.d.ts +42 -0
  141. package/dist/impact.d.ts.map +1 -0
  142. package/dist/impact.js +443 -0
  143. package/dist/impact.js.map +1 -0
  144. package/dist/index.d.ts +26 -0
  145. package/dist/index.d.ts.map +1 -0
  146. package/dist/index.js +34 -0
  147. package/dist/index.js.map +1 -0
  148. package/dist/insights.d.ts +5 -0
  149. package/dist/insights.d.ts.map +1 -0
  150. package/dist/insights.js +271 -0
  151. package/dist/insights.js.map +1 -0
  152. package/dist/joiner.d.ts +9 -0
  153. package/dist/joiner.d.ts.map +1 -0
  154. package/dist/joiner.js +247 -0
  155. package/dist/joiner.js.map +1 -0
  156. package/dist/orchestrator.d.ts +34 -0
  157. package/dist/orchestrator.d.ts.map +1 -0
  158. package/dist/orchestrator.js +827 -0
  159. package/dist/orchestrator.js.map +1 -0
  160. package/dist/pdf.d.ts +26 -0
  161. package/dist/pdf.d.ts.map +1 -0
  162. package/dist/pdf.js +84 -0
  163. package/dist/pdf.js.map +1 -0
  164. package/dist/prediction.d.ts +33 -0
  165. package/dist/prediction.d.ts.map +1 -0
  166. package/dist/prediction.js +316 -0
  167. package/dist/prediction.js.map +1 -0
  168. package/dist/prompts/loader.d.ts +38 -0
  169. package/dist/prompts/loader.d.ts.map +1 -0
  170. package/dist/prompts/loader.js +60 -0
  171. package/dist/prompts/loader.js.map +1 -0
  172. package/dist/renderer.d.ts +64 -0
  173. package/dist/renderer.d.ts.map +1 -0
  174. package/dist/renderer.js +923 -0
  175. package/dist/renderer.js.map +1 -0
  176. package/dist/runid.d.ts +57 -0
  177. package/dist/runid.d.ts.map +1 -0
  178. package/dist/runid.js +199 -0
  179. package/dist/runid.js.map +1 -0
  180. package/dist/runtime.d.ts +29 -0
  181. package/dist/runtime.d.ts.map +1 -0
  182. package/dist/runtime.js +366 -0
  183. package/dist/runtime.js.map +1 -0
  184. package/dist/scanner.d.ts +11 -0
  185. package/dist/scanner.d.ts.map +1 -0
  186. package/dist/scanner.js +426 -0
  187. package/dist/scanner.js.map +1 -0
  188. package/dist/templates.d.ts +120 -0
  189. package/dist/templates.d.ts.map +1 -0
  190. package/dist/templates.js +429 -0
  191. package/dist/templates.js.map +1 -0
  192. package/dist/tools/index.d.ts +153 -0
  193. package/dist/tools/index.d.ts.map +1 -0
  194. package/dist/tools/index.js +177 -0
  195. package/dist/tools/index.js.map +1 -0
  196. package/dist/types.d.ts +3647 -0
  197. package/dist/types.d.ts.map +1 -0
  198. package/dist/types.js +703 -0
  199. package/dist/types.js.map +1 -0
  200. package/dist/version.d.ts +7 -0
  201. package/dist/version.d.ts.map +1 -0
  202. package/dist/version.js +23 -0
  203. package/dist/version.js.map +1 -0
  204. package/docs/demo-guide.md +423 -0
  205. package/docs/events-format.md +295 -0
  206. package/docs/inferencemap-spec.md +344 -0
  207. package/docs/migration-v2.md +293 -0
  208. package/fixtures/demo/precomputed.json +142 -0
  209. package/fixtures/demo-project/README.md +52 -0
  210. package/fixtures/demo-project/ai-service.ts +65 -0
  211. package/fixtures/demo-project/sample-events.jsonl +15 -0
  212. package/fixtures/demo-project/src/ai-service.ts +128 -0
  213. package/fixtures/demo-project/src/llm-client.ts +155 -0
  214. package/package.json +65 -0
  215. package/prompts/agent-analyzer.yaml +47 -0
  216. package/prompts/ci-gate.yaml +98 -0
  217. package/prompts/correlation-analyzer.yaml +178 -0
  218. package/prompts/format-normalizer.yaml +46 -0
  219. package/prompts/peak-performance.yaml +180 -0
  220. package/prompts/pr-comment.yaml +111 -0
  221. package/prompts/runtime-analyzer.yaml +189 -0
  222. package/prompts/unified-analyzer.yaml +241 -0
  223. package/schemas/inference-map.v0.1.json +215 -0
  224. package/scripts/benchmark.ts +394 -0
  225. package/scripts/demo-v1.5.sh +158 -0
  226. package/scripts/sync-from-site.sh +197 -0
  227. package/scripts/validate-sync.sh +178 -0
  228. package/src/agent-analyzer.ts +481 -0
  229. package/src/agent.ts +1232 -0
  230. package/src/agents/correlation-analyzer.ts +353 -0
  231. package/src/agents/index.ts +235 -0
  232. package/src/agents/runtime-analyzer.ts +343 -0
  233. package/src/analysis-types.ts +558 -0
  234. package/src/analytics.ts +100 -0
  235. package/src/analyzer.ts +692 -0
  236. package/src/artifacts.ts +218 -0
  237. package/src/benchmarks/index.ts +309 -0
  238. package/src/cli.ts +503 -0
  239. package/src/commands/ci.ts +336 -0
  240. package/src/commands/config.ts +288 -0
  241. package/src/commands/demo.ts +175 -0
  242. package/src/commands/export.ts +297 -0
  243. package/src/commands/history.ts +425 -0
  244. package/src/commands/template.ts +385 -0
  245. package/src/commands/validate-map.ts +324 -0
  246. package/src/commands/whatif.ts +272 -0
  247. package/src/comparison.ts +283 -0
  248. package/src/config.ts +188 -0
  249. package/src/connectors/helicone.ts +164 -0
  250. package/src/connectors/index.ts +93 -0
  251. package/src/connectors/langsmith.ts +179 -0
  252. package/src/connectors/types.ts +180 -0
  253. package/src/cost-estimator.ts +146 -0
  254. package/src/costs.ts +347 -0
  255. package/src/counterfactuals.ts +516 -0
  256. package/src/enhancement-prompts.ts +118 -0
  257. package/src/envelopes.ts +814 -0
  258. package/src/format-normalizer.ts +1486 -0
  259. package/src/history.ts +400 -0
  260. package/src/html.ts +512 -0
  261. package/src/impact.ts +522 -0
  262. package/src/index.ts +83 -0
  263. package/src/insights.ts +341 -0
  264. package/src/joiner.ts +289 -0
  265. package/src/orchestrator.ts +1015 -0
  266. package/src/pdf.ts +110 -0
  267. package/src/prediction.ts +392 -0
  268. package/src/prompts/loader.ts +88 -0
  269. package/src/renderer.ts +1045 -0
  270. package/src/runid.ts +261 -0
  271. package/src/runtime.ts +450 -0
  272. package/src/scanner.ts +508 -0
  273. package/src/templates.ts +561 -0
  274. package/src/tools/index.ts +214 -0
  275. package/src/types.ts +873 -0
  276. package/src/version.ts +24 -0
  277. package/templates/context-accumulation.yaml +23 -0
  278. package/templates/cost-concentration.yaml +20 -0
  279. package/templates/dead-code.yaml +20 -0
  280. package/templates/latency-explainer.yaml +23 -0
  281. package/templates/optimizations/ab-testing-framework.yaml +74 -0
  282. package/templates/optimizations/api-gateway-optimization.yaml +81 -0
  283. package/templates/optimizations/api-model-routing-strategy.yaml +126 -0
  284. package/templates/optimizations/auto-scaling-optimization.yaml +85 -0
  285. package/templates/optimizations/batch-utilization-diagnostic.yaml +142 -0
  286. package/templates/optimizations/comprehensive-apm.yaml +76 -0
  287. package/templates/optimizations/context-window-optimization.yaml +91 -0
  288. package/templates/optimizations/cost-sensitive-batch-processing.yaml +77 -0
  289. package/templates/optimizations/distributed-training-optimization.yaml +77 -0
  290. package/templates/optimizations/document-analysis-edge.yaml +77 -0
  291. package/templates/optimizations/document-pipeline-optimization.yaml +78 -0
  292. package/templates/optimizations/domain-specific-distillation.yaml +78 -0
  293. package/templates/optimizations/error-handling-optimization.yaml +76 -0
  294. package/templates/optimizations/gptq-4bit-quantization.yaml +96 -0
  295. package/templates/optimizations/long-context-memory-management.yaml +78 -0
  296. package/templates/optimizations/max-tokens-optimization.yaml +76 -0
  297. package/templates/optimizations/memory-bandwidth-optimization.yaml +73 -0
  298. package/templates/optimizations/multi-framework-resilience.yaml +75 -0
  299. package/templates/optimizations/multi-tenant-optimization.yaml +75 -0
  300. package/templates/optimizations/prompt-caching-optimization.yaml +143 -0
  301. package/templates/optimizations/pytorch-to-onnx-migration.yaml +109 -0
  302. package/templates/optimizations/quality-monitoring.yaml +74 -0
  303. package/templates/optimizations/realtime-budget-controls.yaml +74 -0
  304. package/templates/optimizations/realtime-latency-optimization.yaml +74 -0
  305. package/templates/optimizations/sglang-concurrency-optimization.yaml +78 -0
  306. package/templates/optimizations/smart-model-routing.yaml +96 -0
  307. package/templates/optimizations/streaming-batch-selection.yaml +167 -0
  308. package/templates/optimizations/system-prompt-optimization.yaml +75 -0
  309. package/templates/optimizations/tensorrt-llm-performance.yaml +77 -0
  310. package/templates/optimizations/vllm-high-throughput-optimization.yaml +93 -0
  311. package/templates/optimizations/vllm-migration-memory-bound.yaml +78 -0
  312. package/templates/overpowered-extraction.yaml +32 -0
  313. package/templates/overpowered-model.yaml +31 -0
  314. package/templates/prompt-bloat.yaml +24 -0
  315. package/templates/retry-explosion.yaml +28 -0
  316. package/templates/schema/insight.schema.json +113 -0
  317. package/templates/schema/optimization.schema.json +180 -0
  318. package/templates/streaming-drift.yaml +30 -0
  319. package/templates/throughput-gap.yaml +21 -0
  320. package/templates/token-underutilization.yaml +28 -0
  321. package/templates/untested-fallback.yaml +21 -0
  322. package/tests/accuracy/drift-detection.test.ts +184 -0
  323. package/tests/accuracy/false-positives.test.ts +166 -0
  324. package/tests/accuracy/templates.test.ts +205 -0
  325. package/tests/action/commands.test.ts +125 -0
  326. package/tests/action/comments.test.ts +347 -0
  327. package/tests/cli.test.ts +203 -0
  328. package/tests/comparison.test.ts +309 -0
  329. package/tests/correlation-analyzer.test.ts +534 -0
  330. package/tests/counterfactuals.test.ts +347 -0
  331. package/tests/fixtures/events/missing-id.jsonl +1 -0
  332. package/tests/fixtures/events/missing-input.jsonl +1 -0
  333. package/tests/fixtures/events/missing-latency.jsonl +1 -0
  334. package/tests/fixtures/events/missing-model.jsonl +1 -0
  335. package/tests/fixtures/events/missing-output.jsonl +1 -0
  336. package/tests/fixtures/events/missing-provider.jsonl +1 -0
  337. package/tests/fixtures/events/missing-ts.jsonl +1 -0
  338. package/tests/fixtures/events/valid.csv +3 -0
  339. package/tests/fixtures/events/valid.json +1 -0
  340. package/tests/fixtures/events/valid.jsonl +2 -0
  341. package/tests/fixtures/events/with-callsite.jsonl +1 -0
  342. package/tests/fixtures/events/with-intent.jsonl +1 -0
  343. package/tests/fixtures/events/wrong-type.jsonl +1 -0
  344. package/tests/fixtures/repos/empty/.gitkeep +0 -0
  345. package/tests/fixtures/repos/hybrid-router/router.py +35 -0
  346. package/tests/fixtures/repos/saas-anthropic/agent.ts +27 -0
  347. package/tests/fixtures/repos/saas-openai/assistant.js +33 -0
  348. package/tests/fixtures/repos/saas-openai/client.py +26 -0
  349. package/tests/fixtures/repos/self-hosted-vllm/inference.py +22 -0
  350. package/tests/github-action.test.ts +292 -0
  351. package/tests/insights.test.ts +878 -0
  352. package/tests/joiner.test.ts +168 -0
  353. package/tests/performance/action-latency.test.ts +132 -0
  354. package/tests/performance/benchmark.test.ts +189 -0
  355. package/tests/performance/cli-latency.test.ts +102 -0
  356. package/tests/pr-comment.test.ts +313 -0
  357. package/tests/prediction.test.ts +296 -0
  358. package/tests/runtime-analyzer.test.ts +375 -0
  359. package/tests/runtime.test.ts +205 -0
  360. package/tests/scanner.test.ts +122 -0
  361. package/tests/template-conformance.test.ts +526 -0
  362. package/tests/unit/cost-calculator.test.ts +303 -0
  363. package/tests/unit/credits.test.ts +180 -0
  364. package/tests/unit/inference-map.test.ts +276 -0
  365. package/tests/unit/schema.test.ts +300 -0
  366. package/tsconfig.json +20 -0
  367. package/vitest.config.ts +14 -0
@@ -0,0 +1,175 @@
1
+ /**
2
+ * PeakInfer Demo Command
3
+ *
4
+ * Runs a pre-computed demo analysis WITHOUT requiring an API key.
5
+ * This is the first-contact moment - must work offline.
6
+ *
7
+ * Per Design Doc v1.9.3:
8
+ * - Shows the "Magic Moment" (drift detection)
9
+ * - Works without API key
10
+ * - Completes in under 30 seconds
11
+ * - Always produces an alarming finding
12
+ */
13
+ import { Command } from 'commander';
14
+ import { readFileSync, existsSync } from 'fs';
15
+ import { join, dirname } from 'path';
16
+ import { fileURLToPath } from 'url';
17
+ import chalk from 'chalk';
18
+
19
+ // Get package root directory
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = dirname(__filename);
22
+ const packageRoot = join(__dirname, '..', '..');
23
+
24
+ const COLORS = {
25
+ text: '#c9d1d9',
26
+ command: '#f0f6fc',
27
+ info: '#8b949e',
28
+ path: '#a5a29e',
29
+ critical: '#991b1b',
30
+ criticalLight: '#b91c1c',
31
+ warning: '#d29922',
32
+ duration: '#9e6a03',
33
+ border: '#30363d',
34
+ success: '#2d6a4f',
35
+ };
36
+
37
+ interface DemoData {
38
+ version: string;
39
+ drift: {
40
+ detected: boolean;
41
+ type: string;
42
+ description: string;
43
+ evidence: {
44
+ code: string;
45
+ runtime: string;
46
+ impact: string;
47
+ duration: string;
48
+ };
49
+ };
50
+ issues: Array<{
51
+ id: string;
52
+ severity: string;
53
+ category: string;
54
+ title: string;
55
+ description: string;
56
+ impact: string;
57
+ savings?: string;
58
+ file: string;
59
+ line: number;
60
+ fix: {
61
+ description: string;
62
+ effort: string;
63
+ };
64
+ }>;
65
+ summary: {
66
+ totalInferencePoints: number;
67
+ providers: string[];
68
+ criticalIssues: number;
69
+ highIssues: number;
70
+ mediumIssues: number;
71
+ estimatedMonthlySavings: string;
72
+ estimatedLatencyImprovement: string;
73
+ };
74
+ }
75
+
76
+ export function registerDemoCommand(program: Command): void {
77
+ program
78
+ .command('demo')
79
+ .description('see PeakInfer in action with a sample project (no API key needed)')
80
+ .option('--verbose', 'show additional details')
81
+ .action(async (options: { verbose?: boolean }) => {
82
+ await runDemo(options.verbose);
83
+ });
84
+ }
85
+
86
+ async function runDemo(verbose?: boolean): Promise<void> {
87
+ const startTime = Date.now();
88
+
89
+ // Load pre-computed demo data
90
+ const demoDataPath = join(packageRoot, 'fixtures', 'demo', 'precomputed.json');
91
+
92
+ if (!existsSync(demoDataPath)) {
93
+ console.error(chalk.hex(COLORS.critical)('Error: Demo data not found. Please reinstall PeakInfer.'));
94
+ process.exit(1);
95
+ }
96
+
97
+ const demoData: DemoData = JSON.parse(readFileSync(demoDataPath, 'utf-8'));
98
+
99
+ // Render the demo output
100
+ console.log();
101
+ console.log(chalk.hex(COLORS.border)('╔══════════════════════════════════════════════════════════════╗'));
102
+ console.log(chalk.hex(COLORS.border)('║') + chalk.hex(COLORS.text)(' PeakInfer Demo ') + chalk.hex(COLORS.border)('║'));
103
+ console.log(chalk.hex(COLORS.border)('╚══════════════════════════════════════════════════════════════╝'));
104
+ console.log();
105
+
106
+ // Simulate scanning animation
107
+ console.log(chalk.hex(COLORS.info)('Scanning demo project...'));
108
+ await sleep(500);
109
+ console.log(chalk.hex(COLORS.info)(`Found ${demoData.summary.totalInferencePoints} inference points`));
110
+ await sleep(300);
111
+ console.log();
112
+
113
+ // THE MAGIC MOMENT - Drift Detection
114
+ if (demoData.drift.detected) {
115
+ console.log(chalk.hex(COLORS.criticalLight)('DRIFT DETECTED'));
116
+ console.log();
117
+ console.log(chalk.hex(COLORS.border)(' ┌─────────────────────────────────────────────────────────┐'));
118
+ console.log(chalk.hex(COLORS.border)(' │') + chalk.hex(COLORS.info)(' YOUR CODE: ') + chalk.hex(COLORS.text)(`${demoData.drift.evidence.code}`) + ' ' + chalk.hex(COLORS.border)('│'));
119
+ console.log(chalk.hex(COLORS.border)(' │') + chalk.hex(COLORS.info)(' RUNTIME: ') + chalk.hex(COLORS.critical)(`${demoData.drift.evidence.runtime}`) + ' ' + chalk.hex(COLORS.border)('│'));
120
+ console.log(chalk.hex(COLORS.border)(' │') + chalk.hex(COLORS.info)(' IMPACT: ') + chalk.hex(COLORS.warning)(`${demoData.drift.evidence.impact}`) + ' ' + chalk.hex(COLORS.border)('│'));
121
+ console.log(chalk.hex(COLORS.border)(' │') + chalk.hex(COLORS.info)(' BROKEN FOR: ') + chalk.hex(COLORS.duration)(`${demoData.drift.evidence.duration}`) + ' ' + chalk.hex(COLORS.border)('│'));
122
+ console.log(chalk.hex(COLORS.border)(' └─────────────────────────────────────────────────────────┘'));
123
+ console.log();
124
+ }
125
+
126
+ // Summary stats
127
+ console.log(chalk.hex(COLORS.border)('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
128
+ console.log();
129
+ console.log(chalk.hex(COLORS.text)(` ${demoData.summary.totalInferencePoints} inference points found`));
130
+ console.log(chalk.hex(COLORS.text)(` ${demoData.issues.length} issues detected`));
131
+ console.log();
132
+
133
+ // Top issues
134
+ const criticalAndHigh = demoData.issues.filter(i => i.severity === 'critical' || i.severity === 'high');
135
+
136
+ for (const issue of criticalAndHigh.slice(0, 3)) {
137
+ const severityColor = issue.severity === 'critical'
138
+ ? chalk.hex(COLORS.critical)
139
+ : chalk.hex(COLORS.warning);
140
+
141
+ console.log(` ${severityColor(issue.severity.toUpperCase())}: ${chalk.hex(COLORS.text)(issue.title)}`);
142
+ console.log(chalk.hex(COLORS.path)(` ${issue.file}:${issue.line}`));
143
+ console.log(chalk.hex(COLORS.info)(` ${issue.description}`));
144
+ if (issue.savings) {
145
+ console.log(chalk.hex(COLORS.success)(` Potential savings: ${issue.savings}`));
146
+ }
147
+ console.log();
148
+ }
149
+
150
+ // Quick wins summary
151
+ console.log(chalk.hex(COLORS.success)('QUICK WINS:'));
152
+ console.log(chalk.hex(COLORS.text)(` • Estimated savings: ${demoData.summary.estimatedMonthlySavings}`));
153
+ console.log(chalk.hex(COLORS.text)(` • Latency improvement: ${demoData.summary.estimatedLatencyImprovement}`));
154
+ console.log();
155
+
156
+ // CTA
157
+ console.log(chalk.hex(COLORS.border)('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
158
+ console.log();
159
+ console.log(chalk.hex(COLORS.text)(' Is YOUR code like this?'));
160
+ console.log();
161
+ console.log(chalk.hex(COLORS.text)(' Run on your codebase:'));
162
+ console.log(chalk.hex(COLORS.command)(' peakinfer analyze ./src'));
163
+ console.log();
164
+ console.log(chalk.hex(COLORS.info)(' Requires Anthropic API key. Set ANTHROPIC_API_KEY in .env'));
165
+ console.log();
166
+
167
+ const duration = Date.now() - startTime;
168
+ if (verbose) {
169
+ console.log(chalk.hex(COLORS.info)(`Demo completed in ${duration}ms`));
170
+ }
171
+ }
172
+
173
+ function sleep(ms: number): Promise<void> {
174
+ return new Promise(resolve => setTimeout(resolve, ms));
175
+ }
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Export Command (v1.6)
3
+ *
4
+ * CLI command for exporting analysis results in various formats:
5
+ * - inferencemap: InferenceMap v0.1 schema (default)
6
+ * - json: Full analysis results
7
+ * - prometheus: Prometheus metrics format
8
+ */
9
+
10
+ import { Command } from 'commander';
11
+ import { existsSync, writeFileSync } from 'fs';
12
+ import { listRuns, loadRun } from '../history.js';
13
+ import type { InferenceMap, Insight } from '../types.js';
14
+
15
+ // =============================================================================
16
+ // TYPES
17
+ // =============================================================================
18
+
19
+ interface ExportOptions {
20
+ format: 'inferencemap' | 'json' | 'prometheus';
21
+ output?: string;
22
+ run?: string;
23
+ }
24
+
25
+ interface AnalysisExport {
26
+ inferenceMap?: InferenceMap;
27
+ insights?: Insight[];
28
+ runtime?: unknown;
29
+ joined?: unknown;
30
+ }
31
+
32
+ // =============================================================================
33
+ // EXPORTERS
34
+ // =============================================================================
35
+
36
+ /**
37
+ * Export in InferenceMap v0.1 schema format
38
+ * Matches schemas/inference-map.v0.1.json
39
+ */
40
+ function exportInferenceMap(data: AnalysisExport): string {
41
+ if (!data.inferenceMap) {
42
+ throw new Error('No inference map data available to export');
43
+ }
44
+
45
+ // InferenceMap v0.1 schema - preserve the original version
46
+ // The inferenceMap should already have version: "0.1"
47
+ const output = {
48
+ ...data.inferenceMap,
49
+ exportedAt: new Date().toISOString(),
50
+ };
51
+
52
+ return JSON.stringify(output, null, 2);
53
+ }
54
+
55
+ /**
56
+ * Export full analysis results as JSON
57
+ */
58
+ function exportJSON(data: AnalysisExport): string {
59
+ const output = {
60
+ exportedAt: new Date().toISOString(),
61
+ format: 'peakinfer-analysis',
62
+ version: '1.0',
63
+ inferenceMap: data.inferenceMap,
64
+ insights: data.insights,
65
+ runtime: data.runtime,
66
+ joined: data.joined,
67
+ };
68
+
69
+ return JSON.stringify(output, null, 2);
70
+ }
71
+
72
+ /**
73
+ * Export in Prometheus metrics format
74
+ */
75
+ function exportPrometheus(data: AnalysisExport): string {
76
+ const lines: string[] = [];
77
+ const timestamp = Date.now();
78
+
79
+ // Helper to add metric
80
+ const addMetric = (name: string, help: string, type: string, value: number, labels: Record<string, string> = {}) => {
81
+ lines.push(`# HELP ${name} ${help}`);
82
+ lines.push(`# TYPE ${name} ${type}`);
83
+
84
+ const labelStr = Object.entries(labels)
85
+ .map(([k, v]) => `${k}="${v}"`)
86
+ .join(',');
87
+
88
+ const fullName = labelStr ? `${name}{${labelStr}}` : name;
89
+ lines.push(`${fullName} ${value} ${timestamp}`);
90
+ };
91
+
92
+ if (data.inferenceMap) {
93
+ const map = data.inferenceMap;
94
+
95
+ // Total inference points
96
+ addMetric(
97
+ 'peakinfer_inference_points_total',
98
+ 'Total number of inference points detected',
99
+ 'gauge',
100
+ map.summary.totalCallsites
101
+ );
102
+
103
+ // Providers
104
+ for (const provider of map.summary.providers) {
105
+ const count = map.callsites.filter(c => c.provider === provider).length;
106
+ addMetric(
107
+ 'peakinfer_inference_points_by_provider',
108
+ 'Inference points by provider',
109
+ 'gauge',
110
+ count,
111
+ { provider }
112
+ );
113
+ }
114
+
115
+ // Models
116
+ for (const model of map.summary.models) {
117
+ const count = map.callsites.filter(c => c.model === model).length;
118
+ addMetric(
119
+ 'peakinfer_inference_points_by_model',
120
+ 'Inference points by model',
121
+ 'gauge',
122
+ count,
123
+ { model }
124
+ );
125
+ }
126
+
127
+ // Patterns
128
+ for (const [pattern, count] of Object.entries(map.summary.patterns)) {
129
+ addMetric(
130
+ 'peakinfer_pattern_usage',
131
+ 'Pattern usage across inference points',
132
+ 'gauge',
133
+ count,
134
+ { pattern }
135
+ );
136
+ }
137
+
138
+ // Average confidence
139
+ const avgConfidence = map.callsites.length > 0
140
+ ? map.callsites.reduce((sum, c) => sum + c.confidence, 0) / map.callsites.length
141
+ : 0;
142
+ addMetric(
143
+ 'peakinfer_detection_confidence_avg',
144
+ 'Average detection confidence (0-1)',
145
+ 'gauge',
146
+ avgConfidence
147
+ );
148
+ }
149
+
150
+ // Insights by severity
151
+ if (data.insights) {
152
+ const bySeverity = {
153
+ critical: data.insights.filter(i => i.severity === 'critical').length,
154
+ warning: data.insights.filter(i => i.severity === 'warning').length,
155
+ info: data.insights.filter(i => i.severity === 'info').length,
156
+ };
157
+
158
+ for (const [severity, count] of Object.entries(bySeverity)) {
159
+ addMetric(
160
+ 'peakinfer_insights_total',
161
+ 'Total insights by severity',
162
+ 'gauge',
163
+ count,
164
+ { severity }
165
+ );
166
+ }
167
+
168
+ // Insights by category
169
+ const byCategory: Record<string, number> = {};
170
+ for (const insight of data.insights) {
171
+ byCategory[insight.category] = (byCategory[insight.category] || 0) + 1;
172
+ }
173
+
174
+ for (const [category, count] of Object.entries(byCategory)) {
175
+ addMetric(
176
+ 'peakinfer_insights_by_category',
177
+ 'Insights by category',
178
+ 'gauge',
179
+ count,
180
+ { category }
181
+ );
182
+ }
183
+ }
184
+
185
+ return lines.join('\n');
186
+ }
187
+
188
+ // =============================================================================
189
+ // HELPERS
190
+ // =============================================================================
191
+
192
+ /**
193
+ * Get the default output filename based on format
194
+ */
195
+ function getDefaultFilename(format: string): string {
196
+ switch (format) {
197
+ case 'inferencemap':
198
+ return 'inference-map.json';
199
+ case 'prometheus':
200
+ return 'metrics.prom';
201
+ case 'json':
202
+ default:
203
+ return 'analysis.json';
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Load analysis data from history or latest run
209
+ */
210
+ function loadAnalysisData(runId?: string): AnalysisExport | null {
211
+ if (runId) {
212
+ // Load specific run
213
+ const run = loadRun(runId);
214
+ if (!run) {
215
+ return null;
216
+ }
217
+ return run.data;
218
+ }
219
+
220
+ // Load latest run
221
+ const runs = listRuns();
222
+ if (runs.length === 0) {
223
+ return null;
224
+ }
225
+
226
+ const latestRun = loadRun(runs[0].runId);
227
+ return latestRun?.data || null;
228
+ }
229
+
230
+ // =============================================================================
231
+ // COMMAND
232
+ // =============================================================================
233
+
234
+ /**
235
+ * Register export command
236
+ */
237
+ export function registerExportCommand(program: Command): void {
238
+ program
239
+ .command('export')
240
+ .description('export analysis results in various formats')
241
+ .option('--format <format>', 'output format: inferencemap (default), json, prometheus', 'inferencemap')
242
+ .option('--output <file>', 'output file path')
243
+ .option('--run <runId>', 'specific run to export (default: latest)')
244
+ .action(async (options: ExportOptions) => {
245
+ try {
246
+ // Validate format
247
+ const validFormats = ['inferencemap', 'json', 'prometheus'];
248
+ if (!validFormats.includes(options.format)) {
249
+ console.error(`Invalid format: ${options.format}`);
250
+ console.log(`Valid formats: ${validFormats.join(', ')}`);
251
+ process.exit(1);
252
+ }
253
+
254
+ // Load analysis data
255
+ const data = loadAnalysisData(options.run);
256
+ if (!data) {
257
+ console.error('No analysis data found.');
258
+ console.log('\nRun "peakinfer analyze ." first to generate analysis data.');
259
+ console.log('Or specify a run ID with --run <runId>');
260
+ process.exit(1);
261
+ }
262
+
263
+ // Export based on format
264
+ let output: string;
265
+ try {
266
+ switch (options.format) {
267
+ case 'inferencemap':
268
+ output = exportInferenceMap(data);
269
+ break;
270
+ case 'prometheus':
271
+ output = exportPrometheus(data);
272
+ break;
273
+ case 'json':
274
+ default:
275
+ output = exportJSON(data);
276
+ }
277
+ } catch (error) {
278
+ console.error('Export failed:', error instanceof Error ? error.message : 'Unknown error');
279
+ process.exit(1);
280
+ }
281
+
282
+ // Determine output destination
283
+ const outputFile = options.output || getDefaultFilename(options.format);
284
+
285
+ // Write to file or stdout
286
+ if (outputFile === '-') {
287
+ console.log(output);
288
+ } else {
289
+ writeFileSync(outputFile, output);
290
+ console.log(`Exported to ${outputFile} (${options.format} format)`);
291
+ }
292
+ } catch (error) {
293
+ console.error('Error:', error instanceof Error ? error.message : 'Export failed');
294
+ process.exit(1);
295
+ }
296
+ });
297
+ }