@brutalist/mcp 1.11.2 → 1.13.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/dist/brutalist-server.js +1 -1
- package/dist/cli-adapters/claude-adapter.d.ts +12 -2
- package/dist/cli-adapters/claude-adapter.d.ts.map +1 -1
- package/dist/cli-adapters/claude-adapter.js +175 -38
- package/dist/cli-adapters/claude-adapter.js.map +1 -1
- package/dist/cli-adapters/codex-adapter.d.ts +18 -1
- package/dist/cli-adapters/codex-adapter.d.ts.map +1 -1
- package/dist/cli-adapters/codex-adapter.js +86 -3
- package/dist/cli-adapters/codex-adapter.js.map +1 -1
- package/dist/cli-adapters/gemini-adapter.d.ts +22 -1
- package/dist/cli-adapters/gemini-adapter.d.ts.map +1 -1
- package/dist/cli-adapters/gemini-adapter.js +100 -3
- package/dist/cli-adapters/gemini-adapter.js.map +1 -1
- package/dist/cli-adapters/index.d.ts +55 -9
- package/dist/cli-adapters/index.d.ts.map +1 -1
- package/dist/cli-adapters/index.js.map +1 -1
- package/dist/cli-agents.d.ts.map +1 -1
- package/dist/cli-agents.js +53 -56
- package/dist/cli-agents.js.map +1 -1
- package/dist/mcp-registry.d.ts +48 -4
- package/dist/mcp-registry.d.ts.map +1 -1
- package/dist/mcp-registry.js +92 -12
- package/dist/mcp-registry.js.map +1 -1
- package/package.json +1 -1
|
@@ -171,11 +171,75 @@ export class GeminiAdapter {
|
|
|
171
171
|
* Parses a single JSON object and returns the `response` field.
|
|
172
172
|
*/
|
|
173
173
|
decodeOutput(rawOutput, args, log) {
|
|
174
|
-
//
|
|
174
|
+
// Legacy text-only API.
|
|
175
|
+
const result = this.decode(rawOutput, '', args, log);
|
|
176
|
+
return result.kind === 'ok' ? result.text : '';
|
|
177
|
+
}
|
|
178
|
+
decode(stdout, stderr, args, log) {
|
|
179
|
+
// Only structured-decode if Gemini was run with --output-format json
|
|
175
180
|
if (!(args.includes('--output-format') && args.includes('json'))) {
|
|
176
|
-
return
|
|
181
|
+
return { kind: 'ok', text: stdout };
|
|
182
|
+
}
|
|
183
|
+
return this.decodeJson(stdout, stderr, log ?? rootLogger);
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Structured decode of Gemini --output-format json output.
|
|
187
|
+
*
|
|
188
|
+
* Gemini exits 0 on quota and bakes the refusal text into the
|
|
189
|
+
* `response` field itself — there is no envelope-level signal in the
|
|
190
|
+
* stdout JSON to distinguish a real answer from a refusal. So:
|
|
191
|
+
* - parse stdout; non-empty `response` → ok (best-effort; we can't
|
|
192
|
+
* tell the difference here without prose matching, which we
|
|
193
|
+
* explicitly refuse to do)
|
|
194
|
+
* - empty/missing `response`, or unparseable stdout, AND stderr
|
|
195
|
+
* matches anchored Google API quota markers → refused (quota)
|
|
196
|
+
* - empty + no anchored markers → error (empty/malformed)
|
|
197
|
+
*
|
|
198
|
+
* Per the user direction for Phase 2: anchored stderr markers only.
|
|
199
|
+
* No fallback to loose patterns. The honest residual is that a
|
|
200
|
+
* gemini quota that prints ONLY to `response` (no stderr signal)
|
|
201
|
+
* passes through as a normal response — surfaced to the caller as
|
|
202
|
+
* agent output. That is documented and accepted.
|
|
203
|
+
*/
|
|
204
|
+
decodeJson(jsonOutput, stderr, log) {
|
|
205
|
+
if (!jsonOutput || !jsonOutput.trim()) {
|
|
206
|
+
// Stdout empty — check stderr for anchored quota markers before
|
|
207
|
+
// declaring this an empty error.
|
|
208
|
+
if (classifyGeminiStderrReason(stderr) === 'quota') {
|
|
209
|
+
return { kind: 'refused', reason: 'quota' };
|
|
210
|
+
}
|
|
211
|
+
log.debug('extractGeminiResponse: empty input');
|
|
212
|
+
return { kind: 'error', reason: 'empty' };
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const parsed = JSON.parse(jsonOutput);
|
|
216
|
+
if (parsed.response && typeof parsed.response === 'string') {
|
|
217
|
+
log.info(`✅ extractGeminiResponse: extracted response with ${parsed.response.length} chars`);
|
|
218
|
+
return { kind: 'ok', text: parsed.response };
|
|
219
|
+
}
|
|
220
|
+
log.warn('extractGeminiResponse: no response field in JSON output', {
|
|
221
|
+
keys: Object.keys(parsed)
|
|
222
|
+
});
|
|
223
|
+
// No response field — check anchored stderr markers before
|
|
224
|
+
// treating as error.
|
|
225
|
+
if (classifyGeminiStderrReason(stderr) === 'quota') {
|
|
226
|
+
return { kind: 'refused', reason: 'quota' };
|
|
227
|
+
}
|
|
228
|
+
return { kind: 'error', reason: 'empty' };
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
// Redacted: raw jsonOutput is never emitted — only its length plus
|
|
232
|
+
// the parse error reason. Prevents prompt / response leakage
|
|
233
|
+
// through log aggregators.
|
|
234
|
+
log.warn('extractGeminiResponse: failed to parse JSON', {
|
|
235
|
+
error: e instanceof Error ? e.message : String(e),
|
|
236
|
+
length: jsonOutput.length
|
|
237
|
+
});
|
|
238
|
+
if (classifyGeminiStderrReason(stderr) === 'quota') {
|
|
239
|
+
return { kind: 'refused', reason: 'quota' };
|
|
240
|
+
}
|
|
241
|
+
return { kind: 'error', reason: 'malformed' };
|
|
177
242
|
}
|
|
178
|
-
return this.extractGeminiResponse(rawOutput, log ?? rootLogger);
|
|
179
243
|
}
|
|
180
244
|
extractGeminiResponse(jsonOutput, log) {
|
|
181
245
|
if (!jsonOutput || !jsonOutput.trim()) {
|
|
@@ -205,4 +269,37 @@ export class GeminiAdapter {
|
|
|
205
269
|
}
|
|
206
270
|
}
|
|
207
271
|
}
|
|
272
|
+
/**
|
|
273
|
+
* Classify Gemini stderr against anchored Google API quota markers.
|
|
274
|
+
* Operates only on stderr, never on the `response` field or any other
|
|
275
|
+
* assistant-author surface.
|
|
276
|
+
*
|
|
277
|
+
* Anchored markers chosen against the literal strings Google's API and
|
|
278
|
+
* gemini-cli surface on quota:
|
|
279
|
+
* - "RESOURCE_EXHAUSTED" — gRPC / Google API status code
|
|
280
|
+
* - "Quota exceeded for quota metric" — Google API canonical phrase
|
|
281
|
+
* - "Quota exhausted" — alt phrasing
|
|
282
|
+
* - "rateLimitExceeded" — Google API error reason
|
|
283
|
+
* - "userRateLimitExceeded" — per-user variant
|
|
284
|
+
* - "429" — HTTP status
|
|
285
|
+
*
|
|
286
|
+
* No loose `rate limit` / `usage limit` / `plan.*limit` patterns. The
|
|
287
|
+
* known residual: a quota state that prints only to gemini's `response`
|
|
288
|
+
* field (no stderr signal) passes through as a normal answer. We
|
|
289
|
+
* document and accept that — gemini's protocol gives us no honest way
|
|
290
|
+
* to distinguish that case from a real reply.
|
|
291
|
+
*/
|
|
292
|
+
function classifyGeminiStderrReason(stderr) {
|
|
293
|
+
if (!stderr)
|
|
294
|
+
return 'unknown';
|
|
295
|
+
const markers = [
|
|
296
|
+
/RESOURCE_EXHAUSTED/,
|
|
297
|
+
/Quota exceeded for quota metric/i,
|
|
298
|
+
/Quota exhausted/i,
|
|
299
|
+
/rateLimitExceeded/i,
|
|
300
|
+
/userRateLimitExceeded/i,
|
|
301
|
+
/\b429\b/,
|
|
302
|
+
];
|
|
303
|
+
return markers.some((p) => p.test(stderr)) ? 'quota' : 'unknown';
|
|
304
|
+
}
|
|
208
305
|
//# sourceMappingURL=gemini-adapter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini-adapter.js","sourceRoot":"","sources":["../../src/cli-adapters/gemini-adapter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"gemini-adapter.js","sourceRoot":"","sources":["../../src/cli-adapters/gemini-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,6 +34,34 @@ export interface CLIBuilderConfig {
|
|
|
34
34
|
mpcEnvCleanup?: string[];
|
|
35
35
|
mcpSupport?: MCPSupportConfig;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Structured outcome of decoding a CLI's raw output.
|
|
39
|
+
*
|
|
40
|
+
* Replaces the previous `decodeOutput(): string` shape, which collapsed
|
|
41
|
+
* three distinct states (success / refusal / error) into one string and
|
|
42
|
+
* forced the orchestrator to re-grep the assistant prose for refusal
|
|
43
|
+
* markers — a brittle layer that produced the 2026-05-21 false-positive
|
|
44
|
+
* class (see Phase 1 fix in cli-agents.ts).
|
|
45
|
+
*
|
|
46
|
+
* Each provider adapter populates this from its own protocol-level
|
|
47
|
+
* signals (Claude: `result.subtype` / `is_error`; Codex: error events;
|
|
48
|
+
* Gemini: anchored stderr markers). The orchestrator never inspects
|
|
49
|
+
* assistant prose to classify refusals.
|
|
50
|
+
*/
|
|
51
|
+
export type DecodeRefusalReason = 'quota' | 'auth' | 'policy';
|
|
52
|
+
export type DecodeErrorReason = 'malformed' | 'empty' | 'unknown';
|
|
53
|
+
export type DecodeResult = {
|
|
54
|
+
kind: 'ok';
|
|
55
|
+
text: string;
|
|
56
|
+
} | {
|
|
57
|
+
kind: 'refused';
|
|
58
|
+
reason: DecodeRefusalReason;
|
|
59
|
+
detail?: string;
|
|
60
|
+
} | {
|
|
61
|
+
kind: 'error';
|
|
62
|
+
reason: DecodeErrorReason;
|
|
63
|
+
detail?: string;
|
|
64
|
+
};
|
|
37
65
|
export interface CLIProvider {
|
|
38
66
|
readonly name: CLIName;
|
|
39
67
|
/** Return the static configuration for this provider */
|
|
@@ -51,16 +79,34 @@ export interface CLIProvider {
|
|
|
51
79
|
model?: string;
|
|
52
80
|
}>;
|
|
53
81
|
/**
|
|
54
|
-
* Decode raw CLI output into
|
|
55
|
-
*
|
|
56
|
-
*
|
|
82
|
+
* Decode raw CLI output into a structured outcome (preferred API).
|
|
83
|
+
*
|
|
84
|
+
* Each adapter inspects ITS OWN protocol-level signals to classify the
|
|
85
|
+
* run — refusal markers must come from the CLI's structured error
|
|
86
|
+
* channel (stream-json `result` events for Claude, error items for
|
|
87
|
+
* Codex, anchored stderr envelopes for Gemini) and never from the
|
|
88
|
+
* assistant text the CLI returned.
|
|
89
|
+
*
|
|
90
|
+
* The orchestrator consumes `DecodeResult.kind` directly; no caller
|
|
91
|
+
* grep the prose for "rate limit"-style strings (Phase 1 hot-fix
|
|
92
|
+
* scoped that pattern set to stderr; Phase 2 removes it entirely).
|
|
93
|
+
*
|
|
94
|
+
* stderr is passed in alongside stdout because two of the three CLIs
|
|
95
|
+
* (Codex error envelopes, Gemini quota errors) surface refusal state
|
|
96
|
+
* on stderr, not in the JSON event stream.
|
|
97
|
+
*/
|
|
98
|
+
decode(stdout: string, stderr: string, args: string[], log?: StructuredLogger): DecodeResult;
|
|
99
|
+
/**
|
|
100
|
+
* Decode raw CLI output into clean text (legacy API).
|
|
101
|
+
*
|
|
102
|
+
* Delegates to `decode()` and returns the assistant text on success,
|
|
103
|
+
* empty string on refusal/error. Retained for the legacy test proxies
|
|
104
|
+
* at `cli-agents.ts:716-728` and any external consumers; new code
|
|
105
|
+
* should call `decode()` and switch on `kind`.
|
|
57
106
|
*
|
|
58
|
-
* Pattern A: `log` is optional. When provided
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* absent, adapters fall back to the root logger so the legacy test
|
|
62
|
-
* proxies (cli-agents.ts decodeClaudeStreamJson / extractCodexAgentMessage
|
|
63
|
-
* / extractGeminiResponse) keep working with no args.
|
|
107
|
+
* Pattern A: `log` is optional. When provided, adapter warnings/errors
|
|
108
|
+
* during decode emit with the scoped logger. When absent, adapters
|
|
109
|
+
* fall back to the root logger.
|
|
64
110
|
*/
|
|
65
111
|
decodeOutput(rawOutput: string, args: string[], log?: StructuredLogger): string;
|
|
66
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli-adapters/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAI1C,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEpD,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,YAAY,EAAE,WAAW,GAAG,iBAAiB,GAAG,kBAAkB,CAAC;IAGnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IAGpB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAG3B,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,yDAAyD;IACzD,eAAe,EAAE;QACf,MAAM,EAAE,kBAAkB,GAAG,SAAS,GAAG,eAAe,CAAC;QACzD,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,MAAM,EAAE,CAAC;IACvD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAID,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAEvB,wDAAwD;IACxD,SAAS,IAAI,gBAAgB,CAAC;IAE9B;;;OAGG;IACH,YAAY,CACV,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,eAAe,EACxB,aAAa,EAAE,aAAa,EAC5B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,OAAO,CAAC;QACT,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli-adapters/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli-adapters/index.ts"],"names":[],"mappings":"AAUA,6BAA6B;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli-adapters/index.ts"],"names":[],"mappings":"AAUA,6BAA6B;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA0I1C,8EAA8E;AAE9E,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,SAAS,GAAiC;IAC9C,MAAM,EAAE,IAAI,aAAa,EAAE;IAC3B,KAAK,EAAE,IAAI,YAAY,EAAE;IACzB,MAAM,EAAE,IAAI,aAAa,EAAE;CAC5B,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAa;IACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,MAAM,CAAC,IAAI,CAAC,SAAS,CAAc,CAAC;AAC7C,CAAC"}
|
package/dist/cli-agents.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-agents.d.ts","sourceRoot":"","sources":["../src/cli-agents.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-agents.d.ts","sourceRoot":"","sources":["../src/cli-agents.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAKpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAwD1D,MAAM,MAAM,mBAAmB,GAC3B,MAAM,GACN,UAAU,GACV,cAAc,GACd,MAAM,GACN,UAAU,GACV,MAAM,GACN,UAAU,GACV,SAAS,GACT,gBAAgB,GAChB,QAAQ,GACR,cAAc,GACd,eAAe,GACf,YAAY,GACZ,cAAc,GACd,QAAQ,GACR,OAAO,CAAC;AAiBZ,eAAO,MAAM,cAAc,sCAAuC,CAAC;AAgdnE,MAAM,WAAW,eAAe;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,CAAC,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC;IACzC,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,MAAM,CAAC,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IACnD,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAwB;IACvC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,aAAa,CAAC;IAC1E,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,CAAC,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC,EAAE,CAAC;CAClD;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,cAAc,CAAW;IACjC,OAAO,CAAC,iBAAiB,CAAiB;IAC1C,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,mBAAmB,CAAK;IAChC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAuB;IAG3D,SAAgB,aAAa,EAAE,aAAa,CAAC;IAM7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAmB;IAGxC,OAAO,CAAC,gBAAgB,CAA8D;IACtF,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAO;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAQ;IACvC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAQ;IAC3C,OAAO,CAAC,aAAa,CAAK;IAE1B;;;;OAIG;gBACS,IAAI,CAAC,EAAE,wBAAwB,GAAG,aAAa;IA2B3D;;;;OAIG;IACH,OAAO,CAAC,OAAO;IAIf;;;;;;;;;;OAUG;IACH,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,sBAAsB;IAK9B,OAAO,CAAC,wBAAwB;IAKhC,OAAO,CAAC,qBAAqB;IAK7B,OAAO,CAAC,2BAA2B;YA6DrB,eAAe;IAqBvB,gBAAgB,IAAI,OAAO,CAAC,UAAU,CAAC;IAyC7C,eAAe,CACb,YAAY,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,EAC5C,YAAY,CAAC,EAAE,mBAAmB,GACjC,QAAQ,GAAG,OAAO,GAAG,QAAQ;YAwClB,WAAW;IAwVnB,iBAAiB,CACrB,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC;IAUtB,YAAY,CAChB,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC;IAUtB,aAAa,CACjB,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC;IAUtB,gBAAgB,CACpB,GAAG,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,EAClC,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC;IA0E5B;;;;;;;;;;;;;;;;;;;OAmBG;YACW,0BAA0B;YAmD1B,oBAAoB;IAS5B,gBAAgB,CACpB,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAoCxB,eAAe,CACnB,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC;IAQtB,wBAAwB,CAC5B,YAAY,EAAE,mBAAmB,EACjC,cAAc,EAAE,MAAM,EACtB,gBAAgB,EAAE,MAAM,EACxB,OAAO,CAAC,EAAE,MAAM,EAChB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,gBAAgB,EAAE,CAAC;IA2F9B,2BAA2B,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAyCxF,OAAO,CAAC,mBAAmB;CA8B5B"}
|
package/dist/cli-agents.js
CHANGED
|
@@ -3,7 +3,7 @@ import { promises as fs, realpathSync } from 'fs';
|
|
|
3
3
|
import { promisify } from 'util';
|
|
4
4
|
import { logger } from './logger.js';
|
|
5
5
|
import { ModelResolver } from './model-resolver.js';
|
|
6
|
-
import { cleanupTempConfig
|
|
6
|
+
import { cleanupTempConfig } from './mcp-registry.js';
|
|
7
7
|
import { getProvider, parseNDJSON } from './cli-adapters/index.js';
|
|
8
8
|
import { GEMINI_FRONTIER_CHAIN } from './cli-adapters/gemini-adapter.js';
|
|
9
9
|
import { safeMetric } from './metrics/index.js';
|
|
@@ -794,46 +794,29 @@ export class CLIAgentOrchestrator {
|
|
|
794
794
|
});
|
|
795
795
|
}
|
|
796
796
|
// Post-process CLI output via provider adapter. Thread the scoped
|
|
797
|
-
// logger through
|
|
797
|
+
// logger through decode so adapter warnings/errors carry
|
|
798
798
|
// module=cli-orchestrator + operation=<provider>_spawn context.
|
|
799
|
+
//
|
|
800
|
+
// Phase 2: consume the structured DecodeResult from `decode()`
|
|
801
|
+
// instead of grepping the returned string for refusal markers.
|
|
802
|
+
// Each adapter classifies refusal from its own protocol-level
|
|
803
|
+
// signals (Claude `result.subtype`, Codex error events / stderr
|
|
804
|
+
// markers, Gemini anchored stderr markers). The orchestrator
|
|
805
|
+
// does not inspect assistant prose to classify outcomes.
|
|
799
806
|
let finalOutput = stdout;
|
|
800
807
|
const providerAdapter = getProvider(cliName);
|
|
801
808
|
const decodeLog = this.log?.forOperation(`${cliName}_spawn`);
|
|
802
|
-
const
|
|
803
|
-
if (
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
// (e.g., Gemini CLI returns exit code 0 on quota exhaustion,
|
|
814
|
-
// Codex CLI may return usage limit errors in output)
|
|
815
|
-
const combinedOutput = `${finalOutput}\n${stderr}`;
|
|
816
|
-
const quotaPatterns = [
|
|
817
|
-
/TerminalQuotaError/i,
|
|
818
|
-
/exhausted your capacity/i,
|
|
819
|
-
/quota will reset/i,
|
|
820
|
-
/rateLimitExceeded/i,
|
|
821
|
-
/rate limit/i,
|
|
822
|
-
/usage limit/i,
|
|
823
|
-
/Too Many Requests/i,
|
|
824
|
-
/\b429\b/,
|
|
825
|
-
/token limit exceeded/i,
|
|
826
|
-
/billing.*limit/i,
|
|
827
|
-
/spending.*limit/i,
|
|
828
|
-
/plan.*limit/i,
|
|
829
|
-
];
|
|
830
|
-
const quotaMatch = quotaPatterns.find(p => p.test(combinedOutput));
|
|
831
|
-
if (quotaMatch) {
|
|
832
|
-
// Extract reset time if present
|
|
833
|
-
const resetMatch = combinedOutput.match(/reset(?:s)? (?:in|after) (\d+h\s*\d+m(?:\s*\d+s)?)/i);
|
|
834
|
-
const resetInfo = resetMatch ? ` (resets in ${resetMatch[1]})` : '';
|
|
835
|
-
const errorMsg = `${cliName.toUpperCase()} quota exhausted${resetInfo}. The CLI exited 0 but returned a quota error instead of analysis output.`;
|
|
836
|
-
this.emitLog().warn(`⏱️ ${errorMsg}`);
|
|
809
|
+
const decoded = providerAdapter.decode(stdout, stderr, args, decodeLog);
|
|
810
|
+
if (decoded.kind === 'refused') {
|
|
811
|
+
// Structured refusal — the adapter saw the CLI's own
|
|
812
|
+
// protocol-level signal that this run hit a wall (quota / auth /
|
|
813
|
+
// policy). No prose matching.
|
|
814
|
+
const errorMsg = `${cliName.toUpperCase()} ${decoded.reason} refused. The CLI exited 0 but its own protocol returned a refusal instead of analysis output.`;
|
|
815
|
+
this.emitLog().warn(`⏱️ ${errorMsg}`, {
|
|
816
|
+
reason: decoded.reason,
|
|
817
|
+
detail: decoded.detail,
|
|
818
|
+
stderrLength: stderr.length,
|
|
819
|
+
});
|
|
837
820
|
if (options.onStreamingEvent) {
|
|
838
821
|
options.onStreamingEvent({
|
|
839
822
|
type: 'agent_error',
|
|
@@ -843,19 +826,12 @@ export class CLIAgentOrchestrator {
|
|
|
843
826
|
sessionId: options.sessionId
|
|
844
827
|
});
|
|
845
828
|
}
|
|
846
|
-
|
|
847
|
-
// with a quota error in stdout/stderr). Labels annotated against
|
|
848
|
-
// CLI_SPAWN_LABELS so a future label-set change fails at compile
|
|
849
|
-
// time. Wrapped in `safeMetric` so a label-validation throw or
|
|
850
|
-
// other metric-layer exception cannot propagate into the outer
|
|
851
|
-
// spawn try/catch and be misclassified as a spawn failure
|
|
852
|
-
// (Cycle 3 Task CLI-B' — parity with debate's safeMetric).
|
|
853
|
-
const quotaLabels = {
|
|
829
|
+
const refusedLabels = {
|
|
854
830
|
provider,
|
|
855
831
|
outcome: 'refused',
|
|
856
832
|
};
|
|
857
|
-
safeMetric(this.emitLog(),
|
|
858
|
-
this.metrics?.cliSpawnTotal.inc(
|
|
833
|
+
safeMetric(this.emitLog(), `cliSpawnTotal.inc(refused:${decoded.reason})`, () => {
|
|
834
|
+
this.metrics?.cliSpawnTotal.inc(refusedLabels, 1);
|
|
859
835
|
});
|
|
860
836
|
return {
|
|
861
837
|
agent: cliName,
|
|
@@ -863,18 +839,26 @@ export class CLIAgentOrchestrator {
|
|
|
863
839
|
output: '',
|
|
864
840
|
error: errorMsg,
|
|
865
841
|
executionTime: Date.now() - startTime,
|
|
866
|
-
// Cycle 4 Task T18 (F9): match the failure-path redaction
|
|
867
|
-
// parity — `command` is a diagnostic display field; the
|
|
868
|
-
// static placeholder preserves the response shape without
|
|
869
|
-
// leaking raw command + args (which may include Codex TOML
|
|
870
|
-
// MCP overrides, Claude temp config paths, or prompt
|
|
871
|
-
// fragments that crossed the trust boundary).
|
|
872
842
|
command: `(redacted command for ${cliName})`,
|
|
873
843
|
workingDirectory: workingDir,
|
|
874
844
|
exitCode: 0,
|
|
875
845
|
model: built?.model
|
|
876
846
|
};
|
|
877
847
|
}
|
|
848
|
+
if (decoded.kind === 'ok') {
|
|
849
|
+
finalOutput = decoded.text;
|
|
850
|
+
}
|
|
851
|
+
// For `kind: 'error'` (empty/malformed/unknown) we fall through
|
|
852
|
+
// and keep finalOutput as the raw stdout — preserving the legacy
|
|
853
|
+
// "if decode returned nothing useful, pass raw stdout through"
|
|
854
|
+
// behavior. The success path below then surfaces the raw output
|
|
855
|
+
// and the caller can see what the CLI emitted.
|
|
856
|
+
// Fallback: If stdout is empty but stderr has content and exit was successful,
|
|
857
|
+
// Claude might have written to stderr (common in non-TTY environments)
|
|
858
|
+
if (!finalOutput.trim() && stderr && stderr.trim()) {
|
|
859
|
+
this.emitLog().info(`📝 Using stderr as output for ${cliName} (stdout was empty)`);
|
|
860
|
+
finalOutput = stderr;
|
|
861
|
+
}
|
|
878
862
|
// Spawn counter: outcome=success (normal completion path). Labels
|
|
879
863
|
// annotated against CLI_SPAWN_LABELS so a future label-set change
|
|
880
864
|
// fails at compile time. Wrapped in `safeMetric` so a metric-layer
|
|
@@ -910,14 +894,22 @@ export class CLIAgentOrchestrator {
|
|
|
910
894
|
catch (error) {
|
|
911
895
|
const execError = error;
|
|
912
896
|
const exitCode = execError.code || -1;
|
|
913
|
-
// Detect rate limiting / usage limit errors across all CLIs
|
|
897
|
+
// Detect rate limiting / usage limit errors across all CLIs.
|
|
898
|
+
//
|
|
899
|
+
// Scoped to `message + stderr`. The previous scope of
|
|
900
|
+
// `message + stdout + stderr` ran these substrings against the
|
|
901
|
+
// child's captured stdout — which on a partial/aborted run is
|
|
902
|
+
// assistant prose that crossed the same trust boundary as the
|
|
903
|
+
// success path. `message` is the spawn-layer error string from
|
|
904
|
+
// Node (e.g., "Command failed with exit code 1"), not user
|
|
905
|
+
// content; safe to keep.
|
|
914
906
|
const rateLimitPatterns = [
|
|
915
907
|
'429', 'rate limit', 'rate_limit', 'rateLimitExceeded',
|
|
916
908
|
'Too Many Requests', 'usage limit', 'usage_limit',
|
|
917
909
|
'quota', 'exhausted', 'billing', 'spending limit',
|
|
918
910
|
'token limit', 'plan limit',
|
|
919
911
|
];
|
|
920
|
-
const errorText = `${execError.message || ''} ${execError.
|
|
912
|
+
const errorText = `${execError.message || ''} ${execError.stderr || ''}`.toLowerCase();
|
|
921
913
|
const isRateLimit = rateLimitPatterns.some(p => errorText.includes(p.toLowerCase()));
|
|
922
914
|
const unsupportedCodexModel = cliName === 'codex'
|
|
923
915
|
&& isCodexUnsupportedChatGPTModelError(execError, options.models?.codex);
|
|
@@ -1005,7 +997,12 @@ export class CLIAgentOrchestrator {
|
|
|
1005
997
|
};
|
|
1006
998
|
}
|
|
1007
999
|
finally {
|
|
1008
|
-
// Clean up temp MCP config file
|
|
1000
|
+
// Clean up the temp MCP config file when the Claude adapter
|
|
1001
|
+
// wrote one. The Claude path always uses `writeClaudeMcpConfigSecure`
|
|
1002
|
+
// when MCP is enabled, so `tempMcpConfigPath` is set whenever the
|
|
1003
|
+
// run had `--mcp-config <path>` on argv. When MCP is disabled
|
|
1004
|
+
// (no servers requested) the adapter never writes a file and
|
|
1005
|
+
// this finally is a no-op.
|
|
1009
1006
|
if (tempMcpConfigPath) {
|
|
1010
1007
|
await cleanupTempConfig(tempMcpConfigPath);
|
|
1011
1008
|
}
|