@optima-chat/comfy-cli 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +2 -1
- package/.claude/skills/comfy-cli/SKILL.md +2 -9
- package/dist/backends/bfl.d.ts +18 -0
- package/dist/backends/bfl.d.ts.map +1 -0
- package/dist/backends/bfl.js +115 -0
- package/dist/backends/bfl.js.map +1 -0
- package/dist/backends/comfyui.d.ts +10 -0
- package/dist/backends/comfyui.d.ts.map +1 -0
- package/dist/backends/comfyui.js +108 -0
- package/dist/backends/comfyui.js.map +1 -0
- package/dist/backends/index.d.ts +24 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +59 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/backends/types.d.ts +47 -0
- package/dist/backends/types.d.ts.map +1 -0
- package/dist/backends/types.js +2 -0
- package/dist/backends/types.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +22 -17
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/image.d.ts +3 -0
- package/dist/commands/image.d.ts.map +1 -0
- package/dist/commands/image.js +148 -0
- package/dist/commands/image.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/services/bfl-api.d.ts +67 -0
- package/dist/services/bfl-api.d.ts.map +1 -0
- package/dist/services/bfl-api.js +99 -0
- package/dist/services/bfl-api.js.map +1 -0
- package/dist/services/config.d.ts +11 -1
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +26 -0
- package/dist/services/config.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,21 +14,14 @@ description: "ComfyUI CLI tool for AI agents. ALWAYS use when user wants to: gen
|
|
|
14
14
|
2. 等待完成(默认行为,显示进度)
|
|
15
15
|
3. 使用返回的 prompt_id 下载:`comfy download <prompt_id>`
|
|
16
16
|
|
|
17
|
-
### 场景 2
|
|
18
|
-
**用户需求**:"生成 3 张不同风格的产品图"
|
|
19
|
-
**执行步骤**:
|
|
20
|
-
1. 使用 `--no-wait` 提交多个任务
|
|
21
|
-
2. `comfy queue status` 查看进度
|
|
22
|
-
3. 完成后批量下载
|
|
23
|
-
|
|
24
|
-
### 场景 3:图片迭代优化
|
|
17
|
+
### 场景 2:图片迭代优化
|
|
25
18
|
**用户需求**:"这张图片不够好,帮我优化"
|
|
26
19
|
**执行步骤**:
|
|
27
20
|
1. 分析用户不满意的点(光线、风格、细节)
|
|
28
21
|
2. 使用 `comfy edit` 添加优化描述
|
|
29
22
|
3. 如需多次尝试,生成多个变体供用户选择
|
|
30
23
|
|
|
31
|
-
### 场景
|
|
24
|
+
### 场景 3:图片生成视频
|
|
32
25
|
**用户需求**:"把这张人物照片做成动态视频"
|
|
33
26
|
**执行步骤**:
|
|
34
27
|
1. `comfy video portrait.png --prompt "natural head movement"`
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ImageBackend, ImageParams, ImageResult } from './types.js';
|
|
2
|
+
export declare class BFLBackend implements ImageBackend {
|
|
3
|
+
readonly name: "bfl";
|
|
4
|
+
private client;
|
|
5
|
+
constructor(apiKey: string);
|
|
6
|
+
isAvailable(): boolean;
|
|
7
|
+
generate(params: ImageParams): Promise<ImageResult>;
|
|
8
|
+
getStatus(id: string): Promise<ImageResult>;
|
|
9
|
+
/**
|
|
10
|
+
* 处理输入图像,转换为 base64
|
|
11
|
+
*/
|
|
12
|
+
private processInputImages;
|
|
13
|
+
/**
|
|
14
|
+
* 将输入图像映射到 BFL 参数
|
|
15
|
+
*/
|
|
16
|
+
private mapInputImages;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=bfl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bfl.d.ts","sourceRoot":"","sources":["../../src/backends/bfl.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAIzE,qBAAa,UAAW,YAAW,YAAY;IAC7C,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAC/B,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,EAAE,MAAM;IAI1B,WAAW,IAAI,OAAO;IAIhB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IA4DnD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAsBjD;;OAEG;YACW,kBAAkB;IAQhC;;OAEG;IACH,OAAO,CAAC,cAAc;CAcvB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { BFLClient } from '../services/bfl-api.js';
|
|
2
|
+
import { getConfig } from '../services/config.js';
|
|
3
|
+
export class BFLBackend {
|
|
4
|
+
name = 'bfl';
|
|
5
|
+
client;
|
|
6
|
+
constructor(apiKey) {
|
|
7
|
+
this.client = new BFLClient(apiKey);
|
|
8
|
+
}
|
|
9
|
+
isAvailable() {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
async generate(params) {
|
|
13
|
+
const startTime = Date.now();
|
|
14
|
+
const cfg = getConfig();
|
|
15
|
+
// 1. 处理输入图像(转为 base64)
|
|
16
|
+
const inputImageBase64s = await this.processInputImages(params.inputImages);
|
|
17
|
+
// 2. 构建 BFL 请求参数
|
|
18
|
+
const bflParams = {
|
|
19
|
+
prompt: params.prompt,
|
|
20
|
+
width: params.width,
|
|
21
|
+
height: params.height,
|
|
22
|
+
seed: params.seed,
|
|
23
|
+
output_format: params.outputFormat || cfg.bfl?.outputFormat || 'png',
|
|
24
|
+
safety_tolerance: params.safetyTolerance ?? cfg.bfl?.safetyTolerance ?? 2,
|
|
25
|
+
...this.mapInputImages(inputImageBase64s),
|
|
26
|
+
};
|
|
27
|
+
// 3. 提交任务
|
|
28
|
+
const submitResult = await this.client.submit(bflParams);
|
|
29
|
+
const taskId = submitResult.id;
|
|
30
|
+
// 4. 如果不等待,直接返回
|
|
31
|
+
if (params.wait === false) {
|
|
32
|
+
return {
|
|
33
|
+
id: taskId,
|
|
34
|
+
backend: 'bfl',
|
|
35
|
+
status: 'pending',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// 5. 轮询等待结果
|
|
39
|
+
const pollResult = await this.client.poll(taskId, {
|
|
40
|
+
interval: 1000,
|
|
41
|
+
timeout: 300000,
|
|
42
|
+
});
|
|
43
|
+
// 6. 下载图像到本地
|
|
44
|
+
const outputDir = cfg.outputDir || './comfy-output';
|
|
45
|
+
const outputFormat = params.outputFormat || cfg.bfl?.outputFormat || 'png';
|
|
46
|
+
const filename = `bfl_${taskId}.${outputFormat}`;
|
|
47
|
+
let localPath;
|
|
48
|
+
if (pollResult.result?.sample) {
|
|
49
|
+
localPath = await this.client.downloadImage(pollResult.result.sample, outputDir, filename);
|
|
50
|
+
}
|
|
51
|
+
const durationMs = Date.now() - startTime;
|
|
52
|
+
return {
|
|
53
|
+
id: taskId,
|
|
54
|
+
backend: 'bfl',
|
|
55
|
+
status: 'completed',
|
|
56
|
+
output: localPath,
|
|
57
|
+
outputUrl: pollResult.result?.sample,
|
|
58
|
+
seed: pollResult.result?.seed,
|
|
59
|
+
durationMs,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async getStatus(id) {
|
|
63
|
+
const result = await this.client.getResult(id);
|
|
64
|
+
let status = 'pending';
|
|
65
|
+
if (result.status === 'Ready') {
|
|
66
|
+
status = 'completed';
|
|
67
|
+
}
|
|
68
|
+
else if (result.status === 'Error' || result.status === 'Request Moderated' || result.status === 'Content Moderated') {
|
|
69
|
+
status = 'failed';
|
|
70
|
+
}
|
|
71
|
+
else if (result.status === 'Pending') {
|
|
72
|
+
status = result.progress && result.progress > 0 ? 'processing' : 'pending';
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
id,
|
|
76
|
+
backend: 'bfl',
|
|
77
|
+
status,
|
|
78
|
+
outputUrl: result.result?.sample,
|
|
79
|
+
seed: result.result?.seed,
|
|
80
|
+
error: status === 'failed' ? result.status : undefined,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 处理输入图像,转换为 base64
|
|
85
|
+
*/
|
|
86
|
+
async processInputImages(paths) {
|
|
87
|
+
if (!paths || paths.length === 0)
|
|
88
|
+
return [];
|
|
89
|
+
return Promise.all(paths.map(p => this.client.imageToBase64(p)));
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* 将输入图像映射到 BFL 参数
|
|
93
|
+
*/
|
|
94
|
+
mapInputImages(base64Images) {
|
|
95
|
+
const mapping = {};
|
|
96
|
+
if (base64Images[0])
|
|
97
|
+
mapping.input_image = base64Images[0];
|
|
98
|
+
if (base64Images[1])
|
|
99
|
+
mapping.input_image_2 = base64Images[1];
|
|
100
|
+
if (base64Images[2])
|
|
101
|
+
mapping.input_image_3 = base64Images[2];
|
|
102
|
+
if (base64Images[3])
|
|
103
|
+
mapping.input_image_4 = base64Images[3];
|
|
104
|
+
if (base64Images[4])
|
|
105
|
+
mapping.input_image_5 = base64Images[4];
|
|
106
|
+
if (base64Images[5])
|
|
107
|
+
mapping.input_image_6 = base64Images[5];
|
|
108
|
+
if (base64Images[6])
|
|
109
|
+
mapping.input_image_7 = base64Images[6];
|
|
110
|
+
if (base64Images[7])
|
|
111
|
+
mapping.input_image_8 = base64Images[7];
|
|
112
|
+
return mapping;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=bfl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bfl.js","sourceRoot":"","sources":["../../src/backends/bfl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ImageBackend, ImageParams, ImageResult } from './types.js';
|
|
2
|
+
export declare class ComfyUIBackend implements ImageBackend {
|
|
3
|
+
readonly name: "comfyui";
|
|
4
|
+
private client;
|
|
5
|
+
constructor();
|
|
6
|
+
isAvailable(): boolean;
|
|
7
|
+
generate(params: ImageParams): Promise<ImageResult>;
|
|
8
|
+
getStatus(id: string): Promise<ImageResult>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=comfyui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comfyui.d.ts","sourceRoot":"","sources":["../../src/backends/comfyui.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzE,qBAAa,cAAe,YAAW,YAAY;IACjD,QAAQ,CAAC,IAAI,EAAG,SAAS,CAAU;IACnC,OAAO,CAAC,MAAM,CAAiB;;IAM/B,WAAW,IAAI,OAAO;IAIhB,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAiGnD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAelD"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { ComfyAPIClient } from '../services/api.js';
|
|
4
|
+
import { loadWorkflow, getBuiltinWorkflowPath, replaceVariables } from '../utils/workflow.js';
|
|
5
|
+
import { monitorProgress } from '../services/websocket.js';
|
|
6
|
+
import { getConfig } from '../services/config.js';
|
|
7
|
+
export class ComfyUIBackend {
|
|
8
|
+
name = 'comfyui';
|
|
9
|
+
client;
|
|
10
|
+
constructor() {
|
|
11
|
+
this.client = new ComfyAPIClient();
|
|
12
|
+
}
|
|
13
|
+
isAvailable() {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
async generate(params) {
|
|
17
|
+
const startTime = Date.now();
|
|
18
|
+
const cfg = getConfig();
|
|
19
|
+
// 1. 选择工作流模板
|
|
20
|
+
const hasInputImage = params.inputImages && params.inputImages.length > 0;
|
|
21
|
+
const workflowName = hasInputImage ? 'flux_image_to_image.json' : 'flux_text_to_image.json';
|
|
22
|
+
const workflowPath = getBuiltinWorkflowPath(workflowName);
|
|
23
|
+
const workflow = loadWorkflow(workflowPath);
|
|
24
|
+
// 2. 处理输入图像(如果有)
|
|
25
|
+
let uploadedImageName;
|
|
26
|
+
if (hasInputImage && params.inputImages[0]) {
|
|
27
|
+
const imagePath = params.inputImages[0];
|
|
28
|
+
const imageBuffer = await fs.readFile(imagePath);
|
|
29
|
+
const filename = path.basename(imagePath);
|
|
30
|
+
const uploadResult = await this.client.uploadImage(imageBuffer, filename);
|
|
31
|
+
uploadedImageName = uploadResult.name;
|
|
32
|
+
}
|
|
33
|
+
// 3. 构建工作流参数
|
|
34
|
+
const workflowParams = {
|
|
35
|
+
prompt: params.prompt,
|
|
36
|
+
width: params.width || 1024,
|
|
37
|
+
height: params.height || 1024,
|
|
38
|
+
steps: 20,
|
|
39
|
+
cfg_scale: 1.0,
|
|
40
|
+
seed: params.seed ?? Math.floor(Math.random() * 1000000),
|
|
41
|
+
filename_prefix: 'comfy-cli',
|
|
42
|
+
model: 'FLUX1/flux1-dev-fp8.safetensors',
|
|
43
|
+
sampler: 'euler',
|
|
44
|
+
scheduler: 'simple',
|
|
45
|
+
negative_prompt: 'Blurry details, distorted shapes, unrealistic reflections, harsh lighting, excessive shadows, overly saturated colors, unnatural composition, poor rendering, low resolution, pixelation, artificial-looking textures, overly exaggerated contrast, cluttered background, unnecessary elements, random objects, plastic-like appearance.',
|
|
46
|
+
guidance: 3.5,
|
|
47
|
+
};
|
|
48
|
+
if (uploadedImageName) {
|
|
49
|
+
workflowParams.input_image = uploadedImageName;
|
|
50
|
+
workflowParams.denoise = 0.75; // 图生图默认 denoise
|
|
51
|
+
}
|
|
52
|
+
// 4. 替换变量并提交
|
|
53
|
+
const processedWorkflow = replaceVariables(workflow, workflowParams);
|
|
54
|
+
const result = await this.client.submitWorkflow(processedWorkflow);
|
|
55
|
+
const promptId = result.prompt_id;
|
|
56
|
+
// 5. 如果不等待,直接返回
|
|
57
|
+
if (params.wait === false) {
|
|
58
|
+
return {
|
|
59
|
+
id: promptId,
|
|
60
|
+
backend: 'comfyui',
|
|
61
|
+
status: 'pending',
|
|
62
|
+
seed: workflowParams.seed,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// 6. WebSocket 监控进度
|
|
66
|
+
await monitorProgress(promptId);
|
|
67
|
+
// 7. 获取输出文件并下载到本地
|
|
68
|
+
const outputs = await this.client.getOutputFiles(promptId);
|
|
69
|
+
const outputFile = outputs[0];
|
|
70
|
+
let localPath;
|
|
71
|
+
let outputUrl;
|
|
72
|
+
if (outputFile) {
|
|
73
|
+
// 构建 URL
|
|
74
|
+
const serverUrl = cfg.server;
|
|
75
|
+
outputUrl = `${serverUrl}/view?filename=${encodeURIComponent(outputFile.filename)}&subfolder=${encodeURIComponent(outputFile.subfolder)}&type=${encodeURIComponent(outputFile.type)}`;
|
|
76
|
+
// 下载到本地
|
|
77
|
+
const outputDir = cfg.outputDir || './comfy-output';
|
|
78
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
79
|
+
localPath = path.join(outputDir, outputFile.filename);
|
|
80
|
+
const imageBuffer = await this.client.downloadImage(outputFile.filename, outputFile.subfolder, outputFile.type);
|
|
81
|
+
await fs.writeFile(localPath, imageBuffer);
|
|
82
|
+
}
|
|
83
|
+
const durationMs = Date.now() - startTime;
|
|
84
|
+
return {
|
|
85
|
+
id: promptId,
|
|
86
|
+
backend: 'comfyui',
|
|
87
|
+
status: 'completed',
|
|
88
|
+
output: localPath,
|
|
89
|
+
outputUrl,
|
|
90
|
+
seed: workflowParams.seed,
|
|
91
|
+
durationMs,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
async getStatus(id) {
|
|
95
|
+
const history = await this.client.getHistory(id);
|
|
96
|
+
let status = 'pending';
|
|
97
|
+
if (history && history[id]) {
|
|
98
|
+
const outputs = history[id].outputs;
|
|
99
|
+
status = outputs && Object.keys(outputs).length > 0 ? 'completed' : 'processing';
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
id,
|
|
103
|
+
backend: 'comfyui',
|
|
104
|
+
status,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=comfyui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comfyui.js","sourceRoot":"","sources":["../../src/backends/comfyui.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ImageBackend } from './types.js';
|
|
2
|
+
export type BackendType = 'auto' | 'bfl' | 'comfyui';
|
|
3
|
+
export { ImageBackend, ImageParams, ImageResult } from './types.js';
|
|
4
|
+
export { BFLBackend } from './bfl.js';
|
|
5
|
+
export { ComfyUIBackend } from './comfyui.js';
|
|
6
|
+
/**
|
|
7
|
+
* 获取 BFL API Key(优先环境变量,其次配置文件)
|
|
8
|
+
*/
|
|
9
|
+
export declare function getBFLApiKey(): string | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* 获取图像生成后端
|
|
12
|
+
*
|
|
13
|
+
* - auto: 有 BFL API Key 则用 BFL,否则用 ComfyUI
|
|
14
|
+
* - bfl: 强制使用 BFL(需要 API Key)
|
|
15
|
+
* - comfyui: 强制使用 ComfyUI
|
|
16
|
+
*
|
|
17
|
+
* API Key 优先级: 环境变量 BFL_API_KEY > 配置文件 bfl.apiKey
|
|
18
|
+
*/
|
|
19
|
+
export declare function getBackend(type?: BackendType): ImageBackend;
|
|
20
|
+
/**
|
|
21
|
+
* 获取当前会使用的后端名称
|
|
22
|
+
*/
|
|
23
|
+
export declare function getCurrentBackendName(type?: BackendType): 'bfl' | 'comfyui';
|
|
24
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,SAAS,CAEjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,YAAY,CAyB3D;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE,WAAW,GAAG,KAAK,GAAG,SAAS,CAe3E"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { getConfig } from '../services/config.js';
|
|
2
|
+
import { BFLBackend } from './bfl.js';
|
|
3
|
+
import { ComfyUIBackend } from './comfyui.js';
|
|
4
|
+
export { BFLBackend } from './bfl.js';
|
|
5
|
+
export { ComfyUIBackend } from './comfyui.js';
|
|
6
|
+
/**
|
|
7
|
+
* 获取 BFL API Key(优先环境变量,其次配置文件)
|
|
8
|
+
*/
|
|
9
|
+
export function getBFLApiKey() {
|
|
10
|
+
return process.env.BFL_API_KEY || getConfig().bfl?.apiKey;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 获取图像生成后端
|
|
14
|
+
*
|
|
15
|
+
* - auto: 有 BFL API Key 则用 BFL,否则用 ComfyUI
|
|
16
|
+
* - bfl: 强制使用 BFL(需要 API Key)
|
|
17
|
+
* - comfyui: 强制使用 ComfyUI
|
|
18
|
+
*
|
|
19
|
+
* API Key 优先级: 环境变量 BFL_API_KEY > 配置文件 bfl.apiKey
|
|
20
|
+
*/
|
|
21
|
+
export function getBackend(type) {
|
|
22
|
+
const cfg = getConfig();
|
|
23
|
+
const backendType = type || cfg.preferBackend || 'auto';
|
|
24
|
+
// 强制使用 BFL
|
|
25
|
+
if (backendType === 'bfl') {
|
|
26
|
+
const apiKey = getBFLApiKey();
|
|
27
|
+
if (!apiKey) {
|
|
28
|
+
throw new Error('BFL API key not configured. Set BFL_API_KEY env or run: comfy config set bfl.apiKey <key>');
|
|
29
|
+
}
|
|
30
|
+
return new BFLBackend(apiKey);
|
|
31
|
+
}
|
|
32
|
+
// 强制使用 ComfyUI
|
|
33
|
+
if (backendType === 'comfyui') {
|
|
34
|
+
return new ComfyUIBackend();
|
|
35
|
+
}
|
|
36
|
+
// 自动选择:优先 BFL
|
|
37
|
+
const apiKey = getBFLApiKey();
|
|
38
|
+
if (apiKey) {
|
|
39
|
+
return new BFLBackend(apiKey);
|
|
40
|
+
}
|
|
41
|
+
return new ComfyUIBackend();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 获取当前会使用的后端名称
|
|
45
|
+
*/
|
|
46
|
+
export function getCurrentBackendName(type) {
|
|
47
|
+
const cfg = getConfig();
|
|
48
|
+
const backendType = type || cfg.preferBackend || 'auto';
|
|
49
|
+
if (backendType === 'bfl') {
|
|
50
|
+
return 'bfl';
|
|
51
|
+
}
|
|
52
|
+
if (backendType === 'comfyui') {
|
|
53
|
+
return 'comfyui';
|
|
54
|
+
}
|
|
55
|
+
// auto
|
|
56
|
+
const apiKey = getBFLApiKey();
|
|
57
|
+
return apiKey ? 'bfl' : 'comfyui';
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAM9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC;AAC5D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,IAAkB;IAC3C,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,WAAW,GAAG,IAAI,IAAI,GAAG,CAAC,aAAa,IAAI,MAAM,CAAC;IAExD,WAAW;IACX,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2FAA2F,CAAC,CAAC;QAC/G,CAAC;QACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAED,eAAe;IACf,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,IAAI,cAAc,EAAE,CAAC;IAC9B,CAAC;IAED,cAAc;IACd,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,IAAI,cAAc,EAAE,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAkB;IACtD,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,WAAW,GAAG,IAAI,IAAI,GAAG,CAAC,aAAa,IAAI,MAAM,CAAC;IAExD,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;QAC1B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;IACP,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,OAAO,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 图像生成/编辑参数
|
|
3
|
+
*/
|
|
4
|
+
export interface ImageParams {
|
|
5
|
+
prompt: string;
|
|
6
|
+
inputImages?: string[];
|
|
7
|
+
width?: number;
|
|
8
|
+
height?: number;
|
|
9
|
+
seed?: number;
|
|
10
|
+
outputFormat?: 'jpeg' | 'png';
|
|
11
|
+
safetyTolerance?: number;
|
|
12
|
+
wait?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 图像生成/编辑结果
|
|
16
|
+
*/
|
|
17
|
+
export interface ImageResult {
|
|
18
|
+
id: string;
|
|
19
|
+
backend: 'bfl' | 'comfyui';
|
|
20
|
+
status: 'pending' | 'processing' | 'completed' | 'failed';
|
|
21
|
+
output?: string;
|
|
22
|
+
outputUrl?: string;
|
|
23
|
+
seed?: number;
|
|
24
|
+
cost?: number;
|
|
25
|
+
megapixels?: number;
|
|
26
|
+
durationMs?: number;
|
|
27
|
+
error?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 后端接口
|
|
31
|
+
*/
|
|
32
|
+
export interface ImageBackend {
|
|
33
|
+
readonly name: 'bfl' | 'comfyui';
|
|
34
|
+
/**
|
|
35
|
+
* 检查后端是否可用
|
|
36
|
+
*/
|
|
37
|
+
isAvailable(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* 生成/编辑图像
|
|
40
|
+
*/
|
|
41
|
+
generate(params: ImageParams): Promise<ImageResult>;
|
|
42
|
+
/**
|
|
43
|
+
* 获取任务状态
|
|
44
|
+
*/
|
|
45
|
+
getStatus(id: string): Promise<ImageResult>;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/backends/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,KAAK,GAAG,SAAS,CAAC;IAC3B,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;IAEjC;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC;IAEvB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAEpD;;OAEG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC7C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/backends/types.ts"],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,QA+MrD"}
|
package/dist/commands/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { config, getConfig, setConfig, resetConfig } from '../services/config.js';
|
|
1
|
+
import { config, getConfig, setConfig, resetConfig, isValidConfigKey } from '../services/config.js';
|
|
2
2
|
import { success, info } from '../utils/logger.js';
|
|
3
3
|
import { outputSuccess, outputError, isPrettyMode } from '../utils/output.js';
|
|
4
4
|
import { addEnhancedHelp } from '../utils/helpText.js';
|
|
@@ -10,21 +10,23 @@ export function registerConfigCommand(program) {
|
|
|
10
10
|
// comfy config set
|
|
11
11
|
const setCmd = configCmd
|
|
12
12
|
.command('set')
|
|
13
|
-
.description('设置配置项 - 配置 ComfyUI
|
|
14
|
-
.argument('<key>', '配置键
|
|
13
|
+
.description('设置配置项 - 配置 ComfyUI/BFL 服务器和其他选项')
|
|
14
|
+
.argument('<key>', '配置键')
|
|
15
15
|
.argument('<value>', '配置值')
|
|
16
16
|
.action((key, value, options) => {
|
|
17
17
|
const pretty = isPrettyMode(options);
|
|
18
18
|
try {
|
|
19
|
-
if (!
|
|
19
|
+
if (!isValidConfigKey(key)) {
|
|
20
20
|
outputError('INVALID_CONFIG_KEY', `无效的配置键: ${key}`, options);
|
|
21
|
+
return;
|
|
21
22
|
}
|
|
22
23
|
let parsedValue = value;
|
|
23
24
|
// 类型转换
|
|
24
|
-
if (key === 'timeout') {
|
|
25
|
+
if (key === 'timeout' || key === 'bfl.safetyTolerance') {
|
|
25
26
|
parsedValue = parseInt(value);
|
|
26
27
|
if (isNaN(parsedValue)) {
|
|
27
|
-
outputError('INVALID_VALUE',
|
|
28
|
+
outputError('INVALID_VALUE', `${key} 必须是数字`, options);
|
|
29
|
+
return;
|
|
28
30
|
}
|
|
29
31
|
}
|
|
30
32
|
else if (key === 'autoConnect') {
|
|
@@ -49,11 +51,14 @@ export function registerConfigCommand(program) {
|
|
|
49
51
|
// Add enhanced help for set command
|
|
50
52
|
addEnhancedHelp(setCmd, {
|
|
51
53
|
examples: [
|
|
52
|
-
'# 设置 ComfyUI
|
|
54
|
+
'# 设置 ComfyUI 服务器地址',
|
|
53
55
|
'$ comfy config set server http://localhost:8188',
|
|
54
56
|
'',
|
|
55
|
-
'#
|
|
56
|
-
'$ comfy config set
|
|
57
|
+
'# 设置 BFL API Key(启用云端 FLUX.2 Pro)',
|
|
58
|
+
'$ comfy config set bfl.apiKey your-api-key',
|
|
59
|
+
'',
|
|
60
|
+
'# 设置默认后端偏好',
|
|
61
|
+
'$ comfy config set preferBackend auto',
|
|
57
62
|
'',
|
|
58
63
|
'# 设置输出目录',
|
|
59
64
|
'$ comfy config set outputDir ./my-outputs',
|
|
@@ -62,8 +67,8 @@ export function registerConfigCommand(program) {
|
|
|
62
67
|
"success": true,
|
|
63
68
|
"data": {
|
|
64
69
|
"message": "配置已更新",
|
|
65
|
-
"key": "
|
|
66
|
-
"value": "
|
|
70
|
+
"key": "bfl.apiKey",
|
|
71
|
+
"value": "your-api-key"
|
|
67
72
|
}
|
|
68
73
|
}`,
|
|
69
74
|
relatedCommands: [
|
|
@@ -71,10 +76,10 @@ export function registerConfigCommand(program) {
|
|
|
71
76
|
{ command: 'config reset --confirm', description: '重置为默认配置' },
|
|
72
77
|
],
|
|
73
78
|
notes: [
|
|
74
|
-
'
|
|
75
|
-
'
|
|
76
|
-
'
|
|
77
|
-
'
|
|
79
|
+
'基础配置: server, timeout, autoConnect, outputDir',
|
|
80
|
+
'BFL 配置: bfl.apiKey, bfl.safetyTolerance, bfl.outputFormat',
|
|
81
|
+
'后端偏好: preferBackend (auto | bfl | comfyui)',
|
|
82
|
+
'设置 bfl.apiKey 后会自动使用 BFL 云端 API',
|
|
78
83
|
],
|
|
79
84
|
});
|
|
80
85
|
// comfy config list
|
|
@@ -88,9 +93,9 @@ export function registerConfigCommand(program) {
|
|
|
88
93
|
if (pretty) {
|
|
89
94
|
const table = new Table({
|
|
90
95
|
head: ['配置项', '值'],
|
|
91
|
-
colWidths: [
|
|
96
|
+
colWidths: [25, 55],
|
|
92
97
|
});
|
|
93
|
-
table.push(['Server', cfg.server], ['Timeout', `${cfg.timeout}ms`], ['Auto Connect', cfg.autoConnect ? '✓' : '✗'], ['Output Dir', cfg.outputDir]);
|
|
98
|
+
table.push(['Server', cfg.server], ['Timeout', `${cfg.timeout}ms`], ['Auto Connect', cfg.autoConnect ? '✓' : '✗'], ['Output Dir', cfg.outputDir], ['Prefer Backend', cfg.preferBackend], ['─── BFL ───', '───────────'], ['BFL API Key', cfg.bfl?.apiKey ? '******' + cfg.bfl.apiKey.slice(-4) : '(未设置)'], ['BFL Safety', cfg.bfl?.safetyTolerance ?? 2], ['BFL Format', cfg.bfl?.outputFormat ?? 'png']);
|
|
94
99
|
console.log(table.toString());
|
|
95
100
|
info(`配置文件位置: ${config.path}`);
|
|
96
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/commands/image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyBpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QA+IpD"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import ora from 'ora';
|
|
2
|
+
import { getBackend, getCurrentBackendName } from '../backends/index.js';
|
|
3
|
+
import { outputSuccess, outputError, isPrettyMode } from '../utils/output.js';
|
|
4
|
+
import { info, warning } from '../utils/logger.js';
|
|
5
|
+
import { addEnhancedHelp } from '../utils/helpText.js';
|
|
6
|
+
// 收集多个 -i 参数
|
|
7
|
+
function collect(value, previous) {
|
|
8
|
+
return previous.concat([value]);
|
|
9
|
+
}
|
|
10
|
+
export function registerImageCommand(program) {
|
|
11
|
+
const cmd = program
|
|
12
|
+
.command('image')
|
|
13
|
+
.description('生成或编辑图像 - 统一的图像命令,自动选择 BFL 或 ComfyUI 后端')
|
|
14
|
+
.argument('<prompt>', '图像描述提示词')
|
|
15
|
+
.option('-i, --input <path>', '输入图像路径(可多次使用,最多 8 个)', collect, [])
|
|
16
|
+
.option('-w, --width <px>', '输出宽度 (默认: 1024)')
|
|
17
|
+
.option('-h, --height <px>', '输出高度 (默认: 1024)')
|
|
18
|
+
.option('-s, --seed <number>', '随机种子')
|
|
19
|
+
.option('-f, --format <fmt>', '输出格式: jpeg | png (默认: png)')
|
|
20
|
+
.option('-o, --output <path>', '输出目录')
|
|
21
|
+
.option('--safety <level>', '安全等级 0-5 (仅 BFL)')
|
|
22
|
+
.option('--backend <name>', '强制指定后端: bfl | comfyui | auto (默认: auto)')
|
|
23
|
+
.option('--no-wait', '提交后不等待结果')
|
|
24
|
+
.action(async (prompt, options) => {
|
|
25
|
+
const pretty = isPrettyMode(options);
|
|
26
|
+
try {
|
|
27
|
+
// 确定后端类型
|
|
28
|
+
const backendType = options.backend || 'auto';
|
|
29
|
+
const backendName = getCurrentBackendName(backendType);
|
|
30
|
+
// 多图检查
|
|
31
|
+
if (options.input && options.input.length > 1 && backendName === 'comfyui') {
|
|
32
|
+
if (pretty) {
|
|
33
|
+
warning('ComfyUI 只支持单张输入图像,将使用第一张');
|
|
34
|
+
}
|
|
35
|
+
options.input = [options.input[0]];
|
|
36
|
+
}
|
|
37
|
+
if (options.input && options.input.length > 8) {
|
|
38
|
+
outputError('TOO_MANY_INPUTS', '最多支持 8 张输入图像', options);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// 获取后端
|
|
42
|
+
const backend = getBackend(backendType);
|
|
43
|
+
// 显示信息
|
|
44
|
+
const spinner = pretty ? ora(`使用 ${backend.name.toUpperCase()} 后端...`).start() : null;
|
|
45
|
+
if (pretty) {
|
|
46
|
+
spinner.text = options.input?.length
|
|
47
|
+
? `正在编辑图像: "${prompt}"`
|
|
48
|
+
: `正在生成图像: "${prompt}"`;
|
|
49
|
+
}
|
|
50
|
+
// 执行生成
|
|
51
|
+
const result = await backend.generate({
|
|
52
|
+
prompt,
|
|
53
|
+
inputImages: options.input?.length ? options.input : undefined,
|
|
54
|
+
width: options.width ? parseInt(options.width) : undefined,
|
|
55
|
+
height: options.height ? parseInt(options.height) : undefined,
|
|
56
|
+
seed: options.seed ? parseInt(options.seed) : undefined,
|
|
57
|
+
outputFormat: options.format,
|
|
58
|
+
safetyTolerance: options.safety ? parseInt(options.safety) : undefined,
|
|
59
|
+
wait: options.wait !== false,
|
|
60
|
+
});
|
|
61
|
+
// 输出结果
|
|
62
|
+
if (pretty) {
|
|
63
|
+
if (result.status === 'completed') {
|
|
64
|
+
spinner.succeed('图像生成完成!');
|
|
65
|
+
info(`输出文件: ${result.output}`);
|
|
66
|
+
if (result.seed !== undefined) {
|
|
67
|
+
info(`Seed: ${result.seed}`);
|
|
68
|
+
}
|
|
69
|
+
if (result.durationMs !== undefined) {
|
|
70
|
+
info(`耗时: ${(result.durationMs / 1000).toFixed(1)}s`);
|
|
71
|
+
}
|
|
72
|
+
if (result.cost !== undefined) {
|
|
73
|
+
info(`费用: $${result.cost.toFixed(4)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
spinner.info(`任务已提交,ID: ${result.id}`);
|
|
78
|
+
info(`使用 'comfy workflow get ${result.id}' 查看状态`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
outputSuccess({
|
|
83
|
+
id: result.id,
|
|
84
|
+
backend: result.backend,
|
|
85
|
+
status: result.status,
|
|
86
|
+
output: result.output,
|
|
87
|
+
output_url: result.outputUrl,
|
|
88
|
+
seed: result.seed,
|
|
89
|
+
duration_ms: result.durationMs,
|
|
90
|
+
cost: result.cost,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
96
|
+
outputError('IMAGE_ERROR', message, options);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
// Add enhanced help
|
|
100
|
+
addEnhancedHelp(cmd, {
|
|
101
|
+
examples: [
|
|
102
|
+
'# 文生图(自动选择后端)',
|
|
103
|
+
'$ comfy image "a cute cat sitting on a sofa"',
|
|
104
|
+
'',
|
|
105
|
+
'# 单图编辑',
|
|
106
|
+
'$ comfy image "make it look like watercolor" -i photo.png',
|
|
107
|
+
'',
|
|
108
|
+
'# 多图风格融合(BFL 专属)',
|
|
109
|
+
'$ comfy image "combine styles" -i style.png -i content.png',
|
|
110
|
+
'',
|
|
111
|
+
'# 指定尺寸',
|
|
112
|
+
'$ comfy image "landscape" -w 1920 -h 1080',
|
|
113
|
+
'',
|
|
114
|
+
'# 强制使用特定后端',
|
|
115
|
+
'$ comfy image "a cat" --backend comfyui',
|
|
116
|
+
'$ comfy image "a cat" --backend bfl',
|
|
117
|
+
'',
|
|
118
|
+
'# 非阻塞模式',
|
|
119
|
+
'$ comfy image "sunset" --no-wait',
|
|
120
|
+
],
|
|
121
|
+
outputJson: `{
|
|
122
|
+
"success": true,
|
|
123
|
+
"data": {
|
|
124
|
+
"id": "abc-123-xyz",
|
|
125
|
+
"backend": "bfl",
|
|
126
|
+
"status": "completed",
|
|
127
|
+
"output": "./comfy-output/bfl_abc-123-xyz.png",
|
|
128
|
+
"seed": 12345,
|
|
129
|
+
"duration_ms": 12500,
|
|
130
|
+
"cost": 0.03
|
|
131
|
+
}
|
|
132
|
+
}`,
|
|
133
|
+
relatedCommands: [
|
|
134
|
+
{ command: 'config set bfl.apiKey <key>', description: '设置 BFL API Key' },
|
|
135
|
+
{ command: 'config list', description: '查看当前配置和后端' },
|
|
136
|
+
{ command: 'generate <prompt>', description: '生成图像(别名)' },
|
|
137
|
+
{ command: 'edit <image> <prompt>', description: '编辑图像(别名)' },
|
|
138
|
+
],
|
|
139
|
+
notes: [
|
|
140
|
+
'自动选择后端: 有 BFL API Key 用 BFL,否则用 ComfyUI',
|
|
141
|
+
'BFL 云端 API: 高质量、支持多图参考、按量付费',
|
|
142
|
+
'ComfyUI 本地: 免费、支持自定义工作流',
|
|
143
|
+
'多图参考(-i 多次)仅 BFL 支持,ComfyUI 只用第一张',
|
|
144
|
+
'使用 --backend 可强制指定后端',
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/commands/image.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { readFileSync } from 'fs';
|
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
5
5
|
import { dirname, join } from 'path';
|
|
6
6
|
import { setGlobalPrettyMode } from './utils/output.js';
|
|
7
|
+
import { registerImageCommand } from './commands/image.js';
|
|
7
8
|
import { registerGenerateCommand } from './commands/generate.js';
|
|
8
9
|
import { registerEditCommand } from './commands/edit.js';
|
|
9
10
|
import { registerVideoCommand } from './commands/video.js';
|
|
@@ -57,6 +58,7 @@ Output Formats:
|
|
|
57
58
|
Issues: https://github.com/Optima-Chat/comfy-cli/issues
|
|
58
59
|
`);
|
|
59
60
|
// 注册功能命令
|
|
61
|
+
registerImageCommand(program); // 统一图像命令(推荐)
|
|
60
62
|
registerGenerateCommand(program);
|
|
61
63
|
registerEditCommand(program);
|
|
62
64
|
registerVideoCommand(program);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1F,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,2DAA2D,CAAC;KACxE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;KAC5B,MAAM,CAAC,UAAU,EAAE,yBAAyB,CAAC;KAC7C,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;IACjC,6BAA6B;IAC7B,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,EAAE,CAAC;IAC3C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC,CAAC;KACD,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBvB,CAAC,CAAC;AAEH,SAAS;AACT,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAEjC,SAAS;AACT,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1F,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,2DAA2D,CAAC;KACxE,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;KAC5B,MAAM,CAAC,UAAU,EAAE,yBAAyB,CAAC;KAC7C,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,EAAE;IACjC,6BAA6B;IAC7B,MAAM,IAAI,GAAG,WAAW,CAAC,eAAe,EAAE,CAAC;IAC3C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC,CAAC;KACD,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;CAuBvB,CAAC,CAAC;AAEH,SAAS;AACT,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAE,aAAa;AAC7C,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,uBAAuB,CAAC,OAAO,CAAC,CAAC;AAEjC,SAAS;AACT,uBAAuB,CAAC,OAAO,CAAC,CAAC;AACjC,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,wBAAwB,CAAC,OAAO,CAAC,CAAC;AAClC,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export interface BFLSubmitParams {
|
|
2
|
+
prompt: string;
|
|
3
|
+
input_image?: string;
|
|
4
|
+
input_image_2?: string;
|
|
5
|
+
input_image_3?: string;
|
|
6
|
+
input_image_4?: string;
|
|
7
|
+
input_image_5?: string;
|
|
8
|
+
input_image_6?: string;
|
|
9
|
+
input_image_7?: string;
|
|
10
|
+
input_image_8?: string;
|
|
11
|
+
width?: number;
|
|
12
|
+
height?: number;
|
|
13
|
+
seed?: number;
|
|
14
|
+
safety_tolerance?: number;
|
|
15
|
+
output_format?: 'jpeg' | 'png';
|
|
16
|
+
}
|
|
17
|
+
export interface BFLSubmitResponse {
|
|
18
|
+
id: string;
|
|
19
|
+
polling_url: string;
|
|
20
|
+
status?: string;
|
|
21
|
+
cost?: number;
|
|
22
|
+
input_mp?: number;
|
|
23
|
+
output_mp?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface BFLPollResponse {
|
|
26
|
+
status: 'Pending' | 'Ready' | 'Error' | 'Request Moderated' | 'Content Moderated' | 'Task not found';
|
|
27
|
+
result?: {
|
|
28
|
+
sample?: string;
|
|
29
|
+
prompt?: string;
|
|
30
|
+
seed?: number;
|
|
31
|
+
start_time?: number;
|
|
32
|
+
end_time?: number;
|
|
33
|
+
duration?: number;
|
|
34
|
+
};
|
|
35
|
+
progress?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface PollOptions {
|
|
38
|
+
interval?: number;
|
|
39
|
+
timeout?: number;
|
|
40
|
+
onProgress?: (status: string, progress?: number) => void;
|
|
41
|
+
}
|
|
42
|
+
export declare class BFLClient {
|
|
43
|
+
private client;
|
|
44
|
+
constructor(apiKey: string);
|
|
45
|
+
/**
|
|
46
|
+
* 提交图像生成/编辑任务 (FLUX.2 Pro)
|
|
47
|
+
*/
|
|
48
|
+
submit(params: BFLSubmitParams): Promise<BFLSubmitResponse>;
|
|
49
|
+
/**
|
|
50
|
+
* 获取任务结果
|
|
51
|
+
*/
|
|
52
|
+
getResult(taskId: string): Promise<BFLPollResponse>;
|
|
53
|
+
/**
|
|
54
|
+
* 轮询等待结果
|
|
55
|
+
*/
|
|
56
|
+
poll(taskId: string, options?: PollOptions): Promise<BFLPollResponse>;
|
|
57
|
+
/**
|
|
58
|
+
* 将本地图像转换为 base64 data URL
|
|
59
|
+
*/
|
|
60
|
+
imageToBase64(filePath: string): Promise<string>;
|
|
61
|
+
/**
|
|
62
|
+
* 下载图像到本地
|
|
63
|
+
*/
|
|
64
|
+
downloadImage(url: string, outputDir: string, filename?: string): Promise<string>;
|
|
65
|
+
private sleep;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=bfl-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bfl-api.d.ts","sourceRoot":"","sources":["../../src/services/bfl-api.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,gBAAgB,CAAC;IACrG,MAAM,CAAC,EAAE;QACP,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1D;AAED,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,MAAM;IAW1B;;OAEG;IACG,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAKjE;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAOzD;;OAEG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,eAAe,CAAC;IA4C/E;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAStD;;OAEG;IACG,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBvF,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import axios from 'axios';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
export class BFLClient {
|
|
5
|
+
client;
|
|
6
|
+
constructor(apiKey) {
|
|
7
|
+
this.client = axios.create({
|
|
8
|
+
baseURL: 'https://api.bfl.ml/v1',
|
|
9
|
+
headers: {
|
|
10
|
+
'X-Key': apiKey,
|
|
11
|
+
'Content-Type': 'application/json',
|
|
12
|
+
},
|
|
13
|
+
timeout: 30000,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 提交图像生成/编辑任务 (FLUX.2 Pro)
|
|
18
|
+
*/
|
|
19
|
+
async submit(params) {
|
|
20
|
+
const response = await this.client.post('/flux-2-pro', params);
|
|
21
|
+
return response.data;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 获取任务结果
|
|
25
|
+
*/
|
|
26
|
+
async getResult(taskId) {
|
|
27
|
+
const response = await this.client.get('/get_result', {
|
|
28
|
+
params: { id: taskId },
|
|
29
|
+
});
|
|
30
|
+
return response.data;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 轮询等待结果
|
|
34
|
+
*/
|
|
35
|
+
async poll(taskId, options = {}) {
|
|
36
|
+
const { interval = 1000, timeout = 300000, // 5 分钟
|
|
37
|
+
onProgress, } = options;
|
|
38
|
+
const startTime = Date.now();
|
|
39
|
+
while (true) {
|
|
40
|
+
// 检查超时
|
|
41
|
+
if (Date.now() - startTime > timeout) {
|
|
42
|
+
throw new Error('BFL polling timeout exceeded');
|
|
43
|
+
}
|
|
44
|
+
// 获取状态
|
|
45
|
+
const result = await this.getResult(taskId);
|
|
46
|
+
// 通知进度
|
|
47
|
+
onProgress?.(result.status, result.progress);
|
|
48
|
+
// 完成
|
|
49
|
+
if (result.status === 'Ready') {
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
// 失败
|
|
53
|
+
if (result.status === 'Error') {
|
|
54
|
+
throw new Error('BFL generation failed');
|
|
55
|
+
}
|
|
56
|
+
if (result.status === 'Request Moderated' || result.status === 'Content Moderated') {
|
|
57
|
+
throw new Error(`BFL content moderation: ${result.status}`);
|
|
58
|
+
}
|
|
59
|
+
if (result.status === 'Task not found') {
|
|
60
|
+
throw new Error('BFL task not found');
|
|
61
|
+
}
|
|
62
|
+
// 等待后继续轮询
|
|
63
|
+
await this.sleep(interval);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* 将本地图像转换为 base64 data URL
|
|
68
|
+
*/
|
|
69
|
+
async imageToBase64(filePath) {
|
|
70
|
+
const absolutePath = path.resolve(filePath);
|
|
71
|
+
const buffer = await fs.readFile(absolutePath);
|
|
72
|
+
const base64 = buffer.toString('base64');
|
|
73
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
74
|
+
const mimeType = ext === '.png' ? 'image/png' : 'image/jpeg';
|
|
75
|
+
return `data:${mimeType};base64,${base64}`;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* 下载图像到本地
|
|
79
|
+
*/
|
|
80
|
+
async downloadImage(url, outputDir, filename) {
|
|
81
|
+
// 确保输出目录存在
|
|
82
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
83
|
+
// 下载图像
|
|
84
|
+
const response = await axios.get(url, {
|
|
85
|
+
responseType: 'arraybuffer',
|
|
86
|
+
timeout: 120000, // 2 分钟
|
|
87
|
+
});
|
|
88
|
+
// 确定文件名
|
|
89
|
+
const finalFilename = filename || `bfl_${Date.now()}.png`;
|
|
90
|
+
const outputPath = path.join(outputDir, finalFilename);
|
|
91
|
+
// 写入文件
|
|
92
|
+
await fs.writeFile(outputPath, response.data);
|
|
93
|
+
return outputPath;
|
|
94
|
+
}
|
|
95
|
+
sleep(ms) {
|
|
96
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=bfl-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bfl-api.js","sourceRoot":"","sources":["../../src/services/bfl-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import Conf from 'conf';
|
|
2
|
+
export interface BFLConfig {
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
safetyTolerance: number;
|
|
5
|
+
outputFormat: 'jpeg' | 'png';
|
|
6
|
+
}
|
|
2
7
|
export interface ComfyConfig {
|
|
3
8
|
server: string;
|
|
4
9
|
timeout: number;
|
|
5
10
|
autoConnect: boolean;
|
|
6
11
|
outputDir: string;
|
|
12
|
+
bfl: BFLConfig;
|
|
13
|
+
preferBackend: 'auto' | 'bfl' | 'comfyui';
|
|
7
14
|
}
|
|
8
15
|
export declare const config: Conf<ComfyConfig>;
|
|
9
16
|
export declare function getConfig(): ComfyConfig;
|
|
10
|
-
export declare function setConfig(key:
|
|
17
|
+
export declare function setConfig(key: string, value: any): void;
|
|
18
|
+
export declare function getConfigValue(key: string): any;
|
|
19
|
+
export declare function deleteConfig(key: string): void;
|
|
11
20
|
export declare function resetConfig(): void;
|
|
21
|
+
export declare function isValidConfigKey(key: string): boolean;
|
|
12
22
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,KAAK,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,SAAS,CAAC;IACf,aAAa,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;CAC3C;AAcD,eAAO,MAAM,MAAM,mBAGjB,CAAC;AAEH,wBAAgB,SAAS,IAAI,WAAW,CAEvC;AAGD,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,IAAI,CAEvD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAE/C;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE9C;AAED,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAGD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAYrD"}
|
package/dist/services/config.js
CHANGED
|
@@ -4,6 +4,11 @@ const defaultConfig = {
|
|
|
4
4
|
timeout: 30000,
|
|
5
5
|
autoConnect: true,
|
|
6
6
|
outputDir: './comfy-output',
|
|
7
|
+
bfl: {
|
|
8
|
+
safetyTolerance: 2,
|
|
9
|
+
outputFormat: 'png',
|
|
10
|
+
},
|
|
11
|
+
preferBackend: 'auto',
|
|
7
12
|
};
|
|
8
13
|
export const config = new Conf({
|
|
9
14
|
projectName: 'comfy-cli',
|
|
@@ -12,10 +17,31 @@ export const config = new Conf({
|
|
|
12
17
|
export function getConfig() {
|
|
13
18
|
return config.store;
|
|
14
19
|
}
|
|
20
|
+
// 支持嵌套键,如 'bfl.apiKey'
|
|
15
21
|
export function setConfig(key, value) {
|
|
16
22
|
config.set(key, value);
|
|
17
23
|
}
|
|
24
|
+
export function getConfigValue(key) {
|
|
25
|
+
return config.get(key);
|
|
26
|
+
}
|
|
27
|
+
export function deleteConfig(key) {
|
|
28
|
+
config.delete(key);
|
|
29
|
+
}
|
|
18
30
|
export function resetConfig() {
|
|
19
31
|
config.clear();
|
|
20
32
|
}
|
|
33
|
+
// 验证配置键是否有效
|
|
34
|
+
export function isValidConfigKey(key) {
|
|
35
|
+
const validKeys = [
|
|
36
|
+
'server',
|
|
37
|
+
'timeout',
|
|
38
|
+
'autoConnect',
|
|
39
|
+
'outputDir',
|
|
40
|
+
'bfl.apiKey',
|
|
41
|
+
'bfl.safetyTolerance',
|
|
42
|
+
'bfl.outputFormat',
|
|
43
|
+
'preferBackend',
|
|
44
|
+
];
|
|
45
|
+
return validKeys.includes(key);
|
|
46
|
+
}
|
|
21
47
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/services/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAiBxB,MAAM,aAAa,GAAgB;IACjC,MAAM,EAAE,6BAA6B;IACrC,OAAO,EAAE,KAAK;IACd,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,gBAAgB;IAC3B,GAAG,EAAE;QACH,eAAe,EAAE,CAAC;QAClB,YAAY,EAAE,KAAK;KACpB;IACD,aAAa,EAAE,MAAM;CACtB,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,IAAI,CAAc;IAC1C,WAAW,EAAE,WAAW;IACxB,QAAQ,EAAE,aAAa;CACxB,CAAC,CAAC;AAEH,MAAM,UAAU,SAAS;IACvB,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB,CAAC;AAED,uBAAuB;AACvB,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,KAAU;IAC/C,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,CAAC,MAAM,CAAC,GAAwB,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC;AAED,YAAY;AACZ,MAAM,UAAU,gBAAgB,CAAC,GAAW;IAC1C,MAAM,SAAS,GAAG;QAChB,QAAQ;QACR,SAAS;QACT,aAAa;QACb,WAAW;QACX,YAAY;QACZ,qBAAqB;QACrB,kBAAkB;QAClB,eAAe;KAChB,CAAC;IACF,OAAO,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AACjC,CAAC"}
|