@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.
- package/.claude/settings.local.json +8 -0
- package/.env.example +6 -0
- package/.github/workflows/peakinfer.yml +64 -0
- package/CHANGELOG.md +31 -0
- package/LICENSE +190 -0
- package/README.md +335 -0
- package/data/inferencemax.json +274 -0
- package/dist/agent-analyzer.d.ts +45 -0
- package/dist/agent-analyzer.d.ts.map +1 -0
- package/dist/agent-analyzer.js +374 -0
- package/dist/agent-analyzer.js.map +1 -0
- package/dist/agent.d.ts +76 -0
- package/dist/agent.d.ts.map +1 -0
- package/dist/agent.js +965 -0
- package/dist/agent.js.map +1 -0
- package/dist/agents/correlation-analyzer.d.ts +34 -0
- package/dist/agents/correlation-analyzer.d.ts.map +1 -0
- package/dist/agents/correlation-analyzer.js +261 -0
- package/dist/agents/correlation-analyzer.js.map +1 -0
- package/dist/agents/index.d.ts +91 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +111 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/runtime-analyzer.d.ts +38 -0
- package/dist/agents/runtime-analyzer.d.ts.map +1 -0
- package/dist/agents/runtime-analyzer.js +244 -0
- package/dist/agents/runtime-analyzer.js.map +1 -0
- package/dist/analysis-types.d.ts +500 -0
- package/dist/analysis-types.d.ts.map +1 -0
- package/dist/analysis-types.js +11 -0
- package/dist/analysis-types.js.map +1 -0
- package/dist/analytics.d.ts +25 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +94 -0
- package/dist/analytics.js.map +1 -0
- package/dist/analyzer.d.ts +48 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +547 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/artifacts.d.ts +44 -0
- package/dist/artifacts.d.ts.map +1 -0
- package/dist/artifacts.js +165 -0
- package/dist/artifacts.js.map +1 -0
- package/dist/benchmarks/index.d.ts +88 -0
- package/dist/benchmarks/index.d.ts.map +1 -0
- package/dist/benchmarks/index.js +205 -0
- package/dist/benchmarks/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +427 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/ci.d.ts +19 -0
- package/dist/commands/ci.d.ts.map +1 -0
- package/dist/commands/ci.js +253 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/config.d.ts +16 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +249 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/demo.d.ts +15 -0
- package/dist/commands/demo.d.ts.map +1 -0
- package/dist/commands/demo.js +106 -0
- package/dist/commands/demo.js.map +1 -0
- package/dist/commands/export.d.ts +14 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +209 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/history.d.ts +15 -0
- package/dist/commands/history.d.ts.map +1 -0
- package/dist/commands/history.js +389 -0
- package/dist/commands/history.js.map +1 -0
- package/dist/commands/template.d.ts +14 -0
- package/dist/commands/template.d.ts.map +1 -0
- package/dist/commands/template.js +341 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/validate-map.d.ts +12 -0
- package/dist/commands/validate-map.d.ts.map +1 -0
- package/dist/commands/validate-map.js +274 -0
- package/dist/commands/validate-map.js.map +1 -0
- package/dist/commands/whatif.d.ts +17 -0
- package/dist/commands/whatif.d.ts.map +1 -0
- package/dist/commands/whatif.js +206 -0
- package/dist/commands/whatif.js.map +1 -0
- package/dist/comparison.d.ts +38 -0
- package/dist/comparison.d.ts.map +1 -0
- package/dist/comparison.js +223 -0
- package/dist/comparison.js.map +1 -0
- package/dist/config.d.ts +42 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +158 -0
- package/dist/config.js.map +1 -0
- package/dist/connectors/helicone.d.ts +9 -0
- package/dist/connectors/helicone.d.ts.map +1 -0
- package/dist/connectors/helicone.js +106 -0
- package/dist/connectors/helicone.js.map +1 -0
- package/dist/connectors/index.d.ts +37 -0
- package/dist/connectors/index.d.ts.map +1 -0
- package/dist/connectors/index.js +65 -0
- package/dist/connectors/index.js.map +1 -0
- package/dist/connectors/langsmith.d.ts +9 -0
- package/dist/connectors/langsmith.d.ts.map +1 -0
- package/dist/connectors/langsmith.js +122 -0
- package/dist/connectors/langsmith.js.map +1 -0
- package/dist/connectors/types.d.ts +83 -0
- package/dist/connectors/types.d.ts.map +1 -0
- package/dist/connectors/types.js +98 -0
- package/dist/connectors/types.js.map +1 -0
- package/dist/cost-estimator.d.ts +46 -0
- package/dist/cost-estimator.d.ts.map +1 -0
- package/dist/cost-estimator.js +104 -0
- package/dist/cost-estimator.js.map +1 -0
- package/dist/costs.d.ts +57 -0
- package/dist/costs.d.ts.map +1 -0
- package/dist/costs.js +251 -0
- package/dist/costs.js.map +1 -0
- package/dist/counterfactuals.d.ts +29 -0
- package/dist/counterfactuals.d.ts.map +1 -0
- package/dist/counterfactuals.js +448 -0
- package/dist/counterfactuals.js.map +1 -0
- package/dist/enhancement-prompts.d.ts +41 -0
- package/dist/enhancement-prompts.d.ts.map +1 -0
- package/dist/enhancement-prompts.js +88 -0
- package/dist/enhancement-prompts.js.map +1 -0
- package/dist/envelopes.d.ts +20 -0
- package/dist/envelopes.d.ts.map +1 -0
- package/dist/envelopes.js +790 -0
- package/dist/envelopes.js.map +1 -0
- package/dist/format-normalizer.d.ts +71 -0
- package/dist/format-normalizer.d.ts.map +1 -0
- package/dist/format-normalizer.js +1331 -0
- package/dist/format-normalizer.js.map +1 -0
- package/dist/history.d.ts +79 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +313 -0
- package/dist/history.js.map +1 -0
- package/dist/html.d.ts +11 -0
- package/dist/html.d.ts.map +1 -0
- package/dist/html.js +463 -0
- package/dist/html.js.map +1 -0
- package/dist/impact.d.ts +42 -0
- package/dist/impact.d.ts.map +1 -0
- package/dist/impact.js +443 -0
- package/dist/impact.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/insights.d.ts +5 -0
- package/dist/insights.d.ts.map +1 -0
- package/dist/insights.js +271 -0
- package/dist/insights.js.map +1 -0
- package/dist/joiner.d.ts +9 -0
- package/dist/joiner.d.ts.map +1 -0
- package/dist/joiner.js +247 -0
- package/dist/joiner.js.map +1 -0
- package/dist/orchestrator.d.ts +34 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +827 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/pdf.d.ts +26 -0
- package/dist/pdf.d.ts.map +1 -0
- package/dist/pdf.js +84 -0
- package/dist/pdf.js.map +1 -0
- package/dist/prediction.d.ts +33 -0
- package/dist/prediction.d.ts.map +1 -0
- package/dist/prediction.js +316 -0
- package/dist/prediction.js.map +1 -0
- package/dist/prompts/loader.d.ts +38 -0
- package/dist/prompts/loader.d.ts.map +1 -0
- package/dist/prompts/loader.js +60 -0
- package/dist/prompts/loader.js.map +1 -0
- package/dist/renderer.d.ts +64 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +923 -0
- package/dist/renderer.js.map +1 -0
- package/dist/runid.d.ts +57 -0
- package/dist/runid.d.ts.map +1 -0
- package/dist/runid.js +199 -0
- package/dist/runid.js.map +1 -0
- package/dist/runtime.d.ts +29 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +366 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scanner.d.ts +11 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +426 -0
- package/dist/scanner.js.map +1 -0
- package/dist/templates.d.ts +120 -0
- package/dist/templates.d.ts.map +1 -0
- package/dist/templates.js +429 -0
- package/dist/templates.js.map +1 -0
- package/dist/tools/index.d.ts +153 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +177 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types.d.ts +3647 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +703 -0
- package/dist/types.js.map +1 -0
- package/dist/version.d.ts +7 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +23 -0
- package/dist/version.js.map +1 -0
- package/docs/demo-guide.md +423 -0
- package/docs/events-format.md +295 -0
- package/docs/inferencemap-spec.md +344 -0
- package/docs/migration-v2.md +293 -0
- package/fixtures/demo/precomputed.json +142 -0
- package/fixtures/demo-project/README.md +52 -0
- package/fixtures/demo-project/ai-service.ts +65 -0
- package/fixtures/demo-project/sample-events.jsonl +15 -0
- package/fixtures/demo-project/src/ai-service.ts +128 -0
- package/fixtures/demo-project/src/llm-client.ts +155 -0
- package/package.json +65 -0
- package/prompts/agent-analyzer.yaml +47 -0
- package/prompts/ci-gate.yaml +98 -0
- package/prompts/correlation-analyzer.yaml +178 -0
- package/prompts/format-normalizer.yaml +46 -0
- package/prompts/peak-performance.yaml +180 -0
- package/prompts/pr-comment.yaml +111 -0
- package/prompts/runtime-analyzer.yaml +189 -0
- package/prompts/unified-analyzer.yaml +241 -0
- package/schemas/inference-map.v0.1.json +215 -0
- package/scripts/benchmark.ts +394 -0
- package/scripts/demo-v1.5.sh +158 -0
- package/scripts/sync-from-site.sh +197 -0
- package/scripts/validate-sync.sh +178 -0
- package/src/agent-analyzer.ts +481 -0
- package/src/agent.ts +1232 -0
- package/src/agents/correlation-analyzer.ts +353 -0
- package/src/agents/index.ts +235 -0
- package/src/agents/runtime-analyzer.ts +343 -0
- package/src/analysis-types.ts +558 -0
- package/src/analytics.ts +100 -0
- package/src/analyzer.ts +692 -0
- package/src/artifacts.ts +218 -0
- package/src/benchmarks/index.ts +309 -0
- package/src/cli.ts +503 -0
- package/src/commands/ci.ts +336 -0
- package/src/commands/config.ts +288 -0
- package/src/commands/demo.ts +175 -0
- package/src/commands/export.ts +297 -0
- package/src/commands/history.ts +425 -0
- package/src/commands/template.ts +385 -0
- package/src/commands/validate-map.ts +324 -0
- package/src/commands/whatif.ts +272 -0
- package/src/comparison.ts +283 -0
- package/src/config.ts +188 -0
- package/src/connectors/helicone.ts +164 -0
- package/src/connectors/index.ts +93 -0
- package/src/connectors/langsmith.ts +179 -0
- package/src/connectors/types.ts +180 -0
- package/src/cost-estimator.ts +146 -0
- package/src/costs.ts +347 -0
- package/src/counterfactuals.ts +516 -0
- package/src/enhancement-prompts.ts +118 -0
- package/src/envelopes.ts +814 -0
- package/src/format-normalizer.ts +1486 -0
- package/src/history.ts +400 -0
- package/src/html.ts +512 -0
- package/src/impact.ts +522 -0
- package/src/index.ts +83 -0
- package/src/insights.ts +341 -0
- package/src/joiner.ts +289 -0
- package/src/orchestrator.ts +1015 -0
- package/src/pdf.ts +110 -0
- package/src/prediction.ts +392 -0
- package/src/prompts/loader.ts +88 -0
- package/src/renderer.ts +1045 -0
- package/src/runid.ts +261 -0
- package/src/runtime.ts +450 -0
- package/src/scanner.ts +508 -0
- package/src/templates.ts +561 -0
- package/src/tools/index.ts +214 -0
- package/src/types.ts +873 -0
- package/src/version.ts +24 -0
- package/templates/context-accumulation.yaml +23 -0
- package/templates/cost-concentration.yaml +20 -0
- package/templates/dead-code.yaml +20 -0
- package/templates/latency-explainer.yaml +23 -0
- package/templates/optimizations/ab-testing-framework.yaml +74 -0
- package/templates/optimizations/api-gateway-optimization.yaml +81 -0
- package/templates/optimizations/api-model-routing-strategy.yaml +126 -0
- package/templates/optimizations/auto-scaling-optimization.yaml +85 -0
- package/templates/optimizations/batch-utilization-diagnostic.yaml +142 -0
- package/templates/optimizations/comprehensive-apm.yaml +76 -0
- package/templates/optimizations/context-window-optimization.yaml +91 -0
- package/templates/optimizations/cost-sensitive-batch-processing.yaml +77 -0
- package/templates/optimizations/distributed-training-optimization.yaml +77 -0
- package/templates/optimizations/document-analysis-edge.yaml +77 -0
- package/templates/optimizations/document-pipeline-optimization.yaml +78 -0
- package/templates/optimizations/domain-specific-distillation.yaml +78 -0
- package/templates/optimizations/error-handling-optimization.yaml +76 -0
- package/templates/optimizations/gptq-4bit-quantization.yaml +96 -0
- package/templates/optimizations/long-context-memory-management.yaml +78 -0
- package/templates/optimizations/max-tokens-optimization.yaml +76 -0
- package/templates/optimizations/memory-bandwidth-optimization.yaml +73 -0
- package/templates/optimizations/multi-framework-resilience.yaml +75 -0
- package/templates/optimizations/multi-tenant-optimization.yaml +75 -0
- package/templates/optimizations/prompt-caching-optimization.yaml +143 -0
- package/templates/optimizations/pytorch-to-onnx-migration.yaml +109 -0
- package/templates/optimizations/quality-monitoring.yaml +74 -0
- package/templates/optimizations/realtime-budget-controls.yaml +74 -0
- package/templates/optimizations/realtime-latency-optimization.yaml +74 -0
- package/templates/optimizations/sglang-concurrency-optimization.yaml +78 -0
- package/templates/optimizations/smart-model-routing.yaml +96 -0
- package/templates/optimizations/streaming-batch-selection.yaml +167 -0
- package/templates/optimizations/system-prompt-optimization.yaml +75 -0
- package/templates/optimizations/tensorrt-llm-performance.yaml +77 -0
- package/templates/optimizations/vllm-high-throughput-optimization.yaml +93 -0
- package/templates/optimizations/vllm-migration-memory-bound.yaml +78 -0
- package/templates/overpowered-extraction.yaml +32 -0
- package/templates/overpowered-model.yaml +31 -0
- package/templates/prompt-bloat.yaml +24 -0
- package/templates/retry-explosion.yaml +28 -0
- package/templates/schema/insight.schema.json +113 -0
- package/templates/schema/optimization.schema.json +180 -0
- package/templates/streaming-drift.yaml +30 -0
- package/templates/throughput-gap.yaml +21 -0
- package/templates/token-underutilization.yaml +28 -0
- package/templates/untested-fallback.yaml +21 -0
- package/tests/accuracy/drift-detection.test.ts +184 -0
- package/tests/accuracy/false-positives.test.ts +166 -0
- package/tests/accuracy/templates.test.ts +205 -0
- package/tests/action/commands.test.ts +125 -0
- package/tests/action/comments.test.ts +347 -0
- package/tests/cli.test.ts +203 -0
- package/tests/comparison.test.ts +309 -0
- package/tests/correlation-analyzer.test.ts +534 -0
- package/tests/counterfactuals.test.ts +347 -0
- package/tests/fixtures/events/missing-id.jsonl +1 -0
- package/tests/fixtures/events/missing-input.jsonl +1 -0
- package/tests/fixtures/events/missing-latency.jsonl +1 -0
- package/tests/fixtures/events/missing-model.jsonl +1 -0
- package/tests/fixtures/events/missing-output.jsonl +1 -0
- package/tests/fixtures/events/missing-provider.jsonl +1 -0
- package/tests/fixtures/events/missing-ts.jsonl +1 -0
- package/tests/fixtures/events/valid.csv +3 -0
- package/tests/fixtures/events/valid.json +1 -0
- package/tests/fixtures/events/valid.jsonl +2 -0
- package/tests/fixtures/events/with-callsite.jsonl +1 -0
- package/tests/fixtures/events/with-intent.jsonl +1 -0
- package/tests/fixtures/events/wrong-type.jsonl +1 -0
- package/tests/fixtures/repos/empty/.gitkeep +0 -0
- package/tests/fixtures/repos/hybrid-router/router.py +35 -0
- package/tests/fixtures/repos/saas-anthropic/agent.ts +27 -0
- package/tests/fixtures/repos/saas-openai/assistant.js +33 -0
- package/tests/fixtures/repos/saas-openai/client.py +26 -0
- package/tests/fixtures/repos/self-hosted-vllm/inference.py +22 -0
- package/tests/github-action.test.ts +292 -0
- package/tests/insights.test.ts +878 -0
- package/tests/joiner.test.ts +168 -0
- package/tests/performance/action-latency.test.ts +132 -0
- package/tests/performance/benchmark.test.ts +189 -0
- package/tests/performance/cli-latency.test.ts +102 -0
- package/tests/pr-comment.test.ts +313 -0
- package/tests/prediction.test.ts +296 -0
- package/tests/runtime-analyzer.test.ts +375 -0
- package/tests/runtime.test.ts +205 -0
- package/tests/scanner.test.ts +122 -0
- package/tests/template-conformance.test.ts +526 -0
- package/tests/unit/cost-calculator.test.ts +303 -0
- package/tests/unit/credits.test.ts +180 -0
- package/tests/unit/inference-map.test.ts +276 -0
- package/tests/unit/schema.test.ts +300 -0
- package/tsconfig.json +20 -0
- 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
|
+
}
|