ai-world-sdk 1.2.1 → 1.2.2

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.
@@ -0,0 +1,8 @@
1
+ /**
2
+ * ResourceClient 集成测试
3
+ * 使用真实 SDK 调用后端 /api/resources 接口
4
+ * 需要后端运行 + MinIO 服务 + 数据库可用
5
+ *
6
+ * 运行: npx jest --testPathPattern=resource.test.ts
7
+ */
8
+ export {};
@@ -0,0 +1,208 @@
1
+ "use strict";
2
+ /**
3
+ * ResourceClient 集成测试
4
+ * 使用真实 SDK 调用后端 /api/resources 接口
5
+ * 需要后端运行 + MinIO 服务 + 数据库可用
6
+ *
7
+ * 运行: npx jest --testPathPattern=resource.test.ts
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ const dotenv = __importStar(require("dotenv"));
44
+ const index_1 = require("../index");
45
+ dotenv.config();
46
+ index_1.sdkConfig.setBaseUrl("http://localhost:8000");
47
+ index_1.sdkConfig.setToken(process.env.AUTH_TOKEN || process.env.TOKEN || "");
48
+ index_1.sdkConfig.setDebug(true);
49
+ const PLUGIN_ID = "test-plugin";
50
+ describe("ResourceClient 测试", () => {
51
+ let client;
52
+ let uploadedResourceId;
53
+ beforeAll(() => {
54
+ index_1.sdkConfig.setPluginId(PLUGIN_ID);
55
+ client = new index_1.ResourceClient();
56
+ });
57
+ // ==================== 上传 ====================
58
+ test("上传资源 - 默认 private", async () => {
59
+ const content = "Resource test content: " + Date.now();
60
+ const blob = new Blob([content], { type: "text/plain" });
61
+ const file = new File([blob], "resource-test.txt", { type: "text/plain" });
62
+ const result = await client.upload("test/resource-test.txt", file);
63
+ expect(result).toBeDefined();
64
+ expect(result.id).toBeDefined();
65
+ expect(result.path).toBe("test/resource-test.txt");
66
+ expect(result.access_level).toBe("private");
67
+ expect(result.owner_id).toBeDefined();
68
+ expect(result.plugin_id).toBe(PLUGIN_ID);
69
+ expect(result.size).toBeGreaterThan(0);
70
+ uploadedResourceId = result.id;
71
+ console.log("上传成功:", result);
72
+ }, 30000);
73
+ test("上传资源 - public 带描述", async () => {
74
+ const blob = new Blob(["public content"], { type: "text/plain" });
75
+ const file = new File([blob], "public-file.txt", { type: "text/plain" });
76
+ const result = await client.upload("test/public-file.txt", file, {
77
+ accessLevel: "public",
78
+ description: "公开测试文件",
79
+ });
80
+ expect(result).toBeDefined();
81
+ expect(result.access_level).toBe("public");
82
+ expect(result.description).toBe("公开测试文件");
83
+ console.log("公开资源上传成功:", result);
84
+ }, 30000);
85
+ // ==================== 列表 ====================
86
+ test("列出我的资源", async () => {
87
+ const resources = await client.listMy();
88
+ expect(resources).toBeDefined();
89
+ expect(Array.isArray(resources)).toBe(true);
90
+ expect(resources.length).toBeGreaterThan(0);
91
+ const testFile = resources.find((r) => r.path === "test/resource-test.txt");
92
+ expect(testFile).toBeDefined();
93
+ console.log(`我的资源 (${resources.length} 个):`, resources.map((r) => r.path));
94
+ }, 30000);
95
+ test("列出公开资源", async () => {
96
+ const resources = await client.listPublic();
97
+ expect(resources).toBeDefined();
98
+ expect(Array.isArray(resources)).toBe(true);
99
+ const publicFile = resources.find((r) => r.path === "test/public-file.txt");
100
+ expect(publicFile).toBeDefined();
101
+ console.log(`公开资源 (${resources.length} 个):`, resources.map((r) => r.path));
102
+ }, 30000);
103
+ // ==================== 获取详情 ====================
104
+ test("获取资源详情", async () => {
105
+ expect(uploadedResourceId).toBeDefined();
106
+ const info = await client.getInfo(uploadedResourceId);
107
+ expect(info).toBeDefined();
108
+ expect(info.id).toBe(uploadedResourceId);
109
+ expect(info.path).toBe("test/resource-test.txt");
110
+ expect(info.filename).toBe("resource-test.txt");
111
+ console.log("资源详情:", info);
112
+ }, 30000);
113
+ // ==================== 修改权限 ====================
114
+ test("修改访问级别为 public", async () => {
115
+ expect(uploadedResourceId).toBeDefined();
116
+ const updated = await client.updateAccess(uploadedResourceId, "public");
117
+ expect(updated).toBeDefined();
118
+ expect(updated.access_level).toBe("public");
119
+ console.log("访问级别已更新:", updated.access_level);
120
+ }, 30000);
121
+ test("修改访问级别为 specific_users", async () => {
122
+ expect(uploadedResourceId).toBeDefined();
123
+ const updated = await client.updateAccess(uploadedResourceId, "specific_users");
124
+ expect(updated).toBeDefined();
125
+ expect(updated.access_level).toBe("specific_users");
126
+ console.log("访问级别已更新:", updated.access_level);
127
+ }, 30000);
128
+ // ==================== 批量分享 ====================
129
+ test("批量添加分享 - 单个用户", async () => {
130
+ expect(uploadedResourceId).toBeDefined();
131
+ const result = await client.addShare(uploadedResourceId, 99);
132
+ expect(result).toBeDefined();
133
+ expect(result.resource_id).toBe(uploadedResourceId);
134
+ expect(result.total_requested).toBe(1);
135
+ console.log("批量添加分享(单个):", result);
136
+ }, 30000);
137
+ test("批量添加分享 - 多个用户", async () => {
138
+ expect(uploadedResourceId).toBeDefined();
139
+ const result = await client.addShare(uploadedResourceId, [100, 101]);
140
+ expect(result).toBeDefined();
141
+ expect(result.total_requested).toBe(2);
142
+ console.log("批量添加分享(多个):", result);
143
+ }, 30000);
144
+ test("批量移除分享 - 多个用户", async () => {
145
+ expect(uploadedResourceId).toBeDefined();
146
+ const result = await client.removeShare(uploadedResourceId, [99, 100, 101]);
147
+ expect(result).toBeDefined();
148
+ expect(result.total_requested).toBe(3);
149
+ console.log("批量移除分享:", result);
150
+ }, 30000);
151
+ // ==================== 下载 ====================
152
+ test("通过资源 ID 下载", async () => {
153
+ expect(uploadedResourceId).toBeDefined();
154
+ // 先改回 private 验证 owner 仍可下载
155
+ await client.updateAccess(uploadedResourceId, "private");
156
+ const blob = await client.download(uploadedResourceId);
157
+ expect(blob).toBeDefined();
158
+ expect(blob.size).toBeGreaterThan(0);
159
+ console.log("下载成功, 大小:", blob.size);
160
+ }, 30000);
161
+ // ==================== 列出被分享的 ====================
162
+ test("列出被分享给我的资源", async () => {
163
+ const resources = await client.listSharedWithMe();
164
+ expect(resources).toBeDefined();
165
+ expect(Array.isArray(resources)).toBe(true);
166
+ console.log(`被分享资源 (${resources.length} 个)`);
167
+ }, 30000);
168
+ // ==================== 跨插件 ====================
169
+ test("列出我的资源 - 跨插件", async () => {
170
+ const resources = await client.listMy({ crossPlugin: true });
171
+ expect(resources).toBeDefined();
172
+ expect(Array.isArray(resources)).toBe(true);
173
+ console.log(`跨插件资源 (${resources.length} 个)`);
174
+ }, 30000);
175
+ // ==================== 删除 ====================
176
+ test("删除资源", async () => {
177
+ expect(uploadedResourceId).toBeDefined();
178
+ await client.delete(uploadedResourceId);
179
+ console.log("资源已删除:", uploadedResourceId);
180
+ // 验证已删除
181
+ try {
182
+ await client.getInfo(uploadedResourceId);
183
+ fail("应该抛出错误");
184
+ }
185
+ catch (e) {
186
+ expect(e.message).toContain("404");
187
+ }
188
+ }, 30000);
189
+ // 清理 public-file
190
+ test("清理测试资源", async () => {
191
+ const resources = await client.listMy();
192
+ const publicFile = resources.find((r) => r.path === "test/public-file.txt");
193
+ if (publicFile) {
194
+ await client.delete(publicFile.id);
195
+ console.log("清理 public-file:", publicFile.id);
196
+ }
197
+ }, 30000);
198
+ // ==================== 插件 ID 验证 ====================
199
+ test("缺少 pluginId 时抛出错误", () => {
200
+ const originalPluginId = index_1.sdkConfig.getPluginId();
201
+ index_1.sdkConfig.setPluginId("");
202
+ const badClient = new index_1.ResourceClient();
203
+ expect(() => {
204
+ badClient.ensurePluginId();
205
+ }).toThrow("X-Plugin-Id is required");
206
+ index_1.sdkConfig.setPluginId(originalPluginId || PLUGIN_ID);
207
+ });
208
+ });
package/dist/config.d.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * 注意: {VERSION} 占位符会在构建时被替换为实际版本号
11
11
  */
