@momentiq/dark-factory-cli 0.1.0-alpha.4
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/LICENSE +201 -0
- package/README.md +150 -0
- package/dist/adapters/_shared.d.ts +45 -0
- package/dist/adapters/_shared.d.ts.map +1 -0
- package/dist/adapters/_shared.js +200 -0
- package/dist/adapters/_shared.js.map +1 -0
- package/dist/adapters/codex-sdk.d.ts +279 -0
- package/dist/adapters/codex-sdk.d.ts.map +1 -0
- package/dist/adapters/codex-sdk.js +930 -0
- package/dist/adapters/codex-sdk.js.map +1 -0
- package/dist/adapters/critic-result-schema.d.ts +215 -0
- package/dist/adapters/critic-result-schema.d.ts.map +1 -0
- package/dist/adapters/critic-result-schema.js +153 -0
- package/dist/adapters/critic-result-schema.js.map +1 -0
- package/dist/adapters/critic.d.ts +62 -0
- package/dist/adapters/critic.d.ts.map +1 -0
- package/dist/adapters/critic.js +79 -0
- package/dist/adapters/critic.js.map +1 -0
- package/dist/adapters/cursor-sdk.d.ts +153 -0
- package/dist/adapters/cursor-sdk.d.ts.map +1 -0
- package/dist/adapters/cursor-sdk.js +818 -0
- package/dist/adapters/cursor-sdk.js.map +1 -0
- package/dist/adapters/gemini-sdk.d.ts +113 -0
- package/dist/adapters/gemini-sdk.d.ts.map +1 -0
- package/dist/adapters/gemini-sdk.js +532 -0
- package/dist/adapters/gemini-sdk.js.map +1 -0
- package/dist/adapters/grok-direct-sdk.d.ts +148 -0
- package/dist/adapters/grok-direct-sdk.d.ts.map +1 -0
- package/dist/adapters/grok-direct-sdk.js +694 -0
- package/dist/adapters/grok-direct-sdk.js.map +1 -0
- package/dist/branch-protection/audit_branch_protection.py +759 -0
- package/dist/branch-protection/index.d.ts +25 -0
- package/dist/branch-protection/index.d.ts.map +1 -0
- package/dist/branch-protection/index.js +70 -0
- package/dist/branch-protection/index.js.map +1 -0
- package/dist/branch-protection/spec-default.yaml +314 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +581 -0
- package/dist/cli.js.map +1 -0
- package/dist/cycle-doc-validator/index.d.ts +43 -0
- package/dist/cycle-doc-validator/index.d.ts.map +1 -0
- package/dist/cycle-doc-validator/index.js +69 -0
- package/dist/cycle-doc-validator/index.js.map +1 -0
- package/dist/cycle-doc-validator/validate_cycle_doc.py +1260 -0
- package/dist/cycle-tracker-sync/attribute_pr_cycle_ref.py +384 -0
- package/dist/cycle-tracker-sync/index.d.ts +20 -0
- package/dist/cycle-tracker-sync/index.d.ts.map +1 -0
- package/dist/cycle-tracker-sync/index.js +71 -0
- package/dist/cycle-tracker-sync/index.js.map +1 -0
- package/dist/cycle-tracker-sync/sync_cycle_trackers.py +1093 -0
- package/dist/evidence/audit-trail.d.ts +59 -0
- package/dist/evidence/audit-trail.d.ts.map +1 -0
- package/dist/evidence/audit-trail.js +283 -0
- package/dist/evidence/audit-trail.js.map +1 -0
- package/dist/evidence/index.d.ts +4 -0
- package/dist/evidence/index.d.ts.map +1 -0
- package/dist/evidence/index.js +29 -0
- package/dist/evidence/index.js.map +1 -0
- package/dist/evidence/per-sha.d.ts +13 -0
- package/dist/evidence/per-sha.d.ts.map +1 -0
- package/dist/evidence/per-sha.js +97 -0
- package/dist/evidence/per-sha.js.map +1 -0
- package/dist/evidence/quality-gates.d.ts +19 -0
- package/dist/evidence/quality-gates.d.ts.map +1 -0
- package/dist/evidence/quality-gates.js +212 -0
- package/dist/evidence/quality-gates.js.map +1 -0
- package/dist/git.d.ts +40 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +414 -0
- package/dist/git.js.map +1 -0
- package/dist/glob.d.ts +4 -0
- package/dist/glob.d.ts.map +1 -0
- package/dist/glob.js +99 -0
- package/dist/glob.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +42 -0
- package/dist/paths.js.map +1 -0
- package/dist/policy/baseline.d.ts +15 -0
- package/dist/policy/baseline.d.ts.map +1 -0
- package/dist/policy/baseline.js +115 -0
- package/dist/policy/baseline.js.map +1 -0
- package/dist/policy/config.d.ts +64 -0
- package/dist/policy/config.d.ts.map +1 -0
- package/dist/policy/config.js +363 -0
- package/dist/policy/config.js.map +1 -0
- package/dist/policy/gate.d.ts +80 -0
- package/dist/policy/gate.d.ts.map +1 -0
- package/dist/policy/gate.js +1019 -0
- package/dist/policy/gate.js.map +1 -0
- package/dist/policy/index.d.ts +7 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +14 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/merge-queue.d.ts +183 -0
- package/dist/policy/merge-queue.d.ts.map +1 -0
- package/dist/policy/merge-queue.js +310 -0
- package/dist/policy/merge-queue.js.map +1 -0
- package/dist/policy/profile.d.ts +98 -0
- package/dist/policy/profile.d.ts.map +1 -0
- package/dist/policy/profile.js +156 -0
- package/dist/policy/profile.js.map +1 -0
- package/dist/policy/tdd-classifier.d.ts +18 -0
- package/dist/policy/tdd-classifier.d.ts.map +1 -0
- package/dist/policy/tdd-classifier.js +79 -0
- package/dist/policy/tdd-classifier.js.map +1 -0
- package/dist/prompt.d.ts +13 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +175 -0
- package/dist/prompt.js.map +1 -0
- package/dist/report.d.ts +88 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +376 -0
- package/dist/report.js.map +1 -0
- package/dist/runner.d.ts +30 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +456 -0
- package/dist/runner.js.map +1 -0
- package/dist/security.d.ts +2 -0
- package/dist/security.d.ts.map +1 -0
- package/dist/security.js +19 -0
- package/dist/security.js.map +1 -0
- package/dist/trusted-surface/rebind.d.ts +10 -0
- package/dist/trusted-surface/rebind.d.ts.map +1 -0
- package/dist/trusted-surface/rebind.js +154 -0
- package/dist/trusted-surface/rebind.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
// Cycle 322.2 — Gemini direct-API adapter via `@google/genai`.
|
|
2
|
+
//
|
|
3
|
+
// Why a second adapter (manifesto §11): a single critic shares all of its
|
|
4
|
+
// blind spots with itself. Adding a second critic on a different vendor
|
|
5
|
+
// lineage (Google Gemini ≠ OpenAI/Cursor) is the literal §11 implementation:
|
|
6
|
+
// the disagreements between the two critics are the value, even when they
|
|
7
|
+
// agree most of the time. This adapter ships in shadow mode (`required:
|
|
8
|
+
// false` in `.agent-review/config.json`) so its findings are informational
|
|
9
|
+
// during the calibration window before 322.3's `min-complete-quorum` policy
|
|
10
|
+
// promotes the multi-critic config to default.
|
|
11
|
+
//
|
|
12
|
+
// The adapter:
|
|
13
|
+
// - implements `CriticAdapter` from `critic.ts` (post-Component-3
|
|
14
|
+
// migration, which adds `requiredEnvVars`)
|
|
15
|
+
// - mirrors the 322.1 retry shape (`runRetryLoop` + `attemptReview`)
|
|
16
|
+
// from a single source of truth in `cursor-sdk.ts`, so the policy +
|
|
17
|
+
// budget are byte-identical across adapters and any future fix lands
|
|
18
|
+
// in one place
|
|
19
|
+
// - routes diagnostic-redaction + JSON parsing + reviewer-metadata merge
|
|
20
|
+
// + error-result construction through `_shared.ts` so the security
|
|
21
|
+
// boundary (redactSecrets at the only writeFileSync site) cannot drift
|
|
22
|
+
// - is read-only by structure: no `tools` / function-calling configured;
|
|
23
|
+
// the only output channel is the JSON response itself (so a malicious
|
|
24
|
+
// diff convincing the model to "run a command" has no command surface)
|
|
25
|
+
// - guards the chunk `text` getter with try/catch — Gemini stream
|
|
26
|
+
// chunks can be safety-filtered or empty payloads where the
|
|
27
|
+
// getter throws
|
|
28
|
+
//
|
|
29
|
+
// The implementation deliberately uses the dependency-injection ESCAPE
|
|
30
|
+
// hatch on the constructor (`createClient` factory) so unit tests can
|
|
31
|
+
// supply a mock GoogleGenAI without forcing the SDK to be present at test
|
|
32
|
+
// time — this matches the testing posture of the cycle 322.1 retry tests.
|
|
33
|
+
import { ApiError, GoogleGenAI, } from "@google/genai";
|
|
34
|
+
import { compileCriticPrompt } from "../prompt.js";
|
|
35
|
+
import { parseCriticResult, } from "@momentiq/dark-factory-schemas";
|
|
36
|
+
import { buildErrorResult, mergeAdapterMetadata, normalizeCriticEcho, parseAssistantJson, writeRedactedDiagnostic, } from "./_shared.js";
|
|
37
|
+
import { runRetryLoop, } from "./cursor-sdk.js";
|
|
38
|
+
export const GEMINI_SDK_ADAPTER_ID = "gemini-sdk";
|
|
39
|
+
export const GEMINI_API_KEY_ENV = "GEMINI_API_KEY";
|
|
40
|
+
// Default thinking-token budget when the critic config does not specify one.
|
|
41
|
+
// 32k is enough headroom for a deep review of a typical PR diff while
|
|
42
|
+
// staying well under the model's max thinking budget. Operators can override
|
|
43
|
+
// per-critic via `critic.model.params: [{ id: "thinkingBudget", value: 65536 }]`.
|
|
44
|
+
//
|
|
45
|
+
// Setting `thinkingBudget = 0` would disable Gemini thinking entirely; that
|
|
46
|
+
// is intentionally allowed (cost optimization for cheap-pass critics) but
|
|
47
|
+
// not the default.
|
|
48
|
+
export const DEFAULT_THINKING_BUDGET = 32_768;
|
|
49
|
+
// Gemini API permanent failures by HTTP status. The classification is
|
|
50
|
+
// derived from Google's API contract:
|
|
51
|
+
// 400 INVALID_ARGUMENT — bad request shape, model name typo
|
|
52
|
+
// 401 / 403 — auth failure
|
|
53
|
+
// 404 NOT_FOUND — model id not in caller's project
|
|
54
|
+
// 429 RESOURCE_EXHAUSTED — quota / rate-limit (retrying within 20s
|
|
55
|
+
// burns budget; surface immediately so the
|
|
56
|
+
// operator can investigate)
|
|
57
|
+
// Anything else (5xx, 504, transient network) is retryable. The retry
|
|
58
|
+
// budget is bounded by `runRetryLoop` to 2 retries / 20s wall-clock.
|
|
59
|
+
export const GEMINI_PERMANENT_STATUS = new Set([
|
|
60
|
+
400,
|
|
61
|
+
401,
|
|
62
|
+
403,
|
|
63
|
+
404,
|
|
64
|
+
429,
|
|
65
|
+
]);
|
|
66
|
+
/**
|
|
67
|
+
* Resolve the Gemini thinking budget from the critic config's
|
|
68
|
+
* `model.params`. Falls back to {@link DEFAULT_THINKING_BUDGET} when
|
|
69
|
+
* unset. Coerces string/number inputs (config schema allows both).
|
|
70
|
+
*
|
|
71
|
+
* Negative or non-finite values are treated as "use default" — Gemini
|
|
72
|
+
* accepts 0 (disabled) and -1 (automatic) as sentinels, so the helper
|
|
73
|
+
* preserves those exact values; anything else outside [0, +Infinity)
|
|
74
|
+
* falls back to the default rather than corrupting the request.
|
|
75
|
+
*
|
|
76
|
+
* Exported for direct unit testing (no SDK mock required).
|
|
77
|
+
*/
|
|
78
|
+
export function resolveThinkingBudget(critic) {
|
|
79
|
+
const param = critic.model.params.find((p) => p.id === "thinkingBudget");
|
|
80
|
+
if (!param)
|
|
81
|
+
return DEFAULT_THINKING_BUDGET;
|
|
82
|
+
const v = param.value;
|
|
83
|
+
let n;
|
|
84
|
+
if (typeof v === "number")
|
|
85
|
+
n = v;
|
|
86
|
+
else if (typeof v === "string")
|
|
87
|
+
n = Number(v);
|
|
88
|
+
else if (typeof v === "boolean")
|
|
89
|
+
return DEFAULT_THINKING_BUDGET; // boolean is meaningless here
|
|
90
|
+
else
|
|
91
|
+
return DEFAULT_THINKING_BUDGET;
|
|
92
|
+
if (!Number.isFinite(n))
|
|
93
|
+
return DEFAULT_THINKING_BUDGET;
|
|
94
|
+
// Gemini sentinel values: 0 = disabled, -1 = automatic. Preserve them.
|
|
95
|
+
if (n === 0 || n === -1)
|
|
96
|
+
return n;
|
|
97
|
+
// Anything below -1 is an operator typo (e.g., -32768). Fall back to default.
|
|
98
|
+
if (n < 0)
|
|
99
|
+
return DEFAULT_THINKING_BUDGET;
|
|
100
|
+
return Math.floor(n);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Probe a thrown error for a Gemini API HTTP status code. Returns `null`
|
|
104
|
+
* when the error didn't carry one (network error, non-API exception).
|
|
105
|
+
* Exported for direct unit testing.
|
|
106
|
+
*
|
|
107
|
+
* The SDK throws `ApiError extends Error` with a `status: number`
|
|
108
|
+
* field; a non-API failure (DNS, timeout in fetch, etc.) won't have this
|
|
109
|
+
* field set. Treating "no status" as retryable lets the loop catch real
|
|
110
|
+
* transient blips while not silently retrying logic errors.
|
|
111
|
+
*/
|
|
112
|
+
export function extractApiErrorStatus(err) {
|
|
113
|
+
if (!err || typeof err !== "object")
|
|
114
|
+
return null;
|
|
115
|
+
const e = err;
|
|
116
|
+
// Direct property on the SDK's ApiError class
|
|
117
|
+
if (typeof e["status"] === "number")
|
|
118
|
+
return e["status"];
|
|
119
|
+
// Some SDK error shapes nest it under `error.code`
|
|
120
|
+
const inner = e["error"];
|
|
121
|
+
if (inner && typeof inner === "object") {
|
|
122
|
+
const code = inner["code"];
|
|
123
|
+
if (typeof code === "number")
|
|
124
|
+
return code;
|
|
125
|
+
}
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Policy gate: decide whether a Gemini SDK failure is retryable.
|
|
130
|
+
* Returns `false` for HTTP statuses in {@link GEMINI_PERMANENT_STATUS},
|
|
131
|
+
* `true` otherwise (including no-status network errors).
|
|
132
|
+
*
|
|
133
|
+
* Exported for direct unit testing.
|
|
134
|
+
*/
|
|
135
|
+
export function isGeminiPermanentFailure(status) {
|
|
136
|
+
if (status === null)
|
|
137
|
+
return false; // no status → treat as transient
|
|
138
|
+
return GEMINI_PERMANENT_STATUS.has(status);
|
|
139
|
+
}
|
|
140
|
+
export class GeminiSdkAdapter {
|
|
141
|
+
options;
|
|
142
|
+
id = GEMINI_SDK_ADAPTER_ID;
|
|
143
|
+
requiredEnvVars = [GEMINI_API_KEY_ENV];
|
|
144
|
+
createClient;
|
|
145
|
+
constructor(options = {}) {
|
|
146
|
+
this.options = options;
|
|
147
|
+
this.createClient =
|
|
148
|
+
options.createClient ??
|
|
149
|
+
((apiKey) => new GoogleGenAI({ apiKey }));
|
|
150
|
+
}
|
|
151
|
+
async review(packet, critic, options) {
|
|
152
|
+
return runRetryLoop({
|
|
153
|
+
attempt: (idx) => this.attemptReview(packet, critic, options, idx),
|
|
154
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
155
|
+
...(this.options.sleep !== undefined ? { sleep: this.options.sleep } : {}),
|
|
156
|
+
buildExhausted: ({ last, totalAttempts, aborted }) => {
|
|
157
|
+
const retriesUsed = Math.max(0, totalAttempts - 1);
|
|
158
|
+
const summary = aborted
|
|
159
|
+
? last
|
|
160
|
+
? `gemini SDK run aborted after ${retriesUsed} retries: ${last.message}`
|
|
161
|
+
: "gemini SDK run aborted before any attempt completed"
|
|
162
|
+
: last
|
|
163
|
+
? `gemini SDK run failed after ${retriesUsed} retries: ${last.message}`
|
|
164
|
+
: "gemini SDK run failed with no captured failure metadata";
|
|
165
|
+
return buildErrorResult({
|
|
166
|
+
critic,
|
|
167
|
+
message: summary,
|
|
168
|
+
retryable: true,
|
|
169
|
+
...(last?.errorCode != null ? { code: last.errorCode } : {}),
|
|
170
|
+
retryCount: retriesUsed,
|
|
171
|
+
});
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
// One attempt. Mirrors `CursorSdkAdapter.attemptReview` shape so the
|
|
176
|
+
// outer retry loop dispatches identically; differences are
|
|
177
|
+
// Gemini-specific (no agentId/runId, JSON-only responseMimeType,
|
|
178
|
+
// thinkingConfig) and surface here.
|
|
179
|
+
async attemptReview(packet, critic, options, attemptIdx) {
|
|
180
|
+
const apiKey = this.options.apiKey ?? process.env[GEMINI_API_KEY_ENV];
|
|
181
|
+
if (!apiKey) {
|
|
182
|
+
// Missing key is permanent — no retry can fix a missing secret.
|
|
183
|
+
return {
|
|
184
|
+
kind: "permanent_failure",
|
|
185
|
+
errorCode: null,
|
|
186
|
+
statusMessage: null,
|
|
187
|
+
result: buildErrorResult({
|
|
188
|
+
critic,
|
|
189
|
+
message: `${GEMINI_API_KEY_ENV} is not set; cannot run Gemini critic`,
|
|
190
|
+
retryable: false,
|
|
191
|
+
retryCount: attemptIdx,
|
|
192
|
+
}),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const prompt = compileCriticPrompt({
|
|
196
|
+
packet,
|
|
197
|
+
critic,
|
|
198
|
+
blockingSeverities: options.blockingSeverities,
|
|
199
|
+
treatDiffAsUntrusted: true,
|
|
200
|
+
});
|
|
201
|
+
const startMs = Date.now();
|
|
202
|
+
if (attemptIdx === 0) {
|
|
203
|
+
options.emit?.({
|
|
204
|
+
ts: new Date().toISOString(),
|
|
205
|
+
event: "critic_run_started",
|
|
206
|
+
commit: packet.commit.sha,
|
|
207
|
+
criticId: critic.id,
|
|
208
|
+
adapter: this.id,
|
|
209
|
+
model: critic.model.id,
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
const client = this.createClient(apiKey);
|
|
213
|
+
const thinkingBudget = resolveThinkingBudget(critic);
|
|
214
|
+
let assistantText = "";
|
|
215
|
+
let lastUsage;
|
|
216
|
+
let blockReason;
|
|
217
|
+
try {
|
|
218
|
+
const stream = await client.models.generateContentStream({
|
|
219
|
+
model: critic.model.id,
|
|
220
|
+
contents: [{ role: "user", parts: [{ text: prompt.text }] }],
|
|
221
|
+
config: {
|
|
222
|
+
...(options.signal !== undefined ? { abortSignal: options.signal } : {}),
|
|
223
|
+
temperature: 0,
|
|
224
|
+
responseMimeType: "application/json",
|
|
225
|
+
thinkingConfig: { thinkingBudget },
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
for await (const chunk of stream) {
|
|
229
|
+
if (options.signal?.aborted)
|
|
230
|
+
break;
|
|
231
|
+
// Guard the .text getter — for safety-blocked or empty chunks it
|
|
232
|
+
// can throw on the real SDK. The structured `candidates` path is
|
|
233
|
+
// the fallback.
|
|
234
|
+
try {
|
|
235
|
+
const t = chunk.text;
|
|
236
|
+
if (typeof t === "string" && t.length > 0) {
|
|
237
|
+
assistantText += t;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
// fall through to structured-extraction path
|
|
242
|
+
}
|
|
243
|
+
const candidates = chunk.candidates;
|
|
244
|
+
if (Array.isArray(candidates)) {
|
|
245
|
+
for (const cand of candidates) {
|
|
246
|
+
const parts = cand.content?.parts;
|
|
247
|
+
if (!Array.isArray(parts))
|
|
248
|
+
continue;
|
|
249
|
+
for (const part of parts) {
|
|
250
|
+
if (typeof part.text === "string") {
|
|
251
|
+
// Avoid double-counting if `.text` already worked above.
|
|
252
|
+
if (!assistantText.endsWith(part.text)) {
|
|
253
|
+
assistantText += part.text;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const usage = chunk.usageMetadata;
|
|
260
|
+
if (usage)
|
|
261
|
+
lastUsage = usage;
|
|
262
|
+
const feedback = chunk.promptFeedback;
|
|
263
|
+
if (feedback?.blockReason && !blockReason)
|
|
264
|
+
blockReason = feedback.blockReason;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
const e = err;
|
|
269
|
+
const status = err instanceof ApiError ? err.status : extractApiErrorStatus(err);
|
|
270
|
+
const permanent = isGeminiPermanentFailure(status);
|
|
271
|
+
const codeStr = status !== null ? `http_${status}` : "transport_error";
|
|
272
|
+
options.emit?.({
|
|
273
|
+
ts: new Date().toISOString(),
|
|
274
|
+
event: "critic_run_error",
|
|
275
|
+
commit: packet.commit.sha,
|
|
276
|
+
criticId: critic.id,
|
|
277
|
+
adapter: this.id,
|
|
278
|
+
model: critic.model.id,
|
|
279
|
+
durationMs: Date.now() - startMs,
|
|
280
|
+
error: e.message,
|
|
281
|
+
status: permanent ? "run_failure_permanent" : "run_failure",
|
|
282
|
+
retryCount: attemptIdx,
|
|
283
|
+
errorCode: codeStr,
|
|
284
|
+
});
|
|
285
|
+
if (permanent) {
|
|
286
|
+
return {
|
|
287
|
+
kind: "permanent_failure",
|
|
288
|
+
errorCode: codeStr,
|
|
289
|
+
statusMessage: null,
|
|
290
|
+
result: buildErrorResult({
|
|
291
|
+
critic,
|
|
292
|
+
message: `gemini SDK run failed (permanent, status=${status ?? "?"}): ${e.message}`,
|
|
293
|
+
retryable: false,
|
|
294
|
+
code: codeStr,
|
|
295
|
+
retryCount: attemptIdx,
|
|
296
|
+
}),
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return {
|
|
300
|
+
kind: "retryable_failure",
|
|
301
|
+
errorCode: codeStr,
|
|
302
|
+
statusMessage: null,
|
|
303
|
+
message: `gemini SDK run failed: ${e.message}`,
|
|
304
|
+
runId: null,
|
|
305
|
+
agentId: null,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
if (blockReason) {
|
|
309
|
+
// Safety filter blocked the response BEFORE any text was produced.
|
|
310
|
+
// Treat as permanent — retrying with the same prompt re-trips the
|
|
311
|
+
// same filter.
|
|
312
|
+
const msg = `gemini critic response blocked by safety filter: ${blockReason}`;
|
|
313
|
+
options.emit?.({
|
|
314
|
+
ts: new Date().toISOString(),
|
|
315
|
+
event: "critic_run_error",
|
|
316
|
+
commit: packet.commit.sha,
|
|
317
|
+
criticId: critic.id,
|
|
318
|
+
adapter: this.id,
|
|
319
|
+
model: critic.model.id,
|
|
320
|
+
durationMs: Date.now() - startMs,
|
|
321
|
+
error: msg,
|
|
322
|
+
status: "safety_blocked",
|
|
323
|
+
retryCount: attemptIdx,
|
|
324
|
+
errorCode: "safety_blocked",
|
|
325
|
+
});
|
|
326
|
+
return {
|
|
327
|
+
kind: "permanent_failure",
|
|
328
|
+
errorCode: "safety_blocked",
|
|
329
|
+
statusMessage: null,
|
|
330
|
+
result: buildErrorResult({
|
|
331
|
+
critic,
|
|
332
|
+
message: msg,
|
|
333
|
+
retryable: false,
|
|
334
|
+
code: "safety_blocked",
|
|
335
|
+
retryCount: attemptIdx,
|
|
336
|
+
}),
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
const parseOutcome = parseAssistantJson(assistantText);
|
|
340
|
+
if (!parseOutcome.ok) {
|
|
341
|
+
const diagPath = writeRedactedDiagnostic({
|
|
342
|
+
diagnosticsDir: options.diagnosticsDir,
|
|
343
|
+
criticId: critic.id,
|
|
344
|
+
commit: packet.commit.sha,
|
|
345
|
+
rawText: assistantText,
|
|
346
|
+
});
|
|
347
|
+
options.emit?.({
|
|
348
|
+
ts: new Date().toISOString(),
|
|
349
|
+
event: "critic_run_error",
|
|
350
|
+
commit: packet.commit.sha,
|
|
351
|
+
criticId: critic.id,
|
|
352
|
+
adapter: this.id,
|
|
353
|
+
model: critic.model.id,
|
|
354
|
+
durationMs: Date.now() - startMs,
|
|
355
|
+
error: `invalid critic JSON: ${parseOutcome.message}`,
|
|
356
|
+
status: "invalid_json",
|
|
357
|
+
retryCount: attemptIdx,
|
|
358
|
+
});
|
|
359
|
+
return {
|
|
360
|
+
kind: "permanent_failure",
|
|
361
|
+
errorCode: null,
|
|
362
|
+
statusMessage: null,
|
|
363
|
+
result: buildErrorResult({
|
|
364
|
+
critic,
|
|
365
|
+
message: `gemini critic returned invalid JSON: ${parseOutcome.message}`,
|
|
366
|
+
retryable: false,
|
|
367
|
+
...(diagPath !== undefined ? { rawSamplePath: diagPath } : {}),
|
|
368
|
+
retryCount: attemptIdx,
|
|
369
|
+
}),
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
let result;
|
|
373
|
+
try {
|
|
374
|
+
// Drop schema-invalid `validation.qualityGateResults[]` entries
|
|
375
|
+
// (e.g. model emits `gate` instead of `command`) BEFORE strict
|
|
376
|
+
// parsing — the validation block is informational and gets
|
|
377
|
+
// overwritten below with deterministic packet evidence. Issue #1484.
|
|
378
|
+
const normalized = normalizeCriticEcho(parseOutcome.value);
|
|
379
|
+
const enriched = mergeAdapterMetadata(normalized, { critic });
|
|
380
|
+
result = parseCriticResult(enriched, options.blockingSeverities);
|
|
381
|
+
}
|
|
382
|
+
catch (err) {
|
|
383
|
+
const e = err;
|
|
384
|
+
const diagPath = writeRedactedDiagnostic({
|
|
385
|
+
diagnosticsDir: options.diagnosticsDir,
|
|
386
|
+
criticId: critic.id,
|
|
387
|
+
commit: packet.commit.sha,
|
|
388
|
+
rawText: assistantText,
|
|
389
|
+
});
|
|
390
|
+
options.emit?.({
|
|
391
|
+
ts: new Date().toISOString(),
|
|
392
|
+
event: "critic_run_error",
|
|
393
|
+
commit: packet.commit.sha,
|
|
394
|
+
criticId: critic.id,
|
|
395
|
+
adapter: this.id,
|
|
396
|
+
model: critic.model.id,
|
|
397
|
+
durationMs: Date.now() - startMs,
|
|
398
|
+
error: `schema validation failed: ${e.message}`,
|
|
399
|
+
status: "schema_violation",
|
|
400
|
+
retryCount: attemptIdx,
|
|
401
|
+
});
|
|
402
|
+
return {
|
|
403
|
+
kind: "permanent_failure",
|
|
404
|
+
errorCode: null,
|
|
405
|
+
statusMessage: null,
|
|
406
|
+
result: buildErrorResult({
|
|
407
|
+
critic,
|
|
408
|
+
message: `gemini critic JSON failed schema validation: ${e.message}`,
|
|
409
|
+
retryable: false,
|
|
410
|
+
...(diagPath !== undefined ? { rawSamplePath: diagPath } : {}),
|
|
411
|
+
retryCount: attemptIdx,
|
|
412
|
+
}),
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
const durationMs = Date.now() - startMs;
|
|
416
|
+
// Replace the critic's echoed validation block with the deterministic
|
|
417
|
+
// packet evidence (same posture as the Cursor adapter).
|
|
418
|
+
const enriched = {
|
|
419
|
+
...result,
|
|
420
|
+
durationMs,
|
|
421
|
+
validation: {
|
|
422
|
+
qualityGateResults: packet.validation.evidence,
|
|
423
|
+
qualityGatesMissing: packet.validation.missing,
|
|
424
|
+
},
|
|
425
|
+
};
|
|
426
|
+
const blockerCount = enriched.findings.filter((f) => f.severity === "blocker").length;
|
|
427
|
+
const highCount = enriched.findings.filter((f) => f.severity === "high").length;
|
|
428
|
+
options.emit?.({
|
|
429
|
+
ts: new Date().toISOString(),
|
|
430
|
+
event: "critic_run_finished",
|
|
431
|
+
commit: packet.commit.sha,
|
|
432
|
+
criticId: critic.id,
|
|
433
|
+
adapter: this.id,
|
|
434
|
+
model: critic.model.id,
|
|
435
|
+
durationMs,
|
|
436
|
+
...(enriched.verdict !== undefined ? { verdict: enriched.verdict } : {}),
|
|
437
|
+
findingCount: enriched.findings.length,
|
|
438
|
+
blockerCount,
|
|
439
|
+
highCount,
|
|
440
|
+
...(typeof lastUsage?.promptTokenCount === "number"
|
|
441
|
+
? { tokensIn: lastUsage.promptTokenCount }
|
|
442
|
+
: {}),
|
|
443
|
+
...(typeof lastUsage?.candidatesTokenCount === "number"
|
|
444
|
+
? { tokensOut: lastUsage.candidatesTokenCount }
|
|
445
|
+
: {}),
|
|
446
|
+
status: "complete",
|
|
447
|
+
retryCount: attemptIdx,
|
|
448
|
+
});
|
|
449
|
+
return { kind: "success", result: enriched };
|
|
450
|
+
}
|
|
451
|
+
async doctor(critic) {
|
|
452
|
+
const checks = [];
|
|
453
|
+
const apiKey = this.options.apiKey ?? process.env[GEMINI_API_KEY_ENV];
|
|
454
|
+
checks.push({
|
|
455
|
+
name: "gemini_api_key",
|
|
456
|
+
passed: Boolean(apiKey),
|
|
457
|
+
detail: apiKey ? `${GEMINI_API_KEY_ENV} present` : `${GEMINI_API_KEY_ENV} missing`,
|
|
458
|
+
...(apiKey
|
|
459
|
+
? {}
|
|
460
|
+
: {
|
|
461
|
+
remediation: `export ${GEMINI_API_KEY_ENV}=... or add it to the Doppler scope (sage/dev)`,
|
|
462
|
+
}),
|
|
463
|
+
});
|
|
464
|
+
let sdkLoaded = false;
|
|
465
|
+
try {
|
|
466
|
+
// The dynamic import path catches both "package missing on disk" and
|
|
467
|
+
// "package present but no exports we recognize" (older shape) cases.
|
|
468
|
+
const mod = (await import("@google/genai"));
|
|
469
|
+
sdkLoaded = typeof mod["GoogleGenAI"] === "function";
|
|
470
|
+
}
|
|
471
|
+
catch {
|
|
472
|
+
sdkLoaded = false;
|
|
473
|
+
}
|
|
474
|
+
checks.push({
|
|
475
|
+
name: "gemini_sdk_loaded",
|
|
476
|
+
passed: sdkLoaded,
|
|
477
|
+
detail: sdkLoaded
|
|
478
|
+
? "@google/genai imported"
|
|
479
|
+
: "@google/genai missing or shape unexpected",
|
|
480
|
+
...(sdkLoaded
|
|
481
|
+
? {}
|
|
482
|
+
: { remediation: "make agent-review-deps && make agent-review-build" }),
|
|
483
|
+
});
|
|
484
|
+
if (!sdkLoaded || !apiKey)
|
|
485
|
+
return checks;
|
|
486
|
+
// Verify the configured model id resolves via models.list(). The Gemini
|
|
487
|
+
// model-version churn (gemini-3-pro-preview → gemini-3.1-pro-preview →
|
|
488
|
+
// gemini-3.1-pro GA) makes this check load-bearing — without it, a
|
|
489
|
+
// first-run after a model rotation would fail at review time with a
|
|
490
|
+
// less-actionable HTTP 404.
|
|
491
|
+
try {
|
|
492
|
+
const client = this.createClient(apiKey);
|
|
493
|
+
const list = client.models.list;
|
|
494
|
+
if (typeof list !== "function") {
|
|
495
|
+
checks.push({
|
|
496
|
+
name: "gemini_model_listing",
|
|
497
|
+
passed: false,
|
|
498
|
+
detail: "@google/genai models.list not exposed; cannot verify model id",
|
|
499
|
+
remediation: "Run `make agent-review-spike-gemini` (source at tools/agent-review/src/spikes/gemini-models-list-2026-05.ts) and confirm the configured id is current.",
|
|
500
|
+
});
|
|
501
|
+
return checks;
|
|
502
|
+
}
|
|
503
|
+
const models = await list({});
|
|
504
|
+
const ids = [];
|
|
505
|
+
for await (const m of models) {
|
|
506
|
+
if (typeof m.name === "string")
|
|
507
|
+
ids.push(m.name);
|
|
508
|
+
}
|
|
509
|
+
const matched = ids.some((n) => n === critic.model.id || n.endsWith(`/${critic.model.id}`));
|
|
510
|
+
checks.push({
|
|
511
|
+
name: "gemini_model_id",
|
|
512
|
+
passed: matched,
|
|
513
|
+
detail: matched
|
|
514
|
+
? `model ${critic.model.id} available`
|
|
515
|
+
: `model ${critic.model.id} not in available list (${ids.slice(0, 8).join(", ")}${ids.length > 8 ? "..." : ""})`,
|
|
516
|
+
...(matched
|
|
517
|
+
? {}
|
|
518
|
+
: { remediation: "update .agent-review/config.json critic.model.id (see tools/agent-review/evals/spike-gemini-models-2026-05.md or run `make agent-review-spike-gemini` to refresh)" }),
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
catch (err) {
|
|
522
|
+
checks.push({
|
|
523
|
+
name: "gemini_model_id",
|
|
524
|
+
passed: false,
|
|
525
|
+
detail: `models.list() failed: ${err.message}`,
|
|
526
|
+
remediation: `verify ${GEMINI_API_KEY_ENV} and network connectivity`,
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
return checks;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
//# sourceMappingURL=gemini-sdk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-sdk.js","sourceRoot":"","sources":["../../src/adapters/gemini-sdk.ts"],"names":[],"mappings":"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"}
|