veogent 1.0.25 → 1.1.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/index.js +183 -1
- package/package.json +1 -1
- package/skills/SKILL.md +734 -185
package/index.js
CHANGED
|
@@ -744,7 +744,11 @@ program
|
|
|
744
744
|
}
|
|
745
745
|
|
|
746
746
|
const data = await api.post('/app/request', payload);
|
|
747
|
-
|
|
747
|
+
let requestResult = unwrapData(data);
|
|
748
|
+
// Ensure requestResult is an object (backend may return boolean/primitive)
|
|
749
|
+
if (typeof requestResult !== 'object' || requestResult === null) {
|
|
750
|
+
requestResult = { raw: requestResult };
|
|
751
|
+
}
|
|
748
752
|
// P2-7: Persist endScene metadata when chained video generation
|
|
749
753
|
if (options.endscene) {
|
|
750
754
|
requestResult.end_scene_id = options.endscene;
|
|
@@ -1046,6 +1050,184 @@ program
|
|
|
1046
1050
|
}
|
|
1047
1051
|
});
|
|
1048
1052
|
|
|
1053
|
+
// --- Standalone Generate (Image / Video from text) ---
|
|
1054
|
+
program
|
|
1055
|
+
.command('gen-image')
|
|
1056
|
+
.description('Generate an image from a text prompt (standalone, no project needed). Costs 3 credits. Uses Imagen 3.5.')
|
|
1057
|
+
.requiredOption('-p, --prompt <prompt>', 'Text prompt to generate image from (10-2000 chars)')
|
|
1058
|
+
.option('-n, --negative <negative>', 'Negative prompt — things to avoid')
|
|
1059
|
+
.option('-o, --orientation <orientation>', 'Orientation: HORIZONTAL or VERTICAL', 'HORIZONTAL')
|
|
1060
|
+
.option('-w, --wait', 'Wait for completion (poll until done)', false)
|
|
1061
|
+
.option('-i, --interval <sec>', 'Polling interval in seconds (with --wait)', '5')
|
|
1062
|
+
.option('-t, --timeout <sec>', 'Timeout in seconds (with --wait)', '300')
|
|
1063
|
+
.action(async (options) => {
|
|
1064
|
+
try {
|
|
1065
|
+
const payload = {
|
|
1066
|
+
prompt: options.prompt,
|
|
1067
|
+
orientation: options.orientation.toUpperCase(),
|
|
1068
|
+
};
|
|
1069
|
+
if (options.negative) payload.negativePrompt = options.negative;
|
|
1070
|
+
|
|
1071
|
+
humanLog('🎨 Submitting standalone image generation request...');
|
|
1072
|
+
const data = await api.post('/app/standalone/generate-image', payload);
|
|
1073
|
+
const result = unwrapData(data);
|
|
1074
|
+
const requestId = result?.requestId || result?.request_id;
|
|
1075
|
+
|
|
1076
|
+
if (!requestId) {
|
|
1077
|
+
emitJson({ status: 'error', message: 'No requestId returned', data: result });
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
humanLog(`✅ Request created: ${requestId}`);
|
|
1082
|
+
|
|
1083
|
+
if (!options.wait) {
|
|
1084
|
+
emitJson({ status: 'success', requestId, message: 'Request submitted. Use --wait to poll for completion, or check with: veogent standalone-request ' + requestId });
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
// Poll for completion
|
|
1089
|
+
const intervalMs = Math.max(1, Number(options.interval || 5)) * 1000;
|
|
1090
|
+
const timeoutMs = Math.max(10, Number(options.timeout || 300)) * 1000;
|
|
1091
|
+
const startedAt = Date.now();
|
|
1092
|
+
|
|
1093
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
1094
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
1095
|
+
try {
|
|
1096
|
+
const statusData = await api.get(`/app/standalone/request/${requestId}`);
|
|
1097
|
+
const req = unwrapData(statusData);
|
|
1098
|
+
const status = String(req?.status || '').toUpperCase();
|
|
1099
|
+
humanLog(`⏳ Status: ${status}`);
|
|
1100
|
+
|
|
1101
|
+
if (status === 'COMPLETED') {
|
|
1102
|
+
emitJson({ status: 'success', requestId, imageUri: req?.outputData?.imageUri || null, data: req });
|
|
1103
|
+
return;
|
|
1104
|
+
}
|
|
1105
|
+
if (status === 'FAILED') {
|
|
1106
|
+
emitJson({ status: 'error', requestId, message: req?.message || 'Generation failed', data: req });
|
|
1107
|
+
process.exit(1);
|
|
1108
|
+
}
|
|
1109
|
+
} catch (pollErr) {
|
|
1110
|
+
humanError(`⚠️ Poll error: ${pollErr.message}`);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
emitJson({ status: 'error', code: 'WAIT_TIMEOUT', requestId, message: `Timeout after ${options.timeout}s` });
|
|
1115
|
+
process.exit(1);
|
|
1116
|
+
} catch (error) {
|
|
1117
|
+
emitJson({ status: 'error', ...formatCliError(error) });
|
|
1118
|
+
process.exit(1);
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
|
|
1122
|
+
program
|
|
1123
|
+
.command('gen-video')
|
|
1124
|
+
.description('Generate a video from a text prompt (standalone, no project needed). Costs 5 credits. Uses Veo 3.1 Fast.')
|
|
1125
|
+
.requiredOption('-p, --prompt <prompt>', 'Text prompt to generate video from (10-2000 chars)')
|
|
1126
|
+
.option('-n, --negative <negative>', 'Negative prompt — things to avoid')
|
|
1127
|
+
.option('-o, --orientation <orientation>', 'Orientation: HORIZONTAL or VERTICAL', 'HORIZONTAL')
|
|
1128
|
+
.option('-r, --reference <imageUri>', 'Reference image URI for image-to-video generation')
|
|
1129
|
+
.option('-w, --wait', 'Wait for completion (poll until done)', false)
|
|
1130
|
+
.option('-i, --interval <sec>', 'Polling interval in seconds (with --wait)', '10')
|
|
1131
|
+
.option('-t, --timeout <sec>', 'Timeout in seconds (with --wait)', '600')
|
|
1132
|
+
.action(async (options) => {
|
|
1133
|
+
try {
|
|
1134
|
+
const payload = {
|
|
1135
|
+
prompt: options.prompt,
|
|
1136
|
+
orientation: options.orientation.toUpperCase(),
|
|
1137
|
+
};
|
|
1138
|
+
if (options.negative) payload.negativePrompt = options.negative;
|
|
1139
|
+
if (options.reference) payload.referenceImageUri = options.reference;
|
|
1140
|
+
|
|
1141
|
+
humanLog('🎬 Submitting standalone video generation request...');
|
|
1142
|
+
const data = await api.post('/app/standalone/generate-video', payload);
|
|
1143
|
+
const result = unwrapData(data);
|
|
1144
|
+
const requestId = result?.requestId || result?.request_id;
|
|
1145
|
+
|
|
1146
|
+
if (!requestId) {
|
|
1147
|
+
emitJson({ status: 'error', message: 'No requestId returned', data: result });
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
humanLog(`✅ Request created: ${requestId}`);
|
|
1152
|
+
|
|
1153
|
+
if (!options.wait) {
|
|
1154
|
+
emitJson({ status: 'success', requestId, message: 'Request submitted. Use --wait to poll for completion, or check with: veogent standalone-request ' + requestId });
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// Poll for completion
|
|
1159
|
+
const intervalMs = Math.max(1, Number(options.interval || 10)) * 1000;
|
|
1160
|
+
const timeoutMs = Math.max(30, Number(options.timeout || 600)) * 1000;
|
|
1161
|
+
const startedAt = Date.now();
|
|
1162
|
+
|
|
1163
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
1164
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
1165
|
+
try {
|
|
1166
|
+
const statusData = await api.get(`/app/standalone/request/${requestId}`);
|
|
1167
|
+
const req = unwrapData(statusData);
|
|
1168
|
+
const status = String(req?.status || '').toUpperCase();
|
|
1169
|
+
humanLog(`⏳ Status: ${status}`);
|
|
1170
|
+
|
|
1171
|
+
if (status === 'COMPLETED') {
|
|
1172
|
+
emitJson({ status: 'success', requestId, videoUri: req?.outputData?.videoUri || null, data: req });
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
if (status === 'FAILED') {
|
|
1176
|
+
emitJson({ status: 'error', requestId, message: req?.message || 'Generation failed', data: req });
|
|
1177
|
+
process.exit(1);
|
|
1178
|
+
}
|
|
1179
|
+
} catch (pollErr) {
|
|
1180
|
+
humanError(`⚠️ Poll error: ${pollErr.message}`);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
emitJson({ status: 'error', code: 'WAIT_TIMEOUT', requestId, message: `Timeout after ${options.timeout}s` });
|
|
1185
|
+
process.exit(1);
|
|
1186
|
+
} catch (error) {
|
|
1187
|
+
emitJson({ status: 'error', ...formatCliError(error) });
|
|
1188
|
+
process.exit(1);
|
|
1189
|
+
}
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
program
|
|
1193
|
+
.command('standalone-requests')
|
|
1194
|
+
.description('List your standalone image/video generation requests')
|
|
1195
|
+
.option('-n, --limit <n>', 'Return only the N most recent', null)
|
|
1196
|
+
.option('-s, --status <status>', 'Filter by status (PENDING, PROCESSING, COMPLETED, FAILED)')
|
|
1197
|
+
.action(async (options) => {
|
|
1198
|
+
try {
|
|
1199
|
+
const data = await api.get('/app/standalone/requests');
|
|
1200
|
+
let items = unwrapData(data);
|
|
1201
|
+
items = Array.isArray(items) ? items : (items?.items || []);
|
|
1202
|
+
|
|
1203
|
+
if (options.status) {
|
|
1204
|
+
const s = options.status.toUpperCase();
|
|
1205
|
+
items = items.filter((r) => String(r?.status || '').toUpperCase() === s);
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
if (options.limit !== null && options.limit !== undefined) {
|
|
1209
|
+
const n = parseInt(options.limit, 10);
|
|
1210
|
+
if (!isNaN(n) && n > 0) items = items.slice(0, n);
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
emitJson({ status: 'success', total: items.length, data: items });
|
|
1214
|
+
} catch (error) {
|
|
1215
|
+
emitJson({ status: 'error', ...formatCliError(error) });
|
|
1216
|
+
}
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
program
|
|
1220
|
+
.command('standalone-request <requestId>')
|
|
1221
|
+
.description('Get details of a specific standalone request')
|
|
1222
|
+
.action(async (requestId) => {
|
|
1223
|
+
try {
|
|
1224
|
+
const data = await api.get(`/app/standalone/request/${requestId}`);
|
|
1225
|
+
emitJson({ status: 'success', data: unwrapData(data) });
|
|
1226
|
+
} catch (error) {
|
|
1227
|
+
emitJson({ status: 'error', ...formatCliError(error) });
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
|
|
1049
1231
|
// --- System ---
|
|
1050
1232
|
program
|
|
1051
1233
|
.command('skill')
|