@revojs/ai 0.2.7 → 0.2.9

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/index.d.ts CHANGED
@@ -613,5 +613,9 @@ export interface Provider {
613
613
  export declare function defineProvider<TProvider extends Provider>(provider: TProvider): TProvider;
614
614
  export declare function useAi<TSource extends Source<Provider> = typeof import("#providers").default>(scope: Scope): AiConnections<TSource>;
615
615
  export declare function mergeHeaders(...headers: Array<Record<string, string | undefined> | undefined>): Record<string, string>;
616
+ export declare function postJson(url: string, body: unknown, options?: {
617
+ headers?: Record<string, string | undefined>;
618
+ signal?: AbortSignal;
619
+ }): Promise<Response>;
616
620
  export declare function readDataFrames(response: Response): AsyncGenerator<string>;
617
621
  export declare function toStream<T>(read: () => AsyncGenerator<T>): ReadableStream<T>;
package/dist/index.js CHANGED
@@ -39,6 +39,16 @@ function mergeHeaders(...headers) {
39
39
  for (const record of headers) for (const [name, value] of Object.entries(record ?? {})) if (value !== void 0) merged[name] = value;
40
40
  return merged;
41
41
  }
42
+ async function postJson(url, body, options) {
43
+ const response = await globalThis.fetch(url, {
44
+ method: "POST",
45
+ headers: mergeHeaders({ "Content-Type": "application/json" }, options?.headers),
46
+ body: JSON.stringify(body),
47
+ signal: options?.signal
48
+ });
49
+ if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
50
+ return response;
51
+ }
42
52
  async function* readDataFrames(response) {
43
53
  const body = response.body;
44
54
  if (!body) throw new Error("AI provider response has no body");
@@ -73,4 +83,4 @@ function toStream(read) {
73
83
  });
74
84
  }
75
85
  //#endregion
76
- export { defineProvider, mergeHeaders, readDataFrames, toStream, useAi };
86
+ export { defineProvider, mergeHeaders, postJson, readDataFrames, toStream, useAi };
@@ -1,4 +1,4 @@
1
- import { mergeHeaders, readDataFrames, toStream } from "../index.js";
1
+ import { mergeHeaders, postJson, readDataFrames, toStream } from "../index.js";
2
2
  import { toJsonSchema } from "revojs/shared";
3
3
  //#region src/protocols/anthropic-messages.ts
4
4
  function toUsage(inputTokens, cacheRead, cacheWrite, outputTokens) {
@@ -308,17 +308,10 @@ async function* readParts(response, warnings) {
308
308
  };
309
309
  }
