@vijaypjavvadi/bdd2pw 3.9.0 → 3.12.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.
- package/CHANGELOG.md +245 -0
- package/README.md +13 -10
- package/dist/cli.js +40 -7
- package/dist/cli.js.map +1 -1
- package/dist/llm/geminiClient.d.ts +86 -0
- package/dist/llm/geminiClient.js +472 -0
- package/dist/llm/geminiClient.js.map +1 -0
- package/dist/llm/index.d.ts +2 -0
- package/dist/llm/index.js +13 -2
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/openaiClient.d.ts +77 -0
- package/dist/llm/openaiClient.js +447 -0
- package/dist/llm/openaiClient.js.map +1 -0
- package/dist/llm/telemetry.js +14 -0
- package/dist/llm/telemetry.js.map +1 -1
- package/dist/llm/types.d.ts +9 -2
- package/dist/reports/healStats.d.ts +132 -0
- package/dist/reports/healStats.js +303 -0
- package/dist/reports/healStats.js.map +1 -0
- package/dist/types.d.ts +2 -1
- package/package.json +3 -1
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Gemini LLM client — v3.12.0.
|
|
4
|
+
*
|
|
5
|
+
* Implements the same `LLMClient` interface as `AnthropicLLMClient` and
|
|
6
|
+
* `OpenAILLMClient`: single-step `generateBinding`, batched
|
|
7
|
+
* `generateBatchBindings`, cache hit accounting, budget tracking,
|
|
8
|
+
* governance sanitisation, step deadlines, provider timeouts.
|
|
9
|
+
*
|
|
10
|
+
* SDK-shape differences from Anthropic / OpenAI:
|
|
11
|
+
*
|
|
12
|
+
* Anthropic OpenAI Gemini
|
|
13
|
+
* -------------------------------- ------------------------------ ------------------------------------
|
|
14
|
+
* anthropic.messages.create({ openai.chat.completions.create({ model.generateContent({
|
|
15
|
+
* system: SYSTEM_PROMPT, messages: [ systemInstruction: SYSTEM_PROMPT,
|
|
16
|
+
* messages: [ { role: 'system', ... }, contents: [
|
|
17
|
+
* { role: 'user', content } { role: 'user', ... } { role: 'user',
|
|
18
|
+
* ] ] parts: [{ text: prompt }] }
|
|
19
|
+
* }) }) ]
|
|
20
|
+
* })
|
|
21
|
+
*
|
|
22
|
+
* resp.content[0].text resp.choices[0].message.content resp.response.text()
|
|
23
|
+
* resp.usage.input_tokens resp.usage.prompt_tokens resp.response.usageMetadata.promptTokenCount
|
|
24
|
+
* resp.usage.output_tokens resp.usage.completion_tokens resp.response.usageMetadata.candidatesTokenCount
|
|
25
|
+
*
|
|
26
|
+
* The prompt machinery (`SYSTEM_PROMPT`, `buildUserPrompt`,
|
|
27
|
+
* `buildBatchUserPrompt`, `cacheKey`), the parser (`parseBindingJson`),
|
|
28
|
+
* the cache (`openSqliteCache`), and the governance client are shared
|
|
29
|
+
* with the other two providers. Cache keys include the model name —
|
|
30
|
+
* cross-provider hits only fire when the model strings match.
|
|
31
|
+
*
|
|
32
|
+
* Default model: `gemini-2.5-flash`. Reasoning: bdd2pw's task is
|
|
33
|
+
* structured JSON output over regex-shaped deterministic patterns.
|
|
34
|
+
* Flash handles it reliably and runs even cheaper than gpt-4o-mini.
|
|
35
|
+
* Override via `LLMClientOptions.model`.
|
|
36
|
+
*
|
|
37
|
+
* Note on JSON output: Gemini's structured-output mode would let us
|
|
38
|
+
* request a JSON schema directly. We deliberately don't — the prompt
|
|
39
|
+
* already constrains the response shape, and going through the same
|
|
40
|
+
* text-then-parse pipeline as the other providers keeps the
|
|
41
|
+
* parseBindingJson behavior provider-agnostic.
|
|
42
|
+
*/
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.GeminiLLMClient = void 0;
|
|
45
|
+
const cache_1 = require("./cache");
|
|
46
|
+
const governanceClient_1 = require("./governanceClient");
|
|
47
|
+
const prompt_1 = require("./prompt");
|
|
48
|
+
const anthropicClient_1 = require("./anthropicClient");
|
|
49
|
+
const DEFAULT_MODEL = "gemini-2.5-flash";
|
|
50
|
+
const DEFAULT_MAX_CALLS = 50;
|
|
51
|
+
const DEFAULT_GOVERNANCE_URL = "http://localhost:4900";
|
|
52
|
+
const DEFAULT_PROVIDER_TIMEOUT_MS = 30000;
|
|
53
|
+
const DEFAULT_GOVERNANCE_TIMEOUT_MS = 15000;
|
|
54
|
+
class GeminiLLMClient {
|
|
55
|
+
constructor(opts, cachePathDefault) {
|
|
56
|
+
this.cache = null;
|
|
57
|
+
this.callsCounter = 0;
|
|
58
|
+
this.attemptsCounter = 0;
|
|
59
|
+
this.genai = null;
|
|
60
|
+
this.modelHandle = null;
|
|
61
|
+
this.cachePersistent = null;
|
|
62
|
+
this.model = opts.model ?? DEFAULT_MODEL;
|
|
63
|
+
this.apiKey = opts.apiKey ?? process.env.GEMINI_API_KEY ?? process.env.GOOGLE_API_KEY ?? "";
|
|
64
|
+
this.maxCalls = opts.maxCalls ?? DEFAULT_MAX_CALLS;
|
|
65
|
+
this.skipGovernance = opts.skipGovernance ?? false;
|
|
66
|
+
this.log = opts.log ?? (() => { });
|
|
67
|
+
this.providerTimeoutMs =
|
|
68
|
+
opts.providerTimeoutMs ?? DEFAULT_PROVIDER_TIMEOUT_MS;
|
|
69
|
+
this.governance = new governanceClient_1.GovernanceClient(opts.governanceUrl ?? DEFAULT_GOVERNANCE_URL, opts.governanceTimeoutMs ?? DEFAULT_GOVERNANCE_TIMEOUT_MS);
|
|
70
|
+
this.cachePath = opts.cachePath ?? cachePathDefault;
|
|
71
|
+
}
|
|
72
|
+
async ensureCache() {
|
|
73
|
+
if (!this.cache) {
|
|
74
|
+
const result = await (0, cache_1.openSqliteCache)(this.cachePath);
|
|
75
|
+
this.cache = result.cache;
|
|
76
|
+
this.cachePersistent = result.persistent;
|
|
77
|
+
this.cacheFallbackReason = result.fallbackReason;
|
|
78
|
+
if (!result.persistent && result.fallbackReason) {
|
|
79
|
+
this.log({ kind: "cache_fallback", reason: result.fallbackReason });
|
|
80
|
+
this.log({
|
|
81
|
+
kind: "error",
|
|
82
|
+
phase: "cache_load",
|
|
83
|
+
message: `Cache backend unavailable, falling back to in-memory for this run. Reason: ${result.fallbackReason}`,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return this.cache;
|
|
88
|
+
}
|
|
89
|
+
budgetExhausted() {
|
|
90
|
+
return this.attemptsCounter >= this.maxCalls;
|
|
91
|
+
}
|
|
92
|
+
callsMade() {
|
|
93
|
+
return this.callsCounter;
|
|
94
|
+
}
|
|
95
|
+
callsAttempted() {
|
|
96
|
+
return this.attemptsCounter;
|
|
97
|
+
}
|
|
98
|
+
cacheBackendPersistent() {
|
|
99
|
+
return this.cachePersistent;
|
|
100
|
+
}
|
|
101
|
+
cacheBackendFallbackReason() {
|
|
102
|
+
return this.cacheFallbackReason;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Single-step generation. Cache → governance → Gemini → parse.
|
|
106
|
+
* Mirrors `AnthropicLLMClient.generateBinding` and `OpenAILLMClient.generateBinding`.
|
|
107
|
+
*/
|
|
108
|
+
async generateBinding(input) {
|
|
109
|
+
const start = Date.now();
|
|
110
|
+
const key = (0, prompt_1.cacheKey)(input, this.model);
|
|
111
|
+
const cache = await this.ensureCache();
|
|
112
|
+
const hit = await cache.get(key);
|
|
113
|
+
if (hit) {
|
|
114
|
+
this.log({ kind: "cache_hit", key });
|
|
115
|
+
return {
|
|
116
|
+
binding: hit.binding,
|
|
117
|
+
fromCache: true,
|
|
118
|
+
model: hit.model,
|
|
119
|
+
latencyMs: Date.now() - start,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
this.log({ kind: "cache_miss", key });
|
|
123
|
+
if (this.budgetExhausted()) {
|
|
124
|
+
return {
|
|
125
|
+
error: `LLM budget exhausted (${this.callsCounter}/${this.maxCalls} calls). Increase via --llm-max-calls.`,
|
|
126
|
+
fromCache: false,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
const userPrompt = (0, prompt_1.buildUserPrompt)(input);
|
|
130
|
+
let sanitisedUserPrompt = userPrompt;
|
|
131
|
+
if (!this.skipGovernance) {
|
|
132
|
+
try {
|
|
133
|
+
this.log({ kind: "sanitise_start", bytes: userPrompt.length });
|
|
134
|
+
const result = await this.governance.sanitiseCode(userPrompt);
|
|
135
|
+
sanitisedUserPrompt = result.sanitised;
|
|
136
|
+
this.log({
|
|
137
|
+
kind: "sanitise_done",
|
|
138
|
+
bytes: sanitisedUserPrompt.length,
|
|
139
|
+
findings: result.findings.length,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
const isUnreachable = err instanceof governanceClient_1.GovernanceUnreachableError;
|
|
144
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
145
|
+
this.log({ kind: "error", phase: "governance", message });
|
|
146
|
+
return {
|
|
147
|
+
error: isUnreachable
|
|
148
|
+
? `Governance sidecar unreachable; refusing to call LLM (fail-closed). ${message}`
|
|
149
|
+
: `Governance sanitise failed: ${message}`,
|
|
150
|
+
fromCache: false,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!this.apiKey) {
|
|
155
|
+
return {
|
|
156
|
+
error: "GEMINI_API_KEY (or GOOGLE_API_KEY) is not set; pass apiKey or set the env var.",
|
|
157
|
+
fromCache: false,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
const model = await this.lazyModel();
|
|
161
|
+
if (!model) {
|
|
162
|
+
return {
|
|
163
|
+
error: "@google/generative-ai SDK not installed. Run: npm install @google/generative-ai",
|
|
164
|
+
fromCache: false,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
let responseText = "";
|
|
168
|
+
let inputTokens = 0;
|
|
169
|
+
let outputTokens = 0;
|
|
170
|
+
this.attemptsCounter += 1;
|
|
171
|
+
try {
|
|
172
|
+
this.log({
|
|
173
|
+
kind: "provider_call_start",
|
|
174
|
+
model: this.model,
|
|
175
|
+
promptBytes: sanitisedUserPrompt.length,
|
|
176
|
+
});
|
|
177
|
+
const callStart = Date.now();
|
|
178
|
+
// Gemini's generateContent does not take a timeout option. We race
|
|
179
|
+
// against a setTimeout-driven deadline via withTimeout. The SDK's
|
|
180
|
+
// public type is not exported in a stable namespace, so we cast
|
|
181
|
+
// to a structural type for the fields we actually read.
|
|
182
|
+
const result = (await this.withTimeout(model.generateContent({
|
|
183
|
+
contents: [{ role: "user", parts: [{ text: sanitisedUserPrompt }] }],
|
|
184
|
+
generationConfig: { temperature: 0, maxOutputTokens: 1024 },
|
|
185
|
+
}), this.providerTimeoutMs));
|
|
186
|
+
this.callsCounter += 1;
|
|
187
|
+
const callLatency = Date.now() - callStart;
|
|
188
|
+
// response.text() is the canonical accessor.
|
|
189
|
+
responseText = typeof result?.response?.text === "function"
|
|
190
|
+
? result.response.text()
|
|
191
|
+
: "";
|
|
192
|
+
const usage = result?.response?.usageMetadata ?? {};
|
|
193
|
+
inputTokens = usage.promptTokenCount ?? 0;
|
|
194
|
+
outputTokens = usage.candidatesTokenCount ?? 0;
|
|
195
|
+
this.log({
|
|
196
|
+
kind: "provider_call_done",
|
|
197
|
+
model: this.model,
|
|
198
|
+
latencyMs: callLatency,
|
|
199
|
+
inputTokens,
|
|
200
|
+
outputTokens,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
205
|
+
this.log({ kind: "error", phase: "gemini", message });
|
|
206
|
+
return {
|
|
207
|
+
error: `Gemini API call failed: ${message}`,
|
|
208
|
+
fromCache: false,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
const binding = (0, anthropicClient_1.parseBindingJson)(responseText, input);
|
|
212
|
+
if (!binding) {
|
|
213
|
+
this.log({
|
|
214
|
+
kind: "error",
|
|
215
|
+
phase: "parse",
|
|
216
|
+
message: `Could not parse JSON binding from LLM output: ${responseText.slice(0, 200)}`,
|
|
217
|
+
});
|
|
218
|
+
return {
|
|
219
|
+
error: `Could not parse JSON binding from LLM output (first 200 chars): ${responseText.slice(0, 200)}`,
|
|
220
|
+
fromCache: false,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
this.log({ kind: "binding_parsed", binding });
|
|
224
|
+
await cache.set(key, {
|
|
225
|
+
binding,
|
|
226
|
+
model: this.model,
|
|
227
|
+
createdAt: new Date().toISOString(),
|
|
228
|
+
});
|
|
229
|
+
return {
|
|
230
|
+
binding,
|
|
231
|
+
fromCache: false,
|
|
232
|
+
model: this.model,
|
|
233
|
+
latencyMs: Date.now() - start,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Batched generation — same per-step cache lookup + single batched
|
|
238
|
+
* prompt as the Anthropic / OpenAI clients. JSON array response
|
|
239
|
+
* parsed slot by slot through `parseBindingJson`.
|
|
240
|
+
*/
|
|
241
|
+
async generateBatchBindings(inputs) {
|
|
242
|
+
if (inputs.length === 0)
|
|
243
|
+
return [];
|
|
244
|
+
const start = Date.now();
|
|
245
|
+
const cache = await this.ensureCache();
|
|
246
|
+
const results = new Array(inputs.length);
|
|
247
|
+
const missIndexes = [];
|
|
248
|
+
const missInputs = [];
|
|
249
|
+
const missKeys = [];
|
|
250
|
+
for (let i = 0; i < inputs.length; i++) {
|
|
251
|
+
const key = (0, prompt_1.cacheKey)(inputs[i], this.model);
|
|
252
|
+
const hit = await cache.get(key);
|
|
253
|
+
if (hit) {
|
|
254
|
+
this.log({ kind: "cache_hit", key });
|
|
255
|
+
results[i] = {
|
|
256
|
+
binding: hit.binding,
|
|
257
|
+
fromCache: true,
|
|
258
|
+
model: hit.model,
|
|
259
|
+
latencyMs: Date.now() - start,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
this.log({ kind: "cache_miss", key });
|
|
264
|
+
missIndexes.push(i);
|
|
265
|
+
missInputs.push(inputs[i]);
|
|
266
|
+
missKeys.push(key);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (missInputs.length === 0) {
|
|
270
|
+
return results.map((r) => r);
|
|
271
|
+
}
|
|
272
|
+
if (this.budgetExhausted()) {
|
|
273
|
+
const err = {
|
|
274
|
+
error: `LLM budget exhausted (${this.callsCounter}/${this.maxCalls} calls). Increase via --llm-max-calls.`,
|
|
275
|
+
fromCache: false,
|
|
276
|
+
};
|
|
277
|
+
for (const i of missIndexes)
|
|
278
|
+
results[i] = err;
|
|
279
|
+
return results.map((r) => r);
|
|
280
|
+
}
|
|
281
|
+
const userPrompt = (0, prompt_1.buildBatchUserPrompt)(missInputs);
|
|
282
|
+
let sanitisedUserPrompt = userPrompt;
|
|
283
|
+
if (!this.skipGovernance) {
|
|
284
|
+
try {
|
|
285
|
+
this.log({ kind: "sanitise_start", bytes: userPrompt.length });
|
|
286
|
+
const sr = await this.governance.sanitiseCode(userPrompt);
|
|
287
|
+
sanitisedUserPrompt = sr.sanitised;
|
|
288
|
+
this.log({
|
|
289
|
+
kind: "sanitise_done",
|
|
290
|
+
bytes: sanitisedUserPrompt.length,
|
|
291
|
+
findings: sr.findings.length,
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
const isUnreachable = err instanceof governanceClient_1.GovernanceUnreachableError;
|
|
296
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
297
|
+
this.log({ kind: "error", phase: "governance", message });
|
|
298
|
+
const errResult = {
|
|
299
|
+
error: isUnreachable
|
|
300
|
+
? `Governance sidecar unreachable; refusing to call LLM (fail-closed). ${message}`
|
|
301
|
+
: `Governance sanitise failed: ${message}`,
|
|
302
|
+
fromCache: false,
|
|
303
|
+
};
|
|
304
|
+
for (const i of missIndexes)
|
|
305
|
+
results[i] = errResult;
|
|
306
|
+
return results.map((r) => r);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (!this.apiKey) {
|
|
310
|
+
const err = {
|
|
311
|
+
error: "GEMINI_API_KEY (or GOOGLE_API_KEY) is not set; pass apiKey or set the env var.",
|
|
312
|
+
fromCache: false,
|
|
313
|
+
};
|
|
314
|
+
for (const i of missIndexes)
|
|
315
|
+
results[i] = err;
|
|
316
|
+
return results.map((r) => r);
|
|
317
|
+
}
|
|
318
|
+
const model = await this.lazyModel();
|
|
319
|
+
if (!model) {
|
|
320
|
+
const err = {
|
|
321
|
+
error: "@google/generative-ai SDK not installed. Run: npm install @google/generative-ai",
|
|
322
|
+
fromCache: false,
|
|
323
|
+
};
|
|
324
|
+
for (const i of missIndexes)
|
|
325
|
+
results[i] = err;
|
|
326
|
+
return results.map((r) => r);
|
|
327
|
+
}
|
|
328
|
+
let responseText = "";
|
|
329
|
+
this.attemptsCounter += 1;
|
|
330
|
+
try {
|
|
331
|
+
this.log({
|
|
332
|
+
kind: "provider_call_start",
|
|
333
|
+
model: this.model,
|
|
334
|
+
promptBytes: sanitisedUserPrompt.length,
|
|
335
|
+
});
|
|
336
|
+
const callStart = Date.now();
|
|
337
|
+
const maxTokens = Math.min(8192, 1024 + missInputs.length * 512);
|
|
338
|
+
const result = (await this.withTimeout(model.generateContent({
|
|
339
|
+
contents: [{ role: "user", parts: [{ text: sanitisedUserPrompt }] }],
|
|
340
|
+
generationConfig: { temperature: 0, maxOutputTokens: maxTokens },
|
|
341
|
+
}), this.providerTimeoutMs));
|
|
342
|
+
this.callsCounter += 1;
|
|
343
|
+
const callLatency = Date.now() - callStart;
|
|
344
|
+
responseText = typeof result?.response?.text === "function"
|
|
345
|
+
? result.response.text()
|
|
346
|
+
: "";
|
|
347
|
+
const usage = result?.response?.usageMetadata ?? {};
|
|
348
|
+
this.log({
|
|
349
|
+
kind: "provider_call_done",
|
|
350
|
+
model: this.model,
|
|
351
|
+
latencyMs: callLatency,
|
|
352
|
+
inputTokens: usage.promptTokenCount ?? 0,
|
|
353
|
+
outputTokens: usage.candidatesTokenCount ?? 0,
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
catch (err) {
|
|
357
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
358
|
+
this.log({ kind: "error", phase: "gemini", message });
|
|
359
|
+
const errResult = {
|
|
360
|
+
error: `Gemini API call failed: ${message}`,
|
|
361
|
+
fromCache: false,
|
|
362
|
+
};
|
|
363
|
+
for (const i of missIndexes)
|
|
364
|
+
results[i] = errResult;
|
|
365
|
+
return results.map((r) => r);
|
|
366
|
+
}
|
|
367
|
+
let parsedArray;
|
|
368
|
+
try {
|
|
369
|
+
let body = responseText.trim();
|
|
370
|
+
const fence = body.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/);
|
|
371
|
+
if (fence)
|
|
372
|
+
body = fence[1].trim();
|
|
373
|
+
const parsed = JSON.parse(body);
|
|
374
|
+
if (!Array.isArray(parsed))
|
|
375
|
+
throw new Error("expected a JSON array");
|
|
376
|
+
parsedArray = parsed;
|
|
377
|
+
}
|
|
378
|
+
catch (err) {
|
|
379
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
380
|
+
this.log({ kind: "error", phase: "parse", message });
|
|
381
|
+
const errResult = {
|
|
382
|
+
error: `Could not parse JSON array from batch LLM output (first 200 chars): ${responseText.slice(0, 200)}`,
|
|
383
|
+
fromCache: false,
|
|
384
|
+
};
|
|
385
|
+
for (const i of missIndexes)
|
|
386
|
+
results[i] = errResult;
|
|
387
|
+
return results.map((r) => r);
|
|
388
|
+
}
|
|
389
|
+
for (let j = 0; j < missInputs.length; j++) {
|
|
390
|
+
const slotInput = missInputs[j];
|
|
391
|
+
const slotKey = missKeys[j];
|
|
392
|
+
const slotRaw = parsedArray[j];
|
|
393
|
+
const originalIdx = missIndexes[j];
|
|
394
|
+
if (slotRaw === undefined) {
|
|
395
|
+
results[originalIdx] = {
|
|
396
|
+
error: `Batch response missing entry for step ${j}: "${slotInput.step.text}"`,
|
|
397
|
+
fromCache: false,
|
|
398
|
+
};
|
|
399
|
+
continue;
|
|
400
|
+
}
|
|
401
|
+
const slotJson = JSON.stringify(slotRaw);
|
|
402
|
+
const binding = (0, anthropicClient_1.parseBindingJson)(slotJson, slotInput);
|
|
403
|
+
if (!binding) {
|
|
404
|
+
results[originalIdx] = {
|
|
405
|
+
error: `Could not parse binding for step ${j} ("${slotInput.step.text}"); slot was: ${slotJson.slice(0, 200)}`,
|
|
406
|
+
fromCache: false,
|
|
407
|
+
};
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
this.log({ kind: "binding_parsed", binding });
|
|
411
|
+
await cache.set(slotKey, {
|
|
412
|
+
binding,
|
|
413
|
+
model: this.model,
|
|
414
|
+
createdAt: new Date().toISOString(),
|
|
415
|
+
});
|
|
416
|
+
results[originalIdx] = {
|
|
417
|
+
binding,
|
|
418
|
+
fromCache: false,
|
|
419
|
+
model: this.model,
|
|
420
|
+
latencyMs: Date.now() - start,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
return results.map((r) => r);
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Wraps a promise with a deadline. Gemini's generateContent has no
|
|
427
|
+
* native timeout option (unlike Anthropic/OpenAI SDKs), so we race
|
|
428
|
+
* the SDK call against a setTimeout.
|
|
429
|
+
*/
|
|
430
|
+
async withTimeout(p, ms) {
|
|
431
|
+
let timer;
|
|
432
|
+
const timeout = new Promise((_, reject) => {
|
|
433
|
+
timer = setTimeout(() => reject(new Error(`Gemini call exceeded ${ms}ms timeout`)), ms);
|
|
434
|
+
});
|
|
435
|
+
try {
|
|
436
|
+
return await Promise.race([p, timeout]);
|
|
437
|
+
}
|
|
438
|
+
finally {
|
|
439
|
+
if (timer)
|
|
440
|
+
clearTimeout(timer);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
async lazyModel() {
|
|
444
|
+
if (this.modelHandle)
|
|
445
|
+
return this.modelHandle;
|
|
446
|
+
try {
|
|
447
|
+
// @google/generative-ai is in optionalDependencies. require()
|
|
448
|
+
// defensively so a teammate without the SDK installed gets a
|
|
449
|
+
// clean error instead of a module-load crash.
|
|
450
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
451
|
+
const mod = require("@google/generative-ai");
|
|
452
|
+
const GoogleGenerativeAI = mod.GoogleGenerativeAI ?? mod.default ?? mod;
|
|
453
|
+
this.genai = new GoogleGenerativeAI(this.apiKey);
|
|
454
|
+
this.modelHandle = this.genai.getGenerativeModel({
|
|
455
|
+
model: this.model,
|
|
456
|
+
systemInstruction: prompt_1.SYSTEM_PROMPT,
|
|
457
|
+
});
|
|
458
|
+
return this.modelHandle;
|
|
459
|
+
}
|
|
460
|
+
catch {
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
async close() {
|
|
465
|
+
if (this.cache) {
|
|
466
|
+
await this.cache.close().catch(() => undefined);
|
|
467
|
+
this.cache = null;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
exports.GeminiLLMClient = GeminiLLMClient;
|
|
472
|
+
//# sourceMappingURL=geminiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geminiClient.js","sourceRoot":"","sources":["../../src/llm/geminiClient.ts"],"names":[],"mappings":"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"}
|
package/dist/llm/index.d.ts
CHANGED
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { LLMClient, LLMClientOptions } from "./types";
|
|
11
11
|
export { AnthropicLLMClient } from "./anthropicClient";
|
|
12
|
+
export { OpenAILLMClient } from "./openaiClient";
|
|
13
|
+
export { GeminiLLMClient } from "./geminiClient";
|
|
12
14
|
export { CandidateRulesWriter } from "./candidateRules";
|
|
13
15
|
export { proposeRules, fingerprint, synthesiseRegex, type ProposeRulesOptions, type ProposeRulesResult, } from "./proposeRules";
|
|
14
16
|
export { LLMTelemetry, DEFAULT_PRICING, type TelemetryCall, type TelemetrySummary, } from "./telemetry";
|
package/dist/llm/index.js
CHANGED
|
@@ -42,12 +42,18 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
42
42
|
};
|
|
43
43
|
})();
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
-
exports.matchScenarioWithLLM = exports.matchStepsWithLLM = exports.matchStepWithLLM = exports.GovernanceUnreachableError = exports.GovernanceClient = exports.DEFAULT_PRICING = exports.LLMTelemetry = exports.synthesiseRegex = exports.fingerprint = exports.proposeRules = exports.CandidateRulesWriter = exports.AnthropicLLMClient = void 0;
|
|
45
|
+
exports.matchScenarioWithLLM = exports.matchStepsWithLLM = exports.matchStepWithLLM = exports.GovernanceUnreachableError = exports.GovernanceClient = exports.DEFAULT_PRICING = exports.LLMTelemetry = exports.synthesiseRegex = exports.fingerprint = exports.proposeRules = exports.CandidateRulesWriter = exports.GeminiLLMClient = exports.OpenAILLMClient = exports.AnthropicLLMClient = void 0;
|
|
46
46
|
exports.createLLMClient = createLLMClient;
|
|
47
47
|
const path = __importStar(require("path"));
|
|
48
48
|
const anthropicClient_1 = require("./anthropicClient");
|
|
49
|
+
const openaiClient_1 = require("./openaiClient");
|
|
50
|
+
const geminiClient_1 = require("./geminiClient");
|
|
49
51
|
var anthropicClient_2 = require("./anthropicClient");
|
|
50
52
|
Object.defineProperty(exports, "AnthropicLLMClient", { enumerable: true, get: function () { return anthropicClient_2.AnthropicLLMClient; } });
|
|
53
|
+
var openaiClient_2 = require("./openaiClient");
|
|
54
|
+
Object.defineProperty(exports, "OpenAILLMClient", { enumerable: true, get: function () { return openaiClient_2.OpenAILLMClient; } });
|
|
55
|
+
var geminiClient_2 = require("./geminiClient");
|
|
56
|
+
Object.defineProperty(exports, "GeminiLLMClient", { enumerable: true, get: function () { return geminiClient_2.GeminiLLMClient; } });
|
|
51
57
|
var candidateRules_1 = require("./candidateRules");
|
|
52
58
|
Object.defineProperty(exports, "CandidateRulesWriter", { enumerable: true, get: function () { return candidateRules_1.CandidateRulesWriter; } });
|
|
53
59
|
var proposeRules_1 = require("./proposeRules");
|
|
@@ -83,8 +89,13 @@ function createLLMClient(opts, repoRoot) {
|
|
|
83
89
|
switch (opts.provider) {
|
|
84
90
|
case "anthropic":
|
|
85
91
|
return new anthropicClient_1.AnthropicLLMClient(opts, cachePathDefault);
|
|
92
|
+
case "openai":
|
|
93
|
+
// v3.11.0 — full parity (cache, governance, batching, telemetry).
|
|
94
|
+
return new openaiClient_1.OpenAILLMClient(opts, cachePathDefault);
|
|
95
|
+
case "gemini":
|
|
96
|
+
// v3.12.0 — full parity. Default model gemini-2.5-flash.
|
|
97
|
+
return new geminiClient_1.GeminiLLMClient(opts, cachePathDefault);
|
|
86
98
|
default:
|
|
87
|
-
// v2.1 will add openai / gemini.
|
|
88
99
|
return undefined;
|
|
89
100
|
}
|
|
90
101
|
}
|
package/dist/llm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/llm/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDH,0CAsBC;AAzED,2CAA6B;AAC7B,uDAAuD;AACvD,iDAAiD;AACjD,iDAAiD;AAGjD,qDAAuD;AAA9C,qHAAA,kBAAkB,OAAA;AAC3B,+CAAiD;AAAxC,+GAAA,eAAe,OAAA;AACxB,+CAAiD;AAAxC,+GAAA,eAAe,OAAA;AACxB,mDAAwD;AAA/C,sHAAA,oBAAoB,OAAA;AAC7B,+CAMwB;AALtB,4GAAA,YAAY,OAAA;AACZ,2GAAA,WAAW,OAAA;AACX,+GAAA,eAAe,OAAA;AAIjB,yCAKqB;AAJnB,yGAAA,YAAY,OAAA;AACZ,4GAAA,eAAe,OAAA;AAIjB,uDAAkF;AAAzE,oHAAA,gBAAgB,OAAA;AAAE,8HAAA,0BAA0B,OAAA;AACrD,mDAK0B;AAJxB,kHAAA,gBAAgB,OAAA;AAChB,mHAAA,iBAAiB,OAAA;AACjB,sHAAA,oBAAoB,OAAA;AAYtB;;;;;;;;;;;GAWG;AACH,SAAgB,eAAe,CAC7B,IAAkC,EAClC,QAAgB;IAEhB,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC9C,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAChC,QAAQ,EACR,SAAS,EACT,kBAAkB,CACnB,CAAC;IACF,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QACtB,KAAK,WAAW;YACd,OAAO,IAAI,oCAAkB,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QACxD,KAAK,QAAQ;YACX,kEAAkE;YAClE,OAAO,IAAI,8BAAe,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QACrD,KAAK,QAAQ;YACX,yDAAyD;YACzD,OAAO,IAAI,8BAAe,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;QACrD;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
close(): Promise<void>;
|
|
77
|
+
}
|