praxis-agent 0.62.3 → 0.62.6
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 +2 -2
- package/dist/application/background-agent-manager.js +16 -0
- package/dist/application/session-service.js +56 -4
- package/dist/application/subagent-service.js +15 -0
- package/dist/application/turn-accounting.js +24 -0
- package/dist/application/workflow-manager.js +12 -0
- package/dist/cli/protocol.js +4 -2
- package/dist/core/runtime.d.ts +7 -0
- package/dist/core/runtime.js +63 -23
- package/dist/core/usage.d.ts +9 -0
- package/dist/core/usage.js +102 -10
- package/dist/persistence/subagent-lifecycle-store.d.ts +1 -0
- package/dist/persistence/subagent-lifecycle-store.js +4 -0
- package/dist/providers/anthropic-compatible.js +45 -10
- package/dist/providers/anthropic-model-spec.d.ts +2 -0
- package/dist/providers/anthropic-model-spec.js +18 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,7 +92,7 @@ For Anthropic Messages:
|
|
|
92
92
|
```sh
|
|
93
93
|
export PRAXIS_PROVIDER="anthropic"
|
|
94
94
|
export PRAXIS_API_KEY="your-api-key"
|
|
95
|
-
export PRAXIS_MODEL="claude-sonnet-4-
|
|
95
|
+
export PRAXIS_MODEL="claude-sonnet-4-6"
|
|
96
96
|
|
|
97
97
|
cd /path/to/project
|
|
98
98
|
praxis
|
|
@@ -100,7 +100,7 @@ praxis
|
|
|
100
100
|
|
|
101
101
|
Anthropic models use a 200,000-token context window by default, including
|
|
102
102
|
unknown model IDs. Add the exact terminal `[1m]` suffix (for example,
|
|
103
|
-
`claude-sonnet-4-
|
|
103
|
+
`claude-sonnet-4-6[1m]`) to request a 1,000,000-token context window;
|
|
104
104
|
Praxis keeps that selected model public, removes the suffix on the wire, and
|
|
105
105
|
adds the `context-1m-2025-08-07` Anthropic beta once. An explicit
|
|
106
106
|
`PRAXIS_CONTEXT_WINDOW_TOKENS` value overrides either inferred window.
|
|
@@ -77,6 +77,7 @@ const modelUsageCounterFields = [
|
|
|
77
77
|
'outputTokens',
|
|
78
78
|
'cacheReadInputTokens',
|
|
79
79
|
'cacheCreationInputTokens',
|
|
80
|
+
'cacheCreationInputTokens1h',
|
|
80
81
|
'webSearchRequests',
|
|
81
82
|
];
|
|
82
83
|
const modelUsageMetadataFields = ['contextWindow', 'maxOutputTokens'];
|
|
@@ -90,6 +91,10 @@ function assertValidModelUsageEntry(model, usage) {
|
|
|
90
91
|
throw new Error(`Model usage for "${model}" has an invalid ${field} counter`);
|
|
91
92
|
}
|
|
92
93
|
}
|
|
94
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
95
|
+
(usage.cacheCreationInputTokens ?? 0)) {
|
|
96
|
+
throw new Error(`Model usage for "${model}" has an invalid cacheCreationInputTokens1h counter`);
|
|
97
|
+
}
|
|
93
98
|
for (const field of modelUsageMetadataFields) {
|
|
94
99
|
const value = usage[field];
|
|
95
100
|
if (value !== undefined && (!Number.isSafeInteger(value) || value < 1)) {
|
|
@@ -120,14 +125,20 @@ function addUsageChecked(model, left, right) {
|
|
|
120
125
|
const outputTokens = left.outputTokens + right.outputTokens;
|
|
121
126
|
const cacheReadInputTokens = (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0);
|
|
122
127
|
const cacheCreationInputTokens = (left.cacheCreationInputTokens ?? 0) + (right.cacheCreationInputTokens ?? 0);
|
|
128
|
+
const cacheCreationInputTokens1h = (left.cacheCreationInputTokens1h ?? 0) +
|
|
129
|
+
(right.cacheCreationInputTokens1h ?? 0);
|
|
123
130
|
const webSearchRequests = (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0);
|
|
124
131
|
if (!Number.isSafeInteger(inputTokens) ||
|
|
125
132
|
!Number.isSafeInteger(outputTokens) ||
|
|
126
133
|
!Number.isSafeInteger(cacheReadInputTokens) ||
|
|
127
134
|
!Number.isSafeInteger(cacheCreationInputTokens) ||
|
|
135
|
+
!Number.isSafeInteger(cacheCreationInputTokens1h) ||
|
|
128
136
|
!Number.isSafeInteger(webSearchRequests)) {
|
|
129
137
|
throw new Error('Model usage total overflow');
|
|
130
138
|
}
|
|
139
|
+
if (cacheCreationInputTokens1h > cacheCreationInputTokens) {
|
|
140
|
+
throw new Error(`Model usage${model === undefined ? '' : ` for "${model}"`} has an invalid cacheCreationInputTokens1h counter`);
|
|
141
|
+
}
|
|
131
142
|
// Aggregates without a model stay counter-only; per-model rows merge their
|
|
132
143
|
// capability metadata with conflict rejection.
|
|
133
144
|
const metadata = model === undefined ? {} : mergeModelUsageMetadata(model, left, right);
|
|
@@ -136,6 +147,7 @@ function addUsageChecked(model, left, right) {
|
|
|
136
147
|
outputTokens,
|
|
137
148
|
...(cacheReadInputTokens === 0 ? {} : { cacheReadInputTokens }),
|
|
138
149
|
...(cacheCreationInputTokens === 0 ? {} : { cacheCreationInputTokens }),
|
|
150
|
+
...(cacheCreationInputTokens1h === 0 ? {} : { cacheCreationInputTokens1h }),
|
|
139
151
|
...(webSearchRequests === 0 ? {} : { webSearchRequests }),
|
|
140
152
|
...metadata,
|
|
141
153
|
};
|
|
@@ -147,6 +159,10 @@ function assertValidResultUsage(usage) {
|
|
|
147
159
|
throw new Error(`Model usage total has an invalid ${field} counter`);
|
|
148
160
|
}
|
|
149
161
|
}
|
|
162
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
163
|
+
(usage.cacheCreationInputTokens ?? 0)) {
|
|
164
|
+
throw new Error('Model usage total has an invalid cacheCreationInputTokens1h counter');
|
|
165
|
+
}
|
|
150
166
|
}
|
|
151
167
|
function addApiDuration(value, total, field) {
|
|
152
168
|
if (!Number.isFinite(value) || value < 0) {
|
|
@@ -14,7 +14,7 @@ import { projectNativeSessionEntries } from './native-session-projection.js';
|
|
|
14
14
|
import { classifyClaudeInterruption, } from '../native/interruption.js';
|
|
15
15
|
import { findUnresolvedClaudeToolCalls, getClaudeContentBlocks, } from '../native/tool-links.js';
|
|
16
16
|
import { createClaudeAgentSettingEntry, createClaudeHookAttachmentEntries, createClaudeRuleAttachmentEntry, translateProviderEvents, } from '../native/translation.js';
|
|
17
|
-
import { AgentRunCancelledError, AgentRuntime, MALFORMED_TOOL_INPUT_MESSAGE, ModelProviderError, } from '../core/runtime.js';
|
|
17
|
+
import { AgentBudgetExceededError, AgentRunCancelledError, AgentRuntime, MALFORMED_TOOL_INPUT_MESSAGE, ModelProviderError, } from '../core/runtime.js';
|
|
18
18
|
import { resolveToolSchedulingPolicy } from '../core/tool-scheduling-policy.js';
|
|
19
19
|
import { BackgroundTaskRuntime, } from './background-task-runtime.js';
|
|
20
20
|
import { backgroundAgentNotificationMarkers, } from './background-agent-manager.js';
|
|
@@ -115,14 +115,30 @@ const emptyToolRegistry = {
|
|
|
115
115
|
execute: async () => ({ content: '', isError: false }),
|
|
116
116
|
};
|
|
117
117
|
function mergeUsage(left, right) {
|
|
118
|
+
for (const usage of [left, right]) {
|
|
119
|
+
const oneHour = usage.cacheCreationInputTokens1h;
|
|
120
|
+
if (oneHour !== undefined &&
|
|
121
|
+
(!Number.isSafeInteger(oneHour) ||
|
|
122
|
+
oneHour < 0 ||
|
|
123
|
+
oneHour > (usage.cacheCreationInputTokens ?? 0))) {
|
|
124
|
+
throw new Error('Model usage has an invalid cacheCreationInputTokens1h counter');
|
|
125
|
+
}
|
|
126
|
+
}
|
|
118
127
|
const cacheReadInputTokens = (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0);
|
|
119
128
|
const cacheCreationInputTokens = (left.cacheCreationInputTokens ?? 0) + (right.cacheCreationInputTokens ?? 0);
|
|
129
|
+
const cacheCreationInputTokens1h = (left.cacheCreationInputTokens1h ?? 0) +
|
|
130
|
+
(right.cacheCreationInputTokens1h ?? 0);
|
|
120
131
|
const webSearchRequests = (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0);
|
|
132
|
+
if (!Number.isSafeInteger(cacheCreationInputTokens1h) ||
|
|
133
|
+
cacheCreationInputTokens1h > cacheCreationInputTokens) {
|
|
134
|
+
throw new Error('Model usage has an invalid cacheCreationInputTokens1h counter');
|
|
135
|
+
}
|
|
121
136
|
return {
|
|
122
137
|
inputTokens: left.inputTokens + right.inputTokens,
|
|
123
138
|
outputTokens: left.outputTokens + right.outputTokens,
|
|
124
139
|
...(cacheReadInputTokens === 0 ? {} : { cacheReadInputTokens }),
|
|
125
140
|
...(cacheCreationInputTokens === 0 ? {} : { cacheCreationInputTokens }),
|
|
141
|
+
...(cacheCreationInputTokens1h === 0 ? {} : { cacheCreationInputTokens1h }),
|
|
126
142
|
...(webSearchRequests === 0 ? {} : { webSearchRequests }),
|
|
127
143
|
};
|
|
128
144
|
}
|
|
@@ -131,6 +147,7 @@ const sessionUsageCounterFields = [
|
|
|
131
147
|
'outputTokens',
|
|
132
148
|
'cacheReadInputTokens',
|
|
133
149
|
'cacheCreationInputTokens',
|
|
150
|
+
'cacheCreationInputTokens1h',
|
|
134
151
|
'webSearchRequests',
|
|
135
152
|
];
|
|
136
153
|
const sessionUsageMetadataFields = ['contextWindow', 'maxOutputTokens'];
|
|
@@ -144,6 +161,10 @@ function assertValidSessionUsageEntry(model, usage) {
|
|
|
144
161
|
throw new Error(`Model usage for "${model}" has an invalid ${field} counter`);
|
|
145
162
|
}
|
|
146
163
|
}
|
|
164
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
165
|
+
(usage.cacheCreationInputTokens ?? 0)) {
|
|
166
|
+
throw new Error(`Model usage for "${model}" has an invalid cacheCreationInputTokens1h counter`);
|
|
167
|
+
}
|
|
147
168
|
for (const field of sessionUsageMetadataFields) {
|
|
148
169
|
const value = usage[field];
|
|
149
170
|
if (value !== undefined && (!Number.isSafeInteger(value) || value < 1)) {
|
|
@@ -174,20 +195,27 @@ function addSessionUsageChecked(model, left, right) {
|
|
|
174
195
|
const outputTokens = left.outputTokens + right.outputTokens;
|
|
175
196
|
const cacheReadInputTokens = (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0);
|
|
176
197
|
const cacheCreationInputTokens = (left.cacheCreationInputTokens ?? 0) + (right.cacheCreationInputTokens ?? 0);
|
|
198
|
+
const cacheCreationInputTokens1h = (left.cacheCreationInputTokens1h ?? 0) +
|
|
199
|
+
(right.cacheCreationInputTokens1h ?? 0);
|
|
177
200
|
const webSearchRequests = (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0);
|
|
178
201
|
if (!Number.isSafeInteger(inputTokens) ||
|
|
179
202
|
!Number.isSafeInteger(outputTokens) ||
|
|
180
203
|
!Number.isSafeInteger(cacheReadInputTokens) ||
|
|
181
204
|
!Number.isSafeInteger(cacheCreationInputTokens) ||
|
|
205
|
+
!Number.isSafeInteger(cacheCreationInputTokens1h) ||
|
|
182
206
|
!Number.isSafeInteger(webSearchRequests)) {
|
|
183
207
|
throw new Error('Model usage total overflow');
|
|
184
208
|
}
|
|
209
|
+
if (cacheCreationInputTokens1h > cacheCreationInputTokens) {
|
|
210
|
+
throw new Error(`Model usage for "${model}" has an invalid cacheCreationInputTokens1h counter`);
|
|
211
|
+
}
|
|
185
212
|
const metadata = mergeSessionUsageMetadata(model, left, right);
|
|
186
213
|
return {
|
|
187
214
|
inputTokens,
|
|
188
215
|
outputTokens,
|
|
189
216
|
...(cacheReadInputTokens === 0 ? {} : { cacheReadInputTokens }),
|
|
190
217
|
...(cacheCreationInputTokens === 0 ? {} : { cacheCreationInputTokens }),
|
|
218
|
+
...(cacheCreationInputTokens1h === 0 ? {} : { cacheCreationInputTokens1h }),
|
|
191
219
|
...(webSearchRequests === 0 ? {} : { webSearchRequests }),
|
|
192
220
|
...metadata,
|
|
193
221
|
};
|
|
@@ -228,6 +256,7 @@ function hasNonZeroUsage(usage) {
|
|
|
228
256
|
usage.outputTokens > 0 ||
|
|
229
257
|
(usage.cacheReadInputTokens ?? 0) > 0 ||
|
|
230
258
|
(usage.cacheCreationInputTokens ?? 0) > 0 ||
|
|
259
|
+
(usage.cacheCreationInputTokens1h ?? 0) > 0 ||
|
|
231
260
|
(usage.webSearchRequests ?? 0) > 0);
|
|
232
261
|
}
|
|
233
262
|
function requireUsageCounter(value, field) {
|
|
@@ -244,6 +273,12 @@ function requireManualCompactUsage(usage) {
|
|
|
244
273
|
if (usage.cacheCreationInputTokens !== undefined) {
|
|
245
274
|
requireUsageCounter(usage.cacheCreationInputTokens, 'usage.cacheCreationInputTokens');
|
|
246
275
|
}
|
|
276
|
+
if (usage.cacheCreationInputTokens1h !== undefined) {
|
|
277
|
+
requireUsageCounter(usage.cacheCreationInputTokens1h, 'usage.cacheCreationInputTokens1h');
|
|
278
|
+
if (usage.cacheCreationInputTokens1h > (usage.cacheCreationInputTokens ?? 0)) {
|
|
279
|
+
throw new TypeError('usage.cacheCreationInputTokens1h must not exceed usage.cacheCreationInputTokens');
|
|
280
|
+
}
|
|
281
|
+
}
|
|
247
282
|
if (usage.webSearchRequests !== undefined) {
|
|
248
283
|
requireUsageCounter(usage.webSearchRequests, 'usage.webSearchRequests');
|
|
249
284
|
}
|
|
@@ -3935,9 +3970,23 @@ export class ClaudeSessionService {
|
|
|
3935
3970
|
permissionUpdates: this.sessionPermissionUpdates.get(sessionId) ?? [],
|
|
3936
3971
|
onPermissionUpdates: (updates) => this.applyPermissionUpdates(sessionId, updates),
|
|
3937
3972
|
};
|
|
3938
|
-
const attemptMainTurn = () =>
|
|
3939
|
-
|
|
3940
|
-
|
|
3973
|
+
const attemptMainTurn = async () => {
|
|
3974
|
+
try {
|
|
3975
|
+
return signal
|
|
3976
|
+
? await runtime.run({ ...runtimeRequest, signal })
|
|
3977
|
+
: await runtime.run(runtimeRequest);
|
|
3978
|
+
}
|
|
3979
|
+
catch (error) {
|
|
3980
|
+
if (error instanceof AgentBudgetExceededError) {
|
|
3981
|
+
turnAccounting.complete({
|
|
3982
|
+
kind: 'runtime',
|
|
3983
|
+
recovery: recoveryResults,
|
|
3984
|
+
result: error.result,
|
|
3985
|
+
});
|
|
3986
|
+
}
|
|
3987
|
+
throw error;
|
|
3988
|
+
}
|
|
3989
|
+
};
|
|
3941
3990
|
const surfaceExhaustedRecovery = (error) => {
|
|
3942
3991
|
this.options.eventSink?.({
|
|
3943
3992
|
type: 'failed',
|
|
@@ -3975,6 +4024,9 @@ export class ClaudeSessionService {
|
|
|
3975
4024
|
retryError instanceof AgentRunCancelledError) {
|
|
3976
4025
|
throw new AgentRunCancelledError();
|
|
3977
4026
|
}
|
|
4027
|
+
if (retryError instanceof AgentBudgetExceededError) {
|
|
4028
|
+
throw retryError;
|
|
4029
|
+
}
|
|
3978
4030
|
surfaceExhaustedRecovery(error);
|
|
3979
4031
|
throw error;
|
|
3980
4032
|
}
|
|
@@ -33,6 +33,7 @@ function mergeSubagentUsage(left, right) {
|
|
|
33
33
|
'outputTokens',
|
|
34
34
|
'cacheReadInputTokens',
|
|
35
35
|
'cacheCreationInputTokens',
|
|
36
|
+
'cacheCreationInputTokens1h',
|
|
36
37
|
'webSearchRequests',
|
|
37
38
|
]) {
|
|
38
39
|
const value = usage[field];
|
|
@@ -46,6 +47,10 @@ function mergeSubagentUsage(left, right) {
|
|
|
46
47
|
throw new Error(`Subagent usage has an invalid ${field}`);
|
|
47
48
|
}
|
|
48
49
|
}
|
|
50
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
51
|
+
(usage.cacheCreationInputTokens ?? 0)) {
|
|
52
|
+
throw new Error('Subagent usage has an invalid cacheCreationInputTokens1h counter');
|
|
53
|
+
}
|
|
49
54
|
}
|
|
50
55
|
const counters = {
|
|
51
56
|
inputTokens: left.inputTokens + right.inputTokens,
|
|
@@ -53,11 +58,16 @@ function mergeSubagentUsage(left, right) {
|
|
|
53
58
|
cacheReadInputTokens: (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0),
|
|
54
59
|
cacheCreationInputTokens: (left.cacheCreationInputTokens ?? 0) +
|
|
55
60
|
(right.cacheCreationInputTokens ?? 0),
|
|
61
|
+
cacheCreationInputTokens1h: (left.cacheCreationInputTokens1h ?? 0) +
|
|
62
|
+
(right.cacheCreationInputTokens1h ?? 0),
|
|
56
63
|
webSearchRequests: (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0),
|
|
57
64
|
};
|
|
58
65
|
if (Object.values(counters).some((value) => !Number.isSafeInteger(value))) {
|
|
59
66
|
throw new Error('Subagent usage total overflow');
|
|
60
67
|
}
|
|
68
|
+
if (counters.cacheCreationInputTokens1h > counters.cacheCreationInputTokens) {
|
|
69
|
+
throw new Error('Subagent usage has an invalid cacheCreationInputTokens1h counter');
|
|
70
|
+
}
|
|
61
71
|
const metadata = (field) => {
|
|
62
72
|
const leftValue = left[field];
|
|
63
73
|
const rightValue = right[field];
|
|
@@ -79,6 +89,11 @@ function mergeSubagentUsage(left, right) {
|
|
|
79
89
|
...(counters.cacheCreationInputTokens === 0
|
|
80
90
|
? {}
|
|
81
91
|
: { cacheCreationInputTokens: counters.cacheCreationInputTokens }),
|
|
92
|
+
...(counters.cacheCreationInputTokens1h === 0
|
|
93
|
+
? {}
|
|
94
|
+
: {
|
|
95
|
+
cacheCreationInputTokens1h: counters.cacheCreationInputTokens1h,
|
|
96
|
+
}),
|
|
82
97
|
...(counters.webSearchRequests === 0
|
|
83
98
|
? {}
|
|
84
99
|
: { webSearchRequests: counters.webSearchRequests }),
|
|
@@ -5,6 +5,7 @@ const counterFields = [
|
|
|
5
5
|
'outputTokens',
|
|
6
6
|
'cacheReadInputTokens',
|
|
7
7
|
'cacheCreationInputTokens',
|
|
8
|
+
'cacheCreationInputTokens1h',
|
|
8
9
|
'webSearchRequests',
|
|
9
10
|
];
|
|
10
11
|
const metadataFields = ['contextWindow', 'maxOutputTokens'];
|
|
@@ -25,19 +26,26 @@ function mergeUsage(left, right) {
|
|
|
25
26
|
}
|
|
26
27
|
const cacheReadInputTokens = (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0);
|
|
27
28
|
const cacheCreationInputTokens = (left.cacheCreationInputTokens ?? 0) + (right.cacheCreationInputTokens ?? 0);
|
|
29
|
+
const cacheCreationInputTokens1h = (left.cacheCreationInputTokens1h ?? 0) +
|
|
30
|
+
(right.cacheCreationInputTokens1h ?? 0);
|
|
28
31
|
const webSearchRequests = (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0);
|
|
29
32
|
if (!Number.isSafeInteger(left.inputTokens + right.inputTokens) ||
|
|
30
33
|
!Number.isSafeInteger(left.outputTokens + right.outputTokens) ||
|
|
31
34
|
!Number.isSafeInteger(cacheReadInputTokens) ||
|
|
32
35
|
!Number.isSafeInteger(cacheCreationInputTokens) ||
|
|
36
|
+
!Number.isSafeInteger(cacheCreationInputTokens1h) ||
|
|
33
37
|
!Number.isSafeInteger(webSearchRequests)) {
|
|
34
38
|
throw new Error('Model usage total overflow');
|
|
35
39
|
}
|
|
40
|
+
if (cacheCreationInputTokens1h > cacheCreationInputTokens) {
|
|
41
|
+
throw new Error('Model usage has an invalid cacheCreationInputTokens1h counter');
|
|
42
|
+
}
|
|
36
43
|
return {
|
|
37
44
|
inputTokens: left.inputTokens + right.inputTokens,
|
|
38
45
|
outputTokens: left.outputTokens + right.outputTokens,
|
|
39
46
|
...(cacheReadInputTokens === 0 ? {} : { cacheReadInputTokens }),
|
|
40
47
|
...(cacheCreationInputTokens === 0 ? {} : { cacheCreationInputTokens }),
|
|
48
|
+
...(cacheCreationInputTokens1h === 0 ? {} : { cacheCreationInputTokens1h }),
|
|
41
49
|
...(webSearchRequests === 0 ? {} : { webSearchRequests }),
|
|
42
50
|
};
|
|
43
51
|
}
|
|
@@ -51,6 +59,10 @@ function assertValidSessionUsageEntry(model, usage) {
|
|
|
51
59
|
throw new Error(`Model usage for "${model}" has an invalid ${field} counter`);
|
|
52
60
|
}
|
|
53
61
|
}
|
|
62
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
63
|
+
(usage.cacheCreationInputTokens ?? 0)) {
|
|
64
|
+
throw new Error(`Model usage for "${model}" has an invalid cacheCreationInputTokens1h counter`);
|
|
65
|
+
}
|
|
54
66
|
for (const field of metadataFields) {
|
|
55
67
|
const value = usage[field];
|
|
56
68
|
if (value !== undefined && (!Number.isSafeInteger(value) || value < 1)) {
|
|
@@ -81,20 +93,27 @@ function addSessionUsageChecked(model, left, right) {
|
|
|
81
93
|
const outputTokens = left.outputTokens + right.outputTokens;
|
|
82
94
|
const cacheReadInputTokens = (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0);
|
|
83
95
|
const cacheCreationInputTokens = (left.cacheCreationInputTokens ?? 0) + (right.cacheCreationInputTokens ?? 0);
|
|
96
|
+
const cacheCreationInputTokens1h = (left.cacheCreationInputTokens1h ?? 0) +
|
|
97
|
+
(right.cacheCreationInputTokens1h ?? 0);
|
|
84
98
|
const webSearchRequests = (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0);
|
|
85
99
|
if (!Number.isSafeInteger(inputTokens) ||
|
|
86
100
|
!Number.isSafeInteger(outputTokens) ||
|
|
87
101
|
!Number.isSafeInteger(cacheReadInputTokens) ||
|
|
88
102
|
!Number.isSafeInteger(cacheCreationInputTokens) ||
|
|
103
|
+
!Number.isSafeInteger(cacheCreationInputTokens1h) ||
|
|
89
104
|
!Number.isSafeInteger(webSearchRequests)) {
|
|
90
105
|
throw new Error('Model usage total overflow');
|
|
91
106
|
}
|
|
107
|
+
if (cacheCreationInputTokens1h > cacheCreationInputTokens) {
|
|
108
|
+
throw new Error(`Model usage for "${model}" has an invalid cacheCreationInputTokens1h counter`);
|
|
109
|
+
}
|
|
92
110
|
const metadata = mergeSessionUsageMetadata(model, left, right);
|
|
93
111
|
return {
|
|
94
112
|
inputTokens,
|
|
95
113
|
outputTokens,
|
|
96
114
|
...(cacheReadInputTokens === 0 ? {} : { cacheReadInputTokens }),
|
|
97
115
|
...(cacheCreationInputTokens === 0 ? {} : { cacheCreationInputTokens }),
|
|
116
|
+
...(cacheCreationInputTokens1h === 0 ? {} : { cacheCreationInputTokens1h }),
|
|
98
117
|
...(webSearchRequests === 0 ? {} : { webSearchRequests }),
|
|
99
118
|
...metadata,
|
|
100
119
|
};
|
|
@@ -119,6 +138,7 @@ function hasNonZeroUsage(usage) {
|
|
|
119
138
|
usage.outputTokens > 0 ||
|
|
120
139
|
(usage.cacheReadInputTokens ?? 0) > 0 ||
|
|
121
140
|
(usage.cacheCreationInputTokens ?? 0) > 0 ||
|
|
141
|
+
(usage.cacheCreationInputTokens1h ?? 0) > 0 ||
|
|
122
142
|
(usage.webSearchRequests ?? 0) > 0);
|
|
123
143
|
}
|
|
124
144
|
function validateMetricUsage(usage) {
|
|
@@ -134,6 +154,10 @@ function validateMetricUsage(usage) {
|
|
|
134
154
|
throw new TypeError(`usage.${field} must be a nonnegative safe integer`);
|
|
135
155
|
}
|
|
136
156
|
}
|
|
157
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
158
|
+
(usage.cacheCreationInputTokens ?? 0)) {
|
|
159
|
+
throw new TypeError('usage.cacheCreationInputTokens1h must not exceed usage.cacheCreationInputTokens');
|
|
160
|
+
}
|
|
137
161
|
}
|
|
138
162
|
function requireMetric(value, field) {
|
|
139
163
|
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
|
|
@@ -85,6 +85,7 @@ const workflowUsageCounterFields = [
|
|
|
85
85
|
'outputTokens',
|
|
86
86
|
'cacheReadInputTokens',
|
|
87
87
|
'cacheCreationInputTokens',
|
|
88
|
+
'cacheCreationInputTokens1h',
|
|
88
89
|
'webSearchRequests',
|
|
89
90
|
];
|
|
90
91
|
const workflowUsageMetadataFields = [
|
|
@@ -98,6 +99,10 @@ function assertValidWorkflowUsage(usage) {
|
|
|
98
99
|
throw new Error(`Workflow agent usage has an invalid ${field} counter`);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
102
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
103
|
+
(usage.cacheCreationInputTokens ?? 0)) {
|
|
104
|
+
throw new Error('Workflow agent usage has an invalid cacheCreationInputTokens1h counter');
|
|
105
|
+
}
|
|
101
106
|
}
|
|
102
107
|
function addWorkflowApiDuration(value, total, field) {
|
|
103
108
|
if (!Number.isFinite(value) || value < 0) {
|
|
@@ -115,14 +120,20 @@ function addWorkflowUsageChecked(model, left, right) {
|
|
|
115
120
|
const outputTokens = left.outputTokens + right.outputTokens;
|
|
116
121
|
const cacheReadInputTokens = (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0);
|
|
117
122
|
const cacheCreationInputTokens = (left.cacheCreationInputTokens ?? 0) + (right.cacheCreationInputTokens ?? 0);
|
|
123
|
+
const cacheCreationInputTokens1h = (left.cacheCreationInputTokens1h ?? 0) +
|
|
124
|
+
(right.cacheCreationInputTokens1h ?? 0);
|
|
118
125
|
const webSearchRequests = (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0);
|
|
119
126
|
if (!Number.isSafeInteger(inputTokens) ||
|
|
120
127
|
!Number.isSafeInteger(outputTokens) ||
|
|
121
128
|
!Number.isSafeInteger(cacheReadInputTokens) ||
|
|
122
129
|
!Number.isSafeInteger(cacheCreationInputTokens) ||
|
|
130
|
+
!Number.isSafeInteger(cacheCreationInputTokens1h) ||
|
|
123
131
|
!Number.isSafeInteger(webSearchRequests)) {
|
|
124
132
|
throw new Error('Workflow model usage total overflow');
|
|
125
133
|
}
|
|
134
|
+
if (cacheCreationInputTokens1h > cacheCreationInputTokens) {
|
|
135
|
+
throw new Error(`Workflow model usage${model === undefined ? '' : ` for "${model}"`} has an invalid cacheCreationInputTokens1h counter`);
|
|
136
|
+
}
|
|
126
137
|
// Aggregates without a model stay counter-only; per-model rows merge their
|
|
127
138
|
// capability metadata with conflict rejection.
|
|
128
139
|
const metadata = model === undefined ? {} : mergeWorkflowUsageMetadata(model, left, right);
|
|
@@ -131,6 +142,7 @@ function addWorkflowUsageChecked(model, left, right) {
|
|
|
131
142
|
outputTokens,
|
|
132
143
|
...(cacheReadInputTokens === 0 ? {} : { cacheReadInputTokens }),
|
|
133
144
|
...(cacheCreationInputTokens === 0 ? {} : { cacheCreationInputTokens }),
|
|
145
|
+
...(cacheCreationInputTokens1h === 0 ? {} : { cacheCreationInputTokens1h }),
|
|
134
146
|
...(webSearchRequests === 0 ? {} : { webSearchRequests }),
|
|
135
147
|
...metadata,
|
|
136
148
|
};
|
package/dist/cli/protocol.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { cacheCreationInputTokenSplit } from '../core/usage.js';
|
|
2
3
|
export function projectProtocolTimings(startedAt, requestAt, outputAt) {
|
|
3
4
|
return {
|
|
4
5
|
...(requestAt === undefined
|
|
@@ -13,6 +14,7 @@ export function projectProtocolTimings(startedAt, requestAt, outputAt) {
|
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
16
|
function protocolUsage(usage) {
|
|
17
|
+
const cacheCreation = cacheCreationInputTokenSplit(usage);
|
|
16
18
|
return {
|
|
17
19
|
input_tokens: usage.inputTokens,
|
|
18
20
|
cache_creation_input_tokens: usage.cacheCreationInputTokens ?? 0,
|
|
@@ -24,8 +26,8 @@ function protocolUsage(usage) {
|
|
|
24
26
|
},
|
|
25
27
|
service_tier: 'standard',
|
|
26
28
|
cache_creation: {
|
|
27
|
-
ephemeral_1h_input_tokens:
|
|
28
|
-
ephemeral_5m_input_tokens:
|
|
29
|
+
ephemeral_1h_input_tokens: cacheCreation.oneHour,
|
|
30
|
+
ephemeral_5m_input_tokens: cacheCreation.fiveMinute,
|
|
29
31
|
},
|
|
30
32
|
inference_geo: '',
|
|
31
33
|
iterations: [],
|
package/dist/core/runtime.d.ts
CHANGED
|
@@ -74,6 +74,8 @@ export interface ModelUsage {
|
|
|
74
74
|
outputTokens: number;
|
|
75
75
|
cacheReadInputTokens?: number;
|
|
76
76
|
cacheCreationInputTokens?: number;
|
|
77
|
+
/** One-hour cache writes included in cacheCreationInputTokens. */
|
|
78
|
+
cacheCreationInputTokens1h?: number;
|
|
77
79
|
webSearchRequests?: number;
|
|
78
80
|
/** Positive safe integer when the completing model's context window is known. */
|
|
79
81
|
contextWindow?: number;
|
|
@@ -563,6 +565,11 @@ export declare class AgentRunCancelledError extends Error {
|
|
|
563
565
|
readonly name = "AgentRunCancelledError";
|
|
564
566
|
constructor();
|
|
565
567
|
}
|
|
568
|
+
export declare class AgentBudgetExceededError extends Error {
|
|
569
|
+
readonly name = "AgentBudgetExceededError";
|
|
570
|
+
readonly result: AgentRunResult;
|
|
571
|
+
constructor(message: string, result: AgentRunResult);
|
|
572
|
+
}
|
|
566
573
|
export type RuntimeEventSink = (event: RuntimeEvent) => void;
|
|
567
574
|
export type ProviderErrorKind = 'authentication_failed' | 'billing_error' | 'rate_limit' | 'invalid_request' | 'server_error' | 'timeout' | 'overloaded' | 'api_error' | 'prompt_too_long' | 'transport_error' | 'cancelled' | 'unknown' | 'max_output_tokens';
|
|
568
575
|
export declare function modelProviderErrorKind(error: ModelProviderError): ProviderErrorKind;
|
package/dist/core/runtime.js
CHANGED
|
@@ -55,6 +55,14 @@ export class AgentRunCancelledError extends Error {
|
|
|
55
55
|
super('Agent run cancelled');
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
export class AgentBudgetExceededError extends Error {
|
|
59
|
+
name = 'AgentBudgetExceededError';
|
|
60
|
+
result;
|
|
61
|
+
constructor(message, result) {
|
|
62
|
+
super(message);
|
|
63
|
+
this.result = result;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
58
66
|
const emptyUsage = () => ({ inputTokens: 0, outputTokens: 0 });
|
|
59
67
|
export function modelProviderErrorKind(error) {
|
|
60
68
|
if (error.kind !== undefined)
|
|
@@ -76,14 +84,30 @@ export function modelProviderErrorKind(error) {
|
|
|
76
84
|
const unsupportedImageResult = 'Provider does not support image tool results';
|
|
77
85
|
const unsupportedDocumentResult = 'Provider does not support document tool results';
|
|
78
86
|
function addUsage(left, right) {
|
|
87
|
+
for (const usage of [left, right]) {
|
|
88
|
+
const oneHour = usage.cacheCreationInputTokens1h;
|
|
89
|
+
if (oneHour !== undefined &&
|
|
90
|
+
(!Number.isSafeInteger(oneHour) ||
|
|
91
|
+
oneHour < 0 ||
|
|
92
|
+
oneHour > (usage.cacheCreationInputTokens ?? 0))) {
|
|
93
|
+
throw new Error('Model usage has an invalid cacheCreationInputTokens1h counter');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
79
96
|
const cacheReadInputTokens = (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0);
|
|
80
97
|
const cacheCreationInputTokens = (left.cacheCreationInputTokens ?? 0) + (right.cacheCreationInputTokens ?? 0);
|
|
98
|
+
const cacheCreationInputTokens1h = (left.cacheCreationInputTokens1h ?? 0) +
|
|
99
|
+
(right.cacheCreationInputTokens1h ?? 0);
|
|
81
100
|
const webSearchRequests = (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0);
|
|
101
|
+
if (!Number.isSafeInteger(cacheCreationInputTokens1h) ||
|
|
102
|
+
cacheCreationInputTokens1h > cacheCreationInputTokens) {
|
|
103
|
+
throw new Error('Model usage has an invalid cacheCreationInputTokens1h counter');
|
|
104
|
+
}
|
|
82
105
|
return {
|
|
83
106
|
inputTokens: left.inputTokens + right.inputTokens,
|
|
84
107
|
outputTokens: left.outputTokens + right.outputTokens,
|
|
85
108
|
...(cacheReadInputTokens === 0 ? {} : { cacheReadInputTokens }),
|
|
86
109
|
...(cacheCreationInputTokens === 0 ? {} : { cacheCreationInputTokens }),
|
|
110
|
+
...(cacheCreationInputTokens1h === 0 ? {} : { cacheCreationInputTokens1h }),
|
|
87
111
|
...(webSearchRequests === 0 ? {} : { webSearchRequests }),
|
|
88
112
|
};
|
|
89
113
|
}
|
|
@@ -126,6 +150,7 @@ const modelUsageCounterFields = [
|
|
|
126
150
|
'outputTokens',
|
|
127
151
|
'cacheReadInputTokens',
|
|
128
152
|
'cacheCreationInputTokens',
|
|
153
|
+
'cacheCreationInputTokens1h',
|
|
129
154
|
'webSearchRequests',
|
|
130
155
|
];
|
|
131
156
|
const modelUsageMetadataFields = ['contextWindow', 'maxOutputTokens'];
|
|
@@ -134,6 +159,7 @@ function hasNonZeroModelUsage(usage) {
|
|
|
134
159
|
usage.outputTokens > 0 ||
|
|
135
160
|
(usage.cacheReadInputTokens ?? 0) > 0 ||
|
|
136
161
|
(usage.cacheCreationInputTokens ?? 0) > 0 ||
|
|
162
|
+
(usage.cacheCreationInputTokens1h ?? 0) > 0 ||
|
|
137
163
|
(usage.webSearchRequests ?? 0) > 0);
|
|
138
164
|
}
|
|
139
165
|
function assertValidModelUsageEntry(model, usage) {
|
|
@@ -146,6 +172,10 @@ function assertValidModelUsageEntry(model, usage) {
|
|
|
146
172
|
throw new Error(`Model usage for "${model}" has an invalid ${field} counter`);
|
|
147
173
|
}
|
|
148
174
|
}
|
|
175
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
176
|
+
(usage.cacheCreationInputTokens ?? 0)) {
|
|
177
|
+
throw new Error(`Model usage for "${model}" has an invalid cacheCreationInputTokens1h counter`);
|
|
178
|
+
}
|
|
149
179
|
for (const field of modelUsageMetadataFields) {
|
|
150
180
|
const value = usage[field];
|
|
151
181
|
if (value !== undefined && (!Number.isSafeInteger(value) || value < 1)) {
|
|
@@ -176,20 +206,27 @@ function addUsageChecked(model, left, right) {
|
|
|
176
206
|
const outputTokens = left.outputTokens + right.outputTokens;
|
|
177
207
|
const cacheReadInputTokens = (left.cacheReadInputTokens ?? 0) + (right.cacheReadInputTokens ?? 0);
|
|
178
208
|
const cacheCreationInputTokens = (left.cacheCreationInputTokens ?? 0) + (right.cacheCreationInputTokens ?? 0);
|
|
209
|
+
const cacheCreationInputTokens1h = (left.cacheCreationInputTokens1h ?? 0) +
|
|
210
|
+
(right.cacheCreationInputTokens1h ?? 0);
|
|
179
211
|
const webSearchRequests = (left.webSearchRequests ?? 0) + (right.webSearchRequests ?? 0);
|
|
180
212
|
if (!Number.isSafeInteger(inputTokens) ||
|
|
181
213
|
!Number.isSafeInteger(outputTokens) ||
|
|
182
214
|
!Number.isSafeInteger(cacheReadInputTokens) ||
|
|
183
215
|
!Number.isSafeInteger(cacheCreationInputTokens) ||
|
|
216
|
+
!Number.isSafeInteger(cacheCreationInputTokens1h) ||
|
|
184
217
|
!Number.isSafeInteger(webSearchRequests)) {
|
|
185
218
|
throw new Error('Model usage total overflow');
|
|
186
219
|
}
|
|
220
|
+
if (cacheCreationInputTokens1h > cacheCreationInputTokens) {
|
|
221
|
+
throw new Error(`Model usage for "${model}" has an invalid cacheCreationInputTokens1h counter`);
|
|
222
|
+
}
|
|
187
223
|
const metadata = mergeModelUsageMetadata(model, left, right);
|
|
188
224
|
return {
|
|
189
225
|
inputTokens,
|
|
190
226
|
outputTokens,
|
|
191
227
|
...(cacheReadInputTokens === 0 ? {} : { cacheReadInputTokens }),
|
|
192
228
|
...(cacheCreationInputTokens === 0 ? {} : { cacheCreationInputTokens }),
|
|
229
|
+
...(cacheCreationInputTokens1h === 0 ? {} : { cacheCreationInputTokens1h }),
|
|
193
230
|
...(webSearchRequests === 0 ? {} : { webSearchRequests }),
|
|
194
231
|
...metadata,
|
|
195
232
|
};
|
|
@@ -337,6 +374,30 @@ export class AgentRuntime {
|
|
|
337
374
|
let linesRemoved = 0;
|
|
338
375
|
let activeAttemptHasPresentation = false;
|
|
339
376
|
let activeAttemptDiscarded = false;
|
|
377
|
+
const materializeResult = (text) => {
|
|
378
|
+
const modelUsage = modelUsageByModel.size === 0
|
|
379
|
+
? undefined
|
|
380
|
+
: Object.fromEntries(modelUsageByModel);
|
|
381
|
+
return {
|
|
382
|
+
text,
|
|
383
|
+
usage,
|
|
384
|
+
...(modelUsage === undefined ? {} : { modelUsage }),
|
|
385
|
+
...(sawExternallyMeteredSummary
|
|
386
|
+
? {
|
|
387
|
+
unrecordedModelUsage: Object.fromEntries(unrecordedModelUsageByModel),
|
|
388
|
+
unrecordedDurationApiMs,
|
|
389
|
+
unrecordedDurationApiWithoutRetriesMs,
|
|
390
|
+
}
|
|
391
|
+
: {}),
|
|
392
|
+
...(durationApiMs === 0 ? {} : { durationApiMs }),
|
|
393
|
+
...(durationApiMs === 0 && durationApiWithoutRetriesMs === 0
|
|
394
|
+
? {}
|
|
395
|
+
: { durationApiWithoutRetriesMs }),
|
|
396
|
+
...(durationToolMs === 0 ? {} : { durationToolMs }),
|
|
397
|
+
...(linesAdded === 0 ? {} : { linesAdded }),
|
|
398
|
+
...(linesRemoved === 0 ? {} : { linesRemoved }),
|
|
399
|
+
};
|
|
400
|
+
};
|
|
340
401
|
const maxModelTurns = request.maxModelTurns ?? this.options.maxModelTurns;
|
|
341
402
|
if (maxModelTurns !== undefined &&
|
|
342
403
|
(!Number.isSafeInteger(maxModelTurns) || maxModelTurns <= 0)) {
|
|
@@ -399,7 +460,7 @@ export class AgentRuntime {
|
|
|
399
460
|
if (this.options.maxBudgetUsd !== undefined &&
|
|
400
461
|
spent !== undefined &&
|
|
401
462
|
spent >= this.options.maxBudgetUsd) {
|
|
402
|
-
throw new
|
|
463
|
+
throw new AgentBudgetExceededError(`Maximum budget of $${this.options.maxBudgetUsd.toFixed(6)} exceeded`, materializeResult(''));
|
|
403
464
|
}
|
|
404
465
|
modelTurns += 1;
|
|
405
466
|
this.emit({ type: 'state', state: 'awaiting-model' });
|
|
@@ -698,28 +759,7 @@ export class AgentRuntime {
|
|
|
698
759
|
continue;
|
|
699
760
|
}
|
|
700
761
|
this.emit({ type: 'state', state: 'completed' });
|
|
701
|
-
|
|
702
|
-
? undefined
|
|
703
|
-
: Object.fromEntries(modelUsageByModel);
|
|
704
|
-
return {
|
|
705
|
-
text,
|
|
706
|
-
usage,
|
|
707
|
-
...(modelUsage === undefined ? {} : { modelUsage }),
|
|
708
|
-
...(sawExternallyMeteredSummary
|
|
709
|
-
? {
|
|
710
|
-
unrecordedModelUsage: Object.fromEntries(unrecordedModelUsageByModel),
|
|
711
|
-
unrecordedDurationApiMs,
|
|
712
|
-
unrecordedDurationApiWithoutRetriesMs,
|
|
713
|
-
}
|
|
714
|
-
: {}),
|
|
715
|
-
...(durationApiMs === 0 ? {} : { durationApiMs }),
|
|
716
|
-
...(durationApiMs === 0 && durationApiWithoutRetriesMs === 0
|
|
717
|
-
? {}
|
|
718
|
-
: { durationApiWithoutRetriesMs }),
|
|
719
|
-
...(durationToolMs === 0 ? {} : { durationToolMs }),
|
|
720
|
-
...(linesAdded === 0 ? {} : { linesAdded }),
|
|
721
|
-
...(linesRemoved === 0 ? {} : { linesRemoved }),
|
|
722
|
-
};
|
|
762
|
+
return materializeResult(text);
|
|
723
763
|
}
|
|
724
764
|
const scheduledToolResults = await toolScheduler.settle();
|
|
725
765
|
const followUpUserMessages = [];
|
package/dist/core/usage.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export interface ModelPricing {
|
|
|
4
4
|
outputPerMillionUsd: number;
|
|
5
5
|
cacheReadInputPerMillionUsd?: number;
|
|
6
6
|
cacheCreationInputPerMillionUsd?: number;
|
|
7
|
+
/** Falls back to cacheCreationInputPerMillionUsd when omitted. */
|
|
8
|
+
cacheCreationInputPerMillionUsd1h?: number;
|
|
9
|
+
webSearchPerRequestUsd?: number;
|
|
7
10
|
}
|
|
8
11
|
export type ModelPricingTable = Readonly<Record<string, ModelPricing>>;
|
|
9
12
|
export type ModelPricingSource = 'builtin' | 'environment' | 'unknown';
|
|
@@ -18,9 +21,15 @@ export declare class ModelPricingRegistry {
|
|
|
18
21
|
private readonly table;
|
|
19
22
|
private readonly environmentModels;
|
|
20
23
|
constructor(overrides?: ModelPricingTable);
|
|
24
|
+
private resolveKey;
|
|
21
25
|
resolve(model: string): ModelPricing | undefined;
|
|
22
26
|
diagnose(model: string): ModelPricingDiagnosis;
|
|
23
27
|
static fromEnvironment(value: string | undefined): ModelPricingRegistry;
|
|
24
28
|
}
|
|
29
|
+
export declare function cacheCreationInputTokenSplit(usage: ModelUsage): {
|
|
30
|
+
total: number;
|
|
31
|
+
fiveMinute: number;
|
|
32
|
+
oneHour: number;
|
|
33
|
+
};
|
|
25
34
|
export declare function usageCostUsd(usage: ModelUsage, pricing: ModelPricing): number;
|
|
26
35
|
//# sourceMappingURL=usage.d.ts.map
|
package/dist/core/usage.js
CHANGED
|
@@ -1,28 +1,67 @@
|
|
|
1
|
+
function anthropicPricing(inputPerMillionUsd, outputPerMillionUsd, cacheReadInputPerMillionUsd, cacheCreationInputPerMillionUsd) {
|
|
2
|
+
return {
|
|
3
|
+
inputPerMillionUsd,
|
|
4
|
+
outputPerMillionUsd,
|
|
5
|
+
cacheReadInputPerMillionUsd,
|
|
6
|
+
cacheCreationInputPerMillionUsd,
|
|
7
|
+
cacheCreationInputPerMillionUsd1h: inputPerMillionUsd * 2,
|
|
8
|
+
webSearchPerRequestUsd: 0.01,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
1
11
|
const BUILTIN_PRICING = {
|
|
2
12
|
'claude-3-5-sonnet-20241022': {
|
|
3
13
|
inputPerMillionUsd: 3,
|
|
4
14
|
outputPerMillionUsd: 15,
|
|
5
15
|
cacheReadInputPerMillionUsd: 0.3,
|
|
6
16
|
cacheCreationInputPerMillionUsd: 3.75,
|
|
17
|
+
cacheCreationInputPerMillionUsd1h: 6,
|
|
18
|
+
webSearchPerRequestUsd: 0.01,
|
|
7
19
|
},
|
|
8
20
|
'claude-3-7-sonnet-20250219': {
|
|
9
21
|
inputPerMillionUsd: 3,
|
|
10
22
|
outputPerMillionUsd: 15,
|
|
11
23
|
cacheReadInputPerMillionUsd: 0.3,
|
|
12
24
|
cacheCreationInputPerMillionUsd: 3.75,
|
|
25
|
+
cacheCreationInputPerMillionUsd1h: 6,
|
|
26
|
+
webSearchPerRequestUsd: 0.01,
|
|
13
27
|
},
|
|
14
28
|
'claude-sonnet-4-20250514': {
|
|
15
29
|
inputPerMillionUsd: 3,
|
|
16
30
|
outputPerMillionUsd: 15,
|
|
17
31
|
cacheReadInputPerMillionUsd: 0.3,
|
|
18
32
|
cacheCreationInputPerMillionUsd: 3.75,
|
|
33
|
+
cacheCreationInputPerMillionUsd1h: 6,
|
|
34
|
+
webSearchPerRequestUsd: 0.01,
|
|
19
35
|
},
|
|
20
36
|
'claude-opus-4-20250514': {
|
|
21
37
|
inputPerMillionUsd: 15,
|
|
22
38
|
outputPerMillionUsd: 75,
|
|
23
39
|
cacheReadInputPerMillionUsd: 1.5,
|
|
24
40
|
cacheCreationInputPerMillionUsd: 18.75,
|
|
41
|
+
cacheCreationInputPerMillionUsd1h: 30,
|
|
42
|
+
webSearchPerRequestUsd: 0.01,
|
|
25
43
|
},
|
|
44
|
+
'claude-fable-5-1': anthropicPricing(10, 50, 0.25, 12.5),
|
|
45
|
+
'claude-opus-5': anthropicPricing(5, 25, 0.5, 6.25),
|
|
46
|
+
'claude-opus-4-8': anthropicPricing(5, 25, 0.5, 6.25),
|
|
47
|
+
'claude-opus-4-7': anthropicPricing(5, 25, 0.5, 6.25),
|
|
48
|
+
'claude-opus-4-6': anthropicPricing(5, 25, 0.5, 6.25),
|
|
49
|
+
'claude-opus-4-5': anthropicPricing(5, 25, 0.5, 6.25),
|
|
50
|
+
'claude-opus-4-5-20251101': anthropicPricing(5, 25, 0.5, 6.25),
|
|
51
|
+
'claude-sonnet-5': anthropicPricing(2, 10, 0.2, 2.5),
|
|
52
|
+
'claude-sonnet-4-6': anthropicPricing(3, 15, 0.3, 3.75),
|
|
53
|
+
'claude-sonnet-4-5': anthropicPricing(3, 15, 0.3, 3.75),
|
|
54
|
+
'claude-sonnet-4-5-20250929': anthropicPricing(3, 15, 0.3, 3.75),
|
|
55
|
+
'claude-haiku-4-5': anthropicPricing(1, 5, 0.1, 1.25),
|
|
56
|
+
'claude-haiku-4-5-20251001': anthropicPricing(1, 5, 0.1, 1.25),
|
|
57
|
+
'claude-opus-4': anthropicPricing(15, 75, 1.5, 18.75),
|
|
58
|
+
'claude-opus-4-1': anthropicPricing(15, 75, 1.5, 18.75),
|
|
59
|
+
'claude-opus-4-1-20250805': anthropicPricing(15, 75, 1.5, 18.75),
|
|
60
|
+
'claude-sonnet-4': anthropicPricing(3, 15, 0.3, 3.75),
|
|
61
|
+
'claude-3-5-sonnet-20240620': anthropicPricing(3, 15, 0.3, 3.75),
|
|
62
|
+
'claude-3-5-sonnet-latest': anthropicPricing(3, 15, 0.3, 3.75),
|
|
63
|
+
'claude-3-5-haiku-20241022': anthropicPricing(0.8, 4, 0.08, 1),
|
|
64
|
+
'claude-3-5-haiku-latest': anthropicPricing(0.8, 4, 0.08, 1),
|
|
26
65
|
'gpt-4o': {
|
|
27
66
|
inputPerMillionUsd: 5,
|
|
28
67
|
outputPerMillionUsd: 15,
|
|
@@ -47,12 +86,20 @@ function parsePricing(value, label) {
|
|
|
47
86
|
}
|
|
48
87
|
const cacheRead = record.cacheReadInputPerMillionUsd;
|
|
49
88
|
const cacheCreation = record.cacheCreationInputPerMillionUsd;
|
|
89
|
+
const cacheCreation1h = record.cacheCreationInputPerMillionUsd1h;
|
|
90
|
+
const webSearch = record.webSearchPerRequestUsd;
|
|
50
91
|
if (cacheRead !== undefined && !validRate(cacheRead)) {
|
|
51
92
|
throw new Error(`${label}.cacheReadInputPerMillionUsd must be non-negative`);
|
|
52
93
|
}
|
|
53
94
|
if (cacheCreation !== undefined && !validRate(cacheCreation)) {
|
|
54
95
|
throw new Error(`${label}.cacheCreationInputPerMillionUsd must be non-negative`);
|
|
55
96
|
}
|
|
97
|
+
if (cacheCreation1h !== undefined && !validRate(cacheCreation1h)) {
|
|
98
|
+
throw new Error(`${label}.cacheCreationInputPerMillionUsd1h must be non-negative`);
|
|
99
|
+
}
|
|
100
|
+
if (webSearch !== undefined && !validRate(webSearch)) {
|
|
101
|
+
throw new Error(`${label}.webSearchPerRequestUsd must be non-negative`);
|
|
102
|
+
}
|
|
56
103
|
return {
|
|
57
104
|
inputPerMillionUsd: input,
|
|
58
105
|
outputPerMillionUsd: output,
|
|
@@ -62,6 +109,10 @@ function parsePricing(value, label) {
|
|
|
62
109
|
...(cacheCreation === undefined
|
|
63
110
|
? {}
|
|
64
111
|
: { cacheCreationInputPerMillionUsd: cacheCreation }),
|
|
112
|
+
...(cacheCreation1h === undefined
|
|
113
|
+
? {}
|
|
114
|
+
: { cacheCreationInputPerMillionUsd1h: cacheCreation1h }),
|
|
115
|
+
...(webSearch === undefined ? {} : { webSearchPerRequestUsd: webSearch }),
|
|
65
116
|
};
|
|
66
117
|
}
|
|
67
118
|
export class ModelPricingRegistry {
|
|
@@ -71,12 +122,36 @@ export class ModelPricingRegistry {
|
|
|
71
122
|
this.table = { ...BUILTIN_PRICING, ...overrides };
|
|
72
123
|
this.environmentModels = new Set(Object.keys(overrides));
|
|
73
124
|
}
|
|
125
|
+
resolveKey(model) {
|
|
126
|
+
if (Object.prototype.hasOwnProperty.call(this.table, model)) {
|
|
127
|
+
return model;
|
|
128
|
+
}
|
|
129
|
+
const suffix = '[1m]';
|
|
130
|
+
if (!model.endsWith(suffix))
|
|
131
|
+
return undefined;
|
|
132
|
+
const base = model.slice(0, -suffix.length);
|
|
133
|
+
if (base.length === 0 || base.endsWith(suffix))
|
|
134
|
+
return undefined;
|
|
135
|
+
return Object.prototype.hasOwnProperty.call(this.table, base)
|
|
136
|
+
? base
|
|
137
|
+
: undefined;
|
|
138
|
+
}
|
|
74
139
|
resolve(model) {
|
|
75
|
-
|
|
140
|
+
const key = this.resolveKey(model);
|
|
141
|
+
return key === undefined ? undefined : this.table[key];
|
|
76
142
|
}
|
|
77
143
|
diagnose(model) {
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
144
|
+
const key = this.resolveKey(model);
|
|
145
|
+
if (key === undefined) {
|
|
146
|
+
return {
|
|
147
|
+
model,
|
|
148
|
+
source: 'unknown',
|
|
149
|
+
policy: 'fail-closed',
|
|
150
|
+
budgetBehavior: 'reject-before-provider',
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const pricing = this.table[key];
|
|
154
|
+
if (pricing === undefined) {
|
|
80
155
|
return {
|
|
81
156
|
model,
|
|
82
157
|
source: 'unknown',
|
|
@@ -86,7 +161,7 @@ export class ModelPricingRegistry {
|
|
|
86
161
|
}
|
|
87
162
|
return {
|
|
88
163
|
model,
|
|
89
|
-
source: this.environmentModels.has(
|
|
164
|
+
source: this.environmentModels.has(key) ? 'environment' : 'builtin',
|
|
90
165
|
pricing,
|
|
91
166
|
policy: 'fail-closed',
|
|
92
167
|
budgetBehavior: 'enforce',
|
|
@@ -115,19 +190,36 @@ export class ModelPricingRegistry {
|
|
|
115
190
|
return new ModelPricingRegistry(overrides);
|
|
116
191
|
}
|
|
117
192
|
}
|
|
193
|
+
export function cacheCreationInputTokenSplit(usage) {
|
|
194
|
+
const total = usage.cacheCreationInputTokens ?? 0;
|
|
195
|
+
const oneHour = usage.cacheCreationInputTokens1h ?? 0;
|
|
196
|
+
if (!Number.isSafeInteger(total) ||
|
|
197
|
+
total < 0 ||
|
|
198
|
+
!Number.isSafeInteger(oneHour) ||
|
|
199
|
+
oneHour < 0 ||
|
|
200
|
+
oneHour > total) {
|
|
201
|
+
throw new Error('cacheCreationInputTokens1h must be a nonnegative safe integer no greater than cacheCreationInputTokens');
|
|
202
|
+
}
|
|
203
|
+
return { total, fiveMinute: total - oneHour, oneHour };
|
|
204
|
+
}
|
|
118
205
|
function regularInputTokens(usage) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
(usage.cacheCreationInputTokens ?? 0));
|
|
206
|
+
const { total } = cacheCreationInputTokenSplit(usage);
|
|
207
|
+
return Math.max(0, usage.inputTokens - (usage.cacheReadInputTokens ?? 0) - total);
|
|
122
208
|
}
|
|
123
209
|
export function usageCostUsd(usage, pricing) {
|
|
210
|
+
const cacheCreation = cacheCreationInputTokenSplit(usage);
|
|
124
211
|
const regularInput = regularInputTokens(usage);
|
|
125
212
|
const input = regularInput * pricing.inputPerMillionUsd;
|
|
126
213
|
const output = usage.outputTokens * pricing.outputPerMillionUsd;
|
|
127
214
|
const cacheRead = (usage.cacheReadInputTokens ?? 0) *
|
|
128
215
|
(pricing.cacheReadInputPerMillionUsd ?? pricing.inputPerMillionUsd);
|
|
129
|
-
const
|
|
130
|
-
(pricing.cacheCreationInputPerMillionUsd ?? pricing.inputPerMillionUsd)
|
|
131
|
-
|
|
216
|
+
const cacheCreationCost = cacheCreation.fiveMinute *
|
|
217
|
+
(pricing.cacheCreationInputPerMillionUsd ?? pricing.inputPerMillionUsd) +
|
|
218
|
+
cacheCreation.oneHour *
|
|
219
|
+
(pricing.cacheCreationInputPerMillionUsd1h ??
|
|
220
|
+
pricing.cacheCreationInputPerMillionUsd ??
|
|
221
|
+
pricing.inputPerMillionUsd);
|
|
222
|
+
return ((input + output + cacheRead + cacheCreationCost) / 1_000_000 +
|
|
223
|
+
(usage.webSearchRequests ?? 0) * (pricing.webSearchPerRequestUsd ?? 0));
|
|
132
224
|
}
|
|
133
225
|
//# sourceMappingURL=usage.js.map
|
|
@@ -8,6 +8,7 @@ export interface PersistedSubagentRunResult {
|
|
|
8
8
|
outputTokens: number;
|
|
9
9
|
cacheReadInputTokens?: number;
|
|
10
10
|
cacheCreationInputTokens?: number;
|
|
11
|
+
cacheCreationInputTokens1h?: number;
|
|
11
12
|
webSearchRequests?: number;
|
|
12
13
|
contextWindow?: number;
|
|
13
14
|
maxOutputTokens?: number;
|
|
@@ -38,10 +38,14 @@ function isUsage(value) {
|
|
|
38
38
|
for (const field of [
|
|
39
39
|
'cacheReadInputTokens',
|
|
40
40
|
'cacheCreationInputTokens',
|
|
41
|
+
'cacheCreationInputTokens1h',
|
|
41
42
|
'webSearchRequests',
|
|
42
43
|
])
|
|
43
44
|
if (usage[field] !== undefined && !isNonnegativeInteger(usage[field]))
|
|
44
45
|
return false;
|
|
46
|
+
if ((usage.cacheCreationInputTokens1h ?? 0) >
|
|
47
|
+
(usage.cacheCreationInputTokens ?? 0))
|
|
48
|
+
return false;
|
|
45
49
|
for (const field of ['contextWindow', 'maxOutputTokens'])
|
|
46
50
|
if (usage[field] !== undefined &&
|
|
47
51
|
(!Number.isSafeInteger(usage[field]) || Number(usage[field]) < 1))
|
|
@@ -3,7 +3,7 @@ import { transportFailureKind } from './provider-errors.js';
|
|
|
3
3
|
import { reportProviderTransportActivity } from './provider-transport-activity.js';
|
|
4
4
|
import { markNonStreamingFallbackEligible } from './non-streaming-fallback-provider.js';
|
|
5
5
|
import { createAnthropicPromptCachePolicyResolver, } from './anthropic-prompt-cache.js';
|
|
6
|
-
import { resolveAnthropicModelSpec } from './anthropic-model-spec.js';
|
|
6
|
+
import { resolveAnthropicEffort, resolveAnthropicModelSpec, } from './anthropic-model-spec.js';
|
|
7
7
|
function isRecord(value) {
|
|
8
8
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
9
9
|
}
|
|
@@ -16,6 +16,28 @@ function readNonNegativeTokenCount(usage, field, required) {
|
|
|
16
16
|
}
|
|
17
17
|
return value;
|
|
18
18
|
}
|
|
19
|
+
function readCacheCreationInputTokens1h(usage) {
|
|
20
|
+
const detail = usage.cache_creation;
|
|
21
|
+
if (detail === undefined)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (!isRecord(detail)) {
|
|
24
|
+
throw new ModelProviderError('Provider returned an invalid cache_creation usage object', { retryable: false });
|
|
25
|
+
}
|
|
26
|
+
const total = readNonNegativeTokenCount(usage, 'cache_creation_input_tokens', true);
|
|
27
|
+
if (total === undefined) {
|
|
28
|
+
throw new ModelProviderError('Provider returned cache_creation usage without cache_creation_input_tokens', { retryable: false });
|
|
29
|
+
}
|
|
30
|
+
const fiveMinute = readNonNegativeTokenCount(detail, 'ephemeral_5m_input_tokens', true);
|
|
31
|
+
const oneHour = readNonNegativeTokenCount(detail, 'ephemeral_1h_input_tokens', true);
|
|
32
|
+
if (fiveMinute === undefined || oneHour === undefined) {
|
|
33
|
+
throw new ModelProviderError('Provider returned an incomplete cache_creation usage object', { retryable: false });
|
|
34
|
+
}
|
|
35
|
+
const sum = fiveMinute + oneHour;
|
|
36
|
+
if (!Number.isSafeInteger(sum) || sum !== total) {
|
|
37
|
+
throw new ModelProviderError('Provider returned cache_creation usage whose TTL counters do not sum to cache_creation_input_tokens', { retryable: false });
|
|
38
|
+
}
|
|
39
|
+
return oneHour;
|
|
40
|
+
}
|
|
19
41
|
function webSearchLinks(value) {
|
|
20
42
|
if (!Array.isArray(value))
|
|
21
43
|
return [];
|
|
@@ -207,6 +229,10 @@ function parseSseEvent(data, state, maxToolArgumentsBytes, maxToolCallsPerRespon
|
|
|
207
229
|
typeof usage.cache_creation_input_tokens === 'number'
|
|
208
230
|
? usage.cache_creation_input_tokens
|
|
209
231
|
: 0;
|
|
232
|
+
const cacheCreationInputTokens1h = readCacheCreationInputTokens1h(usage);
|
|
233
|
+
if (cacheCreationInputTokens1h !== undefined) {
|
|
234
|
+
state.cacheCreationInputTokens1h = cacheCreationInputTokens1h;
|
|
235
|
+
}
|
|
210
236
|
state.cacheReadInputTokens =
|
|
211
237
|
typeof usage.cache_read_input_tokens === 'number'
|
|
212
238
|
? usage.cache_read_input_tokens
|
|
@@ -466,6 +492,10 @@ function parseSseEvent(data, state, maxToolArgumentsBytes, maxToolCallsPerRespon
|
|
|
466
492
|
...(state.cacheCreationInputTokens === 0
|
|
467
493
|
? {}
|
|
468
494
|
: { cacheCreationInputTokens: state.cacheCreationInputTokens }),
|
|
495
|
+
...(state.cacheCreationInputTokens1h === undefined ||
|
|
496
|
+
state.cacheCreationInputTokens1h === 0
|
|
497
|
+
? {}
|
|
498
|
+
: { cacheCreationInputTokens1h: state.cacheCreationInputTokens1h }),
|
|
469
499
|
...(state.webSearchRequests === 0
|
|
470
500
|
? {}
|
|
471
501
|
: { webSearchRequests: state.webSearchRequests }),
|
|
@@ -666,12 +696,7 @@ export class AnthropicCompatibleProvider {
|
|
|
666
696
|
this.providerBetas = Object.freeze([...modelSpec.betas]);
|
|
667
697
|
this.streaming = options.streaming ?? true;
|
|
668
698
|
this.fetchImplementation = options.fetchImplementation ?? fetch;
|
|
669
|
-
this.maxOutputTokens = positiveInteger(options.maxOutputTokens ??
|
|
670
|
-
(this.wireModel.includes('claude-opus-4-6')
|
|
671
|
-
? 64_000
|
|
672
|
-
: this.wireModel.startsWith('claude-')
|
|
673
|
-
? 32_000
|
|
674
|
-
: 8192), 'Max output tokens');
|
|
699
|
+
this.maxOutputTokens = positiveInteger(options.maxOutputTokens ?? modelSpec.defaultMaxOutputTokens, 'Max output tokens');
|
|
675
700
|
this.capabilities = {
|
|
676
701
|
streaming: this.streaming,
|
|
677
702
|
usage: true,
|
|
@@ -739,6 +764,7 @@ export class AnthropicCompatibleProvider {
|
|
|
739
764
|
].filter((beta, index, all) => all.indexOf(beta) === index);
|
|
740
765
|
const serialized = serializeMessages(request.messages, request.stableSystemMessageCount, this.promptCaching);
|
|
741
766
|
const requestTools = request.tools;
|
|
767
|
+
const effort = resolveAnthropicEffort(this.wireModel, request.effort);
|
|
742
768
|
const requestInit = {
|
|
743
769
|
method: 'POST',
|
|
744
770
|
headers: {
|
|
@@ -754,9 +780,7 @@ export class AnthropicCompatibleProvider {
|
|
|
754
780
|
messages: serialized.messages,
|
|
755
781
|
stream: this.streaming,
|
|
756
782
|
...(thinkingPayload ? { thinking: thinkingPayload } : {}),
|
|
757
|
-
...(
|
|
758
|
-
? { output_config: { effort: request.effort } }
|
|
759
|
-
: {}),
|
|
783
|
+
...(effort ? { output_config: { effort } } : {}),
|
|
760
784
|
...(serialized.system.length ? { system: serialized.system } : {}),
|
|
761
785
|
...(request.webSearch
|
|
762
786
|
? {
|
|
@@ -926,6 +950,8 @@ export class AnthropicCompatibleProvider {
|
|
|
926
950
|
const outputTokens = readNonNegativeTokenCount(payload.usage, 'output_tokens', true);
|
|
927
951
|
const cacheReadInputTokens = readNonNegativeTokenCount(payload.usage, 'cache_read_input_tokens', false);
|
|
928
952
|
const cacheCreationInputTokens = readNonNegativeTokenCount(payload.usage, 'cache_creation_input_tokens', false);
|
|
953
|
+
const cacheCreationInputTokens1h = readCacheCreationInputTokens1h(payload.usage);
|
|
954
|
+
const normalizedCacheCreationInputTokens = cacheCreationInputTokens ?? 0;
|
|
929
955
|
const usage = {
|
|
930
956
|
input_tokens: inputTokens,
|
|
931
957
|
output_tokens: outputTokens,
|
|
@@ -935,6 +961,15 @@ export class AnthropicCompatibleProvider {
|
|
|
935
961
|
...(cacheCreationInputTokens === undefined
|
|
936
962
|
? {}
|
|
937
963
|
: { cache_creation_input_tokens: cacheCreationInputTokens }),
|
|
964
|
+
...(cacheCreationInputTokens1h === undefined
|
|
965
|
+
? {}
|
|
966
|
+
: {
|
|
967
|
+
cache_creation: {
|
|
968
|
+
ephemeral_5m_input_tokens: normalizedCacheCreationInputTokens -
|
|
969
|
+
cacheCreationInputTokens1h,
|
|
970
|
+
ephemeral_1h_input_tokens: cacheCreationInputTokens1h,
|
|
971
|
+
},
|
|
972
|
+
}),
|
|
938
973
|
...(payload.usage.server_tool_use === undefined
|
|
939
974
|
? {}
|
|
940
975
|
: { server_tool_use: payload.usage.server_tool_use }),
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export declare const ANTHROPIC_LONG_CONTEXT_BETA = "context-1m-2025-08-07";
|
|
2
|
+
export declare function resolveAnthropicEffort(wireModel: string, effort: string | undefined): string | undefined;
|
|
2
3
|
export interface ResolvedAnthropicModelSpec {
|
|
3
4
|
readonly model: string;
|
|
4
5
|
readonly wireModel: string;
|
|
5
6
|
readonly contextWindowTokens: number;
|
|
7
|
+
readonly defaultMaxOutputTokens: number;
|
|
6
8
|
readonly betas: readonly string[];
|
|
7
9
|
readonly supportsAdaptiveThinking: boolean;
|
|
8
10
|
}
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
export const ANTHROPIC_LONG_CONTEXT_BETA = 'context-1m-2025-08-07';
|
|
2
|
+
function defaultMaxOutputTokens(wireModel) {
|
|
3
|
+
if (/(?:^|[^a-z0-9])claude-(?:opus-4-[678]|opus-5|sonnet-5)(?=$|[-@.:/_])/.test(wireModel)) {
|
|
4
|
+
return 64_000;
|
|
5
|
+
}
|
|
6
|
+
return wireModel.startsWith('claude-') ? 32_000 : 8192;
|
|
7
|
+
}
|
|
8
|
+
export function resolveAnthropicEffort(wireModel, effort) {
|
|
9
|
+
if (effort === undefined)
|
|
10
|
+
return undefined;
|
|
11
|
+
if (wireModel === 'claude-sonnet-4-6' || wireModel === 'claude-opus-4-6') {
|
|
12
|
+
return effort === 'xhigh' ? 'high' : effort;
|
|
13
|
+
}
|
|
14
|
+
if (/^claude-opus-4-5(?:-|$)/.test(wireModel)) {
|
|
15
|
+
return effort === 'xhigh' || effort === 'max' ? 'high' : effort;
|
|
16
|
+
}
|
|
17
|
+
return effort;
|
|
18
|
+
}
|
|
2
19
|
export function resolveAnthropicModelSpec(model, explicitContextWindowTokens) {
|
|
3
20
|
const longContext = model.endsWith('[1m]');
|
|
4
21
|
const wireModel = longContext ? model.slice(0, -'[1m]'.length) : model;
|
|
@@ -8,6 +25,7 @@ export function resolveAnthropicModelSpec(model, explicitContextWindowTokens) {
|
|
|
8
25
|
return Object.freeze({
|
|
9
26
|
model,
|
|
10
27
|
wireModel,
|
|
28
|
+
defaultMaxOutputTokens: defaultMaxOutputTokens(wireModel),
|
|
11
29
|
contextWindowTokens: explicitContextWindowTokens ?? (longContext ? 1_000_000 : 200_000),
|
|
12
30
|
betas: Object.freeze(longContext ? [ANTHROPIC_LONG_CONTEXT_BETA] : []),
|
|
13
31
|
supportsAdaptiveThinking: wireModel === 'claude-sonnet-4-6' || wireModel === 'claude-opus-4-6',
|