stepproof 0.2.22 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/dist/adapters/anthropic.d.ts +3 -2
  2. package/dist/adapters/anthropic.d.ts.map +1 -1
  3. package/dist/adapters/anthropic.js +27 -5
  4. package/dist/adapters/anthropic.js.map +1 -1
  5. package/dist/adapters/base.d.ts +14 -1
  6. package/dist/adapters/base.d.ts.map +1 -1
  7. package/dist/adapters/gemini.d.ts +9 -0
  8. package/dist/adapters/gemini.d.ts.map +1 -0
  9. package/dist/adapters/gemini.js +80 -0
  10. package/dist/adapters/gemini.js.map +1 -0
  11. package/dist/adapters/index.d.ts.map +1 -1
  12. package/dist/adapters/index.js +7 -1
  13. package/dist/adapters/index.js.map +1 -1
  14. package/dist/adapters/ollama.d.ts +9 -0
  15. package/dist/adapters/ollama.d.ts.map +1 -0
  16. package/dist/adapters/ollama.js +61 -0
  17. package/dist/adapters/ollama.js.map +1 -0
  18. package/dist/adapters/openai.d.ts +3 -2
  19. package/dist/adapters/openai.d.ts.map +1 -1
  20. package/dist/adapters/openai.js +16 -5
  21. package/dist/adapters/openai.js.map +1 -1
  22. package/dist/assertions/engine.d.ts +6 -1
  23. package/dist/assertions/engine.d.ts.map +1 -1
  24. package/dist/assertions/engine.js +176 -11
  25. package/dist/assertions/engine.js.map +1 -1
  26. package/dist/baseline.d.ts +23 -0
  27. package/dist/baseline.d.ts.map +1 -0
  28. package/dist/baseline.js +98 -0
  29. package/dist/baseline.js.map +1 -0
  30. package/dist/cache.d.ts +5 -0
  31. package/dist/cache.d.ts.map +1 -0
  32. package/dist/cache.js +71 -0
  33. package/dist/cache.js.map +1 -0
  34. package/dist/cli.js +283 -18
  35. package/dist/cli.js.map +1 -1
  36. package/dist/commands/compare.d.ts +43 -0
  37. package/dist/commands/compare.d.ts.map +1 -0
  38. package/dist/commands/compare.js +75 -0
  39. package/dist/commands/compare.js.map +1 -0
  40. package/dist/commands/diff.d.ts +2 -0
  41. package/dist/commands/diff.d.ts.map +1 -0
  42. package/dist/commands/diff.js +252 -0
  43. package/dist/commands/diff.js.map +1 -0
  44. package/dist/commands/history.d.ts +2 -0
  45. package/dist/commands/history.d.ts.map +1 -0
  46. package/dist/commands/history.js +46 -0
  47. package/dist/commands/history.js.map +1 -0
  48. package/dist/commands/results-store.d.ts +15 -0
  49. package/dist/commands/results-store.d.ts.map +1 -0
  50. package/dist/commands/results-store.js +77 -0
  51. package/dist/commands/results-store.js.map +1 -0
  52. package/dist/commands/view.d.ts +2 -0
  53. package/dist/commands/view.d.ts.map +1 -0
  54. package/dist/commands/view.js +51 -0
  55. package/dist/commands/view.js.map +1 -0
  56. package/dist/commands/watch.d.ts +7 -0
  57. package/dist/commands/watch.d.ts.map +1 -0
  58. package/dist/commands/watch.js +84 -0
  59. package/dist/commands/watch.js.map +1 -0
  60. package/dist/core/scenario-parser.d.ts.map +1 -1
  61. package/dist/core/scenario-parser.js +47 -5
  62. package/dist/core/scenario-parser.js.map +1 -1
  63. package/dist/core/scenario-runner.d.ts +12 -0
  64. package/dist/core/scenario-runner.d.ts.map +1 -1
  65. package/dist/core/scenario-runner.js +372 -41
  66. package/dist/core/scenario-runner.js.map +1 -1
  67. package/dist/core/types.d.ts +63 -9
  68. package/dist/core/types.d.ts.map +1 -1
  69. package/dist/dataset.d.ts +6 -0
  70. package/dist/dataset.d.ts.map +1 -0
  71. package/dist/dataset.js +108 -0
  72. package/dist/dataset.js.map +1 -0
  73. package/dist/reporters/github-comment.d.ts +8 -0
  74. package/dist/reporters/github-comment.d.ts.map +1 -0
  75. package/dist/reporters/github-comment.js +114 -0
  76. package/dist/reporters/github-comment.js.map +1 -0
  77. package/dist/reporters/html-reporter.d.ts +3 -0
  78. package/dist/reporters/html-reporter.d.ts.map +1 -0
  79. package/dist/reporters/html-reporter.js +152 -0
  80. package/dist/reporters/html-reporter.js.map +1 -0
  81. package/dist/reporters/terminal-reporter.d.ts +10 -1
  82. package/dist/reporters/terminal-reporter.d.ts.map +1 -1
  83. package/dist/reporters/terminal-reporter.js +139 -8
  84. package/dist/reporters/terminal-reporter.js.map +1 -1
  85. package/package.json +2 -1
