ai-world-sdk 1.5.7 → 1.5.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/__tests__/llm.real.test.d.ts +1 -3
- package/dist/__tests__/llm.real.test.js +36 -4
- package/dist/ai-config.d.ts +17 -0
- package/dist/ai-config.js +56 -0
- package/dist/cli/commands/ai-config.d.ts +2 -0
- package/dist/cli/commands/ai-config.js +61 -0
- package/dist/cli/commands/image.js +146 -43
- package/dist/cli/commands/stats.js +20 -4
- package/dist/cli/index.js +2 -0
- package/dist/config.d.ts +3 -3
- package/dist/config.js +2 -2
- package/dist/image.d.ts +93 -0
- package/dist/image.js +227 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +12 -1
- package/dist/stats.d.ts +5 -2
- package/dist/stats.js +11 -0
- package/package.json +6 -6
- package/skills/ai-world-sdk/SKILL.md +2 -1
- package/skills/ai-world-sdk/docs/cli-commands.md +11 -1
- package/skills/ai-world-sdk/docs/image-generation.md +324 -9
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* llm.ts
|
|
2
|
+
* llm.ts 真实集成测试(文本生成 + kunpo 图像生成)
|
|
3
3
|
*
|
|
4
4
|
* 通过真实后端代理测试 createProvider 和 checkModel。
|
|
5
5
|
* 需要:
|
|
6
6
|
* 1. 运行中的后端服务 (http://localhost:8000)
|
|
7
7
|
* 2. .env 文件中配置 AUTH_TOKEN
|
|
8
8
|
*
|
|
9
|
-
* ⚠️ 图像生成测试由用户手动测试,此文件仅包含文本生成测试。
|
|
10
|
-
*
|
|
11
9
|
* 运行: npm run test:llm-real
|
|
12
10
|
*/
|
|
13
11
|
export {};
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* llm.ts
|
|
3
|
+
* llm.ts 真实集成测试(文本生成 + kunpo 图像生成)
|
|
4
4
|
*
|
|
5
5
|
* 通过真实后端代理测试 createProvider 和 checkModel。
|
|
6
6
|
* 需要:
|
|
7
7
|
* 1. 运行中的后端服务 (http://localhost:8000)
|
|
8
8
|
* 2. .env 文件中配置 AUTH_TOKEN
|
|
9
9
|
*
|
|
10
|
-
* ⚠️ 图像生成测试由用户手动测试,此文件仅包含文本生成测试。
|
|
11
|
-
*
|
|
12
10
|
* 运行: npm run test:llm-real
|
|
13
11
|
*/
|
|
14
12
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
@@ -47,6 +45,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
47
45
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
46
|
const dotenv = __importStar(require("dotenv"));
|
|
49
47
|
const llm_1 = require("../llm");
|
|
48
|
+
const image_1 = require("../image");
|
|
50
49
|
const config_1 = require("../config");
|
|
51
50
|
const ai_1 = require("ai");
|
|
52
51
|
// 加载环境变量
|
|
@@ -54,7 +53,8 @@ dotenv.config();
|
|
|
54
53
|
config_1.sdkConfig.setBaseUrl("http://localhost:8000");
|
|
55
54
|
config_1.sdkConfig.setToken(process.env.AUTH_TOKEN || process.env.TOKEN || "");
|
|
56
55
|
config_1.sdkConfig.setDebug(true);
|
|
57
|
-
|
|
56
|
+
const PLUGIN_ID = "test-plugin";
|
|
57
|
+
describe("llm.ts — 真实集成测试(文本 + 图像)", () => {
|
|
58
58
|
const token = process.env.AUTH_TOKEN || process.env.TOKEN;
|
|
59
59
|
beforeAll(() => {
|
|
60
60
|
if (!token) {
|
|
@@ -213,6 +213,32 @@ describe("llm.ts — 真实集成测试(文本生成)", () => {
|
|
|
213
213
|
}, 30000);
|
|
214
214
|
});
|
|
215
215
|
// ============================================================
|
|
216
|
+
// createProvider + generateImage(kunpo 图像生成)
|
|
217
|
+
// ============================================================
|
|
218
|
+
describe("generateKunpoImage(kunpo 图像)", () => {
|
|
219
|
+
const promptArg = "A simple red circle on a white background";
|
|
220
|
+
test("kunpo — Image-GI2(异步)", async () => {
|
|
221
|
+
const modelId = process.env.KUNPO_IMAGE_MODEL || "Image-GI2";
|
|
222
|
+
const result = await (0, image_1.generateKunpoImage)({
|
|
223
|
+
pluginId: PLUGIN_ID,
|
|
224
|
+
model: modelId,
|
|
225
|
+
prompt: promptArg,
|
|
226
|
+
size: "1024x1024",
|
|
227
|
+
quality: "high",
|
|
228
|
+
async: true,
|
|
229
|
+
});
|
|
230
|
+
expect(result.images).toBeDefined();
|
|
231
|
+
expect(result.images.length).toBeGreaterThan(0);
|
|
232
|
+
const first = result.images[0];
|
|
233
|
+
expect(first?.base64 || first?.uint8Array?.byteLength).toBeTruthy();
|
|
234
|
+
console.log("✅ Kunpo 图像生成:", {
|
|
235
|
+
model: modelId,
|
|
236
|
+
mediaType: first?.mediaType,
|
|
237
|
+
bytes: first?.uint8Array?.byteLength ?? first?.base64?.length,
|
|
238
|
+
});
|
|
239
|
+
}, 120000);
|
|
240
|
+
});
|
|
241
|
+
// ============================================================
|
|
216
242
|
// checkModel 真实可用性检查
|
|
217
243
|
// ============================================================
|
|
218
244
|
describe("checkModel(模型可用性检查)", () => {
|
|
@@ -263,10 +289,16 @@ describe("llm.ts — 真实集成测试(文本生成)", () => {
|
|
|
263
289
|
expect(() => (0, llm_1.createProvider)("api2img", "gemini", "test")).not.toThrow();
|
|
264
290
|
// Anthropic
|
|
265
291
|
expect(() => (0, llm_1.createProvider)("anthropic", "anthropic", "test")).not.toThrow();
|
|
292
|
+
expect(() => (0, llm_1.createProvider)("kunpo", "openai", "test")).not.toThrow();
|
|
266
293
|
});
|
|
267
294
|
test("provider 实例有 languageModel 方法", () => {
|
|
268
295
|
const provider = (0, llm_1.createProvider)("api2img", "openai", "test");
|
|
269
296
|
expect(typeof provider.languageModel).toBe("function");
|
|
270
297
|
});
|
|
298
|
+
test("getImageProxyConfig 返回 /api/llm/image 代理地址", () => {
|
|
299
|
+
const { getImageProxyConfig } = require("../image");
|
|
300
|
+
const cfg = getImageProxyConfig("test");
|
|
301
|
+
expect(cfg.baseUrl).toContain("/api/llm/image");
|
|
302
|
+
});
|
|
271
303
|
});
|
|
272
304
|
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Config Client
|
|
3
|
+
* 管理员 AI 配置(提供商、模型列表)
|
|
4
|
+
*/
|
|
5
|
+
export interface AIConfigClientConfig {
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
token?: string;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
export declare class AIConfigClient {
|
|
11
|
+
private baseUrl;
|
|
12
|
+
private headers;
|
|
13
|
+
constructor(config?: AIConfigClientConfig);
|
|
14
|
+
private handleErrorResponse;
|
|
15
|
+
getProviders(): Promise<any>;
|
|
16
|
+
getProviderModels(providerId: string): Promise<any>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AI Config Client
|
|
4
|
+
* 管理员 AI 配置(提供商、模型列表)
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.AIConfigClient = void 0;
|
|
8
|
+
const config_1 = require("./config");
|
|
9
|
+
const log_1 = require("./log");
|
|
10
|
+
class AIConfigClient {
|
|
11
|
+
constructor(config = {}) {
|
|
12
|
+
this.baseUrl =
|
|
13
|
+
config.baseUrl ||
|
|
14
|
+
config_1.sdkConfig.getServerUrl() ||
|
|
15
|
+
(typeof window !== "undefined" ? window.location.origin : "");
|
|
16
|
+
const globalHeaders = config_1.sdkConfig.getHeaders();
|
|
17
|
+
const globalToken = config.token || config_1.sdkConfig.getToken();
|
|
18
|
+
this.headers = {
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
...globalHeaders,
|
|
21
|
+
...config.headers,
|
|
22
|
+
};
|
|
23
|
+
if (globalToken) {
|
|
24
|
+
this.headers["Authorization"] = `Bearer ${globalToken}`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async handleErrorResponse(response) {
|
|
28
|
+
let errorMessage = `Request failed: ${response.status} ${response.statusText}`;
|
|
29
|
+
try {
|
|
30
|
+
const errorText = await response.text();
|
|
31
|
+
const errorJson = JSON.parse(errorText);
|
|
32
|
+
errorMessage = errorJson.detail || errorMessage;
|
|
33
|
+
}
|
|
34
|
+
catch { }
|
|
35
|
+
throw new Error(errorMessage);
|
|
36
|
+
}
|
|
37
|
+
async getProviders() {
|
|
38
|
+
config_1.sdkConfig.ensureVersionCompatible();
|
|
39
|
+
const url = `${this.baseUrl}/api/ai/config/providers`;
|
|
40
|
+
(0, log_1.logRequest)("GET", url, this.headers);
|
|
41
|
+
const response = await fetch(url, { headers: this.headers });
|
|
42
|
+
if (!response.ok)
|
|
43
|
+
await this.handleErrorResponse(response);
|
|
44
|
+
return await response.json();
|
|
45
|
+
}
|
|
46
|
+
async getProviderModels(providerId) {
|
|
47
|
+
config_1.sdkConfig.ensureVersionCompatible();
|
|
48
|
+
const url = `${this.baseUrl}/api/ai/config/providers/${encodeURIComponent(providerId)}/models`;
|
|
49
|
+
(0, log_1.logRequest)("GET", url, this.headers);
|
|
50
|
+
const response = await fetch(url, { headers: this.headers });
|
|
51
|
+
if (!response.ok)
|
|
52
|
+
await this.handleErrorResponse(response);
|
|
53
|
+
return await response.json();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.AIConfigClient = AIConfigClient;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerAiConfigCommands = registerAiConfigCommands;
|
|
4
|
+
const ai_config_1 = require("../../ai-config");
|
|
5
|
+
const config_1 = require("../config");
|
|
6
|
+
const output_1 = require("../output");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
function collectOpts(cmd) {
|
|
9
|
+
const chain = [];
|
|
10
|
+
for (let c = cmd; c; c = c.parent) {
|
|
11
|
+
chain.unshift(c);
|
|
12
|
+
}
|
|
13
|
+
const o = {};
|
|
14
|
+
for (const c of chain) {
|
|
15
|
+
Object.assign(o, c.opts());
|
|
16
|
+
}
|
|
17
|
+
return o;
|
|
18
|
+
}
|
|
19
|
+
function prepareAiConfig(program, cmd) {
|
|
20
|
+
const o = collectOpts(cmd);
|
|
21
|
+
const auth = (0, config_1.resolveAuth)({
|
|
22
|
+
baseUrl: o.baseUrl,
|
|
23
|
+
token: o.token,
|
|
24
|
+
pluginId: o.pluginId,
|
|
25
|
+
});
|
|
26
|
+
(0, utils_1.requireOption)(auth.token, 'token');
|
|
27
|
+
(0, utils_1.initSDK)(auth);
|
|
28
|
+
return (0, utils_1.getFormat)(program);
|
|
29
|
+
}
|
|
30
|
+
function registerAiConfigCommands(program) {
|
|
31
|
+
const aiConfig = program
|
|
32
|
+
.command('ai-config')
|
|
33
|
+
.description('AI 配置(提供商与模型列表)');
|
|
34
|
+
aiConfig.command('providers').action(async (_opts, cmd) => {
|
|
35
|
+
const commandName = 'ai-config providers';
|
|
36
|
+
try {
|
|
37
|
+
const format = prepareAiConfig(program, cmd);
|
|
38
|
+
const client = new ai_config_1.AIConfigClient();
|
|
39
|
+
const result = await client.getProviders();
|
|
40
|
+
(0, output_1.output)(result, format);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
(0, utils_1.handleError)(err, commandName);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
aiConfig
|
|
47
|
+
.command('models')
|
|
48
|
+
.requiredOption('--provider <id>', '提供商 ID')
|
|
49
|
+
.action(async (opts, cmd) => {
|
|
50
|
+
const commandName = 'ai-config models';
|
|
51
|
+
try {
|
|
52
|
+
const format = prepareAiConfig(program, cmd);
|
|
53
|
+
const client = new ai_config_1.AIConfigClient();
|
|
54
|
+
const result = await client.getProviderModels(opts.provider);
|
|
55
|
+
(0, output_1.output)(result, format);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
(0, utils_1.handleError)(err, commandName);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -36,9 +36,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.registerImageCommands = registerImageCommands;
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
38
|
const path = __importStar(require("path"));
|
|
39
|
-
const ai_1 = require("ai");
|
|
40
39
|
const index_1 = require("../../index");
|
|
41
|
-
const config_1 = require("
|
|
40
|
+
const config_1 = require("../../config");
|
|
41
|
+
const config_2 = require("../config");
|
|
42
42
|
const output_1 = require("../output");
|
|
43
43
|
const utils_1 = require("../utils");
|
|
44
44
|
function collectOpts(cmd) {
|
|
@@ -63,22 +63,86 @@ function stripB64ForLog(obj) {
|
|
|
63
63
|
}
|
|
64
64
|
return copy;
|
|
65
65
|
}
|
|
66
|
+
async function downloadUrlToFile(url, outputPath) {
|
|
67
|
+
const res = await fetch(url);
|
|
68
|
+
if (!res.ok) {
|
|
69
|
+
throw new Error(`下载图像失败: ${res.status}`);
|
|
70
|
+
}
|
|
71
|
+
const abs = path.resolve(outputPath);
|
|
72
|
+
const dir = path.dirname(abs);
|
|
73
|
+
if (!fs.existsSync(dir))
|
|
74
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
75
|
+
fs.writeFileSync(abs, Buffer.from(await res.arrayBuffer()));
|
|
76
|
+
}
|
|
77
|
+
/** OpenAI 图像:经 /api/llm/openai 代理(HTTP,非 AI SDK) */
|
|
78
|
+
async function generateOpenAIImageViaProxy(pluginId, model, prompt, size) {
|
|
79
|
+
const serverUrl = config_1.sdkConfig.getServerUrl() || '';
|
|
80
|
+
const token = config_1.sdkConfig.getToken() || '';
|
|
81
|
+
const body = {
|
|
82
|
+
model,
|
|
83
|
+
prompt,
|
|
84
|
+
n: 1,
|
|
85
|
+
response_format: 'b64_json',
|
|
86
|
+
};
|
|
87
|
+
if (size)
|
|
88
|
+
body.size = size;
|
|
89
|
+
const res = await fetch(`${serverUrl}/api/llm/openai/images/generations`, {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: {
|
|
92
|
+
'Content-Type': 'application/json',
|
|
93
|
+
'X-Plugin-Id': pluginId,
|
|
94
|
+
'X-Provider': 'api2img',
|
|
95
|
+
Authorization: `Bearer ${token}`,
|
|
96
|
+
},
|
|
97
|
+
body: JSON.stringify(body),
|
|
98
|
+
});
|
|
99
|
+
if (!res.ok) {
|
|
100
|
+
const text = await res.text().catch(() => '');
|
|
101
|
+
throw new Error(`OpenAI 图像生成失败: ${res.status} ${text}`);
|
|
102
|
+
}
|
|
103
|
+
const json = (await res.json());
|
|
104
|
+
const first = json.data?.[0];
|
|
105
|
+
if (!first) {
|
|
106
|
+
throw new Error('OpenAI 图像生成响应无数据');
|
|
107
|
+
}
|
|
108
|
+
if (first.b64_json) {
|
|
109
|
+
const buf = Buffer.from(first.b64_json, 'base64');
|
|
110
|
+
return { uint8Array: new Uint8Array(buf), mediaType: 'image/png' };
|
|
111
|
+
}
|
|
112
|
+
if (first.url) {
|
|
113
|
+
const imgRes = await fetch(first.url);
|
|
114
|
+
if (!imgRes.ok) {
|
|
115
|
+
throw new Error(`下载图像失败: ${imgRes.status}`);
|
|
116
|
+
}
|
|
117
|
+
const buf = Buffer.from(await imgRes.arrayBuffer());
|
|
118
|
+
return {
|
|
119
|
+
uint8Array: new Uint8Array(buf),
|
|
120
|
+
mediaType: imgRes.headers.get('content-type') || 'image/png',
|
|
121
|
+
url: first.url,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
throw new Error('OpenAI 图像生成响应无 url 或 b64_json');
|
|
125
|
+
}
|
|
66
126
|
function registerImageCommands(program) {
|
|
67
|
-
const image = program
|
|
127
|
+
const image = program
|
|
128
|
+
.command('image')
|
|
129
|
+
.description('图像生成(doubao / gemini / openai / kunpo)');
|
|
68
130
|
image
|
|
69
131
|
.command('generate')
|
|
70
|
-
.requiredOption('--provider <name>', 'doubao, gemini, or
|
|
132
|
+
.requiredOption('--provider <name>', 'doubao, gemini, openai, or kunpo')
|
|
71
133
|
.requiredOption('--prompt <text>', 'Prompt text')
|
|
72
134
|
.option('--model <id>', 'Model id')
|
|
73
|
-
.option('--size <value>', 'Size
|
|
135
|
+
.option('--size <value>', 'Size e.g. 1024x1024, 1536x1024')
|
|
136
|
+
.option('--quality <value>', 'KUNPO quality: low, standard, medium, high, hd')
|
|
137
|
+
.option('--sync', 'KUNPO: use sync /images/generations (not recommended)')
|
|
74
138
|
.option('--output <file>', 'Write first image to file')
|
|
75
|
-
.option('--plugin-id <id>', 'Plugin id (required for openai)')
|
|
139
|
+
.option('--plugin-id <id>', 'Plugin id (required for openai / kunpo)')
|
|
76
140
|
.action(async (options, cmd) => {
|
|
77
141
|
const commandName = 'image generate';
|
|
78
142
|
try {
|
|
79
143
|
void (0, utils_1.getFormat)(program);
|
|
80
144
|
const o = collectOpts(cmd);
|
|
81
|
-
const auth = (0,
|
|
145
|
+
const auth = (0, config_2.resolveAuth)({
|
|
82
146
|
baseUrl: o.baseUrl,
|
|
83
147
|
token: o.token,
|
|
84
148
|
pluginId: options.pluginId ??
|
|
@@ -88,8 +152,8 @@ function registerImageCommands(program) {
|
|
|
88
152
|
(0, utils_1.requireOption)(options.prompt, 'prompt');
|
|
89
153
|
(0, utils_1.requireOption)(options.provider, 'provider');
|
|
90
154
|
const providerName = options.provider.toLowerCase();
|
|
91
|
-
if (!['doubao', 'gemini', 'openai'].includes(providerName)) {
|
|
92
|
-
const err = new Error('缺少必需参数: --provider 必须是 doubao、gemini 或
|
|
155
|
+
if (!['doubao', 'gemini', 'openai', 'kunpo'].includes(providerName)) {
|
|
156
|
+
const err = new Error('缺少必需参数: --provider 必须是 doubao、gemini、openai 或 kunpo');
|
|
93
157
|
err.code = 'VALIDATION_ERROR';
|
|
94
158
|
throw err;
|
|
95
159
|
}
|
|
@@ -106,15 +170,7 @@ function registerImageCommands(program) {
|
|
|
106
170
|
(0, utils_1.writeOutputFile)(options.output, Buffer.from(first.b64_json, 'base64'));
|
|
107
171
|
}
|
|
108
172
|
else if (first?.url) {
|
|
109
|
-
|
|
110
|
-
const dir = path.dirname(abs);
|
|
111
|
-
if (!fs.existsSync(dir))
|
|
112
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
113
|
-
const res = await fetch(first.url);
|
|
114
|
-
if (!res.ok) {
|
|
115
|
-
throw new Error(`下载图像失败: ${res.status}`);
|
|
116
|
-
}
|
|
117
|
-
fs.writeFileSync(abs, Buffer.from(await res.arrayBuffer()));
|
|
173
|
+
await downloadUrlToFile(first.url, options.output);
|
|
118
174
|
}
|
|
119
175
|
}
|
|
120
176
|
(0, output_1.outputJSON)(options.output ? stripB64ForLog({ ...result, savedTo: options.output }) : result);
|
|
@@ -136,15 +192,7 @@ function registerImageCommands(program) {
|
|
|
136
192
|
(0, utils_1.writeOutputFile)(options.output, Buffer.from(first.b64_json, 'base64'));
|
|
137
193
|
}
|
|
138
194
|
else if (first?.url) {
|
|
139
|
-
|
|
140
|
-
const dir = path.dirname(abs);
|
|
141
|
-
if (!fs.existsSync(dir))
|
|
142
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
143
|
-
const res = await fetch(first.url);
|
|
144
|
-
if (!res.ok) {
|
|
145
|
-
throw new Error(`下载图像失败: ${res.status}`);
|
|
146
|
-
}
|
|
147
|
-
fs.writeFileSync(abs, Buffer.from(await res.arrayBuffer()));
|
|
195
|
+
await downloadUrlToFile(first.url, options.output);
|
|
148
196
|
}
|
|
149
197
|
}
|
|
150
198
|
(0, output_1.outputJSON)(options.output ? stripB64ForLog({ ...result, savedTo: options.output }) : result);
|
|
@@ -155,28 +203,83 @@ function registerImageCommands(program) {
|
|
|
155
203
|
auth.pluginId;
|
|
156
204
|
(0, utils_1.requireOption)(pluginId, 'plugin-id');
|
|
157
205
|
(0, utils_1.initSDK)({ ...auth, pluginId });
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
206
|
+
if (providerName === 'kunpo') {
|
|
207
|
+
const modelId = options.model || 'Image-GI2';
|
|
208
|
+
const useSync = Boolean(options.sync);
|
|
209
|
+
if (useSync) {
|
|
210
|
+
const body = {
|
|
211
|
+
model: modelId,
|
|
212
|
+
prompt: options.prompt,
|
|
213
|
+
response_format: 'b64_json',
|
|
214
|
+
n: 1,
|
|
215
|
+
};
|
|
216
|
+
if (options.size && /^\d+x\d+$|auto/.test(options.size)) {
|
|
217
|
+
body.size = options.size;
|
|
218
|
+
}
|
|
219
|
+
if (options.quality) {
|
|
220
|
+
body.quality = options.quality;
|
|
221
|
+
}
|
|
222
|
+
const resp = await (0, index_1.generateImageSync)(pluginId, body);
|
|
223
|
+
const first = resp.data?.[0];
|
|
224
|
+
if (options.output && first?.b64_json) {
|
|
225
|
+
(0, utils_1.writeOutputFile)(options.output, Buffer.from(first.b64_json, 'base64'));
|
|
226
|
+
}
|
|
227
|
+
else if (options.output && first?.url) {
|
|
228
|
+
await downloadUrlToFile(first.url, options.output);
|
|
229
|
+
}
|
|
230
|
+
(0, output_1.outputJSON)({
|
|
231
|
+
provider: 'kunpo',
|
|
232
|
+
model: modelId,
|
|
233
|
+
mode: 'sync',
|
|
234
|
+
proxy: (0, index_1.getImageProxyConfig)(pluginId).baseUrl,
|
|
235
|
+
savedTo: options.output || undefined,
|
|
236
|
+
data: resp.data?.map((d) => ({
|
|
237
|
+
...d,
|
|
238
|
+
b64_json: d.b64_json ? '[omitted]' : undefined,
|
|
239
|
+
})),
|
|
240
|
+
});
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const kunpoOpts = {
|
|
244
|
+
pluginId: pluginId,
|
|
245
|
+
model: modelId,
|
|
246
|
+
prompt: options.prompt,
|
|
247
|
+
async: true,
|
|
248
|
+
};
|
|
249
|
+
if (options.size && /^\d+x\d+$|auto/.test(options.size)) {
|
|
250
|
+
kunpoOpts.size = options.size;
|
|
251
|
+
}
|
|
252
|
+
if (options.quality) {
|
|
253
|
+
kunpoOpts.quality = options.quality;
|
|
254
|
+
}
|
|
255
|
+
const imgResult = await (0, index_1.generateKunpoImage)(kunpoOpts);
|
|
256
|
+
const first = imgResult.images[0];
|
|
257
|
+
if (options.output && first) {
|
|
258
|
+
(0, utils_1.writeOutputFile)(options.output, Buffer.from(first.uint8Array));
|
|
259
|
+
}
|
|
260
|
+
(0, output_1.outputJSON)({
|
|
261
|
+
provider: 'kunpo',
|
|
262
|
+
model: modelId,
|
|
263
|
+
mode: 'async',
|
|
264
|
+
taskId: imgResult.taskId,
|
|
265
|
+
resultUrl: imgResult.resultUrl,
|
|
266
|
+
mediaType: first?.mediaType,
|
|
267
|
+
savedTo: options.output || undefined,
|
|
268
|
+
});
|
|
269
|
+
return;
|
|
167
270
|
}
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
271
|
+
// openai:/api/llm/openai 代理 HTTP
|
|
272
|
+
const modelId = options.model || 'dall-e-3';
|
|
273
|
+
const img = await generateOpenAIImageViaProxy(pluginId, modelId, options.prompt, options.size);
|
|
274
|
+
if (options.output) {
|
|
275
|
+
(0, utils_1.writeOutputFile)(options.output, Buffer.from(img.uint8Array));
|
|
172
276
|
}
|
|
173
277
|
(0, output_1.outputJSON)({
|
|
174
278
|
provider: 'openai',
|
|
175
279
|
model: modelId,
|
|
176
|
-
mediaType:
|
|
280
|
+
mediaType: img.mediaType,
|
|
281
|
+
url: img.url,
|
|
177
282
|
savedTo: options.output || undefined,
|
|
178
|
-
usage: imgResult.usage,
|
|
179
|
-
warnings: imgResult.warnings,
|
|
180
283
|
});
|
|
181
284
|
}
|
|
182
285
|
catch (err) {
|
|
@@ -30,9 +30,9 @@ function prepareStats(program, cmd) {
|
|
|
30
30
|
function parsePeriod(raw) {
|
|
31
31
|
if (raw === undefined)
|
|
32
32
|
return undefined;
|
|
33
|
-
if (raw === 'daily' || raw === 'weekly' || raw === 'monthly')
|
|
33
|
+
if (raw === 'hourly' || raw === 'daily' || raw === 'weekly' || raw === 'monthly')
|
|
34
34
|
return raw;
|
|
35
|
-
const err = new Error('period 必须是 daily | weekly | monthly');
|
|
35
|
+
const err = new Error('period 必须是 hourly | daily | weekly | monthly');
|
|
36
36
|
err.code = 'VALIDATION_ERROR';
|
|
37
37
|
throw err;
|
|
38
38
|
}
|
|
@@ -116,8 +116,10 @@ function registerStatsCommands(program) {
|
|
|
116
116
|
});
|
|
117
117
|
stats
|
|
118
118
|
.command('ai-trend')
|
|
119
|
-
.option('--period <p>', 'daily | weekly | monthly', 'daily')
|
|
119
|
+
.option('--period <p>', 'hourly | daily | weekly | monthly', 'daily')
|
|
120
120
|
.option('--days <n>', '天数', (v) => parseInt(v, 10))
|
|
121
|
+
.option('--start-date <date>', '开始日期')
|
|
122
|
+
.option('--end-date <date>', '结束日期')
|
|
121
123
|
.option('--provider <name>', '提供商')
|
|
122
124
|
.option('--model <id>', '模型')
|
|
123
125
|
.option('--user-id <n>', '用户 ID', (v) => parseInt(v, 10))
|
|
@@ -131,6 +133,8 @@ function registerStatsCommands(program) {
|
|
|
131
133
|
const result = await client.getAiApiCallsTrend({
|
|
132
134
|
period,
|
|
133
135
|
days: opts.days,
|
|
136
|
+
startDate: opts.startDate,
|
|
137
|
+
endDate: opts.endDate,
|
|
134
138
|
userId: opts.userId,
|
|
135
139
|
apiType: opts.apiType,
|
|
136
140
|
provider: opts.provider,
|
|
@@ -142,9 +146,21 @@ function registerStatsCommands(program) {
|
|
|
142
146
|
(0, utils_1.handleError)(err, commandName);
|
|
143
147
|
}
|
|
144
148
|
});
|
|
149
|
+
stats.command('ai-filters').action(async (_opts, cmd) => {
|
|
150
|
+
const commandName = 'stats ai-filters';
|
|
151
|
+
try {
|
|
152
|
+
const format = prepareStats(program, cmd);
|
|
153
|
+
const client = new stats_1.StatsClient();
|
|
154
|
+
const result = await client.getAiApiCallsFilters();
|
|
155
|
+
(0, output_1.output)(result, format);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
(0, utils_1.handleError)(err, commandName);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
145
161
|
stats
|
|
146
162
|
.command('ai-trend-by-user')
|
|
147
|
-
.option('--period <p>', 'daily | weekly | monthly', 'daily')
|
|
163
|
+
.option('--period <p>', 'hourly | daily | weekly | monthly', 'daily')
|
|
148
164
|
.option('--days <n>', '天数', (v) => parseInt(v, 10))
|
|
149
165
|
.option('--limit <n>', '条数上限', (v) => parseInt(v, 10))
|
|
150
166
|
.option('--provider <name>', '提供商')
|
package/dist/cli/index.js
CHANGED
|
@@ -101,6 +101,7 @@ const skill_1 = require("./commands/skill");
|
|
|
101
101
|
const plugin_1 = require("./commands/plugin");
|
|
102
102
|
const admin_1 = require("./commands/admin");
|
|
103
103
|
const stats_1 = require("./commands/stats");
|
|
104
|
+
const ai_config_1 = require("./commands/ai-config");
|
|
104
105
|
const shared_1 = require("./commands/shared");
|
|
105
106
|
const chrome_1 = require("./commands/chrome");
|
|
106
107
|
(0, help_1.registerHelpCommand)(program);
|
|
@@ -117,6 +118,7 @@ const chrome_1 = require("./commands/chrome");
|
|
|
117
118
|
(0, plugin_1.registerPluginCommands)(program);
|
|
118
119
|
(0, admin_1.registerAdminCommands)(program);
|
|
119
120
|
(0, stats_1.registerStatsCommands)(program);
|
|
121
|
+
(0, ai_config_1.registerAiConfigCommands)(program);
|
|
120
122
|
(0, shared_1.registerSharedCommands)(program);
|
|
121
123
|
(0, chrome_1.registerChromeCommands)(program);
|
|
122
124
|
program.parseAsync(process.argv).catch((err) => {
|
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.
|
|
12
|
+
export declare const SDK_SIGNATURE = "AI_WORLD_SDK_V:1.5.9";
|
|
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.
|
|
39
|
-
readonly sdkVersion = "1.5.
|
|
38
|
+
readonly sdkSignature = "AI_WORLD_SDK_V:1.5.9";
|
|
39
|
+
readonly sdkVersion = "1.5.9";
|
|
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.
|
|
10
|
+
const SDK_VERSION = "1.5.9";
|
|
11
11
|
/**
|
|
12
12
|
* SDK 特征码 - 用于在构建后的 JS 文件中识别 SDK 版本
|
|
13
13
|
* 格式: AI_WORLD_SDK_V:版本号
|
|
@@ -15,7 +15,7 @@ const SDK_VERSION = "1.5.7";
|
|
|
15
15
|
*
|
|
16
16
|
* 注意: {VERSION} 占位符会在构建时被替换为实际版本号
|
|
17
17
|
*/
|
|
18
|
-
exports.SDK_SIGNATURE = "AI_WORLD_SDK_V:1.5.
|
|
18
|
+
exports.SDK_SIGNATURE = "AI_WORLD_SDK_V:1.5.9";
|
|
19
19
|
/**
|
|
20
20
|
* 版本兼容性错误
|
|
21
21
|
*/
|