sintetica-cli 0.3.0 → 0.4.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/dist/commands/generate.js +75 -33
- package/package.json +1 -1
|
@@ -84,47 +84,89 @@ exports.generateCommand
|
|
|
84
84
|
.option('--product <id>', 'Product ID')
|
|
85
85
|
.option('--style <style>', 'Style preset', 'minimal')
|
|
86
86
|
.option('--format <format>', 'Image format', 'instagram_square')
|
|
87
|
-
.option('--count <n>', 'Number of
|
|
88
|
-
.option('--prompt <text>', 'Custom creative direction
|
|
89
|
-
.option('--
|
|
90
|
-
.option('--brand-
|
|
91
|
-
.option('--
|
|
92
|
-
.option('--
|
|
87
|
+
.option('--count <n>', 'Number of images per job', '1')
|
|
88
|
+
.option('--prompt <text>', 'Custom creative direction')
|
|
89
|
+
.option('--shots <json>', 'Multiple shots with different prompts (JSON array of strings)')
|
|
90
|
+
.option('--brand-colors <colors>', 'Brand colors, comma-separated')
|
|
91
|
+
.option('--brand-voice <voice>', 'Brand voice')
|
|
92
|
+
.option('--target-audience <audience>', 'Target audience')
|
|
93
|
+
.option('--background <bg>', 'Background style')
|
|
93
94
|
.option('--keywords <words>', 'Brand keywords, comma-separated')
|
|
94
95
|
.option('--wait', 'Wait for completion')
|
|
95
96
|
.action(async (opts) => {
|
|
96
|
-
if (opts.product) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
97
|
+
if (!opts.product) {
|
|
98
|
+
exports.generateCommand.help();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const baseBody = {
|
|
103
|
+
productId: opts.product,
|
|
104
|
+
style: opts.style,
|
|
105
|
+
format: opts.format,
|
|
106
|
+
brandColors: opts.brandColors?.split(',').map(c => c.trim()),
|
|
107
|
+
brandVoice: opts.brandVoice,
|
|
108
|
+
targetAudience: opts.targetAudience,
|
|
109
|
+
background: opts.background,
|
|
110
|
+
keywords: opts.keywords?.split(',').map(k => k.trim()),
|
|
111
|
+
};
|
|
112
|
+
// Multi-shot mode: separate jobs with different prompts
|
|
113
|
+
if (opts.shots) {
|
|
114
|
+
let shotPrompts;
|
|
115
|
+
try {
|
|
116
|
+
shotPrompts = JSON.parse(opts.shots);
|
|
117
|
+
if (!Array.isArray(shotPrompts))
|
|
118
|
+
throw new Error('not an array');
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
console.error(JSON.stringify({ error: '--shots must be a JSON array of strings, e.g. \'["prompt 1","prompt 2"]\'' }));
|
|
122
|
+
process.exit(1);
|
|
114
123
|
return;
|
|
115
124
|
}
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
const allAssets = [];
|
|
126
|
+
const jobs = [];
|
|
127
|
+
for (let i = 0; i < shotPrompts.length; i++) {
|
|
128
|
+
const shotPrompt = shotPrompts[i];
|
|
129
|
+
process.stderr.write(` Shot ${i + 1}/${shotPrompts.length}: submitting...\n`);
|
|
130
|
+
const result = await (0, api_js_1.api)('/api/cli/generate', {
|
|
131
|
+
body: { ...baseBody, count: 1, prompt: shotPrompt },
|
|
132
|
+
});
|
|
133
|
+
jobs.push({ jobId: result.jobId, prompt: shotPrompt });
|
|
134
|
+
process.stderr.write(` Shot ${i + 1}: job ${result.jobId} (${result.creditsCost} credits)\n`);
|
|
135
|
+
}
|
|
136
|
+
if (opts.wait) {
|
|
137
|
+
for (let i = 0; i < jobs.length; i++) {
|
|
138
|
+
process.stderr.write(` Waiting for shot ${i + 1}/${jobs.length}...`);
|
|
139
|
+
const status = await pollUntilDone(jobs[i].jobId);
|
|
140
|
+
process.stderr.write('\n');
|
|
141
|
+
allAssets.push(...status.assets);
|
|
142
|
+
}
|
|
143
|
+
console.log(JSON.stringify({
|
|
144
|
+
shots: jobs.length,
|
|
145
|
+
assets: allAssets,
|
|
146
|
+
jobIds: jobs.map(j => j.jobId),
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
console.log(JSON.stringify({ jobs }));
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
120
153
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
154
|
+
// Single shot mode
|
|
155
|
+
const result = await (0, api_js_1.api)('/api/cli/generate', {
|
|
156
|
+
body: { ...baseBody, count: parseInt(opts.count), prompt: opts.prompt },
|
|
157
|
+
});
|
|
158
|
+
if (!opts.wait) {
|
|
159
|
+
console.log(JSON.stringify(result));
|
|
160
|
+
return;
|
|
124
161
|
}
|
|
162
|
+
process.stderr.write(` Job ${result.jobId} started (${result.creditsCost} credits)\n`);
|
|
163
|
+
const finalStatus = await pollUntilDone(result.jobId);
|
|
164
|
+
process.stderr.write('\n');
|
|
165
|
+
console.log(JSON.stringify(finalStatus));
|
|
125
166
|
}
|
|
126
|
-
|
|
127
|
-
|
|
167
|
+
catch (err) {
|
|
168
|
+
console.error(JSON.stringify({ error: err instanceof Error ? err.message : 'Generation failed' }));
|
|
169
|
+
process.exit(1);
|
|
128
170
|
}
|
|
129
171
|
});
|
|
130
172
|
exports.generateCommand.addCommand(statusCommand);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sintetica-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Sintetica CLI — AI product photography from your terminal. Generate professional product photos with one command.",
|
|
5
5
|
"keywords": ["sintetica", "ai", "product-photography", "ecommerce", "shopify", "cli", "claude-code"],
|
|
6
6
|
"author": "Sintetica <hello@sintetica.ro>",
|