@@ -1,8 +1,9 @@
1
- import type { ProviderAdapter } from './base.js';
1
+ import type { AdapterResponse, ChatMessage, ProviderAdapter } from './base.js';
2
2
  export declare class AnthropicAdapter implements ProviderAdapter {
3
3
  private client;
4
4
  private model;
5
5
  constructor(model: string);
6
- call(prompt: string, system?: string): Promise<string>;
6
+ call(prompt: string, system?: string): Promise<AdapterResponse>;
7
+ chat(messages: ChatMessage[], system?: string): Promise<AdapterResponse>;
7
8
  }
8
9
  //# sourceMappingURL=anthropic.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAsBjD,qBAAa,gBAAiB,YAAW,eAAe;IACtD,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAQnB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAiB7D"}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAsB/E,qBAAa,gBAAiB,YAAW,eAAe;IACtD,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAQnB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAI/D,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAoC/E"}
@@ -30,17 +30,39 @@ export class AnthropicAdapter {
30
30
  this.client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
31
31
  }
32
32
  async call(prompt, system) {
33
+ return this.chat([{ role: 'user', content: prompt }], system);
34
+ }
35
+ async chat(messages, system) {
36
+ // Anthropic API requires alternating user/assistant messages.
37
+ // System messages are passed via the top-level system param.
38
+ const apiMessages = [];
39
+ for (const msg of messages) {
40
+ if (msg.role === 'system') {
41
+ // Fold into system param — Anthropic doesn't support system in messages array
42
+ system = system ? `${system}\n\n${msg.content}` : msg.content;
43
+ }
44
+ else {
45
+ apiMessages.push({ role: msg.role, content: msg.content });
46
+ }
47
+ }
48
+ const startMs = Date.now();
33
49
  const response = await withRetry(() => this.client.messages.create({
34
50
  model: this.model,
35
51
  max_tokens: 1024,
36
52
  ...(system && { system }),
37
- messages: [{ role: 'user', content: prompt }],
53
+ messages: apiMessages,
38
54
  }));
55
+ const durationMs = Date.now() - startMs;
39
56
  const content = response.content[0];
40
- if (content?.type === 'text') {
41
- return content.text;
42
- }
43
- return '';
57
+ const text = content?.type === 'text' ? content.text : '';
58
+ return {
59
+ text,
60
+ usage: {
61
+ inputTokens: response.usage.input_tokens,
62
+ outputTokens: response.usage.output_tokens,
63
+ },
64
+ durationMs,
65
+ };
44
66
  }
45
67
  }
46
68
  //# sourceMappingURL=anthropic.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAG1C,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,KAAK,UAAU,SAAS,CAAI,EAAoB;IAC9C,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,SAAS,GAAG,GAAG,CAAC;YAChB,MAAM,MAAM,GAAI,GAA2B,CAAC,MAAM,CAAC;YACnD,uDAAuD;YACvD,IAAI,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;gBAAE,MAAM,GAAG,CAAC;YAC5D,MAAM,KAAK,GAAG,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACnD,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,gBAAgB;IACnB,MAAM,CAAY;IAClB,KAAK,CAAS;IAEtB,YAAY,KAAa;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAe;QACxC,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC1B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,UAAU,EAAE,IAAI;YAChB,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,CAAC;YACzB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;SAC9C,CAAC,CACH,CAAC;QAEF,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,OAAO,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;YAC7B,OAAO,OAAO,CAAC,IAAI,CAAC;QACtB,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC;CACF"}
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/adapters/anthropic.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,17 @@
1
+ export interface AdapterResponse {
2
+ text: string;
3
+ usage?: {
4
+ inputTokens: number;
5
+ outputTokens: number;
6
+ };
7
+ durationMs: number;
8
+ }
9
+ export interface ChatMessage {
10
+ role: 'user' | 'assistant' | 'system';
11
+ content: string;
12
+ }
1
13
  export interface ProviderAdapter {
2
- call(prompt: string, system?: string): Promise<string>;
14
+ call(prompt: string, system?: string): Promise<AdapterResponse>;
15
+ chat(messages: ChatMessage[], system?: string): Promise<AdapterResponse>;
3
16
  }
