gobananas-cli 1.0.1
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/bin/gobananas-mcp.js +10 -0
- package/bin/gobananas.js +8 -0
- package/dist/commands/account.d.ts +8 -0
- package/dist/commands/account.d.ts.map +1 -0
- package/dist/commands/account.js +200 -0
- package/dist/commands/account.js.map +1 -0
- package/dist/commands/character.d.ts +8 -0
- package/dist/commands/character.d.ts.map +1 -0
- package/dist/commands/character.js +493 -0
- package/dist/commands/character.js.map +1 -0
- package/dist/commands/config.d.ts +8 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +232 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/edit.d.ts +19 -0
- package/dist/commands/edit.d.ts.map +1 -0
- package/dist/commands/edit.js +279 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/generate.d.ts +8 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +177 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/image.d.ts +8 -0
- package/dist/commands/image.d.ts.map +1 -0
- package/dist/commands/image.js +212 -0
- package/dist/commands/image.js.map +1 -0
- package/dist/commands/index.d.ts +19 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +19 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/mcp-help.d.ts +8 -0
- package/dist/commands/mcp-help.d.ts.map +1 -0
- package/dist/commands/mcp-help.js +264 -0
- package/dist/commands/mcp-help.js.map +1 -0
- package/dist/commands/mcp.d.ts +9 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +25 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/product.d.ts +8 -0
- package/dist/commands/product.d.ts.map +1 -0
- package/dist/commands/product.js +316 -0
- package/dist/commands/product.js.map +1 -0
- package/dist/commands/scene.d.ts +8 -0
- package/dist/commands/scene.d.ts.map +1 -0
- package/dist/commands/scene.js +448 -0
- package/dist/commands/scene.js.map +1 -0
- package/dist/commands/search.d.ts +8 -0
- package/dist/commands/search.d.ts.map +1 -0
- package/dist/commands/search.js +123 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/session.d.ts +8 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +167 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/style.d.ts +8 -0
- package/dist/commands/style.d.ts.map +1 -0
- package/dist/commands/style.js +297 -0
- package/dist/commands/style.js.map +1 -0
- package/dist/commands/usage.d.ts +8 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +144 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/config/config.d.ts +65 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +156 -0
- package/dist/config/config.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +130 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/stdio-proxy.d.ts +8 -0
- package/dist/mcp/stdio-proxy.d.ts.map +1 -0
- package/dist/mcp/stdio-proxy.js +297 -0
- package/dist/mcp/stdio-proxy.js.map +1 -0
- package/dist/mcp-stdio.d.ts +3 -0
- package/dist/mcp-stdio.d.ts.map +1 -0
- package/dist/mcp-stdio.js +8 -0
- package/dist/mcp-stdio.js.map +1 -0
- package/dist/transport/index.d.ts +29 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +72 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/mcp-client.d.ts +342 -0
- package/dist/transport/mcp-client.d.ts.map +1 -0
- package/dist/transport/mcp-client.js +478 -0
- package/dist/transport/mcp-client.js.map +1 -0
- package/dist/transport/rest-client.d.ts +297 -0
- package/dist/transport/rest-client.d.ts.map +1 -0
- package/dist/transport/rest-client.js +461 -0
- package/dist/transport/rest-client.js.map +1 -0
- package/dist/types/responses.d.ts +230 -0
- package/dist/types/responses.d.ts.map +1 -0
- package/dist/types/responses.js +46 -0
- package/dist/types/responses.js.map +1 -0
- package/dist/utils/file-handler.d.ts +51 -0
- package/dist/utils/file-handler.d.ts.map +1 -0
- package/dist/utils/file-handler.js +189 -0
- package/dist/utils/file-handler.js.map +1 -0
- package/dist/utils/output.d.ts +111 -0
- package/dist/utils/output.d.ts.map +1 -0
- package/dist/utils/output.js +240 -0
- package/dist/utils/output.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Help Command
|
|
3
|
+
*
|
|
4
|
+
* Get help from the MCP server about available tools and workflows.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { createTransport, getTransportName } from '../transport/index.js';
|
|
8
|
+
import * as output from '../utils/output.js';
|
|
9
|
+
import { getSecurityWarning } from '../config/config.js';
|
|
10
|
+
export function createMcpHelpCommand() {
|
|
11
|
+
const cmd = new Command('mcp-help')
|
|
12
|
+
.description('Get help from the Go Bananas MCP server')
|
|
13
|
+
.argument('[tool]', 'Get help for a specific tool (e.g., generate_image)')
|
|
14
|
+
.option('-c, --category <name>', 'Filter by category (generation, editing, characters, products, styles, analytics)')
|
|
15
|
+
.option('-w, --workflow <name>', 'Get workflow guidance (consistent_characters, conversational_editing, product_marketing, style_branding)')
|
|
16
|
+
.option('--json', 'Output raw JSON response')
|
|
17
|
+
.action(async (tool, options) => {
|
|
18
|
+
const securityWarning = getSecurityWarning();
|
|
19
|
+
if (securityWarning) {
|
|
20
|
+
output.warning(securityWarning);
|
|
21
|
+
}
|
|
22
|
+
const spin = output.spinner('Fetching help...');
|
|
23
|
+
try {
|
|
24
|
+
const transport = await createTransport();
|
|
25
|
+
spin.text = `Connected via ${getTransportName(transport.type)}. Loading help...`;
|
|
26
|
+
const params = {};
|
|
27
|
+
if (tool) {
|
|
28
|
+
params.toolName = tool;
|
|
29
|
+
}
|
|
30
|
+
if (options.category) {
|
|
31
|
+
params.category = options.category;
|
|
32
|
+
}
|
|
33
|
+
if (options.workflow) {
|
|
34
|
+
params.workflow = options.workflow;
|
|
35
|
+
}
|
|
36
|
+
let result;
|
|
37
|
+
if (transport.type === 'mcp' && transport.mcp) {
|
|
38
|
+
const mcpResult = await transport.mcp.getHelp(params);
|
|
39
|
+
const text = mcpResult.content?.[0]?.text || '';
|
|
40
|
+
try {
|
|
41
|
+
result = JSON.parse(text);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// If not JSON, display as markdown/text
|
|
45
|
+
spin.stop();
|
|
46
|
+
if (options.json) {
|
|
47
|
+
output.json({ text });
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
console.log(text);
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (transport.rest) {
|
|
56
|
+
// REST doesn't have a help endpoint, show local help
|
|
57
|
+
spin.stop();
|
|
58
|
+
showLocalHelp(tool, options.category, options.workflow);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
throw new Error('No transport available');
|
|
63
|
+
}
|
|
64
|
+
spin.stop();
|
|
65
|
+
if (options.json) {
|
|
66
|
+
output.json(result);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
displayHelpResult(result);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
spin.stop();
|
|
74
|
+
output.error(err instanceof Error ? err.message : 'Failed to get help');
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
return cmd;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Display help result in formatted output
|
|
82
|
+
*/
|
|
83
|
+
function displayHelpResult(data) {
|
|
84
|
+
// Overview
|
|
85
|
+
if (data.overview) {
|
|
86
|
+
console.log(data.overview);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Tool-specific help
|
|
90
|
+
const tool = data.tool;
|
|
91
|
+
if (tool) {
|
|
92
|
+
output.header(`Tool: ${tool.name}`);
|
|
93
|
+
console.log();
|
|
94
|
+
console.log(tool.description);
|
|
95
|
+
const params = tool.parameters;
|
|
96
|
+
if (params && params.length > 0) {
|
|
97
|
+
output.newline();
|
|
98
|
+
output.header('Parameters');
|
|
99
|
+
for (const param of params) {
|
|
100
|
+
const required = param.required ? ' (required)' : '';
|
|
101
|
+
console.log(` • ${param.name}${required}: ${param.type}`);
|
|
102
|
+
if (param.description) {
|
|
103
|
+
console.log(` ${param.description}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
const examples = tool.examples;
|
|
108
|
+
if (examples && examples.length > 0) {
|
|
109
|
+
output.newline();
|
|
110
|
+
output.header('Examples');
|
|
111
|
+
for (const example of examples) {
|
|
112
|
+
console.log(` ${example}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
const related = tool.relatedTools;
|
|
116
|
+
if (related && related.length > 0) {
|
|
117
|
+
output.newline();
|
|
118
|
+
output.info(`Related tools: ${related.join(', ')}`);
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
// Category help
|
|
123
|
+
const category = data.category;
|
|
124
|
+
if (category) {
|
|
125
|
+
output.header(`Category: ${category.name}`);
|
|
126
|
+
const tools = category.tools;
|
|
127
|
+
if (tools) {
|
|
128
|
+
output.newline();
|
|
129
|
+
for (const t of tools) {
|
|
130
|
+
console.log(` • ${t.name}: ${t.description}`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
// Workflow help
|
|
136
|
+
const workflow = data.workflow;
|
|
137
|
+
if (workflow) {
|
|
138
|
+
output.header(`Workflow: ${workflow.name}`);
|
|
139
|
+
console.log();
|
|
140
|
+
console.log(workflow.description);
|
|
141
|
+
const steps = workflow.steps;
|
|
142
|
+
if (steps && steps.length > 0) {
|
|
143
|
+
output.newline();
|
|
144
|
+
output.header('Steps');
|
|
145
|
+
for (let i = 0; i < steps.length; i++) {
|
|
146
|
+
console.log(` ${i + 1}. ${steps[i]}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
const examples = workflow.examples;
|
|
150
|
+
if (examples && examples.length > 0) {
|
|
151
|
+
output.newline();
|
|
152
|
+
output.header('Examples');
|
|
153
|
+
for (const example of examples) {
|
|
154
|
+
console.log(` ${example}`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Fallback: just display raw data
|
|
160
|
+
output.json(data);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Show local help when REST doesn't support help endpoint
|
|
164
|
+
*/
|
|
165
|
+
function showLocalHelp(tool, category, workflow) {
|
|
166
|
+
if (tool) {
|
|
167
|
+
output.info(`Help for tool "${tool}" is only available via MCP transport.`);
|
|
168
|
+
output.tip('Use "gb config transport mcp" to switch to MCP mode.');
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (category) {
|
|
172
|
+
const categories = {
|
|
173
|
+
generation: ['generate_image', 'generate_with_character', 'generate_with_multiple_characters', 'generate_with_product'],
|
|
174
|
+
editing: ['edit_image', 'edit_uploaded_image', 'continue_editing', 'upload_image_for_editing'],
|
|
175
|
+
characters: ['create_character', 'update_character', 'delete_character', 'list_characters', 'get_character'],
|
|
176
|
+
products: ['create_product_reference', 'delete_product_reference', 'list_product_references', 'get_product_reference'],
|
|
177
|
+
styles: ['create_style_preset', 'update_style_preset', 'delete_style_preset', 'list_style_presets'],
|
|
178
|
+
analytics: ['get_usage_stats', 'get_account_summary', 'get_session_history', 'search_images', 'get_image_info'],
|
|
179
|
+
};
|
|
180
|
+
const tools = categories[category];
|
|
181
|
+
if (tools) {
|
|
182
|
+
output.header(`Category: ${category}`);
|
|
183
|
+
output.newline();
|
|
184
|
+
for (const t of tools) {
|
|
185
|
+
console.log(` • ${t}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
output.error(`Unknown category: ${category}`);
|
|
190
|
+
output.info('Available categories: generation, editing, characters, products, styles, analytics');
|
|
191
|
+
}
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (workflow) {
|
|
195
|
+
const workflows = {
|
|
196
|
+
consistent_characters: {
|
|
197
|
+
description: 'Create consistent characters across multiple scenes',
|
|
198
|
+
steps: [
|
|
199
|
+
'1. Generate initial character image: gb generate "your character description"',
|
|
200
|
+
'2. Save the character: gb char create "CharName" --prompt "description" --refs <image-id>',
|
|
201
|
+
'3. Generate scenes: gb char use "CharName" "scene description"',
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
conversational_editing: {
|
|
205
|
+
description: 'Iteratively edit images in a conversation',
|
|
206
|
+
steps: [
|
|
207
|
+
'1. Generate initial image: gb generate "your prompt"',
|
|
208
|
+
'2. Continue editing: gb continue "add more clouds"',
|
|
209
|
+
'3. Keep refining: gb continue "make it brighter"',
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
product_marketing: {
|
|
213
|
+
description: 'Generate marketing images with product references',
|
|
214
|
+
steps: [
|
|
215
|
+
'1. Save product: gb prod create "ProductName" --url "https://..."',
|
|
216
|
+
'2. Generate scenes: gb prod use "ProductName" "on a wooden desk"',
|
|
217
|
+
],
|
|
218
|
+
},
|
|
219
|
+
style_branding: {
|
|
220
|
+
description: 'Maintain consistent style across generations',
|
|
221
|
+
steps: [
|
|
222
|
+
'1. Create style preset: gb style create "BrandStyle" --prompt "style description"',
|
|
223
|
+
'2. Use in generation: gb generate "subject" --style-preset "BrandStyle"',
|
|
224
|
+
],
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
const wf = workflows[workflow];
|
|
228
|
+
if (wf) {
|
|
229
|
+
output.header(`Workflow: ${workflow}`);
|
|
230
|
+
console.log();
|
|
231
|
+
console.log(wf.description);
|
|
232
|
+
output.newline();
|
|
233
|
+
for (const step of wf.steps) {
|
|
234
|
+
console.log(` ${step}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
output.error(`Unknown workflow: ${workflow}`);
|
|
239
|
+
output.info('Available workflows: consistent_characters, conversational_editing, product_marketing, style_branding');
|
|
240
|
+
}
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
// Default overview
|
|
244
|
+
output.header('Go Bananas CLI Help');
|
|
245
|
+
console.log();
|
|
246
|
+
console.log('Use mcp-help to get detailed documentation from the server.');
|
|
247
|
+
output.newline();
|
|
248
|
+
output.header('Categories');
|
|
249
|
+
console.log(' • generation - Image generation tools');
|
|
250
|
+
console.log(' • editing - Image editing tools');
|
|
251
|
+
console.log(' • characters - Character reference management');
|
|
252
|
+
console.log(' • products - Product reference management');
|
|
253
|
+
console.log(' • styles - Style preset management');
|
|
254
|
+
console.log(' • analytics - Usage stats and account info');
|
|
255
|
+
output.newline();
|
|
256
|
+
output.header('Workflows');
|
|
257
|
+
console.log(' • consistent_characters - Multi-scene character consistency');
|
|
258
|
+
console.log(' • conversational_editing - Iterative image refinement');
|
|
259
|
+
console.log(' • product_marketing - Product-based marketing images');
|
|
260
|
+
console.log(' • style_branding - Consistent style across images');
|
|
261
|
+
output.newline();
|
|
262
|
+
output.tip('Run "gb mcp-help <tool-name>" for specific tool documentation.');
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=mcp-help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-help.js","sourceRoot":"","sources":["../../src/commands/mcp-help.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Proxy Command
|
|
3
|
+
*
|
|
4
|
+
* Runs a stdio MCP server that proxies requests to the remote Go Bananas MCP endpoint.
|
|
5
|
+
* Intended for MCP clients that require stdio (Claude Desktop, Cursor, Codex, etc).
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
export declare function createMcpProxyCommand(): Command;
|
|
9
|
+
//# sourceMappingURL=mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,wBAAgB,qBAAqB,IAAI,OAAO,CAqB/C"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Proxy Command
|
|
3
|
+
*
|
|
4
|
+
* Runs a stdio MCP server that proxies requests to the remote Go Bananas MCP endpoint.
|
|
5
|
+
* Intended for MCP clients that require stdio (Claude Desktop, Cursor, Codex, etc).
|
|
6
|
+
*/
|
|
7
|
+
import { Command } from 'commander';
|
|
8
|
+
import { runGoBananasMcpStdioProxy } from '../mcp/stdio-proxy.js';
|
|
9
|
+
export function createMcpProxyCommand() {
|
|
10
|
+
const cmd = new Command('mcp').description('Run the Go Bananas MCP stdio proxy');
|
|
11
|
+
cmd
|
|
12
|
+
.option('--server-url <url>', 'Base URL for Go Bananas server (default: config/serverUrl)')
|
|
13
|
+
.option('--api-key <key>', 'Go Bananas API key (default: GO_BANANAS_API_KEY/MCP_API_KEY/config)')
|
|
14
|
+
.option('--transport <mode>', 'Upstream transport: auto, streamable-http, or sse (default: auto)', 'auto')
|
|
15
|
+
.action(async (options) => {
|
|
16
|
+
const transport = options.transport;
|
|
17
|
+
await runGoBananasMcpStdioProxy({
|
|
18
|
+
serverUrl: options.serverUrl,
|
|
19
|
+
apiKey: options.apiKey,
|
|
20
|
+
transport,
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
return cmd;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,yBAAyB,EAA8B,MAAM,uBAAuB,CAAC;AAE9F,MAAM,UAAU,qBAAqB;IACnC,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,oCAAoC,CAAC,CAAC;IAEjF,GAAG;SACA,MAAM,CAAC,oBAAoB,EAAE,4DAA4D,CAAC;SAC1F,MAAM,CAAC,iBAAiB,EAAE,qEAAqE,CAAC;SAChG,MAAM,CACL,oBAAoB,EACpB,mEAAmE,EACnE,MAAM,CACP;SACA,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,MAAM,SAAS,GAAG,OAAO,CAAC,SAAkC,CAAC;QAC7D,MAAM,yBAAyB,CAAC;YAC9B,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS;SACV,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEL,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product.d.ts","sourceRoot":"","sources":["../../src/commands/product.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,oBAAoB,IAAI,OAAO,CAkT9C"}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Commands
|
|
3
|
+
*
|
|
4
|
+
* Commands for managing and using product references for marketing.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { createTransport } from '../transport/index.js';
|
|
8
|
+
import { downloadImage } from '../utils/file-handler.js';
|
|
9
|
+
import * as output from '../utils/output.js';
|
|
10
|
+
export function createProductCommand() {
|
|
11
|
+
const cmd = new Command('product')
|
|
12
|
+
.alias('prod')
|
|
13
|
+
.description('Manage product references for marketing image generation');
|
|
14
|
+
// List products
|
|
15
|
+
cmd
|
|
16
|
+
.command('list')
|
|
17
|
+
.alias('ls')
|
|
18
|
+
.description('List all saved product references')
|
|
19
|
+
.option('-s, --search <query>', 'Search by name, description, or tags')
|
|
20
|
+
.option('-p, --page <number>', 'Page number', '1')
|
|
21
|
+
.option('--page-size <number>', 'Items per page', '20')
|
|
22
|
+
.option('--json', 'Output raw JSON response')
|
|
23
|
+
.action(async (options) => {
|
|
24
|
+
const spin = output.spinner('Loading products...');
|
|
25
|
+
try {
|
|
26
|
+
const transport = await createTransport();
|
|
27
|
+
let result;
|
|
28
|
+
if (transport.type === 'mcp' && transport.mcp) {
|
|
29
|
+
const mcpResult = await transport.mcp.listProductReferences({
|
|
30
|
+
search: options.search,
|
|
31
|
+
page: parseInt(options.page, 10),
|
|
32
|
+
pageSize: parseInt(options.pageSize, 10),
|
|
33
|
+
});
|
|
34
|
+
result = { raw: mcpResult.content?.[0]?.text };
|
|
35
|
+
}
|
|
36
|
+
else if (transport.rest) {
|
|
37
|
+
const restResult = await transport.rest.listProducts({
|
|
38
|
+
search: options.search,
|
|
39
|
+
page: parseInt(options.page, 10),
|
|
40
|
+
pageSize: parseInt(options.pageSize, 10),
|
|
41
|
+
});
|
|
42
|
+
result = restResult;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
throw new Error('No transport available');
|
|
46
|
+
}
|
|
47
|
+
spin.stop();
|
|
48
|
+
if (options.json) {
|
|
49
|
+
output.json(result);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const r = result;
|
|
53
|
+
if (r.raw) {
|
|
54
|
+
console.log(r.raw);
|
|
55
|
+
}
|
|
56
|
+
else if (r.data && Array.isArray(r.data)) {
|
|
57
|
+
output.header(`Products (${r.data.length})`);
|
|
58
|
+
for (const prod of r.data) {
|
|
59
|
+
output.productInfo(prod);
|
|
60
|
+
}
|
|
61
|
+
if (r.pagination) {
|
|
62
|
+
const p = r.pagination;
|
|
63
|
+
if (p.hasMore) {
|
|
64
|
+
output.newline();
|
|
65
|
+
output.info(`Use --page ${(p.page || 1) + 1} to see more.`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
output.info('No products found. Use "gb prod create" to save one!');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
spin.stop();
|
|
76
|
+
output.error(err instanceof Error ? err.message : 'Failed to list products');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
// Get product details
|
|
81
|
+
cmd
|
|
82
|
+
.command('get <nameOrId>')
|
|
83
|
+
.description('Get details of a specific product')
|
|
84
|
+
.option('--json', 'Output raw JSON response')
|
|
85
|
+
.action(async (nameOrId, options) => {
|
|
86
|
+
const spin = output.spinner('Loading product...');
|
|
87
|
+
try {
|
|
88
|
+
const transport = await createTransport();
|
|
89
|
+
const params = isNaN(parseInt(nameOrId, 10))
|
|
90
|
+
? { productName: nameOrId }
|
|
91
|
+
: { id: parseInt(nameOrId, 10) };
|
|
92
|
+
let result;
|
|
93
|
+
if (transport.type === 'mcp' && transport.mcp) {
|
|
94
|
+
const mcpResult = await transport.mcp.getProductReference(params);
|
|
95
|
+
result = { raw: mcpResult.content?.[0]?.text };
|
|
96
|
+
}
|
|
97
|
+
else if (transport.rest) {
|
|
98
|
+
const restResult = await transport.rest.getProduct(nameOrId);
|
|
99
|
+
result = restResult;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
throw new Error('No transport available');
|
|
103
|
+
}
|
|
104
|
+
spin.stop();
|
|
105
|
+
if (options.json) {
|
|
106
|
+
output.json(result);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
const r = result;
|
|
110
|
+
if (r.raw) {
|
|
111
|
+
console.log(r.raw);
|
|
112
|
+
}
|
|
113
|
+
else if (r.data) {
|
|
114
|
+
const prod = r.data;
|
|
115
|
+
output.header(`Product: ${prod.productName || prod.name}`);
|
|
116
|
+
output.keyValue('ID', prod.id);
|
|
117
|
+
if (prod.productDescription)
|
|
118
|
+
output.keyValue('Description', prod.productDescription);
|
|
119
|
+
output.keyValue('Source URL', prod.productUrl);
|
|
120
|
+
output.keyValue('Times Used', prod.timesUsed);
|
|
121
|
+
if (prod.tags)
|
|
122
|
+
output.keyValue('Tags', prod.tags);
|
|
123
|
+
if (prod.fullUrl)
|
|
124
|
+
output.keyValue('Image URL', prod.fullUrl);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
spin.stop();
|
|
130
|
+
output.error(err instanceof Error ? err.message : 'Failed to get product');
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
// Create product
|
|
135
|
+
cmd
|
|
136
|
+
.command('create <name>')
|
|
137
|
+
.description('Save a product image from a URL')
|
|
138
|
+
.requiredOption('-u, --url <url>', 'URL of the product image')
|
|
139
|
+
.option('-d, --description <text>', 'Product description')
|
|
140
|
+
.option('--tags <tags>', 'Comma-separated tags')
|
|
141
|
+
.option('--json', 'Output raw JSON response')
|
|
142
|
+
.action(async (name, options) => {
|
|
143
|
+
const spin = output.spinner('Saving product reference...');
|
|
144
|
+
try {
|
|
145
|
+
const transport = await createTransport();
|
|
146
|
+
const params = {
|
|
147
|
+
productName: name,
|
|
148
|
+
productUrl: options.url,
|
|
149
|
+
productDescription: options.description,
|
|
150
|
+
tags: options.tags,
|
|
151
|
+
};
|
|
152
|
+
let result;
|
|
153
|
+
if (transport.type === 'mcp' && transport.mcp) {
|
|
154
|
+
const mcpResult = await transport.mcp.createProductReference(params);
|
|
155
|
+
result = { raw: mcpResult.content?.[0]?.text };
|
|
156
|
+
}
|
|
157
|
+
else if (transport.rest) {
|
|
158
|
+
const restResult = await transport.rest.createProduct(params);
|
|
159
|
+
result = restResult;
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
throw new Error('No transport available');
|
|
163
|
+
}
|
|
164
|
+
spin.stop();
|
|
165
|
+
if (options.json) {
|
|
166
|
+
output.json(result);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
const r = result;
|
|
170
|
+
if (r.raw) {
|
|
171
|
+
console.log(r.raw);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
output.success(`Product "${name}" saved successfully!`);
|
|
175
|
+
if (r.data) {
|
|
176
|
+
const prod = r.data;
|
|
177
|
+
output.keyValue('ID', prod.id);
|
|
178
|
+
}
|
|
179
|
+
output.newline();
|
|
180
|
+
output.tip(`Use "gb prod use '${name}' '<scene>'" to generate marketing images`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
spin.stop();
|
|
186
|
+
output.error(err instanceof Error ? err.message : 'Failed to create product');
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
// Delete product
|
|
191
|
+
cmd
|
|
192
|
+
.command('delete <nameOrId>')
|
|
193
|
+
.alias('rm')
|
|
194
|
+
.description('Delete a saved product reference')
|
|
195
|
+
.option('--json', 'Output raw JSON response')
|
|
196
|
+
.action(async (nameOrId, options) => {
|
|
197
|
+
const spin = output.spinner('Deleting product...');
|
|
198
|
+
try {
|
|
199
|
+
const transport = await createTransport();
|
|
200
|
+
const params = isNaN(parseInt(nameOrId, 10))
|
|
201
|
+
? { productName: nameOrId }
|
|
202
|
+
: { id: parseInt(nameOrId, 10) };
|
|
203
|
+
let result;
|
|
204
|
+
if (transport.type === 'mcp' && transport.mcp) {
|
|
205
|
+
const mcpResult = await transport.mcp.deleteProductReference(params);
|
|
206
|
+
result = { raw: mcpResult.content?.[0]?.text };
|
|
207
|
+
}
|
|
208
|
+
else if (transport.rest) {
|
|
209
|
+
await transport.rest.deleteProduct(nameOrId);
|
|
210
|
+
result = { deleted: true };
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
throw new Error('No transport available');
|
|
214
|
+
}
|
|
215
|
+
spin.stop();
|
|
216
|
+
if (options.json) {
|
|
217
|
+
output.json(result);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
const r = result;
|
|
221
|
+
if (r.raw) {
|
|
222
|
+
console.log(r.raw);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
output.success(`Product "${nameOrId}" deleted successfully!`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
spin.stop();
|
|
231
|
+
output.error(err instanceof Error ? err.message : 'Failed to delete product');
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
// Generate with product
|
|
236
|
+
cmd
|
|
237
|
+
.command('use <nameOrId> <scene>')
|
|
238
|
+
.alias('gen')
|
|
239
|
+
.description('Generate a marketing image with a saved product')
|
|
240
|
+
.option('--details <text>', 'Additional scene details')
|
|
241
|
+
.option('-a, --aspect <ratio>', 'Aspect ratio')
|
|
242
|
+
.option('--negative <prompt>', 'Negative prompt')
|
|
243
|
+
.option('-n, --count <number>', 'Number of images (1-4)', '1')
|
|
244
|
+
.option('-d, --download', 'Download the generated image')
|
|
245
|
+
.option('-o, --output <path>', 'Output path for downloaded image')
|
|
246
|
+
.option('--json', 'Output raw JSON response')
|
|
247
|
+
.action(async (nameOrId, scene, options) => {
|
|
248
|
+
const spin = output.spinner('Generating marketing image...');
|
|
249
|
+
try {
|
|
250
|
+
const transport = await createTransport();
|
|
251
|
+
const isId = !isNaN(parseInt(nameOrId, 10));
|
|
252
|
+
const params = {
|
|
253
|
+
...(isId ? { productId: parseInt(nameOrId, 10) } : { productName: nameOrId }),
|
|
254
|
+
scenePrompt: scene,
|
|
255
|
+
additionalDetails: options.details,
|
|
256
|
+
aspectRatio: options.aspect,
|
|
257
|
+
negativePrompt: options.negative,
|
|
258
|
+
numberOfImages: parseInt(options.count, 10),
|
|
259
|
+
};
|
|
260
|
+
let result;
|
|
261
|
+
if (transport.type === 'mcp' && transport.mcp) {
|
|
262
|
+
const mcpResult = await transport.mcp.generateWithProduct(params);
|
|
263
|
+
const text = mcpResult.content?.[0]?.text || '';
|
|
264
|
+
const urlMatch = text.match(/https?:\/\/[^\s)]+/);
|
|
265
|
+
const idMatch = text.match(/ID:\s*(\d+)/);
|
|
266
|
+
result = {
|
|
267
|
+
url: urlMatch?.[0],
|
|
268
|
+
id: idMatch ? parseInt(idMatch[1], 10) : undefined,
|
|
269
|
+
raw: text,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
else if (transport.rest) {
|
|
273
|
+
const restResult = await transport.rest.generateWithProduct(params);
|
|
274
|
+
result = restResult.data;
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
throw new Error('No transport available');
|
|
278
|
+
}
|
|
279
|
+
spin.stop();
|
|
280
|
+
if (options.json) {
|
|
281
|
+
output.json(result);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
const r = result;
|
|
285
|
+
output.success('Marketing image generated!');
|
|
286
|
+
if (r.id)
|
|
287
|
+
output.keyValue('ID', r.id);
|
|
288
|
+
const url = (r.url || r.fullUrl);
|
|
289
|
+
if (url)
|
|
290
|
+
output.keyValue('URL', url);
|
|
291
|
+
if (options.download && url) {
|
|
292
|
+
output.newline();
|
|
293
|
+
const downloadSpin = output.spinner('Downloading image...');
|
|
294
|
+
try {
|
|
295
|
+
const savedPath = await downloadImage(url, options.output);
|
|
296
|
+
downloadSpin.succeed(`Saved to: ${savedPath}`);
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
downloadSpin.fail(`Download failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
if (r.raw && !url) {
|
|
303
|
+
output.newline();
|
|
304
|
+
console.log(r.raw);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
catch (err) {
|
|
309
|
+
spin.stop();
|
|
310
|
+
output.error(err instanceof Error ? err.message : 'Failed to generate with product');
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
return cmd;
|
|
315
|
+
}
|
|
316
|
+
//# sourceMappingURL=product.js.map
|