@animalabs/membrane 0.5.80 → 0.5.82
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/dist/cache-wire-receipt.d.ts +13 -0
- package/dist/cache-wire-receipt.d.ts.map +1 -0
- package/dist/cache-wire-receipt.js +108 -0
- package/dist/cache-wire-receipt.js.map +1 -0
- package/dist/context/index.d.ts +1 -1
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +1 -1
- package/dist/context/index.js.map +1 -1
- package/dist/context/process.d.ts +3 -1
- package/dist/context/process.d.ts.map +1 -1
- package/dist/context/process.js +230 -49
- package/dist/context/process.js.map +1 -1
- package/dist/context/types.d.ts +30 -0
- package/dist/context/types.d.ts.map +1 -1
- package/dist/context/types.js +16 -0
- package/dist/context/types.js.map +1 -1
- package/dist/floating-cache-marker.test.js +21 -0
- package/dist/floating-cache-marker.test.js.map +1 -1
- package/dist/formatters/anthropic-xml.d.ts +2 -0
- package/dist/formatters/anthropic-xml.d.ts.map +1 -1
- package/dist/formatters/anthropic-xml.js +64 -23
- package/dist/formatters/anthropic-xml.js.map +1 -1
- package/dist/formatters/native.d.ts.map +1 -1
- package/dist/formatters/native.js +16 -3
- package/dist/formatters/native.js.map +1 -1
- package/dist/formatters/normalize-tool-pairs.d.ts +7 -0
- package/dist/formatters/normalize-tool-pairs.d.ts.map +1 -1
- package/dist/formatters/normalize-tool-pairs.js +45 -0
- package/dist/formatters/normalize-tool-pairs.js.map +1 -1
- package/dist/formatters/types.d.ts +31 -0
- package/dist/formatters/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/membrane.d.ts +137 -8
- package/dist/membrane.d.ts.map +1 -1
- package/dist/membrane.js +823 -310
- package/dist/membrane.js.map +1 -1
- package/dist/providers/anthropic.d.ts +37 -0
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +142 -25
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/bedrock.d.ts +8 -0
- package/dist/providers/bedrock.d.ts.map +1 -1
- package/dist/providers/bedrock.js +24 -1
- package/dist/providers/bedrock.js.map +1 -1
- package/dist/providers/gemini.d.ts +11 -0
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +104 -82
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/mock.d.ts +2 -0
- package/dist/providers/mock.d.ts.map +1 -1
- package/dist/providers/mock.js +2 -0
- package/dist/providers/mock.js.map +1 -1
- package/dist/providers/openai-compatible.d.ts +7 -0
- package/dist/providers/openai-compatible.d.ts.map +1 -1
- package/dist/providers/openai-compatible.js +99 -48
- package/dist/providers/openai-compatible.js.map +1 -1
- package/dist/providers/openai-completions.d.ts +5 -0
- package/dist/providers/openai-completions.d.ts.map +1 -1
- package/dist/providers/openai-completions.js +107 -44
- package/dist/providers/openai-completions.js.map +1 -1
- package/dist/providers/openai-responses-api.d.ts +16 -0
- package/dist/providers/openai-responses-api.d.ts.map +1 -1
- package/dist/providers/openai-responses-api.js +38 -10
- package/dist/providers/openai-responses-api.js.map +1 -1
- package/dist/providers/openai-responses.d.ts +2 -0
- package/dist/providers/openai-responses.d.ts.map +1 -1
- package/dist/providers/openai-responses.js +8 -1
- package/dist/providers/openai-responses.js.map +1 -1
- package/dist/providers/openai.d.ts +7 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +92 -44
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +9 -0
- package/dist/providers/openrouter.d.ts.map +1 -1
- package/dist/providers/openrouter.js +118 -62
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/utils.d.ts +74 -2
- package/dist/providers/utils.d.ts.map +1 -1
- package/dist/providers/utils.js +184 -3
- package/dist/providers/utils.js.map +1 -1
- package/dist/registry/default-pricing.d.ts +22 -0
- package/dist/registry/default-pricing.d.ts.map +1 -1
- package/dist/registry/default-pricing.js +162 -28
- package/dist/registry/default-pricing.js.map +1 -1
- package/dist/types/content.d.ts +13 -0
- package/dist/types/content.d.ts.map +1 -1
- package/dist/types/content.js.map +1 -1
- package/dist/types/errors.d.ts +15 -0
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +26 -0
- package/dist/types/errors.js.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/provider.d.ts +50 -0
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/request.d.ts +6 -0
- package/dist/types/request.d.ts.map +1 -1
- package/dist/types/response.d.ts +85 -4
- package/dist/types/response.d.ts.map +1 -1
- package/dist/types/response.js.map +1 -1
- package/dist/types/streaming.d.ts +6 -1
- package/dist/types/streaming.d.ts.map +1 -1
- package/dist/utils/cache-marker-budget.d.ts +91 -0
- package/dist/utils/cache-marker-budget.d.ts.map +1 -0
- package/dist/utils/cache-marker-budget.js +208 -0
- package/dist/utils/cache-marker-budget.js.map +1 -0
- package/dist/utils/cost.d.ts +22 -0
- package/dist/utils/cost.d.ts.map +1 -1
- package/dist/utils/cost.js +55 -0
- package/dist/utils/cost.js.map +1 -1
- package/dist/utils/thinking-carriers.d.ts +80 -0
- package/dist/utils/thinking-carriers.d.ts.map +1 -0
- package/dist/utils/thinking-carriers.js +115 -0
- package/dist/utils/thinking-carriers.js.map +1 -0
- package/dist/utils/tool-parser.d.ts +24 -0
- package/dist/utils/tool-parser.d.ts.map +1 -1
- package/dist/utils/tool-parser.js +367 -161
- package/dist/utils/tool-parser.js.map +1 -1
- package/dist/utils/usage.d.ts +71 -0
- package/dist/utils/usage.d.ts.map +1 -0
- package/dist/utils/usage.js +161 -0
- package/dist/utils/usage.js.map +1 -0
- package/dist/yielding-stream.d.ts +8 -0
- package/dist/yielding-stream.d.ts.map +1 -1
- package/dist/yielding-stream.js +49 -3
- package/dist/yielding-stream.js.map +1 -1
- package/package.json +1 -1
- package/src/cache-wire-receipt.ts +125 -0
- package/src/context/index.ts +1 -0
- package/src/context/process.ts +305 -59
- package/src/context/types.ts +38 -0
- package/src/floating-cache-marker.test.ts +24 -0
- package/src/formatters/anthropic-xml.ts +66 -23
- package/src/formatters/native.ts +23 -2
- package/src/formatters/normalize-tool-pairs.ts +49 -0
- package/src/formatters/types.ts +35 -0
- package/src/index.ts +6 -0
- package/src/membrane.ts +974 -313
- package/src/providers/anthropic.ts +173 -19
- package/src/providers/bedrock.ts +25 -1
- package/src/providers/gemini.ts +125 -87
- package/src/providers/index.ts +1 -0
- package/src/providers/mock.ts +3 -0
- package/src/providers/openai-compatible.ts +102 -45
- package/src/providers/openai-completions.ts +112 -46
- package/src/providers/openai-responses-api.ts +45 -15
- package/src/providers/openai-responses.ts +8 -1
- package/src/providers/openai.ts +95 -42
- package/src/providers/openrouter.ts +125 -63
- package/src/providers/utils.ts +227 -6
- package/src/registry/default-pricing.ts +165 -28
- package/src/types/content.ts +14 -0
- package/src/types/errors.ts +28 -0
- package/src/types/index.ts +6 -0
- package/src/types/provider.ts +55 -0
- package/src/types/request.ts +7 -0
- package/src/types/response.ts +109 -8
- package/src/types/streaming.ts +8 -2
- package/src/utils/cache-marker-budget.ts +237 -0
- package/src/utils/cost.ts +64 -0
- package/src/utils/thinking-carriers.ts +125 -0
- package/src/utils/tool-parser.ts +473 -174
- package/src/utils/usage.ts +184 -0
- package/src/yielding-stream.ts +54 -3
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One recount of the cache_control markers actually present on a wire
|
|
3
|
+
* request, plus the clamp that keeps that count legal.
|
|
4
|
+
*
|
|
5
|
+
* Anthropic accepts at most 4 cache_control breakpoints per request and
|
|
6
|
+
* rejects the fifth with a non-retryable 400 ("A maximum of 4 blocks with
|
|
7
|
+
* cache_control may be provided. Found 5." — measured live 2026-08-25).
|
|
8
|
+
* Markers arrive from many sites (context strategy breakpoints, block-level
|
|
9
|
+
* passthrough on imported histories, the tools/system fallback, the floating
|
|
10
|
+
* tool-loop marker, caller-marked system blocks, and any beforeRequest hook),
|
|
11
|
+
* and every one of them is invisible to the others' running tallies. The
|
|
12
|
+
* only trustworthy number is a recount of the constructed artifacts, so this
|
|
13
|
+
* module owns it and every site calls it.
|
|
14
|
+
*
|
|
15
|
+
* A marker can also ride a block NESTED inside another block's content array
|
|
16
|
+
* (`tool_result.content` is `string | ContentBlock[]`, passed through to the
|
|
17
|
+
* wire verbatim), so discovery recurses. A belt that cannot see a marker
|
|
18
|
+
* cannot clamp it, and a top-level-only count would report four while five
|
|
19
|
+
* shipped — the request rejected outright with the belt's blessing.
|
|
20
|
+
*/
|
|
21
|
+
/** Anthropic's hard limit on cache_control breakpoints per request. */
|
|
22
|
+
export const MAX_CACHE_BREAKPOINTS = 4;
|
|
23
|
+
/**
|
|
24
|
+
* How many levels of nested `content` arrays marker discovery descends below
|
|
25
|
+
* a top-level block.
|
|
26
|
+
*
|
|
27
|
+
* A marker can ride a block inside another block's own content array —
|
|
28
|
+
* `ToolResultContent.content` is typed `string | ContentBlock[]` and every
|
|
29
|
+
* builder passes it through verbatim, so a caller-built tool_result whose
|
|
30
|
+
* members carry `cache_control` puts real markers on the wire. The API's own
|
|
31
|
+
* nesting is one level deep; 4 is headroom for shapes it grows later, and it
|
|
32
|
+
* is also what makes this walk TOTAL — a caller-built structure that points
|
|
33
|
+
* back at itself terminates at the cap instead of hanging the request.
|
|
34
|
+
* Markers below the cap are outside the belt's reach, by construction.
|
|
35
|
+
*/
|
|
36
|
+
export const MAX_NESTED_CONTENT_DEPTH = 4;
|
|
37
|
+
/**
|
|
38
|
+
* Walk one candidate block and everything nested under it, in document order
|
|
39
|
+
* (a block before its own content), applying `visitBlock` to each object.
|
|
40
|
+
*
|
|
41
|
+
* This is the single traversal law: marker discovery and the ownership copy
|
|
42
|
+
* that protects caller-owned blocks from it both descend exactly here, so
|
|
43
|
+
* the clamp can never reach a grain that ownership did not copy.
|
|
44
|
+
*/
|
|
45
|
+
function walkBlockTree(candidate, depth, visitBlock) {
|
|
46
|
+
if (!candidate || typeof candidate !== 'object')
|
|
47
|
+
return;
|
|
48
|
+
const block = candidate;
|
|
49
|
+
visitBlock(block);
|
|
50
|
+
const nested = nestedContentBlocks(block, depth);
|
|
51
|
+
if (!nested)
|
|
52
|
+
return;
|
|
53
|
+
for (const child of nested)
|
|
54
|
+
walkBlockTree(child, depth + 1, visitBlock);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The one rule for what counts as nested content: an array-valued `content`
|
|
58
|
+
* on a block, while still above the depth cap. Discovery and the ownership
|
|
59
|
+
* copy both ask here, so neither can descend where the other does not.
|
|
60
|
+
*/
|
|
61
|
+
function nestedContentBlocks(block, depth) {
|
|
62
|
+
if (depth >= MAX_NESTED_CONTENT_DEPTH)
|
|
63
|
+
return undefined;
|
|
64
|
+
return Array.isArray(block.content) ? block.content : undefined;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Every marker-bearing block on the request, in WIRE ORDER (tools, then
|
|
68
|
+
* system blocks, then message blocks) and, within each, in DOCUMENT order —
|
|
69
|
+
* a block before anything nested inside its own content. Order is what makes
|
|
70
|
+
* "deepest" mean anything: a deeper marker caches a longer prefix.
|
|
71
|
+
*
|
|
72
|
+
* ONE walk serves both the count and the clamp's strip, so a marker the
|
|
73
|
+
* counter can see is always a marker the clamp can strip. A collector that
|
|
74
|
+
* stopped at the top level would count four while five rode to the wire, and
|
|
75
|
+
* the provider would reject the request the belt just declared legal.
|
|
76
|
+
*/
|
|
77
|
+
function collectMarkedBlocks(surfaces) {
|
|
78
|
+
const marked = [];
|
|
79
|
+
const collectIfMarked = (candidate) => walkBlockTree(candidate, 0, (block) => {
|
|
80
|
+
if (block.cache_control)
|
|
81
|
+
marked.push(block);
|
|
82
|
+
});
|
|
83
|
+
if (Array.isArray(surfaces.tools)) {
|
|
84
|
+
for (const tool of surfaces.tools)
|
|
85
|
+
collectIfMarked(tool);
|
|
86
|
+
}
|
|
87
|
+
if (Array.isArray(surfaces.system)) {
|
|
88
|
+
for (const block of surfaces.system)
|
|
89
|
+
collectIfMarked(block);
|
|
90
|
+
}
|
|
91
|
+
if (Array.isArray(surfaces.messages)) {
|
|
92
|
+
for (const message of surfaces.messages) {
|
|
93
|
+
const content = message?.content;
|
|
94
|
+
if (Array.isArray(content)) {
|
|
95
|
+
for (const block of content)
|
|
96
|
+
collectIfMarked(block);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
collectIfMarked(content);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return marked;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Take ownership of a system surface before it can reach the clamp.
|
|
107
|
+
*
|
|
108
|
+
* `request.system` accepts caller-marked blocks, and the builders pass that
|
|
109
|
+
* array through by reference when they add no marker of their own. The clamp
|
|
110
|
+
* strips markers IN PLACE at the wire boundary — correct for blocks membrane
|
|
111
|
+
* built, catastrophic for the caller's own array, which a long-lived caller
|
|
112
|
+
* reuses turn after turn: one over-budget request would silently delete the
|
|
113
|
+
* caller's breakpoints for the life of that object. Copying the array and its
|
|
114
|
+
* blocks at build time keeps the clamp's mutations inside the request.
|
|
115
|
+
*
|
|
116
|
+
* The copy descends exactly as far as marker discovery does: a shallow
|
|
117
|
+
* `{...block}` leaves any nested `content` array shared with the caller, and
|
|
118
|
+
* the clamp now strips markers at that grain, so ownership has to reach it
|
|
119
|
+
* too or the leak just moves one level down.
|
|
120
|
+
*/
|
|
121
|
+
export function ownSystemBlocks(system) {
|
|
122
|
+
if (!Array.isArray(system))
|
|
123
|
+
return system;
|
|
124
|
+
return system.map((block) => copyBlockTree(block, 0));
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Shallow-copy a block and, recursively, its nested content blocks, to the
|
|
128
|
+
* same depth marker discovery walks. Non-objects pass through untouched.
|
|
129
|
+
*/
|
|
130
|
+
function copyBlockTree(candidate, depth) {
|
|
131
|
+
if (!candidate || typeof candidate !== 'object')
|
|
132
|
+
return candidate;
|
|
133
|
+
const copy = { ...candidate };
|
|
134
|
+
const nested = nestedContentBlocks(copy, depth);
|
|
135
|
+
if (nested)
|
|
136
|
+
copy.content = nested.map((child) => copyBlockTree(child, depth + 1));
|
|
137
|
+
return copy;
|
|
138
|
+
}
|
|
139
|
+
/** How many cache_control markers this request would actually put on the wire. */
|
|
140
|
+
export function countWireCacheMarkers(surfaces) {
|
|
141
|
+
return collectMarkedBlocks(surfaces).length;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Validate a caller-owned marker layout without changing it.
|
|
145
|
+
*
|
|
146
|
+
* In `cm-owned` mode the caller has deliberately allocated the complete
|
|
147
|
+
* breakpoint set. Silently stripping or reordering those markers would make
|
|
148
|
+
* the cache receipt describe a request that was never sent, so invalid
|
|
149
|
+
* layouts fail before submission instead of using the legacy repair clamp.
|
|
150
|
+
*/
|
|
151
|
+
export function assertCacheMarkersWithinLimit(surfaces, site) {
|
|
152
|
+
const marked = collectMarkedBlocks(surfaces);
|
|
153
|
+
const invalidThinking = marked.filter((block) => block.type === 'thinking' || block.type === 'redacted_thinking').length;
|
|
154
|
+
if (invalidThinking > 0) {
|
|
155
|
+
throw new Error(`${site}: caller-owned cache_control cannot be attached to thinking/redacted_thinking blocks`);
|
|
156
|
+
}
|
|
157
|
+
if (marked.length > MAX_CACHE_BREAKPOINTS) {
|
|
158
|
+
throw new Error(`${site}: cache_control limit exceeded: ${marked.length} markers (maximum ${MAX_CACHE_BREAKPOINTS})`);
|
|
159
|
+
}
|
|
160
|
+
return marked.length;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Bring a request inside the breakpoint budget, in place, at the last exit
|
|
164
|
+
* before the adapter call. Two repairs, both loud:
|
|
165
|
+
*
|
|
166
|
+
* 1. a marker riding a thinking / redacted_thinking block is stripped — the
|
|
167
|
+
* API rejects those outright ("thinking.cache_control: Extra inputs are
|
|
168
|
+
* not permitted"), and the three builders' `lastCacheableBlockIndex`
|
|
169
|
+
* discipline is only as good as its last caller. This is the runtime
|
|
170
|
+
* assertion; a fourth builder can no longer repeat that history.
|
|
171
|
+
* 2. markers past the limit are dropped SHALLOWEST-FIRST, keeping the 4
|
|
172
|
+
* deepest — the deepest marker caches the longest prefix, and every
|
|
173
|
+
* shallower prefix it subsumes.
|
|
174
|
+
*
|
|
175
|
+
* Dropping loudly beats a 400: the request still ships, cached less than the
|
|
176
|
+
* caller asked for, with the overspend named.
|
|
177
|
+
*/
|
|
178
|
+
export function clampCacheMarkers(surfaces, site) {
|
|
179
|
+
const marked = collectMarkedBlocks(surfaces);
|
|
180
|
+
let strippedFromThinking = 0;
|
|
181
|
+
const cacheable = [];
|
|
182
|
+
for (const block of marked) {
|
|
183
|
+
if (block.type === 'thinking' || block.type === 'redacted_thinking') {
|
|
184
|
+
delete block.cache_control;
|
|
185
|
+
strippedFromThinking++;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
cacheable.push(block);
|
|
189
|
+
}
|
|
190
|
+
let dropped = 0;
|
|
191
|
+
if (cacheable.length > MAX_CACHE_BREAKPOINTS) {
|
|
192
|
+
for (const block of cacheable.slice(0, cacheable.length - MAX_CACHE_BREAKPOINTS)) {
|
|
193
|
+
delete block.cache_control;
|
|
194
|
+
dropped++;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (strippedFromThinking > 0) {
|
|
198
|
+
console.warn(`[membrane] ${site}: stripped ${strippedFromThinking} cache_control marker(s) from ` +
|
|
199
|
+
`thinking blocks — the API rejects cache_control on thinking/redacted_thinking.`);
|
|
200
|
+
}
|
|
201
|
+
if (dropped > 0) {
|
|
202
|
+
console.warn(`[membrane] ${site}: ${cacheable.length} cache_control markers exceed the limit of ` +
|
|
203
|
+
`${MAX_CACHE_BREAKPOINTS} — dropped the ${dropped} shallowest and kept the deepest ` +
|
|
204
|
+
`${MAX_CACHE_BREAKPOINTS}. The request would otherwise have been rejected outright.`);
|
|
205
|
+
}
|
|
206
|
+
return { total: cacheable.length - dropped, dropped, strippedFromThinking };
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=cache-marker-budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-marker-budget.js","sourceRoot":"","sources":["../../src/utils/cache-marker-budget.ts"],"names":[],"mappings":"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"}
|
package/dist/utils/cost.d.ts
CHANGED
|
@@ -6,5 +6,27 @@ export interface CostableUsage {
|
|
|
6
6
|
cacheCreationTokens?: number;
|
|
7
7
|
cacheReadTokens?: number;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Say once, per model, that membrane has no rates for it — so an omitted
|
|
11
|
+
* `estimatedCost` reads as "unknown" rather than "free" to a caller who only
|
|
12
|
+
* ever sees the absence.
|
|
13
|
+
*/
|
|
14
|
+
export declare function warnUnpricedModel(modelId: string): void;
|
|
15
|
+
/** Test seam: the once-per-model warn latch is process-wide otherwise. */
|
|
16
|
+
export declare function resetUnpricedModelWarnings(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Add two breakdowns that may have been priced at DIFFERENT rates — the
|
|
19
|
+
* multi-round case, where each round is priced under the model that served it
|
|
20
|
+
* and the turn total is their sum.
|
|
21
|
+
*
|
|
22
|
+
* `pricingAsOf` takes the OLDER of the two: a total is only as fresh as its
|
|
23
|
+
* stalest input, and a round whose source vouches for NO date is stalest of
|
|
24
|
+
* all — one unstamped round leaves the sum unstamped. A currency mismatch is
|
|
25
|
+
* not summable at all (the caller's
|
|
26
|
+
* registry priced two rounds in different currencies and membrane has no rate
|
|
27
|
+
* to convert with), so it returns undefined rather than adding dollars to
|
|
28
|
+
* euros — an absent cost says "membrane does not know", which is true.
|
|
29
|
+
*/
|
|
30
|
+
export declare function addCostBreakdowns(a: CostBreakdown, b: CostBreakdown): CostBreakdown | undefined;
|
|
9
31
|
export declare function calculateCost(usage: CostableUsage, pricing: ModelPricing): CostBreakdown;
|
|
10
32
|
//# sourceMappingURL=cost.d.ts.map
|
package/dist/utils/cost.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/utils/cost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../../src/utils/cost.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAKD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAQvD;AAED,0EAA0E;AAC1E,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,aAAa,EAChB,CAAC,EAAE,aAAa,GACf,aAAa,GAAG,SAAS,CAsB3B;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,GAAG,aAAa,CAmBxF"}
|
package/dist/utils/cost.js
CHANGED
|
@@ -1,3 +1,57 @@
|
|
|
1
|
+
/** Unpriced models warn once each, not once per call. */
|
|
2
|
+
const warnedUnpricedModels = new Set();
|
|
3
|
+
/**
|
|
4
|
+
* Say once, per model, that membrane has no rates for it — so an omitted
|
|
5
|
+
* `estimatedCost` reads as "unknown" rather than "free" to a caller who only
|
|
6
|
+
* ever sees the absence.
|
|
7
|
+
*/
|
|
8
|
+
export function warnUnpricedModel(modelId) {
|
|
9
|
+
if (warnedUnpricedModels.has(modelId))
|
|
10
|
+
return;
|
|
11
|
+
warnedUnpricedModels.add(modelId);
|
|
12
|
+
console.warn(`[membrane:cost] no pricing for model "${modelId}" — neither the configured`
|
|
13
|
+
+ ' ModelRegistry nor the built-in table has rates for it, so estimatedCost will be'
|
|
14
|
+
+ ' omitted (this is NOT a cost of zero). Add it to your registry to get cost estimates.');
|
|
15
|
+
}
|
|
16
|
+
/** Test seam: the once-per-model warn latch is process-wide otherwise. */
|
|
17
|
+
export function resetUnpricedModelWarnings() {
|
|
18
|
+
warnedUnpricedModels.clear();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Add two breakdowns that may have been priced at DIFFERENT rates — the
|
|
22
|
+
* multi-round case, where each round is priced under the model that served it
|
|
23
|
+
* and the turn total is their sum.
|
|
24
|
+
*
|
|
25
|
+
* `pricingAsOf` takes the OLDER of the two: a total is only as fresh as its
|
|
26
|
+
* stalest input, and a round whose source vouches for NO date is stalest of
|
|
27
|
+
* all — one unstamped round leaves the sum unstamped. A currency mismatch is
|
|
28
|
+
* not summable at all (the caller's
|
|
29
|
+
* registry priced two rounds in different currencies and membrane has no rate
|
|
30
|
+
* to convert with), so it returns undefined rather than adding dollars to
|
|
31
|
+
* euros — an absent cost says "membrane does not know", which is true.
|
|
32
|
+
*/
|
|
33
|
+
export function addCostBreakdowns(a, b) {
|
|
34
|
+
if (a.currency !== b.currency)
|
|
35
|
+
return undefined;
|
|
36
|
+
const cacheWrite = a.cacheWrite != null || b.cacheWrite != null
|
|
37
|
+
? (a.cacheWrite ?? 0) + (b.cacheWrite ?? 0)
|
|
38
|
+
: undefined;
|
|
39
|
+
const cacheRead = a.cacheRead != null || b.cacheRead != null
|
|
40
|
+
? (a.cacheRead ?? 0) + (b.cacheRead ?? 0)
|
|
41
|
+
: undefined;
|
|
42
|
+
const oldestAsOf = a.pricingAsOf && b.pricingAsOf
|
|
43
|
+
? (a.pricingAsOf < b.pricingAsOf ? a.pricingAsOf : b.pricingAsOf)
|
|
44
|
+
: undefined;
|
|
45
|
+
return {
|
|
46
|
+
input: a.input + b.input,
|
|
47
|
+
output: a.output + b.output,
|
|
48
|
+
cacheWrite,
|
|
49
|
+
cacheRead,
|
|
50
|
+
total: a.total + b.total,
|
|
51
|
+
currency: a.currency,
|
|
52
|
+
...(oldestAsOf ? { pricingAsOf: oldestAsOf } : {}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
1
55
|
export function calculateCost(usage, pricing) {
|
|
2
56
|
const input = usage.inputTokens * pricing.inputPerMillion / 1_000_000;
|
|
3
57
|
const output = usage.outputTokens * pricing.outputPerMillion / 1_000_000;
|
|
@@ -14,6 +68,7 @@ export function calculateCost(usage, pricing) {
|
|
|
14
68
|
cacheRead,
|
|
15
69
|
total: input + output + (cacheWrite ?? 0) + (cacheRead ?? 0),
|
|
16
70
|
currency: pricing.currency,
|
|
71
|
+
...(pricing.asOf ? { pricingAsOf: pricing.asOf } : {}),
|
|
17
72
|
};
|
|
18
73
|
}
|
|
19
74
|
//# sourceMappingURL=cost.js.map
|
package/dist/utils/cost.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/utils/cost.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,aAAa,CAAC,KAAoB,EAAE,OAAqB;IACvE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IACtE,MAAM,MAAM,GAAG,KAAK,CAAC,YAAY,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC;IACzE,MAAM,UAAU,GAAG,OAAO,CAAC,oBAAoB,IAAI,IAAI;QACrD,CAAC,CAAC,CAAC,KAAK,CAAC,mBAAmB,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,oBAAoB,GAAG,SAAS;QAC7E,CAAC,CAAC,SAAS,CAAC;IACd,MAAM,SAAS,GAAG,OAAO,CAAC,mBAAmB,IAAI,IAAI;QACnD,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS;QACxE,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO;QACL,KAAK;QACL,MAAM;QACN,UAAU;QACV,SAAS;QACT,KAAK,EAAE,KAAK,GAAG,MAAM,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,CAAC;QAC5D,QAAQ,EAAE,OAAO,CAAC,QAAQ;
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../../src/utils/cost.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for pairing provider-native thinking carriers (which hold the
|
|
3
|
+
* signatures) with parser-derived thinking blocks (which hold the text).
|
|
4
|
+
* See Membrane.mergeProviderThinkingBlocks for the pairing rules.
|
|
5
|
+
*/
|
|
6
|
+
import type { ContentBlock } from '../types/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Identity for thinking text, insensitive to exactly two artifacts that ride
|
|
9
|
+
* the parser's view of the same reasoning — and to nothing else:
|
|
10
|
+
*
|
|
11
|
+
* - stream scaffolding: the XML path prefills `Claude: <thinking>` and asks
|
|
12
|
+
* the adapter to wrap native thinking deltas, so a parsed block can carry
|
|
13
|
+
* a literal `<thinking>` / `</thinking>` tag the provider block never had.
|
|
14
|
+
* - OUTER boundary whitespace: the continuation path trims the accumulation
|
|
15
|
+
* at each round boundary (`buildContinuationRequest` trimEnds before
|
|
16
|
+
* re-prefilling), so a fragment and the parsed text can differ by leading
|
|
17
|
+
* or trailing whitespace.
|
|
18
|
+
*
|
|
19
|
+
* INTERNAL whitespace is payload and is compared verbatim. Erasing it (the
|
|
20
|
+
* first implementation stripped every `\s`) makes distinct signed payloads
|
|
21
|
+
* collide on nothing but where their spaces fall, and the caller then stamps
|
|
22
|
+
* one payload's signature onto the other's text — a carrier that fails
|
|
23
|
+
* Anthropic signature validation when the consumer ships its history back.
|
|
24
|
+
*
|
|
25
|
+
* Comparison only — stored text is never rewritten. Empty text is never
|
|
26
|
+
* identical to anything: signature-only carriers are prepend-only.
|
|
27
|
+
*/
|
|
28
|
+
export declare function sameThinkingText(left: string, right: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Find a RUN of consecutive still-unpaired provider blocks whose concatenated
|
|
31
|
+
* thinking reconstructs `parsedText` (an auto-continuation split across a
|
|
32
|
+
* max_tokens boundary). Returns the provider indices in order, or undefined
|
|
33
|
+
* when no run of two or more reconstructs it.
|
|
34
|
+
*
|
|
35
|
+
* Two joins are tried, because the round boundary itself is the one place a
|
|
36
|
+
* fragment's whitespace can legitimately vanish: `buildContinuationRequest`
|
|
37
|
+
* trimEnds the accumulation before re-prefilling, so the resumed text may
|
|
38
|
+
* pick up exactly where the trim left off. Modelling that single
|
|
39
|
+
* transformation keeps internal whitespace comparable everywhere else —
|
|
40
|
+
* `sameThinkingText` treats it as payload.
|
|
41
|
+
*/
|
|
42
|
+
export declare function findSpanningProviderRun(providerThinking: Array<{
|
|
43
|
+
thinking?: string;
|
|
44
|
+
signature?: string;
|
|
45
|
+
}>, pairedProviderBlocks: ReadonlySet<number>, parsedText: string): number[] | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Drop the extended-thinking config from a prefill-shaped provider request —
|
|
48
|
+
* from BOTH channels the `thinkingEnabled` resolver reads.
|
|
49
|
+
*
|
|
50
|
+
* Whether the API rejects thinking beside an assistant prefill is MODEL
|
|
51
|
+
* DEPENDENT, not a universal law. Measured live 2026-08-25 against the
|
|
52
|
+
* Anthropic Messages API: `claude-haiku-4-5-20251001` accepts an assistant
|
|
53
|
+
* prefill together with `thinking: {type: 'enabled'}` (HTTP 200, and the
|
|
54
|
+
* response carries no thinking block), while `claude-sonnet-4-6` refuses
|
|
55
|
+
* assistant prefill outright — HTTP 400, "This model does not support
|
|
56
|
+
* assistant message prefill."
|
|
57
|
+
*
|
|
58
|
+
* So the strip is the prefill path's DESIGN wherever prefill works: the XML
|
|
59
|
+
* formatter uses the thinking config to emit a literal `<thinking>` text
|
|
60
|
+
* prefix rather than the API feature, and sending both pays for API thinking
|
|
61
|
+
* the prefill format does not consume. On models that reject the combination
|
|
62
|
+
* it is additionally the 400 guard it always was. Either way both channels
|
|
63
|
+
* must agree, and the guard that only deleted the top-level field left
|
|
64
|
+
* `extra.thinking` (spread from `providerParams`) riding the adapter's
|
|
65
|
+
* `Object.assign(params, rest)` onto the wire — reproducing both the 400 and
|
|
66
|
+
* the interleaved-thinking beta header, since the resolver correctly saw the
|
|
67
|
+
* smuggled config. Mutates and returns the request; callers must own `extra`
|
|
68
|
+
* (never alias the caller's `providerParams`).
|
|
69
|
+
*/
|
|
70
|
+
export declare function stripThinkingForPrefill<T extends {
|
|
71
|
+
thinking?: unknown;
|
|
72
|
+
extra?: unknown;
|
|
73
|
+
}>(providerRequest: T): T;
|
|
74
|
+
/**
|
|
75
|
+
* De-duplication key for a thinking / redacted_thinking carrier: two carriers
|
|
76
|
+
* are the same carrier when their payload and signature match. Any other block
|
|
77
|
+
* type gets a unique key so it can never collide.
|
|
78
|
+
*/
|
|
79
|
+
export declare function thinkingCarrierKey(block: ContentBlock): string;
|
|
80
|
+
//# sourceMappingURL=thinking-carriers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thinking-carriers.d.ts","sourceRoot":"","sources":["../../src/utils/thinking-carriers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAOrE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CACrC,gBAAgB,EAAE,KAAK,CAAC;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAClE,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,EACzC,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,GAAG,SAAS,CAmBtB;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,EACvF,eAAe,EAAE,CAAC,GACjB,CAAC,CAOH;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAS9D"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity for thinking text, insensitive to exactly two artifacts that ride
|
|
3
|
+
* the parser's view of the same reasoning — and to nothing else:
|
|
4
|
+
*
|
|
5
|
+
* - stream scaffolding: the XML path prefills `Claude: <thinking>` and asks
|
|
6
|
+
* the adapter to wrap native thinking deltas, so a parsed block can carry
|
|
7
|
+
* a literal `<thinking>` / `</thinking>` tag the provider block never had.
|
|
8
|
+
* - OUTER boundary whitespace: the continuation path trims the accumulation
|
|
9
|
+
* at each round boundary (`buildContinuationRequest` trimEnds before
|
|
10
|
+
* re-prefilling), so a fragment and the parsed text can differ by leading
|
|
11
|
+
* or trailing whitespace.
|
|
12
|
+
*
|
|
13
|
+
* INTERNAL whitespace is payload and is compared verbatim. Erasing it (the
|
|
14
|
+
* first implementation stripped every `\s`) makes distinct signed payloads
|
|
15
|
+
* collide on nothing but where their spaces fall, and the caller then stamps
|
|
16
|
+
* one payload's signature onto the other's text — a carrier that fails
|
|
17
|
+
* Anthropic signature validation when the consumer ships its history back.
|
|
18
|
+
*
|
|
19
|
+
* Comparison only — stored text is never rewritten. Empty text is never
|
|
20
|
+
* identical to anything: signature-only carriers are prepend-only.
|
|
21
|
+
*/
|
|
22
|
+
export function sameThinkingText(left, right) {
|
|
23
|
+
if (left === right)
|
|
24
|
+
return left !== '';
|
|
25
|
+
if (left === '' || right === '')
|
|
26
|
+
return false;
|
|
27
|
+
const normalized = (text) => text.replace(/<\/?(antml:)?thinking>/g, '').trim();
|
|
28
|
+
const normalizedLeft = normalized(left);
|
|
29
|
+
if (normalizedLeft === '')
|
|
30
|
+
return false;
|
|
31
|
+
return normalizedLeft === normalized(right);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Find a RUN of consecutive still-unpaired provider blocks whose concatenated
|
|
35
|
+
* thinking reconstructs `parsedText` (an auto-continuation split across a
|
|
36
|
+
* max_tokens boundary). Returns the provider indices in order, or undefined
|
|
37
|
+
* when no run of two or more reconstructs it.
|
|
38
|
+
*
|
|
39
|
+
* Two joins are tried, because the round boundary itself is the one place a
|
|
40
|
+
* fragment's whitespace can legitimately vanish: `buildContinuationRequest`
|
|
41
|
+
* trimEnds the accumulation before re-prefilling, so the resumed text may
|
|
42
|
+
* pick up exactly where the trim left off. Modelling that single
|
|
43
|
+
* transformation keeps internal whitespace comparable everywhere else —
|
|
44
|
+
* `sameThinkingText` treats it as payload.
|
|
45
|
+
*/
|
|
46
|
+
export function findSpanningProviderRun(providerThinking, pairedProviderBlocks, parsedText) {
|
|
47
|
+
for (let start = 0; start < providerThinking.length; start++) {
|
|
48
|
+
if (pairedProviderBlocks.has(start))
|
|
49
|
+
continue;
|
|
50
|
+
const firstFragment = providerThinking[start].thinking ?? '';
|
|
51
|
+
let verbatimJoin = firstFragment;
|
|
52
|
+
let trimmedJoin = firstFragment;
|
|
53
|
+
const run = [start];
|
|
54
|
+
for (let next = start + 1; next < providerThinking.length; next++) {
|
|
55
|
+
if (pairedProviderBlocks.has(next))
|
|
56
|
+
break;
|
|
57
|
+
const fragment = providerThinking[next].thinking ?? '';
|
|
58
|
+
verbatimJoin += fragment;
|
|
59
|
+
trimmedJoin = trimmedJoin.trimEnd() + fragment;
|
|
60
|
+
run.push(next);
|
|
61
|
+
if (sameThinkingText(verbatimJoin, parsedText) || sameThinkingText(trimmedJoin, parsedText)) {
|
|
62
|
+
return [...run];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Drop the extended-thinking config from a prefill-shaped provider request —
|
|
70
|
+
* from BOTH channels the `thinkingEnabled` resolver reads.
|
|
71
|
+
*
|
|
72
|
+
* Whether the API rejects thinking beside an assistant prefill is MODEL
|
|
73
|
+
* DEPENDENT, not a universal law. Measured live 2026-08-25 against the
|
|
74
|
+
* Anthropic Messages API: `claude-haiku-4-5-20251001` accepts an assistant
|
|
75
|
+
* prefill together with `thinking: {type: 'enabled'}` (HTTP 200, and the
|
|
76
|
+
* response carries no thinking block), while `claude-sonnet-4-6` refuses
|
|
77
|
+
* assistant prefill outright — HTTP 400, "This model does not support
|
|
78
|
+
* assistant message prefill."
|
|
79
|
+
*
|
|
80
|
+
* So the strip is the prefill path's DESIGN wherever prefill works: the XML
|
|
81
|
+
* formatter uses the thinking config to emit a literal `<thinking>` text
|
|
82
|
+
* prefix rather than the API feature, and sending both pays for API thinking
|
|
83
|
+
* the prefill format does not consume. On models that reject the combination
|
|
84
|
+
* it is additionally the 400 guard it always was. Either way both channels
|
|
85
|
+
* must agree, and the guard that only deleted the top-level field left
|
|
86
|
+
* `extra.thinking` (spread from `providerParams`) riding the adapter's
|
|
87
|
+
* `Object.assign(params, rest)` onto the wire — reproducing both the 400 and
|
|
88
|
+
* the interleaved-thinking beta header, since the resolver correctly saw the
|
|
89
|
+
* smuggled config. Mutates and returns the request; callers must own `extra`
|
|
90
|
+
* (never alias the caller's `providerParams`).
|
|
91
|
+
*/
|
|
92
|
+
export function stripThinkingForPrefill(providerRequest) {
|
|
93
|
+
delete providerRequest.thinking;
|
|
94
|
+
const extra = providerRequest.extra;
|
|
95
|
+
if (extra && typeof extra === 'object') {
|
|
96
|
+
delete extra.thinking;
|
|
97
|
+
}
|
|
98
|
+
return providerRequest;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* De-duplication key for a thinking / redacted_thinking carrier: two carriers
|
|
102
|
+
* are the same carrier when their payload and signature match. Any other block
|
|
103
|
+
* type gets a unique key so it can never collide.
|
|
104
|
+
*/
|
|
105
|
+
export function thinkingCarrierKey(block) {
|
|
106
|
+
if (block.type === 'thinking') {
|
|
107
|
+
const { thinking, signature } = block;
|
|
108
|
+
return `thinking\u0000${thinking ?? ''}\u0000${signature ?? ''}`;
|
|
109
|
+
}
|
|
110
|
+
if (block.type === 'redacted_thinking') {
|
|
111
|
+
return `redacted\u0000${block.data ?? ''}`;
|
|
112
|
+
}
|
|
113
|
+
return `other\u0000${JSON.stringify(block)}`;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=thinking-carriers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thinking-carriers.js","sourceRoot":"","sources":["../../src/utils/thinking-carriers.ts"],"names":[],"mappings":"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"}
|
|
@@ -80,6 +80,30 @@ export declare function parseAccumulatedIntoBlocks(text: string, options?: {
|
|
|
80
80
|
blocks: ContentBlock[];
|
|
81
81
|
toolCalls: ToolCall[];
|
|
82
82
|
toolResults: ToolResult[];
|
|
83
|
+
/**
|
|
84
|
+
* The text ends inside a tool block — an opener with no closer, or a cut
|
|
85
|
+
* mid-tag. The membrane loop does not resume on a length stop, so this is
|
|
86
|
+
* what a max_tokens truncation leaves behind, and persisting it bare lets the
|
|
87
|
+
* next round's closer splice onto the stale opener.
|
|
88
|
+
*/
|
|
89
|
+
unclosedToolBlock: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* function_calls blocks that yielded no invokes at all. Always a defect —
|
|
92
|
+
* never how a well-formed block ends.
|
|
93
|
+
*/
|
|
94
|
+
emptyToolBlocks: number;
|
|
95
|
+
/**
|
|
96
|
+
* Block matches that spanned another opener and were re-anchored to the
|
|
97
|
+
* innermost one. Each is a truncated block that was persisted bare and is
|
|
98
|
+
* being repaired at read time.
|
|
99
|
+
*/
|
|
100
|
+
splicedToolBlocks: number;
|
|
101
|
+
/**
|
|
102
|
+
* `<invoke>` heads that were left open and swallowed a later invoke, so the
|
|
103
|
+
* match was refused and re-anchored to the call it absorbed. Nothing was
|
|
104
|
+
* dispatched under the head's name, and the head itself never ran.
|
|
105
|
+
*/
|
|
106
|
+
unclosedInvokeHeads: number;
|
|
83
107
|
};
|
|
84
108
|
import type { ToolDefinition } from '../types/index.js';
|
|
85
109
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-parser.d.ts","sourceRoot":"","sources":["../../src/utils/tool-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAA0B,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-parser.d.ts","sourceRoot":"","sources":["../../src/utils/tool-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAA0B,MAAM,mBAAmB,CAAC;AA0OrH;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAiCnE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ1D;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAQ9D;AAkCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAsB/D;AAqBD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE3D;AAMD,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,uBAAuB,EAAE,GAAG,MAAM,CA0B9E;AAkKD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,gBAAgB,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,CAAA;CAAE,GACxE;IACD,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B;;;;;OAKG;IACH,iBAAiB,EAAE,OAAO,CAAC;IAC3B;;;OAGG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CA6PA;AAMD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAUxD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,CAsBnE;AAMD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CASpE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,cAAc,EAAE,MAAM,CAAC;IAEvB,yDAAyD;IACzD,MAAM,EAAE,kBAAkB,EAAE,CAAC;IAE7B,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IAEtB,oCAAoC;IACpC,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,gBAAgB,CAuFrF;AA8CD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOhD"}
|