@cendor/core 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +53 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/bus.d.ts +21 -0
- package/dist/bus.d.ts.map +1 -0
- package/dist/bus.js +48 -0
- package/dist/bus.js.map +1 -0
- package/dist/decimal.d.ts +11 -0
- package/dist/decimal.d.ts.map +1 -0
- package/dist/decimal.js +13 -0
- package/dist/decimal.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/instrument.d.ts +26 -0
- package/dist/instrument.d.ts.map +1 -0
- package/dist/instrument.js +478 -0
- package/dist/instrument.js.map +1 -0
- package/dist/json-decimal.d.ts +12 -0
- package/dist/json-decimal.d.ts.map +1 -0
- package/dist/json-decimal.js +189 -0
- package/dist/json-decimal.js.map +1 -0
- package/dist/prices-snapshot.d.ts +8 -0
- package/dist/prices-snapshot.d.ts.map +1 -0
- package/dist/prices-snapshot.js +33 -0
- package/dist/prices-snapshot.js.map +1 -0
- package/dist/prices.d.ts +78 -0
- package/dist/prices.d.ts.map +1 -0
- package/dist/prices.js +311 -0
- package/dist/prices.js.map +1 -0
- package/dist/protocols.d.ts +33 -0
- package/dist/protocols.d.ts.map +1 -0
- package/dist/protocols.js +6 -0
- package/dist/protocols.js.map +1 -0
- package/dist/tokens.d.ts +20 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +161 -0
- package/dist/tokens.js.map +1 -0
- package/dist/trace.d.ts +35 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +59 -0
- package/dist/trace.js.map +1 -0
- package/dist/types.d.ts +106 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +146 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single interception point: wrap a provider client (or tool) once; emit normalized events. The TS
|
|
3
|
+
* mirror of `cendor.core.instrument`, scoped in this port to the OpenAI (Chat Completions + Responses)
|
|
4
|
+
* and Anthropic JS SDKs — the fetch-based clients. Detection is structural (the SDKs are never
|
|
5
|
+
* imported, so they stay optional peer deps). Idempotent, async-first, and streaming-aware.
|
|
6
|
+
*
|
|
7
|
+
* Two cooperation hooks (used by `@cendor/cassette`; harmless otherwise):
|
|
8
|
+
* - **record** — the raw provider response is attached at `call.metadata.response` before emit.
|
|
9
|
+
* - **replay** — registered interceptors run *before* the real call; one may return a response to
|
|
10
|
+
* short-circuit it (returning {@link MISS} to decline).
|
|
11
|
+
*/
|
|
12
|
+
import { emit } from './bus.js';
|
|
13
|
+
import { Dec } from './decimal.js';
|
|
14
|
+
import { estimate } from './prices.js';
|
|
15
|
+
import { count as countTokens } from './tokens.js';
|
|
16
|
+
import { currentTraceId } from './trace.js';
|
|
17
|
+
import { LLMCall, Money, ToolCall, Usage } from './types.js';
|
|
18
|
+
const WRAPPED = Symbol.for('cendor.wrapped');
|
|
19
|
+
/** Sentinel an interceptor returns to decline a call (let it proceed normally). */
|
|
20
|
+
export const MISS = Symbol.for('cendor.MISS');
|
|
21
|
+
/** Returned by an interceptor to modify the outgoing request, then run the real call. */
|
|
22
|
+
export class Reroute {
|
|
23
|
+
updates;
|
|
24
|
+
constructor(updates) {
|
|
25
|
+
this.updates = updates;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const interceptors = [];
|
|
29
|
+
/** Register a pre-call interceptor. Returns a response to short-circuit, or {@link MISS} to proceed. */
|
|
30
|
+
export function addInterceptor(fn) {
|
|
31
|
+
if (!interceptors.includes(fn))
|
|
32
|
+
interceptors.push(fn);
|
|
33
|
+
return fn;
|
|
34
|
+
}
|
|
35
|
+
/** Unregister a previously added interceptor (no error if absent). */
|
|
36
|
+
export function removeInterceptor(fn) {
|
|
37
|
+
const i = interceptors.indexOf(fn);
|
|
38
|
+
if (i >= 0)
|
|
39
|
+
interceptors.splice(i, 1);
|
|
40
|
+
}
|
|
41
|
+
function intercept(event) {
|
|
42
|
+
const snapshot = [...interceptors];
|
|
43
|
+
for (const fn of snapshot) {
|
|
44
|
+
const result = fn(event);
|
|
45
|
+
if (result !== MISS)
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
return MISS;
|
|
49
|
+
}
|
|
50
|
+
function uuidHex() {
|
|
51
|
+
return globalThis.crypto.randomUUID().replace(/-/g, '');
|
|
52
|
+
}
|
|
53
|
+
function get(obj, name, dflt = null) {
|
|
54
|
+
if (obj == null || typeof obj !== 'object')
|
|
55
|
+
return dflt;
|
|
56
|
+
const v = obj[name];
|
|
57
|
+
return v === undefined ? dflt : v;
|
|
58
|
+
}
|
|
59
|
+
function toInt(x) {
|
|
60
|
+
return Math.trunc(Number(x));
|
|
61
|
+
}
|
|
62
|
+
function findTargets(client) {
|
|
63
|
+
if (client == null || typeof client !== 'object')
|
|
64
|
+
return [];
|
|
65
|
+
const c = client;
|
|
66
|
+
const targets = [];
|
|
67
|
+
const chat = c.chat;
|
|
68
|
+
const completions = chat?.completions;
|
|
69
|
+
if (completions && typeof completions.create === 'function') {
|
|
70
|
+
targets.push([completions, 'create', 'openai']);
|
|
71
|
+
}
|
|
72
|
+
const responses = c.responses;
|
|
73
|
+
if (responses && typeof responses.create === 'function') {
|
|
74
|
+
targets.push([responses, 'create', 'openai_responses']);
|
|
75
|
+
}
|
|
76
|
+
if (targets.length > 0)
|
|
77
|
+
return targets;
|
|
78
|
+
const messages = c.messages;
|
|
79
|
+
if (messages && typeof messages.create === 'function') {
|
|
80
|
+
return [[messages, 'create', 'anthropic']];
|
|
81
|
+
}
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
const PUBLIC_PROVIDER = { openai_responses: 'openai' };
|
|
85
|
+
function publicProvider(provider) {
|
|
86
|
+
return PUBLIC_PROVIDER[provider] ?? provider;
|
|
87
|
+
}
|
|
88
|
+
/** Per-provider kwarg carrying request messages (so `Reroute({ messages })` rewrites the right field). */
|
|
89
|
+
const MESSAGES_KWARG = { openai_responses: 'input' };
|
|
90
|
+
/**
|
|
91
|
+
* Wrap a provider client so each call emits an `LLMCall` on the bus. Detection is structural. Unknown
|
|
92
|
+
* clients are returned untouched; wrapping is idempotent and returns the same client object.
|
|
93
|
+
*/
|
|
94
|
+
export function instrument(client) {
|
|
95
|
+
for (const [owner, attr, provider] of findTargets(client)) {
|
|
96
|
+
const fn = owner[attr];
|
|
97
|
+
if (fn[WRAPPED])
|
|
98
|
+
continue;
|
|
99
|
+
owner[attr] = wrap(fn.bind(owner), provider);
|
|
100
|
+
}
|
|
101
|
+
return client;
|
|
102
|
+
}
|
|
103
|
+
// --------------------------------------------------------------------------- model clients
|
|
104
|
+
function wrap(orig, provider) {
|
|
105
|
+
const wrapper = async (...args) => {
|
|
106
|
+
const kwargs = {
|
|
107
|
+
...(args[0] ?? {}),
|
|
108
|
+
};
|
|
109
|
+
const rest = args.slice(1);
|
|
110
|
+
const { call, start } = pre(provider, kwargs);
|
|
111
|
+
ensureStreamUsageOptions(provider, kwargs);
|
|
112
|
+
const streaming = Boolean(kwargs.stream);
|
|
113
|
+
const directive = intercept(call);
|
|
114
|
+
if (directive instanceof Reroute) {
|
|
115
|
+
applyReroute(call, kwargs, directive, provider);
|
|
116
|
+
const response = await orig(kwargs, ...rest);
|
|
117
|
+
if (streaming)
|
|
118
|
+
return proxyStream(call, response, provider, start);
|
|
119
|
+
post(call, response, provider, start);
|
|
120
|
+
return response;
|
|
121
|
+
}
|
|
122
|
+
if (directive !== MISS) {
|
|
123
|
+
call.metadata.replayed = true;
|
|
124
|
+
if (streaming)
|
|
125
|
+
return replayStream(call, directive, provider, start);
|
|
126
|
+
post(call, directive, provider, start);
|
|
127
|
+
return directive;
|
|
128
|
+
}
|
|
129
|
+
const response = await orig(kwargs, ...rest);
|
|
130
|
+
if (streaming)
|
|
131
|
+
return proxyStream(call, response, provider, start);
|
|
132
|
+
post(call, response, provider, start);
|
|
133
|
+
return response;
|
|
134
|
+
};
|
|
135
|
+
wrapper[WRAPPED] = true;
|
|
136
|
+
return wrapper;
|
|
137
|
+
}
|
|
138
|
+
const MISSING = Symbol('missing');
|
|
139
|
+
function applyReroute(call, kwargs, directive, provider) {
|
|
140
|
+
const { messages: messagesUpdate, ...updates } = directive.updates;
|
|
141
|
+
const messages = 'messages' in directive.updates ? messagesUpdate : MISSING;
|
|
142
|
+
Object.assign(kwargs, updates);
|
|
143
|
+
if ('model' in updates)
|
|
144
|
+
call.model = updates.model;
|
|
145
|
+
if (messages !== MISSING) {
|
|
146
|
+
kwargs[MESSAGES_KWARG[provider] ?? 'messages'] = messages;
|
|
147
|
+
call.messages = messages;
|
|
148
|
+
}
|
|
149
|
+
call.metadata.rerouted = true;
|
|
150
|
+
}
|
|
151
|
+
function pre(provider, kwargs) {
|
|
152
|
+
const { model, messages } = extractRequest(provider, kwargs);
|
|
153
|
+
const call = new LLMCall({
|
|
154
|
+
id: uuidHex(),
|
|
155
|
+
provider: publicProvider(provider),
|
|
156
|
+
model,
|
|
157
|
+
messages,
|
|
158
|
+
traceId: currentTraceId(),
|
|
159
|
+
ts: new Date(),
|
|
160
|
+
});
|
|
161
|
+
call.metadata.request_kwargs = kwargs;
|
|
162
|
+
return { call, start: performance.now() };
|
|
163
|
+
}
|
|
164
|
+
function extractRequest(provider, kwargs) {
|
|
165
|
+
if (provider === 'openai_responses') {
|
|
166
|
+
const inp = kwargs.input ?? kwargs.messages;
|
|
167
|
+
let messages;
|
|
168
|
+
if (typeof inp === 'string')
|
|
169
|
+
messages = [{ role: 'user', content: inp }];
|
|
170
|
+
else if (Array.isArray(inp))
|
|
171
|
+
messages = inp;
|
|
172
|
+
else
|
|
173
|
+
messages = [];
|
|
174
|
+
return { model: kwargs.model ?? '', messages };
|
|
175
|
+
}
|
|
176
|
+
// openai / anthropic both take model= + messages=
|
|
177
|
+
const messages = Array.isArray(kwargs.messages) ? kwargs.messages : [];
|
|
178
|
+
return { model: kwargs.model ?? '', messages };
|
|
179
|
+
}
|
|
180
|
+
function post(call, response, provider, start) {
|
|
181
|
+
call.latencyMs = performance.now() - start;
|
|
182
|
+
const usage = extractUsage(response, provider);
|
|
183
|
+
call.usage = usage;
|
|
184
|
+
setCost(call, usage, extractReportedCost(response));
|
|
185
|
+
call.metadata.response = response;
|
|
186
|
+
emit(call);
|
|
187
|
+
}
|
|
188
|
+
function setCost(call, usage, reported) {
|
|
189
|
+
if (reported !== null) {
|
|
190
|
+
call.cost = reported;
|
|
191
|
+
call.metadata.cost_reported = true;
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (usage !== null) {
|
|
195
|
+
try {
|
|
196
|
+
call.cost = estimate(call.model, usage.inputTokens, {
|
|
197
|
+
outputTokens: usage.outputTokens,
|
|
198
|
+
cachedTokens: usage.cachedTokens,
|
|
199
|
+
cacheWriteTokens: usage.cacheWrite,
|
|
200
|
+
});
|
|
201
|
+
call.metadata.cost_estimated = true;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
call.cost = null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function extractReportedCost(response) {
|
|
209
|
+
const u = get(response, 'usage');
|
|
210
|
+
const candidates = [];
|
|
211
|
+
if (u !== null)
|
|
212
|
+
candidates.push(get(u, 'cost'), get(u, 'total_cost'));
|
|
213
|
+
candidates.push(get(response, 'cost'), get(response, 'total_cost'));
|
|
214
|
+
for (const c of candidates) {
|
|
215
|
+
if (c == null)
|
|
216
|
+
continue;
|
|
217
|
+
let amount;
|
|
218
|
+
try {
|
|
219
|
+
amount = new Dec(String(c));
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (amount.greaterThanOrEqualTo(0))
|
|
225
|
+
return new Money(amount);
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
function ensureStreamUsageOptions(provider, kwargs) {
|
|
230
|
+
if (provider === 'openai' && kwargs.stream && !('stream_options' in kwargs)) {
|
|
231
|
+
kwargs.stream_options = { include_usage: true };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// --------------------------------------------------------------------------- streaming
|
|
235
|
+
async function* fromArray(items) {
|
|
236
|
+
for (const item of items)
|
|
237
|
+
yield item;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Wraps a streaming response: chunks pass through unchanged and usage is accumulated, so the
|
|
241
|
+
* `LLMCall` is emitted once with usage/cost/latency when the stream completes (or the consumer stops
|
|
242
|
+
* early). The result is an async-iterable — the contract callers rely on (`for await (const chunk)`).
|
|
243
|
+
*/
|
|
244
|
+
class AsyncStreamProxy {
|
|
245
|
+
call;
|
|
246
|
+
stream;
|
|
247
|
+
provider;
|
|
248
|
+
start;
|
|
249
|
+
replayChunks;
|
|
250
|
+
constructor(call, stream, provider, start, replayChunks = null) {
|
|
251
|
+
this.call = call;
|
|
252
|
+
this.stream = stream;
|
|
253
|
+
this.provider = provider;
|
|
254
|
+
this.start = start;
|
|
255
|
+
this.replayChunks = replayChunks;
|
|
256
|
+
}
|
|
257
|
+
async *[Symbol.asyncIterator]() {
|
|
258
|
+
const chunks = [];
|
|
259
|
+
try {
|
|
260
|
+
for await (const chunk of this.stream) {
|
|
261
|
+
chunks.push(chunk);
|
|
262
|
+
yield chunk;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
finally {
|
|
266
|
+
const finalChunks = this.replayChunks ?? chunks;
|
|
267
|
+
finalizeStream(this.call, finalChunks, this.provider, this.start);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function proxyStream(call, stream, provider, start) {
|
|
272
|
+
return new AsyncStreamProxy(call, stream, provider, start);
|
|
273
|
+
}
|
|
274
|
+
function replayStream(call, recorded, provider, start) {
|
|
275
|
+
const chunks = Array.isArray(recorded) ? [...recorded] : recorded == null ? [] : [recorded];
|
|
276
|
+
return new AsyncStreamProxy(call, fromArray(chunks), provider, start, chunks);
|
|
277
|
+
}
|
|
278
|
+
function finalizeStream(call, chunks, provider, start) {
|
|
279
|
+
call.latencyMs = performance.now() - start;
|
|
280
|
+
let usage = streamUsage(chunks, provider);
|
|
281
|
+
if (usage === null)
|
|
282
|
+
usage = estimateStreamUsage(call, chunks, provider);
|
|
283
|
+
call.usage = usage;
|
|
284
|
+
let reported = null;
|
|
285
|
+
for (const ch of chunks) {
|
|
286
|
+
reported = extractReportedCost(ch);
|
|
287
|
+
if (reported !== null)
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
setCost(call, usage, reported);
|
|
291
|
+
call.metadata.streamed = true;
|
|
292
|
+
call.metadata.response = chunks;
|
|
293
|
+
emit(call);
|
|
294
|
+
}
|
|
295
|
+
function streamUsage(chunks, provider) {
|
|
296
|
+
if (provider === 'anthropic') {
|
|
297
|
+
let inp = null;
|
|
298
|
+
let out = null;
|
|
299
|
+
let cached = 0;
|
|
300
|
+
let cacheWrite = 0;
|
|
301
|
+
for (const ch of chunks) {
|
|
302
|
+
const etype = get(ch, 'type');
|
|
303
|
+
if (etype === 'message_start') {
|
|
304
|
+
const u = get(get(ch, 'message'), 'usage');
|
|
305
|
+
inp = get(u, 'input_tokens', inp);
|
|
306
|
+
cached = get(u, 'cache_read_input_tokens', 0) || 0;
|
|
307
|
+
cacheWrite = get(u, 'cache_creation_input_tokens', 0) || 0;
|
|
308
|
+
}
|
|
309
|
+
else if (etype === 'message_delta') {
|
|
310
|
+
const u = get(ch, 'usage');
|
|
311
|
+
if (u !== null)
|
|
312
|
+
out = get(u, 'output_tokens', out);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (inp === null)
|
|
316
|
+
return null;
|
|
317
|
+
return new Usage({
|
|
318
|
+
inputTokens: toInt(inp) + cached,
|
|
319
|
+
outputTokens: toInt(out ?? 0),
|
|
320
|
+
cachedTokens: cached,
|
|
321
|
+
cacheWrite,
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
if (provider === 'openai_responses') {
|
|
325
|
+
for (const ch of chunks) {
|
|
326
|
+
const resp = get(ch, 'response');
|
|
327
|
+
if (resp !== null && get(resp, 'usage') !== null)
|
|
328
|
+
return extractUsage(resp, 'openai_responses');
|
|
329
|
+
}
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
for (const ch of chunks) {
|
|
333
|
+
const u = extractUsage(ch, provider);
|
|
334
|
+
if (u !== null)
|
|
335
|
+
return u;
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
function estimateStreamUsage(call, chunks, provider) {
|
|
340
|
+
const text = chunks.map((ch) => streamText(ch, provider)).join('');
|
|
341
|
+
if (!text && call.messages.length === 0)
|
|
342
|
+
return null;
|
|
343
|
+
const inp = call.messages.length > 0 ? countTokens(call.messages, call.model) : 0;
|
|
344
|
+
const out = text ? countTokens(text, call.model) : 0;
|
|
345
|
+
call.metadata.usage_estimated = true;
|
|
346
|
+
return new Usage({ inputTokens: inp, outputTokens: out });
|
|
347
|
+
}
|
|
348
|
+
function streamText(chunk, provider) {
|
|
349
|
+
try {
|
|
350
|
+
if (provider === 'openai_responses') {
|
|
351
|
+
if (get(chunk, 'type') === 'response.output_text.delta')
|
|
352
|
+
return String(get(chunk, 'delta', '') ?? '');
|
|
353
|
+
return '';
|
|
354
|
+
}
|
|
355
|
+
if (provider === 'openai') {
|
|
356
|
+
const choices = get(chunk, 'choices') ?? [];
|
|
357
|
+
return choices.map((c) => String(get(get(c, 'delta'), 'content', '') ?? '')).join('');
|
|
358
|
+
}
|
|
359
|
+
if (provider === 'anthropic') {
|
|
360
|
+
if (get(chunk, 'type') === 'content_block_delta')
|
|
361
|
+
return String(get(get(chunk, 'delta'), 'text', '') ?? '');
|
|
362
|
+
return '';
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
return '';
|
|
367
|
+
}
|
|
368
|
+
return '';
|
|
369
|
+
}
|
|
370
|
+
function extractUsage(response, provider) {
|
|
371
|
+
let cached = 0;
|
|
372
|
+
let cacheWrite = 0;
|
|
373
|
+
let reasoning = 0;
|
|
374
|
+
const u = get(response, 'usage');
|
|
375
|
+
if (u === null)
|
|
376
|
+
return null;
|
|
377
|
+
let inp;
|
|
378
|
+
let out;
|
|
379
|
+
if (provider === 'openai' || provider === 'openai_responses') {
|
|
380
|
+
inp = get(u, 'prompt_tokens');
|
|
381
|
+
if (inp == null)
|
|
382
|
+
inp = get(u, 'input_tokens');
|
|
383
|
+
out = get(u, 'completion_tokens');
|
|
384
|
+
if (out == null)
|
|
385
|
+
out = get(u, 'output_tokens', 0);
|
|
386
|
+
out = out || 0;
|
|
387
|
+
const details = get(u, 'prompt_tokens_details') ?? get(u, 'input_tokens_details');
|
|
388
|
+
cached = details !== null ? get(details, 'cached_tokens', 0) || 0 : 0;
|
|
389
|
+
const cdetails = get(u, 'completion_tokens_details') ?? get(u, 'output_tokens_details');
|
|
390
|
+
reasoning = cdetails !== null ? get(cdetails, 'reasoning_tokens', 0) || 0 : 0;
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
// anthropic — thinking tokens are folded into output_tokens with no separate count
|
|
394
|
+
const baseIn = get(u, 'input_tokens');
|
|
395
|
+
out = get(u, 'output_tokens', 0) || 0;
|
|
396
|
+
cached = get(u, 'cache_read_input_tokens', 0) || 0;
|
|
397
|
+
cacheWrite = get(u, 'cache_creation_input_tokens', 0) || 0;
|
|
398
|
+
inp = baseIn == null ? null : toInt(baseIn) + cached;
|
|
399
|
+
}
|
|
400
|
+
if (inp == null)
|
|
401
|
+
return null;
|
|
402
|
+
return new Usage({
|
|
403
|
+
inputTokens: toInt(inp),
|
|
404
|
+
outputTokens: toInt(out),
|
|
405
|
+
cachedTokens: toInt(cached),
|
|
406
|
+
reasoningTokens: toInt(reasoning),
|
|
407
|
+
cacheWrite: toInt(cacheWrite),
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Wrap a tool/function so each invocation emits a `ToolCall` on the bus. Usable as
|
|
412
|
+
* `instrumentTool(fn)` or `instrumentTool('search')(fn)`. Idempotent, sync + async, replay-aware.
|
|
413
|
+
*/
|
|
414
|
+
export function instrumentTool(nameOrFn) {
|
|
415
|
+
if (typeof nameOrFn === 'function')
|
|
416
|
+
return wrapTool(nameOrFn, nameOrFn.name || 'tool');
|
|
417
|
+
return (fn) => wrapTool(fn, (typeof nameOrFn === 'string' && nameOrFn) || fn.name || 'tool');
|
|
418
|
+
}
|
|
419
|
+
function preTool(name, args) {
|
|
420
|
+
const tc = new ToolCall({
|
|
421
|
+
id: uuidHex(),
|
|
422
|
+
name,
|
|
423
|
+
arguments: { args: [...args], kwargs: {} },
|
|
424
|
+
traceId: currentTraceId(),
|
|
425
|
+
ts: new Date(),
|
|
426
|
+
});
|
|
427
|
+
return { tc, start: performance.now() };
|
|
428
|
+
}
|
|
429
|
+
function postTool(tc, result, start) {
|
|
430
|
+
tc.latencyMs = performance.now() - start;
|
|
431
|
+
tc.result = result;
|
|
432
|
+
emit(tc);
|
|
433
|
+
}
|
|
434
|
+
function wrapTool(fn, toolName) {
|
|
435
|
+
if (fn[WRAPPED])
|
|
436
|
+
return fn;
|
|
437
|
+
const isAsync = fn.constructor?.name === 'AsyncFunction';
|
|
438
|
+
let wrapper;
|
|
439
|
+
if (isAsync) {
|
|
440
|
+
wrapper = async function (...args) {
|
|
441
|
+
const { tc, start } = preTool(toolName, args);
|
|
442
|
+
const replayed = intercept(tc);
|
|
443
|
+
let result;
|
|
444
|
+
if (replayed !== MISS) {
|
|
445
|
+
tc.metadata.replayed = true;
|
|
446
|
+
result = replayed;
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
result = await fn.apply(this, args);
|
|
450
|
+
}
|
|
451
|
+
postTool(tc, result, start);
|
|
452
|
+
return result;
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
wrapper = function (...args) {
|
|
457
|
+
const { tc, start } = preTool(toolName, args);
|
|
458
|
+
const replayed = intercept(tc);
|
|
459
|
+
if (replayed !== MISS) {
|
|
460
|
+
tc.metadata.replayed = true;
|
|
461
|
+
postTool(tc, replayed, start);
|
|
462
|
+
return replayed;
|
|
463
|
+
}
|
|
464
|
+
const result = fn.apply(this, args);
|
|
465
|
+
if (result != null && typeof result.then === 'function') {
|
|
466
|
+
return result.then((r) => {
|
|
467
|
+
postTool(tc, r, start);
|
|
468
|
+
return r;
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
postTool(tc, result, start);
|
|
472
|
+
return result;
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
Object.defineProperty(wrapper, WRAPPED, { value: true });
|
|
476
|
+
return wrapper;
|
|
477
|
+
}
|
|
478
|
+
//# sourceMappingURL=instrument.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instrument.js","sourceRoot":"","sources":["../src/instrument.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A JSON parser that decodes every number as a `Decimal` instead of an IEEE double — the TS mirror of
|
|
3
|
+
* Python's `json.loads(text, parse_float=Decimal)`. The price-dataset spec mandates that rates (money)
|
|
4
|
+
* never round-trip through binary floating point in any language, so both the bundled snapshot and any
|
|
5
|
+
* `refresh()`ed table are parsed through this. Dependency-free recursive-descent parser.
|
|
6
|
+
*/
|
|
7
|
+
import { type Decimal } from './decimal.js';
|
|
8
|
+
export type DecimalJsonValue = null | boolean | string | Decimal | DecimalJsonValue[] | {
|
|
9
|
+
[key: string]: DecimalJsonValue;
|
|
10
|
+
};
|
|
11
|
+
export declare function parseDecimalJson(text: string): DecimalJsonValue;
|
|
12
|
+
//# sourceMappingURL=json-decimal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-decimal.d.ts","sourceRoot":"","sources":["../src/json-decimal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAO,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,MAAM,gBAAgB,GACxB,IAAI,GACJ,OAAO,GACP,MAAM,GACN,OAAO,GACP,gBAAgB,EAAE,GAClB;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAA;CAAE,CAAC;AA6KxC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAE/D"}
|