@visibe.ai/node 0.1.23 → 0.1.25
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/cjs/client.js +177 -4
- package/dist/esm/client.js +177 -4
- package/dist/types/client.d.ts +3 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/types/index.d.ts +17 -0
- package/package.json +1 -1
package/dist/cjs/client.js
CHANGED
|
@@ -132,6 +132,170 @@ class Visibe {
|
|
|
132
132
|
});
|
|
133
133
|
}
|
|
134
134
|
// ---------------------------------------------------------------------------
|
|
135
|
+
// runWithSession() — group all auto-instrumented LLM calls inside fn()
|
|
136
|
+
// into a single named trace. Unlike track(), no specific client is required;
|
|
137
|
+
// all already-instrumented clients are automatically captured.
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
async runWithSession(name, fn) {
|
|
140
|
+
const traceId = (0, node_crypto_1.randomUUID)();
|
|
141
|
+
const startedAt = new Date().toISOString();
|
|
142
|
+
const startMs = Date.now();
|
|
143
|
+
await this.apiClient.createTrace({
|
|
144
|
+
trace_id: traceId,
|
|
145
|
+
name,
|
|
146
|
+
framework: 'session',
|
|
147
|
+
started_at: startedAt,
|
|
148
|
+
...(this.sessionId ? { session_id: this.sessionId } : {}),
|
|
149
|
+
});
|
|
150
|
+
let llmCallCount = 0;
|
|
151
|
+
let toolCallCount = 0;
|
|
152
|
+
let totalInput = 0;
|
|
153
|
+
let totalOutput = 0;
|
|
154
|
+
let totalCost = 0;
|
|
155
|
+
const groupCtx = {
|
|
156
|
+
traceId,
|
|
157
|
+
onLLMSpan: (inputTokens, outputTokens, cost) => {
|
|
158
|
+
llmCallCount++;
|
|
159
|
+
totalInput += inputTokens;
|
|
160
|
+
totalOutput += outputTokens;
|
|
161
|
+
totalCost += cost;
|
|
162
|
+
},
|
|
163
|
+
onToolSpan: () => { toolCallCount++; },
|
|
164
|
+
};
|
|
165
|
+
return group_context_1.activeGroupTraceStorage.run(groupCtx, async () => {
|
|
166
|
+
let status = 'completed';
|
|
167
|
+
try {
|
|
168
|
+
return await fn();
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
status = 'failed';
|
|
172
|
+
throw err;
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
const durationMs = Date.now() - startMs;
|
|
176
|
+
// CRITICAL ORDER: flush spans first, then complete the trace.
|
|
177
|
+
this.batcher.flush();
|
|
178
|
+
const sent = await this.apiClient.completeTrace(traceId, {
|
|
179
|
+
status,
|
|
180
|
+
ended_at: new Date().toISOString(),
|
|
181
|
+
duration_ms: durationMs,
|
|
182
|
+
llm_call_count: llmCallCount,
|
|
183
|
+
total_cost: parseFloat(totalCost.toFixed(6)),
|
|
184
|
+
total_tokens: totalInput + totalOutput,
|
|
185
|
+
total_input_tokens: totalInput,
|
|
186
|
+
total_output_tokens: totalOutput,
|
|
187
|
+
});
|
|
188
|
+
printTraceSummary({
|
|
189
|
+
name,
|
|
190
|
+
llmCallCount,
|
|
191
|
+
toolCallCount,
|
|
192
|
+
totalTokens: totalInput + totalOutput,
|
|
193
|
+
totalCost,
|
|
194
|
+
durationMs,
|
|
195
|
+
status,
|
|
196
|
+
}, sent);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
// ---------------------------------------------------------------------------
|
|
201
|
+
// middleware() — Express / Connect / Fastify compatible middleware.
|
|
202
|
+
//
|
|
203
|
+
// Groups every LLM call made during a single HTTP request into one trace.
|
|
204
|
+
// Uses AsyncLocalStorage so concurrent requests are fully isolated — each
|
|
205
|
+
// request gets its own trace regardless of how many are in flight at once.
|
|
206
|
+
//
|
|
207
|
+
// Usage:
|
|
208
|
+
// app.use(visibe.middleware())
|
|
209
|
+
// app.use(visibe.middleware({ name: (req) => `${req.method} ${req.url}` }))
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
middleware(options) {
|
|
212
|
+
return (req, res, next) => {
|
|
213
|
+
// No-op immediately if the SDK is disabled (no/invalid API key).
|
|
214
|
+
if (!this.apiClient._enabled) {
|
|
215
|
+
next();
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const traceId = (0, node_crypto_1.randomUUID)();
|
|
219
|
+
const startedAt = new Date().toISOString();
|
|
220
|
+
const startMs = Date.now();
|
|
221
|
+
// Resolve the trace name from options or fall back to "METHOD /url".
|
|
222
|
+
const name = typeof options?.name === 'function'
|
|
223
|
+
? options.name(req)
|
|
224
|
+
: options?.name ?? `${req.method ?? 'HTTP'} ${req.url ?? '/'}`;
|
|
225
|
+
// Fire createTrace without awaiting — we own the traceId so spans
|
|
226
|
+
// can be buffered safely until the trace creation lands on the backend.
|
|
227
|
+
// Awaiting here would add a network round-trip to every request.
|
|
228
|
+
this.apiClient.createTrace({
|
|
229
|
+
trace_id: traceId,
|
|
230
|
+
name,
|
|
231
|
+
framework: 'http',
|
|
232
|
+
started_at: startedAt,
|
|
233
|
+
...(this.sessionId ? { session_id: this.sessionId } : {}),
|
|
234
|
+
}).catch(() => { });
|
|
235
|
+
let llmCallCount = 0;
|
|
236
|
+
let toolCallCount = 0;
|
|
237
|
+
let totalInput = 0;
|
|
238
|
+
let totalOutput = 0;
|
|
239
|
+
let totalCost = 0;
|
|
240
|
+
const groupCtx = {
|
|
241
|
+
traceId,
|
|
242
|
+
onLLMSpan: (inputTokens, outputTokens, cost) => {
|
|
243
|
+
llmCallCount++;
|
|
244
|
+
totalInput += inputTokens;
|
|
245
|
+
totalOutput += outputTokens;
|
|
246
|
+
totalCost += cost;
|
|
247
|
+
},
|
|
248
|
+
onToolSpan: () => { toolCallCount++; },
|
|
249
|
+
};
|
|
250
|
+
// Guard against both 'finish' and 'close' firing for the same response.
|
|
251
|
+
// 'finish' fires when all data is written; 'close' fires when the
|
|
252
|
+
// underlying connection is closed (e.g. client disconnected early).
|
|
253
|
+
// We only want to complete the trace once.
|
|
254
|
+
let completed = false;
|
|
255
|
+
const complete = () => {
|
|
256
|
+
if (completed)
|
|
257
|
+
return;
|
|
258
|
+
completed = true;
|
|
259
|
+
const durationMs = Date.now() - startMs;
|
|
260
|
+
// Treat any 4xx/5xx as a failed trace.
|
|
261
|
+
const status = res.statusCode >= 400 ? 'failed' : 'completed';
|
|
262
|
+
// Flush buffered spans before completing the trace so the backend
|
|
263
|
+
// has all spans available when it processes the PATCH request.
|
|
264
|
+
this.batcher.flush();
|
|
265
|
+
this.apiClient.completeTrace(traceId, {
|
|
266
|
+
status,
|
|
267
|
+
ended_at: new Date().toISOString(),
|
|
268
|
+
duration_ms: durationMs,
|
|
269
|
+
llm_call_count: llmCallCount,
|
|
270
|
+
total_cost: parseFloat(totalCost.toFixed(6)),
|
|
271
|
+
total_tokens: totalInput + totalOutput,
|
|
272
|
+
total_input_tokens: totalInput,
|
|
273
|
+
total_output_tokens: totalOutput,
|
|
274
|
+
}).catch(() => { });
|
|
275
|
+
// Only print in debug mode — middleware runs on every request and
|
|
276
|
+
// would produce too much noise in production by default.
|
|
277
|
+
if (this.debug) {
|
|
278
|
+
printTraceSummary({
|
|
279
|
+
name,
|
|
280
|
+
llmCallCount,
|
|
281
|
+
toolCallCount,
|
|
282
|
+
totalTokens: totalInput + totalOutput,
|
|
283
|
+
totalCost,
|
|
284
|
+
durationMs,
|
|
285
|
+
status,
|
|
286
|
+
}, true);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
// Run next() inside the ALS context so all async operations spawned
|
|
290
|
+
// by the route handler inherit this request's groupCtx automatically.
|
|
291
|
+
group_context_1.activeGroupTraceStorage.run(groupCtx, () => {
|
|
292
|
+
res.on('finish', complete);
|
|
293
|
+
res.on('close', complete);
|
|
294
|
+
next();
|
|
295
|
+
});
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
// ---------------------------------------------------------------------------
|
|
135
299
|
// flushSpans() — called by shutdown() in index.ts.
|
|
136
300
|
// ---------------------------------------------------------------------------
|
|
137
301
|
flushSpans() {
|
|
@@ -224,19 +388,28 @@ function applyIntegration(client, name, visibe) {
|
|
|
224
388
|
// Integrations are loaded lazily to avoid import errors when the peer
|
|
225
389
|
// dependency is not installed. Each integration module exports a
|
|
226
390
|
// `patchClient(client, name, visibe)` that returns a restore function.
|
|
227
|
-
|
|
391
|
+
// Walk the prototype chain to collect all ancestor class names.
|
|
392
|
+
// This handles subclasses (including our own PatchedOpenAI wrapper) without
|
|
393
|
+
// requiring the direct constructor to have a specific name.
|
|
394
|
+
const ancestorNames = new Set();
|
|
395
|
+
let ctor = client?.constructor;
|
|
396
|
+
while (ctor && ctor.name) {
|
|
397
|
+
ancestorNames.add(ctor.name);
|
|
398
|
+
ctor = Object.getPrototypeOf(ctor);
|
|
399
|
+
}
|
|
400
|
+
const has = (name) => ancestorNames.has(name);
|
|
228
401
|
try {
|
|
229
|
-
if (
|
|
402
|
+
if (has('OpenAI')) {
|
|
230
403
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
231
404
|
const { patchOpenAIClient } = require('./integrations/openai');
|
|
232
405
|
return patchOpenAIClient(client, name, visibe);
|
|
233
406
|
}
|
|
234
|
-
if (
|
|
407
|
+
if (has('Anthropic')) {
|
|
235
408
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
236
409
|
const { patchAnthropicClient } = require('./integrations/anthropic');
|
|
237
410
|
return patchAnthropicClient(client, name, visibe);
|
|
238
411
|
}
|
|
239
|
-
if (
|
|
412
|
+
if (has('BedrockRuntimeClient')) {
|
|
240
413
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
241
414
|
const { patchBedrockClient } = require('./integrations/bedrock');
|
|
242
415
|
return patchBedrockClient(client, name, visibe);
|
package/dist/esm/client.js
CHANGED
|
@@ -129,6 +129,170 @@ export class Visibe {
|
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
131
|
// ---------------------------------------------------------------------------
|
|
132
|
+
// runWithSession() — group all auto-instrumented LLM calls inside fn()
|
|
133
|
+
// into a single named trace. Unlike track(), no specific client is required;
|
|
134
|
+
// all already-instrumented clients are automatically captured.
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
async runWithSession(name, fn) {
|
|
137
|
+
const traceId = randomUUID();
|
|
138
|
+
const startedAt = new Date().toISOString();
|
|
139
|
+
const startMs = Date.now();
|
|
140
|
+
await this.apiClient.createTrace({
|
|
141
|
+
trace_id: traceId,
|
|
142
|
+
name,
|
|
143
|
+
framework: 'session',
|
|
144
|
+
started_at: startedAt,
|
|
145
|
+
...(this.sessionId ? { session_id: this.sessionId } : {}),
|
|
146
|
+
});
|
|
147
|
+
let llmCallCount = 0;
|
|
148
|
+
let toolCallCount = 0;
|
|
149
|
+
let totalInput = 0;
|
|
150
|
+
let totalOutput = 0;
|
|
151
|
+
let totalCost = 0;
|
|
152
|
+
const groupCtx = {
|
|
153
|
+
traceId,
|
|
154
|
+
onLLMSpan: (inputTokens, outputTokens, cost) => {
|
|
155
|
+
llmCallCount++;
|
|
156
|
+
totalInput += inputTokens;
|
|
157
|
+
totalOutput += outputTokens;
|
|
158
|
+
totalCost += cost;
|
|
159
|
+
},
|
|
160
|
+
onToolSpan: () => { toolCallCount++; },
|
|
161
|
+
};
|
|
162
|
+
return activeGroupTraceStorage.run(groupCtx, async () => {
|
|
163
|
+
let status = 'completed';
|
|
164
|
+
try {
|
|
165
|
+
return await fn();
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
status = 'failed';
|
|
169
|
+
throw err;
|
|
170
|
+
}
|
|
171
|
+
finally {
|
|
172
|
+
const durationMs = Date.now() - startMs;
|
|
173
|
+
// CRITICAL ORDER: flush spans first, then complete the trace.
|
|
174
|
+
this.batcher.flush();
|
|
175
|
+
const sent = await this.apiClient.completeTrace(traceId, {
|
|
176
|
+
status,
|
|
177
|
+
ended_at: new Date().toISOString(),
|
|
178
|
+
duration_ms: durationMs,
|
|
179
|
+
llm_call_count: llmCallCount,
|
|
180
|
+
total_cost: parseFloat(totalCost.toFixed(6)),
|
|
181
|
+
total_tokens: totalInput + totalOutput,
|
|
182
|
+
total_input_tokens: totalInput,
|
|
183
|
+
total_output_tokens: totalOutput,
|
|
184
|
+
});
|
|
185
|
+
printTraceSummary({
|
|
186
|
+
name,
|
|
187
|
+
llmCallCount,
|
|
188
|
+
toolCallCount,
|
|
189
|
+
totalTokens: totalInput + totalOutput,
|
|
190
|
+
totalCost,
|
|
191
|
+
durationMs,
|
|
192
|
+
status,
|
|
193
|
+
}, sent);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// middleware() — Express / Connect / Fastify compatible middleware.
|
|
199
|
+
//
|
|
200
|
+
// Groups every LLM call made during a single HTTP request into one trace.
|
|
201
|
+
// Uses AsyncLocalStorage so concurrent requests are fully isolated — each
|
|
202
|
+
// request gets its own trace regardless of how many are in flight at once.
|
|
203
|
+
//
|
|
204
|
+
// Usage:
|
|
205
|
+
// app.use(visibe.middleware())
|
|
206
|
+
// app.use(visibe.middleware({ name: (req) => `${req.method} ${req.url}` }))
|
|
207
|
+
// ---------------------------------------------------------------------------
|
|
208
|
+
middleware(options) {
|
|
209
|
+
return (req, res, next) => {
|
|
210
|
+
// No-op immediately if the SDK is disabled (no/invalid API key).
|
|
211
|
+
if (!this.apiClient._enabled) {
|
|
212
|
+
next();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const traceId = randomUUID();
|
|
216
|
+
const startedAt = new Date().toISOString();
|
|
217
|
+
const startMs = Date.now();
|
|
218
|
+
// Resolve the trace name from options or fall back to "METHOD /url".
|
|
219
|
+
const name = typeof options?.name === 'function'
|
|
220
|
+
? options.name(req)
|
|
221
|
+
: options?.name ?? `${req.method ?? 'HTTP'} ${req.url ?? '/'}`;
|
|
222
|
+
// Fire createTrace without awaiting — we own the traceId so spans
|
|
223
|
+
// can be buffered safely until the trace creation lands on the backend.
|
|
224
|
+
// Awaiting here would add a network round-trip to every request.
|
|
225
|
+
this.apiClient.createTrace({
|
|
226
|
+
trace_id: traceId,
|
|
227
|
+
name,
|
|
228
|
+
framework: 'http',
|
|
229
|
+
started_at: startedAt,
|
|
230
|
+
...(this.sessionId ? { session_id: this.sessionId } : {}),
|
|
231
|
+
}).catch(() => { });
|
|
232
|
+
let llmCallCount = 0;
|
|
233
|
+
let toolCallCount = 0;
|
|
234
|
+
let totalInput = 0;
|
|
235
|
+
let totalOutput = 0;
|
|
236
|
+
let totalCost = 0;
|
|
237
|
+
const groupCtx = {
|
|
238
|
+
traceId,
|
|
239
|
+
onLLMSpan: (inputTokens, outputTokens, cost) => {
|
|
240
|
+
llmCallCount++;
|
|
241
|
+
totalInput += inputTokens;
|
|
242
|
+
totalOutput += outputTokens;
|
|
243
|
+
totalCost += cost;
|
|
244
|
+
},
|
|
245
|
+
onToolSpan: () => { toolCallCount++; },
|
|
246
|
+
};
|
|
247
|
+
// Guard against both 'finish' and 'close' firing for the same response.
|
|
248
|
+
// 'finish' fires when all data is written; 'close' fires when the
|
|
249
|
+
// underlying connection is closed (e.g. client disconnected early).
|
|
250
|
+
// We only want to complete the trace once.
|
|
251
|
+
let completed = false;
|
|
252
|
+
const complete = () => {
|
|
253
|
+
if (completed)
|
|
254
|
+
return;
|
|
255
|
+
completed = true;
|
|
256
|
+
const durationMs = Date.now() - startMs;
|
|
257
|
+
// Treat any 4xx/5xx as a failed trace.
|
|
258
|
+
const status = res.statusCode >= 400 ? 'failed' : 'completed';
|
|
259
|
+
// Flush buffered spans before completing the trace so the backend
|
|
260
|
+
// has all spans available when it processes the PATCH request.
|
|
261
|
+
this.batcher.flush();
|
|
262
|
+
this.apiClient.completeTrace(traceId, {
|
|
263
|
+
status,
|
|
264
|
+
ended_at: new Date().toISOString(),
|
|
265
|
+
duration_ms: durationMs,
|
|
266
|
+
llm_call_count: llmCallCount,
|
|
267
|
+
total_cost: parseFloat(totalCost.toFixed(6)),
|
|
268
|
+
total_tokens: totalInput + totalOutput,
|
|
269
|
+
total_input_tokens: totalInput,
|
|
270
|
+
total_output_tokens: totalOutput,
|
|
271
|
+
}).catch(() => { });
|
|
272
|
+
// Only print in debug mode — middleware runs on every request and
|
|
273
|
+
// would produce too much noise in production by default.
|
|
274
|
+
if (this.debug) {
|
|
275
|
+
printTraceSummary({
|
|
276
|
+
name,
|
|
277
|
+
llmCallCount,
|
|
278
|
+
toolCallCount,
|
|
279
|
+
totalTokens: totalInput + totalOutput,
|
|
280
|
+
totalCost,
|
|
281
|
+
durationMs,
|
|
282
|
+
status,
|
|
283
|
+
}, true);
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
// Run next() inside the ALS context so all async operations spawned
|
|
287
|
+
// by the route handler inherit this request's groupCtx automatically.
|
|
288
|
+
activeGroupTraceStorage.run(groupCtx, () => {
|
|
289
|
+
res.on('finish', complete);
|
|
290
|
+
res.on('close', complete);
|
|
291
|
+
next();
|
|
292
|
+
});
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
132
296
|
// flushSpans() — called by shutdown() in index.ts.
|
|
133
297
|
// ---------------------------------------------------------------------------
|
|
134
298
|
flushSpans() {
|
|
@@ -220,19 +384,28 @@ function applyIntegration(client, name, visibe) {
|
|
|
220
384
|
// Integrations are loaded lazily to avoid import errors when the peer
|
|
221
385
|
// dependency is not installed. Each integration module exports a
|
|
222
386
|
// `patchClient(client, name, visibe)` that returns a restore function.
|
|
223
|
-
|
|
387
|
+
// Walk the prototype chain to collect all ancestor class names.
|
|
388
|
+
// This handles subclasses (including our own PatchedOpenAI wrapper) without
|
|
389
|
+
// requiring the direct constructor to have a specific name.
|
|
390
|
+
const ancestorNames = new Set();
|
|
391
|
+
let ctor = client?.constructor;
|
|
392
|
+
while (ctor && ctor.name) {
|
|
393
|
+
ancestorNames.add(ctor.name);
|
|
394
|
+
ctor = Object.getPrototypeOf(ctor);
|
|
395
|
+
}
|
|
396
|
+
const has = (name) => ancestorNames.has(name);
|
|
224
397
|
try {
|
|
225
|
-
if (
|
|
398
|
+
if (has('OpenAI')) {
|
|
226
399
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
227
400
|
const { patchOpenAIClient } = require('./integrations/openai');
|
|
228
401
|
return patchOpenAIClient(client, name, visibe);
|
|
229
402
|
}
|
|
230
|
-
if (
|
|
403
|
+
if (has('Anthropic')) {
|
|
231
404
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
232
405
|
const { patchAnthropicClient } = require('./integrations/anthropic');
|
|
233
406
|
return patchAnthropicClient(client, name, visibe);
|
|
234
407
|
}
|
|
235
|
-
if (
|
|
408
|
+
if (has('BedrockRuntimeClient')) {
|
|
236
409
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
237
410
|
const { patchBedrockClient } = require('./integrations/bedrock');
|
|
238
411
|
return patchBedrockClient(client, name, visibe);
|
package/dist/types/client.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { APIClient, SpanBatcher } from './api';
|
|
2
|
-
import type { InitOptions } from './types';
|
|
2
|
+
import type { InitOptions, MiddlewareOptions, MiddlewareRequest, MiddlewareResponse } from './types';
|
|
3
3
|
export type { InitOptions };
|
|
4
4
|
export declare class Visibe {
|
|
5
5
|
readonly apiClient: APIClient;
|
|
@@ -14,6 +14,8 @@ export declare class Visibe {
|
|
|
14
14
|
}): void;
|
|
15
15
|
uninstrument(client: object): void;
|
|
16
16
|
track<T>(client: object, name: string, fn: () => Promise<T>): Promise<T>;
|
|
17
|
+
runWithSession<T>(name: string, fn: () => Promise<T>): Promise<T>;
|
|
18
|
+
middleware(options?: MiddlewareOptions): (req: MiddlewareRequest, res: MiddlewareResponse, next: () => void) => void;
|
|
17
19
|
flushSpans(): void;
|
|
18
20
|
buildLLMSpan(opts: {
|
|
19
21
|
spanId: string;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export declare function detectFrameworks(): Record<string, boolean>;
|
|
|
4
4
|
export declare function init(options?: InitOptions): Visibe;
|
|
5
5
|
export declare function shutdown(): Promise<void>;
|
|
6
6
|
export { Visibe } from './client';
|
|
7
|
-
export type { InitOptions, TraceSummary, SpanType, SpanStatus, TraceStatus, LLMProvider } from './types';
|
|
7
|
+
export type { InitOptions, MiddlewareOptions, MiddlewareRequest, MiddlewareResponse, TraceSummary, SpanType, SpanStatus, TraceStatus, LLMProvider } from './types';
|
|
@@ -19,3 +19,20 @@ export interface TraceSummary {
|
|
|
19
19
|
durationMs: number;
|
|
20
20
|
status: TraceStatus;
|
|
21
21
|
}
|
|
22
|
+
export interface MiddlewareRequest {
|
|
23
|
+
method?: string;
|
|
24
|
+
url?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface MiddlewareResponse {
|
|
27
|
+
statusCode: number;
|
|
28
|
+
on(event: 'finish' | 'close', listener: () => void): this;
|
|
29
|
+
}
|
|
30
|
+
export interface MiddlewareOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Trace name for each request.
|
|
33
|
+
* - Omit for the default: "METHOD /url" (e.g. "POST /api/chat")
|
|
34
|
+
* - Pass a string for a fixed name
|
|
35
|
+
* - Pass a function to derive the name from the request
|
|
36
|
+
*/
|
|
37
|
+
name?: string | ((req: MiddlewareRequest) => string);
|
|
38
|
+
}
|
package/package.json
CHANGED