@vijaypjavvadi/bdd2pw 3.10.0 → 4.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.
@@ -0,0 +1,83 @@
1
+ /**
2
+ * OpenAI LLM client — v3.11.0.
3
+ *
4
+ * Implements the same `LLMClient` interface as `AnthropicLLMClient`:
5
+ * single-step `generateBinding`, batched `generateBatchBindings`,
6
+ * cache hit accounting, budget tracking, governance sanitisation,
7
+ * step deadlines, provider timeouts.
8
+ *
9
+ * Differences from the Anthropic client are minimal and limited to
10
+ * the SDK call shape:
11
+ *
12
+ * Anthropic OpenAI
13
+ * ------------------------------- -----------------------------
14
+ * anthropic.messages.create({ openai.chat.completions.create({
15
+ * system: SYSTEM_PROMPT, messages: [
16
+ * messages: [ { role: 'system',
17
+ * { role: 'user', content } content: SYSTEM_PROMPT },
18
+ * ] { role: 'user', content }
19
+ * }) ]
20
+ * })
21
+ *
22
+ * resp.content[0].text resp.choices[0].message.content
23
+ * resp.usage.input_tokens resp.usage.prompt_tokens
24
+ * resp.usage.output_tokens resp.usage.completion_tokens
25
+ *
26
+ * The prompt machinery (`SYSTEM_PROMPT`, `buildUserPrompt`,
27
+ * `buildBatchUserPrompt`, `cacheKey`), the parser (`parseBindingJson`),
28
+ * the cache (`openSqliteCache`), and the governance client
29
+ * (`GovernanceClient`) are all shared with the Anthropic path —
30
+ * cache keys interoperate, so a scaffold cached under one provider
31
+ * hits the cache under another (cache keys include the model name,
32
+ * so cross-provider hits only fire when models match).
33
+ *
34
+ * Default model: `gpt-4o-mini`. Reasoning: bdd2pw's task is
35
+ * structured JSON output over a small set of regex-shaped
36
+ * deterministic patterns. Mini handles it reliably and runs ~17x
37
+ * cheaper than gpt-4o ($0.15 vs $2.50 per million input tokens).
38
+ * Override via `LLMClientOptions.model`.
39
+ */
40
+ import type { BindingCache } from "./cache";
41
+ import type { GenerateBindingInput, GenerateBindingResult, LLMClient, LLMClientOptions } from "./types";
42
+ export declare class OpenAILLMClient implements LLMClient {
43
+ private model;
44
+ private apiKey;
45
+ private maxCalls;
46
+ private skipGovernance;
47
+ private log;
48
+ private governance;
49
+ private cache;
50
+ private cachePath;
51
+ private callsCounter;
52
+ private attemptsCounter;
53
+ private openai;
54
+ private cachePersistent;
55
+ private cacheFallbackReason;
56
+ private providerTimeoutMs;
57
+ constructor(opts: LLMClientOptions, cachePathDefault: string);
58
+ ensureCache(): Promise<BindingCache>;
59
+ budgetExhausted(): boolean;
60
+ callsMade(): number;
61
+ callsAttempted(): number;
62
+ cacheBackendPersistent(): boolean | null;
63
+ cacheBackendFallbackReason(): string | undefined;
64
+ /**
65
+ * Single-step generation. Cache → governance → OpenAI → parse.
66
+ * Mirrors `AnthropicLLMClient.generateBinding` end-to-end.
67
+ */
68
+ generateBinding(input: GenerateBindingInput): Promise<GenerateBindingResult>;
69
+ /**
70
+ * Batched generation — same per-step cache lookup + single batched
71
+ * prompt as `AnthropicLLMClient.generateBatchBindings`. The JSON array
72
+ * response is parsed slot by slot through `parseBindingJson`.
73
+ */
74
+ generateBatchBindings(inputs: GenerateBindingInput[]): Promise<GenerateBindingResult[]>;
75
+ private lazyClient;
76
+ /**
77
+ * v4.0.0 — generic single-prompt text generation. Mirrors
78
+ * AnthropicLLMClient.generateText. Cache intentionally skipped;
79
+ * see that method for rationale.
80
+ */
81
+ generateText(prompt: string): Promise<import("./types").GenerateTextResult>;
82
+ close(): Promise<void>;
83
+ }
@@ -0,0 +1,529 @@
1
+ "use strict";
2
+ /**
3
+ * OpenAI LLM client — v3.11.0.
4
+ *
5
+ * Implements the same `LLMClient` interface as `AnthropicLLMClient`:
6
+ * single-step `generateBinding`, batched `generateBatchBindings`,
7
+ * cache hit accounting, budget tracking, governance sanitisation,
8
+ * step deadlines, provider timeouts.
9
+ *
10
+ * Differences from the Anthropic client are minimal and limited to
11
+ * the SDK call shape:
12
+ *
13
+ * Anthropic OpenAI
14
+ * ------------------------------- -----------------------------
15
+ * anthropic.messages.create({ openai.chat.completions.create({
16
+ * system: SYSTEM_PROMPT, messages: [
17
+ * messages: [ { role: 'system',
18
+ * { role: 'user', content } content: SYSTEM_PROMPT },
19
+ * ] { role: 'user', content }
20
+ * }) ]
21
+ * })
22
+ *
23
+ * resp.content[0].text resp.choices[0].message.content
24
+ * resp.usage.input_tokens resp.usage.prompt_tokens
25
+ * resp.usage.output_tokens resp.usage.completion_tokens
26
+ *
27
+ * The prompt machinery (`SYSTEM_PROMPT`, `buildUserPrompt`,
28
+ * `buildBatchUserPrompt`, `cacheKey`), the parser (`parseBindingJson`),
29
+ * the cache (`openSqliteCache`), and the governance client
30
+ * (`GovernanceClient`) are all shared with the Anthropic path —
31
+ * cache keys interoperate, so a scaffold cached under one provider
32
+ * hits the cache under another (cache keys include the model name,
33
+ * so cross-provider hits only fire when models match).
34
+ *
35
+ * Default model: `gpt-4o-mini`. Reasoning: bdd2pw's task is
36
+ * structured JSON output over a small set of regex-shaped
37
+ * deterministic patterns. Mini handles it reliably and runs ~17x
38
+ * cheaper than gpt-4o ($0.15 vs $2.50 per million input tokens).
39
+ * Override via `LLMClientOptions.model`.
40
+ */
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.OpenAILLMClient = void 0;
43
+ const cache_1 = require("./cache");
44
+ const governanceClient_1 = require("./governanceClient");
45
+ const prompt_1 = require("./prompt");
46
+ const anthropicClient_1 = require("./anthropicClient");
47
+ const DEFAULT_MODEL = "gpt-4o-mini";
48
+ const DEFAULT_MAX_CALLS = 50;
49
+ const DEFAULT_GOVERNANCE_URL = "http://localhost:4900";
50
+ const DEFAULT_STEP_TIMEOUT_MS = 60000;
51
+ const DEFAULT_PROVIDER_TIMEOUT_MS = 30000;
52
+ const DEFAULT_GOVERNANCE_TIMEOUT_MS = 15000;
53
+ class OpenAILLMClient {
54
+ constructor(opts, cachePathDefault) {
55
+ this.cache = null;
56
+ this.callsCounter = 0;
57
+ this.attemptsCounter = 0;
58
+ this.openai = null;
59
+ this.cachePersistent = null;
60
+ this.model = opts.model ?? DEFAULT_MODEL;
61
+ this.apiKey = opts.apiKey ?? process.env.OPENAI_API_KEY ?? "";
62
+ this.maxCalls = opts.maxCalls ?? DEFAULT_MAX_CALLS;
63
+ this.skipGovernance = opts.skipGovernance ?? false;
64
+ this.log = opts.log ?? (() => { });
65
+ this.providerTimeoutMs =
66
+ opts.providerTimeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
67
+ this.governance = new governanceClient_1.GovernanceClient(opts.governanceUrl ?? DEFAULT_GOVERNANCE_URL, opts.governanceTimeoutMs ?? DEFAULT_GOVERNANCE_TIMEOUT_MS);
68
+ this.cachePath = opts.cachePath ?? cachePathDefault;
69
+ }
70
+ async ensureCache() {
71
+ if (!this.cache) {
72
+ const result = await (0, cache_1.openSqliteCache)(this.cachePath);
73
+ this.cache = result.cache;
74
+ this.cachePersistent = result.persistent;
75
+ this.cacheFallbackReason = result.fallbackReason;
76
+ if (!result.persistent && result.fallbackReason) {
77
+ this.log({ kind: "cache_fallback", reason: result.fallbackReason });
78
+ this.log({
79
+ kind: "error",
80
+ phase: "cache_load",
81
+ message: `Cache backend unavailable, falling back to in-memory for this run. Reason: ${result.fallbackReason}`,
82
+ });
83
+ }
84
+ }
85
+ return this.cache;
86
+ }
87
+ budgetExhausted() {
88
+ return this.attemptsCounter >= this.maxCalls;
89
+ }
90
+ callsMade() {
91
+ return this.callsCounter;
92
+ }
93
+ callsAttempted() {
94
+ return this.attemptsCounter;
95
+ }
96
+ cacheBackendPersistent() {
97
+ return this.cachePersistent;
98
+ }
99
+ cacheBackendFallbackReason() {
100
+ return this.cacheFallbackReason;
101
+ }
102
+ /**
103
+ * Single-step generation. Cache → governance → OpenAI → parse.
104
+ * Mirrors `AnthropicLLMClient.generateBinding` end-to-end.
105
+ */
106
+ async generateBinding(input) {
107
+ const start = Date.now();
108
+ const key = (0, prompt_1.cacheKey)(input, this.model);
109
+ const cache = await this.ensureCache();
110
+ const hit = await cache.get(key);
111
+ if (hit) {
112
+ this.log({ kind: "cache_hit", key });
113
+ return {
114
+ binding: hit.binding,
115
+ fromCache: true,
116
+ model: hit.model,
117
+ latencyMs: Date.now() - start,
118
+ };
119
+ }
120
+ this.log({ kind: "cache_miss", key });
121
+ if (this.budgetExhausted()) {
122
+ return {
123
+ error: `LLM budget exhausted (${this.callsCounter}/${this.maxCalls} calls). Increase via --llm-max-calls.`,
124
+ fromCache: false,
125
+ };
126
+ }
127
+ const userPrompt = (0, prompt_1.buildUserPrompt)(input);
128
+ let sanitisedUserPrompt = userPrompt;
129
+ if (!this.skipGovernance) {
130
+ try {
131
+ this.log({ kind: "sanitise_start", bytes: userPrompt.length });
132
+ const result = await this.governance.sanitiseCode(userPrompt);
133
+ sanitisedUserPrompt = result.sanitised;
134
+ this.log({
135
+ kind: "sanitise_done",
136
+ bytes: sanitisedUserPrompt.length,
137
+ findings: result.findings.length,
138
+ });
139
+ }
140
+ catch (err) {
141
+ const isUnreachable = err instanceof governanceClient_1.GovernanceUnreachableError;
142
+ const message = err instanceof Error ? err.message : String(err);
143
+ this.log({ kind: "error", phase: "governance", message });
144
+ return {
145
+ error: isUnreachable
146
+ ? `Governance sidecar unreachable; refusing to call LLM (fail-closed). ${message}`
147
+ : `Governance sanitise failed: ${message}`,
148
+ fromCache: false,
149
+ };
150
+ }
151
+ }
152
+ if (!this.apiKey) {
153
+ return {
154
+ error: "OPENAI_API_KEY is not set; pass apiKey or set the env var.",
155
+ fromCache: false,
156
+ };
157
+ }
158
+ const openai = await this.lazyClient();
159
+ if (!openai) {
160
+ return {
161
+ error: "openai SDK not installed. Run: npm install openai",
162
+ fromCache: false,
163
+ };
164
+ }
165
+ let responseText = "";
166
+ let inputTokens = 0;
167
+ let outputTokens = 0;
168
+ this.attemptsCounter += 1;
169
+ try {
170
+ this.log({
171
+ kind: "provider_call_start",
172
+ model: this.model,
173
+ promptBytes: sanitisedUserPrompt.length,
174
+ });
175
+ const callStart = Date.now();
176
+ const resp = await openai.chat.completions.create({
177
+ model: this.model,
178
+ max_tokens: 1024,
179
+ temperature: 0,
180
+ messages: [
181
+ { role: "system", content: prompt_1.SYSTEM_PROMPT },
182
+ { role: "user", content: sanitisedUserPrompt },
183
+ ],
184
+ }, { timeout: this.providerTimeoutMs });
185
+ this.callsCounter += 1;
186
+ const callLatency = Date.now() - callStart;
187
+ responseText = resp.choices?.[0]?.message?.content ?? "";
188
+ inputTokens = resp.usage?.prompt_tokens ?? 0;
189
+ outputTokens = resp.usage?.completion_tokens ?? 0;
190
+ this.log({
191
+ kind: "provider_call_done",
192
+ model: this.model,
193
+ latencyMs: callLatency,
194
+ inputTokens,
195
+ outputTokens,
196
+ });
197
+ }
198
+ catch (err) {
199
+ const message = err instanceof Error ? err.message : String(err);
200
+ this.log({ kind: "error", phase: "openai", message });
201
+ return {
202
+ error: `OpenAI API call failed: ${message}`,
203
+ fromCache: false,
204
+ };
205
+ }
206
+ const binding = (0, anthropicClient_1.parseBindingJson)(responseText, input);
207
+ if (!binding) {
208
+ this.log({
209
+ kind: "error",
210
+ phase: "parse",
211
+ message: `Could not parse JSON binding from LLM output: ${responseText.slice(0, 200)}`,
212
+ });
213
+ return {
214
+ error: `Could not parse JSON binding from LLM output (first 200 chars): ${responseText.slice(0, 200)}`,
215
+ fromCache: false,
216
+ };
217
+ }
218
+ this.log({ kind: "binding_parsed", binding });
219
+ await cache.set(key, {
220
+ binding,
221
+ model: this.model,
222
+ createdAt: new Date().toISOString(),
223
+ });
224
+ return {
225
+ binding,
226
+ fromCache: false,
227
+ model: this.model,
228
+ latencyMs: Date.now() - start,
229
+ };
230
+ }
231
+ /**
232
+ * Batched generation — same per-step cache lookup + single batched
233
+ * prompt as `AnthropicLLMClient.generateBatchBindings`. The JSON array
234
+ * response is parsed slot by slot through `parseBindingJson`.
235
+ */
236
+ async generateBatchBindings(inputs) {
237
+ if (inputs.length === 0)
238
+ return [];
239
+ const start = Date.now();
240
+ const cache = await this.ensureCache();
241
+ const results = new Array(inputs.length);
242
+ const missIndexes = [];
243
+ const missInputs = [];
244
+ const missKeys = [];
245
+ for (let i = 0; i < inputs.length; i++) {
246
+ const key = (0, prompt_1.cacheKey)(inputs[i], this.model);
247
+ const hit = await cache.get(key);
248
+ if (hit) {
249
+ this.log({ kind: "cache_hit", key });
250
+ results[i] = {
251
+ binding: hit.binding,
252
+ fromCache: true,
253
+ model: hit.model,
254
+ latencyMs: Date.now() - start,
255
+ };
256
+ }
257
+ else {
258
+ this.log({ kind: "cache_miss", key });
259
+ missIndexes.push(i);
260
+ missInputs.push(inputs[i]);
261
+ missKeys.push(key);
262
+ }
263
+ }
264
+ if (missInputs.length === 0) {
265
+ return results.map((r) => r);
266
+ }
267
+ if (this.budgetExhausted()) {
268
+ const err = {
269
+ error: `LLM budget exhausted (${this.callsCounter}/${this.maxCalls} calls). Increase via --llm-max-calls.`,
270
+ fromCache: false,
271
+ };
272
+ for (const i of missIndexes)
273
+ results[i] = err;
274
+ return results.map((r) => r);
275
+ }
276
+ const userPrompt = (0, prompt_1.buildBatchUserPrompt)(missInputs);
277
+ let sanitisedUserPrompt = userPrompt;
278
+ if (!this.skipGovernance) {
279
+ try {
280
+ this.log({ kind: "sanitise_start", bytes: userPrompt.length });
281
+ const sr = await this.governance.sanitiseCode(userPrompt);
282
+ sanitisedUserPrompt = sr.sanitised;
283
+ this.log({
284
+ kind: "sanitise_done",
285
+ bytes: sanitisedUserPrompt.length,
286
+ findings: sr.findings.length,
287
+ });
288
+ }
289
+ catch (err) {
290
+ const isUnreachable = err instanceof governanceClient_1.GovernanceUnreachableError;
291
+ const message = err instanceof Error ? err.message : String(err);
292
+ this.log({ kind: "error", phase: "governance", message });
293
+ const errResult = {
294
+ error: isUnreachable
295
+ ? `Governance sidecar unreachable; refusing to call LLM (fail-closed). ${message}`
296
+ : `Governance sanitise failed: ${message}`,
297
+ fromCache: false,
298
+ };
299
+ for (const i of missIndexes)
300
+ results[i] = errResult;
301
+ return results.map((r) => r);
302
+ }
303
+ }
304
+ if (!this.apiKey) {
305
+ const err = {
306
+ error: "OPENAI_API_KEY is not set; pass apiKey or set the env var.",
307
+ fromCache: false,
308
+ };
309
+ for (const i of missIndexes)
310
+ results[i] = err;
311
+ return results.map((r) => r);
312
+ }
313
+ const openai = await this.lazyClient();
314
+ if (!openai) {
315
+ const err = {
316
+ error: "openai SDK not installed. Run: npm install openai",
317
+ fromCache: false,
318
+ };
319
+ for (const i of missIndexes)
320
+ results[i] = err;
321
+ return results.map((r) => r);
322
+ }
323
+ let responseText = "";
324
+ this.attemptsCounter += 1;
325
+ try {
326
+ this.log({
327
+ kind: "provider_call_start",
328
+ model: this.model,
329
+ promptBytes: sanitisedUserPrompt.length,
330
+ });
331
+ const callStart = Date.now();
332
+ const maxTokens = Math.min(8192, 1024 + missInputs.length * 512);
333
+ const resp = await openai.chat.completions.create({
334
+ model: this.model,
335
+ max_tokens: maxTokens,
336
+ temperature: 0,
337
+ messages: [
338
+ { role: "system", content: prompt_1.SYSTEM_PROMPT },
339
+ { role: "user", content: sanitisedUserPrompt },
340
+ ],
341
+ }, { timeout: this.providerTimeoutMs });
342
+ this.callsCounter += 1;
343
+ const callLatency = Date.now() - callStart;
344
+ responseText = resp.choices?.[0]?.message?.content ?? "";
345
+ this.log({
346
+ kind: "provider_call_done",
347
+ model: this.model,
348
+ latencyMs: callLatency,
349
+ inputTokens: resp.usage?.prompt_tokens ?? 0,
350
+ outputTokens: resp.usage?.completion_tokens ?? 0,
351
+ });
352
+ }
353
+ catch (err) {
354
+ const message = err instanceof Error ? err.message : String(err);
355
+ this.log({ kind: "error", phase: "openai", message });
356
+ const errResult = {
357
+ error: `OpenAI API call failed: ${message}`,
358
+ fromCache: false,
359
+ };
360
+ for (const i of missIndexes)
361
+ results[i] = errResult;
362
+ return results.map((r) => r);
363
+ }
364
+ let parsedArray;
365
+ try {
366
+ let body = responseText.trim();
367
+ const fence = body.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/);
368
+ if (fence)
369
+ body = fence[1].trim();
370
+ const parsed = JSON.parse(body);
371
+ if (!Array.isArray(parsed))
372
+ throw new Error("expected a JSON array");
373
+ parsedArray = parsed;
374
+ }
375
+ catch (err) {
376
+ const message = err instanceof Error ? err.message : String(err);
377
+ this.log({ kind: "error", phase: "parse", message });
378
+ const errResult = {
379
+ error: `Could not parse JSON array from batch LLM output (first 200 chars): ${responseText.slice(0, 200)}`,
380
+ fromCache: false,
381
+ };
382
+ for (const i of missIndexes)
383
+ results[i] = errResult;
384
+ return results.map((r) => r);
385
+ }
386
+ for (let j = 0; j < missInputs.length; j++) {
387
+ const slotInput = missInputs[j];
388
+ const slotKey = missKeys[j];
389
+ const slotRaw = parsedArray[j];
390
+ const originalIdx = missIndexes[j];
391
+ if (slotRaw === undefined) {
392
+ results[originalIdx] = {
393
+ error: `Batch response missing entry for step ${j}: "${slotInput.step.text}"`,
394
+ fromCache: false,
395
+ };
396
+ continue;
397
+ }
398
+ const slotJson = JSON.stringify(slotRaw);
399
+ const binding = (0, anthropicClient_1.parseBindingJson)(slotJson, slotInput);
400
+ if (!binding) {
401
+ results[originalIdx] = {
402
+ error: `Could not parse binding for step ${j} ("${slotInput.step.text}"); slot was: ${slotJson.slice(0, 200)}`,
403
+ fromCache: false,
404
+ };
405
+ continue;
406
+ }
407
+ this.log({ kind: "binding_parsed", binding });
408
+ await cache.set(slotKey, {
409
+ binding,
410
+ model: this.model,
411
+ createdAt: new Date().toISOString(),
412
+ });
413
+ results[originalIdx] = {
414
+ binding,
415
+ fromCache: false,
416
+ model: this.model,
417
+ latencyMs: Date.now() - start,
418
+ };
419
+ }
420
+ return results.map((r) => r);
421
+ }
422
+ async lazyClient() {
423
+ if (this.openai)
424
+ return this.openai;
425
+ try {
426
+ // openai is in optionalDependencies. require() defensively so a
427
+ // teammate without the SDK installed gets a clean error instead
428
+ // of a module-load crash.
429
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
430
+ const mod = require("openai");
431
+ const OpenAI = mod.OpenAI ?? mod.default ?? mod;
432
+ this.openai = new OpenAI({ apiKey: this.apiKey });
433
+ return this.openai;
434
+ }
435
+ catch {
436
+ return null;
437
+ }
438
+ }
439
+ /**
440
+ * v4.0.0 — generic single-prompt text generation. Mirrors
441
+ * AnthropicLLMClient.generateText. Cache intentionally skipped;
442
+ * see that method for rationale.
443
+ */
444
+ async generateText(prompt) {
445
+ const start = Date.now();
446
+ if (this.budgetExhausted()) {
447
+ return {
448
+ error: `LLM budget exhausted (${this.callsCounter}/${this.maxCalls} calls). Increase via --llm-max-calls.`,
449
+ };
450
+ }
451
+ let sanitisedPrompt = prompt;
452
+ if (!this.skipGovernance) {
453
+ try {
454
+ this.log({ kind: "sanitise_start", bytes: prompt.length });
455
+ const result = await this.governance.sanitiseCode(prompt);
456
+ sanitisedPrompt = result.sanitised;
457
+ this.log({
458
+ kind: "sanitise_done",
459
+ bytes: sanitisedPrompt.length,
460
+ findings: result.findings.length,
461
+ });
462
+ }
463
+ catch (err) {
464
+ const isUnreachable = err instanceof governanceClient_1.GovernanceUnreachableError;
465
+ const message = err instanceof Error ? err.message : String(err);
466
+ this.log({ kind: "error", phase: "governance", message });
467
+ return {
468
+ error: isUnreachable
469
+ ? `Governance sidecar unreachable; refusing to call LLM (fail-closed). ${message}`
470
+ : `Governance sanitise failed: ${message}`,
471
+ };
472
+ }
473
+ }
474
+ if (!this.apiKey) {
475
+ return { error: "OPENAI_API_KEY is not set; pass apiKey or set the env var." };
476
+ }
477
+ const openai = await this.lazyClient();
478
+ if (!openai) {
479
+ return { error: "openai SDK not installed. Run: npm install openai" };
480
+ }
481
+ this.attemptsCounter += 1;
482
+ try {
483
+ this.log({
484
+ kind: "provider_call_start",
485
+ model: this.model,
486
+ promptBytes: sanitisedPrompt.length,
487
+ });
488
+ const callStart = Date.now();
489
+ const resp = await openai.chat.completions.create({
490
+ model: this.model,
491
+ max_tokens: 2048,
492
+ temperature: 0,
493
+ messages: [{ role: "user", content: sanitisedPrompt }],
494
+ }, { timeout: this.providerTimeoutMs });
495
+ this.callsCounter += 1;
496
+ const callLatency = Date.now() - callStart;
497
+ const text = resp.choices?.[0]?.message?.content ?? "";
498
+ const inputTokens = resp.usage?.prompt_tokens ?? 0;
499
+ const outputTokens = resp.usage?.completion_tokens ?? 0;
500
+ this.log({
501
+ kind: "provider_call_done",
502
+ model: this.model,
503
+ latencyMs: callLatency,
504
+ inputTokens,
505
+ outputTokens,
506
+ });
507
+ return {
508
+ text,
509
+ model: this.model,
510
+ latencyMs: Date.now() - start,
511
+ inputTokens,
512
+ outputTokens,
513
+ };
514
+ }
515
+ catch (err) {
516
+ const message = err instanceof Error ? err.message : String(err);
517
+ this.log({ kind: "error", phase: "openai", message });
518
+ return { error: `OpenAI API call failed: ${message}` };
519
+ }
520
+ }
521
+ async close() {
522
+ if (this.cache) {
523
+ await this.cache.close().catch(() => undefined);
524
+ this.cache = null;
525
+ }
526
+ }
527
+ }
528
+ exports.OpenAILLMClient = OpenAILLMClient;
529
+ //# sourceMappingURL=openaiClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openaiClient.js","sourceRoot":"","sources":["../../src/llm/openaiClient.ts"],"names":[],"mappings":"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"}
@@ -51,6 +51,20 @@ exports.DEFAULT_PRICING = {
51
51
  inputUsdPerMillion: 0.8,
52
52
  outputUsdPerMillion: 4,
53
53
  },
