@bytesbrains/cruise-worker 0.0.0-stage → 0.12.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/LICENSE +202 -0
- package/README.md +37 -2
- package/index.d.ts +14 -0
- package/index.mjs +41 -0
- package/migrations/0001_virtual_keys.sql +102 -0
- package/migrations/0002_seed_projects.sql +16 -0
- package/migrations/0003_budgets.sql +43 -0
- package/migrations/0004_tenant_isolation_and_integer_money.sql +49 -0
- package/migrations/0005_model_prices.sql +42 -0
- package/migrations/0006_budget_reservation.sql +38 -0
- package/migrations/0007_routing_table.sql +93 -0
- package/migrations/0008_measurement_provenance.sql +24 -0
- package/migrations/0009_conformance.sql +37 -0
- package/migrations/0010_conformance_key.sql +20 -0
- package/migrations/0011_correct_workers_ai_price.sql +30 -0
- package/migrations/0012_rate_limits.sql +28 -0
- package/migrations/0013_deepseek_and_mistral.sql +42 -0
- package/migrations/0014_cost_ledger.sql +104 -0
- package/migrations/0015_memberships.sql +33 -0
- package/migrations/0016_latency.sql +23 -0
- package/migrations/0017_ledger_provider_index.sql +8 -0
- package/migrations/0018_fallback_chains.sql +34 -0
- package/migrations/0019_rate_buckets.sql +27 -0
- package/migrations/0020_mistral_price_and_pin.sql +62 -0
- package/migrations/0021_mistral_price_date_is_utc.sql +35 -0
- package/migrations/0022_drop_unenforced_key_budget.sql +32 -0
- package/migrations/0023_model_limits.sql +48 -0
- package/migrations/0024_conditional_prices.sql +84 -0
- package/migrations/0025_catalogue_from_keyed_hosts.sql +172 -0
- package/migrations/0026_lanes.sql +83 -0
- package/migrations/0027_lane_alternatives.sql +36 -0
- package/migrations/0028_lanes_tenant_scope.sql +66 -0
- package/migrations/0029_lane_jobs.sql +146 -0
- package/migrations/0030_lane_requires.sql +38 -0
- package/migrations/0031_tenant_billable.sql +15 -0
- package/migrations/0032_cache_hit_billing.sql +35 -0
- package/migrations/0033_sell_markup.sql +37 -0
- package/migrations/0034_tiers_and_lane_quotas.sql +38 -0
- package/migrations/0035_wallet_scope.sql +68 -0
- package/migrations/0036_credit_grants.sql +53 -0
- package/migrations/0037_reconciliation.sql +45 -0
- package/migrations/0038_balance_service_keys.sql +35 -0
- package/migrations/0039_deepseek_peak_is_weekdays.sql +77 -0
- package/migrations/0040_glm_5_3_on_workers_ai.sql +63 -0
- package/migrations/0041_mistral_sweep_2026_08_29.sql +89 -0
- package/migrations/0042_provision_service_keys.sql +50 -0
- package/migrations/0043_tier_project_quota.sql +32 -0
- package/migrations/0044_audit_tenant_scope.sql +49 -0
- package/migrations/0045_audit_backfill_derivable.sql +42 -0
- package/migrations/0046_measurement_note.sql +24 -0
- package/migrations/0047_ledger_max_tokens.sql +21 -0
- package/migrations/0048_price_observations.sql +140 -0
- package/migrations/0049_openai_and_gemini.sql +239 -0
- package/migrations/0050_meta_direct_upstream.sql +127 -0
- package/migrations/0051_upstream_credential_and_operator.sql +74 -0
- package/migrations/0052_muse_spark_1_3.sql +71 -0
- package/migrations/0053_anthropic_groq_and_xai.sql +172 -0
- package/migrations/0054_tier_service_keys.sql +60 -0
- package/migrations/0055_output_defaults.sql +79 -0
- package/migrations/0056_model_modality.sql +37 -0
- package/migrations/0057_openai_image_models.sql +177 -0
- package/migrations/0058_price_components.sql +230 -0
- package/migrations/0059_speech.sql +151 -0
- package/migrations/0060_embeddings.sql +131 -0
- package/migrations/0061_data_retention_backfill.sql +121 -0
- package/migrations/0062_gemini_embedding_disabled.sql +125 -0
- package/migrations/0063_google_provider_path_prefix.sql +59 -0
- package/migrations/0064_economics_service_keys.sql +51 -0
- package/migrations/0065_lane_selection.sql +66 -0
- package/migrations/0066_tenant_default_selection.sql +42 -0
- package/migrations/0067_graduated_selection.sql +103 -0
- package/migrations/0068_cache_scope.sql +73 -0
- package/migrations/0069_lane_cache_settings.sql +50 -0
- package/migrations/0070_lane_member_quality_rank.sql +98 -0
- package/migrations/0071_key_cache_pool.sql +60 -0
- package/migrations/0072_cache_digest.sql +51 -0
- package/migrations/0073_lane_max_chain.sql +51 -0
- package/migrations/0074_hunter_builder_lanes.sql +149 -0
- package/migrations/0075_hunter_builder_frontline.sql +36 -0
- package/migrations/0076_deepseek_flash.sql +86 -0
- package/migrations/0077_gpt_6_astra.sql +35 -0
- package/migrations/0078_astra_deep_reasoning.sql +20 -0
- package/migrations/0079_gemini_flash_lite_extraction.sql +15 -0
- package/migrations/0080_priced_by.sql +24 -0
- package/migrations/0081_grok_imagine.sql +81 -0
- package/migrations/0082_markup_three_percent.sql +32 -0
- package/migrations/0083_markup_per_tenant_and_tier.sql +57 -0
- package/migrations/0084_coding_lanes_frontier.sql +93 -0
- package/migrations/0085_minute_period_and_demo_charge.sql +77 -0
- package/migrations/0086_project_sentry.sql +41 -0
- package/migrations/0087_lane_router.sql +71 -0
- package/migrations/0088_openai_frontier_coding_lanes.sql +54 -0
- package/migrations/0089_agentic_coding_drops_codestral.sql +44 -0
- package/migrations/0090_board_followups_2026_10.sql +196 -0
- package/migrations/0091_opus_5_5_coding_lanes.sql +43 -0
- package/migrations/0092_deepseek_peak_holidays.sql +83 -0
- package/migrations/0093_tool_choice_forced.sql +26 -0
- package/migrations/0094_board_followups_2026_10_08.sql +115 -0
- package/migrations/0095_request_compression.sql +43 -0
- package/migrations/0096_lane_compress.sql +36 -0
- package/migrations/0097_tenant_default_compress.sql +34 -0
- package/migrations/0098_ledger_session.sql +47 -0
- package/migrations/0099_wallet_low_water_backfill.sql +47 -0
- package/migrations/0100_rag_grounded_answers_lane.sql +92 -0
- package/migrations/0101_perplexity_agent_api.sql +125 -0
- package/migrations/0102_web_search_job_and_flag.sql +137 -0
- package/migrations/0103_openai_web_search_price.sql +44 -0
- package/migrations/0104_web_search_lane.sql +82 -0
- package/migrations/0105_web_search_lane_billed.sql +22 -0
- package/migrations/0106_reservations_journal.sql +64 -0
- package/migrations/0107_session_cap.sql +65 -0
- package/migrations/0108_ledger_attempts.sql +41 -0
- package/migrations/0109_gemini_retention.sql +39 -0
- package/migrations/0110_gemini_4_argon.sql +110 -0
- package/migrations/0111_gemini_4_argon_lanes.sql +80 -0
- package/migrations/0112_ledger_affinity.sql +42 -0
- package/migrations/0113_contributor_lane_namespace.sql +125 -0
- package/migrations/0114_meta_contributor_models.sql +55 -0
- package/migrations/0115_oss_chat_assistant_lane.sql +41 -0
- package/migrations/0116_promo_credits.sql +63 -0
- package/migrations/0117_oss_mirror_lanes.sql +85 -0
- package/migrations/0118_project_management_job.sql +112 -0
- package/migrations/0119_oss_project_management_lane.sql +29 -0
- package/migrations/0120_moonshot_k3_1_pro.sql +107 -0
- package/migrations/0121_jobs.sql +100 -0
- package/migrations/0122_batch_prices.sql +188 -0
- package/migrations/0123_batch_files.sql +50 -0
- package/migrations/0124_batch_run.sql +21 -0
- package/migrations/0125_anthropic_path_prefix.sql +22 -0
- package/package.json +37 -4
- package/worker/284906b51fc0a3173ea7d301234907f30e834f54-cruise-mark-64.png +0 -0
- package/worker/2c39de526314484775fdfc503fac50c437d21e4e-cruise-logo-240.png +0 -0
- package/worker/63fb63e2d8ae6d8b68228768ef6c91ab8f0c0100-cruise-logo-480.png +0 -0
- package/worker/VERSION +1 -0
- package/worker/b23bfbc792e8710d3b74284a0a1b8ab044c18897-logo-dark.png +0 -0
- package/worker/index.js +31451 -0
- package/wrangler.template.jsonc +48 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
-- Five frontier rows, the xAI rows re-cited, and a Mistral re-host retired
|
|
2
|
+
-- (#534, #559 — the model board's 2026-09-24 and 2026-10-01 follow-ups).
|
|
3
|
+
--
|
|
4
|
+
-- This migration catalogues and prices. It staffs no lane: a member nobody has
|
|
5
|
+
-- measured makes the lane's capability `null` (`src/lanes.ts`), so restaffing
|
|
6
|
+
-- the coding lanes with Opus 5.5 and GPT-6.1 Sol is a later migration, after a
|
|
7
|
+
-- conformance run has written their flags — the 0077 → 0088 order.
|
|
8
|
+
--
|
|
9
|
+
-- Every figure fetched 2026-10-02 UTC from the host's own pages, cited per row.
|
|
10
|
+
-- Not the board: both issues say so, and #79 / #122 say why.
|
|
11
|
+
--
|
|
12
|
+
-- ## Left out, and why
|
|
13
|
+
--
|
|
14
|
+
-- **`gpt-6-sol`** (#534). OpenAI's starting points replaced it with
|
|
15
|
+
-- `gpt-6.1-sol` on 2026-09-29 (#559) at the same headline rate, so cataloguing
|
|
16
|
+
-- it a week later would add a row whose only future is a disable.
|
|
17
|
+
--
|
|
18
|
+
-- **Gemini 2.5, Gemini 3.1 Flash-Lite, Claude Sonnet 4.5, Groq's Llama rows**
|
|
19
|
+
-- (#534, #559). None is in this catalogue, so the access limits, shutdown dates
|
|
20
|
+
-- and enterprise gating the board reported reach nothing here. The Groq rows
|
|
21
|
+
-- held are the two gpt-oss models (0053), which the gating does not name.
|
|
22
|
+
--
|
|
23
|
+
-- **Gemini 3.8 Flash's window** (#559). The board corrected its rounding to
|
|
24
|
+
-- 1M / 64K; 0049 already holds the page's 1,048,576 / 65,536.
|
|
25
|
+
--
|
|
26
|
+
-- **Perplexity Sonar** (#559). 0058 priced `perplexity/sonar*` per request, but
|
|
27
|
+
-- no `models` or `upstreams` row was ever written, so those components price a
|
|
28
|
+
-- model nothing can route. The end of Sonar's Chat Completions support on
|
|
29
|
+
-- 2026-09-27 changes nothing that serves; it does mean the next person to add
|
|
30
|
+
-- Perplexity starts from the Agent API, not from 0058's rows.
|
|
31
|
+
|
|
32
|
+
-- ── OpenAI ────────────────────────────────────────────────────────────────────
|
|
33
|
+
-- https://developers.openai.com/api/docs/models/gpt-6.1-sol
|
|
34
|
+
-- https://developers.openai.com/api/docs/models/gpt-6-luna
|
|
35
|
+
--
|
|
36
|
+
-- Both: window 1,050,000, max output 128,000, and the long-context rule 0049
|
|
37
|
+
-- and 0077 already hold — prompts over 272K input tokens pay 2x input and
|
|
38
|
+
-- cache and 1.5x output for the whole request, so `prompt_tokens_from` is
|
|
39
|
+
-- 272001. Batch / Flex are not written, for 0049's reason.
|
|
40
|
+
--
|
|
41
|
+
-- gpt-6.1-sol $2 / $10, cached $0.10 — a 5% cache read, which is #559's
|
|
42
|
+
-- "deeper discount". Effort accepts low, medium, high, xhigh,
|
|
43
|
+
-- max: **`none` and `minimal` are refused upstream**. Cruise
|
|
44
|
+
-- passes `reasoning_effort` through unchanged
|
|
45
|
+
-- (`src/chat-openai-responses.ts`), so a caller sending `none`
|
|
46
|
+
-- gets OpenAI's 400 — a property of the request, not of a lane,
|
|
47
|
+
-- and not something conformance can measure for every caller.
|
|
48
|
+
-- gpt-6-luna $0.10 / $0.50, cached $0.01. Effort accepts `none`.
|
|
49
|
+
--
|
|
50
|
+
-- Both match `isOpenAIReasoningModel` (`^(gpt-6|gpt-5\.6)`), so their tool calls
|
|
51
|
+
-- take the `/v1/responses` adapter #545 built for gpt-6-astra with no code here.
|
|
52
|
+
-- `data_retention` is `retained` on the same guide 0049 and 0077 cite.
|
|
53
|
+
INSERT INTO models (id, upstream_id, upstream_model, max_context, max_output,
|
|
54
|
+
data_retention, data_retention_source, data_retention_as_of) VALUES
|
|
55
|
+
('openai/gpt-6.1-sol', 'openai', 'gpt-6.1-sol', 1050000, 128000,
|
|
56
|
+
'retained', 'https://developers.openai.com/api/docs/guides/your-data', '2026-10-02'),
|
|
57
|
+
('openai/gpt-6-luna', 'openai', 'gpt-6-luna', 1050000, 128000,
|
|
58
|
+
'retained', 'https://developers.openai.com/api/docs/guides/your-data', '2026-10-02');
|
|
59
|
+
|
|
60
|
+
INSERT INTO price_observations
|
|
61
|
+
(observed_at, model, effective_from, prompt_tokens_from, peak_utc,
|
|
62
|
+
input_micros_per_mtok, output_micros_per_mtok, cached_input_micros_per_mtok, source, note)
|
|
63
|
+
VALUES
|
|
64
|
+
('2026-10-02 00:00:00', 'openai/gpt-6.1-sol', '2026-10-02', 0, '',
|
|
65
|
+
2000000, 10000000, 100000, 'https://developers.openai.com/api/docs/models/gpt-6.1-sol',
|
|
66
|
+
'First observation: GPT-6.1 Sol (#559, 0090).'),
|
|
67
|
+
('2026-10-02 00:00:00', 'openai/gpt-6.1-sol', '2026-10-02', 272001, '',
|
|
68
|
+
4000000, 15000000, 200000, 'https://developers.openai.com/api/docs/models/gpt-6.1-sol',
|
|
69
|
+
'Long-context tier: >272K input tokens, 2x input/cache and 1.5x output for the whole request.'),
|
|
70
|
+
('2026-10-02 00:00:00', 'openai/gpt-6-luna', '2026-10-02', 0, '',
|
|
71
|
+
100000, 500000, 10000, 'https://developers.openai.com/api/docs/models/gpt-6-luna',
|
|
72
|
+
'First observation: GPT-6 Luna (#534, 0090).'),
|
|
73
|
+
('2026-10-02 00:00:00', 'openai/gpt-6-luna', '2026-10-02', 272001, '',
|
|
74
|
+
200000, 750000, 20000, 'https://developers.openai.com/api/docs/models/gpt-6-luna',
|
|
75
|
+
'Long-context tier: >272K input tokens, 2x input/cache and 1.5x output for the whole request.');
|
|
76
|
+
|
|
77
|
+
-- ── Anthropic ─────────────────────────────────────────────────────────────────
|
|
78
|
+
-- https://platform.claude.com/docs/en/models/opus-5-5/overview
|
|
79
|
+
-- https://platform.claude.com/docs/en/models/sonnet-5-5/overview
|
|
80
|
+
--
|
|
81
|
+
-- Both: window 1M, max output 128K, no long-context tier on either page.
|
|
82
|
+
-- `cached_input` is the cache *read* rate, as in 0053; the write rates have a
|
|
83
|
+
-- component (0058) and no reader yet.
|
|
84
|
+
--
|
|
85
|
+
-- claude-opus-5-5 $4 / $20, cache read $0.20 — 5% of input, which the
|
|
86
|
+
-- page flags as this model's exception to the usual 10%.
|
|
87
|
+
-- claude-sonnet-5-5 $2 / $10, cache read $0.20.
|
|
88
|
+
--
|
|
89
|
+
-- **What both narrow, and which of it Cruise sees** (#534, #559, and the pages):
|
|
90
|
+
--
|
|
91
|
+
-- - Forced tool use — `tool_choice` `any` or a named `tool` — returns 400.
|
|
92
|
+
-- Conformance sends no `tool_choice`, so `tools = 1` will be measured true
|
|
93
|
+
-- and a lane will promise tools to a caller whose forced request then 400s
|
|
94
|
+
-- and falls back. That is a gap in the suite, not in this row, and has its
|
|
95
|
+
-- own issue rather than a guess written here.
|
|
96
|
+
-- - Thinking cannot be disabled (Opus 5.5; Sonnet 5.5's floor is
|
|
97
|
+
-- `between_tools`). `src/messages-translate.ts` already drops `thinking`
|
|
98
|
+
-- on the way in, so Cruise never asks for it off.
|
|
99
|
+
-- - Thinking blocks are tied to the producing model and account. The same
|
|
100
|
+
-- file returns no `thinking` blocks to the caller, so no history replays
|
|
101
|
+
-- one across tenant keys.
|
|
102
|
+
-- - Sonnet 5.5 refuses a non-default `temperature`, `top_p` or `top_k` with
|
|
103
|
+
-- 400. Callers that send one get the host's answer, as with any 400.
|
|
104
|
+
--
|
|
105
|
+
-- `retained` on the privacy page 0053 quoted, unchanged for these rows.
|
|
106
|
+
INSERT INTO models (id, upstream_id, upstream_model, max_context, max_output,
|
|
107
|
+
data_retention, data_retention_source, data_retention_as_of) VALUES
|
|
108
|
+
('anthropic/claude-opus-5-5', 'anthropic', 'claude-opus-5-5', 1000000, 128000,
|
|
109
|
+
'retained', 'https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training', '2026-10-02'),
|
|
110
|
+
('anthropic/claude-sonnet-5-5', 'anthropic', 'claude-sonnet-5-5', 1000000, 128000,
|
|
111
|
+
'retained', 'https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training', '2026-10-02');
|
|
112
|
+
|
|
113
|
+
INSERT INTO price_observations
|
|
114
|
+
(observed_at, model, effective_from, prompt_tokens_from, peak_utc,
|
|
115
|
+
input_micros_per_mtok, output_micros_per_mtok, cached_input_micros_per_mtok, source, note)
|
|
116
|
+
VALUES
|
|
117
|
+
('2026-10-02 00:00:00', 'anthropic/claude-opus-5-5', '2026-10-02', 0, '',
|
|
118
|
+
4000000, 20000000, 200000, 'https://platform.claude.com/docs/en/models/opus-5-5/overview',
|
|
119
|
+
'First observation: Claude Opus 5.5 (#534, 0090). Cache read is 0.05x base on this model, which the page states explicitly.'),
|
|
120
|
+
('2026-10-02 00:00:00', 'anthropic/claude-sonnet-5-5', '2026-10-02', 0, '',
|
|
121
|
+
2000000, 10000000, 200000, 'https://platform.claude.com/docs/en/models/sonnet-5-5/overview',
|
|
122
|
+
'First observation: Claude Sonnet 5.5 (#559, 0090).');
|
|
123
|
+
|
|
124
|
+
-- Web search at $10 per 1,000, as 0058 wrote for every Claude row it held —
|
|
125
|
+
-- re-read on the tool's page the same day.
|
|
126
|
+
INSERT INTO price_components
|
|
127
|
+
(observed_at, model, effective_from, component, variant, micros, per, source, note)
|
|
128
|
+
VALUES
|
|
129
|
+
('2026-10-02 00:00:00', 'anthropic/claude-opus-5-5', '2026-10-02', 'search', '', 10000000, 1000,
|
|
130
|
+
'https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool', 'First observation (0090).'),
|
|
131
|
+
('2026-10-02 00:00:00', 'anthropic/claude-sonnet-5-5', '2026-10-02', 'search', '', 10000000, 1000,
|
|
132
|
+
'https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool', 'First observation (0090).');
|
|
133
|
+
|
|
134
|
+
-- ── xAI ───────────────────────────────────────────────────────────────────────
|
|
135
|
+
-- https://docs.x.ai/developers/pricing — where `docs.x.ai/docs/models`, 0053's
|
|
136
|
+
-- source, now lives (#534).
|
|
137
|
+
--
|
|
138
|
+
-- `grok-4.7`: window 500k, same rates as `grok-4.6`, the same "< 200k" /
|
|
139
|
+
-- "≥ 200k" boundary 0053 wrote as `prompt_tokens_from` 200000. xAI offers no
|
|
140
|
+
-- Batch API for it, which Cruise does not use. No max output stated, so NULL
|
|
141
|
+
-- and `checkLimits` derives one (0023). `retained` on the page 0061 read for
|
|
142
|
+
-- every xAI row, re-read today: stored 30 days for abuse review, *"never trains
|
|
143
|
+
-- on your API inputs or outputs without your explicit permission."*
|
|
144
|
+
INSERT INTO models (id, upstream_id, upstream_model, max_context, max_output,
|
|
145
|
+
data_retention, data_retention_source, data_retention_as_of) VALUES
|
|
146
|
+
('grok/grok-4.7', 'grok', 'grok-4.7', 500000, NULL,
|
|
147
|
+
'retained', 'https://docs.x.ai/developers/faq/security', '2026-10-02');
|
|
148
|
+
|
|
149
|
+
-- The four rows 0053 sourced to the old URL, re-read on the new page: **every
|
|
150
|
+
-- figure unchanged**. A re-observation rather than an edit, since
|
|
151
|
+
-- `price_observations` is append-only (0048) — the old rows keep the URL they
|
|
152
|
+
-- were read from, and these say where the same numbers are read today.
|
|
153
|
+
INSERT INTO price_observations
|
|
154
|
+
(observed_at, model, effective_from, prompt_tokens_from, peak_utc,
|
|
155
|
+
input_micros_per_mtok, output_micros_per_mtok, cached_input_micros_per_mtok, source, note)
|
|
156
|
+
VALUES
|
|
157
|
+
('2026-10-02 00:00:00', 'grok/grok-4.7', '2026-10-02', 0, '',
|
|
158
|
+
2000000, 6000000, 500000, 'https://docs.x.ai/developers/pricing', 'First observation: Grok 4.7 (#534, 0090).'),
|
|
159
|
+
('2026-10-02 00:00:00', 'grok/grok-4.7', '2026-10-02', 200000, '',
|
|
160
|
+
4000000, 12000000, 1000000, 'https://docs.x.ai/developers/pricing', 'Long-prompt tier, stated as prompts at or above 200k tokens.'),
|
|
161
|
+
('2026-10-02 00:00:00', 'grok/grok-4.6', '2026-10-02', 0, '',
|
|
162
|
+
2000000, 6000000, 500000, 'https://docs.x.ai/developers/pricing', 'Re-read at the moved URL (#534, 0090); unchanged.'),
|
|
163
|
+
('2026-10-02 00:00:00', 'grok/grok-4.6', '2026-10-02', 200000, '',
|
|
164
|
+
4000000, 12000000, 1000000, 'https://docs.x.ai/developers/pricing', 'Re-read at the moved URL (#534, 0090); unchanged.'),
|
|
165
|
+
('2026-10-02 00:00:00', 'grok/grok-4.5', '2026-10-02', 0, '',
|
|
166
|
+
2000000, 6000000, 300000, 'https://docs.x.ai/developers/pricing', 'Re-read at the moved URL (#534, 0090); unchanged.'),
|
|
167
|
+
('2026-10-02 00:00:00', 'grok/grok-4.5', '2026-10-02', 200000, '',
|
|
168
|
+
4000000, 12000000, 600000, 'https://docs.x.ai/developers/pricing', 'Re-read at the moved URL (#534, 0090); unchanged.'),
|
|
169
|
+
('2026-10-02 00:00:00', 'grok/grok-4.3', '2026-10-02', 0, '',
|
|
170
|
+
1250000, 2500000, 200000, 'https://docs.x.ai/developers/pricing', 'Re-read at the moved URL (#534, 0090); unchanged.'),
|
|
171
|
+
('2026-10-02 00:00:00', 'grok/grok-4.3', '2026-10-02', 200000, '',
|
|
172
|
+
2500000, 5000000, 400000, 'https://docs.x.ai/developers/pricing', 'Re-read at the moved URL (#534, 0090); unchanged.'),
|
|
173
|
+
('2026-10-02 00:00:00', 'grok/grok-build-0.1', '2026-10-02', 0, '',
|
|
174
|
+
1000000, 2000000, 200000, 'https://docs.x.ai/developers/pricing', 'Re-read at the moved URL (#534, 0090); unchanged.'),
|
|
175
|
+
('2026-10-02 00:00:00', 'grok/grok-build-0.1', '2026-10-02', 200000, '',
|
|
176
|
+
2000000, 4000000, 400000, 'https://docs.x.ai/developers/pricing', 'Re-read at the moved URL (#534, 0090); unchanged.');
|
|
177
|
+
|
|
178
|
+
-- ── Mistral's GLM 5.2 re-host ─────────────────────────────────────────────────
|
|
179
|
+
-- Mistral deprecated its hosted `zai-glm-5-2` on 2026-09-29 and retires it on
|
|
180
|
+
-- 2026-10-31 (#559; https://docs.mistral.ai/getting-started/models/). It has
|
|
181
|
+
-- never served here either: every request to it has been a 403 on a Labs
|
|
182
|
+
-- entitlement this account lacks (0041, and `src/doctor-upstreams.ts`). No
|
|
183
|
+
-- migration put it in a lane or a fallback chain; a chain written since through
|
|
184
|
+
-- `fallback:set` is data in that database, and a disabled member is skipped.
|
|
185
|
+
--
|
|
186
|
+
-- Disabled, never deleted: the ledger may name it. Mistral's replacement, GLM
|
|
187
|
+
-- 5.3 as a third-party model, is not added — Cruise already reaches GLM 5.3 on
|
|
188
|
+
-- Workers AI (0040), and a second re-host of another lab's weights is the thing
|
|
189
|
+
-- `upstreams.md` says to add only when nothing else carries the model. The
|
|
190
|
+
-- price row stays, for 0062's reason: append-only, and unreachable is not free.
|
|
191
|
+
UPDATE models
|
|
192
|
+
SET enabled = 0,
|
|
193
|
+
measured_at = NULL,
|
|
194
|
+
measured_by = NULL,
|
|
195
|
+
measurement_source = NULL
|
|
196
|
+
WHERE id = 'mistral/zai-glm-5-2';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
-- Claude Opus 5.5 takes Opus 5's seat in the four coding lanes (#534).
|
|
2
|
+
--
|
|
3
|
+
-- 0090 catalogued it; conformance run 36993727932 (dispatched 2026-10-02 UTC,
|
|
4
|
+
-- narrowed to 0090's five rows) measured it on both environments: every check
|
|
5
|
+
-- passed — chat, usage, tools, parallel tools, streaming, json_schema, vision,
|
|
6
|
+
-- truncation. Measured before staffed, which is the 0077 → 0088 order: an
|
|
7
|
+
-- unmeasured member would make each lane's capability `null` (`src/lanes.ts`).
|
|
8
|
+
--
|
|
9
|
+
-- A swap, not an addition: same position, same `quality_rank` 1. Anthropic
|
|
10
|
+
-- holds two rank-1 seats in each lane already (Fable 5.1 and Opus 5), and Opus
|
|
11
|
+
-- 5.5 is the newer model at a lower price ($4 / $20 against $5 / $25), so
|
|
12
|
+
-- keeping Opus 5 beside it would add a member no allocation should prefer.
|
|
13
|
+
-- Opus 5 stays catalogued and routable when pinned — Anthropic lists it as
|
|
14
|
+
-- active — and disable-never-delete is about rows, not seats.
|
|
15
|
+
--
|
|
16
|
+
-- **GPT-6.1 Sol is not staffed.** The same run passed it on seven checks and
|
|
17
|
+
-- failed vision on both environments (asked the colour of a red image, it said
|
|
18
|
+
-- "Brown" on production and "Orange" on staging). A lane's capability is the
|
|
19
|
+
-- intersection of its members, so seating it would take vision off every coding
|
|
20
|
+
-- lane — screenshots through Claude Code included. `gpt-5.6-sol` keeps its seat
|
|
21
|
+
-- until a re-measurement says otherwise.
|
|
22
|
+
--
|
|
23
|
+
-- What Opus 5.5 narrows and this lane inherits: forced `tool_choice` returns
|
|
24
|
+
-- 400, which Fable 5.1 already does in every one of these lanes, and which
|
|
25
|
+
-- conformance cannot see (#570). Thinking blocks are never returned to callers
|
|
26
|
+
-- (`src/messages-translate.ts`), so its model-tied blocks do not replay.
|
|
27
|
+
--
|
|
28
|
+
-- Two statements for 0089's reason: `lane_members` is keyed (lane_id,
|
|
29
|
+
-- model_id) and the control plane can rewrite a lane's members
|
|
30
|
+
-- (`src/lanes-write.ts`), so an environment where Opus 5.5 was already added
|
|
31
|
+
-- to one of these lanes would fail a bare UPDATE and stop the migration.
|
|
32
|
+
-- OR IGNORE skips that row and the DELETE takes Opus 5 out either way.
|
|
33
|
+
--
|
|
34
|
+
-- Selection policy is unchanged.
|
|
35
|
+
|
|
36
|
+
UPDATE OR IGNORE lane_members
|
|
37
|
+
SET model_id = 'anthropic/claude-opus-5-5'
|
|
38
|
+
WHERE lane_id IN ('bb/agentic-coding', 'bb/builder', 'bb/hunter', 'bb/code-review')
|
|
39
|
+
AND model_id = 'anthropic/claude-opus-5';
|
|
40
|
+
|
|
41
|
+
DELETE FROM lane_members
|
|
42
|
+
WHERE lane_id IN ('bb/agentic-coding', 'bb/builder', 'bb/hunter', 'bb/code-review')
|
|
43
|
+
AND model_id = 'anthropic/claude-opus-5';
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
-- DeepSeek's peak does not apply on Chinese public holidays (#569).
|
|
2
|
+
--
|
|
3
|
+
-- Read 2026-10-02 UTC at https://api-docs.deepseek.com/quick_start/pricing:
|
|
4
|
+
--
|
|
5
|
+
-- Peak: "01:00 - 04:00 and 06:00 - 10:00 UTC, Monday through Friday,
|
|
6
|
+
-- excluding Chinese public holidays."
|
|
7
|
+
-- Off-peak: "All other hours are off-peak, including weekends and Chinese
|
|
8
|
+
-- public holidays in full."
|
|
9
|
+
--
|
|
10
|
+
-- 0039 taught `peak_utc` the weekdays. It cannot say "excluding", so a weekday
|
|
11
|
+
-- holiday was reserved and billed at 2x — the weekend bug 0039 fixed, in the
|
|
12
|
+
-- shape of a calendar. Found by the model board's 2026-09-24 pass (#534) and
|
|
13
|
+
-- confirmed on the page, during Golden Week, which was being over-billed as it
|
|
14
|
+
-- was read. How the exemption is applied, and why a UTC date is the right key
|
|
15
|
+
-- for these windows, is on `src/peak-calendar.ts`.
|
|
16
|
+
--
|
|
17
|
+
-- ## Which days
|
|
18
|
+
--
|
|
19
|
+
-- DeepSeek does not list them. The list is the State Council's own notice,
|
|
20
|
+
-- 国务院办公厅关于2026年部分节假日安排的通知 (国办发明电〔2025〕7号, 2025-11-04),
|
|
21
|
+
-- https://www.gov.cn/zhengce/zhengceku/202511/content_7047091.htm, read
|
|
22
|
+
-- 2026-10-02 UTC. Every 放假 (rest) day it names is written, weekends included:
|
|
23
|
+
-- they decide nothing under `mon-fri@`, and leaving them out would make this
|
|
24
|
+
-- table a partial copy of the notice rather than the notice.
|
|
25
|
+
--
|
|
26
|
+
-- Two readings, both taken literally and both stated so the first invoice that
|
|
27
|
+
-- disagrees is a correction rather than a surprise:
|
|
28
|
+
--
|
|
29
|
+
-- - **"Public holidays" is the whole 放假 period**, swapped days included
|
|
30
|
+
-- (10-06 and 10-07 are rest days only because 09-20 and 10-10 are worked).
|
|
31
|
+
-- The notice names them as one break and DeepSeek says "in full"; reading
|
|
32
|
+
-- only the statutory days would bill a day the country is off at peak.
|
|
33
|
+
-- - **Make-up workdays (上班) are not added as peak.** 2026's fall on a Sunday
|
|
34
|
+
-- and a Saturday (01-04, 02-14, 02-28, 05-09, 09-20, 10-10), and the page
|
|
35
|
+
-- says Monday through Friday. A Saturday worked in China is still a
|
|
36
|
+
-- Saturday on DeepSeek's page.
|
|
37
|
+
--
|
|
38
|
+
-- Earlier 2026 dates are written too. Nothing re-prices a settled request — the
|
|
39
|
+
-- ledger keeps what it charged — so they change no bill; they are here so the
|
|
40
|
+
-- table answers "was this a holiday" for the whole year, not only from today.
|
|
41
|
+
--
|
|
42
|
+
-- **2027 is not here.** Its notice is published around November; a row written
|
|
43
|
+
-- before it exists would be a guess. Until a migration adds it, 2027's holidays
|
|
44
|
+
-- bill at peak — over-counting, the safe direction for a cap, and the same
|
|
45
|
+
-- drift this migration closes. The next notice is a calendar item, not an
|
|
46
|
+
-- incident.
|
|
47
|
+
|
|
48
|
+
CREATE TABLE peak_exempt_days (
|
|
49
|
+
upstream_id TEXT NOT NULL REFERENCES upstreams(id),
|
|
50
|
+
day TEXT NOT NULL CHECK (day GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'),
|
|
51
|
+
note TEXT NOT NULL,
|
|
52
|
+
source TEXT NOT NULL,
|
|
53
|
+
observed_at TEXT NOT NULL,
|
|
54
|
+
PRIMARY KEY (upstream_id, day)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
INSERT INTO peak_exempt_days (upstream_id, day, note, source, observed_at)
|
|
58
|
+
WITH notice(day, note) AS (VALUES
|
|
59
|
+
('2026-01-01', '元旦 New Year'), ('2026-01-02', '元旦 New Year'),
|
|
60
|
+
('2026-01-03', '元旦 New Year'),
|
|
61
|
+
('2026-02-15', '春节 Spring Festival'), ('2026-02-16', '春节 Spring Festival'),
|
|
62
|
+
('2026-02-17', '春节 Spring Festival'), ('2026-02-18', '春节 Spring Festival'),
|
|
63
|
+
('2026-02-19', '春节 Spring Festival'), ('2026-02-20', '春节 Spring Festival'),
|
|
64
|
+
('2026-02-21', '春节 Spring Festival'), ('2026-02-22', '春节 Spring Festival'),
|
|
65
|
+
('2026-02-23', '春节 Spring Festival'),
|
|
66
|
+
('2026-04-04', '清明节 Qingming'), ('2026-04-05', '清明节 Qingming'),
|
|
67
|
+
('2026-04-06', '清明节 Qingming'),
|
|
68
|
+
('2026-05-01', '劳动节 Labour Day'), ('2026-05-02', '劳动节 Labour Day'),
|
|
69
|
+
('2026-05-03', '劳动节 Labour Day'), ('2026-05-04', '劳动节 Labour Day'),
|
|
70
|
+
('2026-05-05', '劳动节 Labour Day'),
|
|
71
|
+
('2026-06-19', '端午节 Dragon Boat'), ('2026-06-20', '端午节 Dragon Boat'),
|
|
72
|
+
('2026-06-21', '端午节 Dragon Boat'),
|
|
73
|
+
('2026-09-25', '中秋节 Mid-Autumn'), ('2026-09-26', '中秋节 Mid-Autumn'),
|
|
74
|
+
('2026-09-27', '中秋节 Mid-Autumn'),
|
|
75
|
+
('2026-10-01', '国庆节 National Day'), ('2026-10-02', '国庆节 National Day'),
|
|
76
|
+
('2026-10-03', '国庆节 National Day'), ('2026-10-04', '国庆节 National Day'),
|
|
77
|
+
('2026-10-05', '国庆节 National Day'), ('2026-10-06', '国庆节 National Day'),
|
|
78
|
+
('2026-10-07', '国庆节 National Day')
|
|
79
|
+
)
|
|
80
|
+
SELECT 'deepseek', day, note,
|
|
81
|
+
'https://www.gov.cn/zhengce/zhengceku/202511/content_7047091.htm',
|
|
82
|
+
'2026-10-02 00:00:00'
|
|
83
|
+
FROM notice;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
-- Whether a model answers a forced `tool_choice`, measured apart from `tools` (#570).
|
|
2
|
+
--
|
|
3
|
+
-- Claude Fable 5.1 (measured 2026-09-12, `src/chat-anthropic-structured.ts`),
|
|
4
|
+
-- Opus 5.5 and Sonnet 5.5 (their own model pages) call a tool when allowed and
|
|
5
|
+
-- answer 400 when `tool_choice` forces one: `"required"` or a named function,
|
|
6
|
+
-- which reach Anthropic as `any` / `tool`. `tool_call` sends no `tool_choice`,
|
|
7
|
+
-- so all three measured `tools = 1`, and Fable and Opus 5.5 are rank-1 members
|
|
8
|
+
-- of all four coding lanes (0091). A caller forcing a call got a wasted chain
|
|
9
|
+
-- slot through a lane and the 400 itself when pinned, with nothing in
|
|
10
|
+
-- `/v1/models` to say so.
|
|
11
|
+
--
|
|
12
|
+
-- A column like the five 0007 made, tri-state and written only by
|
|
13
|
+
-- conformance (`tool_choice_forced`, `src/conformance.ts`). NULL until
|
|
14
|
+
-- measured, and NULL **fails closed**: the gate refuses a request that forces
|
|
15
|
+
-- `tool_choice` for a model nobody has checked (`src/capabilities.ts`).
|
|
16
|
+
--
|
|
17
|
+
-- ## Which is why the order of the rollout is load-bearing
|
|
18
|
+
--
|
|
19
|
+
-- Every row starts NULL. Deploy the Worker that reads this before a
|
|
20
|
+
-- conformance run has measured the column, and every forced request on every
|
|
21
|
+
-- model is refused. So: this migration, then a conformance run (the script
|
|
22
|
+
-- writes the flag; the deployed Worker passes `tool_choice` through and the
|
|
23
|
+
-- conformance key is exempt from the gate), then the Worker. The column alone
|
|
24
|
+
-- is inert under the Worker that predates it.
|
|
25
|
+
|
|
26
|
+
ALTER TABLE models ADD COLUMN tool_choice_forced INTEGER CHECK (tool_choice_forced IN (0, 1));
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
-- Claude Haiku 5.5 catalogued, and Sonnet 5.5's cache read re-priced
|
|
2
|
+
-- (#591 — the model board's 2026-10-08 follow-ups).
|
|
3
|
+
--
|
|
4
|
+
-- Catalogues and prices; staffs no lane, for 0090's reason: an unmeasured
|
|
5
|
+
-- member makes a lane's capability `null` (`src/lanes.ts`). Haiku 5.5 is the
|
|
6
|
+
-- issue's candidate for `bb/chat-assistant` and `bb/extraction`, and that is a
|
|
7
|
+
-- later migration, after conformance has written its flags — the 0077 → 0088
|
|
8
|
+
-- order.
|
|
9
|
+
--
|
|
10
|
+
-- Every figure fetched 2026-10-08 UTC from Anthropic's own pages, cited per
|
|
11
|
+
-- row. Not the board: #591 says so, and #79 / #122 say why.
|
|
12
|
+
--
|
|
13
|
+
-- ## Left out, and why
|
|
14
|
+
--
|
|
15
|
+
-- **Claude Haiku 4.5 going Legacy.** Its page reads "Active (legacy)",
|
|
16
|
+
-- retirement "Not sooner than October 15, 2026", and no retirement date has
|
|
17
|
+
-- been announced. Nothing to write until one is: no migration put
|
|
18
|
+
-- `anthropic/claude-haiku-4-5-20251001` in a lane or a fallback chain, and its
|
|
19
|
+
-- prices are unchanged ($1 / $5, cache read $0.10). When a date is announced it
|
|
20
|
+
-- is 0090's GLM shape — disable on the date, never delete.
|
|
21
|
+
--
|
|
22
|
+
-- **OpenAI's Decisions API and Perplexity's `pplx-decider-v1.1-27b`.** Both
|
|
23
|
+
-- are candidates for `typed-decisions`, which is not a job in
|
|
24
|
+
-- `docs/vocabulary.md`, and both are a separate endpoint rather than a chat
|
|
25
|
+
-- completion — a route and a vocabulary decision, not a catalogue row. The
|
|
26
|
+
-- Decisions API also bills apart from `openai/gpt-6-luna` on Responses, so
|
|
27
|
+
-- 0090's row prices nothing it would serve.
|
|
28
|
+
--
|
|
29
|
+
-- **meraGPT `state-decider-1`, Perplexity's Agent API presets.** Neither host
|
|
30
|
+
-- has an `upstreams` row here (0090 on Perplexity), so a price change reaches
|
|
31
|
+
-- nothing that routes.
|
|
32
|
+
|
|
33
|
+
-- ── Claude Haiku 5.5 ──────────────────────────────────────────────────────────
|
|
34
|
+
-- https://platform.claude.com/docs/en/models/haiku-5-5/overview
|
|
35
|
+
--
|
|
36
|
+
-- Released 2026-10-07. Window 1M, max output 128K, no dated id: the API id is
|
|
37
|
+
-- `claude-haiku-5-5` and the page names no alias.
|
|
38
|
+
--
|
|
39
|
+
-- **Priced by prompt length, for the whole request** — the first Claude row
|
|
40
|
+
-- here that is. Every rate on the page is stated twice, "for prompts up to
|
|
41
|
+
-- 100,000 tokens" and "for prompts over 100,000 tokens", so the second row
|
|
42
|
+
-- starts at `prompt_tokens_from` 100001, as 0090 wrote "over 272K" as 272001:
|
|
43
|
+
--
|
|
44
|
+
-- ≤ 100K $0.10 / $0.50, cache read $0.01
|
|
45
|
+
-- > 100K $0.50 / $2.50, cache read $0.05 — 5x on every line
|
|
46
|
+
--
|
|
47
|
+
-- At a 5x step, `resolvePrice` choosing the short row for a long prompt is an
|
|
48
|
+
-- 80% under-count, so the test pins both sides of the boundary. Cache writes ($0.125 / $0.20 by TTL, and 5x
|
|
49
|
+
-- above 100K) have no column, as 0053 records.
|
|
50
|
+
--
|
|
51
|
+
-- **What it narrows, and which of it Cruise sees:**
|
|
52
|
+
--
|
|
53
|
+
-- - A non-default `temperature`, `top_p` or `top_k` returns 400 — the
|
|
54
|
+
-- Sonnet 5.5 rule 0090 recorded. Callers sending one get the host's answer.
|
|
55
|
+
-- - Manual extended thinking (`budget_tokens`) returns 400 and adaptive
|
|
56
|
+
-- thinking is on by default. Cruise sends no `budget_tokens` to Anthropic
|
|
57
|
+
-- anywhere in `src/`, and `src/messages-translate.ts` drops `thinking` on
|
|
58
|
+
-- the way in, so neither reaches the host from us.
|
|
59
|
+
-- - Thinking blocks work only in the producing account. The same file
|
|
60
|
+
-- returns none to the caller, so no history replays one across keys.
|
|
61
|
+
-- - Forced `tool_choice` is not stated either way on this page. 0093 made it
|
|
62
|
+
-- a measured column, NULL until conformance writes it, and NULL fails
|
|
63
|
+
-- closed — so the row cannot over-promise it.
|
|
64
|
+
-- - Its tokenizer counts the same text as ~30% more tokens than Haiku 4.5.
|
|
65
|
+
-- Cruise bills from the host's reported usage, so that is a price fact, not
|
|
66
|
+
-- a metering bug, and a lane comparison by headline rate understates it.
|
|
67
|
+
--
|
|
68
|
+
-- `retained` on the privacy page 0053 and 0090 quoted, unchanged for this row.
|
|
69
|
+
INSERT INTO models (id, upstream_id, upstream_model, max_context, max_output,
|
|
70
|
+
data_retention, data_retention_source, data_retention_as_of) VALUES
|
|
71
|
+
('anthropic/claude-haiku-5-5', 'anthropic', 'claude-haiku-5-5', 1000000, 128000,
|
|
72
|
+
'retained', 'https://privacy.claude.com/en/articles/7996868-is-my-data-used-for-model-training', '2026-10-08');
|
|
73
|
+
|
|
74
|
+
INSERT INTO price_observations
|
|
75
|
+
(observed_at, model, effective_from, prompt_tokens_from, peak_utc,
|
|
76
|
+
input_micros_per_mtok, output_micros_per_mtok, cached_input_micros_per_mtok, source, note)
|
|
77
|
+
VALUES
|
|
78
|
+
('2026-10-08 00:00:00', 'anthropic/claude-haiku-5-5', '2026-10-08', 0, '',
|
|
79
|
+
100000, 500000, 10000, 'https://platform.claude.com/docs/en/models/haiku-5-5/overview',
|
|
80
|
+
'First observation: Claude Haiku 5.5 (#591, 0094). Prompts up to 100,000 tokens.'),
|
|
81
|
+
('2026-10-08 00:00:00', 'anthropic/claude-haiku-5-5', '2026-10-08', 100001, '',
|
|
82
|
+
500000, 2500000, 50000, 'https://platform.claude.com/docs/en/models/haiku-5-5/overview',
|
|
83
|
+
'Long-prompt tier: prompts over 100,000 tokens pay 5x on every line, for the whole request.');
|
|
84
|
+
|
|
85
|
+
-- Web search at $10 per 1,000, as 0058 and 0090 wrote for every Claude row,
|
|
86
|
+
-- re-read on the tool's page today.
|
|
87
|
+
INSERT INTO price_components
|
|
88
|
+
(observed_at, model, effective_from, component, variant, micros, per, source, note)
|
|
89
|
+
VALUES
|
|
90
|
+
('2026-10-08 00:00:00', 'anthropic/claude-haiku-5-5', '2026-10-08', 'search', '', 10000000, 1000,
|
|
91
|
+
'https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool', 'First observation (0094).');
|
|
92
|
+
|
|
93
|
+
-- ── Claude Sonnet 5.5: cache read halved ──────────────────────────────────────
|
|
94
|
+
-- https://platform.claude.com/docs/en/release-notes/overview, 2026-10-07:
|
|
95
|
+
-- *"We've lowered the price of prompt cache reads on Claude Sonnet 5.5 from
|
|
96
|
+
-- $0.20 USD to $0.10 USD per million tokens: 0.05x the base input price
|
|
97
|
+
-- instead of 0.1x. Cache writes and all other prices are unchanged."*
|
|
98
|
+
--
|
|
99
|
+
-- The model's own page now prints $0.10 too, so the two agree — #591 reported
|
|
100
|
+
-- the pricing table still showing $0.20, and the release note is cited because
|
|
101
|
+
-- it carries the date. A new observation effective that day rather than an
|
|
102
|
+
-- edit: `price_observations` is append-only (0048), and requests served
|
|
103
|
+
-- 2026-10-02 → 06 were billed at $0.20, which was the price then.
|
|
104
|
+
--
|
|
105
|
+
-- Until this deploys, a cache read on this row is billed $0.10 / MTok over
|
|
106
|
+
-- the host. No migration has put it in a lane (0091 staffed Opus 5.5, not
|
|
107
|
+
-- Sonnet), so only a request naming it could have paid that; the ledger says
|
|
108
|
+
-- whether one did.
|
|
109
|
+
INSERT INTO price_observations
|
|
110
|
+
(observed_at, model, effective_from, prompt_tokens_from, peak_utc,
|
|
111
|
+
input_micros_per_mtok, output_micros_per_mtok, cached_input_micros_per_mtok, source, note)
|
|
112
|
+
VALUES
|
|
113
|
+
('2026-10-08 00:00:00', 'anthropic/claude-sonnet-5-5', '2026-10-07', 0, '',
|
|
114
|
+
2000000, 10000000, 100000, 'https://platform.claude.com/docs/en/release-notes/overview',
|
|
115
|
+
'Cache read lowered to $0.10 (0.05x base) on 2026-10-07; all other rates unchanged (#591, 0094).');
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
-- Request compression: the project's setting and the ledger's two figures
|
|
2
|
+
-- (#593). Spec: docs/compression.md.
|
|
3
|
+
--
|
|
4
|
+
-- ## `projects.compress`
|
|
5
|
+
--
|
|
6
|
+
-- Whether this project's requests have their tool outputs compressed. On the
|
|
7
|
+
-- project rather than the lane: a `bb/` lane serves every tenant, so a lane
|
|
8
|
+
-- operator choosing a lossy rewrite of other tenants' prompts is the widening
|
|
9
|
+
-- the cache keeps away from callers, moved to a different party; and the
|
|
10
|
+
-- saving lands on the project's bill, so the project is who buys it.
|
|
11
|
+
--
|
|
12
|
+
-- **0 for every project, existing and new.** Compression is lossy and off at
|
|
13
|
+
-- every level by default. A project is switched on through
|
|
14
|
+
-- `PUT /admin/projects/{project}/compression`, audited like a budget. It also
|
|
15
|
+
-- does nothing while the platform's `COMPRESS_MODE` is `off`, which is the
|
|
16
|
+
-- kill switch and the production default.
|
|
17
|
+
--
|
|
18
|
+
-- ## `ledger.compress_bytes_before` / `compress_bytes_after`
|
|
19
|
+
--
|
|
20
|
+
-- The UTF-8 length of the body sent to the served candidate, built from the
|
|
21
|
+
-- caller's tool outputs and from the compressed ones. Measured, not
|
|
22
|
+
-- estimated: the provider's billed input tokens are the *after* figure, and
|
|
23
|
+
-- the counterfactual bill was never measured, so the byte delta is the fact
|
|
24
|
+
-- and any money figure is derived from it and labelled so.
|
|
25
|
+
--
|
|
26
|
+
-- **NULL when compression did not run** — off at any level, a conformance
|
|
27
|
+
-- key, a request with no tool output, or a compressor that threw. Equal when
|
|
28
|
+
-- it ran and saved nothing. That keeps "off" and "ran and saved 0" two
|
|
29
|
+
-- different rows, which #593 asked for by name. No default, so every existing
|
|
30
|
+
-- row reads NULL, which is what it was.
|
|
31
|
+
--
|
|
32
|
+
-- ## Order
|
|
33
|
+
--
|
|
34
|
+
-- This, then the Worker. The Worker that predates the columns never reads
|
|
35
|
+
-- them; the Worker that reads them before this migration fails every key
|
|
36
|
+
-- lookup on the missing `projects.compress` column.
|
|
37
|
+
|
|
38
|
+
ALTER TABLE projects ADD COLUMN compress INTEGER NOT NULL DEFAULT 0 CHECK (compress IN (0, 1));
|
|
39
|
+
|
|
40
|
+
ALTER TABLE ledger ADD COLUMN compress_bytes_before INTEGER
|
|
41
|
+
CHECK (compress_bytes_before IS NULL OR compress_bytes_before >= 0);
|
|
42
|
+
ALTER TABLE ledger ADD COLUMN compress_bytes_after INTEGER
|
|
43
|
+
CHECK (compress_bytes_after IS NULL OR compress_bytes_after >= 0);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
-- A tenant lane can make compression its default (#608, follow-up to #593).
|
|
2
|
+
-- Spec: docs/compression.md, "The flag".
|
|
3
|
+
--
|
|
4
|
+
-- ## Why a lane, after 0095 said the project
|
|
5
|
+
--
|
|
6
|
+
-- 0095 put the setting on the project and left the lane for when a job turned
|
|
7
|
+
-- out to need it. The dogfood run (#593 slice 6) is that case: the saving
|
|
8
|
+
-- depends on the job, not the project. Agent tool loops send `role: "tool"`
|
|
9
|
+
-- messages full of logs and JSON; review traffic sends diffs as user text and
|
|
10
|
+
-- must never be shortened. The lane is where a job is named, so "compress by
|
|
11
|
+
-- default on `<tenant>/coding`" is the natural way to say it.
|
|
12
|
+
--
|
|
13
|
+
-- ## Tenant lanes only, and the schema says so
|
|
14
|
+
--
|
|
15
|
+
-- 0095's reason against a lane setting still holds for `bb/`: a platform lane
|
|
16
|
+
-- serves every tenant, so whoever runs it would be choosing a lossy rewrite of
|
|
17
|
+
-- other tenants' prompts. On `<tenant>/<slug>` the tenant owns both the lane
|
|
18
|
+
-- and every project that can call it, so the choice stays inside one tenant.
|
|
19
|
+
-- `updateLane` refuses it on a global lane with a 400; the CHECK is the same
|
|
20
|
+
-- rule where a write that skipped the route cannot get past it. Create needs
|
|
21
|
+
-- no check of its own: `laneIdFor` refuses any `bb/` id with a 403 before a
|
|
22
|
+
-- create reaches the insert.
|
|
23
|
+
--
|
|
24
|
+
-- ## 0 for every lane, existing and new
|
|
25
|
+
--
|
|
26
|
+
-- Lossy, so off by default at every level, as 0095. A lane switched on does
|
|
27
|
+
-- nothing while `COMPRESS_MODE` is `off`, and `x-cruise-compress: off` and a
|
|
28
|
+
-- conformance key still win over it (`decideCompression`).
|
|
29
|
+
--
|
|
30
|
+
-- ## Order
|
|
31
|
+
--
|
|
32
|
+
-- This, then the Worker. The Worker that predates the column never reads it;
|
|
33
|
+
-- the Worker that reads it before this migration fails every lane lookup.
|
|
34
|
+
|
|
35
|
+
ALTER TABLE lanes ADD COLUMN compress INTEGER NOT NULL DEFAULT 0
|
|
36
|
+
CHECK (compress IN (0, 1) AND (compress = 0 OR tenant_id IS NOT NULL));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
-- A tenant-wide compression default (#614, follow-up to #593 and #608).
|
|
2
|
+
-- Spec: docs/compression.md, "The flag".
|
|
3
|
+
--
|
|
4
|
+
-- ## What it is
|
|
5
|
+
--
|
|
6
|
+
-- The starting state of every project and lane the tenant creates from now
|
|
7
|
+
-- on. 0095 put the switch on the project and 0096 on the tenant's lanes; this
|
|
8
|
+
-- is the one switch for the whole account, so a tenant that wants compression
|
|
9
|
+
-- everywhere does not flip it once per project and once per lane.
|
|
10
|
+
--
|
|
11
|
+
-- ## Stamped at creation, never read live
|
|
12
|
+
--
|
|
13
|
+
-- The way `default_selection_policy` works (0066, #288). `createProject` reads
|
|
14
|
+
-- the column inside its own insert and `createLane` reads it when a create
|
|
15
|
+
-- names no `compress`, and the concrete value goes in the new row. Nothing on
|
|
16
|
+
-- the request path consults this column. Turning it on therefore switches on
|
|
17
|
+
-- no existing project or lane: compression is lossy, and one setting quietly
|
|
18
|
+
-- rewriting every project's traffic is the widening this repository refuses
|
|
19
|
+
-- everywhere else. Existing ones are changed one by one, by name, through the
|
|
20
|
+
-- routes that already exist.
|
|
21
|
+
--
|
|
22
|
+
-- ## 0 for every tenant, existing and new
|
|
23
|
+
--
|
|
24
|
+
-- Off by default at every level, as 0095 and 0096. A tenant provisioned after
|
|
25
|
+
-- this reads 0 by the column default, so `tenants.ts` needs no change.
|
|
26
|
+
--
|
|
27
|
+
-- ## Order
|
|
28
|
+
--
|
|
29
|
+
-- This, then the Worker. The Worker that predates the column never reads it;
|
|
30
|
+
-- the Worker that reads it before this migration fails every settings read
|
|
31
|
+
-- and every project create.
|
|
32
|
+
|
|
33
|
+
ALTER TABLE tenants ADD COLUMN default_compress INTEGER NOT NULL DEFAULT 0
|
|
34
|
+
CHECK (default_compress IN (0, 1));
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
-- The run a request belonged to, on the ledger (#617).
|
|
2
|
+
--
|
|
3
|
+
-- ## Why
|
|
4
|
+
--
|
|
5
|
+
-- A caller already names its run in `x-cruise-session` (#394) — an agent tenant's
|
|
6
|
+
-- builder sends `agent-<runId>` on every request — and until now the name
|
|
7
|
+
-- reached KV as an affinity pin and nothing else. So a question about one run
|
|
8
|
+
-- ("what did compression save on run 412?", agents#860) could only
|
|
9
|
+
-- be answered by matching timestamps against the run's log, which two
|
|
10
|
+
-- concurrent runs on one project defeat. A column answers it exactly, and the
|
|
11
|
+
-- compression figures (0095) are the first reader.
|
|
12
|
+
--
|
|
13
|
+
-- ## `ledger.session_digest`
|
|
14
|
+
--
|
|
15
|
+
-- `sha256(x-cruise-session)` in lowercase hex, never the value. The affinity
|
|
16
|
+
-- key hashes it for the reason `src/affinity.ts` gives — a run id is a caller
|
|
17
|
+
-- secret of sorts and must not sit in storage in the clear — and the ledger
|
|
18
|
+
-- outlives a one-hour pin by years, so the reason is stronger here, not
|
|
19
|
+
-- weaker. Unsalted, unlike `account`, on purpose: whoever holds the run id
|
|
20
|
+
-- must be able to find its rows (`npm run ledger -- --session <id>` hashes
|
|
21
|
+
-- what it is given), and a salt only the Worker holds would make the column
|
|
22
|
+
-- write-only. A digest of a guessable id is confirmable by someone with the
|
|
23
|
+
-- ledger and the guess, which is the same exposure `cache_digest` (0072)
|
|
24
|
+
-- accepted.
|
|
25
|
+
--
|
|
26
|
+
-- Recorded whenever the header was sent and valid, lane or pinned model: the
|
|
27
|
+
-- header is ignored for *routing* on a pinned model, but the run is still the
|
|
28
|
+
-- run. NULL when no header was sent, and on every existing row — no default.
|
|
29
|
+
--
|
|
30
|
+
-- ## Index
|
|
31
|
+
--
|
|
32
|
+
-- Partial, because most traffic sends no session and those rows should cost
|
|
33
|
+
-- the index nothing. Digest first: the one who asks holds a run id, not
|
|
34
|
+
-- necessarily the project it ran under. The rollup groups by project, so a
|
|
35
|
+
-- run id two tenants happen to share reads as two lines, never one sum.
|
|
36
|
+
--
|
|
37
|
+
-- ## Order
|
|
38
|
+
--
|
|
39
|
+
-- This, then the Worker. The Worker before this never names the column; the
|
|
40
|
+
-- one after it fails every ledger insert without it.
|
|
41
|
+
|
|
42
|
+
ALTER TABLE ledger ADD COLUMN session_digest TEXT
|
|
43
|
+
CHECK (session_digest IS NULL OR (length(session_digest) = 64 AND session_digest NOT GLOB '*[^0-9a-f]*'));
|
|
44
|
+
|
|
45
|
+
CREATE INDEX IF NOT EXISTS idx_ledger_session
|
|
46
|
+
ON ledger (session_digest, project_id)
|
|
47
|
+
WHERE session_digest IS NOT NULL;
|