4
17
  //# sourceMappingURL=base.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACxD"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE;QACN,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAChE,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC1E"}
@@ -0,0 +1,9 @@
1
+ import type { AdapterResponse, ChatMessage, ProviderAdapter } from './base.js';
2
+ export declare class GeminiAdapter implements ProviderAdapter {
3
+ private client;
4
+ private model;
5
+ constructor(model: string);
6
+ call(prompt: string, system?: string): Promise<AdapterResponse>;
7
+ chat(messages: ChatMessage[], system?: string): Promise<AdapterResponse>;
8
+ }
9
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAsB/E,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAWnB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAI/D,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAmD/E"}
@@ -0,0 +1,80 @@
1
+ import { GoogleGenerativeAI } from '@google/generative-ai';
2
+ const MAX_RETRIES = 3;
3
+ const BASE_DELAY_MS = 1000;
4
+ async function withRetry(fn) {
5
+ let lastError;
6
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
7
+ try {
8
+ return await fn();
9
+ }
10
+ catch (err) {
11
+ lastError = err;
12
+ const status = err.status;
13
+ // Only retry on rate limit (429) or server error (5xx)
14
+ if (status !== 429 && !(status && status >= 500))
15
+ throw err;
16
+ const delay = BASE_DELAY_MS * Math.pow(2, attempt);
17
+ await new Promise((res) => setTimeout(res, delay));
18
+ }
19
+ }
20
+ throw lastError;
21
+ }
22
+ export class GeminiAdapter {
23
+ client;
24
+ model;
25
+ constructor(model) {
26
+ this.model = model;
27
+ const apiKey = process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;
28
+ if (!apiKey) {
29
+ throw new Error('GOOGLE_API_KEY or GEMINI_API_KEY environment variable is required for Gemini provider');
30
+ }
31
+ this.client = new GoogleGenerativeAI(apiKey);
32
+ }
33
+ async call(prompt, system) {
34
+ return this.chat([{ role: 'user', content: prompt }], system);
35
+ }
36
+ async chat(messages, system) {
37
+ // Fold any system-role messages into the system instruction
38
+ let effectiveSystem = system;
39
+ for (const msg of messages) {
40
+ if (msg.role === 'system') {
41
+ effectiveSystem = effectiveSystem ? `${effectiveSystem}\n\n${msg.content}` : msg.content;
42
+ }
43
+ }
44
+ const generativeModel = this.client.getGenerativeModel({
45
+ model: this.model,
46
+ ...(effectiveSystem && { systemInstruction: effectiveSystem }),
47
+ });
48
+ // Gemini uses "user" and "model" roles in history, final message sent via sendMessage
49
+ const nonSystemMessages = messages.filter(m => m.role !== 'system');
50
+ // If only one user message, use simple generateContent
51
+ if (nonSystemMessages.length === 1 && nonSystemMessages[0].role === 'user') {
52
+ const startMs = Date.now();
53
+ const result = await withRetry(() => generativeModel.generateContent(nonSystemMessages[0].content));
54
+ const durationMs = Date.now() - startMs;
55
+ const text = result.response.text();
56
+ const usageMetadata = result.response.usageMetadata;
57
+ const usage = usageMetadata
58
+ ? { inputTokens: usageMetadata.promptTokenCount ?? 0, outputTokens: usageMetadata.candidatesTokenCount ?? 0 }
59
+ : undefined;
60
+ return { text, usage, durationMs };
61
+ }
62
+ // Multi-turn: use startChat with history, send the last message
63
+ const history = nonSystemMessages.slice(0, -1).map(m => ({
64
+ role: m.role === 'assistant' ? 'model' : 'user',
65
+ parts: [{ text: m.content }],
66
+ }));
67
+ const lastMsg = nonSystemMessages[nonSystemMessages.length - 1];
68
+ const chat = generativeModel.startChat({ history });
69
+ const startMs = Date.now();
70
+ const result = await withRetry(() => chat.sendMessage(lastMsg.content));
71
+ const durationMs = Date.now() - startMs;
72
+ const text = result.response.text();
73
+ const usageMetadata = result.response.usageMetadata;
74
+ const usage = usageMetadata
75
+ ? { inputTokens: usageMetadata.promptTokenCount ?? 0, outputTokens: usageMetadata.candidatesTokenCount ?? 0 }
76
+ : undefined;
77
+ return { text, usage, durationMs };
78
+ }
79
+ }
80
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/adapters/gemini.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAS3E;AAED,YAAY,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAa3E;AAED,YAAY,EAAE,eAAe,EAAE,CAAC"}
@@ -1,13 +1,19 @@
1
1
  import { OpenAIAdapter } from './openai.js';
