Repository navigation
feat(lechef): opt-in live runner — env-key auth, hard spend cap, per-session logs - #136
Merged
Merged
Conversation
…NL logs, session loop Opt-in live-model path for the LeChef design comparison (PR #102 review): the offline harness replays scripted turns with no model seam, so the live runner owns its session loop and reuses the provider-independent seams (design configs, wrapWithPolicy tool gating, buildSessionWorld, RunRecord assembly) unchanged. - live/types.ts: LiveTransport injection contract (request/response/usage), LiveCaps, TokenPrices, CostEstimate — no provider SDK, no key handling here - live/pricing.ts: conservative token estimates and per-model pricing; unknown model pricing fails closed (no silent zero-cost requests) - live/caps.ts: CapLedger enforcing BOTH LECHEF_LIVE_MAX_SPEND_USD and LECHEF_LIVE_MAX_REQUESTS (whichever binds first) BEFORE each request; a request that would breach a cap is never sent; clean abort reports state - live/config.ts: env-only key resolution (LECHEF_LIVE_API_KEY + provider/ model/caps params); missing key, unsupported provider, unknown pricing and invalid caps all fail closed - live/logs.ts: one append-and-flush JSONL per (arm, session) plus run summary writer; logs are evaluation artifacts, never committed - live/liveSession.ts: slot-driven live session loop — source user turns drive context, generated assistant turns replace scripted ones at source assistant slots, tool calls run through the same wrapWithPolicy gating, approval actions map FIFO to open proposals Tests use an injected mock transport only; nothing in src/lechef/live/ is ever run against a real API by the suite. Live execution stays unrun — the operator supplies key + scope + cap authorization explicitly. Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Pins the fail-closed contract end to end without any network: - env-only opt-in: missing/blank LECHEF_LIVE_API_KEY refuses; unsupported provider, unknown model pricing, and malformed caps all refuse (or throw) instead of falling back - caps: the stricter of the two ceilings binds BEFORE the send — a request cap of 1 aborts slot two with the transport called exactly once; a zero spend cap sends nothing; provider usage reconciles the conservative estimate downward; absent usage keeps the estimate - session loop: generated turns replace scripted ones at source assistant slots, tool calls dispatch through the same wrapWithPolicy runtime and their JSON results feed the next request, a scripted approve maps FIFO to the oldest open proposal (live call ids differ from scripted ids), the unprompted budget suppresses proactive slots before any request, the tool-round limit ends the exchange without a final round, two rejections silence a suggestion type through the system prompt - logs: per-session JSONL records session-start/request/response/tool dispatch/session-end with cap state, and never contains the API key Full suite: 474 pass / 0 fail (449 offline + 25 live), tsc clean. Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
Brings the merged tool layer under the live runner: device-derived userInitiated, single-consume proposal-bound approvals, device-auto required approval, and delta timer deadline extensions. Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
Adapter maps the neutral transport contract onto @google/genai
generateContent with a structured {text, toolCalls} response schema —
the same shape the offline scripts carry — with pure, unit-testable
request/response mappers and the SDK call path reachable only from the
explicit live command.
CLI: plan mode (keyless, prints arms/slots/caps/prices and the exact
live command) and live mode (env-only key, run-wide cap ledger, per
(arm, session) JSONL logs and RunRecord JSON, clean cap abort).
Refuses live mode without LECHEF_LIVE_API_KEY; no request is sent
without an explicit run.
Part of: capped opt-in live runner on overhaul/lechef-live-runner.
Live execution remains unrun pending operator authorization.
Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
…book Adapter mapper unit tests (roles, tool-result JSON, args parsing, usage mapping, malformed-response rejection) plus a localhost-only transport test that drives the real SDK/HTTP path against an in-process server via the endpoint override — no external traffic is possible. CLI hardening: a run that completes zero sessions exits 1. package.json gains the lechef:live script; README-live.md documents the env contract, default caps, outputs, and rehearsal channel; backend .gitignore keeps run outputs out of git. Part of: capped opt-in live runner on overhaul/lechef-live-runner. Live execution remains unrun pending operator authorization. Co-authored-by: obvious-autobuild[bot] <262744130+obvious-autobuild[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Adds the opt-in live-model path for the LeChef three-design comparison. The offline harness replays scripted turns — the script IS the provider, so
runDesignSessionhas no model seam to inject into. This PR therefore adds a newsrc/lechef/live/module and asrc/lechef/run/live.tsCLI with their own session loop, reusing the provider-independent seams unchanged: the per-arm design configs,wrapWithPolicytool gating,buildSessionWorld, and the pinned RunRecord assembly surfaces.New files (no existing
src/lechef/*.tsis edited):live/types.ts— theLiveTransportinjection contract (request, response, provider usage),LiveCaps,TokenPrices,CostEstimate. No provider SDK, no key handling in types.live/pricing.ts— conservative token estimates and per-model prices. Unknown model pricing fails closed: a run cannot silently cost zero.live/caps.ts—CapLedgerenforcing bothLECHEF_LIVE_MAX_SPEND_USDandLECHEF_LIVE_MAX_REQUESTS(whichever binds first) BEFORE each request. A request that would breach a cap is never sent; abort is clean and reports cap state.live/config.ts— env-only key resolution (LECHEF_LIVE_API_KEY, provider/model/caps params). Missing key, unsupported provider, unknown pricing, and invalid caps all fail closed.live/logs.ts— one append-and-flush JSONL per (arm, session) under the run directory, plus a run summary writer. Entries carry wall-clock timestamps, model, request sizes, estimated cost, and cap state — never request content, never the key.live/liveSession.ts— slot-driven session loop: source user turns drive context, generated assistant turns replace scripted ones at source assistant slots, tool calls run through the samewrapWithPolicygating, approval actions map FIFO to open proposals.live/geminiTransport.ts— the Gemini adapter: pure, unit-tested request/response mappers (a structured{text, toolCalls}schema matching the offline scripts' response shape) and an SDK-backed send path constructed only by the explicit live command.LECHEF_LIVE_ENDPOINToverrides the base URL (version suffix stripped) — the documented localhost rehearsal channel.run/live.ts— the CLI. Plan mode (default, keyless) prints arms/slots/caps/prices and the exact live command. Live mode (--mode=live) requires the key in the environment, runs the three arms, writes per-session JSONL + RunRecord JSON +summary.json, aborts cleanly at a cap, and exits 1 on a cap breach or when zero sessions complete.README-live.md— runbook: env contract (including default caps), outputs, sessions input, rehearsal channel.backend/gemini-agent/.gitignorekeeps run outputs out of git;package.jsongainslechef:live.Why
PR #102's review found the three design-arm scorecards not-run because sessions were missing, and asked for the real comparison. Running it needs a real model reachable through an injected seam that does not exist today, with spending bounded and every exchange logged. This PR builds that seam so the comparison becomes one command with an explicit key and hard caps — and is never triggered implicitly. A key appearing in the environment later does nothing; live is an explicit command.
How it works
flowchart LR src[source script\nuser turns + slots] --> loop[live session loop\nwrapWithPolicy gating] loop -->|request| ledger[CapLedger\nspend + requests] ledger -->|authorized| tx[LiveTransport\ninjected — Gemini adapter in live mode] tx -->|response + usage| loop ledger -->|would breach| abort[clean abort\ncap state] loop --> log[per-session JSONL\n+ run summary]The caps ledger authorizes every request before the transport fires and charges the pre-request estimate at send time, so a crash between send and response still counts the attempt.
Verification
Checks run in the sandbox (no CI or workflow edits). Branch head
ef59034:cd backend/gemini-agent && bun run check— clean (tsc, zero errors), before and after theoverhaul/lechef-f1merge (da04d52; the Direction-3 integration gate passed at 528/0 with the merged tool layer).bun test src/__tests__— 543 pass / 0 fail across 45 files: the merged tool-layer suite (503 after the f1 merge) plus 40 live-runner additions:wrapWithPolicy, FIFO approval mapping, clean aborts, proactive suppression.LECHEF_LIVE_ENDPOINT; external traffic is not possible from the test.LECHEF_LIVE_API_KEYexits 2 before any transport is constructed.Risk
usageMetadatawhen the provider reports usage; models missing from the pricing table fail closed.Handoff
Done — branch
overhaul/lechef-live-runner, headef59034, every commit authored by Sam Gu:c4c6e3dlive core modules ·7a3ee89behavior tests (mock transport only) ·a3ec50cmerge ofoverhaul/lechef-f1(da04d52) + integration fixes ·7f131e8Gemini adapter + live CLI ·ef59034adapter tests, localhost transport proof, runbook, exit hardening.Not done
How to continue
backend/gemini-agent:LECHEF_LIVE_API_KEY=... LECHEF_LIVE_MAX_SPEND_USD=<usd> LECHEF_LIVE_MAX_REQUESTS=<n> bun run lechef:live --sessions=<dir-or-file> --mode=liveWithout the key,
bun run lechef:live --sessions=<dir-or-file>prints the plan safely (verified).evaluation/lechef-live-runs/<runId>/(summary.json, per-session JSONL, RunRecord JSON) and stay uncommitted.summary.json(exit 1); zero completed sessions also exit 1. Nothing sends a request without an explicit keyed--mode=livecommand.Checklist