@tokenfactory/acc-runner 0.40.3 → 0.40.5

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,71 @@
1
+ /**
2
+ * CC-3E FAILOVER-E2E — companion contention resolution: most-recent-heartbeat
3
+ * wins.
4
+ *
5
+ * When an operator has TWO companions registered for the same conversation
6
+ * (e.g. a laptop that went to sleep and a desktop that just came online, or a
7
+ * duplicate launch), only one should serve. Per-turn contention is already safe
8
+ * — `acc.claim_chat_turn` takes a per-conversation advisory lock, so exactly one
9
+ * companion wins each individual turn (see companion.ts §advisory lock). But the
10
+ * lock's winner is arbitrary; a stale companion whose host is asleep can still
11
+ * grab the lock first and then requeue on lease-expiry, adding a wasted hop per
12
+ * turn. This module is the PURE tiebreak the pump consults before racing for the
13
+ * lock: prefer the companion whose heartbeat is freshest (and drop ones whose
14
+ * heartbeat has gone stale entirely).
15
+ *
16
+ * The heartbeat-recency comparator mirrors the reviewer-routing "freshest wins"
17
+ * rule (api/_lib/reviewer/routing.ts) but for chat companions, which had no such
18
+ * tiebreak. Pure — the clock is passed in — so every ordering + staleness branch
19
+ * is unit-testable without real timers.
20
+ */
21
+ import type { RunnerCapacityClass } from "./engines/types.js";
22
+ /** A companion's last-known presence, as gathered from `identity:<user>` beats. */
23
+ export interface CompanionPresence {
24
+ runnerId: string;
25
+ /** Epoch ms of this companion's most recent heartbeat. */
26
+ lastHeartbeatMs: number;
27
+ /** Last-reported host capacity. */
28
+ capacity: RunnerCapacityClass;
29
+ /** Engines still claimable on this companion at report time. */
30
+ availableEngineIds: string[];
31
+ }
32
+ /**
33
+ * Default staleness window: a companion whose last heartbeat is older than this
34
+ * is considered gone. Generous relative to the 4 s default beat cadence so a
35
+ * single missed beat (GC pause, brief network blip) does not evict a live host,
36
+ * but tight enough that a slept/crashed host stops winning within seconds.
37
+ */
38
+ export declare const DEFAULT_HEARTBEAT_STALE_MS = 15000;
39
+ export interface CompanionSelectOptions {
40
+ /** Current time (epoch ms). */
41
+ now: number;
42
+ /** Heartbeats older than this are dropped as gone. Default 15s. */
43
+ staleMs?: number;
44
+ /**
45
+ * Require the winner to still advertise claimable engines. Default true — a
46
+ * companion reporting an empty engine set has nothing to serve and should not
47
+ * win even if its heartbeat is the freshest.
48
+ */
49
+ requireEngines?: boolean;
50
+ }
51
+ /** True when a heartbeat is within the staleness window (i.e. the host is live). */
52
+ export declare function isHeartbeatLive(presence: CompanionPresence, now: number, staleMs?: number): boolean;
53
+ /** The eligible companions (live + non-empty engines when required), unranked. */
54
+ export declare function eligibleCompanions(companions: readonly CompanionPresence[], opts: CompanionSelectOptions): CompanionPresence[];
55
+ /**
56
+ * Pick the companion that should serve: the live one with the FRESHEST heartbeat.
57
+ * Ties (identical heartbeat ms — e.g. a replayed beat) break on `runnerId`
58
+ * lexicographically so the choice is deterministic. Returns null when no
59
+ * companion is eligible (all stale / no engines).
60
+ */
61
+ export declare function pickFreshestCompanion(companions: readonly CompanionPresence[], opts: CompanionSelectOptions): CompanionPresence | null;
62
+ /**
63
+ * Should THIS companion defer (yield) to a fresher peer? True when a different,
64
+ * eligible companion has a strictly newer heartbeat. Used by the pump to avoid
65
+ * racing for the claim lock when a fresher peer is present — the stale host backs
66
+ * off instead of winning the lock and then requeueing on lease-expiry.
67
+ */
68
+ export declare function shouldDeferToPeer(self: CompanionPresence, peers: readonly CompanionPresence[], opts: CompanionSelectOptions): boolean;
69
+ /** Parse an ISO-8601 heartbeat timestamp to epoch ms (NaN-safe → 0). */
70
+ export declare function heartbeatMsFromIso(ts: string | null | undefined): number;
71
+ //# sourceMappingURL=companion-select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"companion-select.d.ts","sourceRoot":"","sources":["../src/companion-select.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,mFAAmF;AACnF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC;IACxB,mCAAmC;IACnC,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,gEAAgE;IAChE,kBAAkB,EAAE,MAAM,EAAE,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,QAAS,CAAC;AAEjD,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,mEAAmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,iBAAiB,EAC3B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,MAAmC,GAC3C,OAAO,CAET;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,IAAI,EAAE,sBAAsB,GAC3B,iBAAiB,EAAE,CAQrB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,SAAS,iBAAiB,EAAE,EACxC,IAAI,EAAE,sBAAsB,GAC3B,iBAAiB,GAAG,IAAI,CAS1B;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,SAAS,iBAAiB,EAAE,EACnC,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAGT;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAIxE"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Default staleness window: a companion whose last heartbeat is older than this
3
+ * is considered gone. Generous relative to the 4 s default beat cadence so a
4
+ * single missed beat (GC pause, brief network blip) does not evict a live host,
5
+ * but tight enough that a slept/crashed host stops winning within seconds.
6
+ */
7
+ export const DEFAULT_HEARTBEAT_STALE_MS = 15_000;
8
+ /** True when a heartbeat is within the staleness window (i.e. the host is live). */
9
+ export function isHeartbeatLive(presence, now, staleMs = DEFAULT_HEARTBEAT_STALE_MS) {
10
+ return now - presence.lastHeartbeatMs <= Math.max(0, staleMs);
11
+ }
12
+ /** The eligible companions (live + non-empty engines when required), unranked. */
13
+ export function eligibleCompanions(companions, opts) {
14
+ const staleMs = opts.staleMs ?? DEFAULT_HEARTBEAT_STALE_MS;
15
+ const requireEngines = opts.requireEngines ?? true;
16
+ return companions.filter((c) => {
17
+ if (!isHeartbeatLive(c, opts.now, staleMs))
18
+ return false;
19
+ if (requireEngines && c.availableEngineIds.length === 0)
20
+ return false;
21
+ return true;
22
+ });
23
+ }
24
+ /**
25
+ * Pick the companion that should serve: the live one with the FRESHEST heartbeat.
26
+ * Ties (identical heartbeat ms — e.g. a replayed beat) break on `runnerId`
27
+ * lexicographically so the choice is deterministic. Returns null when no
28
+ * companion is eligible (all stale / no engines).
29
+ */
30
+ export function pickFreshestCompanion(companions, opts) {
31
+ const eligible = eligibleCompanions(companions, opts);
32
+ if (eligible.length === 0)
33
+ return null;
34
+ return eligible.reduce((best, c) => {
35
+ if (c.lastHeartbeatMs !== best.lastHeartbeatMs) {
36
+ return c.lastHeartbeatMs > best.lastHeartbeatMs ? c : best;
37
+ }
38
+ return c.runnerId < best.runnerId ? c : best;
39
+ });
40
+ }
41
+ /**
42
+ * Should THIS companion defer (yield) to a fresher peer? True when a different,
43
+ * eligible companion has a strictly newer heartbeat. Used by the pump to avoid
44
+ * racing for the claim lock when a fresher peer is present — the stale host backs
45
+ * off instead of winning the lock and then requeueing on lease-expiry.
46
+ */
47
+ export function shouldDeferToPeer(self, peers, opts) {
48
+ const winner = pickFreshestCompanion([self, ...peers], opts);
49
+ return !!winner && winner.runnerId !== self.runnerId;
50
+ }
51
+ /** Parse an ISO-8601 heartbeat timestamp to epoch ms (NaN-safe → 0). */
52
+ export function heartbeatMsFromIso(ts) {
53
+ if (!ts)
54
+ return 0;
55
+ const n = Date.parse(ts);
56
+ return Number.isFinite(n) ? n : 0;
57
+ }
58
+ //# sourceMappingURL=companion-select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"companion-select.js","sourceRoot":"","sources":["../src/companion-select.ts"],"names":[],"mappings":"AAiCA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC;AAejD,oFAAoF;AACpF,MAAM,UAAU,eAAe,CAC7B,QAA2B,EAC3B,GAAW,EACX,UAAkB,0BAA0B;IAE5C,OAAO,GAAG,GAAG,QAAQ,CAAC,eAAe,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAChE,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,kBAAkB,CAChC,UAAwC,EACxC,IAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,0BAA0B,CAAC;IAC3D,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC;IACnD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7B,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC;YAAE,OAAO,KAAK,CAAC;QACzD,IAAI,cAAc,IAAI,CAAC,CAAC,kBAAkB,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACtE,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAwC,EACxC,IAA4B;IAE5B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACtD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QACjC,IAAI,CAAC,CAAC,eAAe,KAAK,IAAI,CAAC,eAAe,EAAE,CAAC;YAC/C,OAAO,CAAC,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC7D,CAAC;QACD,OAAO,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/C,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAuB,EACvB,KAAmC,EACnC,IAA4B;IAE5B,MAAM,MAAM,GAAG,qBAAqB,CAAC,CAAC,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,QAAQ,CAAC;AACvD,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,kBAAkB,CAAC,EAA6B;IAC9D,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,CAAC;IAClB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzB,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,113 @@
1
+ import { type ExecaChildProcess } from "execa";
2
+ import type { AccMcpToolBusFence, ConformantAgentEngine, EngineCapabilityMatrix, EngineResult, EngineStreamTurnOptions } from "./types.js";
3
+ /**
4
+ * Feature flag: `engines.gemini_enabled`. DEFAULT OFF. Truthy env forms only
5
+ * ("1"/"true"/"yes"/"on"). Kept as an env read (config.ts is out of this track's
6
+ * scope) so the flag stays fully self-contained. NOTE: unlike codex, the gemini
7
+ * engine IS registered in engines/registry.ts (so the chat-lane failover chain
8
+ * includes it); this flag gates whether a runner ADVERTISES gemini in its
9
+ * caps.engines, which is what the dispatch gate (mig 0229 / dor-gate.ts) keys
10
+ * on. Registration ≠ dispatch: the default fleet never lands a task on gemini
11
+ * unless a runner opts in.
12
+ */
13
+ export declare function geminiEngineEnabled(env?: NodeJS.ProcessEnv): boolean;
14
+ /** Trimmed Google model credential from `env`, or "" when unset/blank. Accepts
15
+ * either GEMINI_API_KEY (the CLI's native var) or GOOGLE_API_KEY (the Cloud
16
+ * var), GEMINI_API_KEY taking precedence. */
17
+ export declare function geminiApiKey(env?: NodeJS.ProcessEnv): string;
18
+ /**
19
+ * Build the argv for a headless one-shot `gemini` batch run. `--output-format
20
+ * json` emits the structured envelope parseResult reads; `--yolo` is the gemini
21
+ * analog of claude's `--dangerously-skip-permissions` — the runner is
22
+ * non-interactive and enforces the permission boundary one level up (worktree
23
+ * isolation + prepr-gate scope + zero-diff guard), so gemini must not block on
24
+ * its own approval prompts. `-m <id>` is forwarded only when non-blank.
25
+ */
26
+ export declare function buildGeminiArgs(modelId?: string | null): string[];
27
+ /**
28
+ * Augment the base env with the Google model credential. Forwards GEMINI_API_KEY
29
+ * (normalising a GOOGLE_API_KEY-only environment onto the CLI's native var) when
30
+ * present; a passthrough of `base` otherwise (the CLI then falls back to an
31
+ * interactive gcloud/OAuth login). Never mutates `base`.
32
+ */
33
+ export declare function geminiEnv(base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
34
+ /**
35
+ * TOLERANT parse of `gemini --output-format json` output into the shared result
36
+ * envelope. Gemini can emit either a single JSON object or a JSONL event stream;
37
+ * we scan every parseable line and keep the LAST text / model / usage seen.
38
+ * Returns null when nothing is parseable so the caller falls back to plain-text
39
+ * extraction, exactly like parseClaudeJson / parseCodexResult.
40
+ */
41
+ export declare function parseGeminiResult(stdout: string): EngineResult;
42
+ /**
43
+ * The tool-bus fence: acc-mcp only. `enforced` is always true for this adapter
44
+ * (the chat lane never runs unfenced), and `allowedServers` is exactly the
45
+ * acc-mcp server id (`ACC_MCP_KEY`, shared with mcp-spawn.ts).
46
+ */
47
+ export declare function accMcpToolBusOnly(): AccMcpToolBusFence;
48
+ /**
49
+ * Build the argv for a headless streaming chat turn. Fences the tool bus to
50
+ * acc-mcp only:
51
+ * --output-format stream-json → incremental JSONL event stream
52
+ * --allowed-mcp-server-names acc → ONLY the acc-mcp MCP server's tools
53
+ * --exclude-tools <native…> → defence-in-depth: disable every
54
+ * built-in shell/file/web tool so none can escape the acc-mcp fence
55
+ * --yolo → non-interactive; the fence, not an
56
+ * approval prompt, is the boundary (mirrors the batch lane rationale).
57
+ * `-m` is forwarded only when the turn pins a non-blank model.
58
+ */
59
+ export declare function buildGeminiChatArgs(opts?: {
60
+ modelId?: string | null;
61
+ }): string[];
62
+ /**
63
+ * Augment the base env for a chat turn: forward the Google model credential and,
64
+ * when present, surface the per-turn delegation token so the acc-mcp bus acts
65
+ * with the narrowly-scoped companion delegation. Never mutates `base`.
66
+ */
67
+ export declare function geminiChatEnv(opts: EngineStreamTurnOptions): NodeJS.ProcessEnv;
68
+ /** One parsed stream event: the text to surface (may be "") and whether the turn is terminal. */
69
+ export interface ParsedGeminiStreamEvent {
70
+ text: string;
71
+ done: boolean;
72
+ }
73
+ /**
74
+ * TOLERANT parse of one line of gemini's `--output-format stream-json` output.
75
+ * Handles both the gemini-native `candidates[].content.parts[].text` shape and
76
+ * the claude-style `{type:"assistant"|"result", …}` shape the engine-agnostic
77
+ * conformance harness replays. Returns:
78
+ * - `{ text, done:false }` for an assistant/content event carrying text,
79
+ * - `{ text, done:true }` for a terminal event (`type:"result"`, or a
80
+ * gemini `finishReason`) — text is the final string, used only as a fallback
81
+ * when nothing streamed,
82
+ * - `null` for a non-JSON line, a keep-alive, or an event with no delta.
83
+ */
84
+ export declare function parseGeminiStreamLine(line: string): ParsedGeminiStreamEvent | null;
85
+ /** Static capability declaration for the gemini chat build. Full-tier: gemini
86
+ * can stream headlessly, fence to acc-mcp, and drive all three lanes. */
87
+ export declare const GEMINI_CAPABILITIES: EngineCapabilityMatrix;
88
+ export interface GeminiEngineDeps {
89
+ /** Spawn the chat child (default: real `gemini` stream-json spawn). */
90
+ spawnChat?: (opts: EngineStreamTurnOptions) => ExecaChildProcess;
91
+ /** Whether a Google API key is present (default: reads GEMINI_API_KEY/GOOGLE_API_KEY). */
92
+ resolveHasApiKey?: () => boolean;
93
+ /** Whether an interactive gemini login is usable (default: optimistic true; a stale one surfaces at turn time). */
94
+ hasInteractiveSession?: () => Promise<boolean>;
95
+ /** Whether the host holds a repo-write grant → full vs draft-only tier (default: `gh auth status`). */
96
+ repoWriteProbe?: () => Promise<boolean>;
97
+ /** Sample host load for capacity classification (default: `os.loadavg`/`os.cpus`). */
98
+ loadSampler?: () => {
99
+ load1: number;
100
+ cores: number;
101
+ };
102
+ }
103
+ /**
104
+ * Build a chat-conformant gemini engine. The batch `AgentEngine` core
105
+ * (id/binary/authMode/buildArgs/env/spawn/parseResult/classifyFailure/
106
+ * healthProbe) is defined inline; the chat-lane conformance surface is layered
107
+ * on top. All side effects are injectable so the conformance suite runs
108
+ * deterministically without a real `gemini`/`gh` binary.
109
+ */
110
+ export declare function createGeminiEngine(deps?: GeminiEngineDeps): ConformantAgentEngine;
111
+ /** The wired default chat-conformant gemini adapter. */
112
+ export declare const geminiEngine: ConformantAgentEngine;
113
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../src/engines/gemini.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAS,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAStD,OAAO,KAAK,EACV,kBAAkB,EAClB,qBAAqB,EAErB,sBAAsB,EAGtB,YAAY,EAGZ,uBAAuB,EAExB,MAAM,YAAY,CAAC;AAIpB;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAGjF;AAED;;8CAE8C;AAC9C,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAEzE;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE,CAKjE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAAC,UAAU,CAIlF;AA+ED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAyB9D;AA8CD;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,kBAAkB,CAEtD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAAG,MAAM,EAAE,CAcpF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,uBAAuB,GAAG,MAAM,CAAC,UAAU,CAK9E;AAcD,iGAAiG;AACjG,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAyBlF;AA4GD;0EAC0E;AAC1E,eAAO,MAAM,mBAAmB,EAAE,sBAOjC,CAAC;AAEF,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,uBAAuB,KAAK,iBAAiB,CAAC;IACjE,0FAA0F;IAC1F,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC;IACjC,mHAAmH;IACnH,qBAAqB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,uGAAuG;IACvG,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAYD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,gBAAqB,GAAG,qBAAqB,CAkBrF;AAED,wDAAwD;AACxD,eAAO,MAAM,YAAY,EAAE,qBAA4C,CAAC"}
@@ -0,0 +1,485 @@
1
+ /**
2
+ * CC-4B (GEMINI-ADAPTER): the `gemini` engine — a Google Gemini CLI adapter on
3
+ * the CC-0A engine conformance interface (`ConformantAgentEngine`,
4
+ * engines/types.ts). It is the second non-Anthropic build engine after `codex`
5
+ * (M4) and the first NON-Anthropic engine to also implement the strictly-larger
6
+ * chat-lane conformance surface (streaming + acc-mcp fence + credential-tier
7
+ * probe + capacity classifier + capability matrix).
8
+ *
9
+ * Structure mirrors the claude-code chat reference adapter (claude-code-chat.ts):
10
+ *
11
+ * 1. A plain batch `AgentEngine` core — buildArgs / env / spawn / parseResult /
12
+ * classifyFailure / healthProbe — so gemini can also drive the batch
13
+ * task/review lanes.
14
+ * 2. The chat-lane conformance layer on top — `streamTurn()` parses the CLI's
15
+ * JSONL event stream, `accMcpToolBusOnly()` + `buildGeminiChatArgs()` fence
16
+ * the tool bus to the acc-mcp server only, `credentialProbe()` resolves the
17
+ * Google auth channel and the tier it authorises (`full` with a repo-write
18
+ * grant, else `draft-only`; `unavailable` with no model credential), and
19
+ * `classifyCapacity()` buckets host load (reusing the shared load→class map).
20
+ *
21
+ * Every side-effecting probe (spawn, auth resolution, repo-write check, load
22
+ * sample) is injectable via `createGeminiEngine(deps)` so the conformance suite
23
+ * exercises the LOGIC deterministically without a real `gemini`/`gh` binary.
24
+ * `geminiEngine` is the wired default built from the production deps.
25
+ *
26
+ * Flags/output are pinned to Gemini CLI v0.x; parseResult / the stream parser are
27
+ * deliberately TOLERANT (the v0.44 codex tolerant-parser lesson) so a point-
28
+ * release event-shape drift degrades to best-effort extraction rather than a
29
+ * hard failure.
30
+ */
31
+ import os from "node:os";
32
+ import { execa } from "execa";
33
+ import { classifyClaudeExit } from "../failure-classifier.js";
34
+ import { ACC_MCP_KEY } from "../mcp-spawn.js";
35
+ import { classifyCapacityFromLoad, NATIVE_TOOLS_DISABLED, ACC_MCP_DELEGATION_TOKEN_ENV, } from "./claude-code-chat.js";
36
+ const BINARY = "gemini";
37
+ /**
38
+ * Feature flag: `engines.gemini_enabled`. DEFAULT OFF. Truthy env forms only
39
+ * ("1"/"true"/"yes"/"on"). Kept as an env read (config.ts is out of this track's
40
+ * scope) so the flag stays fully self-contained. NOTE: unlike codex, the gemini
41
+ * engine IS registered in engines/registry.ts (so the chat-lane failover chain
42
+ * includes it); this flag gates whether a runner ADVERTISES gemini in its
43
+ * caps.engines, which is what the dispatch gate (mig 0229 / dor-gate.ts) keys
44
+ * on. Registration ≠ dispatch: the default fleet never lands a task on gemini
45
+ * unless a runner opts in.
46
+ */
47
+ export function geminiEngineEnabled(env = process.env) {
48
+ const v = (env.ACC_ENGINE_GEMINI_ENABLED ?? "").trim().toLowerCase();
49
+ return v === "1" || v === "true" || v === "yes" || v === "on";
50
+ }
51
+ /** Trimmed Google model credential from `env`, or "" when unset/blank. Accepts
52
+ * either GEMINI_API_KEY (the CLI's native var) or GOOGLE_API_KEY (the Cloud
53
+ * var), GEMINI_API_KEY taking precedence. */
54
+ export function geminiApiKey(env = process.env) {
55
+ return (env.GEMINI_API_KEY ?? env.GOOGLE_API_KEY ?? "").trim();
56
+ }
57
+ /**
58
+ * Build the argv for a headless one-shot `gemini` batch run. `--output-format
59
+ * json` emits the structured envelope parseResult reads; `--yolo` is the gemini
60
+ * analog of claude's `--dangerously-skip-permissions` — the runner is
61
+ * non-interactive and enforces the permission boundary one level up (worktree
62
+ * isolation + prepr-gate scope + zero-diff guard), so gemini must not block on
63
+ * its own approval prompts. `-m <id>` is forwarded only when non-blank.
64
+ */
65
+ export function buildGeminiArgs(modelId) {
66
+ const args = ["--output-format", "json", "--yolo"];
67
+ const trimmed = (modelId ?? "").trim();
68
+ if (trimmed)
69
+ args.push("-m", trimmed);
70
+ return args;
71
+ }
72
+ /**
73
+ * Augment the base env with the Google model credential. Forwards GEMINI_API_KEY
74
+ * (normalising a GOOGLE_API_KEY-only environment onto the CLI's native var) when
75
+ * present; a passthrough of `base` otherwise (the CLI then falls back to an
76
+ * interactive gcloud/OAuth login). Never mutates `base`.
77
+ */
78
+ export function geminiEnv(base = process.env) {
79
+ const key = geminiApiKey(base);
80
+ if (!key)
81
+ return base;
82
+ return { ...base, GEMINI_API_KEY: key };
83
+ }
84
+ function spawnGemini(opts) {
85
+ const { cwd, modelId, baseEnv } = opts;
86
+ return execa(BINARY, buildGeminiArgs(modelId), {
87
+ ...(cwd !== undefined ? { cwd } : {}),
88
+ stdin: "pipe",
89
+ stdout: "pipe",
90
+ stderr: "pipe",
91
+ reject: false,
92
+ env: geminiEnv(baseEnv),
93
+ });
94
+ }
95
+ function asRecord(v) {
96
+ return typeof v === "object" && v !== null ? v : null;
97
+ }
98
+ /** First non-empty string among `obj[key]` for the given candidate keys. */
99
+ function pickString(obj, keys) {
100
+ for (const k of keys) {
101
+ const v = obj[k];
102
+ if (typeof v === "string" && v.trim())
103
+ return v;
104
+ }
105
+ return null;
106
+ }
107
+ /**
108
+ * Extract assistant text from a Gemini `candidates[].content.parts[].text`
109
+ * shape (the native REST/CLI envelope) OR a claude-style `message.content[]`
110
+ * text-block array (the shape the engine-agnostic conformance harness replays).
111
+ * Returns "" when neither yields text.
112
+ */
113
+ function extractGeminiText(obj) {
114
+ // claude-style: { message: { content: [{ type:"text", text }] } } | { content: string }
115
+ const msg = asRecord(obj.message);
116
+ const msgContent = msg?.content ?? obj.content;
117
+ if (typeof msgContent === "string" && msgContent)
118
+ return msgContent;
119
+ if (Array.isArray(msgContent)) {
120
+ let out = "";
121
+ for (const block of msgContent) {
122
+ const b = asRecord(block);
123
+ if (b && b.type === "text" && typeof b.text === "string")
124
+ out += b.text;
125
+ else if (b && typeof b.text === "string")
126
+ out += b.text;
127
+ }
128
+ if (out)
129
+ return out;
130
+ }
131
+ // gemini-native: { candidates: [ { content: { parts: [ { text } ] } } ] }
132
+ const candidates = obj.candidates;
133
+ if (Array.isArray(candidates)) {
134
+ let out = "";
135
+ for (const cand of candidates) {
136
+ const c = asRecord(cand);
137
+ const content = asRecord(c?.content);
138
+ const parts = content?.parts;
139
+ if (Array.isArray(parts)) {
140
+ for (const part of parts) {
141
+ const p = asRecord(part);
142
+ if (p && typeof p.text === "string")
143
+ out += p.text;
144
+ }
145
+ }
146
+ }
147
+ if (out)
148
+ return out;
149
+ }
150
+ return "";
151
+ }
152
+ /** Map a gemini `usageMetadata` (or a claude-style `usage`) onto ClaudeUsage. */
153
+ function pickGeminiUsage(obj) {
154
+ const u = asRecord(obj.usageMetadata) ?? asRecord(obj.usage);
155
+ if (!u)
156
+ return null;
157
+ const inTok = u.promptTokenCount ?? u.input_tokens ?? u.prompt_tokens;
158
+ const outTok = u.candidatesTokenCount ?? u.output_tokens ?? u.completion_tokens;
159
+ const usage = {};
160
+ if (typeof inTok === "number")
161
+ usage.input_tokens = inTok;
162
+ if (typeof outTok === "number")
163
+ usage.output_tokens = outTok;
164
+ return usage.input_tokens !== undefined || usage.output_tokens !== undefined ? usage : null;
165
+ }
166
+ /**
167
+ * TOLERANT parse of `gemini --output-format json` output into the shared result
168
+ * envelope. Gemini can emit either a single JSON object or a JSONL event stream;
169
+ * we scan every parseable line and keep the LAST text / model / usage seen.
170
+ * Returns null when nothing is parseable so the caller falls back to plain-text
171
+ * extraction, exactly like parseClaudeJson / parseCodexResult.
172
+ */
173
+ export function parseGeminiResult(stdout) {
174
+ const trimmed = stdout.trim();
175
+ if (!trimmed)
176
+ return null;
177
+ const out = {};
178
+ for (const line of trimmed.split(/\r?\n/)) {
179
+ const s = line.trim();
180
+ if (!s.startsWith("{"))
181
+ continue;
182
+ let parsed;
183
+ try {
184
+ parsed = JSON.parse(s);
185
+ }
186
+ catch {
187
+ continue;
188
+ }
189
+ const obj = asRecord(parsed);
190
+ if (!obj)
191
+ continue;
192
+ const text = extractGeminiText(obj) || pickString(obj, ["response", "result", "text"]);
193
+ if (text)
194
+ out.result = text;
195
+ const model = pickString(obj, ["model", "modelVersion"]) ??
196
+ (asRecord(obj.response) ? pickString(asRecord(obj.response), ["model", "modelVersion"]) : null);
197
+ if (model)
198
+ out.model = model;
199
+ const usage = pickGeminiUsage(obj);
200
+ if (usage)
201
+ out.usage = usage;
202
+ }
203
+ return out.result !== undefined || out.model !== undefined || out.usage !== undefined ? out : null;
204
+ }
205
+ /**
206
+ * Classify a gemini exit into the shared taxonomy. Delegates to the shared
207
+ * `classifyClaudeExit` mapper so the DB/telemetry class VALUES stay frozen and
208
+ * engine-agnostic (env_broken / capacity_exhausted / usage_limit / auth_expired
209
+ * / task_error). A gemini-specific pattern set + detail strings (Google's
210
+ * RESOURCE_EXHAUSTED / quota wording) is a follow-up in failure-classifier.ts,
211
+ * which is out of this track's file scope; the CLASS decision is what the
212
+ * runner's pause/quarantine/retry policy keys on, and that stays correct here.
213
+ */
214
+ function classifyGeminiFailure(exitCode, stderr, stdout, durationMs) {
215
+ return classifyClaudeExit(exitCode, stderr, stdout, durationMs);
216
+ }
217
+ /**
218
+ * Cheap health check: `gemini --version`. Same contract as the claude/codex
219
+ * probes — exit 0 means the binary/host is fine; any spawn failure / non-zero
220
+ * exit / timeout means the binary or its deps are genuinely broken.
221
+ */
222
+ async function geminiHealthProbe() {
223
+ try {
224
+ const res = await execa(BINARY, ["--version"], { reject: false, timeout: 5_000, env: process.env });
225
+ if (res.exitCode === 0) {
226
+ return { ok: true, detail: (res.stdout || "").trim().slice(0, 200) || "gemini --version ok" };
227
+ }
228
+ return {
229
+ ok: false,
230
+ detail: `gemini --version exited ${res.exitCode ?? "signal"}: ${(res.stderr || "").trim().slice(0, 200)}`,
231
+ };
232
+ }
233
+ catch (err) {
234
+ return { ok: false, detail: `gemini --version spawn failed: ${err.message}` };
235
+ }
236
+ }
237
+ /* ================================================================== *
238
+ * Chat-lane conformance layer
239
+ * ================================================================== */
240
+ const AUTH_MODE = "api-key-or-oauth";
241
+ /**
242
+ * The tool-bus fence: acc-mcp only. `enforced` is always true for this adapter
243
+ * (the chat lane never runs unfenced), and `allowedServers` is exactly the
244
+ * acc-mcp server id (`ACC_MCP_KEY`, shared with mcp-spawn.ts).
245
+ */
246
+ export function accMcpToolBusOnly() {
247
+ return { enforced: true, allowedServers: [ACC_MCP_KEY] };
248
+ }
249
+ /**
250
+ * Build the argv for a headless streaming chat turn. Fences the tool bus to
251
+ * acc-mcp only:
252
+ * --output-format stream-json → incremental JSONL event stream
253
+ * --allowed-mcp-server-names acc → ONLY the acc-mcp MCP server's tools
254
+ * --exclude-tools <native…> → defence-in-depth: disable every
255
+ * built-in shell/file/web tool so none can escape the acc-mcp fence
256
+ * --yolo → non-interactive; the fence, not an
257
+ * approval prompt, is the boundary (mirrors the batch lane rationale).
258
+ * `-m` is forwarded only when the turn pins a non-blank model.
259
+ */
260
+ export function buildGeminiChatArgs(opts = {}) {
261
+ const fence = accMcpToolBusOnly();
262
+ const args = [
263
+ "--output-format",
264
+ "stream-json",
265
+ "--allowed-mcp-server-names",
266
+ fence.allowedServers.join(","),
267
+ "--exclude-tools",
268
+ NATIVE_TOOLS_DISABLED.join(","),
269
+ "--yolo",
270
+ ];
271
+ const trimmed = (opts.modelId ?? "").trim();
272
+ if (trimmed)
273
+ args.push("-m", trimmed);
274
+ return args;
275
+ }
276
+ /**
277
+ * Augment the base env for a chat turn: forward the Google model credential and,
278
+ * when present, surface the per-turn delegation token so the acc-mcp bus acts
279
+ * with the narrowly-scoped companion delegation. Never mutates `base`.
280
+ */
281
+ export function geminiChatEnv(opts) {
282
+ const next = { ...geminiEnv(opts.baseEnv ?? process.env) };
283
+ const token = (opts.delegationToken ?? "").trim();
284
+ if (token)
285
+ next[ACC_MCP_DELEGATION_TOKEN_ENV] = token;
286
+ return next;
287
+ }
288
+ function spawnGeminiChat(opts) {
289
+ return execa(BINARY, buildGeminiChatArgs({ modelId: opts.modelId }), {
290
+ ...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),
291
+ ...(opts.signal ? { signal: opts.signal } : {}),
292
+ stdin: "pipe",
293
+ stdout: "pipe",
294
+ stderr: "pipe",
295
+ reject: false,
296
+ env: geminiChatEnv(opts),
297
+ });
298
+ }
299
+ /**
300
+ * TOLERANT parse of one line of gemini's `--output-format stream-json` output.
301
+ * Handles both the gemini-native `candidates[].content.parts[].text` shape and
302
+ * the claude-style `{type:"assistant"|"result", …}` shape the engine-agnostic
303
+ * conformance harness replays. Returns:
304
+ * - `{ text, done:false }` for an assistant/content event carrying text,
305
+ * - `{ text, done:true }` for a terminal event (`type:"result"`, or a
306
+ * gemini `finishReason`) — text is the final string, used only as a fallback
307
+ * when nothing streamed,
308
+ * - `null` for a non-JSON line, a keep-alive, or an event with no delta.
309
+ */
310
+ export function parseGeminiStreamLine(line) {
311
+ const s = line.trim();
312
+ if (!s.startsWith("{"))
313
+ return null;
314
+ let obj;
315
+ try {
316
+ obj = JSON.parse(s);
317
+ }
318
+ catch {
319
+ return null;
320
+ }
321
+ const rec = asRecord(obj);
322
+ if (!rec)
323
+ return null;
324
+ // Terminal result frame (claude-style) — carries the full text as a fallback.
325
+ if (rec.type === "result") {
326
+ const text = typeof rec.result === "string" ? rec.result : extractGeminiText(rec);
327
+ return { text, done: true };
328
+ }
329
+ // A gemini candidate with a finishReason set is the terminal frame.
330
+ const done = geminiStreamIsDone(rec);
331
+ const text = extractGeminiText(rec);
332
+ if (rec.type === "assistant")
333
+ return text ? { text, done: false } : null;
334
+ if (text)
335
+ return { text, done };
336
+ if (done)
337
+ return { text: "", done: true };
338
+ return null;
339
+ }
340
+ /** True when a gemini-native stream frame carries a set finishReason. */
341
+ function geminiStreamIsDone(rec) {
342
+ const candidates = rec.candidates;
343
+ if (Array.isArray(candidates)) {
344
+ for (const cand of candidates) {
345
+ const c = asRecord(cand);
346
+ const fr = c?.finishReason;
347
+ if (typeof fr === "string" && fr.trim() && fr !== "FINISH_REASON_UNSPECIFIED")
348
+ return true;
349
+ }
350
+ }
351
+ return false;
352
+ }
353
+ async function* streamTurnImpl(deps, opts) {
354
+ const child = deps.spawnChat(opts);
355
+ if (child.stdin) {
356
+ child.stdin.write(opts.prompt);
357
+ child.stdin.end();
358
+ }
359
+ let seq = 0;
360
+ let sawText = false;
361
+ let doneEmitted = false;
362
+ let buf = "";
363
+ const emit = function* (ev) {
364
+ if (ev.done) {
365
+ // The terminal frame carries the full text; only surface it as a delta
366
+ // when nothing was streamed (a CLI build that emits no incremental text).
367
+ yield { seq: seq++, delta: sawText ? "" : ev.text, done: true };
368
+ doneEmitted = true;
369
+ }
370
+ else {
371
+ sawText = true;
372
+ yield { seq: seq++, delta: ev.text, done: false };
373
+ }
374
+ };
375
+ const stdout = child.stdout;
376
+ if (stdout) {
377
+ for await (const raw of stdout) {
378
+ buf += typeof raw === "string" ? raw : raw.toString("utf8");
379
+ let nl;
380
+ while ((nl = buf.indexOf("\n")) !== -1) {
381
+ const line = buf.slice(0, nl);
382
+ buf = buf.slice(nl + 1);
383
+ const ev = parseGeminiStreamLine(line);
384
+ if (ev)
385
+ yield* emit(ev);
386
+ }
387
+ }
388
+ if (buf.trim()) {
389
+ const ev = parseGeminiStreamLine(buf);
390
+ if (ev)
391
+ yield* emit(ev);
392
+ }
393
+ }
394
+ // Await the child so an abort/SIGTERM is observed and the process is reaped.
395
+ await child.catch(() => undefined);
396
+ // A process that ended without a terminal frame (crash, abort, silent exit)
397
+ // still owes the consumer a terminal frame so its gap/done detection fires.
398
+ if (!doneEmitted)
399
+ yield { seq: seq++, delta: "", done: true };
400
+ }
401
+ async function classifyCapacityImpl(deps) {
402
+ const { load1, cores } = deps.loadSampler();
403
+ return classifyCapacityFromLoad(load1, cores);
404
+ }
405
+ async function credentialProbeImpl(deps) {
406
+ const hasKey = deps.resolveHasApiKey();
407
+ const hasModelCreds = hasKey ? true : await deps.hasInteractiveSession();
408
+ if (!hasModelCreds) {
409
+ return {
410
+ ok: false,
411
+ channel: AUTH_MODE,
412
+ tier: "unavailable",
413
+ detail: "no Google credential resolved (set GEMINI_API_KEY / GOOGLE_API_KEY or run an interactive `gemini` login)",
414
+ };
415
+ }
416
+ const repoWrite = await deps.repoWriteProbe();
417
+ const tier = repoWrite ? "full" : "draft-only";
418
+ const channelDetail = hasKey ? "api-key (GEMINI_API_KEY/GOOGLE_API_KEY set)" : "interactive-session (gcloud/OAuth login)";
419
+ return {
420
+ ok: true,
421
+ channel: AUTH_MODE,
422
+ tier,
423
+ detail: `${channelDetail}; repo-write ${repoWrite ? "granted (full tier)" : "absent (draft-only tier)"}`,
424
+ };
425
+ }
426
+ /**
427
+ * Default repo-write probe: `gh auth status` exit 0. A companion runner that can
428
+ * push / open a PR authorises the `full` tier; one that only holds a model
429
+ * credential is `draft-only`. Cheap, short-timeout, never throws.
430
+ */
431
+ async function defaultRepoWriteProbe() {
432
+ try {
433
+ const res = await execa("gh", ["auth", "status"], { reject: false, timeout: 5_000, env: process.env });
434
+ return res.exitCode === 0;
435
+ }
436
+ catch {
437
+ return false;
438
+ }
439
+ }
440
+ /** Static capability declaration for the gemini chat build. Full-tier: gemini
441
+ * can stream headlessly, fence to acc-mcp, and drive all three lanes. */
442
+ export const GEMINI_CAPABILITIES = {
443
+ headlessStreaming: true,
444
+ accMcpToolBus: true,
445
+ chatLane: true,
446
+ taskLane: true,
447
+ reviewLane: true,
448
+ tier: "full",
449
+ };
450
+ const DEFAULT_DEPS = {
451
+ spawnChat: spawnGeminiChat,
452
+ resolveHasApiKey: () => geminiApiKey().length > 0,
453
+ hasInteractiveSession: async () => true,
454
+ repoWriteProbe: defaultRepoWriteProbe,
455
+ loadSampler: () => ({ load1: os.loadavg()[0] ?? 0, cores: os.cpus().length }),
456
+ };
457
+ /**
458
+ * Build a chat-conformant gemini engine. The batch `AgentEngine` core
459
+ * (id/binary/authMode/buildArgs/env/spawn/parseResult/classifyFailure/
460
+ * healthProbe) is defined inline; the chat-lane conformance surface is layered
461
+ * on top. All side effects are injectable so the conformance suite runs
462
+ * deterministically without a real `gemini`/`gh` binary.
463
+ */
464
+ export function createGeminiEngine(deps = {}) {
465
+ const d = { ...DEFAULT_DEPS, ...deps };
466
+ return {
467
+ id: "gemini",
468
+ binary: BINARY,
469
+ authMode: AUTH_MODE,
470
+ buildArgs: buildGeminiArgs,
471
+ env: geminiEnv,
472
+ spawn: spawnGemini,
473
+ parseResult: parseGeminiResult,
474
+ classifyFailure: classifyGeminiFailure,
475
+ healthProbe: geminiHealthProbe,
476
+ capabilities: GEMINI_CAPABILITIES,
477
+ streamTurn: (opts) => streamTurnImpl(d, opts),
478
+ accMcpToolBusOnly,
479
+ credentialProbe: () => credentialProbeImpl(d),
480
+ classifyCapacity: () => classifyCapacityImpl(d),
481
+ };
482
+ }
483
+ /** The wired default chat-conformant gemini adapter. */
484
+ export const geminiEngine = createGeminiEngine();
485
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/engines/gemini.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/engines/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAS7F,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,QAAsB,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,CAOzD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAsBD,uCAAuC;AACvC,eAAO,MAAM,sBAAsB,QAA0B,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,qBAAqB,CASvE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,IAAI,qBAAqB,CAUvF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,sBAAsB,GAAG,IAAI,CAIpF"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/engines/registry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAU7F,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,QAAsB,CAAC;AAErD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,WAAW,CAOzD;AAED,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AA0BD,uCAAuC;AACvC,eAAO,MAAM,sBAAsB,QAA0B,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,qBAAqB,CASvE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAExC;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,IAAI,qBAAqB,CAUvF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,sBAAsB,GAAG,IAAI,CAIpF"}
@@ -1,6 +1,7 @@
1
1
  import { claudeCodeEngine } from "./claude-code.js";