2
2
  import { AnthropicAdapter } from './anthropic.js';
3
+ import { GeminiAdapter } from './gemini.js';
4
+ import { OllamaAdapter } from './ollama.js';
3
5
  export function getAdapter(provider, model) {
4
6
  switch (provider) {
5
7
  case 'openai':
6
8
  return new OpenAIAdapter(model);
7
9
  case 'anthropic':
8
10
  return new AnthropicAdapter(model);
11
+ case 'gemini':
12
+ return new GeminiAdapter(model);
13
+ case 'ollama':
14
+ return new OllamaAdapter(model);
9
15
  default:
10
- throw new Error(`Unknown provider: "${provider}". Supported providers: openai, anthropic`);
16
+ throw new Error(`Unknown provider: "${provider}". Supported providers: openai, anthropic, gemini, ollama`);
11
17
  }
12
18
  }
13
19
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,KAAa;IACxD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,KAAK,WAAW;YACd,OAAO,IAAI,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACrC;YACE,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,2CAA2C,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,UAAU,UAAU,CAAC,QAAgB,EAAE,KAAa;IACxD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,KAAK,WAAW;YACd,OAAO,IAAI,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACrC,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC,KAAK,QAAQ;YACX,OAAO,IAAI,aAAa,CAAC,KAAK,CAAC,CAAC;QAClC;YACE,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,2DAA2D,CAAC,CAAC;IAC/G,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { AdapterResponse, ChatMessage, ProviderAdapter } from './base.js';
2
+ export declare class OllamaAdapter implements ProviderAdapter {
3
+ private baseUrl;
4
+ private model;
5
+ constructor(model: string);
6
+ call(prompt: string, system?: string): Promise<AdapterResponse>;
7
+ chat(messages: ChatMessage[], system?: string): Promise<AdapterResponse>;
8
+ }
9
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../src/adapters/ollama.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAkC/E,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAKnB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAI/D,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAuC/E"}
@@ -0,0 +1,61 @@
1
+ const MAX_RETRIES = 3;
2
+ const BASE_DELAY_MS = 1000;
3
+ async function withRetry(fn) {
4
+ let lastError;
5
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
6
+ try {
7
+ return await fn();
8
+ }
9
+ catch (err) {
10
+ lastError = err;
11
+ const status = err.status;
12
+ // Only retry on rate limit (429) or server error (5xx)
13
+ if (status !== 429 && !(status && status >= 500))
14
+ throw err;
15
+ const delay = BASE_DELAY_MS * Math.pow(2, attempt);
16
+ await new Promise((res) => setTimeout(res, delay));
17
+ }
18
+ }
19
+ throw lastError;
20
+ }
21
+ export class OllamaAdapter {
22
+ baseUrl;
23
+ model;
24
+ constructor(model) {
25
+ this.model = model;
26
+ this.baseUrl = process.env.OLLAMA_BASE_URL ?? 'http://localhost:11434';
27
+ }
28
+ async call(prompt, system) {
29
+ return this.chat([{ role: 'user', content: prompt }], system);
30
+ }
31
+ async chat(messages, system) {
32
+ // Build Ollama chat API messages array
33
+ const apiMessages = [];
34
+ if (system) {
35
+ apiMessages.push({ role: 'system', content: system });
36
+ }
37
+ for (const msg of messages) {
38
+ apiMessages.push({ role: msg.role, content: msg.content });
39
+ }
40
+ const startMs = Date.now();
41
+ const response = await withRetry(() => fetch(`${this.baseUrl}/api/chat`, {
42
+ method: 'POST',
43
+ headers: { 'Content-Type': 'application/json' },
44
+ body: JSON.stringify({
45
+ model: this.model,
46
+ messages: apiMessages,
47
+ stream: false,
48
+ }),
49
+ }));
50
+ const durationMs = Date.now() - startMs;
51
+ if (!response.ok) {
52
+ throw Object.assign(new Error(`Ollama request failed: ${response.status} ${response.statusText}`), { status: response.status });
53
+ }
54
+ const data = (await response.json());
55
+ const usage = data.prompt_eval_count != null && data.eval_count != null
56
+ ? { inputTokens: data.prompt_eval_count, outputTokens: data.eval_count }
57
+ : undefined;
58
+ return { text: data.message.content, usage, durationMs };
59
+ }
60
+ }
61
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/adapters/ollama.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
- import type { ProviderAdapter } from './base.js';
1
+ import type { AdapterResponse, ChatMessage, ProviderAdapter } from './base.js';
2
2
  export declare class OpenAIAdapter implements ProviderAdapter {
3
3
  private client;
4
4
  private model;
5
5
  constructor(model: string);
6
- call(prompt: string, system?: string): Promise<string>;
6
+ call(prompt: string, system?: string): Promise<AdapterResponse>;
7
+ chat(messages: ChatMessage[], system?: string): Promise<AdapterResponse>;
7
8
  }
