router: decouple per-run key budget from wallet, add overdraft buffer (#616)
Replaces today's `keyLimitUsd = min(walletBalance, $25)` with population-aware buffers so users can use 100% of their credits before being paywalled, and opaque mid-run "more credits" failures (e.g. https://github.com/pullfrog/app/actions/runs/25531633203) get a clear PR comment instead of a generic stack-trace dump. Policy matrix: - Auto-reload accounts: `wallet + autoReloadAmountCents` (default $50, no cap) - Card + no-autoreload: `wallet + $5` overdraft buffer - No card: `wallet` (no buffer; existing zero-balance 402 stays) - OSS: `$10` (unchanged) Removes the $25 per-run cap entirely. Long Build runs at high-balance accounts no longer silently cap at $25. Other changes: - Classify mid-run OpenRouter "requires more credits, or fewer max_tokens" errors as `router_keylimit_exhausted` BillingError so users get an actionable PR comment. - Override OpenCode `max_tokens: 32000` default to `5000` via OpenCodeConfig.limit.output. Drops Opus per-call upfront budget reservation from ~$2.40 to ~$0.38 — what makes low-wallet runs viable at all. - Switch `findInitialComment` and `findExistingPaywallComment` to GraphQL `issueOrPullRequest(number:) { comments(last: 100) }` (single round trip, actually returns newest-100; REST listComments doesn't support sort/direction). Also fixes a latent `comments.find()` returning the OLDEST match instead of the most recent — now selects max(databaseId). - Wrap `syncAccountUsage` in `prisma.$transaction` with `SELECT ... FOR UPDATE` on the account row. Pre/post-balance reads inside the transaction enable deterministic low-balance edge detection (currently logs; will push the outreach.low_balance task once #592 lands). Plan: .cursor/plans/router-low-balance-paywall.plan.md (in companion wiki-billing branch)
This commit is contained in:
committed by
pullfrog[bot]
parent
9d04cad360
commit
4101df566b
@@ -56,9 +56,21 @@ type OpenCodeConfig = {
|
||||
agent?: Record<string, unknown>;
|
||||
model?: string;
|
||||
enabled_providers?: string[];
|
||||
/**
|
||||
* OpenCode's `limit.output` controls the per-inference `max_tokens` the agent
|
||||
* reserves with the upstream model. OpenCode defaults to 32_000 (sized for
|
||||
* long-running TUI sessions where a human user might want big outputs).
|
||||
* Pullfrog runs are headless and short — typical outputs are 1-3K tokens —
|
||||
* so we override to a much smaller value. This drastically reduces the
|
||||
* upfront budget reservation OpenRouter requires per call, which is what
|
||||
* lets low-wallet runs actually start.
|
||||
*/
|
||||
limit?: { output?: number };
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
const PULLFROG_OPENCODE_OUTPUT_LIMIT = 5000;
|
||||
|
||||
function buildSecurityConfig(ctx: AgentRunContext, model: string | undefined): string {
|
||||
const config: OpenCodeConfig = {
|
||||
permission: {
|
||||
@@ -73,6 +85,7 @@ function buildSecurityConfig(ctx: AgentRunContext, model: string | undefined): s
|
||||
[pullfrogMcpName]: { type: "remote", url: ctx.mcpServerUrl },
|
||||
},
|
||||
agent: buildReviewerAgentConfig(),
|
||||
limit: { output: PULLFROG_OPENCODE_OUTPUT_LIMIT },
|
||||
};
|
||||
|
||||
if (model) {
|
||||
|
||||
Reference in New Issue
Block a user