@useautumn/gateway 0.0.1
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.md +7 -0
- package/README.md +74 -0
- package/dist/ai-sdk/index.cjs +214 -0
- package/dist/ai-sdk/index.d.cts +43 -0
- package/dist/ai-sdk/index.d.ts +43 -0
- package/dist/ai-sdk/index.js +189 -0
- package/dist/openrouter/index.cjs +327 -0
- package/dist/openrouter/index.d.cts +69 -0
- package/dist/openrouter/index.d.ts +69 -0
- package/dist/openrouter/index.js +298 -0
- package/dist/track-C73uYSG_.d.cts +47 -0
- package/dist/track-C73uYSG_.d.ts +47 -0
- package/package.json +64 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
// src/shared/track.ts
|
|
2
|
+
var WIRE_KEYS = {
|
|
3
|
+
customerId: "customer_id",
|
|
4
|
+
entityId: "entity_id",
|
|
5
|
+
featureId: "feature_id",
|
|
6
|
+
modelId: "model_id",
|
|
7
|
+
inputTokens: "input_tokens",
|
|
8
|
+
outputTokens: "output_tokens",
|
|
9
|
+
cacheReadTokens: "cache_read_tokens",
|
|
10
|
+
cacheWriteTokens: "cache_write_tokens",
|
|
11
|
+
audioInputTokens: "audio_input_tokens",
|
|
12
|
+
audioOutputTokens: "audio_output_tokens",
|
|
13
|
+
reasoningTokens: "reasoning_tokens"
|
|
14
|
+
};
|
|
15
|
+
var toWire = (params) => Object.fromEntries(
|
|
16
|
+
Object.entries(params).filter(([, value]) => value !== void 0).map(([key, value]) => [WIRE_KEYS[key] ?? key, value])
|
|
17
|
+
);
|
|
18
|
+
var envClient = () => {
|
|
19
|
+
const env = typeof process === "undefined" ? void 0 : process.env;
|
|
20
|
+
const secretKey = env?.AUTUMN_API_KEY ?? env?.AUTUMN_SECRET_KEY;
|
|
21
|
+
const baseUrl = env?.AUTUMN_BASE_URL ?? "https://api.useautumn.com";
|
|
22
|
+
return {
|
|
23
|
+
trackTokens: async (params) => {
|
|
24
|
+
if (!secretKey) {
|
|
25
|
+
throw new Error(
|
|
26
|
+
"[Autumn] No autumn client was passed and AUTUMN_API_KEY is not set."
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
const response = await fetch(`${baseUrl}/v1/balances.track_tokens`, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: {
|
|
32
|
+
authorization: `Bearer ${secretKey}`,
|
|
33
|
+
"content-type": "application/json"
|
|
34
|
+
},
|
|
35
|
+
body: JSON.stringify(toWire(params))
|
|
36
|
+
});
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`track_tokens failed (${response.status}): ${await response.text()}`
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
return response.json();
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
var createTracker = ({
|
|
47
|
+
autumn = envClient(),
|
|
48
|
+
customerId,
|
|
49
|
+
featureId,
|
|
50
|
+
entityId,
|
|
51
|
+
properties
|
|
52
|
+
}) => (getEvent) => trackTokenUsage({
|
|
53
|
+
autumn,
|
|
54
|
+
getParams: () => {
|
|
55
|
+
const event = getEvent();
|
|
56
|
+
return {
|
|
57
|
+
...event.pools,
|
|
58
|
+
customerId,
|
|
59
|
+
modelId: event.modelId,
|
|
60
|
+
featureId,
|
|
61
|
+
entityId,
|
|
62
|
+
properties: event.properties ?? properties
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
var trackTokenUsage = async ({
|
|
67
|
+
autumn,
|
|
68
|
+
getParams
|
|
69
|
+
}) => {
|
|
70
|
+
try {
|
|
71
|
+
const balances = autumn.balances;
|
|
72
|
+
const trackTokens = balances?.trackTokens?.bind(balances) ?? autumn.trackTokens?.bind(autumn);
|
|
73
|
+
if (!trackTokens) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
"Autumn client does not support trackTokens \u2014 upgrade @useautumn/sdk."
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
await trackTokens(getParams());
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error("[Autumn Tracking] Failed to track usage:", error);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// src/shared/usage.ts
|
|
85
|
+
var clamp = (value) => Math.max(0, value);
|
|
86
|
+
var requiredCount = (value, label, modelName) => {
|
|
87
|
+
if (value == null) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`[Autumn] ${label} token usage was not returned by the model provider (${modelName}). This provider may not support usage tracking.`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return value;
|
|
93
|
+
};
|
|
94
|
+
var poolsFromParts = (parts, modelName) => {
|
|
95
|
+
const cacheRead = parts.cacheRead ?? 0;
|
|
96
|
+
const cacheWrite = parts.cacheWrite ?? 0;
|
|
97
|
+
const reasoning = parts.reasoning ?? 0;
|
|
98
|
+
const audioInput = parts.audioInput ?? 0;
|
|
99
|
+
const textInput = parts.textInput ?? (parts.totalInput != null ? parts.totalInput - cacheRead - cacheWrite - audioInput : void 0);
|
|
100
|
+
const textOutput = parts.textOutput ?? (parts.totalOutput != null ? parts.totalOutput - reasoning : void 0);
|
|
101
|
+
return {
|
|
102
|
+
inputTokens: clamp(requiredCount(textInput, "Input", modelName)),
|
|
103
|
+
outputTokens: clamp(requiredCount(textOutput, "Output", modelName)),
|
|
104
|
+
cacheReadTokens: clamp(cacheRead),
|
|
105
|
+
cacheWriteTokens: clamp(cacheWrite),
|
|
106
|
+
reasoningTokens: clamp(reasoning),
|
|
107
|
+
...parts.audioInput !== void 0 && {
|
|
108
|
+
audioInputTokens: clamp(audioInput)
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/openrouter/usage.ts
|
|
114
|
+
var normalizeOpenRouterUsage = (usage, modelName) => {
|
|
115
|
+
const promptDetails = usage.promptTokensDetails ?? usage.prompt_tokens_details ?? usage.inputTokensDetails ?? usage.input_tokens_details;
|
|
116
|
+
const completionDetails = usage.completionTokensDetails ?? usage.completion_tokens_details ?? usage.outputTokensDetails ?? usage.output_tokens_details;
|
|
117
|
+
const promptTotal = usage.promptTokens ?? usage.prompt_tokens ?? usage.inputTokens ?? usage.input_tokens;
|
|
118
|
+
const completionTotal = usage.completionTokens ?? usage.completion_tokens ?? usage.outputTokens ?? usage.output_tokens;
|
|
119
|
+
return poolsFromParts(
|
|
120
|
+
{
|
|
121
|
+
totalInput: promptTotal,
|
|
122
|
+
totalOutput: completionTotal,
|
|
123
|
+
cacheRead: promptDetails?.cachedTokens ?? promptDetails?.cached_tokens ?? 0,
|
|
124
|
+
cacheWrite: promptDetails?.cacheWriteTokens ?? promptDetails?.cache_write_tokens ?? 0,
|
|
125
|
+
reasoning: completionDetails?.reasoningTokens ?? completionDetails?.reasoning_tokens ?? 0,
|
|
126
|
+
audioInput: promptDetails?.audioTokens ?? promptDetails?.audio_tokens ?? 0
|
|
127
|
+
},
|
|
128
|
+
modelName
|
|
129
|
+
);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
// src/openrouter/index.ts
|
|
133
|
+
var withCost = (properties, cost) => cost == null ? properties : { ...properties, openrouter_cost: cost };
|
|
134
|
+
var HOOKED_OPERATIONS = /* @__PURE__ */ new Set(["createResponses"]);
|
|
135
|
+
var pendingTracking = /* @__PURE__ */ new WeakMap();
|
|
136
|
+
var trackingSettled = async (openRouter) => {
|
|
137
|
+
const pending = pendingTracking.get(openRouter);
|
|
138
|
+
while (pending && pending.size > 0) {
|
|
139
|
+
await Promise.allSettled([...pending]);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var findCarrier = (value) => {
|
|
143
|
+
if (value == null || typeof value !== "object") {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const record = value;
|
|
147
|
+
if (record.usage && record.model) {
|
|
148
|
+
return record;
|
|
149
|
+
}
|
|
150
|
+
return findCarrier(record.response);
|
|
151
|
+
};
|
|
152
|
+
var lastCarrierFromSse = (body) => {
|
|
153
|
+
let carrier;
|
|
154
|
+
for (const line of body.split("\n")) {
|
|
155
|
+
if (!line.startsWith("data:")) {
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
carrier = findCarrier(JSON.parse(line.slice(5).trim())) ?? carrier;
|
|
160
|
+
} catch {
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return carrier;
|
|
164
|
+
};
|
|
165
|
+
var toModelId = (slug) => slug.startsWith("openrouter/") ? slug : `openrouter/${slug}`;
|
|
166
|
+
var trackOpenRouterUsage = ({
|
|
167
|
+
usage,
|
|
168
|
+
model,
|
|
169
|
+
...tracking
|
|
170
|
+
}) => {
|
|
171
|
+
const modelId = toModelId(model);
|
|
172
|
+
return createTracker(tracking)(() => ({
|
|
173
|
+
pools: normalizeOpenRouterUsage(usage, modelId),
|
|
174
|
+
modelId,
|
|
175
|
+
properties: withCost(tracking.properties, usage.cost)
|
|
176
|
+
}));
|
|
177
|
+
};
|
|
178
|
+
var isAsyncIterable = (value) => value != null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
179
|
+
var hasUsage = (value) => value != null && typeof value === "object" && "usage" in value && value.usage != null;
|
|
180
|
+
var withAutumn = (options) => {
|
|
181
|
+
const { openRouter } = options;
|
|
182
|
+
const track = createTracker(options);
|
|
183
|
+
const trackCarrier = (carrier, requestModel) => track(() => {
|
|
184
|
+
const requested = requestModel?.endsWith("/auto") ? void 0 : requestModel;
|
|
185
|
+
const slug = requested ?? carrier.model ?? requestModel;
|
|
186
|
+
if (!slug) {
|
|
187
|
+
throw new Error(
|
|
188
|
+
"[Autumn] OpenRouter response did not include a model slug."
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
const modelId = toModelId(slug);
|
|
192
|
+
const usage = carrier.usage ?? {};
|
|
193
|
+
return {
|
|
194
|
+
pools: normalizeOpenRouterUsage(usage, modelId),
|
|
195
|
+
modelId,
|
|
196
|
+
properties: withCost(options.properties, usage.cost)
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
const wrapStream = (stream, requestModel) => {
|
|
200
|
+
let tracked = false;
|
|
201
|
+
async function* iterate() {
|
|
202
|
+
let finalCarrier;
|
|
203
|
+
try {
|
|
204
|
+
for await (const chunk of stream) {
|
|
205
|
+
if (hasUsage(chunk)) {
|
|
206
|
+
finalCarrier = chunk;
|
|
207
|
+
}
|
|
208
|
+
yield chunk;
|
|
209
|
+
}
|
|
210
|
+
} finally {
|
|
211
|
+
if (finalCarrier && !tracked) {
|
|
212
|
+
tracked = true;
|
|
213
|
+
await trackCarrier(finalCarrier, requestModel);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return new Proxy(stream, {
|
|
218
|
+
get(target, prop, receiver) {
|
|
219
|
+
if (prop === Symbol.asyncIterator) {
|
|
220
|
+
return () => iterate();
|
|
221
|
+
}
|
|
222
|
+
const value = Reflect.get(target, prop, receiver);
|
|
223
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
};
|
|
227
|
+
const send = async (request, ...rest) => {
|
|
228
|
+
const body = request.chatRequest ?? request;
|
|
229
|
+
const bodyWithUsage = {
|
|
230
|
+
...body,
|
|
231
|
+
usage: { ...body.usage, include: true }
|
|
232
|
+
};
|
|
233
|
+
const requestWithUsage = request.chatRequest ? { ...request, chatRequest: bodyWithUsage } : bodyWithUsage;
|
|
234
|
+
const result = await openRouter.chat.send(requestWithUsage, ...rest);
|
|
235
|
+
if (isAsyncIterable(result)) {
|
|
236
|
+
return wrapStream(result, body.model);
|
|
237
|
+
}
|
|
238
|
+
await trackCarrier(result, body.model);
|
|
239
|
+
return result;
|
|
240
|
+
};
|
|
241
|
+
const captureHookedResponse = async (response, contentType) => {
|
|
242
|
+
let carrier;
|
|
243
|
+
if (contentType.includes("text/event-stream")) {
|
|
244
|
+
carrier = lastCarrierFromSse(await response.text());
|
|
245
|
+
} else if (contentType.includes("json")) {
|
|
246
|
+
carrier = findCarrier(await response.json());
|
|
247
|
+
}
|
|
248
|
+
if (carrier) {
|
|
249
|
+
await trackCarrier(carrier);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
const pending = /* @__PURE__ */ new Set();
|
|
253
|
+
pendingTracking.set(openRouter, pending);
|
|
254
|
+
openRouter._options?.hooks?.registerAfterSuccessHook?.(
|
|
255
|
+
{
|
|
256
|
+
afterSuccess: (ctx, response) => {
|
|
257
|
+
if (!HOOKED_OPERATIONS.has(ctx.operationID)) {
|
|
258
|
+
return response;
|
|
259
|
+
}
|
|
260
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
261
|
+
const capture = captureHookedResponse(
|
|
262
|
+
response.clone(),
|
|
263
|
+
contentType
|
|
264
|
+
).catch((error) => {
|
|
265
|
+
console.error("[Autumn Tracking] Failed to track usage:", error);
|
|
266
|
+
});
|
|
267
|
+
pending.add(capture);
|
|
268
|
+
capture.finally(() => pending.delete(capture));
|
|
269
|
+
return contentType.includes("text/event-stream") ? response : capture.then(() => response);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
);
|
|
273
|
+
const wrappedChat = new Proxy(openRouter.chat, {
|
|
274
|
+
get(target, prop, receiver) {
|
|
275
|
+
if (prop === "send") {
|
|
276
|
+
return send;
|
|
277
|
+
}
|
|
278
|
+
const value = Reflect.get(target, prop, receiver);
|
|
279
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
const wrapped = new Proxy(openRouter, {
|
|
283
|
+
get(target, prop, receiver) {
|
|
284
|
+
if (prop === "chat") {
|
|
285
|
+
return wrappedChat;
|
|
286
|
+
}
|
|
287
|
+
const value = Reflect.get(target, prop, receiver);
|
|
288
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
pendingTracking.set(wrapped, pending);
|
|
292
|
+
return wrapped;
|
|
293
|
+
};
|
|
294
|
+
export {
|
|
295
|
+
trackOpenRouterUsage,
|
|
296
|
+
trackingSettled,
|
|
297
|
+
withAutumn
|
|
298
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Mutually exclusive token pools — each pool is priced at its own rate server-side. */
|
|
2
|
+
type TokenPools = {
|
|
3
|
+
inputTokens: number;
|
|
4
|
+
outputTokens: number;
|
|
5
|
+
cacheReadTokens: number;
|
|
6
|
+
cacheWriteTokens: number;
|
|
7
|
+
reasoningTokens: number;
|
|
8
|
+
audioInputTokens?: number;
|
|
9
|
+
audioOutputTokens?: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type TrackTokensParams = TokenPools & {
|
|
13
|
+
customerId: string;
|
|
14
|
+
modelId: string;
|
|
15
|
+
featureId?: string;
|
|
16
|
+
entityId?: string;
|
|
17
|
+
properties?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
/** Tracking options every adapter shares. */
|
|
20
|
+
type AutumnTrackingOptions = {
|
|
21
|
+
/**
|
|
22
|
+
* Autumn SDK client instance. When omitted, a minimal fetch client is
|
|
23
|
+
* created from AUTUMN_API_KEY (or AUTUMN_SECRET_KEY).
|
|
24
|
+
*/
|
|
25
|
+
autumn?: AutumnClient;
|
|
26
|
+
/** The Autumn customer ID to attribute usage to. */
|
|
27
|
+
customerId: string;
|
|
28
|
+
/** Target a specific AI credit system feature. Auto-detected if omitted. */
|
|
29
|
+
featureId?: string;
|
|
30
|
+
/** Entity ID for entity-scoped balance tracking. */
|
|
31
|
+
entityId?: string;
|
|
32
|
+
/** Additional properties to attach to each usage event. */
|
|
33
|
+
properties?: Record<string, unknown>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Structural view of the Autumn SDK client. @useautumn/sdk exposes
|
|
37
|
+
* trackTokens at the client root; balances.trackTokens is accepted for
|
|
38
|
+
* clients that namespace it. `balances` stays `unknown` so SDK namespace
|
|
39
|
+
* classes without trackTokens still satisfy the type. Older clients may
|
|
40
|
+
* ship neither shape.
|
|
41
|
+
*/
|
|
42
|
+
type AutumnClient = {
|
|
43
|
+
trackTokens?: (params: TrackTokensParams) => Promise<unknown>;
|
|
44
|
+
balances?: unknown;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type { AutumnTrackingOptions as A, TokenPools as T, AutumnClient as a };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** Mutually exclusive token pools — each pool is priced at its own rate server-side. */
|
|
2
|
+
type TokenPools = {
|
|
3
|
+
inputTokens: number;
|
|
4
|
+
outputTokens: number;
|
|
5
|
+
cacheReadTokens: number;
|
|
6
|
+
cacheWriteTokens: number;
|
|
7
|
+
reasoningTokens: number;
|
|
8
|
+
audioInputTokens?: number;
|
|
9
|
+
audioOutputTokens?: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type TrackTokensParams = TokenPools & {
|
|
13
|
+
customerId: string;
|
|
14
|
+
modelId: string;
|
|
15
|
+
featureId?: string;
|
|
16
|
+
entityId?: string;
|
|
17
|
+
properties?: Record<string, unknown>;
|
|
18
|
+
};
|
|
19
|
+
/** Tracking options every adapter shares. */
|
|
20
|
+
type AutumnTrackingOptions = {
|
|
21
|
+
/**
|
|
22
|
+
* Autumn SDK client instance. When omitted, a minimal fetch client is
|
|
23
|
+
* created from AUTUMN_API_KEY (or AUTUMN_SECRET_KEY).
|
|
24
|
+
*/
|
|
25
|
+
autumn?: AutumnClient;
|
|
26
|
+
/** The Autumn customer ID to attribute usage to. */
|
|
27
|
+
customerId: string;
|
|
28
|
+
/** Target a specific AI credit system feature. Auto-detected if omitted. */
|
|
29
|
+
featureId?: string;
|
|
30
|
+
/** Entity ID for entity-scoped balance tracking. */
|
|
31
|
+
entityId?: string;
|
|
32
|
+
/** Additional properties to attach to each usage event. */
|
|
33
|
+
properties?: Record<string, unknown>;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Structural view of the Autumn SDK client. @useautumn/sdk exposes
|
|
37
|
+
* trackTokens at the client root; balances.trackTokens is accepted for
|
|
38
|
+
* clients that namespace it. `balances` stays `unknown` so SDK namespace
|
|
39
|
+
* classes without trackTokens still satisfy the type. Older clients may
|
|
40
|
+
* ship neither shape.
|
|
41
|
+
*/
|
|
42
|
+
type AutumnClient = {
|
|
43
|
+
trackTokens?: (params: TrackTokensParams) => Promise<unknown>;
|
|
44
|
+
balances?: unknown;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export type { AutumnTrackingOptions as A, TokenPools as T, AutumnClient as a };
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@useautumn/gateway",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Autumn usage tracking adapters for AI SDKs and gateways (Vercel AI SDK, OpenRouter)",
|
|
6
|
+
"repository": "github:useautumn/autumn",
|
|
7
|
+
"homepage": "https://useautumn.com",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"autumn",
|
|
11
|
+
"billing",
|
|
12
|
+
"usage-based-billing",
|
|
13
|
+
"ai-sdk",
|
|
14
|
+
"openrouter",
|
|
15
|
+
"llm",
|
|
16
|
+
"token-tracking"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE.md"
|
|
23
|
+
],
|
|
24
|
+
"exports": {
|
|
25
|
+
"./ai-sdk": {
|
|
26
|
+
"types": "./dist/ai-sdk/index.d.ts",
|
|
27
|
+
"require": "./dist/ai-sdk/index.cjs",
|
|
28
|
+
"import": "./dist/ai-sdk/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./openrouter": {
|
|
31
|
+
"types": "./dist/openrouter/index.d.ts",
|
|
32
|
+
"require": "./dist/openrouter/index.cjs",
|
|
33
|
+
"import": "./dist/openrouter/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"ts": "bunx tsgo --noEmit --skipLibCheck",
|
|
38
|
+
"test": "bun test tests/unit",
|
|
39
|
+
"build": "rm -rf dist && tsup",
|
|
40
|
+
"prepublishOnly": "bun run build"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@ai-sdk/provider": "^3.0.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@openrouter/sdk": "*",
|
|
47
|
+
"ai": "^6.0.116",
|
|
48
|
+
"autumn-js": "*"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"@openrouter/sdk": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"ai": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@types/node": "^24.9.1",
|
|
60
|
+
"@typescript/native-preview": "7.0.0-dev.20260220.1",
|
|
61
|
+
"tsup": "^8.4.0",
|
|
62
|
+
"typescript": "^5.8.3"
|
|
63
|
+
}
|
|
64
|
+
}
|