@absolutejs/ai 0.0.51 → 0.0.52

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.
@@ -1990,7 +1990,46 @@ var anthropic = (config2) => {
1990
1990
  };
1991
1991
 
1992
1992
  // src/ai/providers/openrouterClient.ts
1993
+ var OPENROUTER_PRICING_KEYS = [
1994
+ "prompt",
1995
+ "completion",
1996
+ "request",
1997
+ "image",
1998
+ "web_search",
1999
+ "internal_reasoning",
2000
+ "input_cache_read",
2001
+ "input_cache_write"
2002
+ ];
2003
+ var estimateOpenRouterCost = (pricing, units) => {
2004
+ const components = {};
2005
+ let total = 0;
2006
+ for (const key of OPENROUTER_PRICING_KEYS) {
2007
+ const quantity = units[key];
2008
+ if (quantity === undefined)
2009
+ continue;
2010
+ if (!Number.isFinite(quantity) || quantity < 0)
2011
+ throw new Error(`OpenRouter ${key} units must be non-negative`);
2012
+ const rawPrice = pricing[key];
2013
+ if (rawPrice === undefined)
2014
+ continue;
2015
+ const price = Number(rawPrice);
2016
+ if (!Number.isFinite(price) || price < 0)
2017
+ throw new Error(`OpenRouter ${key} price must be non-negative`);
2018
+ components[key] = price * quantity;
2019
+ total += components[key];
2020
+ }
2021
+ return { components, total };
2022
+ };
2023
+ var estimateOpenRouterModelCost = (model, units) => estimateOpenRouterCost(model.pricing ?? {}, units);
1993
2024
  var DEFAULT_BASE_URL4 = "https://openrouter.ai/api/v1";
2025
+ var DEFAULT_BATCH_BASE_URL = "https://openrouter.ai/api/beta";
2026
+ var DEFAULT_SITE_URL = "https://openrouter.ai";
2027
+ var TERMINAL_BATCH_STATUSES = new Set([
2028
+ "completed",
2029
+ "failed",
2030
+ "expired",
2031
+ "cancelled"
2032
+ ]);
1994
2033
  var withoutLatestPrefix = (model) => model.startsWith("~") ? model.slice(1) : model;