54
+ // OpenAI — v3.11.0 provider parity. Q4 2025 published pricing.
55
+ "gpt-4o": { inputUsdPerMillion: 2.5, outputUsdPerMillion: 10 },
56
+ "gpt-4o-mini": { inputUsdPerMillion: 0.15, outputUsdPerMillion: 0.6 },
57
+ "gpt-4-turbo": { inputUsdPerMillion: 10, outputUsdPerMillion: 30 },
58
+ o1: { inputUsdPerMillion: 15, outputUsdPerMillion: 60 },
59
+ "o1-mini": { inputUsdPerMillion: 3, outputUsdPerMillion: 12 },
60
+ "o1-preview": { inputUsdPerMillion: 15, outputUsdPerMillion: 60 },
61
+ // Google Gemini — v3.12.0 provider parity. Q4 2025 published pricing.
62
+ // Flash is the price/perf sweet spot for structured-JSON tasks.
63
+ "gemini-2.5-flash": { inputUsdPerMillion: 0.1, outputUsdPerMillion: 0.4 },
64
+ "gemini-2.5-pro": { inputUsdPerMillion: 1.25, outputUsdPerMillion: 5 },
65
+ "gemini-2.0-flash": { inputUsdPerMillion: 0.1, outputUsdPerMillion: 0.4 },
66
+ "gemini-1.5-flash": { inputUsdPerMillion: 0.075, outputUsdPerMillion: 0.3 },
67
+ "gemini-1.5-pro": { inputUsdPerMillion: 1.25, outputUsdPerMillion: 5 },
54
68
  };
55
69
  /**
56
70
  * Telemetry collector. One instance per scaffold call. Subscribe via