310
310
  async function post(config, options, body) {
311
- const response = await fetch(`${config.baseURL.replace(/\/+$/, "")}/messages`, {
312
- method: "POST",
313
- headers: {
314
- "Content-Type": "application/json",
315
- ...mergeHeaders(config.apiKey === void 0 ? {} : { "x-api-key": config.apiKey }, { "anthropic-version": "2023-06-01" }, options.headers)
316
- },
317
- body: JSON.stringify(body),
311
+ return postJson(`${config.baseURL.replace(/\/+$/, "")}/messages`, body, {
312
+ headers: mergeHeaders(config.apiKey === void 0 ? {} : { "x-api-key": config.apiKey }, { "anthropic-version": "2023-06-01" }, options.headers),
318
313
  signal: options.abortSignal
319
314
  });
320
- if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
321
- return response;
322
315
  }
323
316
  function messagesGenerateProtocol(config) {
324
317
  return async (options) => {
@@ -1,4 +1,4 @@
1
- import { mergeHeaders, readDataFrames, toStream } from "../index.js";
1
+ import { mergeHeaders, postJson, readDataFrames, toStream } from "../index.js";
2
2
  import { toJsonSchema } from "revojs/shared";
3
3
  //#region src/protocols/google-models.ts
4
4
  function toBase64(data) {
@@ -262,13 +262,10 @@ async function* readParts(response, warnings) {
262
262
  function geminiGenerateProtocol(config) {
263
263
  return async (options) => {
264
264
  const [body, warnings] = toBody(options);
265
- const response = await fetch(url(config, options.model, false), {
266
- method: "POST",
265
+ const response = await postJson(url(config, options.model, false), body, {
267
266
  headers: headers(config, options),
268
- body: JSON.stringify(body),
269
267
  signal: options.abortSignal
270
268
  });
271
- if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
272
269
  const data = await response.json();
273
270
  const content = [];
274
271
  let toolCount = 0;
@@ -313,13 +310,10 @@ function geminiGenerateProtocol(config) {
313
310
  function geminiStreamProtocol(config) {
314
311
  return async (options) => {
315
312
  const [body, warnings] = toBody(options);
316
- const response = await fetch(url(config, options.model, true), {
317
- method: "POST",
313
+ const response = await postJson(url(config, options.model, true), body, {
318
314
  headers: headers(config, options),
319
- body: JSON.stringify(body),
320
315
  signal: options.abortSignal
321
316
  });
322
- if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
323
317
  return {
324
318
  request: { body },
325
319
  response: { headers: Object.fromEntries(response.headers.entries()) },
@@ -1,4 +1,4 @@
1
- import { mergeHeaders, readDataFrames, toStream } from "../index.js";
1
+ import { mergeHeaders, postJson, readDataFrames, toStream } from "../index.js";
2
2
  import { toJsonSchema } from "revojs/shared";
3
3
  //#region src/protocols/openai-chat-completions.ts
4
4
  function toMessages(prompt) {
@@ -267,16 +267,10 @@ async function* readParts(response, warnings) {
267
267
  function chatCompletionsGenerateProtocol(config) {
268
268
  return async (options) => {
269
269
  const [body, warnings, url] = toBody(config, options, false);
270
- const response = await fetch(url, {
271
- method: "POST",
272
- headers: {
273
- "Content-Type": "application/json",
274
- ...mergeHeaders(config.apiKey === void 0 ? {} : { Authorization: `Bearer ${config.apiKey}` }, options.headers)
275
- },
276
- body: JSON.stringify(body),
270
+ const response = await postJson(url, body, {
271
+ headers: mergeHeaders(config.apiKey === void 0 ? {} : { Authorization: `Bearer ${config.apiKey}` }, options.headers),
277
272
  signal: options.abortSignal
278
273
  });
279
- if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
280
274
  const chunk = await response.json();
281
275
  const choice = chunk.choices?.at(0);
282
276
  if (choice?.message === void 0) throw new Error("AI provider responded without choices");
@@ -313,16 +307,10 @@ function chatCompletionsGenerateProtocol(config) {
313
307
  function chatCompletionsStreamProtocol(config) {
314
308
  return async (options) => {
315
309
  const [body, warnings, url] = toBody(config, options, true);
316
- const response = await fetch(url, {
317
- method: "POST",
318
- headers: {
319
- "Content-Type": "application/json",
320
- ...mergeHeaders(config.apiKey === void 0 ? {} : { Authorization: `Bearer ${config.apiKey}` }, options.headers)
321
- },
322
- body: JSON.stringify(body),
310
+ const response = await postJson(url, body, {
311
+ headers: mergeHeaders(config.apiKey === void 0 ? {} : { Authorization: `Bearer ${config.apiKey}` }, options.headers),
323
312
  signal: options.abortSignal
324
313
  });
325
- if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
326
314
  return {
327
315
  request: { body },
328
316
  response: { headers: Object.fromEntries(response.headers.entries()) },
@@ -1,4 +1,4 @@
1
- import { mergeHeaders, readDataFrames, toStream } from "../index.js";
1
+ import { mergeHeaders, postJson, readDataFrames, toStream } from "../index.js";
2
2
  import { toJsonSchema } from "revojs/shared";
3
3
  //#region src/protocols/openai-responses.ts
4
4
  function toUsage(usage) {
@@ -327,16 +327,10 @@ async function* readParts(response, warnings) {
327
327
  function responsesGenerateProtocol(config) {
328
328
  return async (options) => {
329
329
  const [body, warnings] = toBody(options, false);
330
- const response = await fetch(`${config.baseURL.replace(/\/+$/, "")}/responses`, {
331
- method: "POST",
332
- headers: {
333
- "Content-Type": "application/json",
334
- ...mergeHeaders(config.apiKey === void 0 ? {} : { Authorization: `Bearer ${config.apiKey}` }, options.headers)
335
- },
336
- body: JSON.stringify(body),
330
+ const response = await postJson(`${config.baseURL.replace(/\/+$/, "")}/responses`, body, {
331
+ headers: mergeHeaders(config.apiKey === void 0 ? {} : { Authorization: `Bearer ${config.apiKey}` }, options.headers),
337
332
  signal: options.abortSignal
338
333
  });
339
- if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
340
334
  const data = await response.json();
341
335
  const content = [];
342
336
  let toolCalls = false;
@@ -388,16 +382,10 @@ function responsesGenerateProtocol(config) {
388
382
  function responsesStreamProtocol(config) {
389
383
  return async (options) => {
390
384
  const [body, warnings] = toBody(options, true);
391
- const response = await fetch(`${config.baseURL.replace(/\/+$/, "")}/responses`, {
392
- method: "POST",
393
- headers: {
394
- "Content-Type": "application/json",
395
- ...mergeHeaders(config.apiKey === void 0 ? {} : { Authorization: `Bearer ${config.apiKey}` }, options.headers)
396
- },
397
- body: JSON.stringify(body),
385
+ const response = await postJson(`${config.baseURL.replace(/\/+$/, "")}/responses`, body, {
386
+ headers: mergeHeaders(config.apiKey === void 0 ? {} : { Authorization: `Bearer ${config.apiKey}` }, options.headers),
398
387
  signal: options.abortSignal
399
388
  });
400
- if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
401
389
  return {
402
390
  request: { body },
403
391
  response: { headers: Object.fromEntries(response.headers.entries()) },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revojs/ai",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",