@koda-sl/baker-bridge 0.172.0 → 0.173.0
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.
- package/README.md +22 -29
- package/dist/hono/bridge-job.test.js +3 -2
- package/dist/hono/bridge-job.test.js.map +1 -1
- package/dist/hono/openrouter-session.d.ts +10 -10
- package/dist/hono/openrouter-session.d.ts.map +1 -1
- package/dist/hono/openrouter-session.js +26 -30
- package/dist/hono/openrouter-session.js.map +1 -1
- package/dist/hono/openrouter-session.test.js +9 -12
- package/dist/hono/openrouter-session.test.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,13 +45,13 @@ await server.start();
|
|
|
45
45
|
| `ANTHROPIC_API_KEY` | Anthropic API key (required by the Agent SDK) |
|
|
46
46
|
| `ANTHROPIC_BASE_URL` / `ANTHROPIC_AUTH_TOKEN` | OpenRouter routing (base URL + per-org key) injected into the sandbox. Forwarded to the Agent SDK subprocess so the agent can reach its model |
|
|
47
47
|
| `OPENROUTER_API_KEY` | The same per-org key under its own name. The bridge reads the user's and the agent's words with it before letting two kinds of call through: a question asking the user to pick an avatar's face (the casting picker shows real portraits), and an avatar accent in a language nobody asked for. Unset or unreachable, both calls go through unchecked |
|
|
48
|
-
| `CLAUDE_CODE_EXTRA_BODY` | Optional JSON merged by the CLI into every model request body. The bridge sets/extends it per turn with a per-thread `session_id` so OpenRouter sticky-routes the whole conversation to one provider instance and its instance-scoped prompt cache is re-read across the turn's many tool-call requests (see [Prompt-cache pinning](#prompt-cache-pinning)). It also
|
|
48
|
+
| `CLAUDE_CODE_EXTRA_BODY` | Optional JSON merged by the CLI into every model request body. The bridge sets/extends it per turn with a per-thread `session_id` so OpenRouter sticky-routes the whole conversation to one provider instance and its instance-scoped prompt cache is re-read across the turn's many tool-call requests (see [Prompt-cache pinning](#prompt-cache-pinning)). It also pins `provider` to our own Bedrock, with no fallback (see [Claude runs on our own Bedrock only](#claude-runs-on-our-own-bedrock-only)). Any inherited value is merged; our `provider`, `session_id` and the `web`-plugin opt-out win (see [OpenRouter web plugin is forced off](#openrouter-web-plugin-is-forced-off)) |
|
|
49
49
|
| `BAKER_ENVIRONMENT`, `BAKER_DEPLOYMENT`, `BAKER_ORGANIZATION_ID` | Optional. Where the Runtime runs (`production`, `preview`, `development`), the backend deployment's name and the organization. With `BAKER_RUNTIME_COMPANY_ID`, `BAKER_CHAT_ID` and the turn's sender they tag every OpenRouter request the agent and the bridge make — `HTTP-Referer` / `X-OpenRouter-Title` naming the app (`https://agent.<environment>.withbaker.com`), `x-session-id`, and in the body `user` (`<feature> | company:<id> | chat:<id> | user:<id>`, what OpenRouter shows per request) plus `trace` — so a request without the tag was not sent by Baker. The agent gets the headers through `ANTHROPIC_CUSTOM_HEADERS` (merged after any inherited value) and the body fields through `CLAUDE_CODE_EXTRA_BODY`; a Session review is tagged `chatReview.session`, a task `builder.task`, a plan `agent.plan`, a chat turn `agent.turn` |
|
|
50
50
|
| `BAKER_CHAT_ID` | Present only when running inside a chat sandbox. When set, the bridge relocates Claude Code auto-memory into the cloned repo (`.claude/memory`) — see [Session journal](#session-journal-agent-memory) |
|
|
51
51
|
| `BAKER_ACTING_USER_ID` | Injected into the Agent SDK subprocess env per turn (when the turn's sender is known) so in-sandbox `baker` CLI calls can scope work to the acting user — e.g. `baker mcp add --scope user` |
|
|
52
52
|
| `CLAUDE_CODE_ENABLE_TASKS` | Set to `0` on every Agent SDK subprocess. Turns off the CLI's built-in task backlog and its `task_reminder` — see [Session surface](#session-surface) |
|
|
53
|
-
| `CLAUDE_CODE_DISABLE_TERMINAL_TITLE` | Set to `1` on every Agent SDK subprocess. The CLI's session-title request carries a structured output OpenRouter cannot route to Bedrock — see [
|
|
54
|
-
| `CLAUDE_CODE_MODEL_CAPABILITIES` | Set to `-per_turn_effort` on every Agent SDK subprocess so no request carries a per-message effort, which OpenRouter cannot route to Bedrock — see [
|
|
53
|
+
| `CLAUDE_CODE_DISABLE_TERMINAL_TITLE` | Set to `1` on every Agent SDK subprocess. The CLI's session-title request carries a structured output OpenRouter cannot route to Bedrock — see [Claude runs on our own Bedrock only](#claude-runs-on-our-own-bedrock-only) |
|
|
54
|
+
| `CLAUDE_CODE_MODEL_CAPABILITIES` | Set to `-per_turn_effort` on every Agent SDK subprocess so no request carries a per-message effort, which OpenRouter cannot route to Bedrock — see [Claude runs on our own Bedrock only](#claude-runs-on-our-own-bedrock-only) |
|
|
55
55
|
| `NO_COLOR` | Set to `1` on every Agent SDK subprocess so `baker --help` output carries no ANSI escapes — see [Session surface](#session-surface) |
|
|
56
56
|
| `BAKER_AGENT_MODEL` | Optional. Runs every turn in this runtime on the named model instead of the default, and is forwarded to subagents as `CLAUDE_CODE_SUBAGENT_MODEL`. Ignored unless it names a model with a known context window — see [Model selection](#model-selection) |
|
|
57
57
|
| `CLAUDE_CODE_SUBAGENT_MODEL`, `CLAUDE_CODE_SUBAGENT_MODEL_FORCE` | Set on the Agent SDK subprocess only when `BAKER_AGENT_MODEL` is set. Together they override the `model:` each subagent pins in its own frontmatter |
|
|
@@ -200,31 +200,28 @@ re-paid full input price on the same ~30k-token prefix.
|
|
|
200
200
|
The fix (`openrouter-session.ts`): the bridge injects a stable per-thread
|
|
201
201
|
`session_id` via `CLAUDE_CODE_EXTRA_BODY`, which the CLI merges into every model
|
|
202
202
|
request body. That pins the whole conversation to its warm provider instance "even
|
|
203
|
-
if the opening messages change".
|
|
204
|
-
provider resilience is preserved. See OpenRouter → Prompt Caching (best practices). A manual
|
|
203
|
+
if the opening messages change". See OpenRouter → Prompt Caching (best practices). A manual
|
|
205
204
|
`provider.order` bypasses this sticky routing — see
|
|
206
|
-
[
|
|
207
|
-
cache stays warm while the Bedrock
|
|
205
|
+
[Claude runs on our own Bedrock only](#claude-runs-on-our-own-bedrock-only) for how the
|
|
206
|
+
cache stays warm while the Bedrock pin is set.
|
|
208
207
|
|
|
209
|
-
##
|
|
208
|
+
## Claude runs on our own Bedrock only
|
|
210
209
|
|
|
211
210
|
The same `CLAUDE_CODE_EXTRA_BODY` value carries a `provider` with
|
|
212
|
-
`allow_fallbacks:
|
|
211
|
+
`allow_fallbacks: false` and these endpoints as both `only` and `order`:
|
|
213
212
|
|
|
214
213
|
```json
|
|
215
214
|
["amazon-bedrock", "amazon-bedrock/eu-west-1", "amazon-bedrock/us-east-1"]
|
|
216
215
|
```
|
|
217
216
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
inherited `provider` (set in the sandbox's `CLAUDE_CODE_EXTRA_BODY`) replaces this
|
|
227
|
-
default as an operator override.
|
|
217
|
+
Every Claude request is served by Amazon Bedrock on Baker's own key (OpenRouter
|
|
218
|
+
BYOK), or the turn fails. Anthropic, Vertex, Azure and OpenRouter's own capacity
|
|
219
|
+
are paid from OpenRouter credits, and an error is preferred to that charge. The
|
|
220
|
+
regions are there because Bedrock's failure mode is AWS capacity, not our quota:
|
|
221
|
+
on weekday mornings the default endpoint answers `503` to most Opus 5.5 requests
|
|
222
|
+
for hours, and AWS's advice for a `503` is another region. All three run on our
|
|
223
|
+
own key. An inherited `provider` (set in the sandbox's `CLAUDE_CODE_EXTRA_BODY`)
|
|
224
|
+
is replaced: the pin is not an operator override.
|
|
228
225
|
|
|
229
226
|
A manual `order` bypasses OpenRouter's sticky routing, so while it is set the
|
|
230
227
|
`session_id` pin above is inert and the `order` is what keeps the cache warm. The
|
|
@@ -237,19 +234,15 @@ and each request retries the default endpoint first, so a cache warmed further
|
|
|
237
234
|
down the `order` is not reused while Bedrock is flapping. During a capacity
|
|
238
235
|
window every request also waits for the default endpoint's `503` (about 7 s)
|
|
239
236
|
before moving on.
|
|
240
|
-
The
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
The preference only holds for a request Bedrock can serve, and OpenRouter drops
|
|
244
|
-
Bedrock from the route without an error when it can't. From Opus 5.5 the CLI
|
|
237
|
+
The pin only works for a request Bedrock can serve; one it can't now fails
|
|
238
|
+
instead of moving to another provider. From Opus 5.5 the CLI
|
|
245
239
|
restates the effort on its mid-conversation `role: "system"` message
|
|
246
240
|
(`output_config.effort`, beta `per-turn-control`), which no Bedrock endpoint
|
|
247
|
-
supports — so the day Opus 5.5 shipped, 52 of ~4,600 of its
|
|
248
|
-
Bedrock and the rest were billed to OpenRouter credits. The bridge sets
|
|
241
|
+
supports — so the day Opus 5.5 shipped, before the pin, 52 of ~4,600 of its
|
|
242
|
+
requests reached Bedrock and the rest were billed to OpenRouter credits. The bridge sets
|
|
249
243
|
`CLAUDE_CODE_MODEL_CAPABILITIES=-per_turn_effort` to stop that; the request-level
|
|
250
|
-
`effort` still applies.
|
|
251
|
-
|
|
252
|
-
such request, naming the session, is never sent
|
|
244
|
+
`effort` still applies. The CLI's request naming the session is never
|
|
245
|
+
sent
|
|
253
246
|
(`CLAUDE_CODE_DISABLE_TERMINAL_TITLE=1`), since nothing in Baker reads the name.
|
|
254
247
|
|
|
255
248
|
## OpenRouter web plugin is forced off
|
|
@@ -1279,13 +1279,14 @@ describe("BridgeJobExecutor", () => {
|
|
|
1279
1279
|
BAKER_THREAD_ID: "thread_env",
|
|
1280
1280
|
BAKER_TURN_ID: "turn_env",
|
|
1281
1281
|
});
|
|
1282
|
-
// Guards the Bedrock
|
|
1282
|
+
// Guards the Bedrock-only pin, the prompt-cache pin and the OpenRouter
|
|
1283
1283
|
// web-plugin opt-out at their integration point: all must actually reach the
|
|
1284
1284
|
// subprocess body via CLAUDE_CODE_EXTRA_BODY.
|
|
1285
1285
|
expect(JSON.parse(env?.CLAUDE_CODE_EXTRA_BODY ?? "{}")).toEqual({
|
|
1286
1286
|
provider: {
|
|
1287
|
+
only: ["amazon-bedrock", "amazon-bedrock/eu-west-1", "amazon-bedrock/us-east-1"],
|
|
1287
1288
|
order: ["amazon-bedrock", "amazon-bedrock/eu-west-1", "amazon-bedrock/us-east-1"],
|
|
1288
|
-
allow_fallbacks:
|
|
1289
|
+
allow_fallbacks: false,
|
|
1289
1290
|
},
|
|
1290
1291
|
session_id: "thread_env",
|
|
1291
1292
|
user: "agent.turn | company:company_env | chat:chat_env",
|