12
- export declare const SDK_SIGNATURE = "AI_WORLD_SDK_V:1.2.1";
12
+ export declare const SDK_SIGNATURE = "AI_WORLD_SDK_V:1.2.2";
13
13
  /**
14
14
  * 版本兼容性错误
15
15
  */
@@ -24,8 +24,8 @@ declare class SDKConfig {
24
24
  private _pluginId;
25
25
  private _versionCompatible;
26
26
  private _versionCheckPromise;
27
- readonly sdkSignature = "AI_WORLD_SDK_V:1.2.1";
28
- readonly sdkVersion = "1.2.1";
27
+ readonly sdkSignature = "AI_WORLD_SDK_V:1.2.2";
28
+ readonly sdkVersion = "1.2.2";
29
29
  constructor();
30
30
  /**
31
31
  * Set global base URL
package/dist/config.js CHANGED
@@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.sdkConfig = exports.VersionCompatibilityError = exports.SDK_SIGNATURE = void 0;
8
8
  // SDK 版本号(构建时自动从 package.json 更新)
9
9
  // 此版本号会在运行 npm run build 时自动从 package.json 读取并更新
10
- const SDK_VERSION = "1.2.1";
10
+ const SDK_VERSION = "1.2.2";
11
11
  /**
12
12
  * SDK 特征码 - 用于在构建后的 JS 文件中识别 SDK 版本
13
13
  * 格式: AI_WORLD_SDK_V:版本号
@@ -15,7 +15,7 @@ const SDK_VERSION = "1.2.1";
15
15
  *
16
16
  * 注意: {VERSION} 占位符会在构建时被替换为实际版本号
17
17
  */
18
- exports.SDK_SIGNATURE = "AI_WORLD_SDK_V:1.2.1";
18
+ exports.SDK_SIGNATURE = "AI_WORLD_SDK_V:1.2.2";
19
19
  /**
20
20
  * 版本兼容性错误
21
21
  */
package/dist/index.d.ts CHANGED
@@ -28,6 +28,7 @@ export { VideoGenerationClient, type VideoGenerationConfig, type VideoGeneration
28
28
  export { OpenAIVideoGenerationClient, type OpenAIVideoGenerationConfig, type OpenAIVideoGenerationRequest, type OpenAIVideoTaskResponse, };
29
29
  export { DownloadClient, type DownloadConfig, type DownloadOptions, type StreamDownloadOptions, };
30
30
  export { MinioStorageClient, type MinioStorageConfig, type UploadResponse, type ObjectInfo, type PresignedUrlResponse, type UploadOptions, type ListOptions, } from "./minio";
31
+ export { ResourceClient, type ResourceClientConfig, type ResourceInfo, type AccessLevel, type UploadResourceOptions, type ListResourceOptions, } from "./resource";
31
32
  export { AuthClient, getCurrentUserInfo, type AuthConfig, type UserInfo, };
32
33
  export { sdkConfig, VersionCompatibilityError, SDK_SIGNATURE } from "./config";
33
34
  /**
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
20
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.SDK_SIGNATURE = exports.VersionCompatibilityError = exports.sdkConfig = exports.getCurrentUserInfo = exports.AuthClient = exports.MinioStorageClient = exports.DownloadClient = exports.OpenAIVideoGenerationClient = exports.VideoGenerationClient = exports.GeminiImageGenerationClient = exports.DoubaoImageGenerationClient = exports.ChatAnthropic = exports.ChatGoogleGenerativeAI = exports.ChatOpenAI = exports.BaseChatModel = exports.AIMessageChunk = exports.SystemMessage = exports.AIMessage = exports.HumanMessage = void 0;
23
+ exports.SDK_SIGNATURE = exports.VersionCompatibilityError = exports.sdkConfig = exports.getCurrentUserInfo = exports.AuthClient = exports.ResourceClient = exports.MinioStorageClient = exports.DownloadClient = exports.OpenAIVideoGenerationClient = exports.VideoGenerationClient = exports.GeminiImageGenerationClient = exports.DoubaoImageGenerationClient = exports.ChatAnthropic = exports.ChatGoogleGenerativeAI = exports.ChatOpenAI = exports.BaseChatModel = exports.AIMessageChunk = exports.SystemMessage = exports.AIMessage = exports.HumanMessage = void 0;
24
24
  exports.createChatModel = createChatModel;
25
25
  const openai_1 = require("./chat_models/openai");
26
26
  const google_1 = require("./chat_models/google");
@@ -56,6 +56,9 @@ Object.defineProperty(exports, "ChatAnthropic", { enumerable: true, get: functio
56
56
  // Export MinIO storage client
57
57
  var minio_1 = require("./minio");
58
58
  Object.defineProperty(exports, "MinioStorageClient", { enumerable: true, get: function () { return minio_1.MinioStorageClient; } });
59
+ // Export resource management client
60
+ var resource_1 = require("./resource");
61
+ Object.defineProperty(exports, "ResourceClient", { enumerable: true, get: function () { return resource_1.ResourceClient; } });
59
62
  // Export global configuration
60
63
  var config_2 = require("./config");
61
64
  Object.defineProperty(exports, "sdkConfig", { enumerable: true, get: function () { return config_2.sdkConfig; } });
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Resource Client
3
+ * 资源管理客户端
4
+ * 通过后端 /api/resources 代理操作资源管理系统
5
+ * 支持 private / specific_users / public 三级访问控制,默认按 plugin_id 隔离
6
+ */
7
+ export interface ResourceClientConfig {
8
+ baseUrl?: string;
9
+ token?: string;
10
+ headers?: Record<string, string>;
11
+ pluginId?: string;
12
+ }
13
+ export type AccessLevel = "private" | "specific_users" | "public";
14
+ export interface ResourceInfo {
15
+ id: number;
16
+ owner_id: number;
17
+ plugin_id: string;
18
+ path: string;
19
+ object_path: string;
20
+ filename: string;
21
+ size: number;
22
+ content_type: string;
23
+ access_level: AccessLevel;
24
+ description?: string;
25
+ created_at: string;
26
+ updated_at: string;
27
+ shared_users?: number[];
28
+ }
29
+ export interface UploadResourceOptions {
30
+ accessLevel?: AccessLevel;
31
+ description?: string;
32
+ contentType?: string;
33
+ }
34
+ export interface ListResourceOptions {
35
+ crossPlugin?: boolean;
36
+ }
37
+ /**
38
+ * Resource Client
39
+ * 资源管理客户端类
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * import { ResourceClient, sdkConfig } from 'ai-world-sdk';
44
+ *
45
+ * sdkConfig.setPluginId('my-plugin');
46
+ * const resources = new ResourceClient();
47
+ *
48
+ * // 上传并设为公开
49
+ * const file = new File(['hello'], 'hello.txt', { type: 'text/plain' });
50
+ * const res = await resources.upload('docs/hello.txt', file, { accessLevel: 'public' });
51
+ *
52
+ * // 列出我的资源
53
+ * const myFiles = await resources.listMy();
54
+ *
55
+ * // 查看某用户的公开资源
56
+ * const userFiles = await resources.listByUser(42);
57
+ *
58
+ * // 分享给指定用户
59
+ * await resources.addShare(res.id, 99);
60
+ *
61
+ * // 通过 userId + path 下载
62
+ * const blob = await resources.downloadByUser(42, 'docs/hello.txt');
63
+ * ```
64
+ */
65
+ export declare class ResourceClient {
66
+ private baseUrl;
67
+ private headers;
68
+ constructor(config?: ResourceClientConfig);
69
+ private ensurePluginId;
70
+ private handleErrorResponse;
71
+ /**
72
+ * 上传文件并创建资源记录
73
+ */
74
+ upload(path: string, file: File | Blob, options?: UploadResourceOptions): Promise<ResourceInfo>;
75
+ /**
76
+ * 列出当前用户的资源
77
+ */
78
+ listMy(options?: ListResourceOptions): Promise<ResourceInfo[]>;
79
+ /**
80
+ * 获取资源详情
81
+ */
82
+ getInfo(resourceId: number): Promise<ResourceInfo>;
83
+ /**
84
+ * 修改资源访问级别
85
+ */
86
+ updateAccess(resourceId: number, accessLevel: AccessLevel): Promise<ResourceInfo>;
87
+ /**
88
+ * 批量添加用户的访问授权
89
+ *
90
+ * @param resourceId - 资源 ID
91
+ * @param userIds - 被授权用户 ID 列表(支持单个或多个)
92
+ */
93
+ addShare(resourceId: number, userIds: number | number[]): Promise<{
94
+ resource_id: number;
95
+ added_user_ids: number[];
96
+ total_requested: number;
97
+ }>;
98
+ /**
99
+ * 批量移除用户的访问授权
100
+ *
101
+ * @param resourceId - 资源 ID
102
+ * @param userIds - 要移除授权的用户 ID 列表(支持单个或多个)
103
+ */
104
+ removeShare(resourceId: number, userIds: number | number[]): Promise<{
105
+ resource_id: number;
106
+ removed_user_ids: number[];
107
+ total_requested: number;
108
+ }>;
109
+ /**
110
+ * 通过资源 ID 下载
111
+ */
112
+ download(resourceId: number): Promise<Blob>;
113
+ /**
114
+ * 删除资源
115
+ */
116
+ delete(resourceId: number): Promise<void>;
117
+ /**
118
+ * 列出指定用户的可访问资源
119
+ */
120
+ listByUser(userId: number, options?: ListResourceOptions): Promise<ResourceInfo[]>;
121
+ /**
122
+ * 通过 userId + path 下载资源
123
+ */
124
+ downloadByUser(userId: number, path: string, pluginId?: string): Promise<Blob>;
125
+ /**
126
+ * 列出被分享给当前用户的资源
127
+ */
128
+ listSharedWithMe(options?: ListResourceOptions): Promise<ResourceInfo[]>;
129
+ /**
130
+ * 列出所有 public 资源
131
+ */
132
+ listPublic(options?: ListResourceOptions): Promise<ResourceInfo[]>;
133
+ /**
134
+ * 下载资源并触发浏览器下载
135
+ */
136
+ downloadAsFile(resourceId: number, filename?: string): Promise<void>;
137
+ }
@@ -0,0 +1,390 @@
1
+ "use strict";
2
+ /**
3
+ * Resource Client
4
+ * 资源管理客户端
5
+ * 通过后端 /api/resources 代理操作资源管理系统
6
+ * 支持 private / specific_users / public 三级访问控制,默认按 plugin_id 隔离
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.ResourceClient = void 0;
10
+ const config_1 = require("./config");
11
+ const log_1 = require("./log");
12
+ // ==================== ResourceClient ====================
13
+ /**
14
+ * Resource Client
15
+ * 资源管理客户端类
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * import { ResourceClient, sdkConfig } from 'ai-world-sdk';
20
+ *
21
+ * sdkConfig.setPluginId('my-plugin');
22
+ * const resources = new ResourceClient();
23
+ *
24
+ * // 上传并设为公开
25
+ * const file = new File(['hello'], 'hello.txt', { type: 'text/plain' });
26
+ * const res = await resources.upload('docs/hello.txt', file, { accessLevel: 'public' });
27
+ *
28
+ * // 列出我的资源
29
+ * const myFiles = await resources.listMy();
30
+ *
31
+ * // 查看某用户的公开资源
32
+ * const userFiles = await resources.listByUser(42);
33
+ *
34
+ * // 分享给指定用户
35
+ * await resources.addShare(res.id, 99);
36
+ *
37
+ * // 通过 userId + path 下载
38
+ * const blob = await resources.downloadByUser(42, 'docs/hello.txt');
39
+ * ```
40
+ */
41
+ class ResourceClient {
42
+ constructor(config = {}) {
43
+ this.baseUrl =
44
+ config.baseUrl ||
45
+ config_1.sdkConfig.getServerUrl() ||
46
+ (typeof window !== "undefined" ? window.location.origin : "");
47
+ const globalHeaders = config_1.sdkConfig.getHeaders();
48
+ const globalToken = config.token || config_1.sdkConfig.getToken();
49
+ this.headers = {
50
+ ...globalHeaders,
51
+ ...config.headers,
52
+ };
53
+ const pluginId = config.pluginId || config_1.sdkConfig.getPluginId();
54
+ if (pluginId) {
55
+ this.headers["X-Plugin-Id"] = pluginId;
56
+ }
57
+ if (globalToken) {
58
+ this.headers["Authorization"] = `Bearer ${globalToken}`;
59
+ }
60
+ }
61
+ ensurePluginId() {
62
+ if (!this.headers["X-Plugin-Id"]) {
63
+ const pluginId = config_1.sdkConfig.getPluginId();
64
+ if (pluginId) {
65
+ this.headers["X-Plugin-Id"] = pluginId;
66
+ }
67
+ else {
68
+ throw new Error("X-Plugin-Id is required. Set it via sdkConfig.setPluginId() or pass pluginId in ResourceClientConfig.");
69
+ }
70
+ }
71
+ }
72
+ async handleErrorResponse(response) {
73
+ let errorMessage = `Request failed: ${response.status} ${response.statusText}`;
74
+ try {
75
+ const errorText = await response.text();
76
+ const errorJson = JSON.parse(errorText);
77
+ errorMessage = errorJson.detail || errorMessage;
78
+ }
79
+ catch {
80
+ // ignore parse error
81
+ }
82
+ throw new Error(errorMessage);
83
+ }
84
+ /**
85
+ * 上传文件并创建资源记录
86
+ */
87
+ async upload(path, file, options = {}) {
88
+ config_1.sdkConfig.ensureVersionCompatible();
89
+ this.ensurePluginId();
90
+ const params = new URLSearchParams();
91
+ params.append("path", path);
92
+ if (options.accessLevel) {
93
+ params.append("access_level", options.accessLevel);
94
+ }
95
+ if (options.description) {
96
+ params.append("description", options.description);
97
+ }
98
+ const apiUrl = `${this.baseUrl}/api/resources/upload?${params.toString()}`;
99
+ const formData = new FormData();
100
+ const filename = file instanceof File ? file.name : path.split("/").pop() || "file";
101
+ formData.append("file", file, filename);
102
+ const headers = { ...this.headers };
103
+ delete headers["Content-Type"];
104
+ (0, log_1.debugLog)("Resource upload request:", { path, options });
105
+ (0, log_1.logRequest)("POST", apiUrl, headers);
106
+ const response = await fetch(apiUrl, {
107
+ method: "POST",
108
+ headers,
109
+ body: formData,
110
+ });
111
+ if (!response.ok) {
112
+ await this.handleErrorResponse(response);
113
+ }
114
+ const result = (await response.json());
115
+ (0, log_1.debugLog)("Resource upload response:", result);
116
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, result);
117
+ return result;
118
+ }
119
+ /**
120
+ * 列出当前用户的资源
121
+ */
122
+ async listMy(options = {}) {
123
+ config_1.sdkConfig.ensureVersionCompatible();
124
+ this.ensurePluginId();
125
+ const params = new URLSearchParams();
126
+ if (options.crossPlugin)
127
+ params.append("cross_plugin", "true");
128
+ const apiUrl = `${this.baseUrl}/api/resources/my?${params.toString()}`;
129
+ (0, log_1.debugLog)("Resource listMy request:", options);
130
+ (0, log_1.logRequest)("GET", apiUrl, this.headers);
131
+ const response = await fetch(apiUrl, {
132
+ method: "GET",
133
+ headers: this.headers,
134
+ });
135
+ if (!response.ok)
136
+ await this.handleErrorResponse(response);
137
+ const result = (await response.json());
138
+ (0, log_1.debugLog)("Resource listMy response:", { count: result.length });
139
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, result);
140
+ return result;
141
+ }
142
+ /**
143
+ * 获取资源详情
144
+ */
145
+ async getInfo(resourceId) {
146
+ config_1.sdkConfig.ensureVersionCompatible();
147
+ this.ensurePluginId();
148
+ const apiUrl = `${this.baseUrl}/api/resources/${resourceId}`;
149
+ (0, log_1.debugLog)("Resource getInfo request:", { resourceId });
150
+ (0, log_1.logRequest)("GET", apiUrl, this.headers);
151
+ const response = await fetch(apiUrl, {
152
+ method: "GET",
153
+ headers: this.headers,
154
+ });
155
+ if (!response.ok)
156
+ await this.handleErrorResponse(response);
157
+ const result = (await response.json());
158
+ (0, log_1.debugLog)("Resource getInfo response:", result);
159
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, result);
160
+ return result;
161
+ }
162
+ /**
163
+ * 修改资源访问级别
164
+ */
165
+ async updateAccess(resourceId, accessLevel) {
166
+ config_1.sdkConfig.ensureVersionCompatible();
167
+ this.ensurePluginId();
168
+ const apiUrl = `${this.baseUrl}/api/resources/${resourceId}/access`;
169
+ (0, log_1.debugLog)("Resource updateAccess request:", { resourceId, accessLevel });
170
+ (0, log_1.logRequest)("PATCH", apiUrl, this.headers);
171
+ const response = await fetch(apiUrl, {
172
+ method: "PATCH",
173
+ headers: {
174
+ ...this.headers,
175
+ "Content-Type": "application/json",
176
+ },
177
+ body: JSON.stringify({ access_level: accessLevel }),
178
+ });
179
+ if (!response.ok)
180
+ await this.handleErrorResponse(response);
181
+ const result = (await response.json());
182
+ (0, log_1.debugLog)("Resource updateAccess response:", result);
183
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, result);
184
+ return result;
185
+ }
186
+ /**
187
+ * 批量添加用户的访问授权
188
+ *
189
+ * @param resourceId - 资源 ID
190
+ * @param userIds - 被授权用户 ID 列表(支持单个或多个)
191
+ */
192
+ async addShare(resourceId, userIds) {
193
+ config_1.sdkConfig.ensureVersionCompatible();
194
+ this.ensurePluginId();
195
+ const ids = Array.isArray(userIds) ? userIds : [userIds];
196
+ const apiUrl = `${this.baseUrl}/api/resources/${resourceId}/share`;
197
+ (0, log_1.debugLog)("Resource addShare request:", { resourceId, userIds: ids });
198
+ (0, log_1.logRequest)("POST", apiUrl, this.headers);
199
+ const response = await fetch(apiUrl, {
200
+ method: "POST",
201
+ headers: {
202
+ ...this.headers,
203
+ "Content-Type": "application/json",
204
+ },
205
+ body: JSON.stringify({ user_ids: ids }),
206
+ });
207
+ if (!response.ok)
208
+ await this.handleErrorResponse(response);
209
+ const result = await response.json();
210
+ (0, log_1.debugLog)("Resource addShare completed:", result);
211
+ return result;
212
+ }
213
+ /**
214
+ * 批量移除用户的访问授权
215
+ *
216
+ * @param resourceId - 资源 ID
217
+ * @param userIds - 要移除授权的用户 ID 列表(支持单个或多个)
218
+ */
219
+ async removeShare(resourceId, userIds) {
220
+ config_1.sdkConfig.ensureVersionCompatible();
221
+ this.ensurePluginId();
222
+ const ids = Array.isArray(userIds) ? userIds : [userIds];
223
+ const apiUrl = `${this.baseUrl}/api/resources/${resourceId}/unshare`;
224
+ (0, log_1.debugLog)("Resource removeShare request:", { resourceId, userIds: ids });
225
+ (0, log_1.logRequest)("POST", apiUrl, this.headers);
226
+ const response = await fetch(apiUrl, {
227
+ method: "POST",
228
+ headers: {
229
+ ...this.headers,
230
+ "Content-Type": "application/json",
231
+ },
232
+ body: JSON.stringify({ user_ids: ids }),
233
+ });
234
+ if (!response.ok)
235
+ await this.handleErrorResponse(response);
236
+ const result = await response.json();
237
+ (0, log_1.debugLog)("Resource removeShare completed:", result);
238
+ return result;
239
+ }
240
+ /**
241
+ * 通过资源 ID 下载
242
+ */
243
+ async download(resourceId) {
244
+ config_1.sdkConfig.ensureVersionCompatible();
245
+ this.ensurePluginId();
246
+ const apiUrl = `${this.baseUrl}/api/resources/${resourceId}/download`;
247
+ (0, log_1.debugLog)("Resource download request:", { resourceId });
248
+ (0, log_1.logRequest)("GET", apiUrl, this.headers);
249
+ const response = await fetch(apiUrl, {
250
+ method: "GET",
251
+ headers: this.headers,
252
+ });
253
+ if (!response.ok)
254
+ await this.handleErrorResponse(response);
255
+ const blob = await response.blob();
256
+ (0, log_1.debugLog)("Resource download completed:", {
257
+ size: blob.size,
258
+ type: blob.type,
259
+ });
260
+ return blob;
261
+ }
262
+ /**
263
+ * 删除资源
264
+ */
265
+ async delete(resourceId) {
266
+ config_1.sdkConfig.ensureVersionCompatible();
267
+ this.ensurePluginId();
268
+ const apiUrl = `${this.baseUrl}/api/resources/${resourceId}`;
269
+ (0, log_1.debugLog)("Resource delete request:", { resourceId });
270
+ (0, log_1.logRequest)("DELETE", apiUrl, this.headers);
271
+ const response = await fetch(apiUrl, {
272
+ method: "DELETE",
273
+ headers: this.headers,
274
+ });
275
+ if (!response.ok)
276
+ await this.handleErrorResponse(response);
277
+ (0, log_1.debugLog)("Resource delete completed:", { resourceId });
278
+ }
279
+ /**
280
+ * 列出指定用户的可访问资源
281
+ */
282
+ async listByUser(userId, options = {}) {
283
+ config_1.sdkConfig.ensureVersionCompatible();
284
+ this.ensurePluginId();
285
+ const params = new URLSearchParams();
286
+ if (options.crossPlugin)
287
+ params.append("cross_plugin", "true");
288
+ const apiUrl = `${this.baseUrl}/api/resources/user/${userId}?${params.toString()}`;
289
+ (0, log_1.debugLog)("Resource listByUser request:", { userId, options });
290
+ (0, log_1.logRequest)("GET", apiUrl, this.headers);
291
+ const response = await fetch(apiUrl, {
292
+ method: "GET",
293
+ headers: this.headers,
294
+ });
295
+ if (!response.ok)
296
+ await this.handleErrorResponse(response);
297
+ const result = (await response.json());
298
+ (0, log_1.debugLog)("Resource listByUser response:", { count: result.length });
299
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, result);
300
+ return result;
301
+ }
302
+ /**
303
+ * 通过 userId + path 下载资源
304
+ */
305
+ async downloadByUser(userId, path, pluginId) {
306
+ config_1.sdkConfig.ensureVersionCompatible();
307
+ this.ensurePluginId();
308
+ const params = new URLSearchParams();
309
+ if (pluginId)
310
+ params.append("plugin_id", pluginId);
311
+ const queryStr = params.toString();
312
+ const apiUrl = `${this.baseUrl}/api/resources/user/${userId}/download/${encodeURIComponent(path)}${queryStr ? `?${queryStr}` : ""}`;
313
+ (0, log_1.debugLog)("Resource downloadByUser request:", { userId, path, pluginId });
314
+ (0, log_1.logRequest)("GET", apiUrl, this.headers);
315
+ const response = await fetch(apiUrl, {
316
+ method: "GET",
317
+ headers: this.headers,
318
+ });
319
+ if (!response.ok)
320
+ await this.handleErrorResponse(response);
321
+ const blob = await response.blob();
322
+ (0, log_1.debugLog)("Resource downloadByUser completed:", {
323
+ size: blob.size,
324
+ type: blob.type,
325
+ });
326
+ return blob;
327
+ }
328
+ /**
329
+ * 列出被分享给当前用户的资源
330
+ */
331
+ async listSharedWithMe(options = {}) {
332
+ config_1.sdkConfig.ensureVersionCompatible();
333
+ this.ensurePluginId();
334
+ const params = new URLSearchParams();
335
+ if (options.crossPlugin)
336
+ params.append("cross_plugin", "true");
337
+ const apiUrl = `${this.baseUrl}/api/resources/shared-with-me?${params.toString()}`;
338
+ (0, log_1.debugLog)("Resource listSharedWithMe request:", options);
339
+ (0, log_1.logRequest)("GET", apiUrl, this.headers);
340
+ const response = await fetch(apiUrl, {
341
+ method: "GET",
342
+ headers: this.headers,
343
+ });
344
+ if (!response.ok)
345
+ await this.handleErrorResponse(response);
346
+ const result = (await response.json());
347
+ (0, log_1.debugLog)("Resource listSharedWithMe response:", { count: result.length });
348
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, result);
349
+ return result;
350
+ }
351
+ /**
352
+ * 列出所有 public 资源
353
+ */
354
+ async listPublic(options = {}) {
355
+ config_1.sdkConfig.ensureVersionCompatible();
356
+ this.ensurePluginId();
357
+ const params = new URLSearchParams();
358
+ if (options.crossPlugin)
359
+ params.append("cross_plugin", "true");
360
+ const apiUrl = `${this.baseUrl}/api/resources/public?${params.toString()}`;
361
+ (0, log_1.debugLog)("Resource listPublic request:", options);
362
+ (0, log_1.logRequest)("GET", apiUrl, this.headers);
363
+ const response = await fetch(apiUrl, {
364
+ method: "GET",
365
+ headers: this.headers,
366
+ });
367
+ if (!response.ok)
368
+ await this.handleErrorResponse(response);
369
+ const result = (await response.json());
370
+ (0, log_1.debugLog)("Resource listPublic response:", { count: result.length });
371
+ (0, log_1.logResponse)(response.status, response.statusText, response.headers, result);
372
+ return result;
373
+ }
374
+ /**
375
+ * 下载资源并触发浏览器下载
376
+ */
377
+ async downloadAsFile(resourceId, filename) {
378
+ const blob = await this.download(resourceId);
379
+ const downloadFilename = filename || "download";
380
+ const url = URL.createObjectURL(blob);
381
+ const a = document.createElement("a");
382
+ a.href = url;
383
+ a.download = downloadFilename;
384
+ document.body.appendChild(a);
385
+ a.click();
386
+ document.body.removeChild(a);
387
+ setTimeout(() => URL.revokeObjectURL(url), 100);
388
+ }
389
+ }
390
+ exports.ResourceClient = ResourceClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-world-sdk",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "TypeScript SDK for AI World Platform - Chat Models, Image Generation, and Video Generation",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",