@darkrishabh/bench-ai 1.0.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 (112) hide show
  1. package/README.md +333 -0
  2. package/dist/cli/app.d.ts +11 -0
  3. package/dist/cli/app.d.ts.map +1 -0
  4. package/dist/cli/app.js +48 -0
  5. package/dist/cli/app.js.map +1 -0
  6. package/dist/cli/components/DiffView.d.ts +5 -0
  7. package/dist/cli/components/DiffView.d.ts.map +1 -0
  8. package/dist/cli/components/DiffView.js +14 -0
  9. package/dist/cli/components/DiffView.js.map +1 -0
  10. package/dist/cli/components/EvalView.d.ts +6 -0
  11. package/dist/cli/components/EvalView.d.ts.map +1 -0
  12. package/dist/cli/components/EvalView.js +82 -0
  13. package/dist/cli/components/EvalView.js.map +1 -0
  14. package/dist/cli/components/Spinner.d.ts +4 -0
  15. package/dist/cli/components/Spinner.d.ts.map +1 -0
  16. package/dist/cli/components/Spinner.js +15 -0
  17. package/dist/cli/components/Spinner.js.map +1 -0
  18. package/dist/cli/index.d.ts +3 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +117 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/cli/run-command.d.ts +11 -0
  23. package/dist/cli/run-command.d.ts.map +1 -0
  24. package/dist/cli/run-command.js +119 -0
  25. package/dist/cli/run-command.js.map +1 -0
  26. package/dist/engine/cost.d.ts +3 -0
  27. package/dist/engine/cost.d.ts.map +1 -0
  28. package/dist/engine/cost.js +52 -0
  29. package/dist/engine/cost.js.map +1 -0
  30. package/dist/engine/diff.d.ts +6 -0
  31. package/dist/engine/diff.d.ts.map +1 -0
  32. package/dist/engine/diff.js +43 -0
  33. package/dist/engine/diff.js.map +1 -0
  34. package/dist/engine/eval.d.ts +14 -0
  35. package/dist/engine/eval.d.ts.map +1 -0
  36. package/dist/engine/eval.js +194 -0
  37. package/dist/engine/eval.js.map +1 -0
  38. package/dist/engine/index.d.ts +15 -0
  39. package/dist/engine/index.d.ts.map +1 -0
  40. package/dist/engine/index.js +10 -0
  41. package/dist/engine/index.js.map +1 -0
  42. package/dist/engine/providers/base.d.ts +7 -0
  43. package/dist/engine/providers/base.d.ts.map +1 -0
  44. package/dist/engine/providers/base.js +2 -0
  45. package/dist/engine/providers/base.js.map +1 -0
  46. package/dist/engine/providers/claude.d.ts +15 -0
  47. package/dist/engine/providers/claude.d.ts.map +1 -0
  48. package/dist/engine/providers/claude.js +53 -0
  49. package/dist/engine/providers/claude.js.map +1 -0
  50. package/dist/engine/providers/minimax.d.ts +16 -0
  51. package/dist/engine/providers/minimax.d.ts.map +1 -0
  52. package/dist/engine/providers/minimax.js +67 -0
  53. package/dist/engine/providers/minimax.js.map +1 -0
  54. package/dist/engine/providers/ollama.d.ts +14 -0
  55. package/dist/engine/providers/ollama.d.ts.map +1 -0
  56. package/dist/engine/providers/ollama.js +60 -0
  57. package/dist/engine/providers/ollama.js.map +1 -0
  58. package/dist/engine/providers/openai-compatible.d.ts +19 -0
  59. package/dist/engine/providers/openai-compatible.d.ts.map +1 -0
  60. package/dist/engine/providers/openai-compatible.js +109 -0
  61. package/dist/engine/providers/openai-compatible.js.map +1 -0
  62. package/dist/engine/providers/subprocess.d.ts +55 -0
  63. package/dist/engine/providers/subprocess.d.ts.map +1 -0
  64. package/dist/engine/providers/subprocess.js +111 -0
  65. package/dist/engine/providers/subprocess.js.map +1 -0
  66. package/dist/engine/suite-loader.d.ts +11 -0
  67. package/dist/engine/suite-loader.d.ts.map +1 -0
  68. package/dist/engine/suite-loader.js +75 -0
  69. package/dist/engine/suite-loader.js.map +1 -0
  70. package/dist/engine/types.d.ts +104 -0
  71. package/dist/engine/types.d.ts.map +1 -0
  72. package/dist/engine/types.js +2 -0
  73. package/dist/engine/types.js.map +1 -0
  74. package/next-env.d.ts +6 -0
  75. package/next.config.ts +26 -0
  76. package/package.json +72 -0
  77. package/public/icon.svg +14 -0
  78. package/src/app/api/diff/route.ts +135 -0
  79. package/src/app/api/models/route.ts +96 -0
  80. package/src/app/api/suite/route.ts +314 -0
  81. package/src/app/globals.css +215 -0
  82. package/src/app/icon.svg +14 -0
  83. package/src/app/layout.tsx +44 -0
  84. package/src/app/opengraph-image.tsx +73 -0
  85. package/src/app/page.tsx +952 -0
  86. package/src/app/suite/layout.tsx +12 -0
  87. package/src/app/suite/page.tsx +206 -0
  88. package/src/app/twitter-image.tsx +1 -0
  89. package/src/components/BenchAiLogo.tsx +38 -0
  90. package/src/components/ComparePanel.tsx +643 -0
  91. package/src/components/ConfigPanel.tsx +809 -0
  92. package/src/components/MarkdownOutput.tsx +16 -0
  93. package/src/components/ModelResponseCard.tsx +313 -0
  94. package/src/components/QuickComparisonBar.tsx +184 -0
  95. package/src/components/ResponsesLineDiff.tsx +149 -0
  96. package/src/components/SettingsPanel.tsx +591 -0
  97. package/src/components/SuitePanel.tsx +875 -0
  98. package/src/lib/brand.ts +4 -0
  99. package/src/lib/config-yaml.ts +70 -0
  100. package/src/lib/consume-suite-sse.ts +70 -0
  101. package/src/lib/describe-judge.ts +23 -0
  102. package/src/lib/model-chip-palette.ts +9 -0
  103. package/src/lib/openai-model-list.ts +33 -0
  104. package/src/lib/provider-ui.ts +30 -0
  105. package/src/lib/resolve-credentials.ts +80 -0
  106. package/src/lib/run-history.ts +66 -0
  107. package/src/lib/simple-line-diff.ts +50 -0
  108. package/src/lib/storage.ts +100 -0
  109. package/src/lib/suite-judge-meta.ts +13 -0
  110. package/src/lib/suite-run-history.ts +81 -0
  111. package/src/types.ts +170 -0
  112. package/vercel.json +5 -0
