@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,353 @@
1
+ /**
2
+ * CorrelationAnalyzerAgent - LLM-based correlation of static code and runtime telemetry
3
+ *
4
+ * From Autonomous Agent Architecture Patterns v0.2:
5
+ * - Subagent with fresh context window
6
+ * - XML-structured prompt from prompts/correlation-analyzer.yaml
7
+ * - Detects drift between code intent and runtime reality
8
+ * - Returns drift signals and alignment score
9
+ *
10
+ * Uses Claude Agent SDK (per TDD v1.9.3)
11
+ */
12
+
13
+ import { query } from '@anthropic-ai/claude-agent-sdk';
14
+ import type { SDKMessage } from '@anthropic-ai/claude-agent-sdk';
15
+ import { loadPrompt } from '../templates.js';
16
+ import type { Callsite, InferenceEvent, RuntimeSummary, Insight, DriftSignal, ImpactEstimate } from '../types.js';
17
+ import { createConstrainedRegistry, type ToolRegistry } from '../tools/index.js';
18
+ import type { BaseAgent, AgentOutput } from './index.js';
19
+
20
+ // =============================================================================
21
+ // TYPES
22
+ // =============================================================================
23
+
24
+ export interface CorrelationAnalyzerInput {
25
+ callsites: Callsite[];
26
+ events: InferenceEvent[];
27
+ runtimeSummary: RuntimeSummary;
28
+ }
29
+
30
+ export interface CorrelationAnalyzerOutput {
31
+ insights: Insight[];
32
+ driftSignals: DriftSignal[];
33
+ correlationSummary: {
34
+ totalCodeCallsites: number;
35
+ totalRuntimeModels: number;
36
+ matched: number;
37
+ codeOnly: number;
38
+ runtimeOnly: number;
39
+ mismatched: number;
40
+ };
41
+ alignmentScore: number; // 0.0 - 1.0
42
+ overallAssessment: string;
43
+ }
44
+
45
+ // LLM response shape (matches prompt output_format)
46
+ interface LLMCorrelationResult {
47
+ drift_signals: Array<{
48
+ type: 'codeOnly' | 'runtimeOnly' | 'modelMismatch' | 'patternMismatch' | 'providerMismatch';
49
+ severity: 'critical' | 'warning' | 'info';
50
+ code_location: string | null;
51
+ code_details: {
52
+ provider: string;
53
+ model: string;
54
+ patterns: Record<string, boolean>;
55
+ } | null;
56
+ runtime_details: {
57
+ provider: string;
58
+ model: string;
59
+ call_count: number;
60
+ patterns_observed: Record<string, boolean>;
61
+ } | null;
62
+ evidence: string;
63
+ explanation: string;
64
+ recommendation: string;
65
+ }>;
66
+ correlation_summary: {
67
+ total_code_callsites: number;
68
+ total_runtime_models: number;
69
+ matched: number;
70
+ code_only: number;
71
+ runtime_only: number;
72
+ mismatched: number;
73
+ };
74
+ alignment_score: number;
75
+ overall_assessment: string;
76
+ }
77
+
78
+ // =============================================================================
79
+ // HELPERS
80
+ // =============================================================================
81
+
82
+ /**
83
+ * Extract text content from Claude Agent SDK messages
84
+ */
85
+ function extractTextFromMessages(messages: SDKMessage[]): string {
86
+ let text = '';
87
+ for (const msg of messages) {
88
+ if (msg.type === 'assistant' && msg.message?.content) {
89
+ for (const block of msg.message.content) {
90
+ if (block.type === 'text') {
91
+ text += block.text;
92
+ }
93
+ }
94
+ }
95
+ }
96
+ return text;
97
+ }
98
+
99
+ function buildCorrelationContext(
100
+ callsites: Callsite[],
101
+ runtimeSummary: RuntimeSummary
102
+ ): string {
103
+ const lines: string[] = [];
104
+
105
+ // Static callsites
106
+ lines.push('=== STATIC CALLSITES (from code analysis) ===');
107
+ if (callsites.length === 0) {
108
+ lines.push('No callsites detected in code.');
109
+ } else {
110
+ for (const cs of callsites) {
111
+ lines.push(`${cs.file}:${cs.line}`);
112
+ lines.push(` provider: ${cs.provider || 'unknown'}`);
113
+ lines.push(` model: ${cs.model || 'unknown'}`);
114
+ lines.push(` framework: ${cs.framework || 'none'}`);
115
+ lines.push(` patterns: ${JSON.stringify(cs.patterns)}`);
116
+ lines.push(` confidence: ${cs.confidence}`);
117
+ }
118
+ }
119
+ lines.push('');
120
+
121
+ // Runtime summary
122
+ lines.push('=== RUNTIME SUMMARY (from telemetry) ===');
123
+ lines.push(`Total events: ${runtimeSummary.totalEvents}`);
124
+ lines.push('');
125
+
126
+ lines.push('--- By Provider ---');
127
+ for (const [provider, stats] of Object.entries(runtimeSummary.byProvider)) {
128
+ lines.push(`${provider}: ${stats.calls} calls, ${stats.tokens_in + stats.tokens_out} tokens`);
129
+ }
130
+ lines.push('');
131
+
132
+ lines.push('--- By Model ---');
133
+ for (const [model, stats] of Object.entries(runtimeSummary.byModel)) {
134
+ lines.push(`${model}: ${stats.calls} calls`);
135
+ lines.push(` tokens: in=${stats.tokens_in}, out=${stats.tokens_out}`);
136
+ lines.push(` latency: p50=${stats.latency_p50}ms, p95=${stats.latency_p95}ms`);
137
+ }
138
+
139
+ return lines.join('\n');
140
+ }
141
+
142
+ // Pre-compute basic correlations for fallback
143
+ function computeBasicCorrelation(
144
+ callsites: Callsite[],
145
+ runtimeSummary: RuntimeSummary
146
+ ): CorrelationAnalyzerOutput {
147
+ const codeProviderModels = new Set<string>();
148
+ const runtimeProviderModels = new Set<string>();
149
+
150
+ // Collect code provider:model pairs
151
+ for (const cs of callsites) {
152
+ if (cs.provider && cs.model) {
153
+ codeProviderModels.add(`${cs.provider}:${cs.model}`);
154
+ }
155
+ }
156
+
157
+ // Collect runtime provider:model pairs
158
+ for (const model of Object.keys(runtimeSummary.byModel)) {
159
+ // Try to infer provider from model name
160
+ let provider = 'unknown';
161
+ if (model.includes('gpt') || model.includes('text-embedding')) provider = 'openai';
162
+ else if (model.includes('claude')) provider = 'anthropic';
163
+ else if (model.includes('gemini')) provider = 'google';
164
+
165
+ runtimeProviderModels.add(`${provider}:${model}`);
166
+ }
167
+
168
+ // Calculate overlaps
169
+ const matched = [...codeProviderModels].filter(pm => runtimeProviderModels.has(pm)).length;
170
+ const codeOnly = codeProviderModels.size - matched;
171
+ const runtimeOnly = runtimeProviderModels.size - matched;
172
+ const mismatched = 0; // Would need more sophisticated matching
173
+
174
+ // Alignment score
175
+ const total = codeProviderModels.size + runtimeProviderModels.size;
176
+ const alignmentScore = total > 0 ? (matched * 2) / total : 1.0;
177
+
178
+ // Build drift signals
179
+ const driftSignals: DriftSignal[] = [];
180
+
181
+ // Code-only entries
182
+ for (const pm of codeProviderModels) {
183
+ if (!runtimeProviderModels.has(pm)) {
184
+ const [provider, model] = pm.split(':');
185
+ const cs = callsites.find(c => c.provider === provider && c.model === model);
186
+ driftSignals.push({
187
+ type: 'codeOnly',
188
+ provider,
189
+ model,
190
+ callsiteId: cs?.id,
191
+ message: `Model ${model} found in code but not in runtime telemetry`,
192
+ });
193
+ }
194
+ }
195
+
196
+ // Runtime-only entries
197
+ for (const pm of runtimeProviderModels) {
198
+ if (!codeProviderModels.has(pm)) {
199
+ const [provider, model] = pm.split(':');
200
+ driftSignals.push({
201
+ type: 'runtimeOnly',
202
+ provider,
203
+ model,
204
+ message: `Model ${model} found in runtime but not in code analysis`,
205
+ });
206
+ }
207
+ }
208
+
209
+ return {
210
+ insights: [],
211
+ driftSignals,
212
+ correlationSummary: {
213
+ totalCodeCallsites: callsites.length,
214
+ totalRuntimeModels: Object.keys(runtimeSummary.byModel).length,
215
+ matched,
216
+ codeOnly,
217
+ runtimeOnly,
218
+ mismatched,
219
+ },
220
+ alignmentScore,
221
+ overallAssessment: alignmentScore >= 0.8
222
+ ? 'Good alignment between code and runtime.'
223
+ : alignmentScore >= 0.5
224
+ ? 'Moderate drift detected. Review unmatched entries.'
225
+ : 'Significant drift. Code and runtime show different behavior.',
226
+ };
227
+ }
228
+
229
+ // =============================================================================
230
+ // AGENT IMPLEMENTATION
231
+ // =============================================================================
232
+
233
+ export const CorrelationAnalyzerAgent: BaseAgent<CorrelationAnalyzerInput, CorrelationAnalyzerOutput> = {
234
+ name: 'correlation-analyzer',
235
+ description: 'Correlate static code analysis with runtime telemetry to detect drift',
236
+ tools: createConstrainedRegistry(),
237
+
238
+ async execute(input: CorrelationAnalyzerInput): Promise<AgentOutput<CorrelationAnalyzerOutput>> {
239
+ const toolsUsed: string[] = ['llm'];
240
+
241
+ // Load prompt from YAML
242
+ const promptConfig = loadPrompt('correlation-analyzer');
243
+ if (!promptConfig) {
244
+ throw new Error('[correlation-analyzer] Prompt not found: prompts/correlation-analyzer.yaml');
245
+ }
246
+
247
+ // Build correlation context
248
+ const correlationContext = buildCorrelationContext(input.callsites, input.runtimeSummary);
249
+
250
+ // Check for API key
251
+ if (!process.env.ANTHROPIC_API_KEY) {
252
+ console.warn('[correlation-analyzer] No ANTHROPIC_API_KEY, returning basic correlation');
253
+ return {
254
+ result: computeBasicCorrelation(input.callsites, input.runtimeSummary),
255
+ toolsUsed: [],
256
+ };
257
+ }
258
+
259
+ try {
260
+ // Use Claude Agent SDK query() function
261
+ const agentQuery = query({
262
+ prompt: `${promptConfig.prompt}\n\n${correlationContext}`,
263
+ options: {
264
+ model: 'claude-sonnet-4-20250514',
265
+ tools: [],
266
+ permissionMode: 'plan',
267
+ cwd: process.cwd(),
268
+ },
269
+ });
270
+
271
+ // Collect all messages from the async generator
272
+ const messages: SDKMessage[] = [];
273
+ for await (const message of agentQuery) {
274
+ messages.push(message);
275
+ }
276
+
277
+ // Extract JSON from response
278
+ const text = extractTextFromMessages(messages);
279
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
280
+
281
+ if (!jsonMatch) {
282
+ console.warn('[correlation-analyzer] No JSON in LLM response, using fallback');
283
+ return {
284
+ result: computeBasicCorrelation(input.callsites, input.runtimeSummary),
285
+ toolsUsed,
286
+ };
287
+ }
288
+
289
+ const parsed = JSON.parse(jsonMatch[0]) as LLMCorrelationResult;
290
+
291
+ // Convert drift signals to our format
292
+ // Map LLM types to DriftSignal types
293
+ const mapDriftType = (t: string): DriftSignal['type'] => {
294
+ if (t === 'codeOnly') return 'codeOnly';
295
+ if (t === 'runtimeOnly') return 'runtimeOnly';
296
+ if (t === 'patternMismatch' || t === 'patternDrift') return 'patternDrift';
297
+ // modelMismatch, providerMismatch -> mismatch
298
+ return 'mismatch';
299
+ };
300
+
301
+ const driftSignals: DriftSignal[] = (parsed.drift_signals || []).map(ds => ({
302
+ type: mapDriftType(ds.type),
303
+ provider: ds.code_details?.provider || ds.runtime_details?.provider,
304
+ model: ds.code_details?.model || ds.runtime_details?.model,
305
+ callsiteId: ds.code_location ? ds.code_location.split(':')[0] : undefined,
306
+ message: ds.evidence,
307
+ }));
308
+
309
+ // Convert to insights
310
+ const insights: Insight[] = (parsed.drift_signals || []).map((ds, idx) => ({
311
+ id: `correlation_${Date.now()}_${idx}`,
312
+ severity: ds.severity,
313
+ category: 'drift' as const,
314
+ headline: `${ds.type}: ${ds.evidence.substring(0, 50)}...`,
315
+ evidence: ds.evidence,
316
+ location: ds.code_location || undefined,
317
+ recommendation: ds.recommendation,
318
+ source: 'llm' as const,
319
+ impact: {
320
+ layer: 'application' as const,
321
+ impactType: 'cost' as const,
322
+ estimatedImpactPercent: ds.severity === 'critical' ? 30 : ds.severity === 'warning' ? 15 : 5,
323
+ effort: 'low' as const,
324
+ confidence: 0.7,
325
+ } as ImpactEstimate,
326
+ }));
327
+
328
+ return {
329
+ result: {
330
+ insights,
331
+ driftSignals,
332
+ correlationSummary: {
333
+ totalCodeCallsites: parsed.correlation_summary?.total_code_callsites || input.callsites.length,
334
+ totalRuntimeModels: parsed.correlation_summary?.total_runtime_models || Object.keys(input.runtimeSummary.byModel).length,
335
+ matched: parsed.correlation_summary?.matched || 0,
336
+ codeOnly: parsed.correlation_summary?.code_only || 0,
337
+ runtimeOnly: parsed.correlation_summary?.runtime_only || 0,
338
+ mismatched: parsed.correlation_summary?.mismatched || 0,
339
+ },
340
+ alignmentScore: parsed.alignment_score || 0.5,
341
+ overallAssessment: parsed.overall_assessment || 'Analysis completed.',
342
+ },
343
+ toolsUsed,
344
+ };
345
+ } catch (error) {
346
+ console.warn('[correlation-analyzer] LLM analysis failed:', error);
347
+ return {
348
+ result: computeBasicCorrelation(input.callsites, input.runtimeSummary),
349
+ toolsUsed,
350
+ };
351
+ }
352
+ },
353
+ };
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Specialized Agents for PeakInfer
3
+ *
4
+ * Architecture v2.0 (Prompt-Based Analysis):
5
+ * - StaticAnalysisOrchestrator: Prompt-based unified analysis (synced from peakinfer-site)
6
+ * - RuntimeAnalyzerAgent: LLM-based runtime telemetry analysis
7
+ * - CorrelationAnalyzerAgent: LLM-based code-runtime drift detection
8
+ *
9
+ * Legacy agents (still available for compatibility):
10
+ * - DiscoveryAgent: Scan and discover inference points
11
+ * - AnalyzerAgent: Semantic classification with tool-limited analysis
12
+ * - JoinerAgent: Correlate static + runtime truth
13
+ * - InsightAgent: Generate findings from templates
14
+ */
15
+
16
+ import { z } from 'zod';
17
+ import { createConstrainedRegistry, type ToolRegistry } from '../tools/index.js';
18
+ import { scan } from '../scanner.js';
19
+ import { analyze as analyzeCallsites } from '../analyzer.js';
20
+ import { join as joinData } from '../joiner.js';
21
+ import { evaluate } from '../insights.js';
22
+ import { ENVELOPES } from '../envelopes.js';
23
+ import type { ScanResult, Callsite, InferenceEvent, JoinedOutput, Insight, InsightTemplate } from '../types.js';
24
+
25
+ // Re-export agents
26
+ export { RuntimeAnalyzerAgent, type RuntimeAnalyzerInput, type RuntimeAnalyzerOutput } from './runtime-analyzer.js';
27
+ export { CorrelationAnalyzerAgent, type CorrelationAnalyzerInput, type CorrelationAnalyzerOutput } from './correlation-analyzer.js';
28
+
29
+ // Static analysis orchestrator (prompt-based, synced from peakinfer-site)
30
+ export { StaticAnalysisOrchestrator, runStaticAnalysis, type StaticAnalysisInput, type StaticAnalysisOutput, type PerformanceProfile, type AnalysisProgressCallback } from '../orchestrator.js';
31
+
32
+ // Re-export analysis types
33
+ export type {
34
+ InferencePoint,
35
+ CostProfile,
36
+ LatencyProfile,
37
+ ThroughputProfile,
38
+ ReliabilityProfile,
39
+ Insight,
40
+ Issue,
41
+ } from '../analysis-types.js';
42
+
43
+ // =============================================================================
44
+ // AGENT INTERFACE (from Patterns v0.1 Section 4)
45
+ // =============================================================================
46
+
47
+ export interface AgentInput {
48
+ description: string;
49
+ context?: Record<string, unknown>;
50
+ }
51
+
52
+ export interface AgentOutput<T> {
53
+ result: T;
54
+ toolsUsed: string[];
55
+ contextPointer?: string;
56
+ }
57
+
58
+ export interface BaseAgent<TInput, TOutput> {
59
+ name: string;
60
+ description: string;
61
+ tools: ToolRegistry;
62
+ execute: (input: TInput) => Promise<AgentOutput<TOutput>>;
63
+ }
64
+
65
+ // =============================================================================
66
+ // CONTEXT POINTER (from Patterns v0.1 Section 3.4)
67
+ // =============================================================================
68
+
69
+ export interface ContextPointer {
70
+ id: string;
71
+ filepath: string;
72
+ agentName: string;
73
+ description: string;
74
+ sizeBytes: number;
75
+ createdAt: string;
76
+ }
77
+
78
+ // =============================================================================
79
+ // DISCOVERY AGENT - Scan and discover inference points
80
+ // =============================================================================
81
+
82
+ export interface DiscoveryInput {
83
+ root: string;
84
+ }
85
+
86
+ export interface DiscoveryOutput {
87
+ scanResult: ScanResult;
88
+ candidateFiles: string[];
89
+ }
90
+
91
+ export const DiscoveryAgent: BaseAgent<DiscoveryInput, DiscoveryOutput> = {
92
+ name: 'discovery',
93
+ description: 'Scan repository and discover potential inference points',
94
+ tools: createConstrainedRegistry(),
95
+
96
+ async execute(input: DiscoveryInput): Promise<AgentOutput<DiscoveryOutput>> {
97
+ const toolsUsed: string[] = [];
98
+
99
+ // Use constrained tools: Glob to find files
100
+ const globResult = await this.tools.execute('glob', {
101
+ pattern: '**/*.{ts,js,py,go,java}',
102
+ cwd: input.root,
103
+ ignore: ['**/node_modules/**', '**/dist/**', '**/.git/**', '**/__pycache__/**'],
104
+ }) as { files: string[]; count: number };
105
+ toolsUsed.push('glob');
106
+
107
+ // Wrap existing scanner for full analysis
108
+ const scanResult = await scan(input.root);
109
+
110
+ // Identify candidate files likely containing inference
111
+ const inferencePatterns = /openai|anthropic|llm|chat|completion|embedding|claude|gpt/i;
112
+ const candidateFiles = globResult.files.filter(f => inferencePatterns.test(f));
113
+
114
+ return {
115
+ result: { scanResult, candidateFiles },
116
+ toolsUsed,
117
+ };
118
+ },
119
+ };
120
+
121
+ // =============================================================================
122
+ // ANALYZER AGENT - Semantic classification
123
+ // =============================================================================
124
+
125
+ export interface AnalyzerInput {
126
+ scanResult: ScanResult;
127
+ onProgress?: (data: { percent: number; currentFile?: string }) => void;
128
+ }
129
+
130
+ export interface AnalyzerOutput {
131
+ callsites: Callsite[];
132
+ llmInsights: unknown[];
133
+ }
134
+
135
+ export const AnalyzerAgent: BaseAgent<AnalyzerInput, AnalyzerOutput> = {
136
+ name: 'analyzer',
137
+ description: 'Analyze code and classify inference patterns',
138
+ tools: createConstrainedRegistry(),
139
+
140
+ async execute(input: AnalyzerInput): Promise<AgentOutput<AnalyzerOutput>> {
141
+ const toolsUsed: string[] = ['read']; // Uses read internally
142
+
143
+ // Wrap existing analyzer (already uses LLM)
144
+ // Pass through onProgress callback for visual progress bar during analysis
145
+ const result = await analyzeCallsites(input.scanResult, {
146
+ onProgress: input.onProgress,
147
+ });
148
+
149
+ return {
150
+ result: {
151
+ callsites: result.callsites,
152
+ llmInsights: result.insights,
153
+ },
154
+ toolsUsed,
155
+ };
156
+ },
157
+ };
158
+
159
+ // =============================================================================
160
+ // JOINER AGENT - Correlate static + runtime
161
+ // =============================================================================
162
+
163
+ export interface JoinerInput {
164
+ callsites: Callsite[];
165
+ events: InferenceEvent[];
166
+ }
167
+
168
+ export interface JoinerOutput {
169
+ joined: JoinedOutput;
170
+ }
171
+
172
+ export const JoinerAgent: BaseAgent<JoinerInput, JoinerOutput> = {
173
+ name: 'joiner',
174
+ description: 'Correlate static callsites with runtime events',
175
+ tools: createConstrainedRegistry(),
176
+
177
+ async execute(input: JoinerInput): Promise<AgentOutput<JoinerOutput>> {
178
+ // Wrap existing joiner
179
+ const joined = joinData(input.callsites, input.events);
180
+
181
+ return {
182
+ result: { joined },
183
+ toolsUsed: [],
184
+ };
185
+ },
186
+ };
187
+
188
+ // =============================================================================
189
+ // INSIGHT AGENT - Generate findings from templates
190
+ // =============================================================================
191
+
192
+ export interface InsightInput {
193
+ data: JoinedOutput | { callsites: Callsite[] };
194
+ templates: InsightTemplate[];
195
+ }
196
+
197
+ export interface InsightOutput {
198
+ insights: Insight[];
199
+ }
200
+
201
+ export const InsightAgent: BaseAgent<InsightInput, InsightOutput> = {
202
+ name: 'insight',
203
+ description: 'Evaluate templates and generate performance insights',
204
+ tools: createConstrainedRegistry(),
205
+
206
+ async execute(input: InsightInput): Promise<AgentOutput<InsightOutput>> {
207
+ // Wrap existing insight evaluator
208
+ const insights = evaluate(input.data, input.templates, ENVELOPES);
209
+
210
+ return {
211
+ result: { insights },
212
+ toolsUsed: [],
213
+ };
214
+ },
215
+ };
216
+
217
+ // =============================================================================
218
+ // AGENT REGISTRY
219
+ // =============================================================================
220
+
221
+ // Import new agents for registry
222
+ import { RuntimeAnalyzerAgent } from './runtime-analyzer.js';
223
+ import { CorrelationAnalyzerAgent } from './correlation-analyzer.js';
224
+
225
+ export const AGENTS = {
226
+ discovery: DiscoveryAgent,
227
+ analyzer: AnalyzerAgent,
228
+ joiner: JoinerAgent,
229
+ insight: InsightAgent,
230
+ // New LLM-based agents (Patterns v0.2)
231
+ runtimeAnalyzer: RuntimeAnalyzerAgent,
232
+ correlationAnalyzer: CorrelationAnalyzerAgent,
233
+ } as const;
234
+
235
+ export type AgentName = keyof typeof AGENTS;