Keep g1t's own runs off the model proxy until it holds g1t's key
The runner reached the gateway with g1t's Anthropic key, a secret the new proxy does not have, so through the proxy the gateway fell back to its own billing and refused. Only runs on a workspace's own provider use the proxy now; MODELS_PROXY_HOSTED moves g1t's runs over once the proxy has the key.
2 files+17−40/2 viewed
| 43 | 43 | */ | |
| 44 | 44 | MODELS_URL?: string; | |
| 45 | 45 | /** | |
| 46 | + | * `true` to send g1t's own runs through the proxy too. Needs the proxy to | |
| 47 | + | * hold what reaches the provider for g1t (ANTHROPIC_API_KEY); until it | |
| 48 | + | * does, only runs on a workspace's own provider go through it. | |
| 49 | + | */ | |
| 50 | + | MODELS_PROXY_HOSTED?: string; | |
| 51 | + | /** | |
| 46 | 52 | * Secret. The provider's key. Leave it unset when the gateway holds the | |
| 47 | 53 | * key, so that no sandbox ever does. | |
| 48 | 54 | */ | |
| 414 | 420 | billedTo: own ? "workspace" : "g1t", | |
| 415 | 421 | }); | |
| 416 | 422 | if (!ticket.ok) return ticket; | |
| 417 | − | const vars: Record<string, string> = session | |
| 423 | + | // g1t's own runs use the proxy once it holds g1t's key; until then | |
| 424 | + | // they reach the gateway as they always have. | |
| 425 | + | const proxied = session != null && (own || this.env.MODELS_PROXY_HOSTED === "true"); | |
| 426 | + | const vars: Record<string, string> = proxied | |
| 418 | 427 | ? { | |
| 419 | 428 | ANTHROPIC_MODEL: model, | |
| 420 | − | AGENT_MODEL_NAME: own ? `${modelName}, through ${session.providerName}` : modelName, | |
| 429 | + | AGENT_MODEL_NAME: own ? `${modelName}, through ${session!.providerName}` : modelName, | |
| 421 | 430 | ANTHROPIC_BASE_URL: `${this.env.MODELS_URL!.replace(/\/+$/, "")}/anthropic`, | |
| 422 | 431 | // Not a key: a token for this run, which the proxy swaps for one. | |
| 423 | − | ANTHROPIC_API_KEY: session.token, | |
| 432 | + | ANTHROPIC_API_KEY: session!.token, | |
| 424 | 433 | // An endpoint that names models its own way gets its model for | |
| 425 | 434 | // the harness's small tasks too. | |
| 426 | − | ...(session.model ? { ANTHROPIC_SMALL_FAST_MODEL: session.model } : {}), | |
| 435 | + | ...(session!.model ? { ANTHROPIC_SMALL_FAST_MODEL: session!.model } : {}), | |
| 427 | 436 | } | |
| 428 | 437 | : modelEnv(this.env, routes, task, tags); | |
| 429 | 438 | if (ticket.value) { |
| 47 | 47 | // Where sandboxes send model requests, with a token for their run. | |
| 48 | 48 | // The proxy holds the keys: g1t's gateway's, or the workspace's own. | |
| 49 | 49 | "MODELS_URL": "https://models.g1t.sh", | |
| 50 | + | // g1t's own runs go through the proxy only once it holds g1t's | |
| 51 | + | // Anthropic key: npx wrangler secret put ANTHROPIC_API_KEY in | |
| 52 | + | // services/models, then set this to "true". | |
| 53 | + | "MODELS_PROXY_HOSTED": "false", | |
| 50 | 54 | // Set to a Cloudflare AI Gateway id to route model traffic through it. | |
| 51 | 55 | // Used only when MODELS_URL is unset. | |
| 52 | 56 | "AI_GATEWAY_ID": "g1t", |