-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbridge.ts
More file actions
64 lines (61 loc) · 2.64 KB
/
bridge.ts
File metadata and controls
64 lines (61 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import { buildScoringPrompt, extractJson } from './prompt';
import { validateResponse } from './scoring';
import type { ScoreResponse, Settings } from './types';
export interface BridgeError {
kind: 'no_bearer' | 'daemon_unreachable' | 'unauthorized' | 'rate_limited' | 'cli_missing' | 'bad_json' | 'unknown';
message: string;
}
export type BridgeResult =
| { ok: true; result: ScoreResponse; durationMs: number }
| { ok: false; error: BridgeError };
export async function scoreDraft(draft: string, settings: Settings): Promise<BridgeResult> {
if (!settings.bearer) {
return { ok: false, error: { kind: 'no_bearer', message: 'Set your local agent bearer token in the extension options first.' } };
}
const prompt = buildScoringPrompt(draft);
const url = `${settings.daemonUrl.replace(/\/+$/, '')}/gemini`;
let resp: Response;
try {
resp = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${settings.bearer}` },
body: JSON.stringify({ prompt, model: settings.model, timeout_ms: 60000 }),
});
} catch (e) {
return {
ok: false,
error: {
kind: 'daemon_unreachable',
message: `Cannot reach ${url}. Is your local agent running? (${(e as Error).message})`,
},
};
}
if (resp.status === 401) {
return { ok: false, error: { kind: 'unauthorized', message: 'Bearer token rejected by local agent. Check the value in options.' } };
}
const payload = (await resp.json().catch(() => null)) as
| { ok: boolean; text: string; stderr: string; rateLimited: boolean; durationMs: number }
| null;
if (!payload) {
return { ok: false, error: { kind: 'unknown', message: `Local agent returned non-JSON (status ${resp.status}).` } };
}
if (payload.rateLimited) {
return { ok: false, error: { kind: 'rate_limited', message: 'Gemini rate-limited. Try again in a minute.' } };
}
if (!payload.ok) {
if (/gemini-cli not found/i.test(payload.stderr)) {
return { ok: false, error: { kind: 'cli_missing', message: payload.stderr } };
}
return { ok: false, error: { kind: 'unknown', message: payload.stderr || 'Local agent reported failure with no detail.' } };
}
let parsed: unknown;
try {
parsed = extractJson(payload.text);
} catch (e) {
return { ok: false, error: { kind: 'bad_json', message: `Could not parse Gemini response as JSON: ${(e as Error).message}` } };
}
if (!validateResponse(parsed)) {
return { ok: false, error: { kind: 'bad_json', message: 'Gemini response was JSON but did not match expected schema.' } };
}
return { ok: true, result: parsed, durationMs: payload.durationMs };
}