Repository navigation
Add pre-session billing and cost notice - #436
AchlysChang wants to merge 1 commit into
Conversation
9d281e8 to
9c008bf
Compare
jserv
left a comment
There was a problem hiding this comment.
Check CONTRIBUTING.md carefully.
Always use git rebase instead of git merge.
An interview opens a Gemini Live session that bills the server's Google AI project on every turn. The lobby now shows a billing notice above Start once /api/session reports candidateVideo, linked via aria-describedby, stating that the provider is billed on the whole context it runs in and naming voice and video only when candidate video is active for the chosen mode. The Setup page states the same in the Google AI section. Refs sysprog21#161
9c008bf to
9e6ab86
Compare
| // Candidate video is sent to Gemini only when the flag is enabled and the | ||
| // interview mode is not whiteboard; whiteboard suppresses it at boot time. | ||
| // Exposed here so the lobby can mention video cost only when it applies. | ||
| let candidate_video = state.config.gemini_candidate_video_enabled; |
There was a problem hiding this comment.
The value of candidateVideo comes from the web process's own CODETRIAL_GEMINI_CANDIDATE_VIDEO_ENABLED. That only matches what happens in the interview when this process also hosts the interviewer. When there is no GOOGLE_API_KEY, main.rs serves the web side only and the agent joins from another host with its own environment. The flag here then usually defaults to false and the lobby promises "voice" while the real agent forwards video. Take the value from the local agent config when one was loaded, and send null (or leave the field out) otherwise, so the lobby does not state something it cannot know.
| applyCostNote(); | ||
| } | ||
|
|
||
| /// Show a billing notice above the Start button when the server has a Gemini |
There was a problem hiding this comment.
The comment says the notice appears "when the server has a Gemini key", but nothing checks for one. /api/session always returns a boolean, so the notice shows on every server, including one with no interviewer configured at all, where the candidate ends up in offline practice. Either gate the notice on an interviewer actually being available or fix the comment. As it stands, the comment describes a check that does not exist.
| function applyCostNote() { | ||
| const videoActive = candidateVideo === true && mode !== "whiteboard"; | ||
| const text = videoActive | ||
| ? "This interview uses voice and video. The provider is billed on the whole context it runs in." |
There was a problem hiding this comment.
"The provider is billed" does not tell the reader who pays, which is the point of #161. A candidate can read it as their own account being charged. Name the payer, for example "Gemini Live usage is billed to this server's Google AI project, on the whole context of the session." The setup page note has the same gap.
| const text = videoActive | ||
| ? "This interview uses voice and video. The provider is billed on the whole context it runs in." | ||
| : candidateVideo !== null | ||
| ? "This interview uses voice. The provider is billed on the whole context it runs in." |
There was a problem hiding this comment.
In whiteboard mode the camera is off, but the board still goes to Gemini as realtime images on the same stream (see the candidate_video doc comment in src/runtime.rs), and those images are billed context too. "This interview uses voice" undersells the cost in exactly the mode that sends the most images. Mention the board images in whiteboard mode, and update the "voice alone otherwise" wording in docs/provider-cost-and-degradation.md to match.
| session = { signedIn: false }; | ||
| await page.goto(`${base}/`, { waitUntil: "domcontentloaded" }); | ||
| await page.waitForFunction( | ||
| () => document.querySelector("#account-status").textContent !== "", |
There was a problem hiding this comment.
#account-status starts out as "Checking account..." in index.html, so this wait passes immediately, before /api/session has been handled, and the assertion runs against the notice's initial hidden attribute. The test passes even if loadAccount would wrongly reveal the notice. Wait for something the session response changes (or hold the route open, check that the notice is hidden, then release it), so the assertion runs after the response has been processed.
jserv
left a comment
There was a problem hiding this comment.
Avoid ambiguous references such as Refs #161. Complete the implementation and close the issue properly.
jserv
left a comment
There was a problem hiding this comment.
CI fails on the indent gate. Run make indent, then amend and force-push.
|
@AchlysChang To settle the two requests about the issue reference: this PR covers the pre-session cost warning accepted on #161 on 2026-10-12, while the session length cap and the text-only toggle stay open there, so it does not close #161 and |
Draw problems from a saved practice listImplements the pre-session cost warning notification for Issue #161. Adds clear cost and billing explanations to the setup screen and the interview lobby before starting, informing users that Gemini Live API continuous audio streaming and rolling context accumulation consume tokens rapidly and require sufficient prepaid credit or active billing.
Refs #161
UI Verification
Summary by cubic
Warns candidates on the setup page and in the interview lobby that a Live interview bills the server's Google AI project, so they see the cost before starting.
/api/sessionreportscandidateVideo, and names voice and video only when that flag is active for the chosen mode; whiteboard mode never mentions video.candidateVideoflag account for that so billing text stays accurate per mode.Written for commit 9e6ab86. Summary will update on new commits.