@revojs/ai 0.2.64 → 0.3.0

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
@@ -821,6 +821,13 @@ export interface ProviderOptions {
821
821
  export interface Provider {
822
822
  setup: (scope: Scope, options?: ProviderOptions) => Awaitable<ProviderConnection>;
823
823
  }
824
+ export declare class ProviderError extends Error {
825
+ readonly status: number;
826
+ readonly body: string;
827
+ readonly retryAfter: number | undefined;
828
+ constructor(status: number, body: string, retryAfter?: number);
829
+ get detail(): string;
830
+ }
824
831
  export declare class ModelContextProtocolError extends Error {
825
832
  readonly code: number;
826
833
  readonly data?: JSONValue;
@@ -878,11 +885,26 @@ export declare function mergeHeaders(...headers: Array<Record<string, string | u
878
885
  export declare function postJson(url: string, body: unknown, options?: {
879
886
  headers?: Record<string, string | undefined>;
880
887
  signal?: AbortSignal;
888
+ retries?: number;
881
889
  }): Promise<Response>;
890
+ export declare function toRetryAfter(value: string | null): number | undefined;
891
+ export declare function toolResult(value: JSONValue | object): CallToolResult;
892
+ export declare function toolError(message: string, details?: JSONObject): CallToolResult;
893
+ export declare function generateText(scope: Scope, options: LanguageModelCallOptions & {
894
+ provider: string;
895
+ providerOptions?: ProviderOptions;
896
+ }): Promise<{
897
+ text: string;
898
+ result: LanguageModelGenerateResult;
899
+ }>;
882
900
  export declare function readDataFrames(response: Response): AsyncGenerator<string>;
883
901
  export declare function toStream<T>(read: () => AsyncGenerator<T>): ReadableStream<T>;
884
902
  export declare const MODEL_CONTEXT_PROTOCOL_VERSIONS: string[];
885
903
  export declare const MODEL_CONTEXT_PROTOCOL_TIMEOUT = 60000;
904
+ export declare const PROVIDER_RETRIES = 2;
905
+ export declare const PROVIDER_RETRY_DELAY = 1000;
906
+ export declare const PROVIDER_RETRY_MAX_DELAY = 30000;
907
+ export declare const RETRYABLE_PROVIDER_STATUSES: Set<number>;
886
908
  export declare const ModelContextProtocolErrorCode: {
887
909
  readonly ParseError: -32700;
888
910
  readonly InvalidRequest: -32600;
package/dist/index.js CHANGED
@@ -6,6 +6,29 @@ import { SERVER_CONTEXT, createServerScope, isResponse, requireSameOrigin, useSe
6
6
  import { useVariables } from "revojs";
7
7
  import { toJsonSchema } from "revojs/shared";
8
8
  //#region src/index.ts
9
+ var ProviderError = class extends Error {
10
+ status;
11
+ body;
12
+ retryAfter;
13
+ constructor(status, body, retryAfter) {
14
+ super(`AI provider responded with ${status}: ${body}`);
15
+ this.name = "ProviderError";
16
+ this.status = status;
17
+ this.body = body;
18
+ this.retryAfter = retryAfter;
19
+ }
20
+ get detail() {
21
+ try {
22
+ const value = JSON.parse(this.body);
23
+ if (typeof value === "object" && value !== null) {
24
+ const nested = "error" in value ? value.error : value;
25
+ if (typeof nested === "string") return nested;
26
+ if (typeof nested === "object" && nested !== null && "message" in nested) return String(nested.message);
27
+ }
28
+ } catch {}
29
+ return this.body.replace(/\s+/g, " ").trim();
30
+ }
31
+ };
9
32
  var ModelContextProtocolError = class extends Error {
10
33
  code;
11
34
  data;
@@ -652,14 +675,83 @@ function mergeHeaders(...headers) {
652
675
  return merged;
653
676
  }
654
677
  async function postJson(url, body, options) {
655
- const response = await globalThis.fetch(url, {
656
- method: "POST",
657
- headers: mergeHeaders({ "Content-Type": "application/json" }, options?.headers),
658
- body: JSON.stringify(body),
659
- signal: options?.signal
660
- });
661
- if (!response.ok) throw new Error(`AI provider responded with ${response.status}: ${(await response.text()).slice(0, 500)}`);
662
- return response;
678
+ const retries = options?.retries ?? 2;
679
+ for (let attempt = 0;; attempt += 1) {
680
+ const response = await globalThis.fetch(url, {
681
+ method: "POST",
682
+ headers: mergeHeaders({ "Content-Type": "application/json" }, options?.headers),
683
+ body: JSON.stringify(body),
684
+ signal: options?.signal
685
+ });
686
+ if (response.ok) return response;
687
+ const error = new ProviderError(response.status, (await response.text()).slice(0, 500), toRetryAfter(response.headers.get("Retry-After")));
688
+ if (attempt >= retries || !RETRYABLE_PROVIDER_STATUSES.has(response.status)) throw error;
689
+ const retryDelay = Math.min(PROVIDER_RETRY_MAX_DELAY, error.retryAfter ?? 1e3 * 2 ** attempt);
690
+ if (error.retryAfter !== void 0 && error.retryAfter > 3e4) throw error;
691
+ const waiting = Promise.withResolvers();
692
+ const timer = setTimeout(waiting.resolve, retryDelay);
693
+ options?.signal?.addEventListener("abort", () => {
694
+ clearTimeout(timer);
695
+ waiting.reject(options.signal?.reason);
696
+ }, { once: true });
697
+ await waiting.promise;
698
+ }
699
+ }
700
+ function toRetryAfter(value) {
701
+ if (value === null) return;
702
+ const seconds = Number(value);
703
+ if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
704
+ const date = Date.parse(value);
705
+ if (Number.isFinite(date)) return Math.max(0, date - Date.now());
706
+ }
707
+ function toolResult(value) {
708
+ const text = JSON.stringify(value);
709
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) return {
710
+ content: [{
711
+ type: "text",
712
+ text
713
+ }],
714
+ structuredContent: value
715
+ };
716
+ return { content: [{
717
+ type: "text",
718
+ text
719
+ }] };
720
+ }
721
+ function toolError(message, details) {
722
+ if (details) return {
723
+ content: [{
724
+ type: "text",
725
+ text: JSON.stringify({
726
+ error: message,
727
+ ...details
728
+ })
729
+ }],
730
+ structuredContent: {
731
+ error: message,
732
+ ...details
733
+ },
734
+ isError: true
735
+ };
736
+ return {
737
+ content: [{
738
+ type: "text",
739
+ text: message
740
+ }],
741
+ isError: true
742
+ };
743
+ }
744
+ async function generateText(scope, options) {
745
+ const { provider, providerOptions, ...call } = options;
746
+ const connection = useAi(scope, { [provider]: providerOptions })[provider];
747
+ if (connection?.textGenerate === void 0) throw new Error(`Unknown AI provider "${provider}".`);
748
+ const result = await connection.textGenerate(call);
749
+ let text = "";
750
+ for (const part of result.content) if (part.type === "text") text += part.text;
751
+ return {
752
+ text: text.trim(),
753
+ result
754
+ };
663
755
  }
664
756
  async function* readDataFrames(response) {
665
757
  const body = response.body;
@@ -719,6 +811,17 @@ var MODEL_CONTEXT_PROTOCOL_VERSIONS = [
719
811
  "2024-11-05"
720
812
  ];
721
813
  var MODEL_CONTEXT_PROTOCOL_TIMEOUT = 6e4;
814
+ var PROVIDER_RETRIES = 2;
815
+ var PROVIDER_RETRY_DELAY = 1e3;
816
+ var PROVIDER_RETRY_MAX_DELAY = 3e4;
817
+ var RETRYABLE_PROVIDER_STATUSES = /* @__PURE__ */ new Set([
818
+ 429,
819
+ 500,
820
+ 502,
821
+ 503,
822
+ 504,
823
+ 529
824
+ ]);
722
825
  var ModelContextProtocolErrorCode = {
723
826
  ParseError: -32700,
724
827
  InvalidRequest: -32600,
@@ -735,4 +838,4 @@ var JSON_SCHEMA_DRAFTS = {
735
838
  "http://json-schema.org/draft-04/schema#": "4"
736
839
  };
737
840
  //#endregion
738
- export { MODEL_CONTEXT_PROTOCOL_TIMEOUT, MODEL_CONTEXT_PROTOCOL_VERSIONS, ModelContextProtocolClient, ModelContextProtocolConnection, ModelContextProtocolError, ModelContextProtocolErrorCode, defineProvider, defineTool, handleModelContextProtocol, mergeHeaders, modelsDevProtocol, postJson, readDataFrames, toStream, toToolInput, toToolParameters, useAi, useModelContextProtocol, useModelsDev, useTools };
841
+ export { MODEL_CONTEXT_PROTOCOL_TIMEOUT, MODEL_CONTEXT_PROTOCOL_VERSIONS, ModelContextProtocolClient, ModelContextProtocolConnection, ModelContextProtocolError, ModelContextProtocolErrorCode, PROVIDER_RETRIES, PROVIDER_RETRY_DELAY, PROVIDER_RETRY_MAX_DELAY, ProviderError, RETRYABLE_PROVIDER_STATUSES, defineProvider, defineTool, generateText, handleModelContextProtocol, mergeHeaders, modelsDevProtocol, postJson, readDataFrames, toRetryAfter, toStream, toToolInput, toToolParameters, toolError, toolResult, useAi, useModelContextProtocol, useModelsDev, useTools };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revojs/ai",
3
- "version": "0.2.64",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -30,10 +30,10 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@cfworker/json-schema": "^4.1.1",
33
- "@revojs/server": "*",
34
- "revojs": "*"
33
+ "@revojs/server": "0.3.0",
34
+ "revojs": "0.3.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@revojs/tsconfig": "*"
37
+ "@revojs/tsconfig": "0.3.0"
38
38
  }
39
39
  }