@openrouter/sdk 0.3.10 → 0.3.12
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/esm/index.d.ts +1 -0
- package/esm/index.js +2 -0
- package/esm/lib/config.d.ts +4 -2
- package/esm/lib/config.js +2 -2
- package/esm/lib/model-result.d.ts +8 -3
- package/esm/lib/model-result.js +57 -35
- package/esm/lib/tool-event-broadcaster.d.ts +44 -0
- package/esm/lib/tool-event-broadcaster.js +146 -0
- package/esm/lib/tool-executor.d.ts +21 -5
- package/esm/lib/tool-executor.js +58 -7
- package/esm/lib/tool-types.d.ts +17 -17
- package/esm/lib/tool.d.ts +16 -16
- package/jsr.json +1 -1
- package/package.json +6 -7
- package/vitest.config.ts +25 -16
- package/.zed/settings.json +0 -10
package/esm/index.d.ts
CHANGED
|
@@ -17,5 +17,6 @@ export { extractUnsupportedContent, getUnsupportedContentSummary, hasUnsupported
|
|
|
17
17
|
export { tool } from './lib/tool.js';
|
|
18
18
|
export { hasExecuteFunction, isGeneratorTool, isRegularExecuteTool, isToolPreliminaryResultEvent, ToolType, } from './lib/tool-types.js';
|
|
19
19
|
export { buildTurnContext, normalizeInputToArray } from './lib/turn-context.js';
|
|
20
|
+
export { ToolEventBroadcaster } from './lib/tool-event-broadcaster.js';
|
|
20
21
|
export * from './sdk/sdk.js';
|
|
21
22
|
//# sourceMappingURL=index.d.ts.map
|
package/esm/index.js
CHANGED
|
@@ -21,5 +21,7 @@ export { tool } from './lib/tool.js';
|
|
|
21
21
|
export { hasExecuteFunction, isGeneratorTool, isRegularExecuteTool, isToolPreliminaryResultEvent, ToolType, } from './lib/tool-types.js';
|
|
22
22
|
// Turn context helpers
|
|
23
23
|
export { buildTurnContext, normalizeInputToArray } from './lib/turn-context.js';
|
|
24
|
+
// Real-time tool event broadcasting
|
|
25
|
+
export { ToolEventBroadcaster } from './lib/tool-event-broadcaster.js';
|
|
24
26
|
export * from './sdk/sdk.js';
|
|
25
27
|
//# sourceMappingURL=index.js.map
|
package/esm/lib/config.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SDKHooks } from "../hooks/hooks.js";
|
|
1
2
|
import { HTTPClient } from "./http.js";
|
|
2
3
|
import { Logger } from "./logger.js";
|
|
3
4
|
import { RetryConfig } from "./retries.js";
|
|
@@ -40,13 +41,14 @@ export type SDKOptions = {
|
|
|
40
41
|
retryConfig?: RetryConfig;
|
|
41
42
|
timeoutMs?: number;
|
|
42
43
|
debugLogger?: Logger;
|
|
44
|
+
hooks?: SDKHooks;
|
|
43
45
|
};
|
|
44
46
|
export declare function serverURLFromOptions(options: SDKOptions): URL | null;
|
|
45
47
|
export declare const SDK_METADATA: {
|
|
46
48
|
readonly language: "typescript";
|
|
47
49
|
readonly openapiDocVersion: "1.0.0";
|
|
48
|
-
readonly sdkVersion: "0.3.
|
|
50
|
+
readonly sdkVersion: "0.3.12";
|
|
49
51
|
readonly genVersion: "2.788.4";
|
|
50
|
-
readonly userAgent: "speakeasy-sdk/typescript 0.3.
|
|
52
|
+
readonly userAgent: "speakeasy-sdk/typescript 0.3.12 2.788.4 1.0.0 @openrouter/sdk";
|
|
51
53
|
};
|
|
52
54
|
//# sourceMappingURL=config.d.ts.map
|
package/esm/lib/config.js
CHANGED
|
@@ -26,8 +26,8 @@ export function serverURLFromOptions(options) {
|
|
|
26
26
|
export const SDK_METADATA = {
|
|
27
27
|
language: "typescript",
|
|
28
28
|
openapiDocVersion: "1.0.0",
|
|
29
|
-
sdkVersion: "0.3.
|
|
29
|
+
sdkVersion: "0.3.12",
|
|
30
30
|
genVersion: "2.788.4",
|
|
31
|
-
userAgent: "speakeasy-sdk/typescript 0.3.
|
|
31
|
+
userAgent: "speakeasy-sdk/typescript 0.3.12 2.788.4 1.0.0 @openrouter/sdk",
|
|
32
32
|
};
|
|
33
33
|
//# sourceMappingURL=config.js.map
|
|
@@ -37,10 +37,15 @@ export declare class ModelResult<TTools extends readonly Tool[]> {
|
|
|
37
37
|
private initPromise;
|
|
38
38
|
private toolExecutionPromise;
|
|
39
39
|
private finalResponse;
|
|
40
|
-
private
|
|
40
|
+
private toolEventBroadcaster;
|
|
41
41
|
private allToolExecutionRounds;
|
|
42
42
|
private resolvedRequest;
|
|
43
43
|
constructor(options: GetResponseOptions<TTools>);
|
|
44
|
+
/**
|
|
45
|
+
* Get or create the tool event broadcaster (lazy initialization).
|
|
46
|
+
* Ensures only one broadcaster exists for the lifetime of this ModelResult.
|
|
47
|
+
*/
|
|
48
|
+
private ensureBroadcaster;
|
|
44
49
|
/**
|
|
45
50
|
* Type guard to check if a value is a non-streaming response
|
|
46
51
|
*/
|
|
@@ -73,7 +78,7 @@ export declare class ModelResult<TTools extends readonly Tool[]> {
|
|
|
73
78
|
/**
|
|
74
79
|
* Stream all response events as they arrive.
|
|
75
80
|
* Multiple consumers can iterate over this stream concurrently.
|
|
76
|
-
*
|
|
81
|
+
* Preliminary tool results are streamed in REAL-TIME as generator tools yield.
|
|
77
82
|
*/
|
|
78
83
|
getFullResponsesStream(): AsyncIterableIterator<ResponseStreamEvent<InferToolEventsUnion<TTools>>>;
|
|
79
84
|
/**
|
|
@@ -95,7 +100,7 @@ export declare class ModelResult<TTools extends readonly Tool[]> {
|
|
|
95
100
|
getReasoningStream(): AsyncIterableIterator<string>;
|
|
96
101
|
/**
|
|
97
102
|
* Stream tool call argument deltas and preliminary results.
|
|
98
|
-
*
|
|
103
|
+
* Preliminary results are streamed in REAL-TIME as generator tools yield.
|
|
99
104
|
* - Tool call argument deltas as { type: "delta", content: string }
|
|
100
105
|
* - Preliminary results as { type: "preliminary_result", toolCallId, result }
|
|
101
106
|
*/
|
package/esm/lib/model-result.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ToolEventBroadcaster } from './tool-event-broadcaster.js';
|
|
1
2
|
import { betaResponsesSend } from '../funcs/betaResponsesSend.js';
|
|
2
3
|
import { hasAsyncFunctions, resolveAsyncFunctions, } from './async-params.js';
|
|
3
4
|
import { ReusableReadableStream } from './reusable-stream.js';
|
|
@@ -51,12 +52,22 @@ export class ModelResult {
|
|
|
51
52
|
this.initPromise = null;
|
|
52
53
|
this.toolExecutionPromise = null;
|
|
53
54
|
this.finalResponse = null;
|
|
54
|
-
this.
|
|
55
|
+
this.toolEventBroadcaster = null;
|
|
55
56
|
this.allToolExecutionRounds = [];
|
|
56
57
|
// Track resolved request after async function resolution
|
|
57
58
|
this.resolvedRequest = null;
|
|
58
59
|
this.options = options;
|
|
59
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Get or create the tool event broadcaster (lazy initialization).
|
|
63
|
+
* Ensures only one broadcaster exists for the lifetime of this ModelResult.
|
|
64
|
+
*/
|
|
65
|
+
ensureBroadcaster() {
|
|
66
|
+
if (!this.toolEventBroadcaster) {
|
|
67
|
+
this.toolEventBroadcaster = new ToolEventBroadcaster();
|
|
68
|
+
}
|
|
69
|
+
return this.toolEventBroadcaster;
|
|
70
|
+
}
|
|
60
71
|
/**
|
|
61
72
|
* Type guard to check if a value is a non-streaming response
|
|
62
73
|
*/
|
|
@@ -91,8 +102,7 @@ export class ModelResult {
|
|
|
91
102
|
// Already resolved, extract non-function fields
|
|
92
103
|
// Since request is CallModelInput, we need to filter out stopWhen
|
|
93
104
|
// Note: tools are already in API format at this point (converted in callModel())
|
|
94
|
-
|
|
95
|
-
const { stopWhen, ...rest } = this.options.request;
|
|
105
|
+
const { stopWhen: _, ...rest } = this.options.request;
|
|
96
106
|
// Cast to ResolvedCallModelInput - we know it's resolved if hasAsyncFunctions returned false
|
|
97
107
|
baseRequest = rest;
|
|
98
108
|
}
|
|
@@ -215,11 +225,17 @@ export class ModelResult {
|
|
|
215
225
|
if (!tool || !hasExecuteFunction(tool)) {
|
|
216
226
|
continue;
|
|
217
227
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
// Create callback for real-time preliminary results
|
|
229
|
+
const onPreliminaryResult = this.toolEventBroadcaster
|
|
230
|
+
? (callId, resultValue) => {
|
|
231
|
+
this.toolEventBroadcaster?.push({
|
|
232
|
+
type: 'preliminary_result',
|
|
233
|
+
toolCallId: callId,
|
|
234
|
+
result: resultValue,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
: undefined;
|
|
238
|
+
const result = await executeTool(tool, toolCall, turnContext, onPreliminaryResult);
|
|
223
239
|
toolResults.push({
|
|
224
240
|
type: 'function_call_output',
|
|
225
241
|
id: `output_${toolCall.id}`,
|
|
@@ -335,7 +351,7 @@ export class ModelResult {
|
|
|
335
351
|
/**
|
|
336
352
|
* Stream all response events as they arrive.
|
|
337
353
|
* Multiple consumers can iterate over this stream concurrently.
|
|
338
|
-
*
|
|
354
|
+
* Preliminary tool results are streamed in REAL-TIME as generator tools yield.
|
|
339
355
|
*/
|
|
340
356
|
getFullResponsesStream() {
|
|
341
357
|
return async function* () {
|
|
@@ -343,24 +359,29 @@ export class ModelResult {
|
|
|
343
359
|
if (!this.reusableStream) {
|
|
344
360
|
throw new Error('Stream not initialized');
|
|
345
361
|
}
|
|
362
|
+
// Get or create broadcaster for real-time tool events (lazy init prevents race conditions)
|
|
363
|
+
const broadcaster = this.ensureBroadcaster();
|
|
364
|
+
const toolEventConsumer = broadcaster.createConsumer();
|
|
365
|
+
// Start tool execution in background (completes broadcaster when done)
|
|
366
|
+
const executionPromise = this.executeToolsIfNeeded().finally(() => {
|
|
367
|
+
broadcaster.complete();
|
|
368
|
+
});
|
|
346
369
|
const consumer = this.reusableStream.createConsumer();
|
|
347
|
-
// Yield original events
|
|
370
|
+
// Yield original API events
|
|
348
371
|
for await (const event of consumer) {
|
|
349
372
|
yield event;
|
|
350
373
|
}
|
|
351
|
-
//
|
|
352
|
-
await
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
result: result,
|
|
360
|
-
timestamp: Date.now(),
|
|
361
|
-
};
|
|
362
|
-
}
|
|
374
|
+
// Yield tool preliminary results as they arrive (real-time!)
|
|
375
|
+
for await (const event of toolEventConsumer) {
|
|
376
|
+
yield {
|
|
377
|
+
type: 'tool.preliminary_result',
|
|
378
|
+
toolCallId: event.toolCallId,
|
|
379
|
+
result: event.result,
|
|
380
|
+
timestamp: Date.now(),
|
|
381
|
+
};
|
|
363
382
|
}
|
|
383
|
+
// Ensure execution completed (handles errors)
|
|
384
|
+
await executionPromise;
|
|
364
385
|
}.call(this);
|
|
365
386
|
}
|
|
366
387
|
/**
|
|
@@ -423,7 +444,7 @@ export class ModelResult {
|
|
|
423
444
|
}
|
|
424
445
|
/**
|
|
425
446
|
* Stream tool call argument deltas and preliminary results.
|
|
426
|
-
*
|
|
447
|
+
* Preliminary results are streamed in REAL-TIME as generator tools yield.
|
|
427
448
|
* - Tool call argument deltas as { type: "delta", content: string }
|
|
428
449
|
* - Preliminary results as { type: "preliminary_result", toolCallId, result }
|
|
429
450
|
*/
|
|
@@ -433,25 +454,26 @@ export class ModelResult {
|
|
|
433
454
|
if (!this.reusableStream) {
|
|
434
455
|
throw new Error('Stream not initialized');
|
|
435
456
|
}
|
|
436
|
-
//
|
|
457
|
+
// Get or create broadcaster for real-time tool events (lazy init prevents race conditions)
|
|
458
|
+
const broadcaster = this.ensureBroadcaster();
|
|
459
|
+
const toolEventConsumer = broadcaster.createConsumer();
|
|
460
|
+
// Start tool execution in background (completes broadcaster when done)
|
|
461
|
+
const executionPromise = this.executeToolsIfNeeded().finally(() => {
|
|
462
|
+
broadcaster.complete();
|
|
463
|
+
});
|
|
464
|
+
// Yield tool deltas from API stream
|
|
437
465
|
for await (const delta of extractToolDeltas(this.reusableStream)) {
|
|
438
466
|
yield {
|
|
439
467
|
type: 'delta',
|
|
440
468
|
content: delta,
|
|
441
469
|
};
|
|
442
470
|
}
|
|
443
|
-
//
|
|
444
|
-
await
|
|
445
|
-
|
|
446
|
-
for (const [toolCallId, results] of this.preliminaryResults) {
|
|
447
|
-
for (const result of results) {
|
|
448
|
-
yield {
|
|
449
|
-
type: 'preliminary_result',
|
|
450
|
-
toolCallId,
|
|
451
|
-
result: result,
|
|
452
|
-
};
|
|
453
|
-
}
|
|
471
|
+
// Yield tool events as they arrive (real-time!)
|
|
472
|
+
for await (const event of toolEventConsumer) {
|
|
473
|
+
yield event;
|
|
454
474
|
}
|
|
475
|
+
// Ensure execution completed (handles errors)
|
|
476
|
+
await executionPromise;
|
|
455
477
|
}.call(this);
|
|
456
478
|
}
|
|
457
479
|
/**
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A push-based event broadcaster that supports multiple concurrent consumers.
|
|
3
|
+
* Similar to ReusableReadableStream but for push-based events from tool execution.
|
|
4
|
+
*
|
|
5
|
+
* Each consumer gets their own position in the buffer and receives all events
|
|
6
|
+
* from their join point onward. This enables real-time streaming of generator
|
|
7
|
+
* tool preliminary results to multiple consumers simultaneously.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The event type being broadcast
|
|
10
|
+
*/
|
|
11
|
+
export declare class ToolEventBroadcaster<T> {
|
|
12
|
+
private buffer;
|
|
13
|
+
private consumers;
|
|
14
|
+
private nextConsumerId;
|
|
15
|
+
private isComplete;
|
|
16
|
+
private completionError;
|
|
17
|
+
/**
|
|
18
|
+
* Push a new event to all consumers.
|
|
19
|
+
* Events are buffered so late-joining consumers can catch up.
|
|
20
|
+
*/
|
|
21
|
+
push(event: T): void;
|
|
22
|
+
/**
|
|
23
|
+
* Mark the broadcaster as complete - no more events will be pushed.
|
|
24
|
+
* Optionally pass an error to signal failure to all consumers.
|
|
25
|
+
* Cleans up buffer and consumers after completion.
|
|
26
|
+
*/
|
|
27
|
+
complete(error?: Error): void;
|
|
28
|
+
/**
|
|
29
|
+
* Clean up resources after all consumers have finished.
|
|
30
|
+
* Called automatically after complete(), but can be called manually.
|
|
31
|
+
*/
|
|
32
|
+
private cleanup;
|
|
33
|
+
/**
|
|
34
|
+
* Create a new consumer that can independently iterate over events.
|
|
35
|
+
* Consumers can join at any time and will receive events from position 0.
|
|
36
|
+
* Multiple consumers can be created and will all receive the same events.
|
|
37
|
+
*/
|
|
38
|
+
createConsumer(): AsyncIterableIterator<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Notify all waiting consumers that new data is available or stream completed
|
|
41
|
+
*/
|
|
42
|
+
private notifyWaitingConsumers;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=tool-event-broadcaster.d.ts.map
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A push-based event broadcaster that supports multiple concurrent consumers.
|
|
3
|
+
* Similar to ReusableReadableStream but for push-based events from tool execution.
|
|
4
|
+
*
|
|
5
|
+
* Each consumer gets their own position in the buffer and receives all events
|
|
6
|
+
* from their join point onward. This enables real-time streaming of generator
|
|
7
|
+
* tool preliminary results to multiple consumers simultaneously.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The event type being broadcast
|
|
10
|
+
*/
|
|
11
|
+
export class ToolEventBroadcaster {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.buffer = [];
|
|
14
|
+
this.consumers = new Map();
|
|
15
|
+
this.nextConsumerId = 0;
|
|
16
|
+
this.isComplete = false;
|
|
17
|
+
this.completionError = null;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Push a new event to all consumers.
|
|
21
|
+
* Events are buffered so late-joining consumers can catch up.
|
|
22
|
+
*/
|
|
23
|
+
push(event) {
|
|
24
|
+
if (this.isComplete) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.buffer.push(event);
|
|
28
|
+
this.notifyWaitingConsumers();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Mark the broadcaster as complete - no more events will be pushed.
|
|
32
|
+
* Optionally pass an error to signal failure to all consumers.
|
|
33
|
+
* Cleans up buffer and consumers after completion.
|
|
34
|
+
*/
|
|
35
|
+
complete(error) {
|
|
36
|
+
this.isComplete = true;
|
|
37
|
+
this.completionError = error ?? null;
|
|
38
|
+
this.notifyWaitingConsumers();
|
|
39
|
+
// Schedule cleanup after consumers have processed completion
|
|
40
|
+
queueMicrotask(() => this.cleanup());
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Clean up resources after all consumers have finished.
|
|
44
|
+
* Called automatically after complete(), but can be called manually.
|
|
45
|
+
*/
|
|
46
|
+
cleanup() {
|
|
47
|
+
// Only cleanup if complete and all consumers are done
|
|
48
|
+
if (this.isComplete && this.consumers.size === 0) {
|
|
49
|
+
this.buffer = [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a new consumer that can independently iterate over events.
|
|
54
|
+
* Consumers can join at any time and will receive events from position 0.
|
|
55
|
+
* Multiple consumers can be created and will all receive the same events.
|
|
56
|
+
*/
|
|
57
|
+
createConsumer() {
|
|
58
|
+
const consumerId = this.nextConsumerId++;
|
|
59
|
+
const state = {
|
|
60
|
+
position: 0,
|
|
61
|
+
waitingPromise: null,
|
|
62
|
+
cancelled: false,
|
|
63
|
+
};
|
|
64
|
+
this.consumers.set(consumerId, state);
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
66
|
+
const self = this;
|
|
67
|
+
return {
|
|
68
|
+
async next() {
|
|
69
|
+
const consumer = self.consumers.get(consumerId);
|
|
70
|
+
if (!consumer) {
|
|
71
|
+
return { done: true, value: undefined };
|
|
72
|
+
}
|
|
73
|
+
if (consumer.cancelled) {
|
|
74
|
+
return { done: true, value: undefined };
|
|
75
|
+
}
|
|
76
|
+
// Return buffered event if available
|
|
77
|
+
if (consumer.position < self.buffer.length) {
|
|
78
|
+
const value = self.buffer[consumer.position];
|
|
79
|
+
consumer.position++;
|
|
80
|
+
return { done: false, value };
|
|
81
|
+
}
|
|
82
|
+
// If complete and caught up, we're done
|
|
83
|
+
if (self.isComplete) {
|
|
84
|
+
self.consumers.delete(consumerId);
|
|
85
|
+
self.cleanup();
|
|
86
|
+
if (self.completionError) {
|
|
87
|
+
throw self.completionError;
|
|
88
|
+
}
|
|
89
|
+
return { done: true, value: undefined };
|
|
90
|
+
}
|
|
91
|
+
// Set up waiting promise FIRST to avoid race condition
|
|
92
|
+
const waitPromise = new Promise((resolve, reject) => {
|
|
93
|
+
consumer.waitingPromise = { resolve, reject };
|
|
94
|
+
// Immediately check if we should resolve after setting up promise
|
|
95
|
+
if (self.isComplete ||
|
|
96
|
+
self.completionError ||
|
|
97
|
+
consumer.position < self.buffer.length) {
|
|
98
|
+
resolve();
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
await waitPromise;
|
|
102
|
+
consumer.waitingPromise = null;
|
|
103
|
+
// Recursively try again after waking up
|
|
104
|
+
return this.next();
|
|
105
|
+
},
|
|
106
|
+
async return() {
|
|
107
|
+
const consumer = self.consumers.get(consumerId);
|
|
108
|
+
if (consumer) {
|
|
109
|
+
consumer.cancelled = true;
|
|
110
|
+
self.consumers.delete(consumerId);
|
|
111
|
+
self.cleanup();
|
|
112
|
+
}
|
|
113
|
+
return { done: true, value: undefined };
|
|
114
|
+
},
|
|
115
|
+
async throw(e) {
|
|
116
|
+
const consumer = self.consumers.get(consumerId);
|
|
117
|
+
if (consumer) {
|
|
118
|
+
consumer.cancelled = true;
|
|
119
|
+
self.consumers.delete(consumerId);
|
|
120
|
+
self.cleanup();
|
|
121
|
+
}
|
|
122
|
+
throw e;
|
|
123
|
+
},
|
|
124
|
+
[Symbol.asyncIterator]() {
|
|
125
|
+
return this;
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Notify all waiting consumers that new data is available or stream completed
|
|
131
|
+
*/
|
|
132
|
+
notifyWaitingConsumers() {
|
|
133
|
+
for (const consumer of this.consumers.values()) {
|
|
134
|
+
if (consumer.waitingPromise) {
|
|
135
|
+
if (this.completionError) {
|
|
136
|
+
consumer.waitingPromise.reject(this.completionError);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
consumer.waitingPromise.resolve();
|
|
140
|
+
}
|
|
141
|
+
consumer.waitingPromise = null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=tool-event-broadcaster.js.map
|
|
@@ -1,9 +1,25 @@
|
|
|
1
|
-
import type { ZodType } from 'zod/v4';
|
|
1
|
+
import type { $ZodType } from 'zod/v4/core';
|
|
2
2
|
import type { APITool, Tool, ParsedToolCall, ToolExecutionResult, TurnContext } from './tool-types.js';
|
|
3
|
+
import * as z4 from 'zod/v4';
|
|
4
|
+
export declare const ZodError: z4.z.core.$constructor<z4.ZodError<unknown>, z4.z.core.$ZodIssue[]>;
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
6
|
+
* Recursively remove keys prefixed with ~ from an object.
|
|
7
|
+
* These are metadata properties (like ~standard from Standard Schema)
|
|
8
|
+
* that should not be sent to downstream providers.
|
|
9
|
+
* @see https://github.com/OpenRouterTeam/typescript-sdk/issues/131
|
|
10
|
+
*
|
|
11
|
+
* When given a Record<string, unknown>, returns Record<string, unknown>.
|
|
12
|
+
* When given unknown, returns unknown (preserves primitives, null, etc).
|
|
5
13
|
*/
|
|
6
|
-
export declare function
|
|
14
|
+
export declare function sanitizeJsonSchema(obj: Record<string, unknown>): Record<string, unknown>;
|
|
15
|
+
export declare function sanitizeJsonSchema(obj: unknown): unknown;
|
|
16
|
+
/**
|
|
17
|
+
* Convert a Zod schema to JSON Schema using Zod v4's toJSONSchema function.
|
|
18
|
+
* Accepts ZodType from the main zod package for user compatibility.
|
|
19
|
+
* The resulting schema is sanitized to remove metadata properties (like ~standard)
|
|
20
|
+
* that would cause 400 errors with downstream providers.
|
|
21
|
+
*/
|
|
22
|
+
export declare function convertZodToJsonSchema(zodSchema: $ZodType): Record<string, unknown>;
|
|
7
23
|
/**
|
|
8
24
|
* Convert tools to OpenRouter API format
|
|
9
25
|
* Accepts readonly arrays for better type compatibility
|
|
@@ -13,12 +29,12 @@ export declare function convertToolsToAPIFormat(tools: readonly Tool[]): APITool
|
|
|
13
29
|
* Validate tool input against Zod schema
|
|
14
30
|
* @throws ZodError if validation fails
|
|
15
31
|
*/
|
|
16
|
-
export declare function validateToolInput<T>(schema: ZodType<T>, args: unknown): T;
|
|
32
|
+
export declare function validateToolInput<T>(schema: $ZodType<T>, args: unknown): T;
|
|
17
33
|
/**
|
|
18
34
|
* Validate tool output against Zod schema
|
|
19
35
|
* @throws ZodError if validation fails
|
|
20
36
|
*/
|
|
21
|
-
export declare function validateToolOutput<T>(schema: ZodType<T>, result: unknown): T;
|
|
37
|
+
export declare function validateToolOutput<T>(schema: $ZodType<T>, result: unknown): T;
|
|
22
38
|
/**
|
|
23
39
|
* Parse tool call arguments from JSON string
|
|
24
40
|
*/
|
package/esm/lib/tool-executor.js
CHANGED
|
@@ -1,13 +1,64 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as z4 from 'zod/v4';
|
|
2
2
|
import { hasExecuteFunction, isGeneratorTool, isRegularExecuteTool } from './tool-types.js';
|
|
3
|
+
// Re-export ZodError for convenience
|
|
4
|
+
export const ZodError = z4.ZodError;
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
6
|
+
* Typeguard to check if a value is a non-null object (not an array).
|
|
7
|
+
*/
|
|
8
|
+
function isNonNullObject(value) {
|
|
9
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
export function sanitizeJsonSchema(obj) {
|
|
12
|
+
if (obj === null || typeof obj !== 'object') {
|
|
13
|
+
return obj;
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(obj)) {
|
|
16
|
+
return obj.map(sanitizeJsonSchema);
|
|
17
|
+
}
|
|
18
|
+
// At this point, obj is a non-null, non-array object
|
|
19
|
+
// Use typeguard to narrow the type for type-safe property access
|
|
20
|
+
if (!isNonNullObject(obj)) {
|
|
21
|
+
return obj;
|
|
22
|
+
}
|
|
23
|
+
const result = {};
|
|
24
|
+
for (const key of Object.keys(obj)) {
|
|
25
|
+
if (!key.startsWith('~')) {
|
|
26
|
+
result[key] = sanitizeJsonSchema(obj[key]);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Typeguard to check if a value is a valid Zod schema compatible with zod/v4.
|
|
33
|
+
* Zod schemas have a _zod property that contains schema metadata.
|
|
34
|
+
*/
|
|
35
|
+
function isZodSchema(value) {
|
|
36
|
+
if (typeof value !== 'object' || value === null) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (!('_zod' in value)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
// After the 'in' check, TypeScript knows value has _zod property
|
|
43
|
+
return typeof value._zod === 'object';
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Convert a Zod schema to JSON Schema using Zod v4's toJSONSchema function.
|
|
47
|
+
* Accepts ZodType from the main zod package for user compatibility.
|
|
48
|
+
* The resulting schema is sanitized to remove metadata properties (like ~standard)
|
|
49
|
+
* that would cause 400 errors with downstream providers.
|
|
5
50
|
*/
|
|
6
51
|
export function convertZodToJsonSchema(zodSchema) {
|
|
7
|
-
|
|
8
|
-
|
|
52
|
+
if (!isZodSchema(zodSchema)) {
|
|
53
|
+
throw new Error('Invalid Zod schema provided');
|
|
54
|
+
}
|
|
55
|
+
// Use draft-7 as it's closest to OpenAPI 3.0's JSON Schema variant
|
|
56
|
+
const jsonSchema = z4.toJSONSchema(zodSchema, {
|
|
57
|
+
target: 'draft-7',
|
|
9
58
|
});
|
|
10
|
-
|
|
59
|
+
// jsonSchema is always a Record<string, unknown> from toJSONSchema
|
|
60
|
+
// The overloaded sanitizeJsonSchema preserves this type
|
|
61
|
+
return sanitizeJsonSchema(jsonSchema);
|
|
11
62
|
}
|
|
12
63
|
/**
|
|
13
64
|
* Convert tools to OpenRouter API format
|
|
@@ -27,14 +78,14 @@ export function convertToolsToAPIFormat(tools) {
|
|
|
27
78
|
* @throws ZodError if validation fails
|
|
28
79
|
*/
|
|
29
80
|
export function validateToolInput(schema, args) {
|
|
30
|
-
return
|
|
81
|
+
return z4.parse(schema, args);
|
|
31
82
|
}
|
|
32
83
|
/**
|
|
33
84
|
* Validate tool output against Zod schema
|
|
34
85
|
* @throws ZodError if validation fails
|
|
35
86
|
*/
|
|
36
87
|
export function validateToolOutput(schema, result) {
|
|
37
|
-
return
|
|
88
|
+
return z4.parse(schema, result);
|
|
38
89
|
}
|
|
39
90
|
/**
|
|
40
91
|
* Parse tool call arguments from JSON string
|
package/esm/lib/tool-types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ZodObject,
|
|
1
|
+
import type { $ZodObject, $ZodShape, $ZodType, infer as zodInfer } from 'zod/v4/core';
|
|
2
2
|
import type * as models from '../models/index.js';
|
|
3
3
|
import type { OpenResponsesStreamEvent } from '../models/index.js';
|
|
4
4
|
import type { ModelResult } from './model-result.js';
|
|
@@ -53,18 +53,18 @@ export type NextTurnParamsFunctions<TInput> = {
|
|
|
53
53
|
/**
|
|
54
54
|
* Base tool function interface with inputSchema
|
|
55
55
|
*/
|
|
56
|
-
export interface BaseToolFunction<TInput extends ZodObject
|
|
56
|
+
export interface BaseToolFunction<TInput extends $ZodObject<$ZodShape>> {
|
|
57
57
|
name: string;
|
|
58
58
|
description?: string;
|
|
59
59
|
inputSchema: TInput;
|
|
60
|
-
nextTurnParams?: NextTurnParamsFunctions<
|
|
60
|
+
nextTurnParams?: NextTurnParamsFunctions<zodInfer<TInput>>;
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
63
|
* Regular tool with synchronous or asynchronous execute function and optional outputSchema
|
|
64
64
|
*/
|
|
65
|
-
export interface ToolFunctionWithExecute<TInput extends ZodObject
|
|
65
|
+
export interface ToolFunctionWithExecute<TInput extends $ZodObject<$ZodShape>, TOutput extends $ZodType = $ZodType<unknown>> extends BaseToolFunction<TInput> {
|
|
66
66
|
outputSchema?: TOutput;
|
|
67
|
-
execute: (params:
|
|
67
|
+
execute: (params: zodInfer<TInput>, context?: TurnContext) => Promise<zodInfer<TOutput>> | zodInfer<TOutput>;
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
70
|
* Generator-based tool with async generator execute function
|
|
@@ -88,42 +88,42 @@ export interface ToolFunctionWithExecute<TInput extends ZodObject<ZodRawShape>,
|
|
|
88
88
|
* }
|
|
89
89
|
* ```
|
|
90
90
|
*/
|
|
91
|
-
export interface ToolFunctionWithGenerator<TInput extends ZodObject
|
|
91
|
+
export interface ToolFunctionWithGenerator<TInput extends $ZodObject<$ZodShape>, TEvent extends $ZodType = $ZodType<unknown>, TOutput extends $ZodType = $ZodType<unknown>> extends BaseToolFunction<TInput> {
|
|
92
92
|
eventSchema: TEvent;
|
|
93
93
|
outputSchema: TOutput;
|
|
94
|
-
execute: (params:
|
|
94
|
+
execute: (params: zodInfer<TInput>, context?: TurnContext) => AsyncGenerator<zodInfer<TEvent> | zodInfer<TOutput>>;
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
97
|
* Manual tool without execute function - requires manual handling by developer
|
|
98
98
|
*/
|
|
99
|
-
export interface ManualToolFunction<TInput extends ZodObject
|
|
99
|
+
export interface ManualToolFunction<TInput extends $ZodObject<$ZodShape>, TOutput extends $ZodType = $ZodType<unknown>> extends BaseToolFunction<TInput> {
|
|
100
100
|
outputSchema?: TOutput;
|
|
101
101
|
}
|
|
102
102
|
/**
|
|
103
103
|
* Tool with execute function (regular or generator)
|
|
104
104
|
*/
|
|
105
|
-
export type ToolWithExecute<TInput extends ZodObject
|
|
105
|
+
export type ToolWithExecute<TInput extends $ZodObject<$ZodShape> = $ZodObject<$ZodShape>, TOutput extends $ZodType = $ZodType<unknown>> = {
|
|
106
106
|
type: ToolType.Function;
|
|
107
107
|
function: ToolFunctionWithExecute<TInput, TOutput>;
|
|
108
108
|
};
|
|
109
109
|
/**
|
|
110
110
|
* Tool with generator execute function
|
|
111
111
|
*/
|
|
112
|
-
export type ToolWithGenerator<TInput extends ZodObject
|
|
112
|
+
export type ToolWithGenerator<TInput extends $ZodObject<$ZodShape> = $ZodObject<$ZodShape>, TEvent extends $ZodType = $ZodType<unknown>, TOutput extends $ZodType = $ZodType<unknown>> = {
|
|
113
113
|
type: ToolType.Function;
|
|
114
114
|
function: ToolFunctionWithGenerator<TInput, TEvent, TOutput>;
|
|
115
115
|
};
|
|
116
116
|
/**
|
|
117
117
|
* Tool without execute function (manual handling)
|
|
118
118
|
*/
|
|
119
|
-
export type ManualTool<TInput extends ZodObject
|
|
119
|
+
export type ManualTool<TInput extends $ZodObject<$ZodShape> = $ZodObject<$ZodShape>, TOutput extends $ZodType = $ZodType<unknown>> = {
|
|
120
120
|
type: ToolType.Function;
|
|
121
121
|
function: ManualToolFunction<TInput, TOutput>;
|
|
122
122
|
};
|
|
123
123
|
/**
|
|
124
124
|
* Union type of all enhanced tool types
|
|
125
125
|
*/
|
|
126
|
-
export type Tool = ToolWithExecute
|
|
126
|
+
export type Tool = ToolWithExecute<$ZodObject<$ZodShape>, $ZodType<unknown>> | ToolWithGenerator<$ZodObject<$ZodShape>, $ZodType<unknown>, $ZodType<unknown>> | ManualTool<$ZodObject<$ZodShape>, $ZodType<unknown>>;
|
|
127
127
|
/**
|
|
128
128
|
* Extracts the input type from a tool definition
|
|
129
129
|
*/
|
|
@@ -131,7 +131,7 @@ export type InferToolInput<T> = T extends {
|
|
|
131
131
|
function: {
|
|
132
132
|
inputSchema: infer S;
|
|
133
133
|
};
|
|
134
|
-
} ? S extends ZodType ?
|
|
134
|
+
} ? S extends $ZodType ? zodInfer<S> : unknown : unknown;
|
|
135
135
|
/**
|
|
136
136
|
* Extracts the output type from a tool definition
|
|
137
137
|
*/
|
|
@@ -139,7 +139,7 @@ export type InferToolOutput<T> = T extends {
|
|
|
139
139
|
function: {
|
|
140
140
|
outputSchema: infer S;
|
|
141
141
|
};
|
|
142
|
-
} ? S extends ZodType ?
|
|
142
|
+
} ? S extends $ZodType ? zodInfer<S> : unknown : unknown;
|
|
143
143
|
/**
|
|
144
144
|
* A tool call with typed arguments based on the tool's inputSchema
|
|
145
145
|
*/
|
|
@@ -172,7 +172,7 @@ export type InferToolEvent<T> = T extends {
|
|
|
172
172
|
function: {
|
|
173
173
|
eventSchema: infer S;
|
|
174
174
|
};
|
|
175
|
-
} ? S extends ZodType ?
|
|
175
|
+
} ? S extends $ZodType ? zodInfer<S> : never : never;
|
|
176
176
|
/**
|
|
177
177
|
* Union of event types for all generator tools in a tuple
|
|
178
178
|
* Filters out non-generator tools (which return `never`)
|
|
@@ -216,8 +216,8 @@ export interface ParsedToolCall<T extends Tool> {
|
|
|
216
216
|
export interface ToolExecutionResult<T extends Tool> {
|
|
217
217
|
toolCallId: string;
|
|
218
218
|
toolName: string;
|
|
219
|
-
result: T extends ToolWithExecute<any, infer O> | ToolWithGenerator<any, any, infer O> ?
|
|
220
|
-
preliminaryResults?: T extends ToolWithGenerator<any, infer E, any> ?
|
|
219
|
+
result: T extends ToolWithExecute<any, infer O> | ToolWithGenerator<any, any, infer O> ? zodInfer<O> : unknown;
|
|
220
|
+
preliminaryResults?: T extends ToolWithGenerator<any, infer E, any> ? zodInfer<E>[] : undefined;
|
|
221
221
|
error?: Error;
|
|
222
222
|
}
|
|
223
223
|
/**
|
package/esm/lib/tool.d.ts
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
import type { ZodObject,
|
|
1
|
+
import type { $ZodObject, $ZodShape, $ZodType, infer as zodInfer } from 'zod/v4/core';
|
|
2
2
|
import { type TurnContext, type ToolWithExecute, type ToolWithGenerator, type ManualTool, type NextTurnParamsFunctions } from "./tool-types.js";
|
|
3
3
|
/**
|
|
4
4
|
* Configuration for a regular tool with outputSchema
|
|
5
5
|
*/
|
|
6
|
-
type RegularToolConfigWithOutput<TInput extends ZodObject
|
|
6
|
+
type RegularToolConfigWithOutput<TInput extends $ZodObject<$ZodShape>, TOutput extends $ZodType> = {
|
|
7
7
|
name: string;
|
|
8
8
|
description?: string;
|
|
9
9
|
inputSchema: TInput;
|
|
10
10
|
outputSchema: TOutput;
|
|
11
11
|
eventSchema?: undefined;
|
|
12
|
-
nextTurnParams?: NextTurnParamsFunctions<
|
|
13
|
-
execute: (params:
|
|
12
|
+
nextTurnParams?: NextTurnParamsFunctions<zodInfer<TInput>>;
|
|
13
|
+
execute: (params: zodInfer<TInput>, context?: TurnContext) => Promise<zodInfer<TOutput>> | zodInfer<TOutput>;
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
16
|
* Configuration for a regular tool without outputSchema (infers return type from execute)
|
|
17
17
|
*/
|
|
18
|
-
type RegularToolConfigWithoutOutput<TInput extends ZodObject
|
|
18
|
+
type RegularToolConfigWithoutOutput<TInput extends $ZodObject<$ZodShape>, TReturn> = {
|
|
19
19
|
name: string;
|
|
20
20
|
description?: string;
|
|
21
21
|
inputSchema: TInput;
|
|
22
22
|
outputSchema?: undefined;
|
|
23
23
|
eventSchema?: undefined;
|
|
24
|
-
nextTurnParams?: NextTurnParamsFunctions<
|
|
25
|
-
execute: (params:
|
|
24
|
+
nextTurnParams?: NextTurnParamsFunctions<zodInfer<TInput>>;
|
|
25
|
+
execute: (params: zodInfer<TInput>, context?: TurnContext) => Promise<TReturn> | TReturn;
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
28
28
|
* Configuration for a generator tool (with eventSchema)
|
|
29
29
|
*/
|
|
30
|
-
type GeneratorToolConfig<TInput extends ZodObject
|
|
30
|
+
type GeneratorToolConfig<TInput extends $ZodObject<$ZodShape>, TEvent extends $ZodType, TOutput extends $ZodType> = {
|
|
31
31
|
name: string;
|
|
32
32
|
description?: string;
|
|
33
33
|
inputSchema: TInput;
|
|
34
34
|
eventSchema: TEvent;
|
|
35
35
|
outputSchema: TOutput;
|
|
36
|
-
nextTurnParams?: NextTurnParamsFunctions<
|
|
37
|
-
execute: (params:
|
|
36
|
+
nextTurnParams?: NextTurnParamsFunctions<zodInfer<TInput>>;
|
|
37
|
+
execute: (params: zodInfer<TInput>, context?: TurnContext) => AsyncGenerator<zodInfer<TEvent> | zodInfer<TOutput>>;
|
|
38
38
|
};
|
|
39
39
|
/**
|
|
40
40
|
* Configuration for a manual tool (execute: false, no eventSchema or outputSchema)
|
|
41
41
|
*/
|
|
42
|
-
type ManualToolConfig<TInput extends ZodObject
|
|
42
|
+
type ManualToolConfig<TInput extends $ZodObject<$ZodShape>> = {
|
|
43
43
|
name: string;
|
|
44
44
|
description?: string;
|
|
45
45
|
inputSchema: TInput;
|
|
46
|
-
nextTurnParams?: NextTurnParamsFunctions<
|
|
46
|
+
nextTurnParams?: NextTurnParamsFunctions<zodInfer<TInput>>;
|
|
47
47
|
execute: false;
|
|
48
48
|
};
|
|
49
49
|
/**
|
|
@@ -91,9 +91,9 @@ type ManualToolConfig<TInput extends ZodObject<ZodRawShape>> = {
|
|
|
91
91
|
* });
|
|
92
92
|
* ```
|
|
93
93
|
*/
|
|
94
|
-
export declare function tool<TInput extends ZodObject
|
|
95
|
-
export declare function tool<TInput extends ZodObject
|
|
96
|
-
export declare function tool<TInput extends ZodObject
|
|
97
|
-
export declare function tool<TInput extends ZodObject
|
|
94
|
+
export declare function tool<TInput extends $ZodObject<$ZodShape>, TEvent extends $ZodType, TOutput extends $ZodType>(config: GeneratorToolConfig<TInput, TEvent, TOutput>): ToolWithGenerator<TInput, TEvent, TOutput>;
|
|
95
|
+
export declare function tool<TInput extends $ZodObject<$ZodShape>>(config: ManualToolConfig<TInput>): ManualTool<TInput>;
|
|
96
|
+
export declare function tool<TInput extends $ZodObject<$ZodShape>, TOutput extends $ZodType>(config: RegularToolConfigWithOutput<TInput, TOutput>): ToolWithExecute<TInput, TOutput>;
|
|
97
|
+
export declare function tool<TInput extends $ZodObject<$ZodShape>, TReturn>(config: RegularToolConfigWithoutOutput<TInput, TReturn>): ToolWithExecute<TInput, $ZodType<TReturn>>;
|
|
98
98
|
export {};
|
|
99
99
|
//# sourceMappingURL=tool.d.ts.map
|
package/jsr.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openrouter/sdk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.12",
|
|
4
4
|
"author": "OpenRouter",
|
|
5
5
|
"description": "The OpenRouter TypeScript SDK is a type-safe toolkit for building AI applications with access to 300+ language models through a unified API.",
|
|
6
6
|
"keywords": [
|
|
@@ -69,11 +69,9 @@
|
|
|
69
69
|
"build": "tsc",
|
|
70
70
|
"typecheck": "tsc --noEmit",
|
|
71
71
|
"prepublishOnly": "npm run build",
|
|
72
|
-
"test": "vitest --run",
|
|
73
|
-
"test:
|
|
74
|
-
|
|
75
|
-
"peerDependencies": {
|
|
76
|
-
|
|
72
|
+
"test": "vitest --run --project unit",
|
|
73
|
+
"test:e2e": "vitest --run --project e2e",
|
|
74
|
+
"test:watch": "vitest --watch --project unit"
|
|
77
75
|
},
|
|
78
76
|
"devDependencies": {
|
|
79
77
|
"@eslint/js": "^9.19.0",
|
|
@@ -87,5 +85,6 @@
|
|
|
87
85
|
},
|
|
88
86
|
"dependencies": {
|
|
89
87
|
"zod": "^3.25.0 || ^4.0.0"
|
|
90
|
-
}
|
|
88
|
+
},
|
|
89
|
+
"packageManager": "pnpm@10.22.0"
|
|
91
90
|
}
|
package/vitest.config.ts
CHANGED
|
@@ -1,36 +1,45 @@
|
|
|
1
|
-
import { dirname, join } from 'node:path';
|
|
2
|
-
import { fileURLToPath } from 'node:url';
|
|
3
1
|
import { config } from 'dotenv';
|
|
4
2
|
import { defineConfig } from 'vitest/config';
|
|
5
3
|
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = dirname(__filename);
|
|
8
|
-
|
|
9
4
|
// Load environment variables from .env file if it exists
|
|
10
5
|
// This will not override existing environment variables
|
|
11
6
|
config({
|
|
12
|
-
path:
|
|
7
|
+
path: new URL('.env', import.meta.url),
|
|
13
8
|
});
|
|
14
9
|
|
|
15
10
|
export default defineConfig({
|
|
16
11
|
test: {
|
|
17
12
|
globals: true,
|
|
18
13
|
environment: 'node',
|
|
19
|
-
// Don't override env vars - just let them pass through from the system
|
|
20
|
-
// The env object here will be merged with process.env
|
|
21
14
|
env: {
|
|
22
15
|
OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY,
|
|
23
16
|
},
|
|
24
|
-
include: [
|
|
25
|
-
'tests/**/*.test.ts',
|
|
26
|
-
],
|
|
27
|
-
hookTimeout: 30000,
|
|
28
|
-
testTimeout: 30000,
|
|
29
17
|
typecheck: {
|
|
30
18
|
enabled: true,
|
|
31
|
-
include: [
|
|
32
|
-
'tests/**/*.test.ts',
|
|
33
|
-
],
|
|
34
19
|
},
|
|
20
|
+
projects: [
|
|
21
|
+
{
|
|
22
|
+
extends: true,
|
|
23
|
+
test: {
|
|
24
|
+
name: 'unit',
|
|
25
|
+
include: [
|
|
26
|
+
'tests/unit/**/*.test.ts',
|
|
27
|
+
'tests/funcs/**/*.test.ts',
|
|
28
|
+
'tests/sdk/**/*.test.ts'
|
|
29
|
+
],
|
|
30
|
+
testTimeout: 10000,
|
|
31
|
+
hookTimeout: 10000,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
extends: true,
|
|
36
|
+
test: {
|
|
37
|
+
name: 'e2e',
|
|
38
|
+
include: ['tests/e2e/**/*.test.ts'],
|
|
39
|
+
testTimeout: 30000,
|
|
40
|
+
hookTimeout: 30000,
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
],
|
|
35
44
|
},
|
|
36
45
|
});
|