sintetica-cli 0.3.0 → 0.5.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 +77 -33
- package/package.json +1 -1
|
@@ -84,47 +84,91 @@ 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('--
|
|
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('--model-url <url>', 'URL of a person/model reference image to include in the shot')
|
|
91
|
+
.option('--brand-colors <colors>', 'Brand colors, comma-separated')
|
|
92
|
+
.option('--brand-voice <voice>', 'Brand voice')
|
|
93
|
+
.option('--target-audience <audience>', 'Target audience')
|
|
94
|
+
.option('--background <bg>', 'Background style')
|
|
93
95
|
.option('--keywords <words>', 'Brand keywords, comma-separated')
|
|
94
96
|
.option('--wait', 'Wait for completion')
|
|
95
97
|
.action(async (opts) => {
|
|
96
|
-
if (opts.product) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
98
|
+
if (!opts.product) {
|
|
99
|
+
exports.generateCommand.help();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const baseBody = {
|
|
104
|
+
productId: opts.product,
|
|
105
|
+
style: opts.style,
|
|
106
|
+
format: opts.format,
|
|
107
|
+
modelUrl: opts.modelUrl,
|
|
108
|
+
brandColors: opts.brandColors?.split(',').map(c => c.trim()),
|
|
109
|
+
brandVoice: opts.brandVoice,
|
|
110
|
+
targetAudience: opts.targetAudience,
|
|
111
|
+
background: opts.background,
|
|
112
|
+
keywords: opts.keywords?.split(',').map(k => k.trim()),
|
|
113
|
+
};
|
|
114
|
+
// Multi-shot mode: separate jobs with different prompts
|
|
115
|
+
if (opts.shots) {
|
|
116
|
+
let shotPrompts;
|
|
117
|
+
try {
|
|
118
|
+
shotPrompts = JSON.parse(opts.shots);
|
|
119
|
+
if (!Array.isArray(shotPrompts))
|
|
120
|
+
throw new Error('not an array');
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
console.error(JSON.stringify({ error: '--shots must be a JSON array of strings, e.g. \'["prompt 1","prompt 2"]\'' }));
|
|
124
|
+
process.exit(1);
|
|
114
125
|
return;
|
|
115
126
|
}
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
127
|
+
const allAssets = [];
|
|
128
|
+
const jobs = [];
|
|
129
|
+
for (let i = 0; i < shotPrompts.length; i++) {
|
|
130
|
+
const shotPrompt = shotPrompts[i];
|
|
131
|
+
process.stderr.write(` Shot ${i + 1}/${shotPrompts.length}: submitting...\n`);
|
|
132
|
+
const result = await (0, api_js_1.api)('/api/cli/generate', {
|
|
133
|
+
body: { ...baseBody, count: 1, prompt: shotPrompt },
|
|
134
|
+
});
|
|
135
|
+
jobs.push({ jobId: result.jobId, prompt: shotPrompt });
|
|
136
|
+
process.stderr.write(` Shot ${i + 1}: job ${result.jobId} (${result.creditsCost} credits)\n`);
|
|
137
|
+
}
|
|
138
|
+
if (opts.wait) {
|
|
139
|
+
for (let i = 0; i < jobs.length; i++) {
|
|
140
|
+
process.stderr.write(` Waiting for shot ${i + 1}/${jobs.length}...`);
|
|
141
|
+
const status = await pollUntilDone(jobs[i].jobId);
|
|
142
|
+
process.stderr.write('\n');
|
|
143
|
+
allAssets.push(...status.assets);
|
|
144
|
+
}
|
|
145
|
+
console.log(JSON.stringify({
|
|
146
|
+
shots: jobs.length,
|
|
147
|
+
assets: allAssets,
|
|
148
|
+
jobIds: jobs.map(j => j.jobId),
|
|
149
|
+
}));
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
console.log(JSON.stringify({ jobs }));
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
120
155
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
156
|
+
// Single shot mode
|
|
157
|
+
const result = await (0, api_js_1.api)('/api/cli/generate', {
|
|
158
|
+
body: { ...baseBody, count: parseInt(opts.count), prompt: opts.prompt },
|
|
159
|
+
});
|
|
160
|
+
if (!opts.wait) {
|
|
161
|
+
console.log(JSON.stringify(result));
|
|
162
|
+
return;
|
|
124
163
|
}
|
|
164
|
+
process.stderr.write(` Job ${result.jobId} started (${result.creditsCost} credits)\n`);
|
|
165
|
+
const finalStatus = await pollUntilDone(result.jobId);
|
|
166
|
+
process.stderr.write('\n');
|
|
167
|
+
console.log(JSON.stringify(finalStatus));
|
|
125
168
|
}
|
|
126
|
-
|
|
127
|
-
|
|
169
|
+
catch (err) {
|
|
170
|
+
console.error(JSON.stringify({ error: err instanceof Error ? err.message : 'Generation failed' }));
|
|
171
|
+
process.exit(1);
|
|
128
172
|
}
|
|
129
173
|
});
|
|
130
174
|
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.5.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>",
|