@xiaozhiclaw/provider-core 0.1.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.
Files changed (93) hide show
  1. package/dist/adapters/aliyun-oss-file-upload-adapter.d.ts +44 -0
  2. package/dist/adapters/aliyun-oss-file-upload-adapter.js +96 -0
  3. package/dist/adapters/gemini-file-upload-adapter.d.ts +26 -0
  4. package/dist/adapters/gemini-file-upload-adapter.js +92 -0
  5. package/dist/adapters/hub-oss-file-upload-adapter.d.ts +29 -0
  6. package/dist/adapters/hub-oss-file-upload-adapter.js +53 -0
  7. package/dist/adapters/index.d.ts +10 -0
  8. package/dist/adapters/index.js +10 -0
  9. package/dist/adapters/openai-file-upload-adapter.d.ts +38 -0
  10. package/dist/adapters/openai-file-upload-adapter.js +56 -0
  11. package/dist/adapters/volcengine-file-upload-adapter.d.ts +24 -0
  12. package/dist/adapters/volcengine-file-upload-adapter.js +45 -0
  13. package/dist/builtin-providers.d.ts +8 -0
  14. package/dist/builtin-providers.js +2237 -0
  15. package/dist/constants.d.ts +1 -0
  16. package/dist/constants.js +1 -0
  17. package/dist/credentials.d.ts +1 -0
  18. package/dist/credentials.js +8 -0
  19. package/dist/debug-transport.d.ts +12 -0
  20. package/dist/debug-transport.js +99 -0
  21. package/dist/errors.d.ts +11 -0
  22. package/dist/errors.js +12 -0
  23. package/dist/events.d.ts +48 -0
  24. package/dist/events.js +1 -0
  25. package/dist/file-upload-service.d.ts +68 -0
  26. package/dist/file-upload-service.js +110 -0
  27. package/dist/gemini-schema-utils.d.ts +17 -0
  28. package/dist/gemini-schema-utils.js +76 -0
  29. package/dist/index.d.ts +37 -0
  30. package/dist/index.js +33 -0
  31. package/dist/llm-client.d.ts +43 -0
  32. package/dist/llm-client.js +217 -0
  33. package/dist/media-client.d.ts +42 -0
  34. package/dist/media-client.js +174 -0
  35. package/dist/media-transport.d.ts +176 -0
  36. package/dist/media-transport.js +16 -0
  37. package/dist/media.d.ts +2 -0
  38. package/dist/media.js +1 -0
  39. package/dist/model-detection.d.ts +22 -0
  40. package/dist/model-detection.js +28 -0
  41. package/dist/paths.d.ts +2 -0
  42. package/dist/paths.js +11 -0
  43. package/dist/provider-def.d.ts +220 -0
  44. package/dist/provider-def.js +9 -0
  45. package/dist/provider-registry.d.ts +51 -0
  46. package/dist/provider-registry.js +130 -0
  47. package/dist/provider-tool-api.d.ts +44 -0
  48. package/dist/provider-tool-api.js +9 -0
  49. package/dist/provider-variant-resolver.d.ts +35 -0
  50. package/dist/provider-variant-resolver.js +174 -0
  51. package/dist/retry.d.ts +37 -0
  52. package/dist/retry.js +71 -0
  53. package/dist/transport.d.ts +281 -0
  54. package/dist/transport.js +27 -0
  55. package/dist/transports/anthropic-messages.d.ts +65 -0
  56. package/dist/transports/anthropic-messages.js +1004 -0
  57. package/dist/transports/gemini-cache-api.d.ts +86 -0
  58. package/dist/transports/gemini-cache-api.js +141 -0
  59. package/dist/transports/gemini-file-api.d.ts +90 -0
  60. package/dist/transports/gemini-file-api.js +164 -0
  61. package/dist/transports/gemini-generatecontent.d.ts +56 -0
  62. package/dist/transports/gemini-generatecontent.js +688 -0
  63. package/dist/transports/gemini-lyria-realtime.d.ts +117 -0
  64. package/dist/transports/gemini-lyria-realtime.js +295 -0
  65. package/dist/transports/gemini-media.d.ts +53 -0
  66. package/dist/transports/gemini-media.js +383 -0
  67. package/dist/transports/media-resolve.d.ts +50 -0
  68. package/dist/transports/media-resolve.js +91 -0
  69. package/dist/transports/minimax-media.d.ts +56 -0
  70. package/dist/transports/minimax-media.js +433 -0
  71. package/dist/transports/openai-chat.d.ts +81 -0
  72. package/dist/transports/openai-chat.js +782 -0
  73. package/dist/transports/openai-media.d.ts +24 -0
  74. package/dist/transports/openai-media.js +118 -0
  75. package/dist/transports/openai-responses.d.ts +63 -0
  76. package/dist/transports/openai-responses.js +778 -0
  77. package/dist/transports/qwen-media.d.ts +59 -0
  78. package/dist/transports/qwen-media.js +411 -0
  79. package/dist/transports/realtime-transport.d.ts +183 -0
  80. package/dist/transports/realtime-transport.js +332 -0
  81. package/dist/transports/volcengine-grounding.d.ts +58 -0
  82. package/dist/transports/volcengine-grounding.js +69 -0
  83. package/dist/transports/volcengine-media.d.ts +94 -0
  84. package/dist/transports/volcengine-media.js +801 -0
  85. package/dist/transports/volcengine-responses.d.ts +64 -0
  86. package/dist/transports/volcengine-responses.js +797 -0
  87. package/dist/transports/zhipu-media.d.ts +82 -0
  88. package/dist/transports/zhipu-media.js +522 -0
  89. package/dist/transports/zhipu-tool-api.d.ts +35 -0
  90. package/dist/transports/zhipu-tool-api.js +126 -0
  91. package/dist/wire-types.d.ts +51 -0
  92. package/dist/wire-types.js +1 -0
  93. package/package.json +33 -0
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Aliyun OSS File Upload Adapter 鈥?direct upload to Alibaba Cloud OSS.
3
+ *
4
+ * Uploads files directly to OSS bucket using V1 signature (HMAC-SHA1).
5
+ * No external dependencies 鈥?uses Node.js crypto + fetch.
6
+ *
7
+ * This is the **universal fallback adapter** for providers without a native
8
+ * File Upload API (e.g. Anthropic). Ensures ALL file handling goes through
9
+ * upload 鈥?never base64 inline.
10
+ *
11
+ * Environment variables:
12
+ * OSS_ACCESS_KEY_ID 鈥?Aliyun AccessKey ID
13
+ * OSS_ACCESS_KEY_SECRET 鈥?Aliyun AccessKey Secret
14
+ * OSS_BUCKET 鈥?Bucket name (default: "qlogicagent")
15
+ * OSS_REGION 鈥?Region (default: "cn-beijing")
16
+ * OSS_ENDPOINT 鈥?Custom endpoint (default: derived from region)
17
+ */
18
+ import type { FileUploadAdapter, FileUploadResult } from "../file-upload-service.js";
19
+ export interface AliyunOSSFileUploadConfig {
20
+ /** Aliyun AccessKey ID. Required. */
21
+ accessKeyId: string;
22
+ /** Aliyun AccessKey Secret. Required. */
23
+ accessKeySecret: string;
24
+ /** OSS Bucket name. Default: "qlogicagent". */
25
+ bucket?: string;
26
+ /** OSS Region. Default: "cn-beijing". */
27
+ region?: string;
28
+ /** Custom OSS endpoint. Default: "{bucket}.oss-{region}.aliyuncs.com". */
29
+ endpoint?: string;
30
+ /** Upload path prefix. Default: "media". */
31
+ pathPrefix?: string;
32
+ /** Timeout ms. Default: 120_000. */
33
+ timeoutMs?: number;
34
+ }
35
+ /**
36
+ * Create an AliyunOSSFileUploadAdapter from environment variables.
37
+ * Returns undefined if required env vars (OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET) are missing.
38
+ */
39
+ export declare function createAliyunOSSAdapterFromEnv(): AliyunOSSFileUploadAdapter | undefined;
40
+ export declare class AliyunOSSFileUploadAdapter implements FileUploadAdapter {
41
+ private readonly config;
42
+ constructor(config: AliyunOSSFileUploadConfig);
43
+ uploadFile(buffer: Buffer, filename: string, mimeType: string, _apiKey: string, signal?: AbortSignal): Promise<FileUploadResult>;
44
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Aliyun OSS File Upload Adapter 鈥?direct upload to Alibaba Cloud OSS.
3
+ *
4
+ * Uploads files directly to OSS bucket using V1 signature (HMAC-SHA1).
5
+ * No external dependencies 鈥?uses Node.js crypto + fetch.
6
+ *
7
+ * This is the **universal fallback adapter** for providers without a native
8
+ * File Upload API (e.g. Anthropic). Ensures ALL file handling goes through
9
+ * upload 鈥?never base64 inline.
10
+ *
11
+ * Environment variables:
12
+ * OSS_ACCESS_KEY_ID 鈥?Aliyun AccessKey ID
13
+ * OSS_ACCESS_KEY_SECRET 鈥?Aliyun AccessKey Secret
14
+ * OSS_BUCKET 鈥?Bucket name (default: "qlogicagent")
15
+ * OSS_REGION 鈥?Region (default: "cn-beijing")
16
+ * OSS_ENDPOINT 鈥?Custom endpoint (default: derived from region)
17
+ */
18
+ import { createHmac, randomUUID } from "node:crypto";
19
+ /**
20
+ * Create an AliyunOSSFileUploadAdapter from environment variables.
21
+ * Returns undefined if required env vars (OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET) are missing.
22
+ */
23
+ export function createAliyunOSSAdapterFromEnv() {
24
+ const accessKeyId = (process.env.OSS_ACCESS_KEY_ID ?? process.env.ALIYUN_OSS_ACCESS_KEY_ID ?? "").trim();
25
+ const accessKeySecret = (process.env.OSS_ACCESS_KEY_SECRET ?? process.env.ALIYUN_OSS_ACCESS_KEY_SECRET ?? "").trim();
26
+ if (!accessKeyId || !accessKeySecret)
27
+ return undefined;
28
+ return new AliyunOSSFileUploadAdapter({
29
+ accessKeyId,
30
+ accessKeySecret,
31
+ bucket: (process.env.OSS_BUCKET ?? process.env.ALIYUN_OSS_BUCKET ?? "qlogicagent").trim(),
32
+ region: (process.env.OSS_REGION ?? process.env.ALIYUN_OSS_REGION ?? "cn-beijing").trim(),
33
+ endpoint: (process.env.OSS_ENDPOINT ?? "").trim() || undefined,
34
+ });
35
+ }
36
+ export class AliyunOSSFileUploadAdapter {
37
+ config;
38
+ constructor(config) {
39
+ const bucket = config.bucket || "qlogicagent";
40
+ const region = config.region || "cn-beijing";
41
+ this.config = {
42
+ accessKeyId: config.accessKeyId,
43
+ accessKeySecret: config.accessKeySecret,
44
+ bucket,
45
+ region,
46
+ endpoint: config.endpoint || `${bucket}.oss-${region}.aliyuncs.com`,
47
+ pathPrefix: config.pathPrefix || "media",
48
+ timeoutMs: config.timeoutMs ?? 120_000,
49
+ };
50
+ }
51
+ async uploadFile(buffer, filename, mimeType, _apiKey, signal) {
52
+ // Generate unique object key: media/2026-05-20/a1b2c3d4_filename.png
53
+ const date = new Date().toISOString().slice(0, 10); // 2026-05-20
54
+ const uid = randomUUID().slice(0, 8);
55
+ const safeName = filename.replace(/[^a-zA-Z0-9._-]/g, "_");
56
+ const objectKey = `${this.config.pathPrefix}/${date}/${uid}_${safeName}`;
57
+ // Build request
58
+ const url = `https://${this.config.endpoint}/${objectKey}`;
59
+ const dateStr = new Date().toUTCString();
60
+ // OSS V1 Signature
61
+ const stringToSign = [
62
+ "PUT",
63
+ "", // Content-MD5 (optional)
64
+ mimeType,
65
+ dateStr,
66
+ `/${this.config.bucket}/${objectKey}`,
67
+ ].join("\n");
68
+ const signature = createHmac("sha1", this.config.accessKeySecret)
69
+ .update(stringToSign)
70
+ .digest("base64");
71
+ const headers = {
72
+ "Date": dateStr,
73
+ "Content-Type": mimeType,
74
+ "Content-Length": String(buffer.byteLength),
75
+ "Authorization": `OSS ${this.config.accessKeyId}:${signature}`,
76
+ };
77
+ const res = await fetch(url, {
78
+ method: "PUT",
79
+ headers,
80
+ body: buffer,
81
+ signal: signal ?? AbortSignal.timeout(this.config.timeoutMs),
82
+ });
83
+ if (!res.ok) {
84
+ const body = await res.text().catch(() => "");
85
+ throw new Error(`Aliyun OSS upload failed ${res.status}: ${body.slice(0, 300)}`);
86
+ }
87
+ return {
88
+ url,
89
+ fileId: objectKey,
90
+ filename: safeName,
91
+ bytes: buffer.byteLength,
92
+ mimeType,
93
+ provider: "aliyun-oss",
94
+ };
95
+ }
96
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Gemini File Upload Adapter.
3
+ *
4
+ * Implements the Google Gemini 2-step resumable upload protocol
5
+ * into the unified FileUploadAdapter interface.
6
+ *
7
+ * Protocol:
8
+ * 1. POST /upload/v1beta/files 鈥?initiate, get upload URL
9
+ * 2. PUT {uploadUrl} 鈥?send bytes, finalize
10
+ *
11
+ * Returns a file URI (e.g. "files/abc123") that can be used in
12
+ * generateContent requests as a file reference.
13
+ */
14
+ import type { FileUploadAdapter, FileUploadResult } from "../file-upload-service.js";
15
+ export interface GeminiFileUploadConfig {
16
+ /** Base URL (e.g. "https://generativelanguage.googleapis.com/v1beta") */
17
+ baseUrl: string;
18
+ /** Timeout ms. Default: 180_000. */
19
+ timeoutMs?: number;
20
+ }
21
+ export declare class GeminiFileUploadAdapter implements FileUploadAdapter {
22
+ private readonly config;
23
+ constructor(config: GeminiFileUploadConfig);
24
+ uploadFile(buffer: Buffer, filename: string, mimeType: string, apiKey: string, signal?: AbortSignal): Promise<FileUploadResult>;
25
+ private waitForProcessing;
26
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Gemini File Upload Adapter.
3
+ *
4
+ * Implements the Google Gemini 2-step resumable upload protocol
5
+ * into the unified FileUploadAdapter interface.
6
+ *
7
+ * Protocol:
8
+ * 1. POST /upload/v1beta/files 鈥?initiate, get upload URL
9
+ * 2. PUT {uploadUrl} 鈥?send bytes, finalize
10
+ *
11
+ * Returns a file URI (e.g. "files/abc123") that can be used in
12
+ * generateContent requests as a file reference.
13
+ */
14
+ export class GeminiFileUploadAdapter {
15
+ config;
16
+ constructor(config) {
17
+ this.config = config;
18
+ }
19
+ async uploadFile(buffer, filename, mimeType, apiKey, signal) {
20
+ const timeout = this.config.timeoutMs ?? 180_000;
21
+ const effectiveSignal = signal ?? AbortSignal.timeout(timeout);
22
+ // Step 1: Initiate resumable upload
23
+ const uploadInitUrl = this.config.baseUrl.replace(/(\/v1beta)$/, "/upload$1/files");
24
+ const initRes = await fetch(uploadInitUrl, {
25
+ method: "POST",
26
+ headers: {
27
+ "x-goog-api-key": apiKey,
28
+ "X-Goog-Upload-Protocol": "resumable",
29
+ "X-Goog-Upload-Command": "start",
30
+ "X-Goog-Upload-Header-Content-Length": String(buffer.length),
31
+ "X-Goog-Upload-Header-Content-Type": mimeType,
32
+ "Content-Type": "application/json",
33
+ },
34
+ body: JSON.stringify({ file: { display_name: filename } }),
35
+ signal: effectiveSignal,
36
+ });
37
+ if (!initRes.ok) {
38
+ const text = await initRes.text().catch(() => "");
39
+ throw new Error(`Gemini file upload init failed (${initRes.status}): ${text.slice(0, 500)}`);
40
+ }
41
+ const uploadUrl = initRes.headers.get("x-goog-upload-url");
42
+ if (!uploadUrl) {
43
+ throw new Error("Gemini file upload: missing x-goog-upload-url in response");
44
+ }
45
+ // Step 2: Upload bytes
46
+ const uploadRes = await fetch(uploadUrl, {
47
+ method: "PUT",
48
+ headers: {
49
+ "Content-Length": String(buffer.length),
50
+ "X-Goog-Upload-Offset": "0",
51
+ "X-Goog-Upload-Command": "upload, finalize",
52
+ },
53
+ body: buffer,
54
+ signal: effectiveSignal,
55
+ });
56
+ if (!uploadRes.ok) {
57
+ const text = await uploadRes.text().catch(() => "");
58
+ throw new Error(`Gemini file upload failed (${uploadRes.status}): ${text.slice(0, 500)}`);
59
+ }
60
+ const data = await uploadRes.json();
61
+ const fileInfo = data.file;
62
+ // Wait for processing if video/audio (they start in PROCESSING state)
63
+ if (fileInfo.state === "PROCESSING") {
64
+ await this.waitForProcessing(fileInfo.name, apiKey, effectiveSignal);
65
+ }
66
+ return {
67
+ url: fileInfo.uri, // e.g. "https://generativelanguage.googleapis.com/v1beta/files/abc123"
68
+ fileId: fileInfo.name,
69
+ filename,
70
+ bytes: parseInt(fileInfo.sizeBytes ?? "0", 10) || buffer.length,
71
+ mimeType,
72
+ provider: "gemini",
73
+ };
74
+ }
75
+ async waitForProcessing(fileName, apiKey, signal, maxRetries = 30) {
76
+ const getUrl = `${this.config.baseUrl}/files/${fileName.replace("files/", "")}`;
77
+ for (let i = 0; i < maxRetries; i++) {
78
+ await new Promise((r) => setTimeout(r, 2000));
79
+ if (signal.aborted)
80
+ throw new Error("Upload aborted during processing wait");
81
+ const res = await fetch(`${getUrl}?key=${apiKey}`, { signal });
82
+ if (!res.ok)
83
+ continue;
84
+ const data = await res.json();
85
+ if (data.state === "ACTIVE")
86
+ return;
87
+ if (data.state === "FAILED")
88
+ throw new Error("Gemini file processing failed");
89
+ }
90
+ // If we exhaust retries, proceed anyway 鈥?LLM might still accept it
91
+ }
92
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Hub OSS File Upload Adapter 鈥?for providers without native File API (e.g. Anthropic).
3
+ *
4
+ * Uploads local files to the Hub's OSS relay endpoint, which stores them in
5
+ * cloud object storage (Aliyun OSS / Tencent COS) and returns a public URL.
6
+ * The LLM provider can then access the file via this public URL.
7
+ *
8
+ * This enables Anthropic (which only supports base64 inline or public URL)
9
+ * to handle large files that exceed the base64 size limit (20MB).
10
+ *
11
+ * Endpoint: POST {hubBaseUrl}/api/v1/files/upload
12
+ * Returns: { url: "https://oss-bucket.oss-cn-xxx.aliyuncs.com/..." }
13
+ */
14
+ import type { FileUploadAdapter, FileUploadResult } from "../file-upload-service.js";
15
+ export interface HubOSSFileUploadConfig {
16
+ /** Hub API base URL (e.g. "https://hub.xiaozhiclaw.com" or from env). */
17
+ hubBaseUrl: string;
18
+ /** Hub API key for authentication. */
19
+ hubApiKey?: string;
20
+ /** Timeout ms. Default: 120_000. */
21
+ timeoutMs?: number;
22
+ /** Provider name for result metadata. Default: "hub-oss". */
23
+ provider?: string;
24
+ }
25
+ export declare class HubOSSFileUploadAdapter implements FileUploadAdapter {
26
+ private readonly config;
27
+ constructor(config: HubOSSFileUploadConfig);
28
+ uploadFile(buffer: Buffer, filename: string, mimeType: string, _apiKey: string, signal?: AbortSignal): Promise<FileUploadResult>;
29
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Hub OSS File Upload Adapter 鈥?for providers without native File API (e.g. Anthropic).
3
+ *
4
+ * Uploads local files to the Hub's OSS relay endpoint, which stores them in
5
+ * cloud object storage (Aliyun OSS / Tencent COS) and returns a public URL.
6
+ * The LLM provider can then access the file via this public URL.
7
+ *
8
+ * This enables Anthropic (which only supports base64 inline or public URL)
9
+ * to handle large files that exceed the base64 size limit (20MB).
10
+ *
11
+ * Endpoint: POST {hubBaseUrl}/api/v1/files/upload
12
+ * Returns: { url: "https://oss-bucket.oss-cn-xxx.aliyuncs.com/..." }
13
+ */
14
+ export class HubOSSFileUploadAdapter {
15
+ config;
16
+ constructor(config) {
17
+ this.config = config;
18
+ }
19
+ async uploadFile(buffer, filename, mimeType, _apiKey, signal) {
20
+ const hubBaseUrl = this.config.hubBaseUrl.replace(/\/+$/, "");
21
+ const url = `${hubBaseUrl}/api/v1/files/upload`;
22
+ const formData = new FormData();
23
+ const blob = new Blob([buffer], { type: mimeType });
24
+ formData.append("file", blob, filename);
25
+ formData.append("purpose", "llm_input");
26
+ const headers = {};
27
+ if (this.config.hubApiKey) {
28
+ headers["Authorization"] = `Bearer ${this.config.hubApiKey}`;
29
+ }
30
+ const res = await fetch(url, {
31
+ method: "POST",
32
+ headers,
33
+ body: formData,
34
+ signal: signal ?? AbortSignal.timeout(this.config.timeoutMs ?? 120_000),
35
+ });
36
+ if (!res.ok) {
37
+ const body = await res.text().catch(() => "");
38
+ throw new Error(`Hub OSS upload failed ${res.status}: ${body.slice(0, 200)}`);
39
+ }
40
+ const json = await res.json();
41
+ if (!json.url) {
42
+ throw new Error("Hub OSS upload response missing 'url' field");
43
+ }
44
+ return {
45
+ url: json.url,
46
+ fileId: json.fileId ?? filename,
47
+ filename,
48
+ bytes: json.bytes ?? buffer.byteLength,
49
+ mimeType,
50
+ provider: this.config.provider ?? "hub-oss",
51
+ };
52
+ }
53
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * File Upload Adapters 鈥?barrel export.
3
+ *
4
+ * Provider-specific implementations of the FileUploadAdapter interface.
5
+ */
6
+ export { OpenAIFileUploadAdapter, type OpenAIFileUploadConfig } from "./openai-file-upload-adapter.js";
7
+ export { VolcengineFileUploadAdapter, type VolcengineFileUploadConfig } from "./volcengine-file-upload-adapter.js";
8
+ export { GeminiFileUploadAdapter, type GeminiFileUploadConfig } from "./gemini-file-upload-adapter.js";
9
+ export { HubOSSFileUploadAdapter, type HubOSSFileUploadConfig } from "./hub-oss-file-upload-adapter.js";
10
+ export { AliyunOSSFileUploadAdapter, type AliyunOSSFileUploadConfig, createAliyunOSSAdapterFromEnv } from "./aliyun-oss-file-upload-adapter.js";
@@ -0,0 +1,10 @@
1
+ /**
2
+ * File Upload Adapters 鈥?barrel export.
3
+ *
4
+ * Provider-specific implementations of the FileUploadAdapter interface.
5
+ */
6
+ export { OpenAIFileUploadAdapter } from "./openai-file-upload-adapter.js";
7
+ export { VolcengineFileUploadAdapter } from "./volcengine-file-upload-adapter.js";
8
+ export { GeminiFileUploadAdapter } from "./gemini-file-upload-adapter.js";
9
+ export { HubOSSFileUploadAdapter } from "./hub-oss-file-upload-adapter.js";
10
+ export { AliyunOSSFileUploadAdapter, createAliyunOSSAdapterFromEnv } from "./aliyun-oss-file-upload-adapter.js";
@@ -0,0 +1,38 @@
1
+ /**
2
+ * OpenAI-compatible File Upload Adapter.
3
+ *
4
+ * Implements FileUploadAdapter for providers using the standard
5
+ * POST /v1/files multipart upload endpoint:
6
+ * - OpenAI
7
+ * - Kimi (Moonshot)
8
+ * - Minimax
9
+ * - Qwen (via DashScope compatible endpoint)
10
+ * - GLM (Zhipu)
11
+ * - Any OpenAI-API-compatible provider
12
+ *
13
+ * The uploaded file gets a file_id which can be referenced in messages.
14
+ * Some providers also return a direct download URL.
15
+ */
16
+ import type { FileUploadAdapter, FileUploadResult } from "../file-upload-service.js";
17
+ export interface OpenAIFileUploadConfig {
18
+ /** Base URL (e.g. "https://api.openai.com/v1" or "https://api.moonshot.cn/v1") */
19
+ baseUrl: string;
20
+ /** Provider name for result metadata. */
21
+ provider: string;
22
+ /** Extra headers to include (e.g. for Minimax group_id). */
23
+ extraHeaders?: Record<string, string>;
24
+ /** Upload purpose (default: "file-extract" for document understanding). */
25
+ defaultPurpose?: string;
26
+ /**
27
+ * Whether the provider returns a download URL in the upload response.
28
+ * If false, constructs URL from file_id (provider-specific).
29
+ */
30
+ returnsUrl?: boolean;
31
+ /** Timeout for upload request (ms). Default: 120_000. */
32
+ timeoutMs?: number;
33
+ }
34
+ export declare class OpenAIFileUploadAdapter implements FileUploadAdapter {
35
+ private readonly config;
36
+ constructor(config: OpenAIFileUploadConfig);
37
+ uploadFile(buffer: Buffer, filename: string, mimeType: string, apiKey: string, signal?: AbortSignal): Promise<FileUploadResult>;
38
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * OpenAI-compatible File Upload Adapter.
3
+ *
4
+ * Implements FileUploadAdapter for providers using the standard
5
+ * POST /v1/files multipart upload endpoint:
6
+ * - OpenAI
7
+ * - Kimi (Moonshot)
8
+ * - Minimax
9
+ * - Qwen (via DashScope compatible endpoint)
10
+ * - GLM (Zhipu)
11
+ * - Any OpenAI-API-compatible provider
12
+ *
13
+ * The uploaded file gets a file_id which can be referenced in messages.
14
+ * Some providers also return a direct download URL.
15
+ */
16
+ export class OpenAIFileUploadAdapter {
17
+ config;
18
+ constructor(config) {
19
+ this.config = config;
20
+ }
21
+ async uploadFile(buffer, filename, mimeType, apiKey, signal) {
22
+ const baseUrl = this.config.baseUrl.replace(/\/+$/, "");
23
+ // Handle both "/v1" and non-versioned base URLs
24
+ const hasVersion = /\/v\d+$/.test(baseUrl);
25
+ const url = hasVersion ? `${baseUrl}/files` : `${baseUrl}/v1/files`;
26
+ const formData = new FormData();
27
+ const blob = new Blob([buffer], { type: mimeType });
28
+ formData.append("file", blob, filename);
29
+ formData.append("purpose", this.config.defaultPurpose ?? "file-extract");
30
+ const res = await fetch(url, {
31
+ method: "POST",
32
+ headers: {
33
+ Authorization: `Bearer ${apiKey}`,
34
+ ...this.config.extraHeaders,
35
+ },
36
+ body: formData,
37
+ signal: signal ?? AbortSignal.timeout(this.config.timeoutMs ?? 120_000),
38
+ });
39
+ if (!res.ok) {
40
+ const errText = await res.text().catch(() => "");
41
+ throw new Error(`File upload to ${this.config.provider} failed (${res.status}): ${errText}`);
42
+ }
43
+ const data = await res.json();
44
+ const fileId = String(data.id ?? "");
45
+ // Some providers return download_url or url directly
46
+ const directUrl = String(data.download_url ?? data.url ?? data.file_url ?? "");
47
+ return {
48
+ url: directUrl || fileId, // If no URL, file_id is used as reference
49
+ fileId,
50
+ filename: String(data.filename ?? filename),
51
+ bytes: Number(data.bytes ?? buffer.byteLength),
52
+ mimeType,
53
+ provider: this.config.provider,
54
+ };
55
+ }
56
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Volcengine File Upload Adapter.
3
+ *
4
+ * Wraps the Volcengine /v3/files endpoint into the unified
5
+ * FileUploadAdapter interface.
6
+ *
7
+ * Volcengine returns a file_id that can be used in API messages
8
+ * as a file reference. Files uploaded this way can be referenced in
9
+ * multimodal inputs via the file_id field.
10
+ */
11
+ import type { FileUploadAdapter, FileUploadResult } from "../file-upload-service.js";
12
+ export interface VolcengineFileUploadConfig {
13
+ /** Base URL (e.g. "https://ark.cn-beijing.volces.com/api") */
14
+ baseUrl: string;
15
+ /** Upload purpose. Default: "user_data". */
16
+ defaultPurpose?: string;
17
+ /** Timeout ms. Default: 120_000. */
18
+ timeoutMs?: number;
19
+ }
20
+ export declare class VolcengineFileUploadAdapter implements FileUploadAdapter {
21
+ private readonly config;
22
+ constructor(config: VolcengineFileUploadConfig);
23
+ uploadFile(buffer: Buffer, filename: string, mimeType: string, apiKey: string, signal?: AbortSignal): Promise<FileUploadResult>;
24
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Volcengine File Upload Adapter.
3
+ *
4
+ * Wraps the Volcengine /v3/files endpoint into the unified
5
+ * FileUploadAdapter interface.
6
+ *
7
+ * Volcengine returns a file_id that can be used in API messages
8
+ * as a file reference. Files uploaded this way can be referenced in
9
+ * multimodal inputs via the file_id field.
10
+ */
11
+ export class VolcengineFileUploadAdapter {
12
+ config;
13
+ constructor(config) {
14
+ this.config = config;
15
+ }
16
+ async uploadFile(buffer, filename, mimeType, apiKey, signal) {
17
+ const baseUrl = this.config.baseUrl.replace(/\/+$/, "");
18
+ const url = `${baseUrl}/v3/files`;
19
+ const formData = new FormData();
20
+ const blob = new Blob([buffer], { type: mimeType });
21
+ formData.append("file", blob, filename);
22
+ formData.append("purpose", this.config.defaultPurpose ?? "user_data");
23
+ const res = await fetch(url, {
24
+ method: "POST",
25
+ headers: { Authorization: `Bearer ${apiKey}` },
26
+ body: formData,
27
+ signal: signal ?? AbortSignal.timeout(this.config.timeoutMs ?? 120_000),
28
+ });
29
+ if (!res.ok) {
30
+ const errText = await res.text().catch(() => "");
31
+ throw new Error(`Volcengine file upload failed (${res.status}): ${errText}`);
32
+ }
33
+ const data = await res.json();
34
+ const fileId = String(data.id ?? "");
35
+ return {
36
+ // Volcengine uses file_id reference in messages, not a direct URL
37
+ url: fileId,
38
+ fileId,
39
+ filename,
40
+ bytes: buffer.byteLength,
41
+ mimeType,
42
+ provider: "volcengine",
43
+ };
44
+ }
45
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Curated Provider Core model catalog.
3
+ *
4
+ * This is the single source used by qlogicagent direct mode and llmrouter's
5
+ * model catalog API. External broad catalogs are intentionally not merged in.
6
+ */
7
+ import type { ProviderDef } from "./provider-def.js";
8
+ export declare const BUILTIN_PROVIDERS: ProviderDef[];