ai-world-sdk 1.5.16 → 1.5.17

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.
@@ -109,7 +109,7 @@ const COMMAND_DETAILS = {
109
109
  },
110
110
  plugin: {
111
111
  desc: '插件管理 —— 部署、启用/禁用、重启、查看日志',
112
- usage: 'ai-world plugin <list|get|ids|create|enable|disable|reload|restart|logs|status|delete>',
112
+ usage: 'ai-world plugin <list|get|ids|create|update|enable|disable|reload|restart|logs|status|delete>',
113
113
  examples: [
114
114
  'ai-world plugin list',
115
115
  'ai-world plugin ids --enabled-only',
@@ -117,6 +117,8 @@ const COMMAND_DETAILS = {
117
117
  'ai-world plugin enable my-plugin',
118
118
  'ai-world plugin logs my-plugin --lines 50',
119
119
  'ai-world plugin create ./dist.zip --plugin-id my-plugin --name "我的插件"',
120
+ 'ai-world plugin create --plugin-id py-plugin --server-zip server.zip --backend-type python',
121
+ 'ai-world plugin update --plugin-id my-plugin --server-zip server.zip --backend-type node',
120
122
  ],
121
123
  },
122
124
  admin: {
@@ -191,8 +191,9 @@ function registerPluginCommands(program) {
191
191
  .option('--description <text>', '插件描述')
192
192
  .option('--author <author>', '插件作者')
193
193
  .option('--version <ver>', '插件版本')
194
- .option('--server-zip <path>', 'JS 后端 zip 包路径')
195
- .option('--backend-entry <entry>', 'JS 后端入口文件(默认 index.js)')
194
+ .option('--server-zip <path>', '后端代码 zip 包路径')
195
+ .option('--backend-type <type>', '后端类型: node 或 python(默认 node)')
196
+ .option('--backend-entry <entry>', '后端入口文件(Node.js 默认 index.js,Python 默认 start.py)')
196
197
  .option('--backend-websocket', '启用 WebSocket 代理')
197
198
  .option('--disable-sdk-update-notice', '禁用 SDK 更新提示')
198
199
  .action(async (zipFile, options, cmd) => {
@@ -206,6 +207,7 @@ function registerPluginCommands(program) {
206
207
  });
207
208
  (0, utils_1.initSDK)(auth);
208
209
  const client = new plugin_management_1.PluginManagementClient();
210
+ const bt = options.backendType;
209
211
  const res = await client.create({
210
212
  pluginId: options.pluginId,
211
213
  name: options.name,
@@ -214,6 +216,7 @@ function registerPluginCommands(program) {
214
216
  version: options.version,
215
217
  staticZip: zipFile ? (0, utils_1.readFileAsFile)(zipFile) : undefined,
216
218
  serverZip: options.serverZip ? (0, utils_1.readFileAsFile)(options.serverZip) : undefined,
219
+ backendType: bt === 'node' || bt === 'python' ? bt : undefined,
217
220
  backendEntry: options.backendEntry,
218
221
  backendWebsocket: options.backendWebsocket === true ? true : undefined,
219
222
  disableSdkUpdateNotice: options.disableSdkUpdateNotice === true ? true : undefined,
@@ -232,8 +235,9 @@ function registerPluginCommands(program) {
232
235
  .option('--description <text>', '插件描述')
233
236
  .option('--author <author>', '插件作者')
234
237
  .option('--version <ver>', '插件版本')
235
- .option('--server-zip <path>', 'JS 后端 zip 包路径')
236
- .option('--backend-entry <entry>', 'JS 后端入口文件(默认 index.js)')
238
+ .option('--server-zip <path>', '后端代码 zip 包路径')
239
+ .option('--backend-type <type>', '后端类型: node 或 python(默认 node)')
240
+ .option('--backend-entry <entry>', '后端入口文件(Node.js 默认 index.js,Python 默认 start.py)')
237
241
  .option('--backend-websocket', '启用 WebSocket 代理')
238
242
  .option('--disable-sdk-update-notice', '禁用 SDK 更新提示')
239
243
  .action(async (zipFile, options, cmd) => {
@@ -247,6 +251,7 @@ function registerPluginCommands(program) {
247
251
  });
248
252
  (0, utils_1.initSDK)(auth);
249
253
  const client = new plugin_management_1.PluginManagementClient();
254
+ const bt = options.backendType;
250
255
  const res = await client.update({
251
256
  pluginId: options.pluginId,
252
257
  name: options.name,
@@ -255,6 +260,7 @@ function registerPluginCommands(program) {
255
260
  version: options.version,
256
261
  staticZip: zipFile ? (0, utils_1.readFileAsFile)(zipFile) : undefined,
257
262
  serverZip: options.serverZip ? (0, utils_1.readFileAsFile)(options.serverZip) : undefined,
263
+ backendType: bt === 'node' || bt === 'python' ? bt : undefined,
258
264
  backendEntry: options.backendEntry,
259
265
  backendWebsocket: options.backendWebsocket === true ? true : undefined,
260
266
  disableSdkUpdateNotice: options.disableSdkUpdateNotice === true ? true : undefined,
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.5.16";
12
+ export declare const SDK_SIGNATURE = "AI_WORLD_SDK_V:1.5.17";
13
13
  /**
14
14
  * 版本兼容性错误
15
15
  */
@@ -35,8 +35,8 @@ declare class SDKConfig {
35
35
  private _authCheckPromise;
36
36
  private _currentUser;
37
37
  private _cliMode;
38
- readonly sdkSignature = "AI_WORLD_SDK_V:1.5.16";
39
- readonly sdkVersion = "1.5.16";
38
+ readonly sdkSignature = "AI_WORLD_SDK_V:1.5.17";
39
+ readonly sdkVersion = "1.5.17";
40
40
  constructor();
41
41
  /**
42
42
  * 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.5.16";
10
+ const SDK_VERSION = "1.5.17";
11
11
  /**
12
12
  * SDK 特征码 - 用于在构建后的 JS 文件中识别 SDK 版本
13
13
  * 格式: AI_WORLD_SDK_V:版本号
@@ -15,7 +15,7 @@ const SDK_VERSION = "1.5.16";
15
15
  *
16
16
  * 注意: {VERSION} 占位符会在构建时被替换为实际版本号
17
17
  */
18
- exports.SDK_SIGNATURE = "AI_WORLD_SDK_V:1.5.16";
18
+ exports.SDK_SIGNATURE = "AI_WORLD_SDK_V:1.5.17";
19
19
  /**
20
20
  * 版本兼容性错误
21
21
  */
package/dist/index.d.ts CHANGED
@@ -34,7 +34,7 @@ export { VersionedResourceClient, type VersionedResourceClientConfig, type Versi
34
34
  export { AgentSkillClient, type AgentSkillClientConfig, type AgentSkillInfo, type AgentSkillListResponse, type ListSkillsOptions, } from "./agent-skills";
35
35
  export { AuthClient, getCurrentUserInfo, type AuthConfig, type UserInfo, };
36
36
  export { AdminClient, type AdminClientConfig, type AdminUserInfo, type AdminUserListResponse, type ListUsersOptions, type RoleInfo, type CreateRoleData, type UpdateRoleData, type RoleUserCount, type TableColumn, type TableDataResponse, type ListTableDataOptions, } from "./admin";
37
- export { PluginManagementClient, type PluginManagementClientConfig, type PluginInfo, type PluginListResponse, type ListPluginsOptions, type CreatePluginData, type PluginStatus, type PluginTemplateInfo, type PluginTemplateListResponse, type ListPluginTemplatesOptions, type CreatePluginTemplateData, type UpdatePluginTemplateData, } from "./plugin-management";
37
+ export { PluginManagementClient, type PluginManagementClientConfig, type PluginInfo, type PluginListResponse, type ListPluginsOptions, type CreatePluginData, type UpdatePluginData, type PluginStatus, type RestartServerResult, type PluginTemplateInfo, type PluginTemplateListResponse, type ListPluginTemplatesOptions, type CreatePluginTemplateData, type UpdatePluginTemplateData, } from "./plugin-management";
38
38
  export { StatsClient, DashboardClient, type StatsClientConfig, type AiApiCallsOptions, type AiApiCallsTrendOptions, type AiApiCallsTrendByUserOptions, type PluginAccessOptions, } from "./stats";
39
39
  export { AIConfigClient, type AIConfigClientConfig, } from "./ai-config";
40
40
  export { SharedResourceClient, type SharedResourceClientConfig, type SharedResourceInfo, type SharedResourceListResponse, type ListSharedResourceOptions, type UpdateSharedResourceData, } from "./shared-resource";
@@ -14,7 +14,13 @@ export interface PluginInfo {
14
14
  author?: string;
15
15
  version?: string;
16
16
  enabled: boolean;
17
- has_server: boolean;
17
+ has_backend?: boolean;
18
+ backend_type?: "node" | "python";
19
+ backend_port?: number;
20
+ backend_running?: boolean;
21
+ backend_entry?: string;
22
+ backend_websocket?: boolean;
23
+ has_static_file?: boolean;
18
24
  created_at?: string;
19
25
  updated_at?: string;
20
26
  [key: string]: any;
@@ -45,6 +51,7 @@ export interface CreatePluginData {
45
51
  templateId?: string;
46
52
  staticZip?: File | Blob;
47
53
  serverZip?: File | Blob;
54
+ backendType?: "node" | "python";
48
55
  backendEntry?: string;
49
56
  backendWebsocket?: boolean;
50
57
  disableSdkUpdateNotice?: boolean;
@@ -57,6 +64,7 @@ export interface UpdatePluginData {
57
64
  version?: string;
58
65
  staticZip?: File | Blob;
59
66
  serverZip?: File | Blob;
67
+ backendType?: "node" | "python";
60
68
  backendEntry?: string;
61
69
  backendWebsocket?: boolean;
62
70
  disableSdkUpdateNotice?: boolean;
@@ -64,8 +72,7 @@ export interface UpdatePluginData {
64
72
  export interface PluginStatus {
65
73
  plugin_id: string;
66
74
  enabled: boolean;
67
- has_server: boolean;
68
- server_running?: boolean;
75
+ exists: boolean;
69
76
  [key: string]: any;
70
77
  }
71
78
  export interface PluginTemplateInfo {
@@ -92,6 +99,14 @@ export interface ListPluginTemplatesOptions {
92
99
  name?: string;
93
100
  category?: string;
94
101
  }
102
+ export interface RestartServerResult {
103
+ message: string;
104
+ plugin_id: string;
105
+ port: number;
106
+ backend_type: string;
107
+ install_logs: string;
108
+ startup_logs: string;
109
+ }
95
110
  export interface CreatePluginTemplateData {
96
111
  pluginId: string;
97
112
  name: string;
@@ -135,9 +150,7 @@ export declare class PluginManagementClient {
135
150
  reload(pluginId: string): Promise<{
136
151
  message: string;
137
152
  }>;
138
- restartServer(pluginId: string): Promise<{
139
- message: string;
140
- }>;
153
+ restartServer(pluginId: string): Promise<RestartServerResult>;
141
154
  getServerLogs(pluginId: string, lines?: number): Promise<string>;
142
155
  listTemplates(): Promise<any[]>;
143
156
  getTemplate(templateId: string): Promise<any>;
@@ -118,6 +118,8 @@ class PluginManagementClient {
118
118
  formData.append("static_zip", data.staticZip);
119
119
  if (data.serverZip)
120
120
  formData.append("server_zip", data.serverZip);
121
+ if (data.backendType)
122
+ formData.append("backend_type", data.backendType);
121
123
  if (data.backendEntry)
122
124
  formData.append("backend_entry", data.backendEntry);
123
125
  if (data.backendWebsocket !== undefined)
@@ -153,6 +155,8 @@ class PluginManagementClient {
153
155
  formData.append("static_zip", data.staticZip);
154
156
  if (data.serverZip)
155
157
  formData.append("server_zip", data.serverZip);
158
+ if (data.backendType)
159
+ formData.append("backend_type", data.backendType);
156
160
  if (data.backendEntry)
157
161
  formData.append("backend_entry", data.backendEntry);
158
162
  if (data.backendWebsocket !== undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-world-sdk",
3
- "version": "1.5.16",
3
+ "version": "1.5.17",
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",
@@ -120,15 +120,15 @@ sdkConfig.setPluginId('my-plugin');
120
120
  ```
121
121
 
122
122
  也可通过环境变量自动初始化(SDK 自动读取 `.env.local` > `.env` > `AI_WORLD_ENV_FILE` 指定文件):
123
- - `AI_WORLD_BASE_URL` — 服务端地址,插件 JS 后端启动时由平台自动注入
123
+ - `AI_WORLD_BASE_URL` — 服务端地址,插件后端启动时由平台自动注入
124
124
  - `PLUGIN_ID` — 插件 ID
125
125
  - `DEBUG_TOKEN` — 调试用 JWT Token
126
126
  - `AI_WORLD_TOKEN` — 用户登录后获取的 JWT Token
127
127
  - `AI_WORLD_ENV_FILE` — 指定自定义 `.env` 文件路径(绝对或相对路径均可)
128
128
 
129
- ### 插件 JS 后端环境(平台自动注入)
129
+ ### 插件后端环境(平台自动注入)
130
130
 
131
- 当插件配置了 Node.js 后端(`plugin.json` 的 `backend` 字段),平台启动子进程时会自动注入以下环境变量:
131
+ 当插件配置了后端(`plugin.json` 的 `backend` 字段),平台启动子进程时会自动注入以下环境变量:
132
132
 
133
133
  | 环境变量 | 说明 |
134
134
  |----------|------|
@@ -137,12 +137,36 @@ sdkConfig.setPluginId('my-plugin');
137
137
  | `PLUGIN_ID` | 当前插件 ID |
138
138
  | `AI_WORLD_BASE_URL` | 平台后端地址(默认 `http://127.0.0.1:8000`) |
139
139
  | `AI_WORLD_ENV_FILE` | 平台写入的 `.env` 文件路径(`server/.env`),SDK 自动加载 |
140
- | `NODE_ENV` | 固定为 `production` |
140
+ | `NODE_ENV` | 固定为 `production`(仅 Node.js 后端) |
141
141
 
142
142
  **重要**:插件后端 **必须** 监听 `PORT` 环境变量指定的端口,否则平台无法正确代理请求。
143
143
 
144
+ #### plugin.json backend 配置
145
+
146
+ ```json
147
+ {
148
+ "backend": {
149
+ "type": "node",
150
+ "entry": "index.js",
151
+ "install_cmd": "npm install",
152
+ "health_check": "/health"
153
+ }
154
+ }
155
+ ```
156
+
157
+ | 字段 | 说明 |
158
+ |------|------|
159
+ | `type` | 后端类型:`"node"` 或 `"python"`(默认 `"node"`) |
160
+ | `entry` | 入口文件(Node.js 默认 `index.js`,Python 默认 `start.py`) |
161
+ | `install_cmd` | 依赖安装命令(Node.js 默认 `npm install`,Python 默认 `pip install -r requirements.txt`) |
162
+ | `start_cmd` | 启动命令(可选,默认 `node {entry}` 或 `python {entry}`) |
163
+ | `health_check` | 健康检查路径(默认 `/health`) |
164
+ | `enable_websocket` | 是否启用 WebSocket 代理(默认 `false`) |
165
+
166
+ #### Node.js 后端示例
167
+
144
168
  ```javascript
145
- // server/index.js 示例
169
+ // server/index.js
146
170
  const express = require('express');
147
171
  const app = express();
148
172
  const port = process.env.PORT || 3000;
@@ -155,9 +179,44 @@ app.listen(port, () => {
155
179
  });
156
180
  ```
157
181
 
182
+ #### Python 后端示例
183
+
184
+ ```python
185
+ # server/start.py
186
+ import os
187
+ from fastapi import FastAPI
188
+ import uvicorn
189
+
190
+ app = FastAPI()
191
+ port = int(os.environ.get("PORT", "3000"))
192
+
193
+ @app.get("/health")
194
+ def health():
195
+ return {"status": "ok"}
196
+
197
+ @app.get("/api/hello")
198
+ def hello():
199
+ return {"message": "Hello from Python plugin backend!"}
200
+
201
+ if __name__ == "__main__":
202
+ uvicorn.run(app, host="0.0.0.0", port=port)
203
+ ```
204
+
205
+ 对应 `plugin.json`:
206
+ ```json
207
+ {
208
+ "backend": {
209
+ "type": "python",
210
+ "entry": "start.py",
211
+ "install_cmd": "pip install -r requirements.txt",
212
+ "health_check": "/health"
213
+ }
214
+ }
215
+ ```
216
+
158
217
  ### 插件前端请求插件后端(HTTP 代理)
159
218
 
160
- 平台为每个 JS 后端插件注册了 HTTP 反向代理路由,**插件前端不需要知道后端实际端口**,统一通过以下地址访问:
219
+ 平台为每个后端插件注册了 HTTP 反向代理路由,**插件前端不需要知道后端实际端口**,统一通过以下地址访问:
161
220
 
162
221
  ```
163
222
  {AI_WORLD_BASE_URL}/api/{plugin-id}/server/{path}
@@ -328,7 +387,8 @@ for await (const chunk of stream.textStream) {
328
387
  - `PluginManagementClient` — 插件 CRUD(`create` / `update` 分离)、启用/禁用/重载/重启、模板管理
329
388
  - `create(data)` — 创建新插件(POST `/api/plugins/create`),插件不存在时使用
330
389
  - `update(data)` — 更新已有插件(POST `/api/plugins/update`),插件必须已存在,未传入的字段保留原值
331
- - 两者均支持: pluginId / name / description / author / version / staticZip / serverZip / backendEntry / backendWebsocket / disableSdkUpdateNotice
390
+ - 两者均支持: pluginId / name / description / author / version / staticZip / serverZip / backendType / backendEntry / backendWebsocket / disableSdkUpdateNotice
391
+ - `backendType` — 后端类型:`"node"` 或 `"python"`(默认 node)
332
392
  - `StatsClient` — AI 接口调用统计/趋势、插件访问统计(管理员)
333
393
  - `DashboardClient` — 当前用户统计(无需管理员权限)
334
394
  - `SharedResourceClient` — 平台级文件共享(与 `ResourceClient` 的插件级 ACL 不同)
@@ -139,7 +139,8 @@ ai-world plugin disable <plugin-id>
139
139
  ai-world plugin reload <plugin-id>
140
140
  ai-world plugin restart <plugin-id>
141
141
  ai-world plugin logs <plugin-id> [--lines 100]
142
- ai-world plugin create ./plugin.zip --plugin-id my-plugin [--name "My Plugin"] [--description "说明"]
142
+ ai-world plugin create ./plugin.zip --plugin-id my-plugin [--name "My Plugin"] [--description "说明"] [--backend-type node|python] [--server-zip server.zip] [--backend-entry index.js]
143
+ ai-world plugin update [zip-file] --plugin-id <id> [--name "Name"] [--backend-type node|python] [--server-zip server.zip] [--backend-entry entry.js]
143
144
  ai-world plugin delete <plugin-id>
144
145
  ai-world plugin status <plugin-id>
145
146
  ```
@@ -19,13 +19,23 @@ const ids = await plugins.listIds(true); // string[]
19
19
  const info = await plugins.get('my-plugin');
20
20
  const status = await plugins.getStatus('my-plugin');
21
21
 
22
- // 创建插件
22
+ // 创建插件(Node.js 后端)
23
23
  await plugins.create({
24
24
  pluginId: 'new-plugin',
25
25
  name: '新插件',
26
26
  description: '描述',
27
27
  staticZip: someZipFile, // 可选,含 index.html 的 zip
28
- serverZip: serverZipFile, // 可选,JS 后端 zip
28
+ serverZip: serverZipFile, // 可选,后端代码 zip
29
+ backendType: 'node', // 可选,'node' | 'python',默认 'node'
30
+ });
31
+
32
+ // 创建 Python 后端插件
33
+ await plugins.create({
34
+ pluginId: 'py-plugin',
35
+ name: 'Python 插件',
36
+ serverZip: pyZipFile,
37
+ backendType: 'python',
38
+ backendEntry: 'start.py',
29
39
  });
30
40
 
31
41
  // 启用 / 禁用 / 重载 / 重启后端