1995
2034
  var openRouterModelMatchesRule = (model, rule) => {
1996
2035
  const normalizedModel = withoutLatestPrefix(model);
@@ -2004,6 +2043,22 @@ var assertAllowedModel = (model, allowedModels) => {
2004
2043
  return;
2005
2044
  throw new Error(`OpenRouter model "${model}" is not allowed`);
2006
2045
  };
2046
+ var assertAllowedModelsInValue = (value, allowedModels, key = "") => {
2047
+ if (key === "model" && typeof value === "string")
2048
+ assertAllowedModel(value, allowedModels);
2049
+ if ((key === "models" || key === "analysis_models" || key === "allowed_models") && Array.isArray(value)) {
2050
+ for (const model of value)
2051
+ if (typeof model === "string")
2052
+ assertAllowedModel(model, allowedModels);
2053
+ }
2054
+ if (Array.isArray(value)) {
2055
+ for (const item of value)
2056
+ assertAllowedModelsInValue(item, allowedModels);
2057
+ } else if (value && typeof value === "object") {
2058
+ for (const [childKey, child] of Object.entries(value))
2059
+ assertAllowedModelsInValue(child, allowedModels, childKey);
2060
+ }
2061
+ };
2007
2062
  var normalizePath = (path) => path.startsWith("/") ? path : `/${path}`;
2008
2063
  var encodeModelPath = (model) => model.split("/").map(encodeURIComponent).join("/");
2009
2064
  var withQuery = (url, query) => {
@@ -2054,6 +2109,54 @@ var parseImageSSE = async function* (response) {
2054
2109
  }
2055
2110
  };
2056
2111
  var toBytes = (value) => typeof value === "string" ? new TextEncoder().encode(value) : value;
2112
+ var toBase64Url = (bytes) => {
2113
+ let binary = "";
2114
+ for (const byte of bytes)
2115
+ binary += String.fromCharCode(byte);
2116
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
2117
+ };
2118
+ var generateOpenRouterPKCE = async () => {
2119
+ const random = crypto.getRandomValues(new Uint8Array(32));
2120
+ const codeVerifier = toBase64Url(random);
2121
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(codeVerifier));
2122
+ return {
2123
+ codeChallenge: toBase64Url(new Uint8Array(digest)),
2124
+ codeChallengeMethod: "S256",
2125
+ codeVerifier
2126
+ };
2127
+ };
2128
+ var createOpenRouterAuthorizationUrl = (options = {}) => {
2129
+ const url = new URL("/auth", options.baseUrl ?? DEFAULT_SITE_URL);
2130
+ if (options.callbackUrl)
2131
+ url.searchParams.set("callback_url", options.callbackUrl);
2132
+ if (options.codeChallenge)
2133
+ url.searchParams.set("code_challenge", options.codeChallenge);
2134
+ if (options.codeChallengeMethod)
2135
+ url.searchParams.set("code_challenge_method", options.codeChallengeMethod);
2136
+ if (options.keyLabel)
2137
+ url.searchParams.set("key_label", options.keyLabel);
2138
+ return url.toString();
2139
+ };
2140
+ var exchangeOpenRouterAuthCode = async (body, options = {}) => {
2141
+ const response = await (options.fetch ?? globalThis.fetch)(`${(options.baseUrl ?? DEFAULT_BASE_URL4).replace(/\/$/, "")}/auth/keys`, {
2142
+ body: JSON.stringify(body),
2143
+ headers: { "Content-Type": "application/json" },
2144
+ method: "POST"
2145
+ });
2146
+ if (!response.ok)
2147
+ throw ProviderError.fromResponse("openrouter", response.status, await response.text());
2148
+ return response.json();
2149
+ };
2150
+ var createOpenRouterKeyLinks = async (key, siteUrl = DEFAULT_SITE_URL) => {
2151
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(key)));
2152
+ const hash = Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join("");
2153
+ const root = siteUrl.replace(/\/$/, "");
2154
+ return {
2155
+ hash,
2156
+ logsUrl: `${root}/logs?api_key_hash=${hash}`,
2157
+ settingsUrl: `${root}/keys/${hash}`
2158
+ };
2159
+ };
2057
2160
  var hexToBytes = (hex) => {
2058
2161
  if (!/^[0-9a-f]+$/iu.test(hex) || hex.length % 2 !== 0)
2059
2162
  return;
@@ -2099,9 +2202,11 @@ var createOpenRouterClient = (config2) => {
2099
2202
  if (!config2.apiKey && !config2.tokenSource)
2100
2203
  throw new Error("createOpenRouterClient() requires either apiKey or tokenSource");
2101
2204
  const baseUrl = (config2.baseUrl ?? DEFAULT_BASE_URL4).replace(/\/$/, "");
2205
+ const batchBaseUrl = (config2.batchBaseUrl ?? (config2.baseUrl ? new URL("../beta", `${baseUrl}/`).toString() : DEFAULT_BATCH_BASE_URL)).replace(/\/$/, "");
2102
2206
  const fetchImpl = config2.fetch ?? globalThis.fetch;
2103
2207
  const allowedModels = config2.allowedModels ? [...config2.allowedModels] : undefined;
2104
- const requestRaw = async (path, options = {}) => {
2208
+ const defaultWorkspaceId = config2.workspaceId;
2209
+ const requestRawAt = async (rootUrl, path, options = {}) => {
2105
2210
  const token = config2.tokenSource ? await Promise.resolve(config2.tokenSource()) : config2.apiKey;
2106
2211
  const suppliedHeaders = typeof config2.headers === "function" ? await config2.headers() : config2.headers ?? {};
2107
2212
  const headers = new Headers(suppliedHeaders);
@@ -2115,13 +2220,16 @@ var createOpenRouterClient = (config2) => {
2115
2220
  body = JSON.stringify(options.body);
2116
2221
  }
2117
2222
  const { query, ...requestInit } = options;
2118
- const response = await fetchImpl(withQuery(`${baseUrl}${normalizePath(path)}`, options.query), { ...requestInit, body, headers });
2223
+ const response = await fetchImpl(withQuery(`${rootUrl}${normalizePath(path)}`, options.query), { ...requestInit, body, headers });
2119
2224
  if (!response.ok) {
2120
2225
  throw ProviderError.fromResponse("openrouter", response.status, await response.text());
2121
2226
  }
2122
2227
  return response;
2123
2228
  };
2229
+ const requestRaw = (path, options = {}) => requestRawAt(baseUrl, path, options);
2124
2230
  const request = async (path, options = {}) => (await requestRaw(path, options)).json();
2231
+ const requestBatch = async (path, options = {}) => (await requestRawAt(batchBaseUrl, path, options)).json();
2232
+ const getBatch = (id) => requestBatch(`/batches/${encodeURIComponent(id)}`);
2125
2233
  const listModels = async (query) => {
2126
2234
  const result = await request("/models", { query });
2127
2235
  if (!allowedModels)
@@ -2140,10 +2248,45 @@ var createOpenRouterClient = (config2) => {
2140
2248
  };
2141
2249
  };
2142
2250
  return {
2143
- cancelBatch: (id) => request(`/batches/${encodeURIComponent(id)}/cancel`, {
2251
+ addWorkspaceMembers: (id, userIds) => request(`/workspaces/${encodeURIComponent(id)}/members/add`, { body: { user_ids: [...userIds] }, method: "POST" }),
2252
+ createAuthCode: (body) => request("/auth/keys/code", {
2253
+ body: {
2254
+ ...body,
2255
+ workspace_id: body.workspace_id ?? defaultWorkspaceId
2256
+ },
2144
2257
  method: "POST"
2145
2258
  }),
2146
- createBatch: (body) => request("/batches", { body, method: "POST" }),
2259
+ createPresetFromChatCompletions: (slug, body) => {
2260
+ assertAllowedModelsInValue(body, allowedModels);
2261
+ return request(`/presets/${encodeURIComponent(slug)}/chat/completions`, { body, method: "POST" });
2262
+ },
2263
+ createPresetFromMessages: (slug, body) => {
2264
+ assertAllowedModelsInValue(body, allowedModels);
2265
+ return request(`/presets/${encodeURIComponent(slug)}/messages`, { body, method: "POST" });
2266
+ },
2267
+ createPresetFromResponses: (slug, body) => {
2268
+ assertAllowedModelsInValue(body, allowedModels);
2269
+ return request(`/presets/${encodeURIComponent(slug)}/responses`, { body, method: "POST" });
2270
+ },
2271
+ createWorkspace: (body) => {
2272
+ assertAllowedModelsInValue(body, allowedModels);
2273
+ return request("/workspaces", {
2274
+ body,
2275
+ method: "POST"
2276
+ });
2277
+ },
2278
+ createBatch: (body) => {
2279
+ assertAllowedModel(body.model, allowedModels);
2280
+ return requestBatch("/batches", {
2281
+ body: {
2282
+ endpoint: body.endpoint,
2283
+ model: body.model,
2284
+ requests: body.requests,
2285
+ ...body.completion_window ? { completion_window: body.completion_window } : {}
2286
+ },
2287
+ method: "POST"
2288
+ });
2289
+ },
2147
2290
  createEmbedding: (body) => {
2148
2291
  assertAllowedModel(body.model, allowedModels);
2149
2292
  return request("/embeddings", {
@@ -2158,8 +2301,12 @@ var createOpenRouterClient = (config2) => {
2158
2301
  method: "POST"
2159
2302
  });
2160
2303
  },
2161
- deleteFile: (id, workspaceId) => request(`/files/${encodeURIComponent(id)}`, { method: "DELETE", query: { workspace_id: workspaceId } }),
2162
- downloadFile: (id, workspaceId) => requestRaw(`/files/${encodeURIComponent(id)}/content`, {
2304
+ deleteFile: (id, workspaceId = defaultWorkspaceId) => request(`/files/${encodeURIComponent(id)}`, { method: "DELETE", query: { workspace_id: workspaceId } }),
2305
+ deleteWorkspace: (id) => request(`/workspaces/${encodeURIComponent(id)}`, {
2306
+ method: "DELETE"
2307
+ }),
2308
+ deleteWorkspaceBudget: (id, interval) => request(`/workspaces/${encodeURIComponent(id)}/budgets/${interval}`, { method: "DELETE" }),
2309
+ downloadFile: (id, workspaceId = defaultWorkspaceId) => requestRaw(`/files/${encodeURIComponent(id)}/content`, {
2163
2310
  query: { workspace_id: workspaceId }
2164
2311
  }),
2165
2312
  downloadVideo: (id, index = 0) => requestRaw(`/videos/${encodeURIComponent(id)}/content`, {
@@ -2172,15 +2319,25 @@ var createOpenRouterClient = (config2) => {
2172
2319
  method: "POST"
2173
2320
  });
2174
2321
  },
2175
- getBatch: (id) => request(`/batches/${encodeURIComponent(id)}`),
2322
+ getBatch,
2323
+ getActivity: (query) => request("/activity", {
2324
+ query: {
2325
+ ...query,
2326
+ workspace_id: query?.workspace_id ?? defaultWorkspaceId
2327
+ }
2328
+ }),
2329
+ getAnalyticsMeta: () => request("/analytics/meta"),
2176
2330
  getCredits: () => request("/credits"),
2177
2331
  getCurrentKey: () => request("/key"),
2178
- getFile: (id, workspaceId) => request(`/files/${encodeURIComponent(id)}`, {
2332
+ getFile: (id, workspaceId = defaultWorkspaceId) => request(`/files/${encodeURIComponent(id)}`, {
2179
2333
  query: { workspace_id: workspaceId }
2180
2334
  }),
2181
2335
  getGeneration: (id) => request("/generation", {
2182
2336
  query: { id }
2183
2337
  }),
2338
+ getGenerationContent: (id) => request("/generation/content", {
2339
+ query: { id }
2340
+ }),
2184
2341
  getModelEndpoints: (model) => {
2185
2342
  assertAllowedModel(model, allowedModels);
2186
2343
  return request(`/models/${encodeModelPath(model)}/endpoints`);
@@ -2193,9 +2350,20 @@ var createOpenRouterClient = (config2) => {
2193
2350
  assertAllowedModel(model, allowedModels);
2194
2351
  return request(`/images/models/${encodeModelPath(model)}/endpoints`);
2195
2352
  },
2353
+ getPreset: (slug) => request(`/presets/${encodeURIComponent(slug)}`),
2354
+ getPresetVersion: (slug, version) => request(`/presets/${encodeURIComponent(slug)}/versions/${encodeURIComponent(String(version))}`),
2355
+ getTaskClassifications: (window = "7d") => request("/classifications/task", {
2356
+ query: { window }
2357
+ }),
2196
2358
  getVideo: (id) => request(`/videos/${encodeURIComponent(id)}`),
2359
+ getWorkspace: (id) => request(`/workspaces/${encodeURIComponent(id)}`),
2197
2360
  listImageModels: async () => filterModelList(await request("/images/models")),
2198
- listFiles: (query) => request("/files", { query }),
2361
+ listFiles: (query) => request("/files", {
2362
+ query: {
2363
+ ...query,
2364
+ workspace_id: query?.workspace_id ?? defaultWorkspaceId
2365
+ }
2366
+ }),
2199
2367
  listModels,
2200
2368
  listUserModels: async () => filterModelList(await request("/models/user")),
2201
2369
  listZdrEndpoints: async () => {
@@ -2210,11 +2378,20 @@ var createOpenRouterClient = (config2) => {
2210
2378
  countModels: (outputModalities) => request("/models/count", {
2211
2379
  query: { output_modalities: outputModalities }
2212
2380
  }),
2213
- listPresets: (offset = 0, limit = 100) => request("/presets", { query: { limit, offset } }),
2381
+ listPresets: (offset = 0, limit = 100) => request("/presets", {
2382
+ query: { limit, offset }
2383
+ }),
2214
2384
  listPresetVersions: (slug, offset = 0, limit = 100) => request(`/presets/${encodeURIComponent(slug)}/versions`, { query: { limit, offset } }),
2215
2385
  listProviders: () => request("/providers"),
2216
2386
  listRerankModels: async () => filterModelList(await request("/rerank/models")),
2217
2387
  listVideoModels: async () => filterModelList(await request("/videos/models")),
2388
+ listWorkspaceBudgets: (id) => request(`/workspaces/${encodeURIComponent(id)}/budgets`),
2389
+ listWorkspaces: (offset = 0, limit = 100) => request("/workspaces", { query: { limit, offset } }),
2390
+ queryAnalytics: (body) => request("/analytics/query", {
2391
+ body,
2392
+ method: "POST"
2393
+ }),
2394
+ removeWorkspaceMembers: (id, userIds) => request(`/workspaces/${encodeURIComponent(id)}/members/remove`, { body: { user_ids: [...userIds] }, method: "POST" }),
2218
2395
  request,
2219
2396
  requestRaw,
2220
2397
  streamImage: async function* (body, options = {}) {
@@ -2267,8 +2444,41 @@ var createOpenRouterClient = (config2) => {
2267
2444
  return request("/files", {
2268
2445
  body,
2269
2446
  method: "POST",
2270
- query: { workspace_id: options.workspaceId }
2447
+ query: { workspace_id: options.workspaceId ?? defaultWorkspaceId }
2271
2448
  });
2449
+ },
2450
+ updateWorkspace: (id, body) => {
2451
+ assertAllowedModelsInValue(body, allowedModels);
2452
+ return request(`/workspaces/${encodeURIComponent(id)}`, { body, method: "PATCH" });
2453
+ },
2454
+ upsertWorkspaceBudget: (id, interval, limitUsd) => request(`/workspaces/${encodeURIComponent(id)}/budgets/${interval}`, { body: { limit_usd: limitUsd }, method: "PUT" }),
2455
+ waitForBatch: async (id, options = {}) => {
2456
+ const intervalMs = options.intervalMs ?? 1000;
2457
+ const timeoutMs = options.timeoutMs;
2458
+ if (!Number.isFinite(intervalMs) || intervalMs < 0)
2459
+ throw new Error("OpenRouter batch intervalMs must be non-negative");
2460
+ if (timeoutMs !== undefined && (!Number.isFinite(timeoutMs) || timeoutMs < 0))
2461
+ throw new Error("OpenRouter batch timeoutMs must be non-negative");
2462
+ const startedAt = Date.now();
2463
+ for (;; ) {
2464
+ options.signal?.throwIfAborted();
2465
+ const batch = await getBatch(id);
2466
+ if (TERMINAL_BATCH_STATUSES.has(batch.status))
2467
+ return batch;
2468
+ if (timeoutMs !== undefined && Date.now() - startedAt + intervalMs > timeoutMs)
2469
+ throw new Error(`Timed out waiting for OpenRouter batch "${id}"`);
2470
+ await new Promise((resolve, reject) => {
2471
+ const onAbort = () => {
2472
+ clearTimeout(timeout);
2473
+ reject(options.signal?.reason);
2474
+ };
2475
+ const timeout = setTimeout(() => {
2476
+ options.signal?.removeEventListener("abort", onAbort);
2477
+ resolve();
2478
+ }, intervalMs);
2479
+ options.signal?.addEventListener("abort", onAbort, { once: true });
2480
+ });
2481
+ }
2272
2482
  }
2273
2483
  };
2274
2484
  };
@@ -2405,7 +2615,7 @@ var assertAllowedPreset = (preset, allowedPresets) => {
2405
2615
  var assertIndirectModels = (value, allowedModels, key = "") => {
2406
2616
  if (key === "model" && typeof value === "string")
2407
2617
  assertAllowedModel2(value, allowedModels);
2408
- if ((key === "models" || key === "analysis_models") && Array.isArray(value)) {
2618
+ if ((key === "models" || key === "analysis_models" || key === "allowed_models") && Array.isArray(value)) {
2409
2619
  for (const model of value) {
2410
2620
  if (typeof model === "string")
2411
2621
  assertAllowedModel2(model, allowedModels);
@@ -2600,8 +2810,14 @@ export {
2600
2810
  openrouterMessages,
2601
2811
  openrouter,
2602
2812
  openRouterModelMatchesRule,
2603
- createOpenRouterClient
2813
+ generateOpenRouterPKCE,
2814
+ exchangeOpenRouterAuthCode,
2815
+ estimateOpenRouterModelCost,
2816
+ estimateOpenRouterCost,
2817
+ createOpenRouterKeyLinks,
2818
+ createOpenRouterClient,
2819
+ createOpenRouterAuthorizationUrl
2604
2820
  };
2605
2821
 
2606
- //# debugId=29E9DB40EA495C0E64756E2164756E21
2822
+ //# debugId=FABF06EDFC815F9A64756E2164756E21
2607
2823
  //# sourceMappingURL=openrouter.js.map