@@ -0,0 +1,15 @@
1
+ export type { ProviderName, ProviderConfig, ProviderResult, DiffResult, RunOptions, Assertion, AssertionResult, TestCase, SuiteConfig, ProviderTestResult, TestCaseResult, ProviderSummary, SuiteResult, } from "./types.js";
2
+ export { calcCost, formatCost } from "./cost.js";
3
+ export { runDiff, runDiffMany } from "./diff.js";
4
+ export { ClaudeProvider } from "./providers/claude.js";
5
+ export { OllamaProvider } from "./providers/ollama.js";
6
+ export { MinimaxProvider } from "./providers/minimax.js";
7
+ export { OpenAICompatibleProvider } from "./providers/openai-compatible.js";
8
+ export type { OpenAICompatibleOptions } from "./providers/openai-compatible.js";
9
+ export { SubprocessProvider, createClaudeCLIProvider, createCodexProvider } from "./providers/subprocess.js";
10
+ export type { SubprocessOptions } from "./providers/subprocess.js";
11
+ export type { Provider } from "./providers/base.js";
12
+ export { runSuite } from "./eval.js";
13
+ export type { RunSuiteOptions } from "./eval.js";
14
+ export { parseSuiteConfig, interpolate } from "./suite-loader.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,cAAc,EACd,cAAc,EACd,UAAU,EACV,UAAU,EACV,SAAS,EACT,eAAe,EACf,QAAQ,EACR,WAAW,EACX,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,WAAW,GACZ,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,YAAY,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAC7G,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export { calcCost, formatCost } from "./cost.js";
2
+ export { runDiff, runDiffMany } from "./diff.js";
3
+ export { ClaudeProvider } from "./providers/claude.js";
4
+ export { OllamaProvider } from "./providers/ollama.js";
5
+ export { MinimaxProvider } from "./providers/minimax.js";
6
+ export { OpenAICompatibleProvider } from "./providers/openai-compatible.js";
7
+ export { SubprocessProvider, createClaudeCLIProvider, createCodexProvider } from "./providers/subprocess.js";
8
+ export { runSuite } from "./eval.js";
9
+ export { parseSuiteConfig, interpolate } from "./suite-loader.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engine/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAG7G,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ProviderResult } from "../types.js";
2
+ export interface Provider {
3
+ readonly name: string;
4
+ readonly model: string;
5
+ complete(prompt: string): Promise<ProviderResult>;
6
+ }
7
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/engine/providers/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CACnD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/engine/providers/base.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import type { ProviderResult } from "../types.js";
2
+ import type { Provider } from "./base.js";
3
+ export interface ClaudeOptions {
4
+ maxTokens?: number;
5
+ temperature?: number;
6
+ }
7
+ export declare class ClaudeProvider implements Provider {
8
+ readonly name = "claude";
9
+ readonly model: string;
10
+ private client;
11
+ private options;
12
+ constructor(apiKey: string, model?: string, options?: ClaudeOptions);
13
+ complete(prompt: string): Promise<ProviderResult>;
14
+ }
15
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/engine/providers/claude.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAI1C,MAAM,WAAW,aAAa;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,qBAAa,cAAe,YAAW,QAAQ;IAC7C,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAgB;gBAEnB,MAAM,EAAE,MAAM,EAAE,KAAK,SAAgB,EAAE,OAAO,GAAE,aAAkB;IAMxE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAwCxD"}
@@ -0,0 +1,53 @@
1
+ import Anthropic from "@anthropic-ai/sdk";
2
+ import { calcCost } from "../cost.js";
3
+ const DEFAULT_MODEL = "claude-3-5-haiku-20241022";
4
+ export class ClaudeProvider {
5
+ name = "claude";
6
+ model;
7
+ client;
8
+ options;
9
+ constructor(apiKey, model = DEFAULT_MODEL, options = {}) {
10
+ this.client = new Anthropic({ apiKey });
11
+ this.model = model;
12
+ this.options = options;
13
+ }
14
+ async complete(prompt) {
15
+ const start = Date.now();
16
+ try {
17
+ const response = await this.client.messages.create({
18
+ model: this.model,
19
+ max_tokens: this.options.maxTokens ?? 2048,
20
+ ...(this.options.temperature !== undefined
21
+ ? { temperature: this.options.temperature }
22
+ : {}),
23
+ messages: [{ role: "user", content: prompt }],
24
+ });
25
+ const latencyMs = Date.now() - start;
26
+ const inputTokens = response.usage.input_tokens;
27
+ const outputTokens = response.usage.output_tokens;
28
+ const output = response.content[0].type === "text" ? response.content[0].text : "";
29
+ return {
30
+ provider: "claude",
31
+ model: this.model,
32
+ output,
33
+ latencyMs,
34
+ inputTokens,
35
+ outputTokens,
36
+ costUsd: calcCost("claude", this.model, inputTokens, outputTokens),
37
+ };
38
+ }
39
+ catch (err) {
40
+ return {
41
+ provider: "claude",
42
+ model: this.model,
43
+ output: "",
44
+ latencyMs: Date.now() - start,
45
+ inputTokens: 0,
46
+ outputTokens: 0,
47
+ costUsd: 0,
48
+ error: err instanceof Error ? err.message : String(err),
49
+ };
50
+ }
51
+ }
52
+ }
53
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/engine/providers/claude.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAOlD,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,QAAQ,CAAC;IAChB,KAAK,CAAS;IACf,MAAM,CAAY;IAClB,OAAO,CAAgB;IAE/B,YAAY,MAAc,EAAE,KAAK,GAAG,aAAa,EAAE,UAAyB,EAAE;QAC5E,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;gBACjD,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI;gBAC1C,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS;oBACxC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;oBAC3C,CAAC,CAAC,EAAE,CAAC;gBACP,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;aAC9C,CAAC,CAAC;YAEH,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACrC,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC;YAChD,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC;YAClD,MAAM,MAAM,GACV,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAEtE,OAAO;gBACL,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM;gBACN,SAAS;gBACT,WAAW;gBACX,YAAY;gBACZ,OAAO,EAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,CAAC;aACnE,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,EAAE;gBACV,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBAC7B,WAAW,EAAE,CAAC;gBACd,YAAY,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;gBACV,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { ProviderResult } from "../types.js";
2
+ import type { Provider } from "./base.js";
3
+ export interface MinimaxOptions {
4
+ maxTokens?: number;
5
+ temperature?: number;
6
+ }
7
+ export declare class MinimaxProvider implements Provider {
8
+ readonly name = "minimax";
9
+ readonly model: string;
10
+ private apiKey;
11
+ private groupId;
12
+ private options;
13
+ constructor(apiKey: string, groupId: string, model?: string, options?: MinimaxOptions);
14
+ complete(prompt: string): Promise<ProviderResult>;
15
+ }
16
+ //# sourceMappingURL=minimax.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minimax.d.ts","sourceRoot":"","sources":["../../../src/engine/providers/minimax.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAK1C,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAOD,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,QAAQ,CAAC,IAAI,aAAa;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAiB;gBAEpB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,SAAgB,EAAE,OAAO,GAAE,cAAmB;IAO1F,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAsDxD"}
@@ -0,0 +1,67 @@
1
+ import { calcCost } from "../cost.js";
2
+ const DEFAULT_MODEL = "abab6.5s-chat";
3
+ const BASE_URL = "https://api.minimax.chat/v1";
4
+ export class MinimaxProvider {
5
+ name = "minimax";
6
+ model;
7
+ apiKey;
8
+ groupId;
9
+ options;
10
+ constructor(apiKey, groupId, model = DEFAULT_MODEL, options = {}) {
11
+ this.apiKey = apiKey;
12
+ this.groupId = groupId;
13
+ this.model = model;
14
+ this.options = options;
15
+ }
16
+ async complete(prompt) {
17
+ const start = Date.now();
18
+ try {
19
+ const body = {
20
+ model: this.model,
21
+ messages: [{ role: "user", content: prompt }],
22
+ };
23
+ if (this.options.maxTokens !== undefined)
24
+ body.max_tokens = this.options.maxTokens;
25
+ if (this.options.temperature !== undefined)
26
+ body.temperature = this.options.temperature;
27
+ const res = await fetch(`${BASE_URL}/text/chatcompletion_v2?GroupId=${this.groupId}`, {
28
+ method: "POST",
29
+ headers: {
30
+ "Content-Type": "application/json",
31
+ Authorization: `Bearer ${this.apiKey}`,
32
+ },
33
+ body: JSON.stringify(body),
34
+ });
35
+ if (!res.ok) {
36
+ throw new Error(`Minimax ${res.status}: ${await res.text()}`);
37
+ }
38
+ const data = (await res.json());
39
+ const latencyMs = Date.now() - start;
40
+ const inputTokens = data.usage.prompt_tokens;
41
+ const outputTokens = data.usage.completion_tokens;
42
+ const output = data.choices[0]?.message.content ?? "";
43
+ return {
44
+ provider: "minimax",
45
+ model: this.model,
46
+ output,
47
+ latencyMs,
48
+ inputTokens,
49
+ outputTokens,
50
+ costUsd: calcCost("minimax", this.model, inputTokens, outputTokens),
51
+ };
52
+ }
53
+ catch (err) {
54
+ return {
55
+ provider: "minimax",
56
+ model: this.model,
57
+ output: "",
58
+ latencyMs: Date.now() - start,
59
+ inputTokens: 0,
60
+ outputTokens: 0,
61
+ costUsd: 0,
62
+ error: err instanceof Error ? err.message : String(err),
63
+ };
64
+ }
65
+ }
66
+ }
67
+ //# sourceMappingURL=minimax.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"minimax.js","sourceRoot":"","sources":["../../../src/engine/providers/minimax.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ProviderResult } from "../types.js";
2
+ import type { Provider } from "./base.js";
3
+ export interface OllamaOptions {
4
+ temperature?: number;
5
+ }
6
+ export declare class OllamaProvider implements Provider {
7
+ readonly name = "ollama";
8
+ readonly model: string;
9
+ private baseUrl;
10
+ private options;
11
+ constructor(baseUrl?: string, model?: string, options?: OllamaOptions);
12
+ complete(prompt: string): Promise<ProviderResult>;
13
+ }
14
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../../src/engine/providers/ollama.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAK1C,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AASD,qBAAa,cAAe,YAAW,QAAQ;IAC7C,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAgB;gBAEnB,OAAO,SAAmB,EAAE,KAAK,SAAgB,EAAE,OAAO,GAAE,aAAkB;IAMpF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAiDxD"}
@@ -0,0 +1,60 @@
1
+ const DEFAULT_BASE_URL = "http://localhost:11434";
2
+ const DEFAULT_MODEL = "llama3.2";
3
+ export class OllamaProvider {
4
+ name = "ollama";
5
+ model;
6
+ baseUrl;
7
+ options;
8
+ constructor(baseUrl = DEFAULT_BASE_URL, model = DEFAULT_MODEL, options = {}) {
9
+ this.baseUrl = baseUrl.replace(/\/$/, "");
10
+ this.model = model;
11
+ this.options = options;
12
+ }
13
+ async complete(prompt) {
14
+ const start = Date.now();
15
+ try {
16
+ const body = {
17
+ model: this.model,
18
+ prompt,
19
+ stream: false,
20
+ };
21
+ if (this.options.temperature !== undefined) {
22
+ body.options = { temperature: this.options.temperature };
23
+ }
24
+ const res = await fetch(`${this.baseUrl}/api/generate`, {
25
+ method: "POST",
26
+ headers: { "Content-Type": "application/json" },
27
+ body: JSON.stringify(body),
28
+ });
29
+ if (!res.ok) {
30
+ throw new Error(`Ollama ${res.status}: ${await res.text()}`);
31
+ }
32
+ const data = (await res.json());
33
+ const latencyMs = Date.now() - start;
34
+ const inputTokens = data.prompt_eval_count ?? 0;
35
+ const outputTokens = data.eval_count ?? 0;
36
+ return {
37
+ provider: "ollama",
38
+ model: this.model,
39
+ output: data.response,
40
+ latencyMs,
41
+ inputTokens,
42
+ outputTokens,
43
+ costUsd: 0,
44
+ };
45
+ }
46
+ catch (err) {
47
+ return {
48
+ provider: "ollama",
49
+ model: this.model,
50
+ output: "",
51
+ latencyMs: Date.now() - start,
52
+ inputTokens: 0,
53
+ outputTokens: 0,
54
+ costUsd: 0,
55
+ error: err instanceof Error ? err.message : String(err),
56
+ };
57
+ }
58
+ }
59
+ }
60
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../../src/engine/providers/ollama.ts"],"names":[],"mappings":"AAGA,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAClD,MAAM,aAAa,GAAG,UAAU,CAAC;AAajC,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,QAAQ,CAAC;IAChB,KAAK,CAAS;IACf,OAAO,CAAS;IAChB,OAAO,CAAgB;IAE/B,YAAY,OAAO,GAAG,gBAAgB,EAAE,KAAK,GAAG,aAAa,EAAE,UAAyB,EAAE;QACxF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc;QAC3B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,GAA4B;gBACpC,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM;gBACN,MAAM,EAAE,KAAK;aACd,CAAC;YACF,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;gBAC3C,IAAI,CAAC,OAAO,GAAG,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YAC3D,CAAC;YAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,eAAe,EAAE;gBACtD,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;aAC3B,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,MAAM,KAAK,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC/D,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmB,CAAC;YAClD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;YACrC,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC;YAChD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;YAE1C,OAAO;gBACL,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,IAAI,CAAC,QAAQ;gBACrB,SAAS;gBACT,WAAW;gBACX,YAAY;gBACZ,OAAO,EAAE,CAAC;aACX,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,IAAI,CAAC,KAAK;gBACjB,MAAM,EAAE,EAAE;gBACV,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;gBAC7B,WAAW,EAAE,CAAC;gBACd,YAAY,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;gBACV,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ import type { ProviderResult } from "../types.js";
2
+ import type { Provider } from "./base.js";
3
+ export interface OpenAICompatibleOptions {
4
+ maxTokens?: number;
5
+ temperature?: number;
6
+ /** Extra headers to merge into every request (e.g. HTTP-Referer for OpenRouter) */
7
+ extraHeaders?: Record<string, string>;
8
+ }
9
+ export declare class OpenAICompatibleProvider implements Provider {
10
+ /** Shown as `provider` in ProviderResult — pass the human name, e.g. "openai", "groq" */
11
+ readonly name: string;
12
+ readonly model: string;
13
+ private baseUrl;
14
+ private apiKey;
15
+ private options;
16
+ constructor(name: string, baseUrl: string, apiKey: string, model: string, options?: OpenAICompatibleOptions);
17
+ complete(prompt: string): Promise<ProviderResult>;
18
+ }
19
+ //# sourceMappingURL=openai-compatible.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-compatible.d.ts","sourceRoot":"","sources":["../../../src/engine/providers/openai-compatible.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAoCD,qBAAa,wBAAyB,YAAW,QAAQ;IACvD,yFAAyF;IACzF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAA0B;gBAGvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,uBAA4B;IASjC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAkExD"}
@@ -0,0 +1,109 @@
1
+ import { calcCost } from "../cost.js";
2
+ function modelTail(model) {
3
+ const id = model.toLowerCase();
4
+ return id.includes("/") ? id.slice(id.lastIndexOf("/") + 1) : id;
5
+ }
6
+ /**
7
+ * Models that reject `max_tokens` and require `max_completion_tokens` on Chat Completions
8
+ * (o-series, GPT-5 family, including OpenRouter-style ids like `openai/gpt-5.4`).
9
+ */
10
+ function openAiUsesMaxCompletionTokens(model) {
11
+ const tail = modelTail(model);
12
+ if (/^o\d/.test(tail))
13
+ return true;
14
+ if (tail.startsWith("gpt-5"))
15
+ return true;
16
+ return false;
17
+ }
18
+ /**
19
+ * GPT-5.4 / GPT-5.2 lines: `temperature`, `top_p`, and `logprobs` are allowed when reasoning
20
+ * effort is `none` (the default for gpt-5.4 per OpenAI). Older `gpt-5` / `gpt-5-mini` / `o*`
21
+ * reject those fields or use different rules — we omit temperature unless this matches.
22
+ *
23
+ * @see https://platform.openai.com/docs/guides/latest-model
24
+ */
25
+ function openAiGpt5DotSeriesAllowsSamplingParams(model) {
26
+ const tail = modelTail(model);
27
+ return /^gpt-5\.4/.test(tail) || /^gpt-5\.2/.test(tail);
28
+ }
29
+ export class OpenAICompatibleProvider {
30
+ /** Shown as `provider` in ProviderResult — pass the human name, e.g. "openai", "groq" */
31
+ name;
32
+ model;
33
+ baseUrl;
34
+ apiKey;
35
+ options;
36
+ constructor(name, baseUrl, apiKey, model, options = {}) {
37
+ this.name = name;
38
+ this.baseUrl = baseUrl.replace(/\/$/, "");
39
+ this.apiKey = apiKey;
40
+ this.model = model;
41
+ this.options = options;
42
+ }
43
+ async complete(prompt) {
44
+ const start = Date.now();
45
+ try {
46
+ const body = {
47
+ model: this.model,
48
+ messages: [{ role: "user", content: prompt }],
49
+ };
50
+ if (this.options.maxTokens) {
51
+ if (openAiUsesMaxCompletionTokens(this.model)) {
52
+ body.max_completion_tokens = this.options.maxTokens;
53
+ }
54
+ else {
55
+ body.max_tokens = this.options.maxTokens;
56
+ }
57
+ }
58
+ if (this.options.temperature !== undefined) {
59
+ if (openAiGpt5DotSeriesAllowsSamplingParams(this.model)) {
60
+ body.temperature = this.options.temperature;
61
+ }
62
+ else if (!openAiUsesMaxCompletionTokens(this.model)) {
63
+ body.temperature = this.options.temperature;
64
+ }
65
+ }
66
+ const headers = {
67
+ "Content-Type": "application/json",
68
+ ...this.options.extraHeaders,
69
+ };
70
+ if (this.apiKey)
71
+ headers["Authorization"] = `Bearer ${this.apiKey}`;
72
+ const res = await fetch(`${this.baseUrl}/chat/completions`, {
73
+ method: "POST",
74
+ headers,
75
+ body: JSON.stringify(body),
76
+ });
77
+ if (!res.ok) {
78
+ throw new Error(`${this.name} ${res.status}: ${await res.text()}`);
79
+ }
80
+ const data = (await res.json());
81
+ const latencyMs = Date.now() - start;
82
+ const inputTokens = data.usage?.prompt_tokens ?? 0;
83
+ const outputTokens = data.usage?.completion_tokens ?? 0;
84
+ const output = data.choices[0]?.message.content ?? "";
85
+ return {
86
+ provider: this.name,
87
+ model: this.model,
88
+ output,
89
+ latencyMs,
90
+ inputTokens,
91
+ outputTokens,
92
+ costUsd: calcCost(this.name, this.model, inputTokens, outputTokens),
93
+ };
94
+ }
95
+ catch (err) {
96
+ return {
97
+ provider: this.name,
98
+ model: this.model,
99
+ output: "",
100
+ latencyMs: Date.now() - start,
101
+ inputTokens: 0,
102
+ outputTokens: 0,
103
+ costUsd: 0,
104
+ error: err instanceof Error ? err.message : String(err),
105
+ };
106
+ }
107
+ }
108
+ }
109
+ //# sourceMappingURL=openai-compatible.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-compatible.js","sourceRoot":"","sources":["../../../src/engine/providers/openai-compatible.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import type { ProviderResult } from "../types.js";
2
+ import type { Provider } from "./base.js";
3
+ export interface SubprocessOptions {
4
+ /**
5
+ * Timeout in milliseconds. Defaults to 120_000 (2 min).
6
+ * Set higher for slow local models.
7
+ */
8
+ timeoutMs?: number;
9
+ /**
10
+ * Extra CLI flags to append before the prompt.
11
+ */
12
+ extraArgs?: string[];
13
+ /**
14
+ * Max characters of output to capture. Defaults to 100_000.
15
+ */
16
+ maxOutputChars?: number;
17
+ /**
18
+ * If set, `[modelFlag, model]` is injected into the command before the prompt.
19
+ * e.g. "--model" → `claude -p --model claude-opus-4-6 "<prompt>"`
20
+ */
21
+ modelFlag?: string;
22
+ }
23
+ /**
24
+ * SubprocessProvider — wraps any local CLI tool that accepts a prompt as a
25
+ * positional argument and writes its response to stdout.
26
+ *
27
+ * Works out of the box with:
28
+ * - Claude Code CLI: binary="claude" args=["-p"]
29
+ * - OpenAI Codex CLI: binary="codex" args=[]
30
+ *
31
+ * Token counts are unavailable from subprocess CLIs, so they are reported
32
+ * as 0 and cost is reported as $0.00.
33
+ */
34
+ export declare class SubprocessProvider implements Provider {
35
+ readonly name: string;
36
+ readonly model: string;
37
+ private binary;
38
+ /** Args that precede the prompt string, e.g. ["-p"] for `claude -p "..."` */
39
+ private prefixArgs;
40
+ private options;
41
+ constructor(name: string, binary: string, prefixArgs: string[], model: string, options?: SubprocessOptions);
42
+ complete(prompt: string): Promise<ProviderResult>;
43
+ }
44
+ /**
45
+ * Claude Code CLI (`claude -p --model <model> "<prompt>"`).
46
+ * Install: npm i -g @anthropic-ai/claude-code
47
+ */
48
+ export declare function createClaudeCLIProvider(model: string, options?: SubprocessOptions): SubprocessProvider;
49
+ /**
50
+ * OpenAI Codex CLI (`codex exec -m <model> "<prompt>"`).
51
+ * Install: npm i -g @openai/codex
52
+ * Uses the `exec` subcommand for non-interactive execution.
53
+ */
54
+ export declare function createCodexProvider(model: string, options?: SubprocessOptions): SubprocessProvider;
55
+ //# sourceMappingURL=subprocess.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subprocess.d.ts","sourceRoot":"","sources":["../../../src/engine/providers/subprocess.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,kBAAmB,YAAW,QAAQ;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAEvB,OAAO,CAAC,MAAM,CAAS;IACvB,6EAA6E;IAC7E,OAAO,CAAC,UAAU,CAAW;IAC7B,OAAO,CAAC,OAAO,CAAoB;gBAGjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAAE,EACpB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,iBAAsB;IAS3B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;CAuExD;AAID;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,kBAAkB,CAKtG;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,kBAAkB,CAKlG"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * SubprocessProvider — wraps any local CLI tool that accepts a prompt as a
3
+ * positional argument and writes its response to stdout.
4
+ *
5
+ * Works out of the box with:
6
+ * - Claude Code CLI: binary="claude" args=["-p"]
7
+ * - OpenAI Codex CLI: binary="codex" args=[]
8
+ *
9
+ * Token counts are unavailable from subprocess CLIs, so they are reported
10
+ * as 0 and cost is reported as $0.00.
11
+ */
12
+ export class SubprocessProvider {
13
+ name;
14
+ model;
15
+ binary;
16
+ /** Args that precede the prompt string, e.g. ["-p"] for `claude -p "..."` */
17
+ prefixArgs;
18
+ options;
19
+ constructor(name, binary, prefixArgs, model, options = {}) {
20
+ this.name = name;
21
+ this.binary = binary;
22
+ this.prefixArgs = prefixArgs;
23
+ this.model = model;
24
+ this.options = options;
25
+ }
26
+ async complete(prompt) {
27
+ const start = Date.now();
28
+ const timeoutMs = this.options.timeoutMs ?? 120_000;
29
+ const maxChars = this.options.maxOutputChars ?? 100_000;
30
+ const extraArgs = this.options.extraArgs ?? [];
31
+ try {
32
+ const { spawn } = await import("child_process");
33
+ // Only pass --model if we have a real model name (not empty / not equal to the provider name)
34
+ const isValidModel = this.model && this.model !== this.name;
35
+ const modelArgs = this.options.modelFlag && isValidModel
36
+ ? [this.options.modelFlag, this.model]
37
+ : [];
38
+ const args = [...this.prefixArgs, ...modelArgs, ...extraArgs, prompt];
39
+ const output = await new Promise((resolve, reject) => {
40
+ // stdio: ['ignore', …] ensures stdin is /dev/null so the CLI doesn't
41
+ // wait for terminal input or error with "stdin is not a terminal"
42
+ const child = spawn(this.binary, args, {
43
+ stdio: ["ignore", "pipe", "pipe"],
44
+ });
45
+ let stdout = "";
46
+ let stderr = "";
47
+ child.stdout.on("data", (chunk) => { stdout += chunk.toString(); });
48
+ child.stderr.on("data", (chunk) => { stderr += chunk.toString(); });
49
+ const timer = setTimeout(() => {
50
+ child.kill();
51
+ reject(new Error(`Timed out after ${timeoutMs}ms`));
52
+ }, timeoutMs);
53
+ child.on("close", (code) => {
54
+ clearTimeout(timer);
55
+ if (code !== 0) {
56
+ const msg = `Command failed: ${this.binary} ${args.join(" ")}`;
57
+ reject(new Error(stderr.trim() ? `${msg}\n${stderr.trim()}` : msg));
58
+ }
59
+ else {
60
+ resolve(stdout);
61
+ }
62
+ });
63
+ child.on("error", (err) => { clearTimeout(timer); reject(err); });
64
+ });
65
+ return {
66
+ provider: this.name,
67
+ model: this.model,
68
+ output: output.slice(0, maxChars),
69
+ latencyMs: Date.now() - start,
70
+ inputTokens: 0,
71
+ outputTokens: 0,
72
+ costUsd: 0,
73
+ };
74
+ }
75
+ catch (err) {
76
+ return {
77
+ provider: this.name,
78
+ model: this.model,
79
+ output: "",
80
+ latencyMs: Date.now() - start,
81
+ inputTokens: 0,
82
+ outputTokens: 0,
83
+ costUsd: 0,
84
+ error: err instanceof Error ? err.message : String(err),
85
+ };
86
+ }
87
+ }
88
+ }
89
+ // ─── Ready-made factory helpers ───────────────────────────────────────────────
90
+ /**
91
+ * Claude Code CLI (`claude -p --model <model> "<prompt>"`).
92
+ * Install: npm i -g @anthropic-ai/claude-code
93
+ */
94
+ export function createClaudeCLIProvider(model, options) {
95
+ return new SubprocessProvider("claude-cli", "claude", ["-p"], model, {
96
+ modelFlag: "--model",
97
+ ...options,
98
+ });
99
+ }
100
+ /**
101
+ * OpenAI Codex CLI (`codex exec -m <model> "<prompt>"`).
102
+ * Install: npm i -g @openai/codex
103
+ * Uses the `exec` subcommand for non-interactive execution.
104
+ */
105
+ export function createCodexProvider(model, options) {
106
+ return new SubprocessProvider("codex", "codex", ["exec"], model, {
107
+ modelFlag: "-m",
108
+ ...options,
109
+ });
110
+ }
111
+ //# sourceMappingURL=subprocess.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subprocess.js","sourceRoot":"","sources":["../../../src/engine/providers/subprocess.ts"],"names":[],"mappings":"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"}