@namzu/sdk 62.5.0 → 62.6.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/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/dist/agents/file-definitions.d.ts +1 -1
- package/dist/agents/file-definitions.js +1 -1
- package/dist/agents/runAgent.d.ts +1 -1
- package/dist/agents/runAgent.js +1 -1
- package/dist/compaction/model-summary.d.ts.map +1 -1
- package/dist/compaction/model-summary.js +2 -1
- package/dist/compaction/model-summary.js.map +1 -1
- package/dist/compaction/verifier.d.ts.map +1 -1
- package/dist/compaction/verifier.js +2 -1
- package/dist/compaction/verifier.js.map +1 -1
- package/dist/eval/judge.d.ts.map +1 -1
- package/dist/eval/judge.js +2 -1
- package/dist/eval/judge.js.map +1 -1
- package/dist/pricing/catalogue.generated.d.ts.map +1 -1
- package/dist/pricing/catalogue.generated.js +19 -0
- package/dist/pricing/catalogue.generated.js.map +1 -1
- package/dist/runtime/query/auto-review/classifier.d.ts.map +1 -1
- package/dist/runtime/query/auto-review/classifier.js +2 -1
- package/dist/runtime/query/auto-review/classifier.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +3 -0
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/request-repair.d.ts +9 -1
- package/dist/runtime/query/iteration/request-repair.d.ts.map +1 -1
- package/dist/runtime/query/iteration/request-repair.js +29 -0
- package/dist/runtime/query/iteration/request-repair.js.map +1 -1
- package/dist/runtime/query/iteration/side-call.d.ts +16 -0
- package/dist/runtime/query/iteration/side-call.d.ts.map +1 -0
- package/dist/runtime/query/iteration/side-call.js +50 -0
- package/dist/runtime/query/iteration/side-call.js.map +1 -0
- package/dist/types/common/index.d.ts +31 -0
- package/dist/types/common/index.d.ts.map +1 -1
- package/dist/types/common/index.js +18 -2
- package/dist/types/common/index.js.map +1 -1
- package/dist/types/session/events.d.ts +10 -0
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/utils/cost.d.ts +6 -0
- package/dist/utils/cost.d.ts.map +1 -1
- package/dist/utils/cost.js +19 -0
- package/dist/utils/cost.js.map +1 -1
- package/package.json +2 -2
- package/src/agents/file-definitions.ts +1 -1
- package/src/agents/runAgent.ts +1 -1
- package/src/compaction/model-summary.ts +2 -1
- package/src/compaction/verifier.ts +2 -1
- package/src/eval/judge.ts +2 -1
- package/src/pricing/catalogue.generated.ts +19 -0
- package/src/pricing/rates.source.json +7 -0
- package/src/runtime/query/auto-review/classifier.ts +2 -1
- package/src/runtime/query/iteration/index.ts +3 -0
- package/src/runtime/query/iteration/request-repair.ts +42 -1
- package/src/runtime/query/iteration/side-call.ts +60 -0
- package/src/types/common/index.ts +54 -2
- package/src/types/session/events.ts +7 -0
- package/src/utils/cost.ts +26 -0
|
@@ -33,6 +33,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
33
33
|
inputCostPer1M: 10,
|
|
34
34
|
outputCostPer1M: 50,
|
|
35
35
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 1, writeCostPer1M: 12.5 },
|
|
36
|
+
webSearchCostPer1000: 10,
|
|
36
37
|
},
|
|
37
38
|
],
|
|
38
39
|
[
|
|
@@ -41,6 +42,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
41
42
|
inputCostPer1M: 10,
|
|
42
43
|
outputCostPer1M: 50,
|
|
43
44
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.25, writeCostPer1M: 12.5 },
|
|
45
|
+
webSearchCostPer1000: 10,
|
|
44
46
|
},
|
|
45
47
|
],
|
|
46
48
|
[
|
|
@@ -50,6 +52,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
50
52
|
outputCostPer1M: 40,
|
|
51
53
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.2, writeCostPer1M: 10 },
|
|
52
54
|
fastMultiplier: 2,
|
|
55
|
+
webSearchCostPer1000: 10,
|
|
53
56
|
},
|
|
54
57
|
],
|
|
55
58
|
[
|
|
@@ -58,6 +61,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
58
61
|
inputCostPer1M: 1,
|
|
59
62
|
outputCostPer1M: 5,
|
|
60
63
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.1, writeCostPer1M: 1.25 },
|
|
64
|
+
webSearchCostPer1000: 10,
|
|
61
65
|
},
|
|
62
66
|
],
|
|
63
67
|
[
|
|
@@ -66,6 +70,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
66
70
|
inputCostPer1M: 10,
|
|
67
71
|
outputCostPer1M: 50,
|
|
68
72
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 1, writeCostPer1M: 12.5 },
|
|
73
|
+
webSearchCostPer1000: 10,
|
|
69
74
|
},
|
|
70
75
|
],
|
|
71
76
|
[
|
|
@@ -74,6 +79,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
74
79
|
inputCostPer1M: 10,
|
|
75
80
|
outputCostPer1M: 50,
|
|
76
81
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.25, writeCostPer1M: 12.5 },
|
|
82
|
+
webSearchCostPer1000: 10,
|
|
77
83
|
},
|
|
78
84
|
],
|
|
79
85
|
[
|
|
@@ -83,6 +89,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
83
89
|
outputCostPer1M: 40,
|
|
84
90
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.2, writeCostPer1M: 10 },
|
|
85
91
|
fastMultiplier: 2,
|
|
92
|
+
webSearchCostPer1000: 10,
|
|
86
93
|
},
|
|
87
94
|
],
|
|
88
95
|
[
|
|
@@ -91,6 +98,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
91
98
|
inputCostPer1M: 15,
|
|
92
99
|
outputCostPer1M: 75,
|
|
93
100
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 1.5, writeCostPer1M: 18.75 },
|
|
101
|
+
webSearchCostPer1000: 10,
|
|
94
102
|
},
|
|
95
103
|
],
|
|
96
104
|
[
|
|
@@ -99,6 +107,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
99
107
|
inputCostPer1M: 15,
|
|
100
108
|
outputCostPer1M: 75,
|
|
101
109
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 1.5, writeCostPer1M: 18.75 },
|
|
110
|
+
webSearchCostPer1000: 10,
|
|
102
111
|
},
|
|
103
112
|
],
|
|
104
113
|
[
|
|
@@ -107,6 +116,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
107
116
|
inputCostPer1M: 5,
|
|
108
117
|
outputCostPer1M: 25,
|
|
109
118
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.5, writeCostPer1M: 6.25 },
|
|
119
|
+
webSearchCostPer1000: 10,
|
|
110
120
|
},
|
|
111
121
|
],
|
|
112
122
|
[
|
|
@@ -115,6 +125,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
115
125
|
inputCostPer1M: 5,
|
|
116
126
|
outputCostPer1M: 25,
|
|
117
127
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.5, writeCostPer1M: 6.25 },
|
|
128
|
+
webSearchCostPer1000: 10,
|
|
118
129
|
},
|
|
119
130
|
],
|
|
120
131
|
[
|
|
@@ -124,6 +135,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
124
135
|
outputCostPer1M: 25,
|
|
125
136
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.5, writeCostPer1M: 6.25 },
|
|
126
137
|
fastMultiplier: 2,
|
|
138
|
+
webSearchCostPer1000: 10,
|
|
127
139
|
},
|
|
128
140
|
],
|
|
129
141
|
[
|
|
@@ -133,6 +145,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
133
145
|
outputCostPer1M: 25,
|
|
134
146
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.5, writeCostPer1M: 6.25 },
|
|
135
147
|
fastMultiplier: 2,
|
|
148
|
+
webSearchCostPer1000: 10,
|
|
136
149
|
},
|
|
137
150
|
],
|
|
138
151
|
[
|
|
@@ -142,6 +155,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
142
155
|
outputCostPer1M: 20,
|
|
143
156
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.2, writeCostPer1M: 5 },
|
|
144
157
|
fastMultiplier: 2,
|
|
158
|
+
webSearchCostPer1000: 10,
|
|
145
159
|
},
|
|
146
160
|
],
|
|
147
161
|
[
|
|
@@ -150,6 +164,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
150
164
|
inputCostPer1M: 3,
|
|
151
165
|
outputCostPer1M: 15,
|
|
152
166
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.3, writeCostPer1M: 3.75 },
|
|
167
|
+
webSearchCostPer1000: 10,
|
|
153
168
|
},
|
|
154
169
|
],
|
|
155
170
|
[
|
|
@@ -158,6 +173,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
158
173
|
inputCostPer1M: 3,
|
|
159
174
|
outputCostPer1M: 15,
|
|
160
175
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.3, writeCostPer1M: 3.75 },
|
|
176
|
+
webSearchCostPer1000: 10,
|
|
161
177
|
},
|
|
162
178
|
],
|
|
163
179
|
[
|
|
@@ -166,6 +182,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
166
182
|
inputCostPer1M: 3,
|
|
167
183
|
outputCostPer1M: 15,
|
|
168
184
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.3, writeCostPer1M: 3.75 },
|
|
185
|
+
webSearchCostPer1000: 10,
|
|
169
186
|
},
|
|
170
187
|
],
|
|
171
188
|
[
|
|
@@ -174,6 +191,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
174
191
|
inputCostPer1M: 2,
|
|
175
192
|
outputCostPer1M: 10,
|
|
176
193
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.2, writeCostPer1M: 2.5 },
|
|
194
|
+
webSearchCostPer1000: 10,
|
|
177
195
|
},
|
|
178
196
|
],
|
|
179
197
|
[
|
|
@@ -182,6 +200,7 @@ export const VENDOR_RATES: readonly VendorRates[] = [
|
|
|
182
200
|
inputCostPer1M: 2,
|
|
183
201
|
outputCostPer1M: 10,
|
|
184
202
|
cache: { promptIncludesCacheReads: false, readCostPer1M: 0.1, writeCostPer1M: 2.5 },
|
|
203
|
+
webSearchCostPer1000: 10,
|
|
185
204
|
},
|
|
186
205
|
],
|
|
187
206
|
]),
|
|
@@ -24,6 +24,12 @@
|
|
|
24
24
|
"2x on the full context window, stacking with cache pricing). A model without it",
|
|
25
25
|
"has no published fast price, so a fast request on it is reported as unpriced.",
|
|
26
26
|
"",
|
|
27
|
+
"webSearchPer1000 (optional, per vendor) is the price in USD of 1,000 hosted web",
|
|
28
|
+
"searches, billed per request on top of tokens (verified 2026-11-10 against the",
|
|
29
|
+
"pricing page's web search section: $10 per 1,000, a failed search is not billed).",
|
|
30
|
+
"It is copied onto every model row of that vendor. Absent means searches are not",
|
|
31
|
+
"part of the total.",
|
|
32
|
+
"",
|
|
27
33
|
"Matching is EXACT on a normalised id (lowercased, one trailing -YYYYMMDD or",
|
|
28
34
|
"@YYYYMMDD snapshot suffix removed). Deliberately not prefix or substring:",
|
|
29
35
|
"within one vendor here, ids one character apart differ in price by 4x, so a",
|
|
@@ -64,6 +70,7 @@
|
|
|
64
70
|
"verified": "2026-11-10",
|
|
65
71
|
"promptIncludesCacheReads": false,
|
|
66
72
|
"reportsCacheWrites": true,
|
|
73
|
+
"webSearchPer1000": 10,
|
|
67
74
|
"note": "The last two rows exist because the driver's own offline catalogue offers those models and this table did not price them — a lookup-key gap that reads as `cost unknown` and is invisible to the generator's own check, which only proves the module matches this file. `providers/anthropic` asserts the two lists agree. Vendor list prices, every row checked against its pricing page on the `verified` date. Cache read is the vendor's published 0.1x of the input rate, except on the six models it prices differently: 0.05x on claude-opus-5-5 and claude-sonnet-5-5 and 0.025x on claude-fable-5-1, claude-mythos-5-1, claude-fable-5-2 and claude-mythos-5-2, entered at the published rate rather than derived. claude-haiku-5-5 has no row on purpose: the vendor prices it by prompt length ($0.10 in / $0.50 out up to 100,000 prompt tokens, $0.50 / $2.50 above, cache counted in the length), this table holds one rate per model, and either single rate would be wrong for the other half of requests, so its cost reports unknown. Cache write is its published 1.25x for the five-minute entry, which is the default TTL and the one the driver's `cacheControl: { type: 'auto' }` asks for. claude-sonnet-5 launched at an introductory $2/$10 with $3/$15 scheduled from 2026-09-01, and this table recorded the scheduled rate; the vendor has since made $2/$10 the standard price and cancelled the increase. The table has no time dimension, so a future promotional window is still recorded at the list rate and over-reported rather than mis-modelled.",
|
|
68
75
|
"models": [
|
|
69
76
|
{
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
} from '../../../utils/backoff.js'
|
|
39
39
|
import { SCOPE_ATTRIBUTE } from '../../../utils/log/types.js'
|
|
40
40
|
import { type Logger, resolveLogger } from '../../../utils/logger.js'
|
|
41
|
+
import { chatStreamWithSamplingRepair } from '../iteration/side-call.js'
|
|
41
42
|
import {
|
|
42
43
|
STAGE_ONE_INSTRUCTION,
|
|
43
44
|
STAGE_TWO_INSTRUCTION,
|
|
@@ -209,7 +210,7 @@ export function createAutoReviewClassifier(
|
|
|
209
210
|
// ignores it would otherwise hold the call open past its deadline, and
|
|
210
211
|
// a turn cancelled while it waits would wait with it.
|
|
211
212
|
const collected = collectChatCompletion(
|
|
212
|
-
options.provider
|
|
213
|
+
chatStreamWithSamplingRepair(options.provider, {
|
|
213
214
|
model: options.model,
|
|
214
215
|
messages,
|
|
215
216
|
maxTokens: stage === 1 ? 64 : 8_192,
|
|
@@ -39,7 +39,13 @@ import { isProviderRejectedImageError } from './provider-rejected-image.js'
|
|
|
39
39
|
* compaction summaries, do not pass through it.
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
-
export type RejectedParameter =
|
|
42
|
+
export type RejectedParameter =
|
|
43
|
+
| 'effort'
|
|
44
|
+
| 'thinking'
|
|
45
|
+
| 'temperature'
|
|
46
|
+
| 'topP'
|
|
47
|
+
| 'topK'
|
|
48
|
+
| 'responseFormat'
|
|
43
49
|
|
|
44
50
|
export interface MediaRemoval {
|
|
45
51
|
readonly count: number
|
|
@@ -110,6 +116,7 @@ const PARAMETER_NAMES: Record<RejectedParameter, string> = {
|
|
|
110
116
|
thinking: 'thinking',
|
|
111
117
|
temperature: 'temperature',
|
|
112
118
|
topP: 'top[_ ]?p',
|
|
119
|
+
topK: 'top[_ ]?k',
|
|
113
120
|
responseFormat:
|
|
114
121
|
'(?:response_format|output_config(?:\\.format)?|json_schema|json_object|structured\\s+output)',
|
|
115
122
|
}
|
|
@@ -124,6 +131,10 @@ const PARAMETER_PATTERNS = Object.fromEntries(
|
|
|
124
131
|
]),
|
|
125
132
|
) as Record<RejectedParameter, { named: RegExp; refused: RegExp }>
|
|
126
133
|
|
|
134
|
+
const SAMPLING = ['temperature', 'topP', 'topK'] as const satisfies readonly RejectedParameter[]
|
|
135
|
+
const SAMPLING_GROUP =
|
|
136
|
+
/\btemperature\b.{0,80}\btop[_ ]?[pk]\b|\btop[_ ]?[pk]\b.{0,80}\btemperature\b/i
|
|
137
|
+
|
|
127
138
|
const BOTH_SAMPLING =
|
|
128
139
|
/temperature.{0,60}top[_ ]?p.{0,80}(?:cannot|can['’]t|may\s+not|should\s+not).{0,20}(?:both|together)/i
|
|
129
140
|
|
|
@@ -156,6 +167,7 @@ function rejectedParameters(
|
|
|
156
167
|
thinking: params.thinking !== undefined,
|
|
157
168
|
temperature: params.temperature !== undefined,
|
|
158
169
|
topP: params.topP !== undefined,
|
|
170
|
+
topK: params.topK !== undefined,
|
|
159
171
|
responseFormat: params.responseFormat !== undefined,
|
|
160
172
|
} satisfies Record<RejectedParameter, boolean>
|
|
161
173
|
const found: RejectedParameter[] = []
|
|
@@ -165,6 +177,12 @@ function rejectedParameters(
|
|
|
165
177
|
if (structured ? pattern.named.test(text) : pattern.refused.test(text)) found.push(name)
|
|
166
178
|
}
|
|
167
179
|
if (found.length === 0 && set.topP && BOTH_SAMPLING.test(text)) found.push('topP')
|
|
180
|
+
// The vendor words a refusal of sampling controls as a group ("Omit
|
|
181
|
+
// temperature, top_p, and top_k"), so naming one of them in a refusal that
|
|
182
|
+
// names the others is enough for whichever of them was sent.
|
|
183
|
+
if (found.length === 0 && SAMPLING_GROUP.test(text)) {
|
|
184
|
+
for (const name of SAMPLING) if (set[name]) found.push(name)
|
|
185
|
+
}
|
|
168
186
|
return found
|
|
169
187
|
}
|
|
170
188
|
|
|
@@ -726,6 +744,7 @@ function withoutParameters(
|
|
|
726
744
|
if (names.has('thinking')) next.thinking = undefined
|
|
727
745
|
if (names.has('temperature')) next.temperature = undefined
|
|
728
746
|
if (names.has('topP')) next.topP = undefined
|
|
747
|
+
if (names.has('topK')) next.topK = undefined
|
|
729
748
|
if (names.has('responseFormat')) next.responseFormat = undefined
|
|
730
749
|
return next
|
|
731
750
|
}
|
|
@@ -741,3 +760,25 @@ function isHandledElsewhere(error: unknown, params: ChatCompletionParams): boole
|
|
|
741
760
|
}
|
|
742
761
|
return isImageInputRefusal(error)
|
|
743
762
|
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* Which of `temperature`, `top_p` and `top_k` a provider refused on this
|
|
766
|
+
* request, from the same reading of its rejection the main turn uses. Empty
|
|
767
|
+
* for any other failure, so a caller can strip exactly these and nothing else.
|
|
768
|
+
*/
|
|
769
|
+
export function rejectedSamplingParameters(
|
|
770
|
+
error: unknown,
|
|
771
|
+
params: ChatCompletionParams,
|
|
772
|
+
): RejectedParameter[] {
|
|
773
|
+
const rejection = classifyRequestRejection(error, params)
|
|
774
|
+
if (rejection?.kind !== 'parameter') return []
|
|
775
|
+
return rejection.parameters.filter((name) => (SAMPLING as readonly string[]).includes(name))
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
/** The request without the named sampling parameters. */
|
|
779
|
+
export function withoutSamplingParameters(
|
|
780
|
+
params: ChatCompletionParams,
|
|
781
|
+
names: ReadonlySet<RejectedParameter>,
|
|
782
|
+
): ChatCompletionParams {
|
|
783
|
+
return withoutParameters(params, names)
|
|
784
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ChatCompletionParams,
|
|
3
|
+
LLMProvider,
|
|
4
|
+
StreamChunk,
|
|
5
|
+
} from '../../../types/provider/index.js'
|
|
6
|
+
import {
|
|
7
|
+
type RejectedParameter,
|
|
8
|
+
rejectedSamplingParameters,
|
|
9
|
+
withoutSamplingParameters,
|
|
10
|
+
} from './request-repair.js'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* What each model was found to refuse, for the life of the provider object.
|
|
14
|
+
* Weakly keyed so a dropped provider takes its entry with it.
|
|
15
|
+
*/
|
|
16
|
+
const refused = new WeakMap<object, Map<string, Set<RejectedParameter>>>()
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A model call made outside the turn loop (a compaction summary, its verifier,
|
|
20
|
+
* the auto-review classifier) that asks for a deterministic answer with
|
|
21
|
+
* `temperature: 0`. Current models refuse sampling parameters outright, and
|
|
22
|
+
* the turn loop already recovers from that; this gives side calls the same
|
|
23
|
+
* recovery instead of letting the call fail and the feature with it.
|
|
24
|
+
*
|
|
25
|
+
* The request goes out as asked. If the provider refuses a sampling parameter
|
|
26
|
+
* BEFORE any output arrived, it is resent without exactly those parameters,
|
|
27
|
+
* and the finding is kept for the model so later calls omit them up front.
|
|
28
|
+
* Nothing is kept unless the resend was accepted, and any other failure is
|
|
29
|
+
* thrown unchanged.
|
|
30
|
+
*/
|
|
31
|
+
export async function* chatStreamWithSamplingRepair(
|
|
32
|
+
provider: LLMProvider,
|
|
33
|
+
params: ChatCompletionParams,
|
|
34
|
+
): AsyncGenerator<StreamChunk> {
|
|
35
|
+
const perModel = refused.get(provider) ?? new Map<string, Set<RejectedParameter>>()
|
|
36
|
+
refused.set(provider, perModel)
|
|
37
|
+
const known = perModel.get(params.model)
|
|
38
|
+
let request = known ? withoutSamplingParameters(params, known) : params
|
|
39
|
+
let stripped: Set<RejectedParameter> | undefined
|
|
40
|
+
for (;;) {
|
|
41
|
+
let yielded = false
|
|
42
|
+
try {
|
|
43
|
+
for await (const chunk of provider.chatStream(request)) {
|
|
44
|
+
yielded = true
|
|
45
|
+
yield chunk
|
|
46
|
+
}
|
|
47
|
+
if (stripped) {
|
|
48
|
+
const merged = new Set([...(perModel.get(params.model) ?? []), ...stripped])
|
|
49
|
+
perModel.set(params.model, merged)
|
|
50
|
+
}
|
|
51
|
+
return
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if (yielded || stripped) throw error
|
|
54
|
+
const names = rejectedSamplingParameters(error, request)
|
|
55
|
+
if (names.length === 0) throw error
|
|
56
|
+
stripped = new Set(names)
|
|
57
|
+
request = withoutSamplingParameters(request, stripped)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -50,6 +50,42 @@ export interface TokenUsage {
|
|
|
50
50
|
* unreported.
|
|
51
51
|
*/
|
|
52
52
|
speed?: import('../provider/chat.js').InferenceSpeed
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Hosted web searches the provider ran for this call and bills per request.
|
|
56
|
+
* Unlike the per-call facts below it IS a count of work done, so it is
|
|
57
|
+
* summed across calls. Absent means the provider did not report one.
|
|
58
|
+
*/
|
|
59
|
+
webSearchRequests?: number
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* The service tier the provider says served this call (`standard`,
|
|
63
|
+
* `priority`, `batch`). A per-call fact, never summed. Absent means
|
|
64
|
+
* unreported.
|
|
65
|
+
*/
|
|
66
|
+
serviceTier?: string
|
|
67
|
+
|
|
68
|
+
/** The region the provider says ran this call, when it says. Per call, never summed. */
|
|
69
|
+
inferenceGeo?: string
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Why the provider's prompt cache did not serve a prefix it had before, when
|
|
73
|
+
* it explains. Per call, never summed. Absent means no miss was explained: the
|
|
74
|
+
* provider reported nothing, a pending answer, or a hit.
|
|
75
|
+
*/
|
|
76
|
+
cacheMiss?: CacheMiss
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** A prompt-cache miss as the provider explains it. See {@link TokenUsage.cacheMiss}. */
|
|
80
|
+
export interface CacheMiss {
|
|
81
|
+
/**
|
|
82
|
+
* The provider's own reason, e.g. `model_changed`, `system_changed`,
|
|
83
|
+
* `tools_changed`, `messages_changed`, `previous_message_not_found`,
|
|
84
|
+
* `unavailable`.
|
|
85
|
+
*/
|
|
86
|
+
reason: string
|
|
87
|
+
/** Input tokens that missed the cache because of it, when the provider counts them. */
|
|
88
|
+
missedTokens?: number
|
|
53
89
|
}
|
|
54
90
|
|
|
55
91
|
export function accumulateTokenUsage(current: TokenUsage, addition: TokenUsage): TokenUsage {
|
|
@@ -66,8 +102,12 @@ export function accumulateTokenUsage(current: TokenUsage, addition: TokenUsage):
|
|
|
66
102
|
...(current.reasoningTokens !== undefined || addition.reasoningTokens !== undefined
|
|
67
103
|
? { reasoningTokens: (current.reasoningTokens ?? 0) + (addition.reasoningTokens ?? 0) }
|
|
68
104
|
: {}),
|
|
69
|
-
|
|
70
|
-
|
|
105
|
+
...(current.webSearchRequests !== undefined || addition.webSearchRequests !== undefined
|
|
106
|
+
? { webSearchRequests: (current.webSearchRequests ?? 0) + (addition.webSearchRequests ?? 0) }
|
|
107
|
+
: {}),
|
|
108
|
+
// `cacheTtlMs`, `cacheWriteTtlTokens`, `speed`, `serviceTier`,
|
|
109
|
+
// `inferenceGeo` and `cacheMiss` are per-call facts and are deliberately
|
|
110
|
+
// not carried into a sum.
|
|
71
111
|
}
|
|
72
112
|
}
|
|
73
113
|
|
|
@@ -112,6 +152,18 @@ export function mergeTokenUsage(current: TokenUsage, next: TokenUsage): TokenUsa
|
|
|
112
152
|
...(next.speed !== undefined || current.speed !== undefined
|
|
113
153
|
? { speed: next.speed ?? current.speed }
|
|
114
154
|
: {}),
|
|
155
|
+
...(next.webSearchRequests !== undefined || current.webSearchRequests !== undefined
|
|
156
|
+
? { webSearchRequests: Math.max(current.webSearchRequests ?? 0, next.webSearchRequests ?? 0) }
|
|
157
|
+
: {}),
|
|
158
|
+
...(next.serviceTier !== undefined || current.serviceTier !== undefined
|
|
159
|
+
? { serviceTier: next.serviceTier ?? current.serviceTier }
|
|
160
|
+
: {}),
|
|
161
|
+
...(next.inferenceGeo !== undefined || current.inferenceGeo !== undefined
|
|
162
|
+
? { inferenceGeo: next.inferenceGeo ?? current.inferenceGeo }
|
|
163
|
+
: {}),
|
|
164
|
+
...(next.cacheMiss !== undefined || current.cacheMiss !== undefined
|
|
165
|
+
? { cacheMiss: next.cacheMiss ?? current.cacheMiss }
|
|
166
|
+
: {}),
|
|
115
167
|
}
|
|
116
168
|
}
|
|
117
169
|
|
|
@@ -926,6 +926,13 @@ type CoreSessionEvent =
|
|
|
926
926
|
* absent means unknown, and a host must not assume one.
|
|
927
927
|
*/
|
|
928
928
|
cache?: { ttlMs: number; touched: boolean }
|
|
929
|
+
/**
|
|
930
|
+
* Why the provider says the latest model call did not read the cache
|
|
931
|
+
* prefix it had before, when it explains one. Absent means no miss was
|
|
932
|
+
* explained: nothing reported, a pending answer, or a hit. A host that
|
|
933
|
+
* shows it should do so quietly; a miss after an edit is ordinary.
|
|
934
|
+
*/
|
|
935
|
+
cacheMiss?: { reason: string; missedTokens?: number }
|
|
929
936
|
/**
|
|
930
937
|
* How large the CONTEXT is right now, and how large it may get.
|
|
931
938
|
*
|
package/src/utils/cost.ts
CHANGED
|
@@ -48,6 +48,12 @@ export interface ModelPricing {
|
|
|
48
48
|
* charged at the standard rate, which would under-report it.
|
|
49
49
|
*/
|
|
50
50
|
fastMultiplier?: number
|
|
51
|
+
/**
|
|
52
|
+
* What the vendor charges per 1,000 hosted web searches
|
|
53
|
+
* (`TokenUsage.webSearchRequests`). Absent means no published search price:
|
|
54
|
+
* searches are then not part of the total, as before this field existed.
|
|
55
|
+
*/
|
|
56
|
+
webSearchCostPer1000?: number
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
export { ZERO_COST }
|
|
@@ -61,6 +67,26 @@ interface Priced {
|
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
function priceUsage(usage: TokenUsage, pricing: ModelPricing): Priced {
|
|
70
|
+
const tokens = priceTokens(usage, pricing)
|
|
71
|
+
const searches = usage.webSearchRequests ?? 0
|
|
72
|
+
if (searches === 0 || pricing.webSearchCostPer1000 === undefined) return tokens
|
|
73
|
+
// Per request, so no speed or tier multiple applies to it.
|
|
74
|
+
return { ...tokens, cost: tokens.cost + (searches / 1000) * pricing.webSearchCostPer1000 }
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Tiers with a published per-token price (anything but `priority` and `batch`; a compatible endpoint may report `default` or `auto`). The vendor lists none for `priority`
|
|
79
|
+
* (a capacity commitment) or `batch` (a different endpoint), so tokens served
|
|
80
|
+
* on one are unpriced rather than charged at the standard rate.
|
|
81
|
+
*/
|
|
82
|
+
function isStandardTier(tier: string | undefined): boolean {
|
|
83
|
+
return tier !== 'priority' && tier !== 'batch'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function priceTokens(usage: TokenUsage, pricing: ModelPricing): Priced {
|
|
87
|
+
if (!isStandardTier(usage.serviceTier)) {
|
|
88
|
+
return { cost: 0, cacheDiscount: 0, unpriced: usage.totalTokens }
|
|
89
|
+
}
|
|
64
90
|
if (usage.speed === 'fast') {
|
|
65
91
|
const multiplier = pricing.fastMultiplier
|
|
66
92
|
if (multiplier === undefined) {
|