@bongos/core 1.19.242 → 1.19.243
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/.bongos-core.json +10 -10
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/src/bongos/llm-pricing.js +43 -6
- package/src/module-api.js +3 -1
- package/tests/llm-pricing.mjs +65 -3
package/.bongos-core.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.243",
|
|
6
|
+
"core_contract": "1.19.243",
|
|
7
|
+
"source_commit": "ac9bed6cf6412a5916b8b5f1c6c946f3c733cc96",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-08-
|
|
9
|
+
"built_at": "2026-08-18T22:39:28.983Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 312,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
19
|
"file_count": 1660,
|
|
20
|
-
"tree_sha256": "
|
|
20
|
+
"tree_sha256": "28e71bece4c2803c63b8674af865cb7cfc74626f6e768d40e3742116571bb7d4",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/blocker-review/SKILL.md",
|
|
@@ -4347,12 +4347,12 @@
|
|
|
4347
4347
|
{
|
|
4348
4348
|
"path": "package-lock.json",
|
|
4349
4349
|
"mode": "0000644",
|
|
4350
|
-
"sha256": "
|
|
4350
|
+
"sha256": "c3f2be5aa7bbd5f5f40977d42f12485c3049df0ac811531d20bf3e7af51aed18"
|
|
4351
4351
|
},
|
|
4352
4352
|
{
|
|
4353
4353
|
"path": "package.json",
|
|
4354
4354
|
"mode": "0000644",
|
|
4355
|
-
"sha256": "
|
|
4355
|
+
"sha256": "c0b9cdaf8ef1290a7c61fc7068390a6a14b9477a0b84c17e9018c4ab832e4d7c"
|
|
4356
4356
|
},
|
|
4357
4357
|
{
|
|
4358
4358
|
"path": "public-docs/index.html",
|
|
@@ -5772,7 +5772,7 @@
|
|
|
5772
5772
|
{
|
|
5773
5773
|
"path": "src/bongos/llm-pricing.js",
|
|
5774
5774
|
"mode": "0000644",
|
|
5775
|
-
"sha256": "
|
|
5775
|
+
"sha256": "a932e617ee66dabc49b4087baf6606eeb2074f70ebb3efa0723b1d9c92add290"
|
|
5776
5776
|
},
|
|
5777
5777
|
{
|
|
5778
5778
|
"path": "src/bongos/metrics.js",
|
|
@@ -5967,7 +5967,7 @@
|
|
|
5967
5967
|
{
|
|
5968
5968
|
"path": "src/module-api.js",
|
|
5969
5969
|
"mode": "0000644",
|
|
5970
|
-
"sha256": "
|
|
5970
|
+
"sha256": "1f5ebdac8a94a258566b8d28fa14a3f47496e0f35e928e2d85ba85e19738134a"
|
|
5971
5971
|
},
|
|
5972
5972
|
{
|
|
5973
5973
|
"path": "src/module-loader/catalog.js",
|
|
@@ -7332,7 +7332,7 @@
|
|
|
7332
7332
|
{
|
|
7333
7333
|
"path": "tests/llm-pricing.mjs",
|
|
7334
7334
|
"mode": "0000644",
|
|
7335
|
-
"sha256": "
|
|
7335
|
+
"sha256": "64f8bd94dc461ca9b4ef82fae929d49675231afa6a24d6d65ba2dbe8721efc89"
|
|
7336
7336
|
},
|
|
7337
7337
|
{
|
|
7338
7338
|
"path": "tests/local_preview.mjs",
|
package/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.243",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@bongos/core",
|
|
9
|
-
"version": "1.19.
|
|
9
|
+
"version": "1.19.243",
|
|
10
10
|
"license": "AGPL-3.0-or-later",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"express": "^4.21.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bongos/core",
|
|
3
|
-
"version": "1.19.
|
|
3
|
+
"version": "1.19.243",
|
|
4
4
|
"description": "Cloud Bongos — the AI-first build platform core (GDS + platform surfaces + module system), installed as a versioned dependency (ADR 0108).",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"main": "src/platform-server.js",
|
|
@@ -49,15 +49,52 @@
|
|
|
49
49
|
// - opus = Claude Opus 5 / 4.8 / 4.7 ($5 in / $25 out) [re-verified]
|
|
50
50
|
// - sonnet = Claude Sonnet 4.6 ($3 in / $15 out) [re-verified]
|
|
51
51
|
// - haiku = Claude Haiku 4.5 ($1 in / $5 out) [re-verified]
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
52
|
+
// VERIFIED 2026-08-18 against the live models overview at platform.claude.com
|
|
53
|
+
// (task 1003001 — the task the note this replaces pointed at):
|
|
54
|
+
// - sonnet = Claude Sonnet 5 ($2 in / $10 out) [WAS $3/$15 = Sonnet 4.6's rate]
|
|
55
|
+
// - fable = Claude Fable 5 / Mythos 5 ($10/$50) [re-verified, unchanged]
|
|
56
|
+
// - opus = Claude Opus 5 / 4.8 / 4.7 ($5/$25) [re-verified, unchanged]
|
|
57
|
+
// - haiku = Claude Haiku 4.5 ($1/$5) [re-verified, unchanged]
|
|
58
|
+
// The live page states Sonnet 5 as $2/$10 flatly — NO introductory qualifier and
|
|
59
|
+
// no scheduled increase. (An earlier launch note describing $2/$10 as
|
|
60
|
+
// introductory through 2026-08-31 is superseded; a cached model table that still
|
|
61
|
+
// carries the qualifier is stale, which is precisely why this file re-verifies
|
|
62
|
+
// against the live page rather than a recalled figure.)
|
|
63
|
+
//
|
|
64
|
+
// WHY IT MATTERED, and why it was worth its own task: the grader's default worker
|
|
65
|
+
// model is claude-sonnet-5 (modules/grading/grader-rubric.json), so the panel is
|
|
66
|
+
// this platform's heaviest sonnet consumer, and ADR 0054 pays each shipped session
|
|
67
|
+
// round(true_cost_usd × 1.20). An over-priced sonnet row therefore OVER-PAID real
|
|
68
|
+
// credits — the mirror image of the fable bug recorded above, which under-paid.
|
|
69
|
+
//
|
|
70
|
+
// HISTORICAL ROWS ARE NOT RE-PRICED. cost_log rows written before today keep the
|
|
71
|
+
// dollars we believed at the time: the ledger is a record of what was charged and
|
|
72
|
+
// paid, and rewriting paid rows to a new rate would make the credit history
|
|
73
|
+
// disagree with the credit_log it produced. Expect a visible step change in
|
|
74
|
+
// cost-per-ship around 2026-08-18 for sonnet-heavy work; this note is its
|
|
75
|
+
// explanation.
|
|
76
|
+
//
|
|
77
|
+
// THE FAMILY↔MODEL BINDING IS NOW DATA (FAMILY_CURRENT_MODEL below) and pinned by
|
|
78
|
+
// tests/llm-pricing.mjs: a family whose current model is re-pinned cannot keep the
|
|
79
|
+
// old model's rate silently, which is exactly the failure this task fixed.
|
|
80
|
+
// The model each family's rate is quoted FROM. Data, not logic: nothing branches
|
|
81
|
+
// on it, but it makes the claim "this row is <model>'s price" checkable — the test
|
|
82
|
+
// asserts each family's rate against that model's published figures, so re-pinning
|
|
83
|
+
// a family to a newer model without re-pricing it reds the build (task 1003001).
|
|
84
|
+
// Legacy members of a family are knowingly mis-priced (the family-pricing trade-off
|
|
85
|
+
// documented above): claude-sonnet-4-6 is really $3/$15 and prices here as Sonnet 5.
|
|
86
|
+
const FAMILY_CURRENT_MODEL = Object.freeze({
|
|
87
|
+
fable: 'claude-fable-5',
|
|
88
|
+
opus: 'claude-opus-5',
|
|
89
|
+
sonnet: 'claude-sonnet-5',
|
|
90
|
+
haiku: 'claude-haiku-4-5',
|
|
91
|
+
});
|
|
92
|
+
|
|
56
93
|
const PRICES = {
|
|
57
94
|
// family : { input, output, cache_write_5m, cache_write_1h, cache_read } (USD / 1e6 tokens)
|
|
58
95
|
fable: { input: 10, output: 50, cache_write_5m: 12.5, cache_write_1h: 20, cache_read: 1 },
|
|
59
96
|
opus: { input: 5, output: 25, cache_write_5m: 6.25, cache_write_1h: 10, cache_read: 0.5 },
|
|
60
|
-
sonnet: { input:
|
|
97
|
+
sonnet: { input: 2, output: 10, cache_write_5m: 2.5, cache_write_1h: 4, cache_read: 0.2 },
|
|
61
98
|
haiku: { input: 1, output: 5, cache_write_5m: 1.25, cache_write_1h: 2, cache_read: 0.1 },
|
|
62
99
|
};
|
|
63
100
|
|
|
@@ -246,4 +283,4 @@ function componentsFromModelUsage(modelUsage) {
|
|
|
246
283
|
};
|
|
247
284
|
}
|
|
248
285
|
|
|
249
|
-
module.exports = { PRICES, familyFor, priceUsage, canonicalizeModelId, priceModelUsage, componentsFromModelUsage };
|
|
286
|
+
module.exports = { PRICES, FAMILY_CURRENT_MODEL, familyFor, priceUsage, canonicalizeModelId, priceModelUsage, componentsFromModelUsage };
|
package/src/module-api.js
CHANGED
|
@@ -911,8 +911,10 @@ const { validateOrRespond, LIMITS, parseId, asyncHandler, corsPublicGet, parsePa
|
|
|
911
911
|
// landed since 1.19.240 with no explicit bump. run 32184475745. (task 1002620)
|
|
912
912
|
// 1.19.242 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
913
913
|
// landed since 1.19.241 with no explicit bump. run 32185198139. (task 1002620)
|
|
914
|
+
// 1.19.243 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
915
|
+
// landed since 1.19.242 with no explicit bump. run 32193666731. (task 1002620)
|
|
914
916
|
// ---------------------------------------------------------------------------
|
|
915
|
-
const CORE_VERSION = '1.19.
|
|
917
|
+
const CORE_VERSION = '1.19.243'; // CI auto-patch carrier (ADR 0161); see changelog above
|
|
916
918
|
|
|
917
919
|
// A namespaced logger so a module's log lines are attributable + consistent.
|
|
918
920
|
// Usage: const log = api.logger('dev-box'); log.info('mounted');
|
package/tests/llm-pricing.mjs
CHANGED
|
@@ -5,12 +5,17 @@
|
|
|
5
5
|
// Re-VERIFIED + extended 2026-08-16 (task 1002883): fable (Fable 5 / Mythos 5)
|
|
6
6
|
// $10/$50 — the family familyFor() used to miss, so Fable sessions priced at the
|
|
7
7
|
// opus fallback and cost-plus under-paid by half.
|
|
8
|
+
// Re-VERIFIED 2026-08-18 (task 1003001): sonnet is CLAUDE SONNET 5 at $2/$10 —
|
|
9
|
+
// the row had carried Sonnet 4.6's $3/$15, over-pricing the grader panel (whose
|
|
10
|
+
// default worker IS claude-sonnet-5) and therefore over-paying cost-plus credits.
|
|
11
|
+
// The family↔model binding is now data (FAMILY_CURRENT_MODEL) and is pinned below,
|
|
12
|
+
// so a future re-pin cannot keep an old model's rate silently.
|
|
8
13
|
// Run: node tests/llm-pricing.mjs
|
|
9
14
|
|
|
10
15
|
import { strict as assert } from 'node:assert';
|
|
11
16
|
import { createRequire } from 'node:module';
|
|
12
17
|
const require = createRequire(import.meta.url);
|
|
13
|
-
const { priceUsage, familyFor, PRICES, canonicalizeModelId, priceModelUsage } = require('../src/bongos/llm-pricing.js');
|
|
18
|
+
const { priceUsage, familyFor, PRICES, FAMILY_CURRENT_MODEL, canonicalizeModelId, priceModelUsage } = require('../src/bongos/llm-pricing.js');
|
|
14
19
|
|
|
15
20
|
let passed = 0, failed = 0;
|
|
16
21
|
function test(name, fn) {
|
|
@@ -101,11 +106,68 @@ test('opus 4.8: 1M input + 1M output = $5 + $25 = $30', () => {
|
|
|
101
106
|
assert.equal(r.family, 'opus');
|
|
102
107
|
});
|
|
103
108
|
|
|
104
|
-
test('sonnet input ($
|
|
105
|
-
assert.ok(near(priceUsage('claude-sonnet-
|
|
109
|
+
test('sonnet input ($2 — Sonnet 5) vs haiku output ($5) use their own rates', () => {
|
|
110
|
+
assert.ok(near(priceUsage('claude-sonnet-5', { input_tokens: M }).usd, 2));
|
|
106
111
|
assert.ok(near(priceUsage('claude-haiku-4-5', { output_tokens: M }).usd, 5));
|
|
107
112
|
});
|
|
108
113
|
|
|
114
|
+
test('the grader panel prices at Sonnet 5, not Sonnet 4.6 — 1M in + 1M out = $12', () => {
|
|
115
|
+
// The regression this task fixed, stated as money: the panel's default worker is
|
|
116
|
+
// claude-sonnet-5 (modules/grading/grader-rubric.json), and the row used to say
|
|
117
|
+
// $3/$15 = $18 for the same tokens. ADR 0054 pays round(true_cost × 1.20), so the
|
|
118
|
+
// extra $6 per million became real over-paid credits.
|
|
119
|
+
const r = priceUsage('claude-sonnet-5', { input_tokens: M, output_tokens: M });
|
|
120
|
+
assert.ok(near(r.usd, 12), `got ${r.usd}`);
|
|
121
|
+
assert.equal(r.family, 'sonnet');
|
|
122
|
+
assert.equal(r.unknown_model, false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('a LEGACY family member is knowingly mis-priced — sonnet 4.6 rides Sonnet 5 rates', () => {
|
|
126
|
+
// Family pricing assumes the CURRENT model in each family (the file says so).
|
|
127
|
+
// claude-sonnet-4-6 really costs $3/$15; here it prices at $2/$10. This test
|
|
128
|
+
// exists so that trade-off is a recorded decision rather than a surprise — if the
|
|
129
|
+
// platform ever runs a legacy model in earnest, this is the test that should fail
|
|
130
|
+
// first and force a per-model override.
|
|
131
|
+
assert.ok(near(priceUsage('claude-sonnet-4-6', { input_tokens: M }).usd, 2));
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// ── the family↔model binding (task 1003001) ─────────────────────────────────
|
|
135
|
+
// Each family's rate is quoted from ONE named model. These literals are the
|
|
136
|
+
// published per-model figures, kept separate from PRICES on purpose: if someone
|
|
137
|
+
// re-pins a family to a newer model, the two copies disagree and this test names
|
|
138
|
+
// the model in its failure — the drift that shipped Sonnet 4.6's price under a
|
|
139
|
+
// Sonnet 5 workload cannot recur silently.
|
|
140
|
+
const PUBLISHED = {
|
|
141
|
+
'claude-fable-5': { input: 10, output: 50 },
|
|
142
|
+
'claude-opus-5': { input: 5, output: 25 },
|
|
143
|
+
'claude-sonnet-5': { input: 2, output: 10 },
|
|
144
|
+
'claude-haiku-4-5': { input: 1, output: 5 },
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
test('every family rate matches the published price of the model it names', () => {
|
|
148
|
+
for (const [family, modelId] of Object.entries(FAMILY_CURRENT_MODEL)) {
|
|
149
|
+
const published = PUBLISHED[modelId];
|
|
150
|
+
assert.ok(published, `FAMILY_CURRENT_MODEL.${family} names ${modelId}, which this test has no published price for — add it (verified against the live models page), do not guess`);
|
|
151
|
+
assert.equal(PRICES[family].input, published.input, `${family} input should be ${modelId}'s $${published.input}`);
|
|
152
|
+
assert.equal(PRICES[family].output, published.output, `${family} output should be ${modelId}'s $${published.output}`);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('every family names a model familyFor() actually resolves back to it', () => {
|
|
157
|
+
for (const [family, modelId] of Object.entries(FAMILY_CURRENT_MODEL)) {
|
|
158
|
+
assert.equal(familyFor(modelId), family,
|
|
159
|
+
`FAMILY_CURRENT_MODEL.${family} names ${modelId}, but familyFor('${modelId}') says ${familyFor(modelId)} — the binding and the matcher disagree`);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('cache rates ride the published multipliers off each family base (1.25× / 2× / 0.1×)', () => {
|
|
164
|
+
for (const [family, p] of Object.entries(PRICES)) {
|
|
165
|
+
assert.ok(near(p.cache_write_5m, p.input * 1.25), `${family} 5m write should be 1.25× input`);
|
|
166
|
+
assert.ok(near(p.cache_write_1h, p.input * 2), `${family} 1h write should be 2× input`);
|
|
167
|
+
assert.ok(near(p.cache_read, p.input * 0.1), `${family} cache read should be 0.1× input`);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
|
|
109
171
|
test('cache read is 0.1× input (opus $0.50 / 1M)', () => {
|
|
110
172
|
const r = priceUsage('claude-opus-4-8', { cache_read_input_tokens: M });
|
|
111
173
|
assert.ok(near(r.usd, 0.5), `got ${r.usd}`);
|