8
9
  //# sourceMappingURL=openai.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAsBjD,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAQnB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAc7D"}
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAsB/E,qBAAa,aAAc,YAAW,eAAe;IACnD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;gBAEV,KAAK,EAAE,MAAM;IAQnB,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAI/D,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAuB/E"}
@@ -30,13 +30,24 @@ export class OpenAIAdapter {
30
30
  this.client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
31
31
  }
32
32
  async call(prompt, system) {
33
- const messages = [];
33
+ return this.chat([{ role: 'user', content: prompt }], system);
34
+ }
35
+ async chat(messages, system) {
36
+ const apiMessages = [];
34
37
  if (system) {
35
- messages.push({ role: 'system', content: system });
38
+ apiMessages.push({ role: 'system', content: system });
39
+ }
40
+ for (const msg of messages) {
41
+ apiMessages.push({ role: msg.role, content: msg.content });
36
42
  }
37
- messages.push({ role: 'user', content: prompt });
38
- const response = await withRetry(() => this.client.chat.completions.create({ model: this.model, messages }));
39
- return response.choices[0]?.message?.content ?? '';
43
+ const startMs = Date.now();
44
+ const response = await withRetry(() => this.client.chat.completions.create({ model: this.model, messages: apiMessages }));
45
+ const durationMs = Date.now() - startMs;
46
+ const text = response.choices[0]?.message?.content ?? '';
47
+ const usage = response.usage
48
+ ? { inputTokens: response.usage.prompt_tokens, outputTokens: response.usage.completion_tokens }
49
+ : undefined;
50
+ return { text, usage, durationMs };
40
51
  }
41
52
  }
42
53
  //# sourceMappingURL=openai.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAG5B,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,KAAK,UAAU,SAAS,CAAI,EAAoB;IAC9C,IAAI,SAAkB,CAAC;IACvB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,SAAS,GAAG,GAAG,CAAC;YAChB,MAAM,MAAM,GAAI,GAA2B,CAAC,MAAM,CAAC;YACnD,uDAAuD;YACvD,IAAI,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;gBAAE,MAAM,GAAG,CAAC;YAC5D,MAAM,KAAK,GAAG,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YACnD,MAAM,IAAI,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,MAAM,SAAS,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,aAAa;IAChB,MAAM,CAAS;IACf,KAAK,CAAS;IAEtB,YAAY,KAAa;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;QACzF,CAAC;QACD,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,MAAe;QACxC,MAAM,QAAQ,GAA6C,EAAE,CAAC;QAE9D,IAAI,MAAM,EAAE,CAAC;YACX,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QAEjD,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CACrE,CAAC;QAEF,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IACrD,CAAC;CACF"}
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/adapters/openai.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,10 @@
1
1
  import type { Assertion, AssertionResult } from '../core/types.js';
2
- export declare function runAssertions(output: string, assertions: Assertion[], scenarioDir: string): Promise<{
2
+ /** Context passed from the runner for cost/latency assertions */
3
+ export interface AssertionContext {
4
+ durationMs?: number;
5
+ costUsd?: number;
6
+ }
7
+ export declare function runAssertions(output: string, assertions: Assertion[], scenarioDir: string, ctx?: AssertionContext): Promise<{
3
8
  results: AssertionResult[];
4
9
  allPassed: boolean;
5
10
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/assertions/engine.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAInE,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,SAAS,EAAE,EACvB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAU7D"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/assertions/engine.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAInE,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,SAAS,EAAE,EACvB,WAAW,EAAE,MAAM,EACnB,GAAG,GAAE,gBAAqB,GACzB,OAAO,CAAC;IAAE,OAAO,EAAE,eAAe,EAAE,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAU7D"}