@koda-sl/baker-bridge 0.109.0-dev.afb6a264b → 0.109.0-dev.f7ef4c7e1
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 +89 -47
- package/dist/broker/baker-api.d.ts +23 -0
- package/dist/broker/baker-api.d.ts.map +1 -0
- package/dist/broker/baker-api.js +55 -0
- package/dist/broker/baker-api.js.map +1 -0
- package/dist/broker/broker-client.d.ts +10 -0
- package/dist/broker/broker-client.d.ts.map +1 -0
- package/dist/broker/broker-client.js +60 -0
- package/dist/broker/broker-client.js.map +1 -0
- package/dist/broker/broker-process.d.ts +10 -0
- package/dist/broker/broker-process.d.ts.map +1 -0
- package/dist/broker/broker-process.js +20 -0
- package/dist/broker/broker-process.js.map +1 -0
- package/dist/broker/broker-process.test.d.ts +2 -0
- package/dist/broker/broker-process.test.d.ts.map +1 -0
- package/dist/broker/broker-process.test.js +13 -0
- package/dist/broker/broker-process.test.js.map +1 -0
- package/dist/broker/ca.d.ts +38 -0
- package/dist/broker/ca.d.ts.map +1 -0
- package/dist/broker/ca.js +80 -0
- package/dist/broker/ca.js.map +1 -0
- package/dist/broker/ca.test.d.ts +2 -0
- package/dist/broker/ca.test.d.ts.map +1 -0
- package/dist/broker/ca.test.js +58 -0
- package/dist/broker/ca.test.js.map +1 -0
- package/dist/broker/credential-cache.d.ts +24 -0
- package/dist/broker/credential-cache.d.ts.map +1 -0
- package/dist/broker/credential-cache.js +76 -0
- package/dist/broker/credential-cache.js.map +1 -0
- package/dist/broker/credential-cache.test.d.ts +2 -0
- package/dist/broker/credential-cache.test.d.ts.map +1 -0
- package/dist/broker/credential-cache.test.js +136 -0
- package/dist/broker/credential-cache.test.js.map +1 -0
- package/dist/broker/credential-text.d.ts +45 -0
- package/dist/broker/credential-text.d.ts.map +1 -0
- package/dist/broker/credential-text.js +103 -0
- package/dist/broker/credential-text.js.map +1 -0
- package/dist/broker/credential-text.test.d.ts +2 -0
- package/dist/broker/credential-text.test.d.ts.map +1 -0
- package/dist/broker/credential-text.test.js +54 -0
- package/dist/broker/credential-text.test.js.map +1 -0
- package/dist/broker/env.d.ts +21 -0
- package/dist/broker/env.d.ts.map +1 -0
- package/dist/broker/env.js +20 -0
- package/dist/broker/env.js.map +1 -0
- package/dist/broker/main.d.ts +3 -0
- package/dist/broker/main.d.ts.map +1 -0
- package/dist/broker/main.js +57 -0
- package/dist/broker/main.js.map +1 -0
- package/dist/broker/proxy.d.ts +24 -0
- package/dist/broker/proxy.d.ts.map +1 -0
- package/dist/broker/proxy.integration.test.d.ts +2 -0
- package/dist/broker/proxy.integration.test.d.ts.map +1 -0
- package/dist/broker/proxy.integration.test.js +197 -0
- package/dist/broker/proxy.integration.test.js.map +1 -0
- package/dist/broker/proxy.js +147 -0
- package/dist/broker/proxy.js.map +1 -0
- package/dist/broker/rewrite.d.ts +44 -0
- package/dist/broker/rewrite.d.ts.map +1 -0
- package/dist/broker/rewrite.js +291 -0
- package/dist/broker/rewrite.js.map +1 -0
- package/dist/broker/rewrite.test.d.ts +2 -0
- package/dist/broker/rewrite.test.d.ts.map +1 -0
- package/dist/broker/rewrite.test.js +171 -0
- package/dist/broker/rewrite.test.js.map +1 -0
- package/dist/broker/socket-service.d.ts +18 -0
- package/dist/broker/socket-service.d.ts.map +1 -0
- package/dist/broker/socket-service.js +113 -0
- package/dist/broker/socket-service.js.map +1 -0
- package/dist/broker/socket-service.test.d.ts +2 -0
- package/dist/broker/socket-service.test.d.ts.map +1 -0
- package/dist/broker/socket-service.test.js +80 -0
- package/dist/broker/socket-service.test.js.map +1 -0
- package/dist/broker/supervisor-main.d.ts +3 -0
- package/dist/broker/supervisor-main.d.ts.map +1 -0
- package/dist/broker/supervisor-main.js +70 -0
- package/dist/broker/supervisor-main.js.map +1 -0
- package/dist/broker/supervisor.d.ts +25 -0
- package/dist/broker/supervisor.d.ts.map +1 -0
- package/dist/broker/supervisor.js +88 -0
- package/dist/broker/supervisor.js.map +1 -0
- package/dist/broker/supervisor.test.d.ts +2 -0
- package/dist/broker/supervisor.test.d.ts.map +1 -0
- package/dist/broker/supervisor.test.js +161 -0
- package/dist/broker/supervisor.test.js.map +1 -0
- package/dist/broker/token-bucket.d.ts +9 -0
- package/dist/broker/token-bucket.d.ts.map +1 -0
- package/dist/broker/token-bucket.js +18 -0
- package/dist/broker/token-bucket.js.map +1 -0
- package/dist/broker/usage-reporter.d.ts +18 -0
- package/dist/broker/usage-reporter.d.ts.map +1 -0
- package/dist/broker/usage-reporter.js +31 -0
- package/dist/broker/usage-reporter.js.map +1 -0
- package/dist/broker/usage-reporter.test.d.ts +2 -0
- package/dist/broker/usage-reporter.test.d.ts.map +1 -0
- package/dist/broker/usage-reporter.test.js +20 -0
- package/dist/broker/usage-reporter.test.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/hono/agent-session.d.ts +3 -0
- package/dist/hono/agent-session.d.ts.map +1 -1
- package/dist/hono/agent-session.js +15 -0
- package/dist/hono/agent-session.js.map +1 -1
- package/dist/hono/agent-tasks.js +4 -4
- package/dist/hono/agent-tasks.js.map +1 -1
- package/dist/hono/agent.d.ts +2 -0
- package/dist/hono/agent.d.ts.map +1 -1
- package/dist/hono/agent.js +11 -2
- package/dist/hono/agent.js.map +1 -1
- package/dist/hono/agent.test.js +8 -2
- package/dist/hono/agent.test.js.map +1 -1
- package/dist/hono/avatar-accent.d.ts +23 -5
- package/dist/hono/avatar-accent.d.ts.map +1 -1
- package/dist/hono/avatar-accent.js +54 -63
- package/dist/hono/avatar-accent.js.map +1 -1
- package/dist/hono/avatar-accent.test.js +64 -35
- package/dist/hono/avatar-accent.test.js.map +1 -1
- package/dist/hono/avatar-casting.d.ts +1 -0
- package/dist/hono/avatar-casting.d.ts.map +1 -1
- package/dist/hono/avatar-casting.js +18 -4
- package/dist/hono/avatar-casting.js.map +1 -1
- package/dist/hono/avatar-casting.test.js +5 -0
- package/dist/hono/avatar-casting.test.js.map +1 -1
- package/dist/hono/avatar-face-question.d.ts +23 -6
- package/dist/hono/avatar-face-question.d.ts.map +1 -1
- package/dist/hono/avatar-face-question.js +48 -59
- package/dist/hono/avatar-face-question.js.map +1 -1
- package/dist/hono/avatar-face-question.test.js +46 -101
- package/dist/hono/avatar-face-question.test.js.map +1 -1
- package/dist/hono/baker-ui-tool-schemas.test.js +30 -4
- package/dist/hono/baker-ui-tool-schemas.test.js.map +1 -1
- package/dist/hono/blocking-card.d.ts +12 -0
- package/dist/hono/blocking-card.d.ts.map +1 -0
- package/dist/hono/blocking-card.js +12 -0
- package/dist/hono/blocking-card.js.map +1 -0
- package/dist/hono/bridge-job.d.ts +48 -2
- package/dist/hono/bridge-job.d.ts.map +1 -1
- package/dist/hono/bridge-job.js +202 -34
- package/dist/hono/bridge-job.js.map +1 -1
- package/dist/hono/bridge-job.test.js +344 -20
- package/dist/hono/bridge-job.test.js.map +1 -1
- package/dist/hono/check-content.d.ts +49 -0
- package/dist/hono/check-content.d.ts.map +1 -0
- package/dist/hono/check-content.js +182 -0
- package/dist/hono/check-content.js.map +1 -0
- package/dist/hono/check-content.test.d.ts +2 -0
- package/dist/hono/check-content.test.d.ts.map +1 -0
- package/dist/hono/check-content.test.js +87 -0
- package/dist/hono/check-content.test.js.map +1 -0
- package/dist/hono/connection-input.d.ts +170 -12
- package/dist/hono/connection-input.d.ts.map +1 -1
- package/dist/hono/connection-input.js +166 -14
- package/dist/hono/connection-input.js.map +1 -1
- package/dist/hono/connection-input.test.js +112 -9
- package/dist/hono/connection-input.test.js.map +1 -1
- package/dist/hono/convex.d.ts +8 -0
- package/dist/hono/convex.d.ts.map +1 -1
- package/dist/hono/convex.js +8 -0
- package/dist/hono/convex.js.map +1 -1
- package/dist/hono/convex.test.js +4 -1
- package/dist/hono/convex.test.js.map +1 -1
- package/dist/hono/credential-input.d.ts +39 -0
- package/dist/hono/credential-input.d.ts.map +1 -0
- package/dist/hono/credential-input.js +78 -0
- package/dist/hono/credential-input.js.map +1 -0
- package/dist/hono/credential-scrub.d.ts +42 -0
- package/dist/hono/credential-scrub.d.ts.map +1 -0
- package/dist/hono/credential-scrub.js +173 -0
- package/dist/hono/credential-scrub.js.map +1 -0
- package/dist/hono/credential-scrub.test.d.ts +2 -0
- package/dist/hono/credential-scrub.test.d.ts.map +1 -0
- package/dist/hono/credential-scrub.test.js +130 -0
- package/dist/hono/credential-scrub.test.js.map +1 -0
- package/dist/hono/env.d.ts +1 -0
- package/dist/hono/env.d.ts.map +1 -1
- package/dist/hono/env.js +2 -0
- package/dist/hono/env.js.map +1 -1
- package/dist/hono/flow-crypto.d.ts +2 -1
- package/dist/hono/flow-crypto.d.ts.map +1 -1
- package/dist/hono/flow-crypto.js +50 -26
- package/dist/hono/flow-crypto.js.map +1 -1
- package/dist/hono/flow-crypto.test.js +32 -0
- package/dist/hono/flow-crypto.test.js.map +1 -1
- package/dist/hono/flow-input-card-fields.test.d.ts +10 -0
- package/dist/hono/flow-input-card-fields.test.d.ts.map +1 -0
- package/dist/hono/flow-input-card-fields.test.js +26 -0
- package/dist/hono/flow-input-card-fields.test.js.map +1 -0
- package/dist/hono/flow-input-fields.test.js +1 -1
- package/dist/hono/flow-input-fields.test.js.map +1 -1
- package/dist/hono/flow-input.d.ts +23 -2
- package/dist/hono/flow-input.d.ts.map +1 -1
- package/dist/hono/flow-input.js +63 -14
- package/dist/hono/flow-input.js.map +1 -1
- package/dist/hono/flow-input.test.js +67 -11
- package/dist/hono/flow-input.test.js.map +1 -1
- package/dist/hono/jev.d.ts +16 -0
- package/dist/hono/jev.d.ts.map +1 -0
- package/dist/hono/jev.js +60 -0
- package/dist/hono/jev.js.map +1 -0
- package/dist/hono/jev.test.d.ts +2 -0
- package/dist/hono/jev.test.d.ts.map +1 -0
- package/dist/hono/jev.test.js +15 -0
- package/dist/hono/jev.test.js.map +1 -0
- package/dist/hono/knowledge-content.d.ts.map +1 -1
- package/dist/hono/knowledge-content.js +4 -2
- package/dist/hono/knowledge-content.js.map +1 -1
- package/dist/hono/knowledge-content.test.js +6 -5
- package/dist/hono/knowledge-content.test.js.map +1 -1
- package/dist/hono/mcp-servers.d.ts +8 -1
- package/dist/hono/mcp-servers.d.ts.map +1 -1
- package/dist/hono/mcp-servers.js +17 -6
- package/dist/hono/mcp-servers.js.map +1 -1
- package/dist/hono/mcp-servers.test.js +25 -0
- package/dist/hono/mcp-servers.test.js.map +1 -1
- package/dist/hono/model-capabilities.d.ts.map +1 -1
- package/dist/hono/model-capabilities.js +20 -9
- package/dist/hono/model-capabilities.js.map +1 -1
- package/dist/hono/model-capabilities.test.js +16 -8
- package/dist/hono/model-capabilities.test.js.map +1 -1
- package/dist/hono/oom-priority.agent.test.d.ts +2 -0
- package/dist/hono/oom-priority.agent.test.d.ts.map +1 -0
- package/dist/hono/oom-priority.agent.test.js +138 -0
- package/dist/hono/oom-priority.agent.test.js.map +1 -0
- package/dist/hono/oom-priority.d.ts +39 -0
- package/dist/hono/oom-priority.d.ts.map +1 -0
- package/dist/hono/oom-priority.js +138 -0
- package/dist/hono/oom-priority.js.map +1 -0
- package/dist/hono/oom-priority.test.d.ts +2 -0
- package/dist/hono/oom-priority.test.d.ts.map +1 -0
- package/dist/hono/oom-priority.test.js +52 -0
- package/dist/hono/oom-priority.test.js.map +1 -0
- package/dist/hono/openrouter-session.d.ts.map +1 -1
- package/dist/hono/openrouter-session.js +12 -1
- package/dist/hono/openrouter-session.js.map +1 -1
- package/dist/hono/openrouter-session.test.js +9 -3
- package/dist/hono/openrouter-session.test.js.map +1 -1
- package/dist/hono/prompt-context.d.ts +8 -1
- package/dist/hono/prompt-context.d.ts.map +1 -1
- package/dist/hono/prompt-context.js +45 -7
- package/dist/hono/prompt-context.js.map +1 -1
- package/dist/hono/prompt-context.test.js +32 -1
- package/dist/hono/prompt-context.test.js.map +1 -1
- package/dist/hono/publish-recovery.d.ts +1 -1
- package/dist/hono/publish-recovery.d.ts.map +1 -1
- package/dist/hono/publish-recovery.js +9 -6
- package/dist/hono/publish-recovery.js.map +1 -1
- package/dist/hono/publish-recovery.test.js +11 -2
- package/dist/hono/publish-recovery.test.js.map +1 -1
- package/dist/hono/relay.d.ts +10 -1
- package/dist/hono/relay.d.ts.map +1 -1
- package/dist/hono/relay.js +6 -0
- package/dist/hono/relay.js.map +1 -1
- package/dist/hono/sandbox-content.d.ts +2 -0
- package/dist/hono/sandbox-content.d.ts.map +1 -1
- package/dist/hono/sandbox-content.js +8 -4
- package/dist/hono/sandbox-content.js.map +1 -1
- package/dist/hono/sandbox-content.test.js +20 -1
- package/dist/hono/sandbox-content.test.js.map +1 -1
- package/dist/hono/server.d.ts.map +1 -1
- package/dist/hono/server.js +32 -0
- package/dist/hono/server.js.map +1 -1
- package/dist/hono/server.test.js +21 -1
- package/dist/hono/server.test.js.map +1 -1
- package/dist/hono/session-continuity.integration.test.js +10 -1
- package/dist/hono/session-continuity.integration.test.js.map +1 -1
- package/dist/hono/tag-fields.d.ts.map +1 -1
- package/dist/hono/tag-fields.js +2 -0
- package/dist/hono/tag-fields.js.map +1 -1
- package/dist/hono/tag-input.d.ts +124 -3
- package/dist/hono/tag-input.d.ts.map +1 -1
- package/dist/hono/tag-input.js +27 -17
- package/dist/hono/tag-input.js.map +1 -1
- package/dist/hono/tag-input.test.js +19 -1
- package/dist/hono/tag-input.test.js.map +1 -1
- package/dist/hono/tool-mentions.d.ts.map +1 -1
- package/dist/hono/tool-mentions.js +1 -0
- package/dist/hono/tool-mentions.js.map +1 -1
- package/dist/hono/tool-mentions.test.js +5 -0
- package/dist/hono/tool-mentions.test.js.map +1 -1
- package/dist/hono/types.d.ts +8 -0
- package/dist/hono/types.d.ts.map +1 -1
- package/dist/hono/workspace-script.d.ts +10 -0
- package/dist/hono/workspace-script.d.ts.map +1 -0
- package/dist/hono/workspace-script.js +19 -0
- package/dist/hono/workspace-script.js.map +1 -0
- package/dist/hono/workspace-settle.d.ts +1 -1
- package/dist/hono/workspace-settle.d.ts.map +1 -1
- package/dist/hono/workspace-settle.js +12 -8
- package/dist/hono/workspace-settle.js.map +1 -1
- package/dist/review/digest.d.ts +8 -1
- package/dist/review/digest.d.ts.map +1 -1
- package/dist/review/digest.js +10 -43
- package/dist/review/digest.js.map +1 -1
- package/dist/review/digest.test.js +11 -6
- package/dist/review/digest.test.js.map +1 -1
- package/dist/review/evidence-block.js +1 -1
- package/dist/review/evidence-block.js.map +1 -1
- package/dist/review/evidence-block.test.js +0 -10
- package/dist/review/evidence-block.test.js.map +1 -1
- package/dist/review/shell-policy.d.ts +6 -0
- package/dist/review/shell-policy.d.ts.map +1 -1
- package/dist/review/shell-policy.js +240 -72
- package/dist/review/shell-policy.js.map +1 -1
- package/dist/review/shell-policy.test.js +114 -0
- package/dist/review/shell-policy.test.js.map +1 -1
- package/package.json +9 -5
- package/dist/hono/latitude-telemetry.d.ts +0 -17
- package/dist/hono/latitude-telemetry.d.ts.map +0 -1
- package/dist/hono/latitude-telemetry.js +0 -52
- package/dist/hono/latitude-telemetry.js.map +0 -1
- package/dist/hono/latitude-telemetry.test.d.ts +0 -2
- package/dist/hono/latitude-telemetry.test.d.ts.map +0 -1
- package/dist/hono/latitude-telemetry.test.js +0 -18
- package/dist/hono/latitude-telemetry.test.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-capabilities.d.ts","sourceRoot":"","sources":["../../src/hono/model-capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAgB9D,eAAO,MAAM,aAAa,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"model-capabilities.d.ts","sourceRoot":"","sources":["../../src/hono/model-capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAgB9D,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAQ/C,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAkBpD;AAwBD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAKrF;AA6CD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,EAAE,GAAG,SAAS,CAKrF;AA4BD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAM9F;AAMD,eAAO,MAAM,eAAe,sBAAsB,CAAC;AAcnD,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAO3F;AAGD,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE9E"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Anthropic-native ID expected by the Claude Agent SDK `query({ options: { model } })`.
|
|
2
2
|
// Opus 5.5 is a deliberate quality-over-cost choice: $4/$20 per MTok on OpenRouter
|
|
3
|
-
// against Sonnet 5's $2/$10, so it is 2x the price on input, output AND cache
|
|
3
|
+
// against Sonnet 5.5's $2/$10, so it is 2x the price on input, output AND cache
|
|
4
4
|
// reads. Most of a turn's spend is re-reading context, so that multiplier lands
|
|
5
5
|
// on the dominant term — it pays for itself only if the extra capability closes
|
|
6
6
|
// the same work in fewer turns.
|
|
7
7
|
//
|
|
8
8
|
// The blast radius is contained on two sides: the main thread runs at
|
|
9
9
|
// `medium` effort (see `bridge-job.ts`), and the shared subagents pin themselves
|
|
10
|
-
// to Sonnet 5 in their own frontmatter rather than inheriting this. Without that
|
|
10
|
+
// to Sonnet 5.5 in their own frontmatter rather than inheriting this. Without that
|
|
11
11
|
// pin every fan-out worker would silently move to Opus pricing too.
|
|
12
12
|
//
|
|
13
13
|
// The Session review runs on the same id (`REVIEW_MODEL` in the backend's
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
export const DEFAULT_MODEL = "claude-opus-5-5";
|
|
16
16
|
// No turn runs on a 4.x Opus or Sonnet any more. Such an id is passed through
|
|
17
17
|
// unchanged so it reads as unknown (no window, an override naming it ignored)
|
|
18
|
-
// instead of silently becoming its 5.x successor. Haiku 4.5
|
|
18
|
+
// instead of silently becoming its 5.x successor. Haiku 4.5 still resolves; development runs
|
|
19
|
+
// on Haiku 5.5.
|
|
19
20
|
const RETIRED_FAMILY_VERSION = /(opus|sonnet)-4/;
|
|
20
21
|
export function normalizeModel(model) {
|
|
21
22
|
const lower = model.toLowerCase();
|
|
@@ -28,10 +29,11 @@ export function normalizeModel(model) {
|
|
|
28
29
|
return lower.includes("opus-5.5") || lower.includes("opus-5-5") ? "claude-opus-5-5" : "claude-opus-5";
|
|
29
30
|
}
|
|
30
31
|
if (lower.includes("haiku")) {
|
|
31
|
-
return "claude-haiku-4-5";
|
|
32
|
+
return lower.includes("haiku-5.5") || lower.includes("haiku-5-5") ? "claude-haiku-5-5" : "claude-haiku-4-5";
|
|
32
33
|
}
|
|
34
|
+
// Same for "sonnet-5" and the Sonnet 5.5 slugs.
|
|
33
35
|
if (lower.includes("sonnet")) {
|
|
34
|
-
return "claude-sonnet-5";
|
|
36
|
+
return lower.includes("sonnet-5.5") || lower.includes("sonnet-5-5") ? "claude-sonnet-5-5" : "claude-sonnet-5";
|
|
35
37
|
}
|
|
36
38
|
return model;
|
|
37
39
|
}
|
|
@@ -48,7 +50,9 @@ export function normalizeModel(model) {
|
|
|
48
50
|
const MODEL_CONTEXT_WINDOW = {
|
|
49
51
|
"claude-opus-5-5": 1_000_000,
|
|
50
52
|
"claude-opus-5": 1_000_000,
|
|
53
|
+
"claude-sonnet-5-5": 1_000_000,
|
|
51
54
|
"claude-sonnet-5": 1_000_000,
|
|
55
|
+
"claude-haiku-5-5": 1_000_000,
|
|
52
56
|
"claude-haiku-4-5": 200_000,
|
|
53
57
|
};
|
|
54
58
|
// The context window for a model id, or null when we don't know it (callers then
|
|
@@ -63,8 +67,8 @@ export function contextWindowForModel(model) {
|
|
|
63
67
|
// Corrects the context window the *runtime* believes each model has. Needed for
|
|
64
68
|
// every 1M model we run, Opus 5.5 (the default) included.
|
|
65
69
|
//
|
|
66
|
-
// The API does not require this beta. Anthropic serves 1M by default on Opus 5.5, Opus 5
|
|
67
|
-
// and Sonnet 5 — `context-1m-2025-08-07` is the legacy
|
|
70
|
+
// The API does not require this beta. Anthropic serves 1M by default on Opus 5.5, Opus 5,
|
|
71
|
+
// Sonnet 5.5 and Sonnet 5 — `context-1m-2025-08-07` is the legacy
|
|
68
72
|
// Sonnet 4/4.5 header, and sending it changes nothing about the response (verified
|
|
69
73
|
// against the OpenRouter endpoint: identical 200s with and without it).
|
|
70
74
|
//
|
|
@@ -86,7 +90,8 @@ export function contextWindowForModel(model) {
|
|
|
86
90
|
// than the equivalent `[1m]` id suffix so no `[1m]` string reaches OpenRouter as a
|
|
87
91
|
// model name.
|
|
88
92
|
//
|
|
89
|
-
// Haiku
|
|
93
|
+
// Haiku 5.5 is `native_1m` and `supports_1m_beta` like the rest. Haiku 4.5 is
|
|
94
|
+
// excluded because it is genuinely a 200k model — the CLI refuses this
|
|
90
95
|
// beta for it, and claiming 1M would only make the meter lie the other way.
|
|
91
96
|
//
|
|
92
97
|
// Opus 5.5 and Opus 5 belong here for the same reason as the rest: their CLI catalog
|
|
@@ -94,7 +99,13 @@ export function contextWindowForModel(model) {
|
|
|
94
99
|
// the first-party host we never use. Omitting either would put the default model back on a
|
|
95
100
|
// 200k window with no error — the exact regression this block exists to prevent.
|
|
96
101
|
const ONE_MILLION_CONTEXT_BETA = "context-1m-2025-08-07";
|
|
97
|
-
const MODELS_NEEDING_1M_BETA = new Set([
|
|
102
|
+
const MODELS_NEEDING_1M_BETA = new Set([
|
|
103
|
+
"claude-opus-5-5",
|
|
104
|
+
"claude-opus-5",
|
|
105
|
+
"claude-sonnet-5-5",
|
|
106
|
+
"claude-sonnet-5",
|
|
107
|
+
"claude-haiku-5-5",
|
|
108
|
+
]);
|
|
98
109
|
export function betasForModel(model) {
|
|
99
110
|
if (!model || !MODELS_NEEDING_1M_BETA.has(normalizeModel(model))) {
|
|
100
111
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-capabilities.js","sourceRoot":"","sources":["../../src/hono/model-capabilities.ts"],"names":[],"mappings":"AAEA,wFAAwF;AACxF,mFAAmF;AACnF,
|
|
1
|
+
{"version":3,"file":"model-capabilities.js","sourceRoot":"","sources":["../../src/hono/model-capabilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@ import { AGENT_MODEL_ENV, agentModelOverride, autoCompactWindowForModel, betasFo
|
|
|
7
7
|
describe("normalizeModel", () => {
|
|
8
8
|
it("strips the anthropic/ prefix from Sonnet 5", () => {
|
|
9
9
|
expect(normalizeModel("anthropic/claude-sonnet-5")).toBe("claude-sonnet-5");
|
|
10
|
+
expect(normalizeModel("anthropic/claude-sonnet-5.5")).toBe("claude-sonnet-5-5");
|
|
11
|
+
expect(normalizeModel("claude-sonnet-5-5")).toBe("claude-sonnet-5-5");
|
|
10
12
|
});
|
|
11
13
|
it("normalizes Opus 5", () => {
|
|
12
14
|
expect(normalizeModel("anthropic/claude-opus-5")).toBe("claude-opus-5");
|
|
@@ -30,6 +32,10 @@ describe("normalizeModel", () => {
|
|
|
30
32
|
it("normalizes Haiku by stripping the prefix", () => {
|
|
31
33
|
expect(normalizeModel("anthropic/claude-haiku-4-5")).toBe("claude-haiku-4-5");
|
|
32
34
|
});
|
|
35
|
+
it("normalizes Haiku 5.5 without collapsing it into Haiku 4.5", () => {
|
|
36
|
+
expect(normalizeModel("claude-haiku-5-5")).toBe("claude-haiku-5-5");
|
|
37
|
+
expect(normalizeModel("anthropic/claude-haiku-5.5")).toBe("claude-haiku-5-5");
|
|
38
|
+
});
|
|
33
39
|
it("normalizes dated Haiku variants", () => {
|
|
34
40
|
expect(normalizeModel("anthropic/claude-haiku-4-5-20251001")).toBe("claude-haiku-4-5");
|
|
35
41
|
});
|
|
@@ -49,6 +55,10 @@ describe("contextWindowForModel", () => {
|
|
|
49
55
|
});
|
|
50
56
|
it("returns 1M for Sonnet 5", () => {
|
|
51
57
|
expect(contextWindowForModel("claude-sonnet-5")).toBe(1_000_000);
|
|
58
|
+
expect(contextWindowForModel("claude-sonnet-5-5")).toBe(1_000_000);
|
|
59
|
+
});
|
|
60
|
+
it("returns 1M for Haiku 5.5", () => {
|
|
61
|
+
expect(contextWindowForModel("claude-haiku-5-5")).toBe(1_000_000);
|
|
52
62
|
});
|
|
53
63
|
it("returns 200k for Haiku 4.5 (not a 1M model on OpenRouter)", () => {
|
|
54
64
|
expect(contextWindowForModel("claude-haiku-4-5")).toBe(200_000);
|
|
@@ -73,9 +83,13 @@ describe("betasForModel", () => {
|
|
|
73
83
|
});
|
|
74
84
|
it("requests the 1M context beta for Sonnet 5", () => {
|
|
75
85
|
expect(betasForModel("claude-sonnet-5")).toEqual(["context-1m-2025-08-07"]);
|
|
86
|
+
expect(betasForModel("claude-sonnet-5-5")).toEqual(["context-1m-2025-08-07"]);
|
|
76
87
|
});
|
|
77
88
|
// Haiku 4.5 is genuinely a 200k model — the CLI refuses the beta for it, so
|
|
78
89
|
// sending it would be a lie we would then divide the meter by.
|
|
90
|
+
it("requests the 1M context beta for Haiku 5.5", () => {
|
|
91
|
+
expect(betasForModel("claude-haiku-5-5")).toEqual(["context-1m-2025-08-07"]);
|
|
92
|
+
});
|
|
79
93
|
it("sends no beta for Haiku 4.5, which is genuinely 200k", () => {
|
|
80
94
|
expect(betasForModel("claude-haiku-4-5")).toBeUndefined();
|
|
81
95
|
});
|
|
@@ -145,13 +159,7 @@ describe("resolveAgentModel", () => {
|
|
|
145
159
|
// walk its prototype and accept every `Object.prototype` member name.
|
|
146
160
|
// `normalizeModel` passes an unrecognized string through unchanged, so these
|
|
147
161
|
// would reach the SDK as a model id and the CLI as CLAUDE_CODE_SUBAGENT_MODEL.
|
|
148
|
-
it.each([
|
|
149
|
-
"constructor",
|
|
150
|
-
"toString",
|
|
151
|
-
"valueOf",
|
|
152
|
-
"hasOwnProperty",
|
|
153
|
-
"__proto__",
|
|
154
|
-
])("ignores %s, which is a prototype member and not a model", (name) => {
|
|
162
|
+
it.each(["constructor", "toString", "valueOf", "hasOwnProperty", "__proto__"])("ignores %s, which is a prototype member and not a model", (name) => {
|
|
155
163
|
expect(resolveAgentModel({ [AGENT_MODEL_ENV]: name })).toBe(DEFAULT_MODEL);
|
|
156
164
|
expect(agentModelOverride({ [AGENT_MODEL_ENV]: name })).toBeUndefined();
|
|
157
165
|
});
|
|
@@ -159,7 +167,7 @@ describe("resolveAgentModel", () => {
|
|
|
159
167
|
describe("agentModelOverride", () => {
|
|
160
168
|
// The bridge forwards this to the CLI as CLAUDE_CODE_SUBAGENT_MODEL, so it has
|
|
161
169
|
// to stay absent in production — otherwise every fan-out worker would lose the
|
|
162
|
-
// Sonnet 5 pin in its own frontmatter.
|
|
170
|
+
// Sonnet 5.5 pin in its own frontmatter.
|
|
163
171
|
it("is absent when the deployment pins nothing", () => {
|
|
164
172
|
expect(agentModelOverride({})).toBeUndefined();
|
|
165
173
|
expect(agentModelOverride({ [AGENT_MODEL_ENV]: " " })).toBeUndefined();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-capabilities.test.js","sourceRoot":"","sources":["../../src/hono/model-capabilities.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,yBAAyB,EACzB,aAAa,EACb,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAEjC,wEAAwE;AACxE,wEAAwE;AACxE,+EAA+E;AAC/E,oDAAoD;AAEpD,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"model-capabilities.test.js","sourceRoot":"","sources":["../../src/hono/model-capabilities.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oom-priority.agent.test.d.ts","sourceRoot":"","sources":["../../src/hono/oom-priority.agent.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
6
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
7
|
+
import { AGENT_COMM, agentShellPrefixEnv, KILL_FIRST_ADJ, killFirstWrapper } from "./oom-priority.js";
|
|
8
|
+
function stream(res, content, stopReason) {
|
|
9
|
+
res.writeHead(200, { "content-type": "text/event-stream" });
|
|
10
|
+
const events = [
|
|
11
|
+
[
|
|
12
|
+
"message_start",
|
|
13
|
+
{
|
|
14
|
+
type: "message_start",
|
|
15
|
+
message: {
|
|
16
|
+
id: "msg_test",
|
|
17
|
+
type: "message",
|
|
18
|
+
role: "assistant",
|
|
19
|
+
model: "claude-sonnet-4-5",
|
|
20
|
+
content: [],
|
|
21
|
+
stop_reason: null,
|
|
22
|
+
usage: { input_tokens: 1, output_tokens: 1 },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
...content,
|
|
27
|
+
["message_delta", { type: "message_delta", delta: { stop_reason: stopReason }, usage: { output_tokens: 1 } }],
|
|
28
|
+
["message_stop", { type: "message_stop" }],
|
|
29
|
+
];
|
|
30
|
+
for (const [event, data] of events)
|
|
31
|
+
res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
32
|
+
res.end();
|
|
33
|
+
}
|
|
34
|
+
function text(value) {
|
|
35
|
+
return [
|
|
36
|
+
["content_block_start", { type: "content_block_start", index: 0, content_block: { type: "text", text: "" } }],
|
|
37
|
+
["content_block_delta", { type: "content_block_delta", index: 0, delta: { type: "text_delta", text: value } }],
|
|
38
|
+
["content_block_stop", { type: "content_block_stop", index: 0 }],
|
|
39
|
+
];
|
|
40
|
+
}
|
|
41
|
+
function bash(command) {
|
|
42
|
+
return [
|
|
43
|
+
[
|
|
44
|
+
"content_block_start",
|
|
45
|
+
{
|
|
46
|
+
type: "content_block_start",
|
|
47
|
+
index: 0,
|
|
48
|
+
content_block: { type: "tool_use", id: "toolu_probe", name: "Bash", input: {} },
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
[
|
|
52
|
+
"content_block_delta",
|
|
53
|
+
{
|
|
54
|
+
type: "content_block_delta",
|
|
55
|
+
index: 0,
|
|
56
|
+
delta: { type: "input_json_delta", partial_json: JSON.stringify({ command, description: "probe" }) },
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
["content_block_stop", { type: "content_block_stop", index: 0 }],
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
/** A model that asks for one Bash command, then records what the command printed. */
|
|
63
|
+
function scriptedModel(command) {
|
|
64
|
+
const toolResults = [];
|
|
65
|
+
const server = createServer((req, res) => {
|
|
66
|
+
let body = "";
|
|
67
|
+
req.on("data", (chunk) => {
|
|
68
|
+
body += chunk;
|
|
69
|
+
});
|
|
70
|
+
req.on("end", () => {
|
|
71
|
+
if (!req.url?.includes("/v1/messages") || req.url.includes("count_tokens")) {
|
|
72
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
73
|
+
res.end(JSON.stringify({ input_tokens: 1 }));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const request = JSON.parse(body || "{}");
|
|
77
|
+
const messages = JSON.stringify(request.messages ?? []);
|
|
78
|
+
if (!request.tools?.length)
|
|
79
|
+
return stream(res, text("ok"), "end_turn");
|
|
80
|
+
if (!messages.includes("tool_result"))
|
|
81
|
+
return stream(res, bash(command), "tool_use");
|
|
82
|
+
toolResults.push(messages);
|
|
83
|
+
return stream(res, text("done"), "end_turn");
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
return { server, toolResults };
|
|
87
|
+
}
|
|
88
|
+
const servers = [];
|
|
89
|
+
afterEach(() => {
|
|
90
|
+
for (const server of servers.splice(0))
|
|
91
|
+
server.close();
|
|
92
|
+
});
|
|
93
|
+
/** Our wrapper behind one that logs how many arguments the agent handed it. */
|
|
94
|
+
function recordingPrefix(wrapper) {
|
|
95
|
+
const dir = mkdtempSync(join(tmpdir(), "kill-first-recorder-"));
|
|
96
|
+
const log = join(dir, "calls.log");
|
|
97
|
+
const prefix = join(dir, "record.sh");
|
|
98
|
+
writeFileSync(prefix, `#!/bin/sh\necho "argc=$#" >> ${log}\nexec ${wrapper} "$@"\n`);
|
|
99
|
+
chmodSync(prefix, 0o755);
|
|
100
|
+
return { prefix, calls: () => (existsSync(log) ? readFileSync(log, "utf8") : "") };
|
|
101
|
+
}
|
|
102
|
+
describe("the agent's Bash commands", () => {
|
|
103
|
+
it("run through the kill-first wrapper, as the script the agent would have run", async () => {
|
|
104
|
+
const model = scriptedModel('echo "probe-adj=$(cat /proc/self/oom_score_adj 2>/dev/null || echo none) probe-agent=$(cat /proc/$PPID/comm 2>/dev/null || echo none)"; [[ 1 == 1 ]]');
|
|
105
|
+
servers.push(model.server);
|
|
106
|
+
await new Promise((resolve) => model.server.listen(0, "127.0.0.1", resolve));
|
|
107
|
+
const { port } = model.server.address();
|
|
108
|
+
const recorder = recordingPrefix(agentShellPrefixEnv(killFirstWrapper(), {}).CLAUDE_CODE_SHELL_PREFIX ?? "");
|
|
109
|
+
const run = query({
|
|
110
|
+
prompt: "probe",
|
|
111
|
+
options: {
|
|
112
|
+
model: "claude-sonnet-4-5",
|
|
113
|
+
cwd: mkdtempSync(join(tmpdir(), "kill-first-agent-")),
|
|
114
|
+
settingSources: [],
|
|
115
|
+
allowedTools: ["Bash"],
|
|
116
|
+
permissionMode: "bypassPermissions",
|
|
117
|
+
allowDangerouslySkipPermissions: true,
|
|
118
|
+
env: {
|
|
119
|
+
PATH: process.env.PATH,
|
|
120
|
+
HOME: mkdtempSync(join(tmpdir(), "kill-first-home-")),
|
|
121
|
+
ANTHROPIC_BASE_URL: `http://127.0.0.1:${port}`,
|
|
122
|
+
ANTHROPIC_API_KEY: "sk-ant-test",
|
|
123
|
+
CLAUDE_CODE_SHELL_PREFIX: recorder.prefix,
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
for await (const _message of run) {
|
|
128
|
+
// Drain the turn.
|
|
129
|
+
}
|
|
130
|
+
expect(recorder.calls()).toBe("argc=1\n");
|
|
131
|
+
// Off Linux there is no score to read; the command must still run intact.
|
|
132
|
+
const expected = process.platform === "linux" ? String(KILL_FIRST_ADJ) : "none";
|
|
133
|
+
expect(model.toolResults.join("")).toContain(`probe-adj=${expected}`);
|
|
134
|
+
// The scan behind the wrapper finds the agent by its process name.
|
|
135
|
+
expect(model.toolResults.join("")).toContain(`probe-agent=${process.platform === "linux" ? AGENT_COMM : "none"}`);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
//# sourceMappingURL=oom-priority.agent.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oom-priority.agent.test.js","sourceRoot":"","sources":["../../src/hono/oom-priority.agent.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type ProcessEntry = {
|
|
2
|
+
pid: number;
|
|
3
|
+
ppid: number;
|
|
4
|
+
comm: string;
|
|
5
|
+
oomScoreAdj: number;
|
|
6
|
+
};
|
|
7
|
+
/** The kernel's maximum: a command of any size is killed before any process left alone, whatever score it started with. */
|
|
8
|
+
export declare const KILL_FIRST_ADJ = 1000;
|
|
9
|
+
/** The agent binary's process name, which the scan finds it by. */
|
|
10
|
+
export declare const AGENT_COMM = "claude";
|
|
11
|
+
/** Pids of the agent's commands — every descendant of an agent process that is not one itself. */
|
|
12
|
+
export declare function killFirst(processes: readonly ProcessEntry[]): number[];
|
|
13
|
+
/** `pid (comm) state ppid …` — the name can hold spaces and parentheses, so it ends at the last `)`. */
|
|
14
|
+
export declare function parseStat(stat: string): {
|
|
15
|
+
pid: number;
|
|
16
|
+
ppid: number;
|
|
17
|
+
comm: string;
|
|
18
|
+
} | null;
|
|
19
|
+
/**
|
|
20
|
+
* Marks the agent's commands every 2 s: the backstop for what the wrapper never
|
|
21
|
+
* sees (an MCP server, a hook not run by bash). Raising a score needs no
|
|
22
|
+
* privilege, so the bridge does it for the processes its agent started; a
|
|
23
|
+
* command dead between the scan and the write is skipped. Off where there is no
|
|
24
|
+
* /proc.
|
|
25
|
+
*/
|
|
26
|
+
export declare function startOomPriority(log?: (message: string) => void): void;
|
|
27
|
+
/** Writes the wrapper into `dir` and returns its path. */
|
|
28
|
+
export declare function installKillFirstWrapper(dir: string): string;
|
|
29
|
+
/** The agent's env addition: the wrapper, unless the Runtime already wraps commands its own way. */
|
|
30
|
+
export declare function agentShellPrefixEnv(wrapper: string | null, env: Record<string, string | undefined>): {
|
|
31
|
+
CLAUDE_CODE_SHELL_PREFIX?: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* The wrapper, written on first use so no agent starts without it whatever
|
|
35
|
+
* started the bridge. Null only where the temp dir is not writable. Off Linux
|
|
36
|
+
* the score write fails quietly and the command runs as is.
|
|
37
|
+
*/
|
|
38
|
+
export declare function killFirstWrapper(log?: (message: string) => void): string | null;
|
|
39
|
+
//# sourceMappingURL=oom-priority.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oom-priority.d.ts","sourceRoot":"","sources":["../../src/hono/oom-priority.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,YAAY,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5F,2HAA2H;AAC3H,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC,mEAAmE;AACnE,eAAO,MAAM,UAAU,WAAW,CAAC;AAEnC,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,SAAS,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,EAAE,CAetE;AAED,wGAAwG;AACxG,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAQ1F;AAkBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAmB,GAAG,IAAI,CAmBpF;AAgBD,0DAA0D;AAC1D,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK3D;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,GAAG,IAAI,EACtB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACtC;IAAE,wBAAwB,CAAC,EAAE,MAAM,CAAA;CAAE,CAGvC;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAmB,GAAG,MAAM,GAAG,IAAI,CAW7F"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which processes the kernel's OOM killer takes first in a Runtime.
|
|
3
|
+
*
|
|
4
|
+
* Every process starts at the same score, so the kernel kills the biggest. When
|
|
5
|
+
* parallel agents fill the sandbox's memory with their commands (a 20-agent run
|
|
6
|
+
* held 60 `baker` processes of ~126 MB each), the biggest is the agent itself
|
|
7
|
+
* or the credential broker, and either ends the turn. A command the agent ran is
|
|
8
|
+
* the one to lose: it fails as `Killed` and the agent can run it again.
|
|
9
|
+
*/
|
|
10
|
+
import { chmodSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
/** The kernel's maximum: a command of any size is killed before any process left alone, whatever score it started with. */
|
|
14
|
+
export const KILL_FIRST_ADJ = 1000;
|
|
15
|
+
/** The agent binary's process name, which the scan finds it by. */
|
|
16
|
+
export const AGENT_COMM = "claude";
|
|
17
|
+
/** Pids of the agent's commands — every descendant of an agent process that is not one itself. */
|
|
18
|
+
export function killFirst(processes) {
|
|
19
|
+
const byPid = new Map(processes.map((entry) => [entry.pid, entry]));
|
|
20
|
+
function underAgent(entry) {
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
let parent = byPid.get(entry.ppid);
|
|
23
|
+
while (parent && !seen.has(parent.pid)) {
|
|
24
|
+
if (parent.comm === AGENT_COMM)
|
|
25
|
+
return true;
|
|
26
|
+
seen.add(parent.pid);
|
|
27
|
+
parent = byPid.get(parent.ppid);
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return processes
|
|
32
|
+
.filter((entry) => entry.comm !== AGENT_COMM && entry.oomScoreAdj < KILL_FIRST_ADJ && underAgent(entry))
|
|
33
|
+
.map((entry) => entry.pid);
|
|
34
|
+
}
|
|
35
|
+
/** `pid (comm) state ppid …` — the name can hold spaces and parentheses, so it ends at the last `)`. */
|
|
36
|
+
export function parseStat(stat) {
|
|
37
|
+
const open = stat.indexOf("(");
|
|
38
|
+
const close = stat.lastIndexOf(")");
|
|
39
|
+
if (open < 0 || close < open)
|
|
40
|
+
return null;
|
|
41
|
+
const pid = Number(stat.slice(0, open).trim());
|
|
42
|
+
const ppid = Number(stat.slice(close + 2).split(" ")[1]);
|
|
43
|
+
if (!Number.isInteger(pid) || !Number.isInteger(ppid))
|
|
44
|
+
return null;
|
|
45
|
+
return { pid, ppid, comm: stat.slice(open + 1, close) };
|
|
46
|
+
}
|
|
47
|
+
function readProcesses() {
|
|
48
|
+
const entries = [];
|
|
49
|
+
for (const name of readdirSync("/proc")) {
|
|
50
|
+
if (!/^\d+$/.test(name))
|
|
51
|
+
continue;
|
|
52
|
+
try {
|
|
53
|
+
const stat = parseStat(readFileSync(`/proc/${name}/stat`, "utf8"));
|
|
54
|
+
if (stat)
|
|
55
|
+
entries.push({ ...stat, oomScoreAdj: Number(readFileSync(`/proc/${name}/oom_score_adj`, "utf8")) });
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Gone between the listing and the read.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return entries;
|
|
62
|
+
}
|
|
63
|
+
const SCAN_INTERVAL_MS = 2_000;
|
|
64
|
+
/**
|
|
65
|
+
* Marks the agent's commands every 2 s: the backstop for what the wrapper never
|
|
66
|
+
* sees (an MCP server, a hook not run by bash). Raising a score needs no
|
|
67
|
+
* privilege, so the bridge does it for the processes its agent started; a
|
|
68
|
+
* command dead between the scan and the write is skipped. Off where there is no
|
|
69
|
+
* /proc.
|
|
70
|
+
*/
|
|
71
|
+
export function startOomPriority(log = console.warn) {
|
|
72
|
+
try {
|
|
73
|
+
readdirSync("/proc/self");
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
let warned = false;
|
|
79
|
+
const timer = setInterval(() => {
|
|
80
|
+
for (const pid of killFirst(readProcesses())) {
|
|
81
|
+
try {
|
|
82
|
+
writeFileSync(`/proc/${pid}/oom_score_adj`, String(KILL_FIRST_ADJ));
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (warned)
|
|
86
|
+
continue;
|
|
87
|
+
warned = true;
|
|
88
|
+
log(`[oom-priority] could not mark command ${pid}: ${error instanceof Error ? error.message : String(error)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}, SCAN_INTERVAL_MS);
|
|
92
|
+
timer.unref();
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The agent's command wrapper (`CLAUDE_CODE_SHELL_PREFIX`). Claude Code hands
|
|
96
|
+
* it one argument, the script it would otherwise run with `bash -c`, so every
|
|
97
|
+
* command — and all it starts — is the OOM killer's first choice from its first
|
|
98
|
+
* instruction, before the scan below could reach it. A burst of parallel
|
|
99
|
+
* commands can fill memory inside one scan interval.
|
|
100
|
+
*/
|
|
101
|
+
const KILL_FIRST_WRAPPER = `#!/bin/sh
|
|
102
|
+
# Written by the Baker bridge (oom-priority.ts): mark this command the OOM killer's first choice, then run it.
|
|
103
|
+
echo ${KILL_FIRST_ADJ} > /proc/self/oom_score_adj 2>/dev/null
|
|
104
|
+
if [ "$#" -eq 1 ]; then exec /bin/bash -c "$1"; fi
|
|
105
|
+
exec "$@"
|
|
106
|
+
`;
|
|
107
|
+
/** Writes the wrapper into `dir` and returns its path. */
|
|
108
|
+
export function installKillFirstWrapper(dir) {
|
|
109
|
+
const path = join(dir, "baker-kill-first.sh");
|
|
110
|
+
writeFileSync(path, KILL_FIRST_WRAPPER);
|
|
111
|
+
chmodSync(path, 0o755);
|
|
112
|
+
return path;
|
|
113
|
+
}
|
|
114
|
+
/** The agent's env addition: the wrapper, unless the Runtime already wraps commands its own way. */
|
|
115
|
+
export function agentShellPrefixEnv(wrapper, env) {
|
|
116
|
+
if (wrapper === null || env.CLAUDE_CODE_SHELL_PREFIX)
|
|
117
|
+
return {};
|
|
118
|
+
return { CLAUDE_CODE_SHELL_PREFIX: wrapper };
|
|
119
|
+
}
|
|
120
|
+
let installedWrapper;
|
|
121
|
+
/**
|
|
122
|
+
* The wrapper, written on first use so no agent starts without it whatever
|
|
123
|
+
* started the bridge. Null only where the temp dir is not writable. Off Linux
|
|
124
|
+
* the score write fails quietly and the command runs as is.
|
|
125
|
+
*/
|
|
126
|
+
export function killFirstWrapper(log = console.warn) {
|
|
127
|
+
if (installedWrapper)
|
|
128
|
+
return installedWrapper;
|
|
129
|
+
try {
|
|
130
|
+
installedWrapper = installKillFirstWrapper(tmpdir());
|
|
131
|
+
return installedWrapper;
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
log(`[oom-priority] could not write the command wrapper: ${error instanceof Error ? error.message : String(error)}`);
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=oom-priority.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oom-priority.js","sourceRoot":"","sources":["../../src/hono/oom-priority.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,2HAA2H;AAC3H,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,CAAC;AAEnC,mEAAmE;AACnE,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC;AAEnC,kGAAkG;AAClG,MAAM,UAAU,SAAS,CAAC,SAAkC;IAC1D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACpE,SAAS,UAAU,CAAC,KAAmB;QACrC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;QAC/B,IAAI,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,OAAO,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU;gBAAE,OAAO,IAAI,CAAC;YAC5C,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACrB,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,SAAS;SACb,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,WAAW,GAAG,cAAc,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;SACvG,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,aAAa;IACpB,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,SAAS;QAClC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,SAAS,CAAC,YAAY,CAAC,SAAS,IAAI,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;YACnE,IAAI,IAAI;gBAAE,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,YAAY,CAAC,SAAS,IAAI,gBAAgB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;QAChH,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAE/B;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAA8B,OAAO,CAAC,IAAI;IAC5E,IAAI,CAAC;QACH,WAAW,CAAC,YAAY,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,KAAK,MAAM,GAAG,IAAI,SAAS,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC;gBACH,aAAa,CAAC,SAAS,GAAG,gBAAgB,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;YACtE,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,MAAM;oBAAE,SAAS;gBACrB,MAAM,GAAG,IAAI,CAAC;gBACd,GAAG,CAAC,yCAAyC,GAAG,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YACjH,CAAC;QACH,CAAC;IACH,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACrB,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAG;;OAEpB,cAAc;;;CAGpB,CAAC;AAEF,0DAA0D;AAC1D,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IACxC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,mBAAmB,CACjC,OAAsB,EACtB,GAAuC;IAEvC,IAAI,OAAO,KAAK,IAAI,IAAI,GAAG,CAAC,wBAAwB;QAAE,OAAO,EAAE,CAAC;IAChE,OAAO,EAAE,wBAAwB,EAAE,OAAO,EAAE,CAAC;AAC/C,CAAC;AAED,IAAI,gBAAoC,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAG,GAA8B,OAAO,CAAC,IAAI;IAC5E,IAAI,gBAAgB;QAAE,OAAO,gBAAgB,CAAC;IAC9C,IAAI,CAAC;QACH,gBAAgB,GAAG,uBAAuB,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,GAAG,CACD,uDAAuD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAChH,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oom-priority.test.d.ts","sourceRoot":"","sources":["../../src/hono/oom-priority.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { mkdtempSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { agentShellPrefixEnv, installKillFirstWrapper, KILL_FIRST_ADJ, killFirst, parseStat } from "./oom-priority.js";
|
|
7
|
+
const bridge = { pid: 100, ppid: 1, comm: "MainThread", oomScoreAdj: 100 };
|
|
8
|
+
const agent = { pid: 200, ppid: 100, comm: "claude", oomScoreAdj: 100 };
|
|
9
|
+
const shell = { pid: 300, ppid: 200, comm: "bash", oomScoreAdj: 100 };
|
|
10
|
+
const bakerCommand = { pid: 301, ppid: 300, comm: "MainThread", oomScoreAdj: 100 };
|
|
11
|
+
describe("killFirst", () => {
|
|
12
|
+
it("marks every command the agent runs, and what they start, to be killed before the agent", () => {
|
|
13
|
+
expect(killFirst([bridge, agent, shell, bakerCommand]).sort()).toEqual([300, 301]);
|
|
14
|
+
});
|
|
15
|
+
it("marks commands even in a sandbox whose processes all start with a high score", () => {
|
|
16
|
+
const high = (entry) => ({ ...entry, oomScoreAdj: 900 });
|
|
17
|
+
expect(killFirst([high(bridge), high(agent), high(shell)])).toEqual([300]);
|
|
18
|
+
});
|
|
19
|
+
it("skips a command already marked, so a scan rewrites only what is new", () => {
|
|
20
|
+
const marked = { ...shell, oomScoreAdj: KILL_FIRST_ADJ };
|
|
21
|
+
expect(killFirst([bridge, agent, marked, bakerCommand])).toEqual([301]);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
describe("parseStat", () => {
|
|
25
|
+
it("reads the parent and the name from /proc/<pid>/stat, even a name holding spaces and parentheses", () => {
|
|
26
|
+
expect(parseStat("4847 (claude) S 2933 4847 2920 0 -1 4194560 2 0")).toEqual({
|
|
27
|
+
pid: 4847,
|
|
28
|
+
ppid: 2933,
|
|
29
|
+
comm: "claude",
|
|
30
|
+
});
|
|
31
|
+
expect(parseStat("77 (a) b (c) R 12 77 1 0")).toEqual({ pid: 77, ppid: 12, comm: "a) b (c" });
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe("the kill-first wrapper", () => {
|
|
35
|
+
// Claude Code hands CLAUDE_CODE_SHELL_PREFIX one argument: the whole script it would run with `bash -c`.
|
|
36
|
+
it("runs the one script it is handed as the agent's bash would, output and exit code intact", () => {
|
|
37
|
+
const wrapper = installKillFirstWrapper(mkdtempSync(join(tmpdir(), "kill-first-")));
|
|
38
|
+
const run = spawnSync(wrapper, ["source /dev/null && eval 'echo from-bash; [[ 1 == 1 ]] && exit 3'"], {
|
|
39
|
+
encoding: "utf8",
|
|
40
|
+
});
|
|
41
|
+
expect(run.stdout).toBe("from-bash\n");
|
|
42
|
+
expect(run.status).toBe(3);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe("agentShellPrefixEnv", () => {
|
|
46
|
+
it("hands the agent the wrapper, unless the Runtime already wraps its commands", () => {
|
|
47
|
+
expect(agentShellPrefixEnv("/tmp/w.sh", {})).toEqual({ CLAUDE_CODE_SHELL_PREFIX: "/tmp/w.sh" });
|
|
48
|
+
expect(agentShellPrefixEnv("/tmp/w.sh", { CLAUDE_CODE_SHELL_PREFIX: "/opt/audit.sh" })).toEqual({});
|
|
49
|
+
expect(agentShellPrefixEnv(null, {})).toEqual({});
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=oom-priority.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oom-priority.test.js","sourceRoot":"","sources":["../../src/hono/oom-priority.test.ts"],"names":[],"mappings":"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"}
|