@artillect/cli 0.1.2 → 0.1.5

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.
Files changed (3) hide show
  1. package/README.md +43 -11
  2. package/dist/index.js +968 -115
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -3,10 +3,12 @@
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
5
 
6
+ // src/config.ts
7
+ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
8
+ import { homedir } from "node:os";
9
+ import { dirname, join } from "node:path";
10
+
6
11
  // ../artillect-sdk/dist/uploadMime.js
7
- import { basename, isAbsolute, resolve } from "node:path";
8
- import { access, readFile } from "node:fs/promises";
9
- import { constants as fsConstants } from "node:fs";
10
12
  function mimeFromFilename(filename) {
11
13
  const ext = String(filename || "").split(".").pop()?.toLowerCase();
12
14
  switch (ext) {
@@ -81,46 +83,6 @@ function resolveUploadContentType(opts) {
81
83
  return { contentType: fromMagic, source: "magic" };
82
84
  return { contentType: declared || "application/octet-stream", source: "unknown" };
83
85
  }
84
- async function resolveLocalUploadPath(filePath) {
85
- const raw = String(filePath || "").trim();
86
- if (!raw)
87
- throw new Error("file_path is empty");
88
- const tried = [];
89
- const candidates = [];
90
- if (isAbsolute(raw)) {
91
- candidates.push(raw);
92
- } else {
93
- candidates.push(resolve(process.cwd(), raw));
94
- const uploadCwd = String(process.env.ARTILLECT_UPLOAD_CWD || "").trim();
95
- if (uploadCwd)
96
- candidates.push(resolve(uploadCwd, raw));
97
- const workspace = String(process.env.CURSOR_WORKSPACE || process.env.PWD || "").trim();
98
- if (workspace)
99
- candidates.push(resolve(workspace, raw));
100
- }
101
- for (const p of candidates) {
102
- if (tried.includes(p))
103
- continue;
104
- tried.push(p);
105
- try {
106
- await access(p, fsConstants.R_OK);
107
- return { path: p, tried };
108
- } catch {
109
- }
110
- }
111
- const err = new Error(`ENOENT: file not found. On stdio MCP pass an absolute path; on remote/hosted MCP use file_base64 + filename instead. Tried: ${tried.join(" | ")}`);
112
- err.code = "ENOENT";
113
- err.tried = tried;
114
- throw err;
115
- }
116
- async function readLocalUploadFile(filePath) {
117
- const { path: resolved } = await resolveLocalUploadPath(filePath);
118
- const buf = await readFile(resolved);
119
- const bytes = new Uint8Array(buf);
120
- const filename = basename(resolved);
121
- const { contentType } = resolveUploadContentType({ filename, bytes });
122
- return { bytes, filename, contentType };
123
- }
124
86
 
125
87
  // ../artillect-sdk/dist/http.js
126
88
  var JOB_SUFFIX_KIND = [
@@ -176,10 +138,21 @@ async function publicApiFetch(config, method, path, body, extraHeaders) {
176
138
  Authorization: `Bearer ${config.apiKey}`,
177
139
  Accept: "application/json"
178
140
  };
141
+ if (config.clientSource)
142
+ headers["X-Artillect-Client-Source"] = config.clientSource;
143
+ let requestBody = body;
144
+ if (body && typeof body === "object" && !Array.isArray(body)) {
145
+ const record = body;
146
+ if (typeof record.idempotency_key === "string" && record.idempotency_key.trim()) {
147
+ headers["Idempotency-Key"] = record.idempotency_key.trim();
148
+ const { idempotency_key: _idempotencyKey, ...withoutIdempotency } = record;
149
+ requestBody = withoutIdempotency;
150
+ }
151
+ }
179
152
  let payload;
180
- if (body !== void 0) {
153
+ if (requestBody !== void 0) {
181
154
  headers["Content-Type"] = "application/json";
182
- payload = JSON.stringify(body);
155
+ payload = JSON.stringify(requestBody);
183
156
  }
184
157
  Object.assign(headers, extraHeaders);
185
158
  const res = await fetch(url, { method, headers, body: payload });
@@ -201,12 +174,20 @@ async function publicApiUploadFile(config, file) {
201
174
  method: "POST",
202
175
  headers: {
203
176
  Authorization: `Bearer ${config.apiKey}`,
204
- Accept: "application/json"
177
+ Accept: "application/json",
178
+ ...config.clientSource ? { "X-Artillect-Client-Source": config.clientSource } : {}
205
179
  },
206
180
  body: form
207
181
  });
208
182
  return parseApiResponse(res);
209
183
  }
184
+ async function publicApiUploadFromUrl(config, opts) {
185
+ return publicApiFetch(config, "POST", "/api/v1/files/from-url", {
186
+ url: opts.url,
187
+ ...opts.filename ? { filename: opts.filename } : {},
188
+ ...opts.projectId != null ? { project_id: opts.projectId } : {}
189
+ });
190
+ }
210
191
  function listQueryPath(basePath, params) {
211
192
  const search = new URLSearchParams();
212
193
  if (params?.limit != null)
@@ -288,7 +269,11 @@ function createClient(opts) {
288
269
  if (!apiKey)
289
270
  throw new Error("apiKey is required");
290
271
  const baseUrl = String(opts.baseUrl || "https://app.artillect.pro").trim().replace(/\/+$/, "");
291
- const config = { apiKey, baseUrl };
272
+ const config = {
273
+ apiKey,
274
+ baseUrl,
275
+ ...opts.clientSource ? { clientSource: opts.clientSource } : {}
276
+ };
292
277
  return {
293
278
  config,
294
279
  getHealth: () => publicApiFetch(config, "GET", "/api/v1/health"),
@@ -297,6 +282,7 @@ function createClient(opts) {
297
282
  listModels: () => publicApiFetch(config, "GET", "/api/v1/models"),
298
283
  estimate: (body) => publicApiFetch(config, "POST", "/api/v1/estimate", body),
299
284
  uploadFile: (file) => publicApiUploadFile(config, file),
285
+ uploadFromUrl: (opts2) => publicApiUploadFromUrl(config, opts2),
300
286
  generateImage: (body) => publicApiFetch(config, "POST", "/api/v1/images/generations", body),
301
287
  getImageGeneration: (id) => publicApiFetch(config, "GET", `/api/v1/images/generations/${encodeURIComponent(id)}`),
302
288
  listImageGenerations: (params) => publicApiFetch(config, "GET", listQueryPath("/api/v1/images/generations", params)),
@@ -317,6 +303,10 @@ function createClient(opts) {
317
303
  getMeshGeneration: (id) => publicApiFetch(config, "GET", `/api/v1/mesh/generations/${encodeURIComponent(id)}`),
318
304
  listMeshGenerations: (params) => publicApiFetch(config, "GET", listQueryPath("/api/v1/mesh/generations", params)),
319
305
  cancelMeshGeneration: (id) => publicApiFetch(config, "POST", `/api/v1/mesh/generations/${encodeURIComponent(id)}/cancel`),
306
+ generateAudio: (body) => publicApiFetch(config, "POST", "/api/v1/audio/generations", body),
307
+ getAudioGeneration: (id) => publicApiFetch(config, "GET", `/api/v1/audio/generations/${encodeURIComponent(id)}`),
308
+ listAudioGenerations: (params) => publicApiFetch(config, "GET", listQueryPath("/api/v1/audio/generations", params)),
309
+ cancelAudioGeneration: (id) => publicApiFetch(config, "POST", `/api/v1/audio/generations/${encodeURIComponent(id)}/cancel`),
320
310
  chatCompletion: (body) => publicApiFetch(config, "POST", "/api/v1/chat/completions", body),
321
311
  getTask: (id, kind) => publicApiFetch(config, "GET", resolvePollPath(id, kind)),
322
312
  getWebhook: () => publicApiFetch(config, "GET", "/api/v1/webhooks"),
@@ -334,10 +324,52 @@ function createClient(opts) {
334
324
  };
335
325
  }
336
326
 
327
+ // ../artillect-sdk/dist/localUpload.js
328
+ import { basename, isAbsolute, resolve } from "node:path";
329
+ import { access, readFile } from "node:fs/promises";
330
+ import { constants as fsConstants } from "node:fs";
331
+ async function resolveLocalUploadPath(filePath) {
332
+ const raw = String(filePath || "").trim();
333
+ if (!raw)
334
+ throw new Error("file_path is empty");
335
+ const tried = [];
336
+ const candidates = [];
337
+ if (isAbsolute(raw)) {
338
+ candidates.push(raw);
339
+ } else {
340
+ candidates.push(resolve(process.cwd(), raw));
341
+ const uploadCwd = String(process.env.ARTILLECT_UPLOAD_CWD || "").trim();
342
+ if (uploadCwd)
343
+ candidates.push(resolve(uploadCwd, raw));
344
+ const workspace = String(process.env.CURSOR_WORKSPACE || process.env.PWD || "").trim();
345
+ if (workspace)
346
+ candidates.push(resolve(workspace, raw));
347
+ }
348
+ for (const p of candidates) {
349
+ if (tried.includes(p))
350
+ continue;
351
+ tried.push(p);
352
+ try {
353
+ await access(p, fsConstants.R_OK);
354
+ return { path: p, tried };
355
+ } catch {
356
+ }
357
+ }
358
+ const err = new Error(`ENOENT: file not found. On stdio MCP pass an absolute path; on remote/hosted MCP use file_base64 + filename instead. Tried: ${tried.join(" | ")}`);
359
+ err.code = "ENOENT";
360
+ err.tried = tried;
361
+ throw err;
362
+ }
363
+ async function readLocalUploadFile(filePath) {
364
+ const { path: resolved } = await resolveLocalUploadPath(filePath);
365
+ const buf = await readFile(resolved);
366
+ const bytes = new Uint8Array(buf);
367
+ const filename = basename(resolved);
368
+ const { contentType } = resolveUploadContentType({ filename, bytes });
369
+ return { bytes, filename, contentType };
370
+ }
371
+
337
372
  // src/config.ts
338
- import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
339
- import { homedir } from "node:os";
340
- import { dirname, join } from "node:path";
341
373
  var DEFAULT_BASE = "https://app.artillect.pro";
342
374
  function configPath() {
343
375
  const xdg = String(process.env.XDG_CONFIG_HOME || "").trim();
@@ -371,6 +403,14 @@ function requireApiKey() {
371
403
  }
372
404
  return cfg;
373
405
  }
406
+ function createCliClient(cfg) {
407
+ const resolved = cfg ?? requireApiKey();
408
+ return createClient({
409
+ apiKey: resolved.apiKey,
410
+ baseUrl: resolved.baseUrl,
411
+ clientSource: "cli"
412
+ });
413
+ }
374
414
  function saveCliConfig(cfg) {
375
415
  const path = configPath();
376
416
  mkdirSync(dirname(path), { recursive: true });
@@ -434,6 +474,22 @@ import { pipeline } from "node:stream/promises";
434
474
  function asRecord(value) {
435
475
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
436
476
  }
477
+ function modelLimits(m) {
478
+ const lines = [];
479
+ if (m.max_prompt_chars != null) lines.push(`prompt \u2264 ${m.max_prompt_chars} \u0441\u0438\u043C\u0432.`);
480
+ if (m.context_length_tokens != null) {
481
+ lines.push(`\u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442 OpenRouter: ${m.context_length_tokens} \u0442\u043E\u043A\u0435\u043D\u043E\u0432`);
482
+ }
483
+ if (m.provider_context_length_tokens != null) {
484
+ lines.push(`\u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442 \u043C\u0430\u0440\u0448\u0440\u0443\u0442\u0430: ${m.provider_context_length_tokens} \u0442\u043E\u043A\u0435\u043D\u043E\u0432`);
485
+ }
486
+ if (m.provider_max_output_tokens != null) {
487
+ lines.push(`\u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u043E\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u2264 ${m.provider_max_output_tokens} \u0442\u043E\u043A\u0435\u043D\u043E\u0432`);
488
+ }
489
+ if (m.max_input_chars != null) lines.push(`\u0432\u0445\u043E\u0434 API \u2264 ${m.max_input_chars} \u0441\u0438\u043C\u0432.`);
490
+ if (m.max_output_tokens != null) lines.push(`\u0432\u044B\u0445\u043E\u0434 API \u2264 ${m.max_output_tokens} \u0442\u043E\u043A\u0435\u043D\u043E\u0432`);
491
+ return lines;
492
+ }
437
493
  function formatModelsList(body, kind) {
438
494
  const groups = [
439
495
  ["images", "\u041A\u0430\u0440\u0442\u0438\u043D\u043A\u0438"],
@@ -455,7 +511,8 @@ function formatModelsList(body, kind) {
455
511
  const m = asRecord(raw);
456
512
  const slug = String(m.slug || "");
457
513
  const name = String(m.display_name || slug);
458
- lines.push(` ${slug.padEnd(24)} ${name}`);
514
+ const limits = modelLimits(m);
515
+ lines.push(` ${slug.padEnd(24)} ${name}${limits.length ? ` \u2014 ${limits.join("; ")}` : ""}`);
459
516
  }
460
517
  lines.push("");
461
518
  }
@@ -585,10 +642,14 @@ async function resolveInputRef(client, ref, opts) {
585
642
  function mediaUrls(body) {
586
643
  const images = Array.isArray(body.images) ? body.images : [];
587
644
  const videos = Array.isArray(body.videos) ? body.videos : [];
588
- const fromSlots = [...images, ...videos].map((item) => item && typeof item === "object" ? String(asRecord(item).url || "") : "").filter(Boolean);
645
+ const audios = Array.isArray(body.audio_urls) ? body.audio_urls : [];
646
+ const meshes = Array.isArray(body.mesh) ? body.mesh : [];
647
+ const fromSlots = [...images, ...videos, ...audios, ...meshes].map(
648
+ (item) => item && typeof item === "object" ? String(asRecord(item).url || asRecord(item).audio_url || asRecord(item).glb_url || "") : typeof item === "string" ? item : ""
649
+ ).filter(Boolean);
589
650
  if (fromSlots.length) return fromSlots;
590
- const media = Array.isArray(body.media_urls) ? body.media_urls : [];
591
- return media.map((u) => String(u || "")).filter(Boolean);
651
+ const media2 = Array.isArray(body.media_urls) ? body.media_urls : [];
652
+ return [...media2, body.audio_url, body.mesh_url].map((u) => String(u || "")).filter(Boolean);
592
653
  }
593
654
  function terminalStatus(body) {
594
655
  const status = String(body.status || "").toLowerCase();
@@ -746,7 +807,7 @@ async function authStatus() {
746
807
  const envKey = Boolean(String(process.env.ARTILLECT_API_KEY || "").trim());
747
808
  try {
748
809
  const cfg = requireApiKey();
749
- const client = createClient({ apiKey: cfg.apiKey, baseUrl: cfg.baseUrl });
810
+ const client = createCliClient(cfg);
750
811
  const me = await client.getMe();
751
812
  if (!me.ok) {
752
813
  console.log(
@@ -764,10 +825,130 @@ async function authStatus() {
764
825
  }
765
826
  }
766
827
 
828
+ // src/generateBody.ts
829
+ function omitEmpty(obj) {
830
+ const out = {};
831
+ for (const [key, value] of Object.entries(obj)) {
832
+ if (value === void 0) continue;
833
+ if (Array.isArray(value) && value.length === 0) continue;
834
+ if (typeof value === "string" && !value.trim()) continue;
835
+ out[key] = value;
836
+ }
837
+ return out;
838
+ }
839
+ function parseExtra(raw) {
840
+ if (!raw) return {};
841
+ if (typeof raw === "object" && !Array.isArray(raw)) return raw;
842
+ if (typeof raw !== "string") return {};
843
+ const trimmed = raw.trim();
844
+ if (!trimmed) return {};
845
+ const parsed = JSON.parse(trimmed);
846
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
847
+ throw new Error("--extra \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C JSON-\u043E\u0431\u044A\u0435\u043A\u0442\u043E\u043C");
848
+ }
849
+ return parsed;
850
+ }
851
+ function mergeExtra(body, extra, prompt) {
852
+ const merged = { ...body, ...extra };
853
+ const extraPrompt = typeof extra.prompt === "string" ? extra.prompt.trim() : "";
854
+ merged.prompt = extraPrompt || prompt;
855
+ return merged;
856
+ }
857
+ function buildImageGenerateBody(flags) {
858
+ const extra = parseExtra(flags.extra);
859
+ const prompt = flags.prompt ?? "";
860
+ const body = omitEmpty({
861
+ prompt,
862
+ ...flags.model ? { model: flags.model } : {},
863
+ ...flags.inputUrls?.length ? { input_urls: flags.inputUrls } : {},
864
+ ...flags.projectId != null ? { project_id: flags.projectId } : {},
865
+ ...flags.aspectRatio ? { aspect_ratio: flags.aspectRatio } : {},
866
+ ...flags.resolution ? { resolution: flags.resolution } : {},
867
+ ...flags.quality ? { quality: flags.quality } : {},
868
+ ...flags.numImages != null ? { num_images: flags.numImages } : {},
869
+ ...flags.outputFormat ? { output_format: flags.outputFormat } : {},
870
+ ...flags.syncMode != null ? { sync_mode: flags.syncMode } : {},
871
+ ...flags.billingSource ? { billing_source: flags.billingSource } : {},
872
+ ...flags.tagIds?.length ? { tag_ids: flags.tagIds } : {},
873
+ ...flags.elementNames?.length ? { element_names: flags.elementNames } : {}
874
+ });
875
+ return mergeExtra(body, extra, prompt);
876
+ }
877
+ function buildVideoGenerateBody(flags) {
878
+ const extra = parseExtra(flags.extra);
879
+ const body = omitEmpty({
880
+ model: flags.model,
881
+ prompt: flags.prompt,
882
+ ...flags.projectId != null ? { project_id: flags.projectId } : {},
883
+ ...flags.startImageUrl ? { start_image_url: flags.startImageUrl } : {},
884
+ ...flags.endImageUrl ? { end_image_url: flags.endImageUrl } : {},
885
+ ...flags.duration != null && flags.duration !== "" ? { duration: flags.duration } : {},
886
+ ...flags.resolution ? { resolution: flags.resolution } : {},
887
+ ...flags.aspectRatio ? { aspect_ratio: flags.aspectRatio } : {},
888
+ ...flags.task ? { task: flags.task } : {},
889
+ ...flags.seedanceMode ? { seedance_mode: flags.seedanceMode } : {},
890
+ ...flags.referenceImages?.length ? { reference_images: flags.referenceImages } : {},
891
+ ...flags.referenceVideos?.length ? { reference_videos: flags.referenceVideos } : {},
892
+ ...flags.referenceAudios?.length ? { reference_audios: flags.referenceAudios } : {},
893
+ ...flags.referenceFiles?.length ? { reference_file_urls: flags.referenceFiles } : {},
894
+ ...flags.referenceLinks?.length ? { reference_link_urls: flags.referenceLinks } : {},
895
+ ...flags.audio != null ? { audio: flags.audio } : {},
896
+ ...flags.seed != null ? { seed: flags.seed } : {},
897
+ ...flags.nsfwChecker != null ? { nsfw_checker: flags.nsfwChecker } : {},
898
+ ...flags.promptExpansionMode ? { prompt_expansion_mode: flags.promptExpansionMode } : {},
899
+ ...flags.enableSafetyChecker != null ? { enable_safety_checker: flags.enableSafetyChecker } : {},
900
+ ...flags.syncMode != null ? { sync_mode: flags.syncMode } : {},
901
+ ...flags.sourceVideoUrl ? { source_video_url: flags.sourceVideoUrl } : {},
902
+ ...flags.audioUrl ? { audio_url: flags.audioUrl } : {},
903
+ ...flags.motionVideoUrl ? { motion_video_url: flags.motionVideoUrl } : {},
904
+ ...flags.elementNames?.length ? { element_names: flags.elementNames } : {},
905
+ ...flags.klingMode ? { kling_mode: flags.klingMode } : {},
906
+ ...flags.shotType ? { shot_type: flags.shotType } : {},
907
+ ...flags.multiPrompt != null ? { multi_prompt: flags.multiPrompt } : {},
908
+ ...flags.multiShots != null ? { multi_shots: flags.multiShots } : {},
909
+ ...flags.keepAudio != null ? { keep_audio: flags.keepAudio } : {},
910
+ ...flags.cfgScale != null ? { cfg_scale: flags.cfgScale } : {},
911
+ ...flags.generateAudio != null ? { generate_audio: flags.generateAudio } : {},
912
+ ...flags.billingSource ? { billing_source: flags.billingSource } : {},
913
+ ...flags.tagIds?.length ? { tag_ids: flags.tagIds } : {}
914
+ });
915
+ return mergeExtra(body, extra, flags.prompt);
916
+ }
917
+
767
918
  // src/generate.ts
919
+ function parseExtra2(raw) {
920
+ if (!raw?.trim()) return {};
921
+ const parsed = JSON.parse(raw);
922
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
923
+ throw new Error("--extra \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C JSON-\u043E\u0431\u044A\u0435\u043A\u0442\u043E\u043C");
924
+ }
925
+ return parsed;
926
+ }
927
+ function parseTagIds(raw) {
928
+ if (!raw?.trim()) return void 0;
929
+ const ids = raw.split(",").map((part) => Number(part.trim()));
930
+ if (ids.some((id) => !Number.isInteger(id) || id <= 0)) {
931
+ throw new Error("--tag-id \u0434\u043E\u043B\u0436\u0435\u043D \u0441\u043E\u0434\u0435\u0440\u0436\u0430\u0442\u044C \u043F\u043E\u043B\u043E\u0436\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u0446\u0435\u043B\u044B\u0435 \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E");
932
+ }
933
+ return ids;
934
+ }
935
+ async function finishSubmitted(client, body, opts) {
936
+ const taskId = String(body.task_id || body.id || "");
937
+ if (!opts.wait) {
938
+ printOrJson(opts.json, body, [`\u041E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E ${taskId || "(\u043D\u0435\u0442 task_id)"}`]);
939
+ return;
940
+ }
941
+ if (!taskId) throw new Error("\u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u0432\u0435\u0440\u043D\u0443\u043B task_id");
942
+ await finishAndSave(client, taskId, {
943
+ json: opts.json,
944
+ out: opts.out,
945
+ open: opts.open,
946
+ timeoutMs: parseDurationMs(opts.waitTimeout, 20 * 60 * 1e3)
947
+ });
948
+ }
768
949
  async function cmdBalance(jsonMode) {
769
950
  const cfg = requireApiKey();
770
- const client = createClient(cfg);
951
+ const client = createCliClient(cfg);
771
952
  const res = await client.getBalance();
772
953
  if (!res.ok) fail(res);
773
954
  const body = asRecord(res.body);
@@ -812,7 +993,12 @@ async function cmdModelsGet(slug, jsonMode) {
812
993
  `${found.kind}: ${String(m.slug || slug)}`,
813
994
  m.display_name ? String(m.display_name) : "",
814
995
  Array.isArray(m.tasks) ? `\u0437\u0430\u0434\u0430\u0447\u0438: ${m.tasks.join(", ")}` : "",
815
- m.max_prompt_chars != null ? `\u043B\u0438\u043C\u0438\u0442 \u043F\u0440\u043E\u043C\u043F\u0442\u0430: ${m.max_prompt_chars}` : ""
996
+ m.max_prompt_chars != null ? `\u043B\u0438\u043C\u0438\u0442 \u043F\u0440\u043E\u043C\u043F\u0442\u0430: ${m.max_prompt_chars}` : "",
997
+ m.context_length_tokens != null ? `\u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442 OpenRouter: ${m.context_length_tokens} \u0442\u043E\u043A\u0435\u043D\u043E\u0432` : "",
998
+ m.provider_context_length_tokens != null ? `\u043A\u043E\u043D\u0442\u0435\u043A\u0441\u0442 \u043C\u0430\u0440\u0448\u0440\u0443\u0442\u0430: ${m.provider_context_length_tokens} \u0442\u043E\u043A\u0435\u043D\u043E\u0432` : "",
999
+ m.provider_max_output_tokens != null ? `\u0432\u044B\u0445\u043E\u0434 \u043F\u0440\u043E\u0432\u0430\u0439\u0434\u0435\u0440\u0430: \u0434\u043E ${m.provider_max_output_tokens} \u0442\u043E\u043A\u0435\u043D\u043E\u0432` : "",
1000
+ m.max_input_chars != null ? `\u0432\u0445\u043E\u0434 API: \u0434\u043E ${m.max_input_chars} \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432` : "",
1001
+ m.max_output_tokens != null ? `\u0432\u044B\u0445\u043E\u0434 API: \u0434\u043E ${m.max_output_tokens} \u0442\u043E\u043A\u0435\u043D\u043E\u0432` : ""
816
1002
  ].filter(Boolean);
817
1003
  if (m.parameters && typeof m.parameters === "object") {
818
1004
  lines.push("\u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B:");
@@ -822,13 +1008,25 @@ async function cmdModelsGet(slug, jsonMode) {
822
1008
  }
823
1009
  async function cmdUpload(opts) {
824
1010
  const cfg = requireApiKey();
825
- const client = createClient(cfg);
1011
+ const client = createCliClient(cfg);
826
1012
  const projectId = opts.projectId ? parseProjectId(opts.projectId) : void 0;
827
- const uploaded = await uploadLocal(
828
- client,
829
- opts.filePath,
830
- projectId != null ? { projectId } : void 0
831
- );
1013
+ if (Boolean(opts.filePath) === Boolean(opts.url)) {
1014
+ throw new Error("\u0443\u043A\u0430\u0436\u0438\u0442\u0435 \u0440\u043E\u0432\u043D\u043E \u043E\u0434\u0438\u043D \u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A: \u0444\u0430\u0439\u043B \u0438\u043B\u0438 --url");
1015
+ }
1016
+ const uploaded = opts.url ? await client.uploadFromUrl({
1017
+ url: opts.url,
1018
+ filename: opts.filename,
1019
+ ...projectId != null ? { projectId } : {}
1020
+ }).then((res) => {
1021
+ if (!res.ok) fail(res);
1022
+ const body = asRecord(res.body);
1023
+ return {
1024
+ assetId: String(body.asset_id || ""),
1025
+ url: String(body.url || ""),
1026
+ kind: String(body.kind || "")
1027
+ };
1028
+ }) : await uploadLocal(client, opts.filePath, projectId != null ? { projectId } : void 0);
1029
+ if (!uploaded.url) throw new Error("\u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u043D\u0435 \u0432\u0435\u0440\u043D\u0443\u043B\u0430 url");
832
1030
  printOrJson(opts.json, { asset_id: uploaded.assetId, url: uploaded.url, kind: uploaded.kind }, [
833
1031
  uploaded.assetId || "(\u043D\u0435\u0442 asset_id)",
834
1032
  uploaded.url
@@ -836,7 +1034,7 @@ async function cmdUpload(opts) {
836
1034
  }
837
1035
  async function cmdEstimate(opts) {
838
1036
  const cfg = requireApiKey();
839
- const client = createClient(cfg);
1037
+ const client = createCliClient(cfg);
840
1038
  const body = {
841
1039
  type: opts.type,
842
1040
  prompt: opts.prompt
@@ -849,7 +1047,7 @@ async function cmdEstimate(opts) {
849
1047
  }
850
1048
  async function cmdGenerateImage(opts) {
851
1049
  const cfg = requireApiKey();
852
- const client = createClient(cfg);
1050
+ const client = createCliClient(cfg);
853
1051
  const projectId = opts.projectId ? parseProjectId(opts.projectId) : void 0;
854
1052
  const inputUrls = [];
855
1053
  for (const ref of opts.input ?? []) {
@@ -857,12 +1055,24 @@ async function cmdGenerateImage(opts) {
857
1055
  await resolveInputRef(client, ref, projectId != null ? { projectId } : void 0)
858
1056
  );
859
1057
  }
860
- const res = await client.generateImage({
861
- prompt: opts.prompt,
862
- ...opts.model ? { model: opts.model } : {},
863
- ...inputUrls.length ? { input_urls: inputUrls } : {},
864
- ...projectId != null ? { project_id: projectId } : {}
1058
+ const payload = buildImageGenerateBody({
1059
+ prompt: opts.prompt ?? "",
1060
+ model: opts.model,
1061
+ inputUrls,
1062
+ projectId,
1063
+ aspectRatio: opts.aspectRatio,
1064
+ resolution: opts.resolution,
1065
+ quality: opts.quality,
1066
+ numImages: opts.numImages == null ? void 0 : Number(opts.numImages),
1067
+ outputFormat: opts.outputFormat,
1068
+ syncMode: opts.syncMode,
1069
+ billingSource: opts.billingSource,
1070
+ tagIds: opts.tagIds,
1071
+ elementNames: opts.elementNames,
1072
+ extra: opts.extra
865
1073
  });
1074
+ if (opts.idempotencyKey) payload.idempotency_key = opts.idempotencyKey;
1075
+ const res = await client.generateImage(payload);
866
1076
  if (!res.ok) fail(res);
867
1077
  const body = asRecord(res.body);
868
1078
  const taskId = String(body.task_id || body.id || "");
@@ -880,25 +1090,116 @@ async function cmdGenerateImage(opts) {
880
1090
  }
881
1091
  async function cmdGenerateVideo(opts) {
882
1092
  const cfg = requireApiKey();
883
- const client = createClient(cfg);
1093
+ const client = createCliClient(cfg);
884
1094
  const projectId = opts.projectId ? parseProjectId(opts.projectId) : void 0;
885
- const body = { model: opts.model, prompt: opts.prompt };
886
- if (projectId != null) body.project_id = projectId;
887
- if (opts.startImage) {
888
- body.start_image_url = await resolveInputRef(
889
- client,
890
- opts.startImage,
891
- projectId != null ? { projectId } : void 0
892
- );
1095
+ const resolveOpts = projectId != null ? { projectId } : void 0;
1096
+ const resolveAll = async (refs) => {
1097
+ const out = [];
1098
+ for (const ref of refs ?? []) {
1099
+ out.push(await resolveInputRef(client, ref, resolveOpts));
1100
+ }
1101
+ return out;
1102
+ };
1103
+ const durationRaw = opts.duration?.trim();
1104
+ const durationNum = durationRaw != null && durationRaw !== "" ? Number(durationRaw) : NaN;
1105
+ const documentRefs = opts.refFile ? [opts.refFile.trim()] : [];
1106
+ if (documentRefs.some((ref) => !/^https?:\/\//i.test(ref))) {
1107
+ throw new Error("--ref-file \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442 \u043F\u0443\u0431\u043B\u0438\u0447\u043D\u044B\u0439 http(s) URL \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430");
893
1108
  }
894
- if (opts.endImage) {
895
- body.end_image_url = await resolveInputRef(
896
- client,
897
- opts.endImage,
898
- projectId != null ? { projectId } : void 0
899
- );
1109
+ const payload = buildVideoGenerateBody({
1110
+ model: opts.model,
1111
+ prompt: opts.prompt,
1112
+ projectId,
1113
+ startImageUrl: opts.startImage ? await resolveInputRef(client, opts.startImage, resolveOpts) : void 0,
1114
+ endImageUrl: opts.endImage ? await resolveInputRef(client, opts.endImage, resolveOpts) : void 0,
1115
+ sourceVideoUrl: opts.sourceVideoUrl ? await resolveInputRef(client, opts.sourceVideoUrl, resolveOpts) : void 0,
1116
+ audioUrl: opts.audioUrl ? await resolveInputRef(client, opts.audioUrl, resolveOpts) : void 0,
1117
+ motionVideoUrl: opts.motionVideoUrl ? await resolveInputRef(client, opts.motionVideoUrl, resolveOpts) : void 0,
1118
+ duration: durationRaw ? Number.isFinite(durationNum) ? durationNum : durationRaw : void 0,
1119
+ resolution: opts.resolution,
1120
+ aspectRatio: opts.aspectRatio,
1121
+ task: opts.task,
1122
+ seedanceMode: opts.seedanceMode,
1123
+ referenceImages: await resolveAll(opts.refImage),
1124
+ referenceVideos: await resolveAll(opts.refVideo),
1125
+ referenceAudios: await resolveAll(opts.refAudio),
1126
+ referenceFiles: documentRefs,
1127
+ referenceLinks: opts.refLink ?? [],
1128
+ audio: opts.audio,
1129
+ seed: opts.seed != null && opts.seed !== "" ? Number(opts.seed) : void 0,
1130
+ nsfwChecker: opts.nsfwChecker,
1131
+ promptExpansionMode: opts.promptExpansionMode,
1132
+ enableSafetyChecker: opts.enableSafetyChecker,
1133
+ syncMode: opts.syncMode,
1134
+ elementNames: opts.elementNames,
1135
+ klingMode: opts.klingMode,
1136
+ shotType: opts.shotType,
1137
+ multiPrompt: opts.multiPrompt ? JSON.parse(opts.multiPrompt) : void 0,
1138
+ multiShots: opts.multiShots == null ? void 0 : Number(opts.multiShots),
1139
+ keepAudio: opts.keepAudio,
1140
+ cfgScale: opts.cfgScale == null ? void 0 : Number(opts.cfgScale),
1141
+ generateAudio: opts.generateAudio,
1142
+ billingSource: opts.billingSource,
1143
+ tagIds: opts.tagIds,
1144
+ extra: opts.extra
1145
+ });
1146
+ if (opts.idempotencyKey) payload.idempotency_key = opts.idempotencyKey;
1147
+ const res = await client.generateVideo(payload);
1148
+ if (!res.ok) fail(res);
1149
+ const submitted = asRecord(res.body);
1150
+ const taskId = String(submitted.task_id || submitted.id || "");
1151
+ if (!opts.wait) {
1152
+ printOrJson(opts.json, submitted, [`\u041E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E ${taskId || "(\u043D\u0435\u0442 task_id)"}`]);
1153
+ return;
900
1154
  }
901
- const res = await client.generateVideo(body);
1155
+ if (!taskId) throw new Error("\u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u0432\u0435\u0440\u043D\u0443\u043B task_id");
1156
+ await finishAndSave(client, taskId, {
1157
+ json: opts.json,
1158
+ out: opts.out,
1159
+ open: opts.open,
1160
+ timeoutMs: parseDurationMs(opts.waitTimeout, 20 * 60 * 1e3)
1161
+ });
1162
+ }
1163
+ async function cmdGenerateMesh(opts) {
1164
+ const cfg = requireApiKey();
1165
+ const client = createCliClient(cfg);
1166
+ const projectId = opts.projectId ? parseProjectId(opts.projectId) : void 0;
1167
+ const resolveOpts = projectId != null ? { projectId } : void 0;
1168
+ const images = [];
1169
+ for (const ref of opts.image ?? []) images.push(await resolveInputRef(client, ref, resolveOpts));
1170
+ const bool = (value) => value == null ? void 0 : value !== "false";
1171
+ const body = {
1172
+ kind: "threed",
1173
+ model: opts.model,
1174
+ task: opts.task,
1175
+ prompt: opts.prompt,
1176
+ project_id: projectId,
1177
+ ...images.length > 1 || opts.task === "multi-i2m" || opts.model === "meshy-v7-multi-i2m" ? { image_urls: images } : images[0] ? { image_url: images[0] } : {},
1178
+ mode: opts.mode,
1179
+ model_type: opts.modelType,
1180
+ topology: opts.topology,
1181
+ target_polycount: opts.targetPolycount == null ? void 0 : Number(opts.targetPolycount),
1182
+ symmetry_mode: opts.symmetryMode,
1183
+ should_remesh: bool(opts.shouldRemesh),
1184
+ should_texture: bool(opts.shouldTexture),
1185
+ enable_pbr: bool(opts.enablePbr),
1186
+ pose_mode: opts.poseMode,
1187
+ enable_prompt_expansion: bool(opts.enablePromptExpansion),
1188
+ texture_prompt: opts.texturePrompt,
1189
+ texture_image_url: opts.textureImage,
1190
+ seed: opts.seed == null ? void 0 : Number(opts.seed),
1191
+ enable_rigging: bool(opts.enableRigging),
1192
+ rigging_height_meters: opts.riggingHeight == null ? void 0 : Number(opts.riggingHeight),
1193
+ enable_animation: bool(opts.enableAnimation),
1194
+ animation_action_id: opts.animationActionId == null ? void 0 : Number(opts.animationActionId),
1195
+ enable_safety_checker: bool(opts.enableSafetyChecker),
1196
+ ultra_mode: bool(opts.ultraMode),
1197
+ billing_source: opts.billingSource,
1198
+ tag_ids: opts.tagIds
1199
+ };
1200
+ const extra = parseExtra2(opts.extra);
1201
+ if (opts.idempotencyKey) extra.idempotency_key = opts.idempotencyKey;
1202
+ const res = await client.generateMesh({ ...body, ...extra });
902
1203
  if (!res.ok) fail(res);
903
1204
  const submitted = asRecord(res.body);
904
1205
  const taskId = String(submitted.task_id || submitted.id || "");
@@ -914,9 +1215,112 @@ async function cmdGenerateVideo(opts) {
914
1215
  timeoutMs: parseDurationMs(opts.waitTimeout, 20 * 60 * 1e3)
915
1216
  });
916
1217
  }
1218
+ async function cmdGenerateUpscale(opts) {
1219
+ const cfg = requireApiKey();
1220
+ const client = createCliClient(cfg);
1221
+ const projectId = opts.projectId ? parseProjectId(opts.projectId) : void 0;
1222
+ if (Boolean(opts.image) === Boolean(opts.video)) {
1223
+ throw new Error("\u0443\u043A\u0430\u0436\u0438\u0442\u0435 \u0440\u043E\u0432\u043D\u043E \u043E\u0434\u0438\u043D \u0438\u0441\u0442\u043E\u0447\u043D\u0438\u043A: --image \u0438\u043B\u0438 --video");
1224
+ }
1225
+ const source = opts.image || opts.video;
1226
+ const sourceUrl = await resolveInputRef(
1227
+ client,
1228
+ source,
1229
+ projectId != null ? { projectId } : void 0
1230
+ );
1231
+ const body = {
1232
+ kind: opts.image ? "image" : "video",
1233
+ model: opts.model,
1234
+ ...opts.image ? { image_url: sourceUrl } : { video_url: sourceUrl },
1235
+ ...opts.enhancementModel ? { enhancement_model: opts.enhancementModel } : {},
1236
+ ...opts.upscaleFactor ? { upscale_factor: Number(opts.upscaleFactor) } : {},
1237
+ ...opts.creativity ? { creativity: Number(opts.creativity) } : {},
1238
+ ...opts.prompt ? { prompt: opts.prompt } : {},
1239
+ ...opts.safetyTolerance ? { safety_tolerance: Number(opts.safetyTolerance) } : {},
1240
+ ...opts.duration ? { duration: Number(opts.duration) } : {},
1241
+ ...opts.width ? { width: Number(opts.width) } : {},
1242
+ ...opts.height ? { height: Number(opts.height) } : {},
1243
+ ...opts.outputFormat ? { output_format: opts.outputFormat } : {},
1244
+ ...opts.cropToFill != null ? { crop_to_fill: opts.cropToFill } : {},
1245
+ ...opts.faceEnhancement != null ? { face_enhancement: opts.faceEnhancement } : {},
1246
+ ...opts.faceEnhancementStrength ? { face_enhancement_strength: Number(opts.faceEnhancementStrength) } : {},
1247
+ ...opts.faceEnhancementCreativity ? { face_enhancement_creativity: Number(opts.faceEnhancementCreativity) } : {},
1248
+ ...opts.billingSource ? { billing_source: opts.billingSource } : {},
1249
+ ...opts.tagIds?.length ? { tag_ids: opts.tagIds } : {}
1250
+ };
1251
+ const extra = parseExtra2(opts.extra);
1252
+ if (opts.idempotencyKey) extra.idempotency_key = opts.idempotencyKey;
1253
+ const res = await client.generateUpscale({ ...body, ...extra });
1254
+ if (!res.ok) fail(res);
1255
+ const submitted = asRecord(res.body);
1256
+ const taskId = String(submitted.task_id || submitted.id || "");
1257
+ if (!opts.wait) {
1258
+ printOrJson(opts.json, submitted, [`\u041E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E ${taskId || "(\u043D\u0435\u0442 task_id)"}`]);
1259
+ return;
1260
+ }
1261
+ if (!taskId) throw new Error("\u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u0432\u0435\u0440\u043D\u0443\u043B task_id");
1262
+ await finishAndSave(client, taskId, {
1263
+ json: opts.json,
1264
+ out: opts.out,
1265
+ open: opts.open,
1266
+ timeoutMs: parseDurationMs(opts.waitTimeout, 20 * 60 * 1e3)
1267
+ });
1268
+ }
1269
+ async function cmdGenerateAudio(opts) {
1270
+ const client = createCliClient(requireApiKey());
1271
+ const body = {
1272
+ prompt: opts.prompt,
1273
+ model: opts.model,
1274
+ style: opts.style,
1275
+ title: opts.title,
1276
+ custom_mode: opts.customMode,
1277
+ instrumental: opts.instrumental,
1278
+ negative_tags: opts.negativeTags,
1279
+ vocal_gender: opts.vocalGender,
1280
+ style_weight: opts.styleWeight == null ? void 0 : Number(opts.styleWeight),
1281
+ weirdness_constraint: opts.weirdnessConstraint == null ? void 0 : Number(opts.weirdnessConstraint),
1282
+ audio_weight: opts.audioWeight == null ? void 0 : Number(opts.audioWeight),
1283
+ project_id: opts.projectId ? parseProjectId(opts.projectId) : void 0,
1284
+ billing_source: opts.billingSource,
1285
+ tag_ids: opts.tagIds,
1286
+ ...parseExtra2(opts.extra)
1287
+ };
1288
+ if (opts.idempotencyKey) body.idempotency_key = opts.idempotencyKey;
1289
+ const res = await client.generateAudio(body);
1290
+ if (!res.ok) fail(res);
1291
+ await finishSubmitted(client, asRecord(res.body), opts);
1292
+ }
1293
+ async function cmdGenerateSwitchx(opts) {
1294
+ const client = createCliClient(requireApiKey());
1295
+ const projectId = opts.projectId ? parseProjectId(opts.projectId) : void 0;
1296
+ const sourceUrl = await resolveInputRef(
1297
+ client,
1298
+ opts.source,
1299
+ projectId ? { projectId } : void 0
1300
+ );
1301
+ const body = {
1302
+ source_url: sourceUrl,
1303
+ model: opts.model,
1304
+ generation_type: opts.generationType,
1305
+ reference_image_url: opts.referenceImage,
1306
+ alpha_mode: opts.alphaMode,
1307
+ alpha_url: opts.alphaUrl,
1308
+ prompt: opts.prompt,
1309
+ max_resolution: opts.maxResolution == null ? void 0 : Number(opts.maxResolution),
1310
+ frame_count: opts.frameCount == null ? void 0 : Number(opts.frameCount),
1311
+ project_id: projectId,
1312
+ billing_source: opts.billingSource,
1313
+ tag_ids: opts.tagIds,
1314
+ ...parseExtra2(opts.extra)
1315
+ };
1316
+ if (opts.idempotencyKey) body.idempotency_key = opts.idempotencyKey;
1317
+ const res = await client.generateSwitchx(body);
1318
+ if (!res.ok) fail(res);
1319
+ await finishSubmitted(client, asRecord(res.body), opts);
1320
+ }
917
1321
  async function cmdGenerateGet(taskId, jsonMode) {
918
1322
  const cfg = requireApiKey();
919
- const client = createClient(cfg);
1323
+ const client = createCliClient(cfg);
920
1324
  const res = await client.getTask(taskId);
921
1325
  if (!res.ok) fail(res);
922
1326
  const body = asRecord(res.body);
@@ -924,7 +1328,7 @@ async function cmdGenerateGet(taskId, jsonMode) {
924
1328
  }
925
1329
  async function cmdGenerateWait(opts) {
926
1330
  const cfg = requireApiKey();
927
- const client = createClient(cfg);
1331
+ const client = createCliClient(cfg);
928
1332
  await finishAndSave(client, opts.taskId, {
929
1333
  json: opts.json,
930
1334
  out: opts.out,
@@ -934,9 +1338,9 @@ async function cmdGenerateWait(opts) {
934
1338
  }
935
1339
  async function cmdGenerateCancel(taskId, jsonMode) {
936
1340
  const cfg = requireApiKey();
937
- const client = createClient(cfg);
1341
+ const client = createCliClient(cfg);
938
1342
  const kind = inferJobKind(taskId);
939
- const res = kind === "image" ? await client.cancelImageGeneration(taskId) : kind === "video" ? await client.cancelVideoGeneration(taskId) : kind === "upscale" ? await client.cancelUpscaleGeneration(taskId) : kind === "mesh" ? await client.cancelMeshGeneration(taskId) : kind === "switchx" ? await client.cancelSwitchxGeneration(taskId) : null;
1343
+ const res = kind === "image" ? await client.cancelImageGeneration(taskId) : kind === "video" ? await client.cancelVideoGeneration(taskId) : kind === "upscale" ? await client.cancelUpscaleGeneration(taskId) : kind === "mesh" ? await client.cancelMeshGeneration(taskId) : kind === "switchx" ? await client.cancelSwitchxGeneration(taskId) : kind === "audio" ? await client.cancelAudioGeneration(taskId) : null;
940
1344
  if (!res) {
941
1345
  throw new Error(`\u043D\u0435 \u0443\u043C\u0435\u044E \u043E\u0442\u043C\u0435\u043D\u044F\u0442\u044C \u044D\u0442\u043E\u0442 \u0442\u0438\u043F \u0437\u0430\u0434\u0430\u0447\u0438 (${kind || "unknown"})`);
942
1346
  }
@@ -945,12 +1349,12 @@ async function cmdGenerateCancel(taskId, jsonMode) {
945
1349
  }
946
1350
  async function cmdGenerateList(opts) {
947
1351
  const cfg = requireApiKey();
948
- const client = createClient(cfg);
1352
+ const client = createCliClient(cfg);
949
1353
  const params = {
950
1354
  limit: opts.limit,
951
1355
  ...opts.cursor ? { cursor: opts.cursor } : {}
952
1356
  };
953
- const res = opts.kind === "video" ? await client.listVideoGenerations(params) : await client.listImageGenerations(params);
1357
+ const res = opts.kind === "video" ? await client.listVideoGenerations(params) : opts.kind === "audio" ? await client.listAudioGenerations(params) : opts.kind === "upscale" ? await client.listUpscaleGenerations(params) : opts.kind === "switchx" ? await client.listSwitchxGenerations(params) : opts.kind === "mesh" ? await client.listMeshGenerations(params) : await client.listImageGenerations(params);
954
1358
  if (!res.ok) fail(res);
955
1359
  const body = asRecord(res.body);
956
1360
  const items = Array.isArray(body.items) ? body.items : [];
@@ -969,8 +1373,8 @@ function mediaHint(body) {
969
1373
  const images = Array.isArray(body.images) ? body.images : [];
970
1374
  const videos = Array.isArray(body.videos) ? body.videos : [];
971
1375
  const urls = [...images, ...videos].map((item) => item && typeof item === "object" ? String(asRecord(item).url || "") : "").filter(Boolean);
972
- const media = Array.isArray(body.media_urls) ? body.media_urls.map((u) => String(u || "")) : [];
973
- return [...urls, ...media].filter(Boolean);
1376
+ const media2 = Array.isArray(body.media_urls) ? body.media_urls.map((u) => String(u || "")) : [];
1377
+ return [...urls, ...media2].filter(Boolean);
974
1378
  }
975
1379
 
976
1380
  // src/library.ts
@@ -979,7 +1383,7 @@ function itemsOf(body) {
979
1383
  }
980
1384
  async function cmdAssetsList(opts) {
981
1385
  const cfg = requireApiKey();
982
- const client = createClient(cfg);
1386
+ const client = createCliClient(cfg);
983
1387
  const res = await client.listAssets({
984
1388
  limit: opts.limit,
985
1389
  ...opts.kind ? { kind: opts.kind } : {},
@@ -1005,7 +1409,7 @@ async function cmdAssetsGet(assetId, json) {
1005
1409
  const id = assetId.trim();
1006
1410
  if (!isAssetId(id)) throw new Error(`\u043D\u0435 \u043F\u043E\u0445\u043E\u0436\u0435 \u043D\u0430 asset id: ${assetId} (\u043E\u0436\u0438\u0434\u0430\u044E ast_\u2026)`);
1007
1411
  const cfg = requireApiKey();
1008
- const client = createClient(cfg);
1412
+ const client = createCliClient(cfg);
1009
1413
  const res = await client.getAsset(id);
1010
1414
  if (!res.ok) fail(res);
1011
1415
  const body = asRecord(res.body);
@@ -1026,7 +1430,7 @@ async function cmdAssetsCopy(opts) {
1026
1430
  throw new Error("\u0443\u043A\u0430\u0436\u0438\u0442\u0435 --project <id> \u0438\u043B\u0438 --personal");
1027
1431
  }
1028
1432
  const cfg = requireApiKey();
1029
- const client = createClient(cfg);
1433
+ const client = createCliClient(cfg);
1030
1434
  const res = await client.copyAsset(
1031
1435
  id,
1032
1436
  opts.personal ? { target: "personal" } : { target: "project", project_id: parseProjectId(String(opts.projectId)) }
@@ -1046,7 +1450,7 @@ async function cmdAssetsCopy(opts) {
1046
1450
  }
1047
1451
  async function cmdProjectsList(opts) {
1048
1452
  const cfg = requireApiKey();
1049
- const client = createClient(cfg);
1453
+ const client = createCliClient(cfg);
1050
1454
  const res = await client.listProjects({
1051
1455
  limit: opts.limit,
1052
1456
  ...opts.cursor ? { cursor: opts.cursor } : {}
@@ -1063,7 +1467,7 @@ async function cmdProjectsList(opts) {
1063
1467
  async function cmdElementsList(opts) {
1064
1468
  const projectId = parseProjectId(opts.projectId);
1065
1469
  const cfg = requireApiKey();
1066
- const client = createClient(cfg);
1470
+ const client = createCliClient(cfg);
1067
1471
  const res = await client.listProjectElements(projectId, {
1068
1472
  limit: opts.limit,
1069
1473
  ...opts.kinds ? { kinds: opts.kinds } : {},
@@ -1100,7 +1504,7 @@ async function cmdElementsCreate(opts) {
1100
1504
  if (!name) throw new Error("\u0443\u043A\u0430\u0436\u0438\u0442\u0435 --name \u0431\u0435\u0437 \u043F\u0443\u0441\u0442\u043E\u0433\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F");
1101
1505
  const projectId = parseProjectId(opts.projectId);
1102
1506
  const cfg = requireApiKey();
1103
- const client = createClient(cfg);
1507
+ const client = createCliClient(cfg);
1104
1508
  let assetId = "";
1105
1509
  let imageUrl = "";
1106
1510
  let kind = String(opts.kind || "").toLowerCase();
@@ -1167,7 +1571,7 @@ function parse(raw) {
1167
1571
  return [Number(m[1]), Number(m[2]), Number(m[3])];
1168
1572
  }
1169
1573
  function cliVersion() {
1170
- return String("0.1.2");
1574
+ return String("0.1.5");
1171
1575
  }
1172
1576
  function updateAvailableMessage(local, latest) {
1173
1577
  return `\u0414\u043E\u0441\u0442\u0443\u043F\u043D\u0430 \u043D\u043E\u0432\u0430\u044F \u0432\u0435\u0440\u0441\u0438\u044F @artillect/cli (${latest}, \u0443 \u0432\u0430\u0441 ${local}).
@@ -1220,6 +1624,228 @@ async function maybeNotifyUpdate() {
1220
1624
  }
1221
1625
  }
1222
1626
 
1627
+ // src/operations.ts
1628
+ function jsonArg(raw, label) {
1629
+ if (!raw) return {};
1630
+ const value = JSON.parse(String(raw));
1631
+ if (!value || typeof value !== "object" || Array.isArray(value))
1632
+ throw new Error(`${label} \u0434\u043E\u043B\u0436\u0435\u043D \u0431\u044B\u0442\u044C JSON-\u043E\u0431\u044A\u0435\u043A\u0442\u043E\u043C`);
1633
+ return value;
1634
+ }
1635
+ async function call(method, path, body) {
1636
+ const res = await publicApiFetch(createCliClient(requireApiKey()).config, method, path, body);
1637
+ if (!res.ok) fail(res);
1638
+ return res.body;
1639
+ }
1640
+ async function cmdApiOperation(operation, args) {
1641
+ const json = Boolean(args.json);
1642
+ let method = "GET";
1643
+ let path = "/api/v1/health";
1644
+ let body;
1645
+ const projectValue = args.project ?? args.id;
1646
+ const project = projectValue ? parseProjectId(String(projectValue)) : void 0;
1647
+ switch (operation) {
1648
+ case "health":
1649
+ path = "/api/v1/health";
1650
+ break;
1651
+ case "feedback":
1652
+ method = "POST";
1653
+ path = "/api/v1/feedback";
1654
+ body = jsonArg(args.body, "--body");
1655
+ break;
1656
+ case "folders":
1657
+ path = "/api/v1/folders";
1658
+ break;
1659
+ case "folder-create":
1660
+ method = "POST";
1661
+ path = "/api/v1/folders";
1662
+ body = {
1663
+ name: args.name,
1664
+ ...args.parentId ? { parent_id: parseProjectId(String(args.parentId)) } : {}
1665
+ };
1666
+ break;
1667
+ case "tags":
1668
+ path = `/api/v1/projects/${project}/tags`;
1669
+ break;
1670
+ case "tag-create":
1671
+ method = "POST";
1672
+ path = `/api/v1/projects/${project}/tags`;
1673
+ body = { name: args.name, ...args.color ? { color: args.color } : {} };
1674
+ break;
1675
+ case "tag-delete":
1676
+ method = "DELETE";
1677
+ path = `/api/v1/projects/${project}/tags/${parseProjectId(String(args.tag))}`;
1678
+ break;
1679
+ case "favorites":
1680
+ path = `/api/v1/projects/${project}/favorites`;
1681
+ break;
1682
+ case "project-generations":
1683
+ path = `/api/v1/projects/${project}/generations`;
1684
+ break;
1685
+ default:
1686
+ throw new Error(`\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430\u044F API-\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F: ${operation}`);
1687
+ }
1688
+ const qs = new URLSearchParams();
1689
+ for (const [key, value] of Object.entries(args)) {
1690
+ if (["json", "body", "name", "color", "parentId", "project", "id", "tag"].includes(key) || value == null || value === false)
1691
+ continue;
1692
+ if (key === "tagIds") qs.set("tag_ids", String(value));
1693
+ else
1694
+ qs.set(
1695
+ key.replace(/[A-Z]/g, (x) => `_${x.toLowerCase()}`),
1696
+ String(value)
1697
+ );
1698
+ }
1699
+ const result = await call(method, qs.size && method === "GET" ? `${path}?${qs}` : path, body);
1700
+ printOrJson(json, result, [JSON.stringify(result)]);
1701
+ }
1702
+ async function cmdChatOperation(operation, args) {
1703
+ const json = Boolean(args.json);
1704
+ const id = args.id != null ? parseProjectId(String(args.id)) : void 0;
1705
+ let method = "GET";
1706
+ let path = "/api/v1/chat/conversations";
1707
+ let body;
1708
+ if (operation === "completion") {
1709
+ method = "POST";
1710
+ path = "/api/v1/chat/completions";
1711
+ body = jsonArg(args.body, "--body");
1712
+ } else if (operation === "send") {
1713
+ method = "POST";
1714
+ path = `/api/v1/chat/conversations/${id}/messages`;
1715
+ body = jsonArg(args.body, "--body");
1716
+ } else if (operation === "create") {
1717
+ method = "POST";
1718
+ body = jsonArg(args.body, "--body");
1719
+ } else if (operation === "messages") {
1720
+ path = `/api/v1/chat/conversations/${id}/messages`;
1721
+ const query = new URLSearchParams();
1722
+ if (args.limit) query.set("limit", String(args.limit));
1723
+ if (args.cursor) query.set("cursor", String(args.cursor));
1724
+ if (query.size) path += `?${query}`;
1725
+ } else if (operation === "delete") {
1726
+ method = "DELETE";
1727
+ path = `/api/v1/chat/conversations/${id}`;
1728
+ }
1729
+ const result = await call(method, path, body);
1730
+ printOrJson(json, result, [JSON.stringify(result)]);
1731
+ }
1732
+ async function cmdProjectOperation(operation, args) {
1733
+ const json = Boolean(args.json);
1734
+ const client = createCliClient(requireApiKey());
1735
+ const id = args.id == null ? void 0 : parseProjectId(String(args.id));
1736
+ let result;
1737
+ if (operation === "list")
1738
+ result = await client.listProjects({
1739
+ limit: parseLimit(args.limit, 50),
1740
+ cursor: args.cursor
1741
+ });
1742
+ else if (operation === "get") result = await call("GET", `/api/v1/projects/${id}`);
1743
+ else if (operation === "create")
1744
+ result = await call("POST", "/api/v1/projects", jsonArg(args.body, "--body"));
1745
+ else if (operation === "update")
1746
+ result = await call("PATCH", `/api/v1/projects/${id}`, jsonArg(args.body, "--body"));
1747
+ else if (operation === "delete") result = await call("DELETE", `/api/v1/projects/${id}`);
1748
+ else if (operation === "roles") result = await call("GET", "/api/v1/projects/roles");
1749
+ else if (operation === "members") result = await call("GET", `/api/v1/projects/${id}/members`);
1750
+ else if (operation === "invite")
1751
+ result = await call("POST", `/api/v1/projects/${id}/members`, jsonArg(args.body, "--body"));
1752
+ else if (operation === "update-member")
1753
+ result = await call(
1754
+ "PATCH",
1755
+ `/api/v1/projects/${id}/members/${args.user}`,
1756
+ jsonArg(args.body, "--body")
1757
+ );
1758
+ else if (operation === "remove-member")
1759
+ result = await call("DELETE", `/api/v1/projects/${id}/members/${args.user}`);
1760
+ else if (operation === "leave")
1761
+ result = await call("DELETE", `/api/v1/projects/${id}/members/me`);
1762
+ else if (operation === "analytics" || operation === "billing")
1763
+ result = await call("GET", `/api/v1/projects/${id}/${operation}`);
1764
+ else throw new Error(`\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430\u044F project-\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F: ${operation}`);
1765
+ const payload = result && typeof result === "object" && "ok" in result ? result.body ?? result : result;
1766
+ printOrJson(json, payload, [JSON.stringify(payload)]);
1767
+ }
1768
+ async function cmdWebhookOperation(operation, args) {
1769
+ const json = Boolean(args.json);
1770
+ const client = createCliClient(requireApiKey());
1771
+ let result;
1772
+ if (operation === "get") result = await client.getWebhook();
1773
+ else if (operation === "upsert")
1774
+ result = await client.upsertWebhook({
1775
+ url: String(args.url),
1776
+ include_studio: Boolean(args.includeStudio)
1777
+ });
1778
+ else if (operation === "delete") result = await client.deleteWebhook();
1779
+ else if (operation === "rotate") result = await client.rotateWebhookSecret();
1780
+ else if (operation === "deliveries")
1781
+ result = await client.listWebhookDeliveries({
1782
+ limit: parseLimit(args.limit, 50),
1783
+ cursor: args.cursor
1784
+ });
1785
+ else if (operation === "delivery") result = await client.getWebhookDelivery(String(args.id));
1786
+ else throw new Error(`\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430\u044F webhook-\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F: ${operation}`);
1787
+ if (!result.ok) fail(result);
1788
+ printOrJson(json, result.body, [JSON.stringify(result.body)]);
1789
+ }
1790
+ async function cmdLibraryOperation(operation, args) {
1791
+ const json = Boolean(args.json);
1792
+ const project = parseProjectId(String(args.project));
1793
+ const generation2 = args.generation == null ? "" : encodeURIComponent(String(args.generation));
1794
+ const element = args.element == null ? "" : encodeURIComponent(String(args.element));
1795
+ let method = "POST";
1796
+ let path = `/api/v1/projects/${project}/generations/${generation2}`;
1797
+ let body;
1798
+ switch (operation) {
1799
+ case "generation-tags":
1800
+ path += "/tags";
1801
+ body = jsonArg(args.body, "--body");
1802
+ break;
1803
+ case "generation-like":
1804
+ path += "/likes";
1805
+ body = jsonArg(args.body, "--body");
1806
+ break;
1807
+ case "generation-copy":
1808
+ path += "/copy";
1809
+ body = { project_id: parseProjectId(String(args.destination)) };
1810
+ break;
1811
+ case "generation-move":
1812
+ method = "PATCH";
1813
+ body = { project_id: parseProjectId(String(args.destination)) };
1814
+ break;
1815
+ case "generation-delete":
1816
+ method = "DELETE";
1817
+ break;
1818
+ case "element-update":
1819
+ method = "PATCH";
1820
+ path = `/api/v1/projects/${project}/elements/${element}`;
1821
+ body = jsonArg(args.body, "--body");
1822
+ break;
1823
+ case "element-delete":
1824
+ method = "DELETE";
1825
+ path = `/api/v1/projects/${project}/elements/${element}`;
1826
+ break;
1827
+ case "element-reorder":
1828
+ path = `/api/v1/projects/${project}/elements/reorder`;
1829
+ body = jsonArg(args.body, "--body");
1830
+ break;
1831
+ case "media-edit":
1832
+ path = "/api/v1/media/operations";
1833
+ body = jsonArg(args.body, "--body");
1834
+ break;
1835
+ case "media-get":
1836
+ method = "GET";
1837
+ path = `/api/v1/media/operations/${encodeURIComponent(String(args.id))}`;
1838
+ break;
1839
+ case "media-cancel":
1840
+ path = `/api/v1/media/operations/${encodeURIComponent(String(args.id))}/cancel`;
1841
+ break;
1842
+ default:
1843
+ throw new Error(`\u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430\u044F library-\u043E\u043F\u0435\u0440\u0430\u0446\u0438\u044F: ${operation}`);
1844
+ }
1845
+ const result = await call(method, path, body);
1846
+ printOrJson(json, result, [JSON.stringify(result)]);
1847
+ }
1848
+
1223
1849
  // src/index.ts
1224
1850
  var program = new Command();
1225
1851
  program.name("artillect").description("Artillect CLI \u2014 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F \u043A\u0430\u0440\u0442\u0438\u043D\u043E\u043A \u0438 \u0432\u0438\u0434\u0435\u043E \u0438\u0437 \u0442\u0435\u0440\u043C\u0438\u043D\u0430\u043B\u0430.").version(cliVersion());
@@ -1236,6 +1862,8 @@ auth.command("status").description("\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u
1236
1862
  program.command("balance").description("\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0431\u0430\u043B\u0430\u043D\u0441 \u0442\u043E\u043A\u0435\u043D\u043E\u0432").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (opts) => {
1237
1863
  await cmdBalance(Boolean(opts.json));
1238
1864
  });
1865
+ program.command("health").description("\u041F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u043E\u0441\u0442\u044C Public API").option("--json").action((opts) => cmdApiOperation("health", opts));
1866
+ program.command("feedback").description("\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C feedback \u0430\u0433\u0435\u043D\u0442\u0441\u043A\u043E\u0433\u043E/CLI \u0441\u0446\u0435\u043D\u0430\u0440\u0438\u044F").requiredOption("--body <json>", "JSON-\u0442\u0435\u043B\u043E feedback").option("--json").action((opts) => cmdApiOperation("feedback", opts));
1239
1867
  var models = program.command("models").description("\u041A\u0430\u0442\u0430\u043B\u043E\u0433 \u043C\u043E\u0434\u0435\u043B\u0435\u0439 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430");
1240
1868
  models.command("list").description("\u0421\u043F\u0438\u0441\u043E\u043A \u043C\u043E\u0434\u0435\u043B\u0435\u0439").option("-k, --kind <kind>", "images | video | chat | audio | upscale | mesh").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (opts) => {
1241
1869
  await cmdModels(opts.kind, Boolean(opts.json));
@@ -1243,15 +1871,19 @@ models.command("list").description("\u0421\u043F\u0438\u0441\u043E\u043A \u043C\
1243
1871
  models.command("get").description("\u041F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u044B \u043E\u0434\u043D\u043E\u0439 \u043C\u043E\u0434\u0435\u043B\u0438").argument("<slug>", "\u0441\u043B\u0430\u0433, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 gpt-image-2").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (slug, opts) => {
1244
1872
  await cmdModelsGet(slug, Boolean(opts.json));
1245
1873
  });
1246
- program.command("upload").description("\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u0432 storage \u0438 \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C ast_\u2026").argument("<file>", "\u043F\u0443\u0442\u044C \u043A \u0444\u0430\u0439\u043B\u0443").option("--project <id>", "\u043F\u043E\u043B\u043E\u0436\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u0432 storage \u043F\u0440\u043E\u0435\u043A\u0442\u0430").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (file, opts) => {
1247
- await cmdUpload({
1248
- filePath: file,
1249
- projectId: opts.project,
1250
- json: Boolean(opts.json)
1251
- });
1252
- });
1253
- program.command("estimate").description("\u041E\u0446\u0435\u043D\u0438\u0442\u044C \u0446\u0435\u043D\u0443 \u0431\u0435\u0437 \u0441\u043F\u0438\u0441\u0430\u043D\u0438\u044F").argument("<type>", "image | video").requiredOption("-p, --prompt <text>", "\u043F\u0440\u043E\u043C\u043F\u0442").option("-m, --model <slug>", "\u0441\u043B\u0430\u0433 \u043C\u043E\u0434\u0435\u043B\u0438").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (type, opts) => {
1254
- const kind = type === "video" ? "video" : type === "image" ? "image" : null;
1874
+ program.command("upload").description("\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u0432 storage \u0438 \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C ast_\u2026").argument("[file]", "\u043F\u0443\u0442\u044C \u043A \u0444\u0430\u0439\u043B\u0443").option("--url <https>", "\u043F\u0443\u0431\u043B\u0438\u0447\u043D\u044B\u0439 URL \u0434\u043B\u044F \u0437\u0435\u0440\u043A\u0430\u043B\u0438\u0440\u043E\u0432\u0430\u043D\u0438\u044F \u0432 storage").option("--filename <name>", "\u0438\u043C\u044F \u0444\u0430\u0439\u043B\u0430 \u0434\u043B\u044F --url").option("--project <id>", "\u043F\u043E\u043B\u043E\u0436\u0438\u0442\u044C \u0444\u0430\u0439\u043B \u0432 storage \u043F\u0440\u043E\u0435\u043A\u0442\u0430").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(
1875
+ async (file, opts) => {
1876
+ await cmdUpload({
1877
+ filePath: file,
1878
+ url: opts.url,
1879
+ filename: opts.filename,
1880
+ projectId: opts.project,
1881
+ json: Boolean(opts.json)
1882
+ });
1883
+ }
1884
+ );
1885
+ program.command("estimate").description("\u041E\u0446\u0435\u043D\u0438\u0442\u044C \u0446\u0435\u043D\u0443 \u0431\u0435\u0437 \u0441\u043F\u0438\u0441\u0430\u043D\u0438\u044F").argument("<type>", "image | video | audio | mesh | upscale | switchx | chat").option("-p, --prompt <text>", "\u043F\u0440\u043E\u043C\u043F\u0442 (\u0434\u043B\u044F Wan 3 ref2v \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u044B\u043C)").option("-m, --model <slug>", "\u0441\u043B\u0430\u0433 \u043C\u043E\u0434\u0435\u043B\u0438").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (type, opts) => {
1886
+ const kind = ["image", "video", "audio", "mesh", "upscale", "switchx", "chat"].includes(type) ? type : null;
1255
1887
  if (!kind) throw new Error("type: image \u0438\u043B\u0438 video");
1256
1888
  await cmdEstimate({
1257
1889
  type: kind,
@@ -1261,12 +1893,61 @@ program.command("estimate").description("\u041E\u0446\u0435\u043D\u0438\u0442\u0
1261
1893
  });
1262
1894
  });
1263
1895
  var generate = program.command("generate").description("\u0417\u0430\u043F\u0443\u0441\u0442\u0438\u0442\u044C \u0438\u043B\u0438 \u0441\u043C\u043E\u0442\u0440\u0435\u0442\u044C \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044E");
1264
- generate.command("image").description("\u041A\u0430\u0440\u0442\u0438\u043D\u043A\u0430 \u043F\u043E \u0442\u0435\u043A\u0441\u0442\u0443 \u0438\u043B\u0438 \u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u043E \u0440\u0435\u0444\u0435\u0440\u0435\u043D\u0441\u0430\u043C").requiredOption("-p, --prompt <text>", "\u043F\u0440\u043E\u043C\u043F\u0442").option("-m, --model <slug>", "\u0441\u043B\u0430\u0433 \u043C\u043E\u0434\u0435\u043B\u0438 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E gpt-image-2)").option("-i, --input <file...>", "\u0440\u0435\u0444\u0435\u0440\u0435\u043D\u0441\u044B: \u0444\u0430\u0439\u043B, url \u0438\u043B\u0438 ast_\u2026").option("--project <id>", "\u043F\u0440\u043E\u0435\u043A\u0442 (\u0434\u043B\u044F @\u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432 \u0438 \u043B\u0435\u043D\u0442\u044B)").option("-w, --wait", "\u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0438 \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442", false).option("--wait-timeout <duration>", "\u043B\u0438\u043C\u0438\u0442 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 10m", "20m").option("-o, --out <dir>", "\u043F\u0430\u043F\u043A\u0430 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432", ".").option("--open", "\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0444\u0430\u0439\u043B \u043F\u043E\u0441\u043B\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F", false).option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).addHelpText(
1896
+ generate.command("audio").description("\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043C\u0443\u0437\u044B\u043A\u0443 Suno").requiredOption("-p, --prompt <text>", "\u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u0438\u043B\u0438 lyrics").option("-m, --model <slug>", "\u0430\u0443\u0434\u0438\u043E\u043C\u043E\u0434\u0435\u043B\u044C").option("--style <text>", "\u0436\u0430\u043D\u0440/\u0441\u0442\u0438\u043B\u044C").option("--title <text>", "\u043D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u0442\u0440\u0435\u043A\u0430").option("--custom-mode <boolean>", "prompt \u0441\u043E\u0434\u0435\u0440\u0436\u0438\u0442 lyrics").option("--instrumental <boolean>", "\u0431\u0435\u0437 \u0432\u043E\u043A\u0430\u043B\u0430").option("--negative-tags <text>", "\u0441\u0442\u0438\u043B\u0438, \u043A\u043E\u0442\u043E\u0440\u044B\u0445 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044C").option("--vocal-gender <m|f>", "\u043F\u043E\u043B \u0432\u043E\u043A\u0430\u043B\u0430").option("--style-weight <n>", "\u0432\u0435\u0441 \u0441\u0442\u0438\u043B\u044F").option("--weirdness-constraint <n>", "weirdness").option("--audio-weight <n>", "\u0432\u0435\u0441 \u0430\u0443\u0434\u0438\u043E").option("--project <id>", "\u043F\u0440\u043E\u0435\u043A\u0442").option("--billing-source <source>", "cli | mcp | public_api | studio").option("--tag-id <ids>", "tag ids \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E").option("--idempotency-key <key>", "\u043A\u043B\u044E\u0447 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0433\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u0430 submit").option("--extra <json>", "\u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u043E\u043B\u044F \u0442\u0435\u043B\u0430 API").option("-w, --wait", "\u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438", false).option("--wait-timeout <duration>", "\u043B\u0438\u043C\u0438\u0442 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F", "20m").option("-o, --out <dir>", "\u043F\u0430\u043F\u043A\u0430 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432", ".").option("--open", "\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0444\u0430\u0439\u043B", false).option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (opts) => {
1897
+ await cmdGenerateAudio({
1898
+ prompt: String(opts.prompt),
1899
+ model: opts.model,
1900
+ style: opts.style,
1901
+ title: opts.title,
1902
+ customMode: opts.customMode == null ? void 0 : opts.customMode !== "false",
1903
+ instrumental: opts.instrumental == null ? void 0 : opts.instrumental !== "false",
1904
+ negativeTags: opts.negativeTags,
1905
+ vocalGender: opts.vocalGender,
1906
+ styleWeight: opts.styleWeight,
1907
+ weirdnessConstraint: opts.weirdnessConstraint,
1908
+ audioWeight: opts.audioWeight,
1909
+ projectId: opts.project,
1910
+ billingSource: opts.billingSource,
1911
+ tagIds: parseTagIds(opts.tagId),
1912
+ idempotencyKey: opts.idempotencyKey,
1913
+ extra: opts.extra,
1914
+ wait: Boolean(opts.wait),
1915
+ json: Boolean(opts.json),
1916
+ out: String(opts.out || "."),
1917
+ open: Boolean(opts.open),
1918
+ waitTimeout: opts.waitTimeout
1919
+ });
1920
+ });
1921
+ generate.command("switchx").description("SwitchX compositing").requiredOption("--source <ref>", "\u0438\u0441\u0445\u043E\u0434\u043D\u043E\u0435 \u0432\u0438\u0434\u0435\u043E/\u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435").option("-m, --model <slug>", "\u043C\u043E\u0434\u0435\u043B\u044C").option("--generation-type <type>", "\u0442\u0438\u043F \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438").option("--reference-image <url>", "\u0440\u0435\u0444\u0435\u0440\u0435\u043D\u0441\u043D\u043E\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435").option("--alpha-mode <mode>", "\u0440\u0435\u0436\u0438\u043C alpha").option("--alpha-url <url>", "alpha URL").option("-p, --prompt <text>", "\u043F\u0440\u043E\u043C\u043F\u0442").option("--max-resolution <n>", "\u043C\u0430\u043A\u0441\u0438\u043C\u0430\u043B\u044C\u043D\u043E\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043D\u0438\u0435").option("--frame-count <n>", "\u0447\u0438\u0441\u043B\u043E \u043A\u0430\u0434\u0440\u043E\u0432").option("--project <id>", "\u043F\u0440\u043E\u0435\u043A\u0442").option("--billing-source <source>", "cli | mcp | public_api | studio").option("--tag-id <ids>", "tag ids \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E").option("--idempotency-key <key>", "\u043A\u043B\u044E\u0447 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0433\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u0430 submit").option("--extra <json>", "\u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u043E\u043B\u044F \u0442\u0435\u043B\u0430 API").option("-w, --wait", "\u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438", false).option("--wait-timeout <duration>", "\u043B\u0438\u043C\u0438\u0442 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F", "20m").option("-o, --out <dir>", "\u043F\u0430\u043F\u043A\u0430 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432", ".").option("--open", "\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0444\u0430\u0439\u043B", false).option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(
1922
+ async (opts) => cmdGenerateSwitchx({
1923
+ source: String(opts.source),
1924
+ model: opts.model,
1925
+ generationType: opts.generationType,
1926
+ referenceImage: opts.referenceImage,
1927
+ alphaMode: opts.alphaMode,
1928
+ alphaUrl: opts.alphaUrl,
1929
+ prompt: opts.prompt,
1930
+ maxResolution: opts.maxResolution,
1931
+ frameCount: opts.frameCount,
1932
+ projectId: opts.project,
1933
+ billingSource: opts.billingSource,
1934
+ tagIds: parseTagIds(opts.tagId),
1935
+ idempotencyKey: opts.idempotencyKey,
1936
+ extra: opts.extra,
1937
+ wait: Boolean(opts.wait),
1938
+ json: Boolean(opts.json),
1939
+ out: String(opts.out || "."),
1940
+ open: Boolean(opts.open),
1941
+ waitTimeout: opts.waitTimeout
1942
+ })
1943
+ );
1944
+ generate.command("image").description("\u041A\u0430\u0440\u0442\u0438\u043D\u043A\u0430 \u043F\u043E \u0442\u0435\u043A\u0441\u0442\u0443 \u0438\u043B\u0438 \u043F\u0440\u0430\u0432\u043A\u0430 \u043F\u043E \u0440\u0435\u0444\u0435\u0440\u0435\u043D\u0441\u0430\u043C").option("-p, --prompt <text>", "\u043F\u0440\u043E\u043C\u043F\u0442 (\u0434\u043B\u044F \u043D\u0435\u043A\u043E\u0442\u043E\u0440\u044B\u0445 image-to-image \u043C\u043E\u0434\u0435\u043B\u0435\u0439 \u043D\u0435 \u043D\u0443\u0436\u0435\u043D)").option("-m, --model <slug>", "\u0441\u043B\u0430\u0433 \u043C\u043E\u0434\u0435\u043B\u0438 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E gpt-image-2)").option("-i, --input <file...>", "\u0440\u0435\u0444\u0435\u0440\u0435\u043D\u0441\u044B: \u0444\u0430\u0439\u043B, url \u0438\u043B\u0438 ast_\u2026").option("--project <id>", "\u043F\u0440\u043E\u0435\u043A\u0442 (\u0434\u043B\u044F @\u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432 \u0438 \u043B\u0435\u043D\u0442\u044B)").option("--aspect-ratio <ratio>", "\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 1:1, 16:9").option("--resolution <size>", "\u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 1K, 2K, 4K").option("--quality <value>", "\u043A\u0430\u0447\u0435\u0441\u0442\u0432\u043E, \u0435\u0441\u043B\u0438 \u043C\u043E\u0434\u0435\u043B\u044C \u0435\u0433\u043E \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442").option("--num-images <n>", "\u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439 (1\u201310, \u0434\u043B\u044F \u043F\u0440\u0438\u043C\u0435\u0440\u043E\u0447\u043D\u043E\u0439 1\u20134)").option("--output-format <format>", "jpeg | png | webp, \u0435\u0441\u043B\u0438 \u043C\u043E\u0434\u0435\u043B\u044C \u043F\u0440\u0438\u043D\u0438\u043C\u0430\u0435\u0442").option("--sync-mode <boolean>", "\u0432\u0435\u0440\u043D\u0443\u0442\u044C data URI \u0432\u043C\u0435\u0441\u0442\u043E persisted URL").option("--billing-source <source>", "cli | mcp | public_api | studio").option("--tag-id <ids>", "tag ids \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E").option("--element-name <names...>", "Element @names \u043F\u0440\u043E\u0435\u043A\u0442\u0430").option("--idempotency-key <key>", "\u043A\u043B\u044E\u0447 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0433\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u0430 submit").option("--extra <json>", "\u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u043E\u043B\u044F \u0442\u0435\u043B\u0430 API (JSON-\u043E\u0431\u044A\u0435\u043A\u0442)").option("-w, --wait", "\u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0438 \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442", false).option("--wait-timeout <duration>", "\u043B\u0438\u043C\u0438\u0442 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 10m", "20m").option("-o, --out <dir>", "\u043F\u0430\u043F\u043A\u0430 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432", ".").option("--open", "\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0444\u0430\u0439\u043B \u043F\u043E\u0441\u043B\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F", false).option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).addHelpText(
1265
1945
  "after",
1266
1946
  `
1267
1947
  \u041F\u0440\u0438\u043C\u0435\u0440\u044B:
1268
1948
  $ artillect generate image -p "\u043A\u043E\u0442 \u0432 \u043A\u043E\u0441\u043C\u043E\u0441\u0435" --wait --open
1269
1949
  $ artillect generate image -m seedream-5-pro -p "\u043A\u043E\u0442" -i ./ref.png --wait
1950
+ $ artillect generate image -m google-virtual-try-on -i ./person.jpg -i ./jacket.jpg --num-images 2 --wait
1270
1951
  `
1271
1952
  ).action(
1272
1953
  async (opts) => {
@@ -1275,6 +1956,17 @@ generate.command("image").description("\u041A\u0430\u0440\u0442\u0438\u043D\u043
1275
1956
  model: opts.model,
1276
1957
  input: opts.input,
1277
1958
  projectId: opts.project,
1959
+ aspectRatio: opts.aspectRatio,
1960
+ resolution: opts.resolution,
1961
+ quality: opts.quality,
1962
+ numImages: opts.numImages,
1963
+ outputFormat: opts.outputFormat,
1964
+ syncMode: opts.syncMode == null ? void 0 : opts.syncMode !== "false",
1965
+ billingSource: opts.billingSource,
1966
+ tagIds: parseTagIds(opts.tagId),
1967
+ elementNames: opts.elementName,
1968
+ idempotencyKey: opts.idempotencyKey,
1969
+ extra: opts.extra,
1278
1970
  wait: Boolean(opts.wait),
1279
1971
  waitTimeout: opts.waitTimeout,
1280
1972
  json: Boolean(opts.json),
@@ -1283,21 +1975,76 @@ generate.command("image").description("\u041A\u0430\u0440\u0442\u0438\u043D\u043
1283
1975
  });
1284
1976
  }
1285
1977
  );
1286
- generate.command("video").description("\u0412\u0438\u0434\u0435\u043E \u043F\u043E \u0442\u0435\u043A\u0441\u0442\u0443 \u0438\u043B\u0438 \u043A\u0430\u0434\u0440\u0430\u043C").argument("[model]", "\u0441\u043B\u0430\u0433 \u0432\u0438\u0434\u0435\u043E\u043C\u043E\u0434\u0435\u043B\u0438 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E kling-3-turbo)").requiredOption("-p, --prompt <text>", "\u043F\u0440\u043E\u043C\u043F\u0442").option("-m, --model <slug>", "\u0441\u043B\u0430\u0433 \u043C\u043E\u0434\u0435\u043B\u0438 (\u0435\u0441\u043B\u0438 \u043D\u0435 \u0443\u043A\u0430\u0437\u0430\u043D \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u043C)").option("--start-image <ref>", "\u0441\u0442\u0430\u0440\u0442\u043E\u0432\u044B\u0439 \u043A\u0430\u0434\u0440: \u0444\u0430\u0439\u043B, url \u0438\u043B\u0438 ast_\u2026").option("--end-image <ref>", "\u0444\u0438\u043D\u0430\u043B\u044C\u043D\u044B\u0439 \u043A\u0430\u0434\u0440: \u0444\u0430\u0439\u043B, url \u0438\u043B\u0438 ast_\u2026").option("--project <id>", "\u043F\u0440\u043E\u0435\u043A\u0442 (\u043D\u0443\u0436\u0435\u043D \u0434\u043B\u044F @\u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432)").option("-w, --wait", "\u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0438 \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442", false).option("--wait-timeout <duration>", "\u043B\u0438\u043C\u0438\u0442 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 10m", "20m").option("-o, --out <dir>", "\u043F\u0430\u043F\u043A\u0430 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432", ".").option("--open", "\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0444\u0430\u0439\u043B \u043F\u043E\u0441\u043B\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F", false).option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).addHelpText(
1978
+ generate.command("mesh").description("\u0421\u043E\u0437\u0434\u0430\u0442\u044C 3D-\u043C\u043E\u0434\u0435\u043B\u044C Meshy").option(
1979
+ "-m, --model <slug>",
1980
+ "meshy-v6-t2m | meshy-v6-i2m | meshy-v7-t2m | meshy-v7-i2m | meshy-v7-multi-i2m"
1981
+ ).option("--task <task>", "t2m | i2m | multi-i2m").option("-p, --prompt <text>", "\u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u043E\u0431\u044A\u0435\u043A\u0442\u0430; \u0434\u043B\u044F Meshy 7 \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C 600 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432").option(
1982
+ "-i, --image <file-or-url>",
1983
+ "\u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435: \u0444\u0430\u0439\u043B, URL \u0438\u043B\u0438 ast_\u2026; \u043C\u043E\u0436\u043D\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u0438\u0442\u044C \u0434\u043E 4 \u0440\u0430\u0437",
1984
+ (value, previous = []) => [...previous, value],
1985
+ []
1986
+ ).option("--mode <mode>", "preview | full; Meshy 7 text-to-3D").option("--model-type <type>", "standard | lowpoly | smart-topology; Meshy 7").option("--topology <topology>", "quad | triangle").option("--target-polycount <n>", "100\u2013300000; smart-topology \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C 15000").option("--symmetry-mode <mode>", "off | auto | on").option("--should-remesh <boolean>", "true | false").option("--should-texture <boolean>", "true | false").option("--enable-pbr <boolean>", "true | false").option("--pose-mode <mode>", "a-pose | t-pose | none").option("--enable-prompt-expansion <boolean>", "true | false").option("--texture-prompt <text>", "\u043F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430 \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u0443\u0440\u044B").option("--texture-image <file-or-url>", "\u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0434\u043B\u044F \u0442\u0435\u043A\u0441\u0442\u0443\u0440\u044B").option("--seed <n>", "seed \u0434\u043B\u044F text-to-3D").option("--enable-rigging <boolean>", "true | false").option("--rigging-height <meters>", "\u0432\u044B\u0441\u043E\u0442\u0430 \u043F\u0435\u0440\u0441\u043E\u043D\u0430\u0436\u0430, \u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 1.7").option("--enable-animation <boolean>", "true | false; \u0442\u0440\u0435\u0431\u0443\u0435\u0442 rigging").option("--animation-action-id <n>", "ID \u0430\u043D\u0438\u043C\u0430\u0446\u0438\u0438 0\u2013696").option("--enable-safety-checker <boolean>", "true | false").option("--ultra-mode <boolean>", "true | false; Meshy 7 standard + textured").option("--billing-source <source>", "cli | mcp | public_api | studio").option("--tag-id <ids>", "tag ids \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E").option("--idempotency-key <key>", "\u043A\u043B\u044E\u0447 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0433\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u0430 submit").option("--extra <json>", "\u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u043E\u043B\u044F \u0442\u0435\u043B\u0430 API (JSON-\u043E\u0431\u044A\u0435\u043A\u0442)").option("--project <id>", "\u043F\u0440\u043E\u0435\u043A\u0442 \u0434\u043B\u044F \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u044B\u0445 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0439").option("-w, --wait", "\u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0438 \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442", false).option("--wait-timeout <duration>", "\u043B\u0438\u043C\u0438\u0442 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 10m", "20m").option("-o, --out <dir>", "\u043F\u0430\u043F\u043A\u0430 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432", ".").option("--open", "\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0444\u0430\u0439\u043B \u043F\u043E\u0441\u043B\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F", false).option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(
1987
+ async (opts) => {
1988
+ await cmdGenerateMesh({
1989
+ ...opts,
1990
+ projectId: opts.project,
1991
+ wait: Boolean(opts.wait),
1992
+ json: Boolean(opts.json),
1993
+ out: opts.out,
1994
+ open: Boolean(opts.open),
1995
+ billingSource: opts.billingSource,
1996
+ tagIds: parseTagIds(opts.tagId),
1997
+ idempotencyKey: opts.idempotencyKey
1998
+ });
1999
+ }
2000
+ );
2001
+ generate.command("video").description("\u0412\u0438\u0434\u0435\u043E \u043F\u043E \u0442\u0435\u043A\u0441\u0442\u0443 \u0438\u043B\u0438 \u043A\u0430\u0434\u0440\u0430\u043C").argument("[model]", "\u0441\u043B\u0430\u0433 \u0432\u0438\u0434\u0435\u043E\u043C\u043E\u0434\u0435\u043B\u0438 (\u043F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E kling-3-turbo)").option("-p, --prompt <text>", "\u043F\u0440\u043E\u043C\u043F\u0442 (\u0434\u043B\u044F Wan 3 ref2v \u043C\u043E\u0436\u0435\u0442 \u0431\u044B\u0442\u044C \u043F\u0443\u0441\u0442\u044B\u043C)").option("-m, --model <slug>", "\u0441\u043B\u0430\u0433 \u043C\u043E\u0434\u0435\u043B\u0438 (\u0435\u0441\u043B\u0438 \u043D\u0435 \u0443\u043A\u0430\u0437\u0430\u043D \u0430\u0440\u0433\u0443\u043C\u0435\u043D\u0442\u043E\u043C)").option("--start-image <ref>", "\u0441\u0442\u0430\u0440\u0442\u043E\u0432\u044B\u0439 \u043A\u0430\u0434\u0440: \u0444\u0430\u0439\u043B, url \u0438\u043B\u0438 ast_\u2026").option("--end-image <ref>", "\u0444\u0438\u043D\u0430\u043B\u044C\u043D\u044B\u0439 \u043A\u0430\u0434\u0440: \u0444\u0430\u0439\u043B, url \u0438\u043B\u0438 ast_\u2026").option("--source-video <ref>", "\u0438\u0441\u0445\u043E\u0434\u043D\u043E\u0435 \u0432\u0438\u0434\u0435\u043E \u0434\u043B\u044F edit/v2v/motion").option("--audio-url <ref>", "\u0430\u0443\u0434\u0438\u043E \u0434\u043B\u044F avatar/lipsync").option("--motion-video <ref>", "motion reference video").option("--element-name <names...>", "Element @names \u043F\u0440\u043E\u0435\u043A\u0442\u0430").option("--kling-mode <mode>", "Kling mode, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 std/pro").option("--shot-type <type>", "single | multi").option("--multi-prompt <json>", "JSON-\u043C\u0430\u0441\u0441\u0438\u0432 multi-prompt").option("--multi-shots <n>", "\u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E shots").option("--keep-audio <boolean>", "\u0441\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C \u0430\u0443\u0434\u0438\u043E \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0430").option("--cfg-scale <n>", "CFG scale").option("--generate-audio <boolean>", "\u0433\u0435\u043D\u0435\u0440\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0430\u0443\u0434\u0438\u043E").option("--billing-source <source>", "cli | mcp | public_api | studio").option("--tag-id <ids>", "tag ids \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E").option("--idempotency-key <key>", "\u043A\u043B\u044E\u0447 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0433\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u0430 submit").option("--duration <n>", "\u0434\u043B\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u044C \u0432 \u0441\u0435\u043A\u0443\u043D\u0434\u0430\u0445").option("--resolution <size>", "480P | 720P | 1080P | \u2026").option("--aspect-ratio <ratio>", "adaptive | 16:9 | 4:3 | 1:1 | 3:4 | 9:16").option("--task <task>", "t2v | i2v | flf2v | \u2026").option("--seedance-mode <mode>", "quality | fast").option("--ref-image <ref...>", "\u0440\u0435\u0444\u0435\u0440\u0435\u043D\u0441-\u043A\u0430\u0440\u0442\u0438\u043D\u043A\u0438: \u0444\u0430\u0439\u043B, url \u0438\u043B\u0438 ast_\u2026").option("--ref-video <ref...>", "\u0440\u0435\u0444\u0435\u0440\u0435\u043D\u0441-\u0432\u0438\u0434\u0435\u043E").option("--ref-audio <ref...>", "\u0440\u0435\u0444\u0435\u0440\u0435\u043D\u0441-\u0430\u0443\u0434\u0438\u043E").option("--ref-file <url>", "\u043F\u0443\u0431\u043B\u0438\u0447\u043D\u044B\u0439 URL \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430 (Wan 3: \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C 1)").option("--ref-link <url>", "\u043F\u0443\u0431\u043B\u0438\u0447\u043D\u0430\u044F \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 (Wan 3: \u043C\u0430\u043A\u0441\u0438\u043C\u0443\u043C 1)").option("--audio <boolean>", "\u0434\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0430\u0443\u0434\u0438\u043E\u0434\u043E\u0440\u043E\u0436\u043A\u0443: true | false").option("--seed <n>", "seed: 0\u20132147483647").option("--nsfw-checker <boolean>", "nsfw_checker: true | false").option("--prompt-expansion-mode <mode>", "MiniMax H3 Max: disabled | balanced | quality").option("--enable-safety-checker <boolean>", "MiniMax H3 Max: \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0430 \u043A\u043E\u043D\u0442\u0435\u043D\u0442\u0430 true | false").option("--sync-mode <boolean>", "MiniMax H3 Max: \u0432\u0435\u0440\u043D\u0443\u0442\u044C base64 \u0432\u043C\u0435\u0441\u0442\u043E CDN URL true | false").option("--extra <json>", "\u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u043E\u043B\u044F \u0442\u0435\u043B\u0430 API (JSON-\u043E\u0431\u044A\u0435\u043A\u0442)").option("--project <id>", "\u043F\u0440\u043E\u0435\u043A\u0442 (\u043D\u0443\u0436\u0435\u043D \u0434\u043B\u044F @\u044D\u043B\u0435\u043C\u0435\u043D\u0442\u043E\u0432)").option("-w, --wait", "\u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0438 \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442", false).option("--wait-timeout <duration>", "\u043B\u0438\u043C\u0438\u0442 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 10m", "20m").option("-o, --out <dir>", "\u043F\u0430\u043F\u043A\u0430 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432", ".").option("--open", "\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0444\u0430\u0439\u043B \u043F\u043E\u0441\u043B\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F", false).option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).addHelpText(
1287
2002
  "after",
1288
2003
  `
1289
2004
  \u041F\u0440\u0438\u043C\u0435\u0440\u044B:
1290
2005
  $ artillect generate video grok-imagine-video -p "\u043A\u043E\u0442 \u0438\u0434\u0451\u0442" --wait --open
1291
2006
  $ artillect generate video kling-3 -p "@Hero \u0438\u0434\u0451\u0442" --project 12 --start-image ast_\u2026 --wait
2007
+ $ artillect generate video seedance-2.5 -p "\u2026" --duration 10 --resolution 1080p --ref-image ./sheet.png --wait
1292
2008
  `
1293
2009
  ).action(
1294
2010
  async (positionalModel, opts) => {
1295
2011
  const model = String(opts.model || positionalModel || "kling-3-turbo").trim();
1296
2012
  await cmdGenerateVideo({
1297
2013
  model,
1298
- prompt: opts.prompt,
2014
+ prompt: opts.prompt ?? "",
1299
2015
  startImage: opts.startImage,
1300
2016
  endImage: opts.endImage,
2017
+ sourceVideoUrl: opts.sourceVideo,
2018
+ audioUrl: opts.audioUrl,
2019
+ motionVideoUrl: opts.motionVideo,
2020
+ elementNames: opts.elementName,
2021
+ klingMode: opts.klingMode,
2022
+ shotType: opts.shotType,
2023
+ multiPrompt: opts.multiPrompt,
2024
+ multiShots: opts.multiShots,
2025
+ keepAudio: opts.keepAudio == null ? void 0 : opts.keepAudio !== "false",
2026
+ cfgScale: opts.cfgScale,
2027
+ generateAudio: opts.generateAudio == null ? void 0 : opts.generateAudio !== "false",
2028
+ billingSource: opts.billingSource,
2029
+ tagIds: parseTagIds(opts.tagId),
2030
+ idempotencyKey: opts.idempotencyKey,
2031
+ duration: opts.duration,
2032
+ resolution: opts.resolution,
2033
+ aspectRatio: opts.aspectRatio,
2034
+ task: opts.task,
2035
+ seedanceMode: opts.seedanceMode,
2036
+ refImage: opts.refImage,
2037
+ refVideo: opts.refVideo,
2038
+ refAudio: opts.refAudio,
2039
+ refFile: opts.refFile,
2040
+ refLink: opts.refLink ? [opts.refLink] : void 0,
2041
+ audio: opts.audio == null ? void 0 : opts.audio !== "false",
2042
+ seed: opts.seed,
2043
+ nsfwChecker: opts.nsfwChecker == null ? void 0 : opts.nsfwChecker !== "false",
2044
+ promptExpansionMode: opts.promptExpansionMode,
2045
+ enableSafetyChecker: opts.enableSafetyChecker == null ? void 0 : opts.enableSafetyChecker !== "false",
2046
+ syncMode: opts.syncMode == null ? void 0 : opts.syncMode !== "false",
2047
+ extra: opts.extra,
1301
2048
  projectId: opts.project,
1302
2049
  wait: Boolean(opts.wait),
1303
2050
  waitTimeout: opts.waitTimeout,
@@ -1307,6 +2054,44 @@ generate.command("video").description("\u0412\u0438\u0434\u0435\u043E \u043F\u04
1307
2054
  });
1308
2055
  }
1309
2056
  );
2057
+ generate.command("upscale").description("\u0423\u0432\u0435\u043B\u0438\u0447\u0438\u0442\u044C \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0438\u043B\u0438 \u0432\u0438\u0434\u0435\u043E").option("-i, --image <file-or-url>", "\u0438\u0441\u0445\u043E\u0434\u043D\u043E\u0435 \u0438\u0437\u043E\u0431\u0440\u0430\u0436\u0435\u043D\u0438\u0435: \u0444\u0430\u0439\u043B, URL \u0438\u043B\u0438 ast_\u2026").option("-v, --video <file-or-url>", "\u0438\u0441\u0445\u043E\u0434\u043D\u043E\u0435 \u0432\u0438\u0434\u0435\u043E: \u0444\u0430\u0439\u043B, URL \u0438\u043B\u0438 ast_\u2026").option("-m, --model <slug>", "\u043C\u043E\u0434\u0435\u043B\u044C: flux-video-upscale | topaz-video | crystal-video").option("--enhancement-model <name>", "Topaz enhancement model").option("--upscale-factor <n>", "\u043A\u043E\u044D\u0444\u0444\u0438\u0446\u0438\u0435\u043D\u0442; FLUX: 1.5\u20133").option("--creativity <0|1>", "FLUX: 0 precise \u0438\u043B\u0438 1 creative").option("-p, --prompt <text>", "FLUX: \u043F\u043E\u0434\u0441\u043A\u0430\u0437\u043A\u0430 \u0434\u043B\u044F creative detail enhancement").option("--safety-tolerance <n>", "FLUX: 0\u20134, \u043C\u0435\u043D\u044C\u0448\u0435 \u2014 \u0441\u0442\u0440\u043E\u0436\u0435").option("--duration <seconds>", "\u0434\u043B\u0438\u0442\u0435\u043B\u044C\u043D\u043E\u0441\u0442\u044C \u0434\u043B\u044F \u0442\u043E\u0447\u043D\u043E\u0439 \u043E\u0446\u0435\u043D\u043A\u0438 \u0446\u0435\u043D\u044B").option("--width <pixels>", "\u0448\u0438\u0440\u0438\u043D\u0430 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0430 \u0434\u043B\u044F \u0442\u043E\u0447\u043D\u043E\u0439 \u043E\u0446\u0435\u043D\u043A\u0438 \u0446\u0435\u043D\u044B").option("--height <pixels>", "\u0432\u044B\u0441\u043E\u0442\u0430 \u0438\u0441\u0445\u043E\u0434\u043D\u0438\u043A\u0430 \u0434\u043B\u044F \u0442\u043E\u0447\u043D\u043E\u0439 \u043E\u0446\u0435\u043D\u043A\u0438 \u0446\u0435\u043D\u044B").option("--output-format <format>", "png | jpg | webp").option("--crop-to-fill <boolean>", "\u043E\u0431\u0440\u0435\u0437\u0430\u0442\u044C \u0434\u043E \u0437\u0430\u043F\u043E\u043B\u043D\u0435\u043D\u0438\u044F").option("--face-enhancement <boolean>", "\u0443\u043B\u0443\u0447\u0448\u0430\u0442\u044C \u043B\u0438\u0446\u0430").option("--face-enhancement-strength <n>", "\u0441\u0438\u043B\u0430 \u0443\u043B\u0443\u0447\u0448\u0435\u043D\u0438\u044F \u043B\u0438\u0446").option("--face-enhancement-creativity <n>", "\u043A\u0440\u0435\u0430\u0442\u0438\u0432\u043D\u043E\u0441\u0442\u044C \u0443\u043B\u0443\u0447\u0448\u0435\u043D\u0438\u044F \u043B\u0438\u0446").option("--billing-source <source>", "cli | mcp | public_api | studio").option("--tag-id <ids>", "tag ids \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u043F\u044F\u0442\u0443\u044E").option("--idempotency-key <key>", "\u043A\u043B\u044E\u0447 \u0431\u0435\u0437\u043E\u043F\u0430\u0441\u043D\u043E\u0433\u043E \u043F\u043E\u0432\u0442\u043E\u0440\u0430 submit").option("--project <id>", "\u043F\u0440\u043E\u0435\u043A\u0442 \u0434\u043B\u044F \u0437\u0430\u0433\u0440\u0443\u0437\u043A\u0438 \u043B\u043E\u043A\u0430\u043B\u044C\u043D\u043E\u0433\u043E \u0444\u0430\u0439\u043B\u0430").option("--extra <json>", "\u0434\u043E\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u044C\u043D\u044B\u0435 \u043F\u043E\u043B\u044F \u0442\u0435\u043B\u0430 API (JSON-\u043E\u0431\u044A\u0435\u043A\u0442)").option("-w, --wait", "\u0434\u043E\u0436\u0434\u0430\u0442\u044C\u0441\u044F \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0438 \u0441\u043A\u0430\u0447\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442", false).option("--wait-timeout <duration>", "\u043B\u0438\u043C\u0438\u0442 \u043E\u0436\u0438\u0434\u0430\u043D\u0438\u044F, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 10m", "20m").option("-o, --out <dir>", "\u043F\u0430\u043F\u043A\u0430 \u0434\u043B\u044F \u0444\u0430\u0439\u043B\u043E\u0432", ".").option("--open", "\u043E\u0442\u043A\u0440\u044B\u0442\u044C \u0444\u0430\u0439\u043B \u043F\u043E\u0441\u043B\u0435 \u0441\u043A\u0430\u0447\u0438\u0432\u0430\u043D\u0438\u044F", false).option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).addHelpText(
2058
+ "after",
2059
+ `
2060
+ \u041F\u0440\u0438\u043C\u0435\u0440:
2061
+ $ artillect generate upscale --model topaz-image --image ./photo.png --wait
2062
+ `
2063
+ ).action(
2064
+ async (opts) => {
2065
+ await cmdGenerateUpscale({
2066
+ model: opts.model,
2067
+ image: opts.image,
2068
+ video: opts.video,
2069
+ enhancementModel: opts.enhancementModel,
2070
+ projectId: opts.project,
2071
+ upscaleFactor: opts.upscaleFactor,
2072
+ creativity: opts.creativity,
2073
+ prompt: opts.prompt,
2074
+ safetyTolerance: opts.safetyTolerance,
2075
+ duration: opts.duration,
2076
+ width: opts.width,
2077
+ height: opts.height,
2078
+ outputFormat: opts.outputFormat,
2079
+ cropToFill: opts.cropToFill == null ? void 0 : opts.cropToFill !== "false",
2080
+ faceEnhancement: opts.faceEnhancement == null ? void 0 : opts.faceEnhancement !== "false",
2081
+ faceEnhancementStrength: opts.faceEnhancementStrength,
2082
+ faceEnhancementCreativity: opts.faceEnhancementCreativity,
2083
+ billingSource: opts.billingSource,
2084
+ tagIds: parseTagIds(opts.tagId),
2085
+ idempotencyKey: opts.idempotencyKey,
2086
+ extra: opts.extra,
2087
+ wait: Boolean(opts.wait),
2088
+ waitTimeout: opts.waitTimeout,
2089
+ json: Boolean(opts.json),
2090
+ out: opts.out,
2091
+ open: Boolean(opts.open)
2092
+ });
2093
+ }
2094
+ );
1310
2095
  generate.command("get").description("\u0421\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u0434\u0430\u0447\u0438").argument("<task_id>", "id \u0438\u0437 generate").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (taskId, opts) => {
1311
2096
  await cmdGenerateGet(taskId, Boolean(opts.json));
1312
2097
  });
@@ -1324,8 +2109,9 @@ generate.command("wait").description("\u0414\u043E\u0436\u0434\u0430\u0442\u044C
1324
2109
  generate.command("cancel").description("\u041E\u0442\u043C\u0435\u043D\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443").argument("<task_id>", "id \u0438\u0437 generate").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (taskId, opts) => {
1325
2110
  await cmdGenerateCancel(taskId, Boolean(opts.json));
1326
2111
  });
1327
- generate.command("list").description("\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438").option("-k, --kind <kind>", "image | video", "image").option("--limit <n>", "\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0442\u0440\u043E\u043A", "20").option("--cursor <id>", "\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043F\u043E\u0441\u043B\u0435 \u044D\u0442\u043E\u0433\u043E task_id").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (opts) => {
1328
- const kind = opts.kind === "video" ? "video" : "image";
2112
+ generate.command("list").description("\u041F\u043E\u0441\u043B\u0435\u0434\u043D\u0438\u0435 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438").option("-k, --kind <kind>", "image | video | audio | upscale | switchx | mesh", "image").option("--limit <n>", "\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0442\u0440\u043E\u043A", "20").option("--cursor <id>", "\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043F\u043E\u0441\u043B\u0435 \u044D\u0442\u043E\u0433\u043E task_id").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(async (opts) => {
2113
+ const kind = ["image", "video", "audio", "upscale", "switchx", "mesh"].includes(opts.kind || "") ? opts.kind : null;
2114
+ if (!kind) throw new Error("--kind: image | video | audio | upscale | switchx | mesh");
1329
2115
  await cmdGenerateList({
1330
2116
  kind,
1331
2117
  json: Boolean(opts.json),
@@ -1368,6 +2154,73 @@ projects.command("list").description("\u0421\u043F\u0438\u0441\u043E\u043A \u043
1368
2154
  json: Boolean(opts.json)
1369
2155
  });
1370
2156
  });
2157
+ for (const [name, description, operation] of [
2158
+ ["get", "\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442", "get"],
2159
+ ["create", "\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442", "create"],
2160
+ ["update", "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442", "update"],
2161
+ ["delete", "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442", "delete"],
2162
+ ["roles", "\u0420\u043E\u043B\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430", "roles"],
2163
+ ["members", "\u0423\u0447\u0430\u0441\u0442\u043D\u0438\u043A\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430", "members"],
2164
+ ["invite", "\u041F\u0440\u0438\u0433\u043B\u0430\u0441\u0438\u0442\u044C \u0443\u0447\u0430\u0441\u0442\u043D\u0438\u043A\u0430", "invite"],
2165
+ ["update-member", "\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C \u0440\u043E\u043B\u044C \u0443\u0447\u0430\u0441\u0442\u043D\u0438\u043A\u0430", "update-member"],
2166
+ ["remove-member", "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0443\u0447\u0430\u0441\u0442\u043D\u0438\u043A\u0430", "remove-member"],
2167
+ ["leave", "\u041F\u043E\u043A\u0438\u043D\u0443\u0442\u044C \u043F\u0440\u043E\u0435\u043A\u0442", "leave"],
2168
+ ["analytics", "\u0410\u043D\u0430\u043B\u0438\u0442\u0438\u043A\u0430 \u043F\u0440\u043E\u0435\u043A\u0442\u0430", "analytics"],
2169
+ ["billing", "\u0411\u0438\u043B\u043B\u0438\u043D\u0433 \u043F\u0440\u043E\u0435\u043A\u0442\u0430", "billing"]
2170
+ ]) {
2171
+ const command = projects.command(name).description(description).option("--json");
2172
+ if (!["roles"].includes(name)) command.option("--id <id>", "id \u043F\u0440\u043E\u0435\u043A\u0442\u0430");
2173
+ if (["create", "update", "invite", "update-member"].includes(name))
2174
+ command.requiredOption("--body <json>", "JSON-\u0442\u0435\u043B\u043E");
2175
+ if (["update-member", "remove-member"].includes(name))
2176
+ command.requiredOption("--user <id>", "id \u043F\u043E\u043B\u044C\u0437\u043E\u0432\u0430\u0442\u0435\u043B\u044F");
2177
+ command.action((opts) => cmdProjectOperation(operation, opts));
2178
+ }
2179
+ projects.command("generations").description("\u041B\u0435\u043D\u0442\u0430 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0439 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u0441 \u0444\u0438\u043B\u044C\u0442\u0440\u0430\u043C\u0438").requiredOption("--id <id>", "id \u043F\u0440\u043E\u0435\u043A\u0442\u0430").option("--limit <n>").option("--cursor <id>").option("--kind <kind>").option("--source <source>").option("--date <YYYY-MM-DD>").option("--date-from <YYYY-MM-DD>").option("--date-to <YYYY-MM-DD>").option("--before-created-at <iso>").option("-q, --query <text>").option("--tag-ids <ids>").option("--json").action((opts) => cmdApiOperation("project-generations", opts));
2180
+ program.command("folders").description("\u041F\u0430\u043F\u043A\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u043E\u0432").option("--json").action((opts) => cmdApiOperation("folders", opts));
2181
+ program.command("folder-create").description("\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043F\u0430\u043F\u043A\u0443").requiredOption("--name <name>").option("--parent-id <id>").option("--json").action((opts) => cmdApiOperation("folder-create", opts));
2182
+ var tags = program.command("tags").description("\u0422\u0435\u0433\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430");
2183
+ tags.command("list").requiredOption("--project <id>").option("--json").action((opts) => cmdApiOperation("tags", opts));
2184
+ tags.command("create").requiredOption("--project <id>").requiredOption("--name <name>").option("--color <color>").option("--json").action((opts) => cmdApiOperation("tag-create", opts));
2185
+ tags.command("delete").requiredOption("--project <id>").requiredOption("--tag <id>").option("--json").action((opts) => cmdApiOperation("tag-delete", opts));
2186
+ program.command("favorites").description("\u0418\u0437\u0431\u0440\u0430\u043D\u043D\u044B\u0435 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430").requiredOption("--project <id>").option("--limit <n>").option("--cursor <id>").option("--json").action((opts) => cmdApiOperation("favorites", opts));
2187
+ var chat = program.command("chat").description("LLM chat \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043D\u044B\u0435 \u0442\u0440\u0435\u0434\u044B");
2188
+ chat.command("completion").requiredOption("--body <json>").option("--json").action((opts) => cmdChatOperation("completion", opts));
2189
+ chat.command("send").requiredOption("--id <id>").requiredOption("--body <json>").option("--json").action((opts) => cmdChatOperation("send", opts));
2190
+ chat.command("list").option("--json").action((opts) => cmdChatOperation("list", opts));
2191
+ chat.command("create").option("--body <json>").option("--json").action((opts) => cmdChatOperation("create", opts));
2192
+ chat.command("messages").requiredOption("--id <id>").option("--limit <n>").option("--cursor <id>").option("--json").action((opts) => cmdChatOperation("messages", opts));
2193
+ chat.command("delete").requiredOption("--id <id>").option("--json").action((opts) => cmdChatOperation("delete", opts));
2194
+ var webhook = program.command("webhook").description("\u0418\u0441\u0445\u043E\u0434\u044F\u0449\u0438\u0435 webhook-\u0438");
2195
+ webhook.command("get").option("--json").action((opts) => cmdWebhookOperation("get", opts));
2196
+ webhook.command("upsert").requiredOption("--url <https>").option("--include-studio").option("--json").action((opts) => cmdWebhookOperation("upsert", opts));
2197
+ webhook.command("delete").option("--json").action((opts) => cmdWebhookOperation("delete", opts));
2198
+ webhook.command("rotate").option("--json").action((opts) => cmdWebhookOperation("rotate", opts));
2199
+ webhook.command("deliveries").option("--limit <n>").option("--cursor <id>").option("--json").action((opts) => cmdWebhookOperation("deliveries", opts));
2200
+ webhook.command("delivery").requiredOption("--id <id>").option("--json").action((opts) => cmdWebhookOperation("delivery", opts));
2201
+ var generation = program.command("generation").description("\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044F \u0441 \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044F\u043C\u0438 \u0432 \u043F\u0440\u043E\u0435\u043A\u0442\u0430\u0445");
2202
+ for (const [name, operation, description] of [
2203
+ ["tags", "generation-tags", "\u041D\u0430\u0437\u043D\u0430\u0447\u0438\u0442\u044C \u0442\u0435\u0433\u0438"],
2204
+ ["like", "generation-like", "\u041B\u0430\u0439\u043A \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u0438"],
2205
+ ["copy", "generation-copy", "\u0421\u043A\u043E\u043F\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0432 \u043F\u0440\u043E\u0435\u043A\u0442"],
2206
+ ["move", "generation-move", "\u041F\u0435\u0440\u0435\u043C\u0435\u0441\u0442\u0438\u0442\u044C \u0432 \u043F\u0440\u043E\u0435\u043A\u0442"],
2207
+ ["delete", "generation-delete", "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0433\u0435\u043D\u0435\u0440\u0430\u0446\u0438\u044E"]
2208
+ ]) {
2209
+ const command = generation.command(name).description(description).requiredOption("--project <id>").requiredOption("--generation <id>").option("--json");
2210
+ if (["generation-tags", "generation-like"].includes(operation))
2211
+ command.requiredOption("--body <json>");
2212
+ if (["generation-copy", "generation-move"].includes(operation))
2213
+ command.requiredOption("--destination <id>");
2214
+ command.action((opts) => cmdLibraryOperation(operation, opts));
2215
+ }
2216
+ var elementActions = program.command("element").description("\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C Element Library");
2217
+ elementActions.command("update").requiredOption("--project <id>").requiredOption("--element <id>").requiredOption("--body <json>").option("--json").action((opts) => cmdLibraryOperation("element-update", opts));
2218
+ elementActions.command("delete").requiredOption("--project <id>").requiredOption("--element <id>").option("--json").action((opts) => cmdLibraryOperation("element-delete", opts));
2219
+ elementActions.command("reorder").requiredOption("--project <id>").requiredOption("--body <json>").option("--json").action((opts) => cmdLibraryOperation("element-reorder", opts));
2220
+ var media = program.command("media").description("\u0410\u0441\u0438\u043D\u0445\u0440\u043E\u043D\u043D\u044B\u0435 trim/concat \u043E\u043F\u0435\u0440\u0430\u0446\u0438\u0438");
2221
+ media.command("edit").requiredOption("--body <json>").option("--json").action((opts) => cmdLibraryOperation("media-edit", opts));
2222
+ media.command("get").requiredOption("--id <id>").option("--json").action((opts) => cmdLibraryOperation("media-get", opts));
2223
+ media.command("cancel").requiredOption("--id <id>").option("--json").action((opts) => cmdLibraryOperation("media-cancel", opts));
1371
2224
  var elements = program.command("elements").description("Element library \u043F\u0440\u043E\u0435\u043A\u0442\u0430 (@Name)");
1372
2225
  elements.command("list").description("\u042D\u043B\u0435\u043C\u0435\u043D\u0442\u044B \u043F\u0440\u043E\u0435\u043A\u0442\u0430").requiredOption("--project <id>", "id \u043F\u0440\u043E\u0435\u043A\u0442\u0430").option("--kinds <kinds>", "image,video").option("--limit <n>", "\u0441\u043A\u043E\u043B\u044C\u043A\u043E \u0441\u0442\u0440\u043E\u043A", "50").option("--cursor <id>", "\u0441\u0442\u0440\u0430\u043D\u0438\u0446\u0430 \u043F\u043E\u0441\u043B\u0435 \u044D\u0442\u043E\u0433\u043E id").option("--json", "\u0432\u044B\u0432\u0435\u0441\u0442\u0438 \u0441\u044B\u0440\u043E\u0439 JSON", false).action(
1373
2226
  async (opts) => {