2
2
  import { claudeCodeChatEngine } from "./claude-code-chat.js";
3
3
  import { codexChatEngine } from "./codex-chat.js";
4
+ import { geminiEngine } from "./gemini.js";
4
5
  const ENGINES = {
5
6
  [claudeCodeEngine.id]: claudeCodeEngine,
6
7
  };
@@ -42,6 +43,10 @@ export function engineIds() {
42
43
  const CHAT_ENGINES = {
43
44
  [claudeCodeChatEngine.id]: claudeCodeChatEngine,
44
45
  [codexChatEngine.id]: codexChatEngine,
46
+ // CC-4B (GEMINI-ADAPTER): the gemini adapter joins the chat-lane conformance
47
+ // registry so the scheduler's engine failover chain includes it. The default
48
+ // chat engine is unchanged (DEFAULT_CHAT_ENGINE_ID stays claude-code).
49
+ [geminiEngine.id]: geminiEngine,
45
50
  };
46
51
  /** The default chat-lane engine id. */
47
52
  export const DEFAULT_CHAT_ENGINE_ID = claudeCodeChatEngine.id;
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/engines/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/engines/registry.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenfactory/acc-runner",
3
- "version": "0.40.3",
3
+ "version": "0.40.5",
4
4
  "description": "Agent Control Center local runner. Spawns Claude Code sessions assigned via ACC.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,