democut 0.6.1 → 0.6.17

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 +8 -4
  2. package/dist/cli.js +3424 -1078
  3. package/package.json +3 -2
package/dist/cli.js CHANGED
@@ -1298,21 +1298,21 @@ var require_errors = __commonJS({
1298
1298
  function extendErrors({ gen, keyword, schemaValue, data, errsCount, it }) {
1299
1299
  if (errsCount === void 0)
1300
1300
  throw new Error("ajv implementation error");
1301
- const err3 = gen.name("err");
1301
+ const err2 = gen.name("err");
1302
1302
  gen.forRange("i", errsCount, names_1.default.errors, (i) => {
1303
- gen.const(err3, (0, codegen_1._)`${names_1.default.vErrors}[${i}]`);
1304
- gen.if((0, codegen_1._)`${err3}.instancePath === undefined`, () => gen.assign((0, codegen_1._)`${err3}.instancePath`, (0, codegen_1.strConcat)(names_1.default.instancePath, it.errorPath)));
1305
- gen.assign((0, codegen_1._)`${err3}.schemaPath`, (0, codegen_1.str)`${it.errSchemaPath}/${keyword}`);
1303
+ gen.const(err2, (0, codegen_1._)`${names_1.default.vErrors}[${i}]`);
1304
+ gen.if((0, codegen_1._)`${err2}.instancePath === undefined`, () => gen.assign((0, codegen_1._)`${err2}.instancePath`, (0, codegen_1.strConcat)(names_1.default.instancePath, it.errorPath)));
1305
+ gen.assign((0, codegen_1._)`${err2}.schemaPath`, (0, codegen_1.str)`${it.errSchemaPath}/${keyword}`);
1306
1306
  if (it.opts.verbose) {
1307
- gen.assign((0, codegen_1._)`${err3}.schema`, schemaValue);
1308
- gen.assign((0, codegen_1._)`${err3}.data`, data);
1307
+ gen.assign((0, codegen_1._)`${err2}.schema`, schemaValue);
1308
+ gen.assign((0, codegen_1._)`${err2}.data`, data);
1309
1309
  }
1310
1310
  });
1311
1311
  }
1312
1312
  exports.extendErrors = extendErrors;
1313
1313
  function addError(gen, errObj) {
1314
- const err3 = gen.const("err", errObj);
1315
- gen.if((0, codegen_1._)`${names_1.default.vErrors} === null`, () => gen.assign(names_1.default.vErrors, (0, codegen_1._)`[${err3}]`), (0, codegen_1._)`${names_1.default.vErrors}.push(${err3})`);
1314
+ const err2 = gen.const("err", errObj);
1315
+ gen.if((0, codegen_1._)`${names_1.default.vErrors} === null`, () => gen.assign(names_1.default.vErrors, (0, codegen_1._)`[${err2}]`), (0, codegen_1._)`${names_1.default.vErrors}.push(${err2})`);
1316
1316
  gen.code((0, codegen_1._)`${names_1.default.errors}++`);
1317
1317
  }
1318
1318
  function returnErrors(it, errs) {
@@ -6916,7 +6916,7 @@ import { realpathSync } from "fs";
6916
6916
  import { fileURLToPath } from "url";
6917
6917
 
6918
6918
  // src/version.ts
6919
- var VERSION = "0.6.1";
6919
+ var VERSION = "0.6.17";
6920
6920
 
6921
6921
  // src/device-flow.ts
6922
6922
  var DeviceFlowError = class extends Error {
@@ -6956,19 +6956,19 @@ function oauthError(json) {
6956
6956
  return "invalid_grant";
6957
6957
  }
6958
6958
  async function requestDeviceAuthorization(baseUrl, fetchImpl = fetch) {
6959
- const { ok, status: status2, json } = await postJson(
6959
+ const { ok, status, json } = await postJson(
6960
6960
  `${baseUrl}/api/oauth/device/authorize`,
6961
6961
  {},
6962
6962
  fetchImpl
6963
6963
  );
6964
6964
  if (!ok) {
6965
- if (status2 === 503) {
6965
+ if (status === 503) {
6966
6966
  throw new DeviceFlowError(
6967
6967
  "disabled",
6968
6968
  "\uC11C\uBC84\uC5D0\uC11C device flow \uAC00 \uBE44\uD65C\uC131\uD654\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4 (DEMOCUT_DEVICE_TOKEN_SECRET \uBBF8\uC124\uC815)."
6969
6969
  );
6970
6970
  }
6971
- throw new DeviceFlowError("authorize_failed", `device authorize \uC2E4\uD328 (HTTP ${status2}).`);
6971
+ throw new DeviceFlowError("authorize_failed", `device authorize \uC2E4\uD328 (HTTP ${status}).`);
6972
6972
  }
6973
6973
  return json;
6974
6974
  }
@@ -6979,10 +6979,10 @@ async function pollTokenOnce(baseUrl, deviceCode, fetchImpl = fetch) {
6979
6979
  fetchImpl
6980
6980
  );
6981
6981
  if (ok) return { status: "approved", tokens: json };
6982
- const err3 = oauthError(json);
6983
- if (err3 === "authorization_pending") return { status: "pending" };
6984
- if (err3 === "slow_down") return { status: "slow_down" };
6985
- throw new DeviceFlowError(err3, describeError(err3));
6982
+ const err2 = oauthError(json);
6983
+ if (err2 === "authorization_pending") return { status: "pending" };
6984
+ if (err2 === "slow_down") return { status: "slow_down" };
6985
+ throw new DeviceFlowError(err2, describeError(err2));
6986
6986
  }
6987
6987
  async function refreshToken(baseUrl, refresh, fetchImpl = fetch) {
6988
6988
  const { ok, json } = await postJson(
@@ -7001,9 +7001,9 @@ async function pollUntilApproved(baseUrl, auth, deps = {}) {
7001
7001
  const deadline = now() + auth.expires_in;
7002
7002
  while (now() < deadline) {
7003
7003
  await sleep(intervalMs);
7004
- const out3 = await pollTokenOnce(baseUrl, auth.device_code, fetchImpl);
7005
- if (out3.status === "approved") return out3.tokens;
7006
- if (out3.status === "slow_down") intervalMs += SLOW_DOWN_INCREMENT_MS;
7004
+ const out2 = await pollTokenOnce(baseUrl, auth.device_code, fetchImpl);
7005
+ if (out2.status === "approved") return out2.tokens;
7006
+ if (out2.status === "slow_down") intervalMs += SLOW_DOWN_INCREMENT_MS;
7007
7007
  deps.onPending?.();
7008
7008
  }
7009
7009
  throw new DeviceFlowError("expired_token", describeError("expired_token"));
@@ -7244,247 +7244,7 @@ function logoutCommand(opts) {
7244
7244
  return 0;
7245
7245
  }
7246
7246
 
7247
- // src/api-client.ts
7248
- var ApiError = class extends Error {
7249
- constructor(status2, code, message, retriable, extra = {}) {
7250
- super(message);
7251
- this.status = status2;
7252
- this.code = code;
7253
- this.retriable = retriable;
7254
- this.extra = extra;
7255
- this.name = "ApiError";
7256
- }
7257
- status;
7258
- code;
7259
- retriable;
7260
- extra;
7261
- };
7262
- function parseDetail(status2, body) {
7263
- const detail = body?.detail;
7264
- if (detail && typeof detail === "object" && !Array.isArray(detail)) {
7265
- const d = detail;
7266
- if (typeof d.code === "string" || typeof d.message === "string") {
7267
- const { code, message, retriable, ...extra } = d;
7268
- return new ApiError(
7269
- status2,
7270
- typeof code === "string" ? code : `HTTP_${status2}`,
7271
- typeof message === "string" ? message : `HTTP ${status2}`,
7272
- typeof retriable === "boolean" ? retriable : null,
7273
- extra
7274
- );
7275
- }
7276
- }
7277
- if (typeof detail === "string") {
7278
- return new ApiError(status2, `HTTP_${status2}`, detail, null);
7279
- }
7280
- if (Array.isArray(detail)) {
7281
- const lines = detail.map((e) => {
7282
- const item = e;
7283
- const where = Array.isArray(item.loc) ? item.loc.filter((p) => p !== "body").join(".") : "";
7284
- const msg = typeof item.msg === "string" ? item.msg : JSON.stringify(e);
7285
- return where ? `${where}: ${msg}` : msg;
7286
- });
7287
- return new ApiError(status2, "VALIDATION_ERROR", lines.join("\n"), true);
7288
- }
7289
- return new ApiError(status2, `HTTP_${status2}`, `\uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (HTTP ${status2}).`, null);
7290
- }
7291
- async function apiRequest(baseUrl, path, init = {}, deps = {}) {
7292
- const fetchImpl = deps.fetchImpl ?? fetch;
7293
- const token = await getValidAccessToken(baseUrl, deps);
7294
- const headers = {
7295
- Authorization: `Bearer ${token}`,
7296
- "User-Agent": `democut/${VERSION}`
7297
- };
7298
- if (init.body !== void 0) headers["Content-Type"] = "application/json";
7299
- const res = await fetchImpl(`${baseUrl}${path}`, {
7300
- method: init.method ?? "GET",
7301
- headers,
7302
- ...init.body === void 0 ? {} : { body: JSON.stringify(init.body) }
7303
- });
7304
- const text = await res.text();
7305
- let json = null;
7306
- if (text) {
7307
- try {
7308
- json = JSON.parse(text);
7309
- } catch {
7310
- json = null;
7311
- }
7312
- }
7313
- if (!res.ok) {
7314
- if (res.status === 401) {
7315
- throw new ApiError(
7316
- 401,
7317
- "UNAUTHENTICATED",
7318
- "\uC778\uC99D\uC774 \uB9CC\uB8CC\uB418\uC5C8\uAC70\uB098 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. 'democut auth login' \uC73C\uB85C \uB2E4\uC2DC \uB85C\uADF8\uC778\uD558\uC138\uC694.",
7319
- false
7320
- );
7321
- }
7322
- throw parseDetail(res.status, json);
7323
- }
7324
- return json;
7325
- }
7326
-
7327
- // src/api-errors.ts
7328
- function usd(v) {
7329
- return v < 0.01 ? `$${v.toFixed(4)}` : `$${v.toFixed(2)}`;
7330
- }
7331
- function classifyApiError(e, ctx) {
7332
- const hint = ctx.statusHint ?? "\uC0C1\uD0DC \uC870\uD68C";
7333
- if (e.status === 422 && e.code === "VIDEOGEN_UPSTREAM_REJECTED") {
7334
- return {
7335
- safety: "unsafe",
7336
- // 돈이 나갔다가 돌아왔다 — "애초에 과금이 없었다" 와는 다르다. 그 구분을 흐리면
7337
- // 원장을 보는 사람이 이 거래를 설명하지 못한다.
7338
- notCharged: false,
7339
- lines: [
7340
- "\uC5C5\uC2A4\uD2B8\uB9BC\uC774 \uC774 \uC791\uC5C5\uC744 \uC601\uAD6C \uAC70\uBD80\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC870\uD68C\uD574\uB3C4 \uBCF5\uAD6C\uB418\uC9C0 \uC54A\uC73C\uBA70, \uACFC\uAE08\uC740 \uD658\uBD88\uB410\uC2B5\uB2C8\uB2E4.",
7341
- "\uACE0\uCE60 \uD30C\uB77C\uBBF8\uD130\uAC00 \uC788\uB294 \uC624\uB958\uAC00 \uC544\uB2D9\uB2C8\uB2E4 \u2014 \uC0C8\uB85C \uB9CC\uB4E4\uB824\uBA74 \uD504\uB86C\uD504\uD2B8\xB7\uC124\uC815\uC744 \uBC14\uAFD4 **\uC0C8\uB85C \uC81C\uCD9C**\uD574\uC57C \uD558\uACE0, \uADF8\uAC74 \uB2E4\uC2DC \uACFC\uAE08\uB429\uB2C8\uB2E4(\uC0AC\uC6A9\uC790 \uB3D9\uC758\uB97C \uBC1B\uC73C\uC138\uC694)."
7342
- ]
7343
- };
7344
- }
7345
- if (e.status === 404 && e.code === "VIDEOGEN_JOB_NOT_FOUND") {
7346
- return {
7347
- safety: "unsafe",
7348
- notCharged: false,
7349
- lines: [
7350
- "\uADF8 \uC791\uC5C5\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. job_id \uAC00 \uB9DE\uB294\uC9C0 \uBA3C\uC800 \uD655\uC778\uD558\uC138\uC694.",
7351
- "\u26A0\uFE0F \uC791\uC5C5\uC774 \uC0B4\uC544 \uC788\uB294\uB370 \uC870\uD68C\uB9CC \uC5B4\uAE0B\uB0AC\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4 \u2014 \uC0C8\uB85C \uC81C\uCD9C\uD558\uBA74 **\uBCC4\uB3C4 \uC791\uC5C5\uC73C\uB85C \uB2E4\uC2DC \uACFC\uAE08**\uB429\uB2C8\uB2E4."
7352
- ]
7353
- };
7354
- }
7355
- if (e.status === 402) {
7356
- const lines = [];
7357
- const limit = e.extra.limit_usd;
7358
- const would = e.extra.would_cost_usd;
7359
- if (typeof limit === "number" && typeof would === "number") {
7360
- lines.push(`\uC0C1\uD55C ${usd(limit)} \xB7 \uC774 \uC694\uCCAD ${usd(would)}`);
7361
- }
7362
- lines.push("\uD574\uC0C1\uB3C4\uB098 \uAE38\uC774\uB97C \uB0AE\uCDB0 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694. \uC544\uC9C1 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
7363
- return { safety: "fixable", notCharged: true, lines };
7364
- }
7365
- if (e.status === 422) {
7366
- return {
7367
- safety: "fixable",
7368
- notCharged: true,
7369
- lines: ["\uD30C\uB77C\uBBF8\uD130\uB97C \uACE0\uCCD0 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694. \uC544\uC9C1 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."]
7370
- };
7371
- }
7372
- if (e.status === 503) {
7373
- return {
7374
- safety: "safe",
7375
- notCharged: true,
7376
- lines: ["\uC77C\uC2DC\uC801\uC778 \uC624\uB958\uC785\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uADF8\uB300\uB85C \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uB3C4 \uC548\uC804\uD569\uB2C8\uB2E4."]
7377
- };
7378
- }
7379
- if (e.status === 502) {
7380
- return ctx.submitted ? {
7381
- safety: "unsafe",
7382
- notCharged: false,
7383
- lines: [
7384
- "\u26A0\uFE0F \uC81C\uCD9C\uC774 \uC774\uBBF8 \uC811\uC218\uB410\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC81C\uCD9C\uD558\uBA74 \uB450 \uBC88 \uACFC\uAE08\uB429\uB2C8\uB2E4 \u2014",
7385
- `\uC7AC\uC2DC\uB3C4\uD558\uC9C0 \uB9D0\uACE0 ${hint} \uB85C \uD655\uC778\uD558\uAC70\uB098 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB38\uC758\uD558\uC138\uC694.`
7386
- ]
7387
- } : {
7388
- safety: "safe",
7389
- notCharged: true,
7390
- lines: [
7391
- "\uC5C5\uC2A4\uD2B8\uB9BC \uC624\uB958\uC785\uB2C8\uB2E4. \uC774 \uC694\uCCAD\uC740 \uBD80\uC791\uC6A9\uC774 \uC5C6\uC73C\uBBC0\uB85C \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uB3C4 \uC548\uC804\uD569\uB2C8\uB2E4."
7392
- ]
7393
- };
7394
- }
7395
- if (e.status === 404) {
7396
- const lines = [];
7397
- if (e.code === "VIDEOGEN_PROJECT_NOT_FOUND") {
7398
- lines.push(
7399
- "democut_list_projects \uB85C \uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC758 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D\uC744 \uD655\uC778\uD558\uACE0 \uADF8\uC911 \uD558\uB098\uC758 \uC2AC\uB7EC\uADF8\uB97C \uC4F0\uC138\uC694. \uBAA9\uB85D\uC774 \uBE44\uC5B4 \uC788\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uD504\uB85C\uC81D\uD2B8\uB97C \uBA3C\uC800 \uB9CC\uB4E4\uC5B4 \uB2EC\uB77C\uACE0 \uC54C\uB9AC\uC138\uC694."
7400
- );
7401
- }
7402
- lines.push("\uC544\uC9C1 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 \uAC12\uC744 \uACE0\uCCD0 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.");
7403
- return { safety: "fixable", notCharged: true, lines };
7404
- }
7405
- if (e.status === 403) {
7406
- return {
7407
- safety: "unknown",
7408
- notCharged: true,
7409
- lines: ["\uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC5D0\uC11C \uC601\uC0C1\uC744 \uC0DD\uC131\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(\uBA64\uBC84 \uC774\uC0C1 \uD544\uC694)."]
7410
- };
7411
- }
7412
- return { safety: "unknown", notCharged: false, lines: [] };
7413
- }
7414
-
7415
- // src/confirm.ts
7416
- import { createInterface } from "readline/promises";
7417
- function isInteractive() {
7418
- return Boolean(process.stdin.isTTY && process.stdout.isTTY);
7419
- }
7420
- async function confirm(question) {
7421
- const rl = createInterface({ input: process.stdin, output: process.stdout });
7422
- try {
7423
- const answer = await rl.question(`${question} [y/N] `);
7424
- return /^y(es)?$/i.test(answer.trim());
7425
- } finally {
7426
- rl.close();
7427
- }
7428
- }
7429
-
7430
- // src/videogen.ts
7431
- var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["succeeded", "failed", "cancelled"]);
7432
- function isTerminal(status2) {
7433
- return TERMINAL_STATUSES.has(status2);
7434
- }
7435
- function estimate(baseUrl, body, deps = {}) {
7436
- return apiRequest(baseUrl, "/api/videogen/estimate", { method: "POST", body }, deps);
7437
- }
7438
- function submit(baseUrl, body, deps = {}) {
7439
- return apiRequest(baseUrl, "/api/videogen", { method: "POST", body }, deps);
7440
- }
7441
- function status(baseUrl, jobId, projectSlug, deps = {}) {
7442
- const q = projectSlug ? `?project_slug=${encodeURIComponent(projectSlug)}` : "";
7443
- return apiRequest(
7444
- baseUrl,
7445
- `/api/videogen/${encodeURIComponent(jobId)}${q}`,
7446
- {},
7447
- deps
7448
- );
7449
- }
7450
- var WaitTimeout = class extends Error {
7451
- constructor(jobId, waitedS) {
7452
- super(
7453
- `${waitedS}\uCD08 \uC548\uC5D0 \uC644\uB8CC\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC791\uC5C5\uC740 \uC11C\uBC84\uC5D0\uC11C \uACC4\uC18D \uC9C4\uD589\uB429\uB2C8\uB2E4 \u2014 'democut video status ${jobId}' \uB85C \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694 (\uC0C8\uB85C \uC81C\uCD9C\uD558\uBA74 \uB2E4\uC2DC \uACFC\uAE08\uB429\uB2C8\uB2E4).`
7454
- );
7455
- this.jobId = jobId;
7456
- this.waitedS = waitedS;
7457
- this.name = "WaitTimeout";
7458
- }
7459
- jobId;
7460
- waitedS;
7461
- };
7462
- var POLL_INTERVAL_S = 5;
7463
- async function waitForCompletion(baseUrl, jobId, projectSlug, timeoutS, deps = {}) {
7464
- const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
7465
- const now = deps.now ?? (() => Math.floor(Date.now() / 1e3));
7466
- const deadline = now() + timeoutS;
7467
- for (; ; ) {
7468
- const job = await status(baseUrl, jobId, projectSlug, deps);
7469
- if (isTerminal(job.status)) return job;
7470
- deps.onTick?.(job);
7471
- if (now() >= deadline) throw new WaitTimeout(jobId, timeoutS);
7472
- await sleep(POLL_INTERVAL_S * 1e3);
7473
- }
7474
- }
7475
- async function download(videoUrl, outPath, fetchImpl = fetch) {
7476
- const { writeFile } = await import("fs/promises");
7477
- const res = await fetchImpl(videoUrl);
7478
- if (!res.ok) {
7479
- throw new Error(
7480
- `\uC0B0\uCD9C\uBB3C \uB0B4\uB824\uBC1B\uAE30 \uC2E4\uD328 (HTTP ${res.status}).`
7481
- );
7482
- }
7483
- await writeFile(outPath, Buffer.from(await res.arrayBuffer()));
7484
- }
7485
-
7486
- // src/commands/video.ts
7487
- var MOCK_NOTICE = "\u26A0\uFE0F mock \uBAA8\uB4DC \u2014 \uC774 \uBC30\uD3EC\uB294 \uC601\uC0C1\uC744 \uC2E4\uC81C\uB85C \uC0DD\uC131\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (API \uD0A4 \uBBF8\uC124\uC815). \uC544\uB798 \uAE08\uC561\xB7job id\xB7URL \uC740 \uC804\uBD80 \uAC00\uC9DC\uC774\uBA70 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.";
7247
+ // src/commands/common.ts
7488
7248
  var EXIT = {
7489
7249
  OK: 0,
7490
7250
  /** 일반 오류 — 미로그인·사용자 취소·생성 실패·알 수 없음. */
@@ -7503,335 +7263,62 @@ var EXIT = {
7503
7263
  */
7504
7264
  WAIT_TIMEOUT: 5
7505
7265
  };
7506
- var out2 = (s) => process.stdout.write(`${s}
7507
- `);
7508
- var err2 = (s) => process.stderr.write(`${s}
7509
- `);
7510
- function emit(opts, ok, payload) {
7511
- if (opts.json) out2(JSON.stringify({ ok, ...payload }));
7512
- }
7513
- function usd2(v) {
7514
- return v < 0.01 ? `$${v.toFixed(4)}` : `$${v.toFixed(2)}`;
7515
- }
7516
- function parseIntOpt(raw, name) {
7517
- if (raw === void 0) return void 0;
7518
- const n = Number(raw);
7519
- if (!Number.isInteger(n)) throw new UsageError(`--${name} \uC740 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${raw}`);
7520
- return n;
7521
- }
7522
7266
  var UsageError = class extends Error {
7523
7267
  };
7524
- var EXIT_BY_SAFETY = {
7525
- fixable: 2,
7526
- // EXIT.FIXABLE
7527
- safe: 3,
7528
- // EXIT.TRANSIENT
7529
- unsafe: 4,
7530
- // EXIT.UPSTREAM_REJECTED
7531
- unknown: 1
7532
- // EXIT.GENERAL
7533
- };
7534
- function renderApiError(e, opts) {
7535
- const g = classifyApiError(e, { submitted: true, statusHint: "democut video status <job_id>" });
7536
- const code = EXIT_BY_SAFETY[g.safety];
7537
- if (opts.json) {
7538
- emit(opts, false, {
7539
- error: { status: e.status, code: e.code, message: e.message, retriable: e.retriable, ...e.extra },
7540
- exit_code: code
7541
- });
7542
- return code;
7543
- }
7544
- err2(`\uC624\uB958 [${e.code}] ${e.message}`);
7545
- for (const line of g.lines) err2(` ${line}`);
7546
- return code;
7547
- }
7548
- async function guarded(opts, fn) {
7549
- try {
7550
- return await fn();
7551
- } catch (e) {
7552
- if (e instanceof NotLoggedInError) {
7553
- if (opts.json) emit(opts, false, { error: { code: "NOT_LOGGED_IN", message: e.message } });
7554
- else err2(e.message);
7555
- return EXIT.GENERAL;
7268
+
7269
+ // node_modules/zod/v4/core/core.js
7270
+ var _a;
7271
+ // @__NO_SIDE_EFFECTS__
7272
+ function $constructor(name, initializer3, params) {
7273
+ function init(inst, def) {
7274
+ if (!inst._zod) {
7275
+ Object.defineProperty(inst, "_zod", {
7276
+ value: {
7277
+ def,
7278
+ constr: _,
7279
+ traits: /* @__PURE__ */ new Set()
7280
+ },
7281
+ enumerable: false
7282
+ });
7556
7283
  }
7557
- if (e instanceof ApiError) return renderApiError(e, opts);
7558
- if (e instanceof UsageError) {
7559
- if (opts.json) emit(opts, false, { error: { code: "USAGE", message: e.message } });
7560
- else err2(`\uC0AC\uC6A9\uBC95 \uC624\uB958: ${e.message}`);
7561
- return EXIT.FIXABLE;
7284
+ if (inst._zod.traits.has(name)) {
7285
+ return;
7562
7286
  }
7563
- if (e instanceof WaitTimeout) {
7564
- if (opts.json) {
7565
- emit(opts, false, {
7566
- error: { code: "WAIT_TIMEOUT", message: e.message, retriable: false },
7567
- job_id: e.jobId,
7568
- still_running: true
7569
- });
7570
- } else {
7571
- err2(e.message);
7287
+ inst._zod.traits.add(name);
7288
+ initializer3(inst, def);
7289
+ const proto = _.prototype;
7290
+ const keys = Object.keys(proto);
7291
+ for (let i = 0; i < keys.length; i++) {
7292
+ const k = keys[i];
7293
+ if (!(k in inst)) {
7294
+ inst[k] = proto[k].bind(inst);
7572
7295
  }
7573
- return EXIT.WAIT_TIMEOUT;
7574
7296
  }
7575
- const msg = e?.message ?? String(e);
7576
- if (opts.json) emit(opts, false, { error: { code: "UNKNOWN", message: msg } });
7577
- else err2(`\uC624\uB958: ${msg}`);
7578
- return EXIT.GENERAL;
7579
7297
  }
7580
- }
7581
- function buildEstimateIn(opts) {
7582
- return {
7583
- duration_s: parseIntOpt(opts.duration, "duration") ?? 5,
7584
- resolution: opts.resolution ?? "720p",
7585
- ratio: opts.ratio ?? "16:9",
7586
- ...opts.model ? { model: opts.model } : {},
7587
- // ★ 이미지 유무가 모델 계열을, 계열이 단가를 정한다 — 추정과 생성이 같은 값을 봐야
7588
- // 승인받은 금액과 실제 청구가 일치한다.
7589
- has_image: Boolean(opts.imageUrls?.length)
7590
- };
7591
- }
7592
- function estimateCommand(opts, deps = {}) {
7593
- return guarded(opts, async () => {
7594
- const base = resolveBaseUrl(opts.baseUrl);
7595
- const r = await estimate(base, buildEstimateIn(opts), deps);
7596
- if (opts.json) {
7597
- emit(opts, true, { tokens: r.tokens, cost_usd: r.cost_usd, model: r.model, mock: r.mock });
7598
- } else {
7599
- if (r.mock) err2(MOCK_NOTICE);
7600
- out2(`\uC608\uC0C1 \uBE44\uC6A9: ${usd2(r.cost_usd)} (${r.tokens.toLocaleString()} tokens \xB7 ${r.model})`);
7298
+ const Parent = params?.Parent ?? Object;
7299
+ class Definition extends Parent {
7300
+ }
7301
+ Object.defineProperty(Definition, "name", { value: name });
7302
+ function _(def) {
7303
+ var _a3;
7304
+ const inst = params?.Parent ? new Definition() : this;
7305
+ init(inst, def);
7306
+ (_a3 = inst._zod).deferred ?? (_a3.deferred = []);
7307
+ for (const fn of inst._zod.deferred) {
7308
+ fn();
7309
+ }
7310
+ return inst;
7311
+ }
7312
+ Object.defineProperty(_, "init", { value: init });
7313
+ Object.defineProperty(_, Symbol.hasInstance, {
7314
+ value: (inst) => {
7315
+ if (params?.Parent && inst instanceof params.Parent)
7316
+ return true;
7317
+ return inst?._zod?.traits?.has(name);
7601
7318
  }
7602
- return EXIT.OK;
7603
7319
  });
7604
- }
7605
- function generateCommand(prompt, opts, deps = {}) {
7606
- return guarded(opts, async () => {
7607
- if (!prompt || !prompt.trim()) {
7608
- throw new UsageError('\uD504\uB86C\uD504\uD2B8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC608: democut video generate "\uACE0\uC591\uC774\uAC00 \uCDA4\uCD98\uB2E4"');
7609
- }
7610
- if (!opts.project || !opts.project.trim()) {
7611
- throw new UsageError(
7612
- "--project <slug> \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uBE44\uC6A9\uC774 \uADC0\uC18D\uB420 \uBCF8\uC778 \uC18C\uC720 \uD504\uB85C\uC81D\uD2B8\uB97C \uC9C0\uC815\uD558\uC138\uC694. \uC2AC\uB7EC\uADF8\uB294 \uC6F9\uC758 \uD504\uB85C\uC81D\uD2B8 \uC8FC\uC18C `/projects/<\uC2AC\uB7EC\uADF8>` \uC5D0\uC11C \uD655\uC778\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
7613
- );
7614
- }
7615
- const base = resolveBaseUrl(opts.baseUrl);
7616
- const est = buildEstimateIn(opts);
7617
- const quote = await estimate(base, est, deps);
7618
- if (!opts.json) {
7619
- if (quote.mock) err2(MOCK_NOTICE);
7620
- out2(`\uC608\uC0C1 \uBE44\uC6A9: ${usd2(quote.cost_usd)} (${quote.tokens.toLocaleString()} tokens \xB7 ${quote.model})`);
7621
- out2(` ${est.duration_s}\uCD08 \xB7 ${est.resolution} \xB7 ${est.ratio}`);
7622
- }
7623
- if (!opts.yes) {
7624
- if (!(deps.isInteractiveImpl ?? isInteractive)()) {
7625
- const message = `\uBE44\uB300\uD654\uD615 \uD658\uACBD\uC774\uB77C \uBE44\uC6A9 \uC2B9\uC778\uC744 \uBC1B\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uC608\uC0C1 ${usd2(quote.cost_usd)}). \uD655\uC778\uD588\uB2E4\uBA74 --yes \uB97C \uBD99\uC5EC \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694.`;
7626
- if (opts.json) {
7627
- emit(opts, false, {
7628
- error: { code: "CONFIRMATION_REQUIRED", message },
7629
- estimated_cost_usd: quote.cost_usd
7630
- });
7631
- } else {
7632
- err2(message);
7633
- }
7634
- return EXIT.FIXABLE;
7635
- }
7636
- if (opts.json) {
7637
- const message = `--json \uBAA8\uB4DC\uC5D0\uC11C\uB294 --yes \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 (\uC608\uC0C1 ${usd2(quote.cost_usd)}).`;
7638
- emit(opts, false, {
7639
- error: { code: "CONFIRMATION_REQUIRED", message },
7640
- estimated_cost_usd: quote.cost_usd
7641
- });
7642
- return EXIT.FIXABLE;
7643
- }
7644
- const ask = deps.confirmImpl ?? confirm;
7645
- const question = quote.mock ? "mock \uBAA8\uB4DC\uC785\uB2C8\uB2E4 \u2014 \uC2E4\uC81C \uC601\uC0C1\uC740 \uC0DD\uC131\uB418\uC9C0 \uC54A\uACE0 \uACFC\uAE08\uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4. \uADF8\uB798\uB3C4 \uC9C4\uD589\uD560\uAE4C\uC694?" : `${usd2(quote.cost_usd)} \uAC00 \uCCAD\uAD6C\uB429\uB2C8\uB2E4. \uC0DD\uC131\uD560\uAE4C\uC694?`;
7646
- if (!await ask(question)) {
7647
- out2("\uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4. \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
7648
- return EXIT.GENERAL;
7649
- }
7650
- }
7651
- const body = {
7652
- prompt,
7653
- duration_s: est.duration_s,
7654
- resolution: est.resolution,
7655
- ratio: est.ratio,
7656
- generate_audio: Boolean(opts.audio),
7657
- watermark: Boolean(opts.watermark),
7658
- ...opts.model ? { model: opts.model } : {},
7659
- ...opts.seed !== void 0 ? { seed: parseIntOpt(opts.seed, "seed") } : {},
7660
- ...opts.imageUrls?.length ? { image_urls: opts.imageUrls } : {},
7661
- project_slug: opts.project
7662
- };
7663
- const job = await submit(base, body, deps);
7664
- if (job.duplicate) {
7665
- if (job.pending) {
7666
- const message = "\uAC19\uC740 \uC694\uCCAD\uC774 \uBC29\uAE08 \uC81C\uCD9C\uB418\uC5B4 \uC9C4\uD589 \uC911\uC785\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 'democut video status <job_id>' \uB85C \uD655\uC778\uD558\uC138\uC694.";
7667
- if (opts.json) emit(opts, true, { duplicate: true, pending: true, job_id: null, message });
7668
- else out2(message);
7669
- return EXIT.OK;
7670
- }
7671
- if (!opts.json) out2(`\uAC19\uC740 \uC694\uCCAD\uC774 \uC774\uBBF8 \uC9C4\uD589 \uC911\uC785\uB2C8\uB2E4 (job ${job.job_id}). \uC0C8\uB85C \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`);
7672
- } else if (!opts.json) {
7673
- if (job.mock) err2(MOCK_NOTICE);
7674
- out2(`\uC81C\uCD9C\uB428: job ${job.job_id} (\uC608\uC0C1 ${usd2(job.estimated_cost_usd)})`);
7675
- }
7676
- if (!opts.wait) {
7677
- if (opts.json) {
7678
- emit(opts, true, {
7679
- job_id: job.job_id,
7680
- status: job.status,
7681
- model: job.model,
7682
- estimated_cost_usd: job.estimated_cost_usd,
7683
- duplicate: job.duplicate,
7684
- pending: job.pending,
7685
- mock: job.mock
7686
- });
7687
- } else {
7688
- out2(`\uC644\uB8CC \uD655\uC778: democut video status ${job.job_id}`);
7689
- }
7690
- return EXIT.OK;
7691
- }
7692
- return finishWithWait(base, job.job_id, opts, deps);
7693
- });
7694
- }
7695
- function statusCommand2(jobId, opts, deps = {}) {
7696
- return guarded(opts, async () => {
7697
- if (!jobId) throw new UsageError("job_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC608: democut video status <job_id>");
7698
- const base = resolveBaseUrl(opts.baseUrl);
7699
- if (opts.wait) return finishWithWait(base, jobId, opts, deps);
7700
- const job = await status(base, jobId, opts.project, deps);
7701
- return report(job, opts, deps);
7702
- });
7703
- }
7704
- async function finishWithWait(base, jobId, opts, deps) {
7705
- const timeoutS = parseIntOpt(opts.timeout, "timeout") ?? 900;
7706
- if (!opts.json) process.stderr.write(" \uC0DD\uC131 \uB300\uAE30 \uC911");
7707
- const job = await waitForCompletion(base, jobId, opts.project, timeoutS, {
7708
- ...deps,
7709
- onTick: () => {
7710
- if (!opts.json) process.stderr.write(".");
7711
- }
7712
- });
7713
- if (!opts.json) err2("");
7714
- return report(job, opts, deps);
7715
- }
7716
- async function report(job, opts, deps = {}) {
7717
- if (job.status === "failed" || job.status === "cancelled") {
7718
- if (opts.json) {
7719
- emit(opts, false, { job_id: job.job_id, status: job.status, error: job.error });
7720
- } else {
7721
- err2(`\uC0DD\uC131 \uC2E4\uD328 (${job.status}): ${job.error ?? "\uC0AC\uC720 \uBBF8\uC0C1"}`);
7722
- }
7723
- return EXIT.GENERAL;
7724
- }
7725
- if (job.mock) {
7726
- if (opts.json) {
7727
- emit(opts, true, {
7728
- job_id: job.job_id,
7729
- status: job.status,
7730
- model: job.model,
7731
- video_url: job.video_url ?? null,
7732
- saved_to: null,
7733
- mock: true
7734
- });
7735
- } else {
7736
- err2(MOCK_NOTICE);
7737
- out2(`\uC0C1\uD0DC: ${job.status} (\uAC00\uC9DC)`);
7738
- if (job.video_url) out2(` URL : ${job.video_url} \u2190 \uC2E4\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
7739
- out2(" \uB0B4\uB824\uBC1B\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uC2E4\uC81C \uC0DD\uC131\uC744 \uD558\uB824\uBA74 \uC6B4\uC601\uC790\uC5D0\uAC8C API \uD0A4 \uC124\uC815\uC744 \uC694\uCCAD\uD558\uC138\uC694.");
7740
- }
7741
- return EXIT.OK;
7742
- }
7743
- let saved = null;
7744
- let downloadError = null;
7745
- if (job.video_url && opts.output) {
7746
- try {
7747
- await (deps.downloadImpl ?? download)(job.video_url, opts.output);
7748
- saved = opts.output;
7749
- } catch (e) {
7750
- downloadError = e?.message ?? String(e);
7751
- }
7752
- }
7753
- if (opts.json) {
7754
- emit(opts, downloadError === null, {
7755
- job_id: job.job_id,
7756
- status: job.status,
7757
- model: job.model,
7758
- video_url: job.video_url ?? null,
7759
- tokens: job.tokens ?? null,
7760
- cost_usd: job.cost_usd ?? null,
7761
- seed: job.seed ?? null,
7762
- saved_to: saved,
7763
- ...downloadError ? { download_error: downloadError } : {}
7764
- });
7765
- } else {
7766
- out2(`\uC0C1\uD0DC: ${job.status}`);
7767
- if (job.cost_usd != null) out2(` \uBE44\uC6A9: ${usd2(job.cost_usd)}${job.tokens != null ? ` (${job.tokens.toLocaleString()} tokens)` : ""}`);
7768
- if (saved) out2(` \uC800\uC7A5\uB428: ${saved}`);
7769
- else if (job.video_url) {
7770
- out2(` URL : ${job.video_url}`);
7771
- if (downloadError) {
7772
- err2(` \uB0B4\uB824\uBC1B\uAE30 \uC2E4\uD328: ${downloadError}`);
7773
- err2(" \u26A0\uFE0F \uC704 URL \uB85C \uC9C1\uC811 \uBC1B\uC73C\uC138\uC694 \u2014 \uC11C\uBC84\uB294 \uBCF4\uAD00\uD558\uC9C0 \uC54A\uC73C\uBA70, \uB2E4\uC2DC \uB9CC\uB4E4\uBA74 \uB610 \uACFC\uAE08\uB429\uB2C8\uB2E4.");
7774
- } else {
7775
- out2(" \u26A0\uFE0F \uC11C\uBC84\uB294 \uC774 \uC0B0\uCD9C\uBB3C\uC744 \uBCF4\uAD00\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 \uC9C0\uAE08 \uB0B4\uB824\uBC1B\uC73C\uC138\uC694 (--output <\uACBD\uB85C>).");
7776
- }
7777
- }
7778
- }
7779
- return downloadError === null ? EXIT.OK : EXIT.GENERAL;
7780
- }
7781
-
7782
- // node_modules/zod/v4/core/core.js
7783
- var _a;
7784
- // @__NO_SIDE_EFFECTS__
7785
- function $constructor(name, initializer3, params) {
7786
- function init(inst, def) {
7787
- if (!inst._zod) {
7788
- Object.defineProperty(inst, "_zod", {
7789
- value: {
7790
- def,
7791
- constr: _,
7792
- traits: /* @__PURE__ */ new Set()
7793
- },
7794
- enumerable: false
7795
- });
7796
- }
7797
- if (inst._zod.traits.has(name)) {
7798
- return;
7799
- }
7800
- inst._zod.traits.add(name);
7801
- initializer3(inst, def);
7802
- const proto = _.prototype;
7803
- const keys = Object.keys(proto);
7804
- for (let i = 0; i < keys.length; i++) {
7805
- const k = keys[i];
7806
- if (!(k in inst)) {
7807
- inst[k] = proto[k].bind(inst);
7808
- }
7809
- }
7810
- }
7811
- const Parent = params?.Parent ?? Object;
7812
- class Definition extends Parent {
7813
- }
7814
- Object.defineProperty(Definition, "name", { value: name });
7815
- function _(def) {
7816
- var _a3;
7817
- const inst = params?.Parent ? new Definition() : this;
7818
- init(inst, def);
7819
- (_a3 = inst._zod).deferred ?? (_a3.deferred = []);
7820
- for (const fn of inst._zod.deferred) {
7821
- fn();
7822
- }
7823
- return inst;
7824
- }
7825
- Object.defineProperty(_, "init", { value: init });
7826
- Object.defineProperty(_, Symbol.hasInstance, {
7827
- value: (inst) => {
7828
- if (params?.Parent && inst instanceof params.Parent)
7829
- return true;
7830
- return inst?._zod?.traits?.has(name);
7831
- }
7832
- });
7833
- Object.defineProperty(_, "name", { value: name });
7834
- return _;
7320
+ Object.defineProperty(_, "name", { value: name });
7321
+ return _;
7835
7322
  }
7836
7323
  var $ZodAsyncError = class extends Error {
7837
7324
  constructor() {
@@ -13000,11 +12487,11 @@ var ZodPipe = /* @__PURE__ */ $constructor("ZodPipe", (inst, def) => {
13000
12487
  inst.in = def.in;
13001
12488
  inst.out = def.out;
13002
12489
  });
13003
- function pipe(in_, out3) {
12490
+ function pipe(in_, out2) {
13004
12491
  return new ZodPipe({
13005
12492
  type: "pipe",
13006
12493
  in: in_,
13007
- out: out3
12494
+ out: out2
13008
12495
  // ...util.normalizeParams(params),
13009
12496
  });
13010
12497
  }
@@ -14569,8 +14056,8 @@ var UrlElicitationRequiredError = class extends McpError {
14569
14056
  };
14570
14057
 
14571
14058
  // node_modules/@modelcontextprotocol/sdk/dist/esm/experimental/tasks/interfaces.js
14572
- function isTerminal2(status2) {
14573
- return status2 === "completed" || status2 === "failed" || status2 === "cancelled";
14059
+ function isTerminal(status) {
14060
+ return status === "completed" || status === "failed" || status === "cancelled";
14574
14061
  }
14575
14062
 
14576
14063
  // node_modules/zod-to-json-schema/dist/esm/parsers/string.js
@@ -14667,11 +14154,11 @@ var Protocol = class {
14667
14154
  if (!task) {
14668
14155
  throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
14669
14156
  }
14670
- if (!isTerminal2(task.status)) {
14157
+ if (!isTerminal(task.status)) {
14671
14158
  await this._waitForTaskUpdate(taskId, extra.signal);
14672
14159
  return await handleTaskResult();
14673
14160
  }
14674
- if (isTerminal2(task.status)) {
14161
+ if (isTerminal(task.status)) {
14675
14162
  const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
14676
14163
  this._clearTaskQueue(taskId);
14677
14164
  return {
@@ -14706,7 +14193,7 @@ var Protocol = class {
14706
14193
  if (!task) {
14707
14194
  throw new McpError(ErrorCode.InvalidParams, `Task not found: ${request.params.taskId}`);
14708
14195
  }
14709
- if (isTerminal2(task.status)) {
14196
+ if (isTerminal(task.status)) {
14710
14197
  throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
14711
14198
  }
14712
14199
  await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
@@ -15074,7 +14561,7 @@ var Protocol = class {
15074
14561
  while (true) {
15075
14562
  const task2 = await this.getTask({ taskId }, options);
15076
14563
  yield { type: "taskStatus", task: task2 };
15077
- if (isTerminal2(task2.status)) {
14564
+ if (isTerminal(task2.status)) {
15078
14565
  if (task2.status === "completed") {
15079
14566
  const result = await this.getTaskResult({ taskId }, resultSchema, options);
15080
14567
  yield { type: "result", result };
@@ -15487,8 +14974,8 @@ var Protocol = class {
15487
14974
  }
15488
14975
  return task;
15489
14976
  },
15490
- storeTaskResult: async (taskId, status2, result) => {
15491
- await taskStore.storeTaskResult(taskId, status2, result, sessionId);
14977
+ storeTaskResult: async (taskId, status, result) => {
14978
+ await taskStore.storeTaskResult(taskId, status, result, sessionId);
15492
14979
  const task = await taskStore.getTask(taskId, sessionId);
15493
14980
  if (task) {
15494
14981
  const notification = TaskStatusNotificationSchema.parse({
@@ -15496,7 +14983,7 @@ var Protocol = class {
15496
14983
  params: task
15497
14984
  });
15498
14985
  await this.notification(notification);
15499
- if (isTerminal2(task.status)) {
14986
+ if (isTerminal(task.status)) {
15500
14987
  this._cleanupTaskProgressHandler(taskId);
15501
14988
  }
15502
14989
  }
@@ -15504,15 +14991,15 @@ var Protocol = class {
15504
14991
  getTaskResult: (taskId) => {
15505
14992
  return taskStore.getTaskResult(taskId, sessionId);
15506
14993
  },
15507
- updateTaskStatus: async (taskId, status2, statusMessage) => {
14994
+ updateTaskStatus: async (taskId, status, statusMessage) => {
15508
14995
  const task = await taskStore.getTask(taskId, sessionId);
15509
14996
  if (!task) {
15510
14997
  throw new McpError(ErrorCode.InvalidParams, `Task "${taskId}" not found - it may have been cleaned up`);
15511
14998
  }
15512
- if (isTerminal2(task.status)) {
15513
- throw new McpError(ErrorCode.InvalidParams, `Cannot update task "${taskId}" from terminal status "${task.status}" to "${status2}". Terminal states (completed, failed, cancelled) cannot transition to other states.`);
14999
+ if (isTerminal(task.status)) {
15000
+ throw new McpError(ErrorCode.InvalidParams, `Cannot update task "${taskId}" from terminal status "${task.status}" to "${status}". Terminal states (completed, failed, cancelled) cannot transition to other states.`);
15514
15001
  }
15515
- await taskStore.updateTaskStatus(taskId, status2, statusMessage, sessionId);
15002
+ await taskStore.updateTaskStatus(taskId, status, statusMessage, sessionId);
15516
15003
  const updatedTask = await taskStore.getTask(taskId, sessionId);
15517
15004
  if (updatedTask) {
15518
15005
  const notification = TaskStatusNotificationSchema.parse({
@@ -15520,7 +15007,7 @@ var Protocol = class {
15520
15007
  params: updatedTask
15521
15008
  });
15522
15009
  await this.notification(notification);
15523
- if (isTerminal2(updatedTask.status)) {
15010
+ if (isTerminal(updatedTask.status)) {
15524
15011
  this._cleanupTaskProgressHandler(taskId);
15525
15012
  }
15526
15013
  }
@@ -16230,123 +15717,2849 @@ var Server = class extends Protocol {
16230
15717
  method: "notifications/resources/list_changed"
16231
15718
  });
16232
15719
  }
16233
- async sendToolListChanged() {
16234
- return this.notification({ method: "notifications/tools/list_changed" });
15720
+ async sendToolListChanged() {
15721
+ return this.notification({ method: "notifications/tools/list_changed" });
15722
+ }
15723
+ async sendPromptListChanged() {
15724
+ return this.notification({ method: "notifications/prompts/list_changed" });
15725
+ }
15726
+ };
15727
+
15728
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
15729
+ import process3 from "process";
15730
+
15731
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
15732
+ var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
15733
+ var ReadBuffer = class {
15734
+ constructor(options) {
15735
+ this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
15736
+ }
15737
+ append(chunk) {
15738
+ const newSize = (this._buffer?.length ?? 0) + chunk.length;
15739
+ if (newSize > this._maxBufferSize) {
15740
+ this.clear();
15741
+ throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
15742
+ }
15743
+ this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
15744
+ }
15745
+ readMessage() {
15746
+ if (!this._buffer) {
15747
+ return null;
15748
+ }
15749
+ const index = this._buffer.indexOf("\n");
15750
+ if (index === -1) {
15751
+ return null;
15752
+ }
15753
+ const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
15754
+ this._buffer = this._buffer.subarray(index + 1);
15755
+ return deserializeMessage(line);
15756
+ }
15757
+ clear() {
15758
+ this._buffer = void 0;
15759
+ }
15760
+ };
15761
+ function deserializeMessage(line) {
15762
+ return JSONRPCMessageSchema.parse(JSON.parse(line));
15763
+ }
15764
+ function serializeMessage(message) {
15765
+ return JSON.stringify(message) + "\n";
15766
+ }
15767
+
15768
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
15769
+ var StdioServerTransport = class {
15770
+ constructor(_stdin = process3.stdin, _stdout = process3.stdout, options) {
15771
+ this._stdin = _stdin;
15772
+ this._stdout = _stdout;
15773
+ this._started = false;
15774
+ this._ondata = (chunk) => {
15775
+ try {
15776
+ this._readBuffer.append(chunk);
15777
+ this.processReadBuffer();
15778
+ } catch (error2) {
15779
+ this.onerror?.(error2);
15780
+ this.close().catch(() => {
15781
+ });
15782
+ }
15783
+ };
15784
+ this._onerror = (error2) => {
15785
+ this.onerror?.(error2);
15786
+ };
15787
+ this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
15788
+ }
15789
+ /**
15790
+ * Starts listening for messages on stdin.
15791
+ */
15792
+ async start() {
15793
+ if (this._started) {
15794
+ throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
15795
+ }
15796
+ this._started = true;
15797
+ this._stdin.on("data", this._ondata);
15798
+ this._stdin.on("error", this._onerror);
15799
+ }
15800
+ processReadBuffer() {
15801
+ while (true) {
15802
+ try {
15803
+ const message = this._readBuffer.readMessage();
15804
+ if (message === null) {
15805
+ break;
15806
+ }
15807
+ this.onmessage?.(message);
15808
+ } catch (error2) {
15809
+ this.onerror?.(error2);
15810
+ }
15811
+ }
15812
+ }
15813
+ async close() {
15814
+ this._stdin.off("data", this._ondata);
15815
+ this._stdin.off("error", this._onerror);
15816
+ const remainingDataListeners = this._stdin.listenerCount("data");
15817
+ if (remainingDataListeners === 0) {
15818
+ this._stdin.pause();
15819
+ }
15820
+ this._readBuffer.clear();
15821
+ this.onclose?.();
15822
+ }
15823
+ send(message) {
15824
+ return new Promise((resolve) => {
15825
+ const json = serializeMessage(message);
15826
+ if (this._stdout.write(json)) {
15827
+ resolve();
15828
+ } else {
15829
+ this._stdout.once("drain", resolve);
15830
+ }
15831
+ });
15832
+ }
15833
+ };
15834
+
15835
+ // src/mcp/tools.generated.ts
15836
+ var GENERATED_TOOLS = [
15837
+ {
15838
+ "name": "democut_auth_status",
15839
+ "description": "\uB85C\uADF8\uC778 \uC0C1\uD0DC\xB7\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\xB7\uC5ED\uD560\xB7\uD2F0\uC5B4\uB97C \uD655\uC778\uD55C\uB2E4. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. \uB2E4\uB978 \uB3C4\uAD6C\uAC00 \uAD8C\uD55C \uC624\uB958\uB97C \uB0B4\uBA74 \uBA3C\uC800 \uC774\uAC78\uB85C \uD655\uC778\uD558\uB77C. \uB2E4\uC74C \uD638\uCD9C: democut_list_projects, democut_create_project.",
15840
+ "inputSchema": {
15841
+ "type": "object",
15842
+ "properties": {},
15843
+ "required": [],
15844
+ "additionalProperties": false
15845
+ },
15846
+ "annotations": {
15847
+ "readOnlyHint": true,
15848
+ "destructiveHint": false,
15849
+ "idempotentHint": true,
15850
+ "openWorldHint": false
15851
+ }
15852
+ },
15853
+ {
15854
+ "name": "democut_list_projects",
15855
+ "description": "\uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC758 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D(\uCD5C\uADFC \uC218\uC815\uC21C). \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. \uCEF7\uC740 \uD504\uB85C\uC81D\uD2B8 \uC5C6\uC774 \uBABB \uB9CC\uB4E0\uB2E4(\uBE44\uC6A9 \uADC0\uC18D \uB2E8\uC704) \u2014 \uC5C6\uC73C\uBA74 democut_create_project. \uD504\uB85C\uC81D\uD2B8\uB97C \uC694\uAD6C\uD558\uB294 \uB3C4\uAD6C\uC758 slug \uB294 \uC2E4\uC7AC\uD558\uB294 \uBCF8\uC778 \uAC83\uC774\uC5B4\uC57C \uD558\uACE0 \uD2C0\uB9AC\uBA74 404 \uB2E4 \u2014 \uC2AC\uB7EC\uADF8\uB97C \uBAA8\uB974\uBA74 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 \uC774\uAC78\uB85C \uBA3C\uC800 \uD655\uC778\uD558\uB77C. \uB2E4\uC74C \uD638\uCD9C: democut_create_project, democut_get_options.",
15856
+ "inputSchema": {
15857
+ "type": "object",
15858
+ "properties": {
15859
+ "limit": {
15860
+ "default": 30,
15861
+ "description": "\uAC00\uC838\uC62C \uAC74\uC218 1~100",
15862
+ "maximum": 100,
15863
+ "minimum": 1,
15864
+ "title": "Limit",
15865
+ "type": "integer"
15866
+ },
15867
+ "query": {
15868
+ "anyOf": [
15869
+ {
15870
+ "maxLength": 200,
15871
+ "type": "string"
15872
+ },
15873
+ {
15874
+ "type": "null"
15875
+ }
15876
+ ],
15877
+ "default": null,
15878
+ "description": "\uC2AC\uB7EC\uADF8\xB7\uC81C\uBAA9 \uBD80\uBD84 \uC77C\uCE58(\uB300\uC18C\uBB38\uC790 \uBB34\uC2DC). \uC774\uB984\uC744 \uC54C \uB54C\uB9CC \uC4F4\uB2E4 \u2014 \uBE44\uC6B0\uBA74 \uCD5C\uADFC \uC218\uC815\uC21C \uC804\uCCB4",
15879
+ "title": "Query"
15880
+ }
15881
+ },
15882
+ "required": [],
15883
+ "additionalProperties": false
15884
+ },
15885
+ "annotations": {
15886
+ "readOnlyHint": true,
15887
+ "destructiveHint": false,
15888
+ "idempotentHint": true,
15889
+ "openWorldHint": false
15890
+ }
15891
+ },
15892
+ {
15893
+ "name": "democut_create_project",
15894
+ "description": "\uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E0\uB2E4 \u2014 \uACFC\uAE08\uC740 \uC5C6\uC9C0\uB9CC \uACC4\uC815\uC5D0 \uB0A8\uB294 **\uC4F0\uAE30** \uC791\uC5C5\uC774\uB2E4. \uBE44\uC728(16:9|9:16|1:1)\uC740 \uC0DD\uC131 \uD6C4 \uBC14\uAFC0 \uC218 \uC5C6\uB2E4. \uAC19\uC740 \uC81C\uBAA9\uC73C\uB85C \uB2E4\uC2DC \uBD80\uB974\uBA74 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uC54A\uACE0 \uAE30\uC874 \uAC83\uC744 \uB3CC\uB824\uC900\uB2E4(\uC7AC\uC2DC\uB3C4 \uC548\uC804). \u2605 \uBA3C\uC800 democut_list_projects \uB85C \uC4F8 \uB9CC\uD55C \uAC83\uC774 \uC774\uBBF8 \uC788\uB294\uC9C0 \uBCF4\uACE0 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC5B4\uB290 \uAC83\uC5D0 \uB123\uC744\uC9C0 \uBB3C\uC5B4\uB77C \u2014 \uBB3B\uC9C0 \uC54A\uACE0 \uB9CC\uB4E4\uBA74 \uBE44\uC2B7\uD55C \uD504\uB85C\uC81D\uD2B8\uAC00 \uC313\uC778\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_get_options, democut_upload_asset, democut_estimate_cuts.",
15895
+ "inputSchema": {
15896
+ "type": "object",
15897
+ "properties": {
15898
+ "title": {
15899
+ "maxLength": 200,
15900
+ "minLength": 1,
15901
+ "title": "Title",
15902
+ "type": "string"
15903
+ },
15904
+ "ratio": {
15905
+ "default": "16:9",
15906
+ "description": "\uC0DD\uC131 \uD6C4 \uACE0\uC815(R24)",
15907
+ "enum": [
15908
+ "16:9",
15909
+ "9:16",
15910
+ "1:1"
15911
+ ],
15912
+ "title": "Ratio",
15913
+ "type": "string"
15914
+ },
15915
+ "resolution": {
15916
+ "default": "1080p",
15917
+ "enum": [
15918
+ "720p",
15919
+ "1080p"
15920
+ ],
15921
+ "title": "Resolution",
15922
+ "type": "string"
15923
+ },
15924
+ "folder_id": {
15925
+ "anyOf": [
15926
+ {
15927
+ "type": "string"
15928
+ },
15929
+ {
15930
+ "type": "null"
15931
+ }
15932
+ ],
15933
+ "default": null,
15934
+ "title": "Folder Id"
15935
+ },
15936
+ "defaults": {
15937
+ "anyOf": [
15938
+ {
15939
+ "$ref": "#/$defs/ProjectDefaults"
15940
+ },
15941
+ {
15942
+ "type": "null"
15943
+ }
15944
+ ],
15945
+ "default": null
15946
+ }
15947
+ },
15948
+ "required": [
15949
+ "title"
15950
+ ],
15951
+ "additionalProperties": false,
15952
+ "$defs": {
15953
+ "Brand": {
15954
+ "additionalProperties": false,
15955
+ "properties": {
15956
+ "accent_hex": {
15957
+ "anyOf": [
15958
+ {
15959
+ "pattern": "^#[0-9A-Fa-f]{6}$",
15960
+ "type": "string"
15961
+ },
15962
+ {
15963
+ "type": "null"
15964
+ }
15965
+ ],
15966
+ "default": null,
15967
+ "title": "Accent Hex"
15968
+ },
15969
+ "heading_font": {
15970
+ "anyOf": [
15971
+ {
15972
+ "type": "string"
15973
+ },
15974
+ {
15975
+ "type": "null"
15976
+ }
15977
+ ],
15978
+ "default": null,
15979
+ "title": "Heading Font"
15980
+ },
15981
+ "body_font": {
15982
+ "anyOf": [
15983
+ {
15984
+ "type": "string"
15985
+ },
15986
+ {
15987
+ "type": "null"
15988
+ }
15989
+ ],
15990
+ "default": null,
15991
+ "title": "Body Font"
15992
+ },
15993
+ "logo_asset_id": {
15994
+ "anyOf": [
15995
+ {
15996
+ "type": "string"
15997
+ },
15998
+ {
15999
+ "type": "null"
16000
+ }
16001
+ ],
16002
+ "default": null,
16003
+ "title": "Logo Asset Id"
16004
+ }
16005
+ },
16006
+ "title": "Brand",
16007
+ "type": "object"
16008
+ },
16009
+ "ProjectDefaults": {
16010
+ "additionalProperties": false,
16011
+ "properties": {
16012
+ "voice_id": {
16013
+ "anyOf": [
16014
+ {
16015
+ "type": "string"
16016
+ },
16017
+ {
16018
+ "type": "null"
16019
+ }
16020
+ ],
16021
+ "default": null,
16022
+ "title": "Voice Id"
16023
+ },
16024
+ "character_id": {
16025
+ "anyOf": [
16026
+ {
16027
+ "type": "string"
16028
+ },
16029
+ {
16030
+ "type": "null"
16031
+ }
16032
+ ],
16033
+ "default": null,
16034
+ "title": "Character Id"
16035
+ },
16036
+ "subtitles": {
16037
+ "default": false,
16038
+ "title": "Subtitles",
16039
+ "type": "boolean"
16040
+ },
16041
+ "brand": {
16042
+ "$ref": "#/$defs/Brand"
16043
+ }
16044
+ },
16045
+ "title": "ProjectDefaults",
16046
+ "type": "object"
16047
+ }
16048
+ }
16049
+ },
16050
+ "annotations": {
16051
+ "readOnlyHint": false,
16052
+ "destructiveHint": false,
16053
+ "idempotentHint": false,
16054
+ "openWorldHint": false
16055
+ }
16056
+ },
16057
+ {
16058
+ "name": "democut_get_options",
16059
+ "description": "\uC774 \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uC4F8 \uC218 \uC788\uB294 \uBC29\uC2DD\xB7\uC9C4\uD589(host)\xB7\uD544\uC218 \uD544\uB4DC\xB7BYO \uD544\uB4DC\xB7\uBCF4\uC774\uC2A4\xB7\uC544\uBC14\uD0C0\xB7\uBC30\uACBD\xB7\uB2E8\uAC00\xB7\uC794\uC561. recommended_mode=ai_video. \uB2E8\uAC00\uB294 \uCC38\uACE0\uAC12\uC774\uB2E4 \u2014 \uCCAD\uAD6C\uB294 democut_estimate_cuts \uC758 \uAC12\uC73C\uB85C. \uB2E4\uC74C \uD638\uCD9C: democut_upload_asset, democut_estimate_cuts.",
16060
+ "inputSchema": {
16061
+ "type": "object",
16062
+ "properties": {
16063
+ "slug": {
16064
+ "type": "string",
16065
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
16066
+ }
16067
+ },
16068
+ "required": [
16069
+ "slug"
16070
+ ],
16071
+ "additionalProperties": false
16072
+ },
16073
+ "annotations": {
16074
+ "readOnlyHint": true,
16075
+ "destructiveHint": false,
16076
+ "idempotentHint": true,
16077
+ "openWorldHint": false
16078
+ }
16079
+ },
16080
+ {
16081
+ "name": "democut_upload_asset",
16082
+ "description": "\uC774\uBBF8\uC9C0\xB7\uB098\uB808\uC774\uC158 wav\xB7\uC6D0\uBCF8 \uC601\uC0C1\xB7tsx\xB7\uC644\uC131 \uCEF7 \uC601\uC0C1\uC744 \uC790\uC0B0\uC73C\uB85C \uC62C\uB9B0\uB2E4(0\uC6D0). \uC751\uB2F5\uC758 state \uAC00 ready \uC5EC\uC57C spec \uC5D0 \uC4F8 \uC218 \uC788\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_estimate_cuts, democut_import_cut.",
16083
+ "inputSchema": {
16084
+ "type": "object",
16085
+ "properties": {
16086
+ "kind": {
16087
+ "enum": [
16088
+ "image",
16089
+ "video",
16090
+ "audio",
16091
+ "subtitle",
16092
+ "code",
16093
+ "archive"
16094
+ ],
16095
+ "title": "Kind",
16096
+ "type": "string"
16097
+ },
16098
+ "project_slug": {
16099
+ "anyOf": [
16100
+ {
16101
+ "type": "string"
16102
+ },
16103
+ {
16104
+ "type": "null"
16105
+ }
16106
+ ],
16107
+ "default": null,
16108
+ "title": "Project Slug"
16109
+ },
16110
+ "source_url": {
16111
+ "anyOf": [
16112
+ {
16113
+ "minLength": 1,
16114
+ "type": "string"
16115
+ },
16116
+ {
16117
+ "type": "null"
16118
+ }
16119
+ ],
16120
+ "default": null,
16121
+ "description": "\uC6D0\uACA9: https \uACF5\uAC1C \uC8FC\uC18C\uC5D0\uC11C \uAC00\uC838\uC628\uB2E4(202, \uC7A1). stdio \uB294 local_path",
16122
+ "title": "Source Url"
16123
+ },
16124
+ "filename": {
16125
+ "anyOf": [
16126
+ {
16127
+ "type": "string"
16128
+ },
16129
+ {
16130
+ "type": "null"
16131
+ }
16132
+ ],
16133
+ "default": null,
16134
+ "title": "Filename"
16135
+ },
16136
+ "local_path": {
16137
+ "type": "string",
16138
+ "description": "\uC62C\uB9B4 \uD30C\uC77C\uC758 \uB85C\uCEEC \uACBD\uB85C(stdio \uC804\uC6A9). source_url \uACFC \uB458 \uC911 \uD558\uB098"
16139
+ }
16140
+ },
16141
+ "required": [
16142
+ "kind"
16143
+ ],
16144
+ "additionalProperties": false,
16145
+ "oneOf": [
16146
+ {
16147
+ "required": [
16148
+ "local_path"
16149
+ ]
16150
+ },
16151
+ {
16152
+ "required": [
16153
+ "source_url"
16154
+ ]
16155
+ }
16156
+ ]
16157
+ },
16158
+ "annotations": {
16159
+ "readOnlyHint": false,
16160
+ "destructiveHint": false,
16161
+ "idempotentHint": false,
16162
+ "openWorldHint": false
16163
+ }
16164
+ },
16165
+ {
16166
+ "name": "democut_estimate_cuts",
16167
+ "description": "\uCEF7 N \uAC1C\uC758 \uACAC\uC801(0\uC6D0, \uBD80\uC791\uC6A9 \uC5C6\uC74C). \uC751\uB2F5\uC758 total_krw\xB7rate_version\xB7can_afford \uB97C \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBCF4\uC5EC \uC8FC\uACE0 \uADF8\uB300\uB85C democut_make_cuts \uC5D0 \uB123\uC5B4\uB77C. BYO \uD544\uB4DC(image_asset_id\xB7narration_asset_id\xB7tsx\xB7source.asset_id)\uB97C \uC8FC\uBA74 \uADF8 \uD589\uC740 0\uC6D0\uC774\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_make_cuts.",
16168
+ "inputSchema": {
16169
+ "type": "object",
16170
+ "properties": {
16171
+ "slug": {
16172
+ "type": "string",
16173
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
16174
+ },
16175
+ "items": {
16176
+ "items": {
16177
+ "$ref": "#/$defs/EstimateItem"
16178
+ },
16179
+ "maxItems": 50,
16180
+ "title": "Items",
16181
+ "type": "array"
16182
+ },
16183
+ "imports": {
16184
+ "items": {
16185
+ "$ref": "#/$defs/ImportEstimateItem"
16186
+ },
16187
+ "maxItems": 50,
16188
+ "title": "Imports",
16189
+ "type": "array"
16190
+ }
16191
+ },
16192
+ "required": [
16193
+ "slug"
16194
+ ],
16195
+ "additionalProperties": false,
16196
+ "$defs": {
16197
+ "AiVideoSpec": {
16198
+ "additionalProperties": false,
16199
+ "properties": {
16200
+ "dialogue": {
16201
+ "items": {
16202
+ "$ref": "#/$defs/DialogueLine"
16203
+ },
16204
+ "title": "Dialogue",
16205
+ "type": "array"
16206
+ },
16207
+ "narration_asset_id": {
16208
+ "anyOf": [
16209
+ {
16210
+ "minLength": 1,
16211
+ "type": "string"
16212
+ },
16213
+ {
16214
+ "type": "null"
16215
+ }
16216
+ ],
16217
+ "default": null,
16218
+ "description": "BYO: \uCEF7 \uC804\uCCB4 \uB098\uB808\uC774\uC158 wav \uD55C \uAC1C(\uB300\uC0AC\uAC00 \uC788\uC5B4\uC57C \uD55C\uB2E4 \u2014 \uC790\uB9C9\xB7\uD0C0\uC774\uBC0D\uC758 \uADFC\uAC70). \uC904\uBCC4 audio_asset_id \uC640 \uB3D9\uC2DC \uC9C0\uC815 422",
16219
+ "title": "Narration Asset Id"
16220
+ },
16221
+ "subtitles": {
16222
+ "default": false,
16223
+ "title": "Subtitles",
16224
+ "type": "boolean"
16225
+ },
16226
+ "host": {
16227
+ "anyOf": [
16228
+ {
16229
+ "type": "string"
16230
+ },
16231
+ {
16232
+ "type": "null"
16233
+ }
16234
+ ],
16235
+ "default": null,
16236
+ "description": "\uC9C4\uD589 \u2014 \uD5C8\uC6A9 \uC9D1\uD569\uC740 \uCE74\uD0C8\uB85C\uADF8(\uBC29\uC2DD\uBCC4). \uBAA8\uC158\uADF8\uB798\uD53D\uC740 \uD544\uC218",
16237
+ "title": "Host"
16238
+ },
16239
+ "voice_id": {
16240
+ "anyOf": [
16241
+ {
16242
+ "minLength": 1,
16243
+ "type": "string"
16244
+ },
16245
+ {
16246
+ "type": "null"
16247
+ }
16248
+ ],
16249
+ "default": null,
16250
+ "description": "host\u2208{voice,avatar} \uC774\uACE0 BYO \uC624\uB514\uC624\uAC00 \uC5C6\uC744 \uB54C \uD544\uC218",
16251
+ "title": "Voice Id"
16252
+ },
16253
+ "pip": {
16254
+ "anyOf": [
16255
+ {
16256
+ "$ref": "#/$defs/PipSpec"
16257
+ },
16258
+ {
16259
+ "type": "null"
16260
+ }
16261
+ ],
16262
+ "default": null,
16263
+ "description": "host=avatar \uC77C \uB54C \uD544\uC218"
16264
+ },
16265
+ "image_asset_id": {
16266
+ "anyOf": [
16267
+ {
16268
+ "minLength": 1,
16269
+ "type": "string"
16270
+ },
16271
+ {
16272
+ "type": "null"
16273
+ }
16274
+ ],
16275
+ "default": null,
16276
+ "description": "\uCEF7 \uC774\uBBF8\uC9C0\uB97C spec \uC5D0\uC11C \uC9C1\uC811 \uC9C0\uC815(\uC5D0\uC774\uC804\uD2B8 \uC6D0\uC0F7\uC6A9)",
16277
+ "title": "Image Asset Id"
16278
+ },
16279
+ "duration_s": {
16280
+ "default": 5,
16281
+ "maximum": 15,
16282
+ "minimum": 4,
16283
+ "title": "Duration S",
16284
+ "type": "number"
16285
+ },
16286
+ "mode": {
16287
+ "const": "ai_video",
16288
+ "default": "ai_video",
16289
+ "title": "Mode",
16290
+ "type": "string"
16291
+ },
16292
+ "image_prompt": {
16293
+ "maxLength": 4e3,
16294
+ "minLength": 1,
16295
+ "title": "Image Prompt",
16296
+ "type": "string"
16297
+ },
16298
+ "provider": {
16299
+ "anyOf": [
16300
+ {
16301
+ "maxLength": 32,
16302
+ "minLength": 1,
16303
+ "type": "string"
16304
+ },
16305
+ {
16306
+ "type": "null"
16307
+ }
16308
+ ],
16309
+ "default": null,
16310
+ "description": "\uC601\uC0C1 \uC0DD\uC131 \uACF5\uAE09\uC790(\uC608: minimax). \uBE44\uC6B0\uBA74 \uC11C\uBC84 \uAE30\uBCF8\uAC12 \u2014 \uC4F8 \uC218 \uC788\uB294 \uBAA9\uB85D\uC740 GET \u2026/options \uC758 videogen_providers",
16311
+ "title": "Provider"
16312
+ },
16313
+ "seed": {
16314
+ "anyOf": [
16315
+ {
16316
+ "minimum": 0,
16317
+ "type": "integer"
16318
+ },
16319
+ {
16320
+ "type": "null"
16321
+ }
16322
+ ],
16323
+ "default": null,
16324
+ "title": "Seed"
16325
+ },
16326
+ "image": {
16327
+ "anyOf": [
16328
+ {
16329
+ "discriminator": {
16330
+ "mapping": {
16331
+ "asset": "#/$defs/AssetImageRef",
16332
+ "from_cut": "#/$defs/FromCutImageRef",
16333
+ "from_version": "#/$defs/FromVersionImageRef"
16334
+ },
16335
+ "propertyName": "kind"
16336
+ },
16337
+ "oneOf": [
16338
+ {
16339
+ "$ref": "#/$defs/AssetImageRef"
16340
+ },
16341
+ {
16342
+ "$ref": "#/$defs/FromCutImageRef"
16343
+ },
16344
+ {
16345
+ "$ref": "#/$defs/FromVersionImageRef"
16346
+ }
16347
+ ]
16348
+ },
16349
+ {
16350
+ "type": "null"
16351
+ }
16352
+ ],
16353
+ "default": null,
16354
+ "description": "\uCCAB \uD504\uB808\uC784. \uC5C6\uC73C\uBA74 image_asset_id \u2192 \uCEF7 \uC774\uBBF8\uC9C0 \u2192 t2v \uC21C",
16355
+ "title": "Image"
16356
+ },
16357
+ "end_image": {
16358
+ "anyOf": [
16359
+ {
16360
+ "discriminator": {
16361
+ "mapping": {
16362
+ "asset": "#/$defs/AssetImageRef",
16363
+ "from_cut": "#/$defs/FromCutImageRef",
16364
+ "from_version": "#/$defs/FromVersionImageRef"
16365
+ },
16366
+ "propertyName": "kind"
16367
+ },
16368
+ "oneOf": [
16369
+ {
16370
+ "$ref": "#/$defs/AssetImageRef"
16371
+ },
16372
+ {
16373
+ "$ref": "#/$defs/FromCutImageRef"
16374
+ },
16375
+ {
16376
+ "$ref": "#/$defs/FromVersionImageRef"
16377
+ }
16378
+ ]
16379
+ },
16380
+ {
16381
+ "type": "null"
16382
+ }
16383
+ ],
16384
+ "default": null,
16385
+ "title": "End Image"
16386
+ }
16387
+ },
16388
+ "required": [
16389
+ "image_prompt"
16390
+ ],
16391
+ "title": "AiVideoSpec",
16392
+ "type": "object"
16393
+ },
16394
+ "AssetImageRef": {
16395
+ "additionalProperties": false,
16396
+ "properties": {
16397
+ "kind": {
16398
+ "const": "asset",
16399
+ "default": "asset",
16400
+ "title": "Kind",
16401
+ "type": "string"
16402
+ },
16403
+ "asset_id": {
16404
+ "minLength": 1,
16405
+ "title": "Asset Id",
16406
+ "type": "string"
16407
+ }
16408
+ },
16409
+ "required": [
16410
+ "asset_id"
16411
+ ],
16412
+ "title": "AssetImageRef",
16413
+ "type": "object"
16414
+ },
16415
+ "DialogueLine": {
16416
+ "additionalProperties": false,
16417
+ "properties": {
16418
+ "id": {
16419
+ "description": "\uC904 id ln_<6> \u2014 \uC81C\uC548 diff \uC758 \uB300\uC870 \uD0A4",
16420
+ "pattern": "^ln_[a-z0-9]{6}$",
16421
+ "title": "Id",
16422
+ "type": "string",
16423
+ "x-diff": "ignore"
16424
+ },
16425
+ "text": {
16426
+ "description": "\uBC1C\uD654 \uD14D\uC2A4\uD2B8(\uC22B\uC790\uB294 \uC11C\uBC84\uAC00 \uC77D\uB294 \uBC95\uC744 \uC815\uD55C\uB2E4 \u2014 \uD480\uC5B4\uC4F0\uC9C0 \uC54A\uB294\uB2E4)",
16427
+ "maxLength": 2e3,
16428
+ "minLength": 1,
16429
+ "title": "Text",
16430
+ "type": "string"
16431
+ },
16432
+ "subtitle_text": {
16433
+ "anyOf": [
16434
+ {
16435
+ "maxLength": 2e3,
16436
+ "type": "string"
16437
+ },
16438
+ {
16439
+ "type": "null"
16440
+ }
16441
+ ],
16442
+ "default": null,
16443
+ "description": "\uC790\uB9C9 \uD45C\uAE30(\uC6D0\uBB38 \uD45C\uAE30). \uC5C6\uC73C\uBA74 text",
16444
+ "title": "Subtitle Text"
16445
+ },
16446
+ "audio_asset_id": {
16447
+ "anyOf": [
16448
+ {
16449
+ "minLength": 1,
16450
+ "type": "string"
16451
+ },
16452
+ {
16453
+ "type": "null"
16454
+ }
16455
+ ],
16456
+ "default": null,
16457
+ "description": "BYO: \uC774 \uC904\uC758 \uB098\uB808\uC774\uC158 \uC624\uB514\uC624 \uC790\uC0B0 \u2014 TTS \uD589 0\uC6D0, \uC815\uB82C \uD589\uB9CC",
16458
+ "title": "Audio Asset Id"
16459
+ }
16460
+ },
16461
+ "required": [
16462
+ "id",
16463
+ "text"
16464
+ ],
16465
+ "title": "DialogueLine",
16466
+ "type": "object"
16467
+ },
16468
+ "EstimateItem": {
16469
+ "additionalProperties": false,
16470
+ "properties": {
16471
+ "cut_id": {
16472
+ "anyOf": [
16473
+ {
16474
+ "type": "string"
16475
+ },
16476
+ {
16477
+ "type": "null"
16478
+ }
16479
+ ],
16480
+ "default": null,
16481
+ "description": "\uC5C6\uC73C\uBA74 \uC0C8 \uCEF7(\uC11C\uBC84\uAC00 ULID \uB97C \uB9CC\uB4E0\uB2E4)",
16482
+ "title": "Cut Id"
16483
+ },
16484
+ "spec": {
16485
+ "discriminator": {
16486
+ "mapping": {
16487
+ "ai_video": "#/$defs/AiVideoSpec",
16488
+ "motion_graphic": "#/$defs/MotionGraphicSpec",
16489
+ "youtube_clip": "#/$defs/YoutubeClipSpec"
16490
+ },
16491
+ "propertyName": "mode"
16492
+ },
16493
+ "oneOf": [
16494
+ {
16495
+ "$ref": "#/$defs/MotionGraphicSpec"
16496
+ },
16497
+ {
16498
+ "$ref": "#/$defs/AiVideoSpec"
16499
+ },
16500
+ {
16501
+ "$ref": "#/$defs/YoutubeClipSpec"
16502
+ }
16503
+ ],
16504
+ "title": "Spec"
16505
+ }
16506
+ },
16507
+ "required": [
16508
+ "spec"
16509
+ ],
16510
+ "title": "EstimateItem",
16511
+ "type": "object"
16512
+ },
16513
+ "FromCutImageRef": {
16514
+ "additionalProperties": false,
16515
+ "properties": {
16516
+ "kind": {
16517
+ "const": "from_cut",
16518
+ "default": "from_cut",
16519
+ "title": "Kind",
16520
+ "type": "string"
16521
+ },
16522
+ "from_cut": {
16523
+ "description": "\uB2E4\uB978 \uCEF7\uC758 \uB300\uD45C \uBC84\uC804 \uD504\uB808\uC784(\uC5F0\uC18D\uC131 \uB3C4\uC6B0\uBBF8)",
16524
+ "minLength": 1,
16525
+ "title": "From Cut",
16526
+ "type": "string"
16527
+ },
16528
+ "frame": {
16529
+ "default": "last",
16530
+ "enum": [
16531
+ "first",
16532
+ "last"
16533
+ ],
16534
+ "title": "Frame",
16535
+ "type": "string"
16536
+ }
16537
+ },
16538
+ "required": [
16539
+ "from_cut"
16540
+ ],
16541
+ "title": "FromCutImageRef",
16542
+ "type": "object"
16543
+ },
16544
+ "FromVersionImageRef": {
16545
+ "additionalProperties": false,
16546
+ "properties": {
16547
+ "kind": {
16548
+ "const": "from_version",
16549
+ "default": "from_version",
16550
+ "title": "Kind",
16551
+ "type": "string"
16552
+ },
16553
+ "from_version": {
16554
+ "description": "\uC774 \uCEF7\uC758 \uD2B9\uC815 \uBC84\uC804 \uD504\uB808\uC784",
16555
+ "minimum": 1,
16556
+ "title": "From Version",
16557
+ "type": "integer"
16558
+ },
16559
+ "frame": {
16560
+ "default": "last",
16561
+ "enum": [
16562
+ "first",
16563
+ "last"
16564
+ ],
16565
+ "title": "Frame",
16566
+ "type": "string"
16567
+ }
16568
+ },
16569
+ "required": [
16570
+ "from_version"
16571
+ ],
16572
+ "title": "FromVersionImageRef",
16573
+ "type": "object"
16574
+ },
16575
+ "ImportEstimateItem": {
16576
+ "additionalProperties": false,
16577
+ "properties": {
16578
+ "cut_id": {
16579
+ "title": "Cut Id",
16580
+ "type": "string"
16581
+ },
16582
+ "video_asset_id": {
16583
+ "title": "Video Asset Id",
16584
+ "type": "string"
16585
+ },
16586
+ "transcribe": {
16587
+ "default": false,
16588
+ "title": "Transcribe",
16589
+ "type": "boolean"
16590
+ }
16591
+ },
16592
+ "required": [
16593
+ "cut_id",
16594
+ "video_asset_id"
16595
+ ],
16596
+ "title": "ImportEstimateItem",
16597
+ "type": "object"
16598
+ },
16599
+ "MotionGraphicSpec": {
16600
+ "additionalProperties": false,
16601
+ "properties": {
16602
+ "dialogue": {
16603
+ "items": {
16604
+ "$ref": "#/$defs/DialogueLine"
16605
+ },
16606
+ "title": "Dialogue",
16607
+ "type": "array"
16608
+ },
16609
+ "narration_asset_id": {
16610
+ "anyOf": [
16611
+ {
16612
+ "minLength": 1,
16613
+ "type": "string"
16614
+ },
16615
+ {
16616
+ "type": "null"
16617
+ }
16618
+ ],
16619
+ "default": null,
16620
+ "description": "BYO: \uCEF7 \uC804\uCCB4 \uB098\uB808\uC774\uC158 wav \uD55C \uAC1C(\uB300\uC0AC\uAC00 \uC788\uC5B4\uC57C \uD55C\uB2E4 \u2014 \uC790\uB9C9\xB7\uD0C0\uC774\uBC0D\uC758 \uADFC\uAC70). \uC904\uBCC4 audio_asset_id \uC640 \uB3D9\uC2DC \uC9C0\uC815 422",
16621
+ "title": "Narration Asset Id"
16622
+ },
16623
+ "subtitles": {
16624
+ "default": false,
16625
+ "title": "Subtitles",
16626
+ "type": "boolean"
16627
+ },
16628
+ "host": {
16629
+ "anyOf": [
16630
+ {
16631
+ "type": "string"
16632
+ },
16633
+ {
16634
+ "type": "null"
16635
+ }
16636
+ ],
16637
+ "default": null,
16638
+ "description": "\uC9C4\uD589 \u2014 \uD5C8\uC6A9 \uC9D1\uD569\uC740 \uCE74\uD0C8\uB85C\uADF8(\uBC29\uC2DD\uBCC4). \uBAA8\uC158\uADF8\uB798\uD53D\uC740 \uD544\uC218",
16639
+ "title": "Host"
16640
+ },
16641
+ "voice_id": {
16642
+ "anyOf": [
16643
+ {
16644
+ "minLength": 1,
16645
+ "type": "string"
16646
+ },
16647
+ {
16648
+ "type": "null"
16649
+ }
16650
+ ],
16651
+ "default": null,
16652
+ "description": "host\u2208{voice,avatar} \uC774\uACE0 BYO \uC624\uB514\uC624\uAC00 \uC5C6\uC744 \uB54C \uD544\uC218",
16653
+ "title": "Voice Id"
16654
+ },
16655
+ "pip": {
16656
+ "anyOf": [
16657
+ {
16658
+ "$ref": "#/$defs/PipSpec"
16659
+ },
16660
+ {
16661
+ "type": "null"
16662
+ }
16663
+ ],
16664
+ "default": null,
16665
+ "description": "host=avatar \uC77C \uB54C \uD544\uC218"
16666
+ },
16667
+ "image_asset_id": {
16668
+ "anyOf": [
16669
+ {
16670
+ "minLength": 1,
16671
+ "type": "string"
16672
+ },
16673
+ {
16674
+ "type": "null"
16675
+ }
16676
+ ],
16677
+ "default": null,
16678
+ "description": "\uCEF7 \uC774\uBBF8\uC9C0\uB97C spec \uC5D0\uC11C \uC9C1\uC811 \uC9C0\uC815(\uC5D0\uC774\uC804\uD2B8 \uC6D0\uC0F7\uC6A9)",
16679
+ "title": "Image Asset Id"
16680
+ },
16681
+ "duration_s": {
16682
+ "anyOf": [
16683
+ {
16684
+ "exclusiveMinimum": 0,
16685
+ "maximum": 600,
16686
+ "type": "number"
16687
+ },
16688
+ {
16689
+ "type": "null"
16690
+ }
16691
+ ],
16692
+ "default": null,
16693
+ "title": "Duration S"
16694
+ },
16695
+ "mode": {
16696
+ "const": "motion_graphic",
16697
+ "default": "motion_graphic",
16698
+ "title": "Mode",
16699
+ "type": "string"
16700
+ },
16701
+ "motion_prompt": {
16702
+ "anyOf": [
16703
+ {
16704
+ "maxLength": 4e3,
16705
+ "type": "string"
16706
+ },
16707
+ {
16708
+ "type": "null"
16709
+ }
16710
+ ],
16711
+ "default": null,
16712
+ "title": "Motion Prompt"
16713
+ },
16714
+ "tsx": {
16715
+ "anyOf": [
16716
+ {
16717
+ "maxLength": 2e5,
16718
+ "type": "string"
16719
+ },
16720
+ {
16721
+ "type": "null"
16722
+ }
16723
+ ],
16724
+ "default": null,
16725
+ "description": "BYO Remotion \uCF54\uB4DC(UTF-8 \u2264 200KB) \u2014 codegen \uD589 0\uC6D0, \uAC8C\uC774\uD2B8\uB294 codegen \uACFC \uB3D9\uAE09",
16726
+ "title": "Tsx"
16727
+ },
16728
+ "brand_override": {
16729
+ "anyOf": [
16730
+ {
16731
+ "additionalProperties": true,
16732
+ "type": "object"
16733
+ },
16734
+ {
16735
+ "type": "null"
16736
+ }
16737
+ ],
16738
+ "default": null,
16739
+ "title": "Brand Override"
16740
+ }
16741
+ },
16742
+ "title": "MotionGraphicSpec",
16743
+ "type": "object"
16744
+ },
16745
+ "PipSpec": {
16746
+ "additionalProperties": false,
16747
+ "properties": {
16748
+ "avatar_id": {
16749
+ "minLength": 1,
16750
+ "title": "Avatar Id",
16751
+ "type": "string"
16752
+ },
16753
+ "background_asset_id": {
16754
+ "description": "\uBC30\uACBD\uC740 \uC5B8\uC81C\uB098 \uC790\uC0B0(origin=background \uCE74\uD0C8\uB85C\uADF8 \uB610\uB294 \uC62C\uB9B0 \uC774\uBBF8\uC9C0)",
16755
+ "minLength": 1,
16756
+ "title": "Background Asset Id",
16757
+ "type": "string"
16758
+ },
16759
+ "position": {
16760
+ "default": "br",
16761
+ "enum": [
16762
+ "tl",
16763
+ "tr",
16764
+ "bl",
16765
+ "br"
16766
+ ],
16767
+ "title": "Position",
16768
+ "type": "string"
16769
+ },
16770
+ "size": {
16771
+ "default": "m",
16772
+ "enum": [
16773
+ "s",
16774
+ "m",
16775
+ "l"
16776
+ ],
16777
+ "title": "Size",
16778
+ "type": "string"
16779
+ }
16780
+ },
16781
+ "required": [
16782
+ "avatar_id",
16783
+ "background_asset_id"
16784
+ ],
16785
+ "title": "PipSpec",
16786
+ "type": "object"
16787
+ },
16788
+ "YoutubeAssetSource": {
16789
+ "additionalProperties": false,
16790
+ "properties": {
16791
+ "kind": {
16792
+ "const": "asset",
16793
+ "default": "asset",
16794
+ "title": "Kind",
16795
+ "type": "string"
16796
+ },
16797
+ "asset_id": {
16798
+ "description": "BYO: \uC62C\uB9B0 \uC6D0\uBCF8 \uC601\uC0C1 \u2014 \uB0B4\uB824\uBC1B\uAE30 \uD589 0\uC6D0",
16799
+ "minLength": 1,
16800
+ "title": "Asset Id",
16801
+ "type": "string"
16802
+ },
16803
+ "start_s": {
16804
+ "anyOf": [
16805
+ {
16806
+ "minimum": 0,
16807
+ "type": "number"
16808
+ },
16809
+ {
16810
+ "type": "null"
16811
+ }
16812
+ ],
16813
+ "default": null,
16814
+ "title": "Start S"
16815
+ },
16816
+ "end_s": {
16817
+ "anyOf": [
16818
+ {
16819
+ "exclusiveMinimum": 0,
16820
+ "type": "number"
16821
+ },
16822
+ {
16823
+ "type": "null"
16824
+ }
16825
+ ],
16826
+ "default": null,
16827
+ "title": "End S"
16828
+ }
16829
+ },
16830
+ "required": [
16831
+ "asset_id"
16832
+ ],
16833
+ "title": "YoutubeAssetSource",
16834
+ "type": "object"
16835
+ },
16836
+ "YoutubeClipSpec": {
16837
+ "additionalProperties": false,
16838
+ "properties": {
16839
+ "dialogue": {
16840
+ "items": {
16841
+ "$ref": "#/$defs/DialogueLine"
16842
+ },
16843
+ "title": "Dialogue",
16844
+ "type": "array"
16845
+ },
16846
+ "narration_asset_id": {
16847
+ "anyOf": [
16848
+ {
16849
+ "minLength": 1,
16850
+ "type": "string"
16851
+ },
16852
+ {
16853
+ "type": "null"
16854
+ }
16855
+ ],
16856
+ "default": null,
16857
+ "description": "BYO: \uCEF7 \uC804\uCCB4 \uB098\uB808\uC774\uC158 wav \uD55C \uAC1C(\uB300\uC0AC\uAC00 \uC788\uC5B4\uC57C \uD55C\uB2E4 \u2014 \uC790\uB9C9\xB7\uD0C0\uC774\uBC0D\uC758 \uADFC\uAC70). \uC904\uBCC4 audio_asset_id \uC640 \uB3D9\uC2DC \uC9C0\uC815 422",
16858
+ "title": "Narration Asset Id"
16859
+ },
16860
+ "subtitles": {
16861
+ "default": false,
16862
+ "title": "Subtitles",
16863
+ "type": "boolean"
16864
+ },
16865
+ "host": {
16866
+ "anyOf": [
16867
+ {
16868
+ "type": "string"
16869
+ },
16870
+ {
16871
+ "type": "null"
16872
+ }
16873
+ ],
16874
+ "default": null,
16875
+ "description": "\uC9C4\uD589 \u2014 \uD5C8\uC6A9 \uC9D1\uD569\uC740 \uCE74\uD0C8\uB85C\uADF8(\uBC29\uC2DD\uBCC4). \uBAA8\uC158\uADF8\uB798\uD53D\uC740 \uD544\uC218",
16876
+ "title": "Host"
16877
+ },
16878
+ "voice_id": {
16879
+ "anyOf": [
16880
+ {
16881
+ "minLength": 1,
16882
+ "type": "string"
16883
+ },
16884
+ {
16885
+ "type": "null"
16886
+ }
16887
+ ],
16888
+ "default": null,
16889
+ "description": "host\u2208{voice,avatar} \uC774\uACE0 BYO \uC624\uB514\uC624\uAC00 \uC5C6\uC744 \uB54C \uD544\uC218",
16890
+ "title": "Voice Id"
16891
+ },
16892
+ "pip": {
16893
+ "anyOf": [
16894
+ {
16895
+ "$ref": "#/$defs/PipSpec"
16896
+ },
16897
+ {
16898
+ "type": "null"
16899
+ }
16900
+ ],
16901
+ "default": null,
16902
+ "description": "host=avatar \uC77C \uB54C \uD544\uC218"
16903
+ },
16904
+ "image_asset_id": {
16905
+ "anyOf": [
16906
+ {
16907
+ "minLength": 1,
16908
+ "type": "string"
16909
+ },
16910
+ {
16911
+ "type": "null"
16912
+ }
16913
+ ],
16914
+ "default": null,
16915
+ "description": "\uCEF7 \uC774\uBBF8\uC9C0\uB97C spec \uC5D0\uC11C \uC9C1\uC811 \uC9C0\uC815(\uC5D0\uC774\uC804\uD2B8 \uC6D0\uC0F7\uC6A9)",
16916
+ "title": "Image Asset Id"
16917
+ },
16918
+ "duration_s": {
16919
+ "anyOf": [
16920
+ {
16921
+ "exclusiveMinimum": 0,
16922
+ "maximum": 600,
16923
+ "type": "number"
16924
+ },
16925
+ {
16926
+ "type": "null"
16927
+ }
16928
+ ],
16929
+ "default": null,
16930
+ "title": "Duration S"
16931
+ },
16932
+ "mode": {
16933
+ "const": "youtube_clip",
16934
+ "default": "youtube_clip",
16935
+ "title": "Mode",
16936
+ "type": "string"
16937
+ },
16938
+ "source": {
16939
+ "discriminator": {
16940
+ "mapping": {
16941
+ "asset": "#/$defs/YoutubeAssetSource",
16942
+ "url": "#/$defs/YoutubeUrlSource"
16943
+ },
16944
+ "propertyName": "kind"
16945
+ },
16946
+ "oneOf": [
16947
+ {
16948
+ "$ref": "#/$defs/YoutubeUrlSource"
16949
+ },
16950
+ {
16951
+ "$ref": "#/$defs/YoutubeAssetSource"
16952
+ }
16953
+ ],
16954
+ "title": "Source"
16955
+ }
16956
+ },
16957
+ "required": [
16958
+ "source"
16959
+ ],
16960
+ "title": "YoutubeClipSpec",
16961
+ "type": "object"
16962
+ },
16963
+ "YoutubeUrlSource": {
16964
+ "additionalProperties": false,
16965
+ "properties": {
16966
+ "kind": {
16967
+ "const": "url",
16968
+ "default": "url",
16969
+ "title": "Kind",
16970
+ "type": "string"
16971
+ },
16972
+ "url": {
16973
+ "description": "https://youtube.com|youtu.be \uACF5\uAC1C \uC8FC\uC18C\uB9CC",
16974
+ "minLength": 1,
16975
+ "title": "Url",
16976
+ "type": "string"
16977
+ },
16978
+ "start_s": {
16979
+ "minimum": 0,
16980
+ "title": "Start S",
16981
+ "type": "number"
16982
+ },
16983
+ "end_s": {
16984
+ "exclusiveMinimum": 0,
16985
+ "title": "End S",
16986
+ "type": "number"
16987
+ }
16988
+ },
16989
+ "required": [
16990
+ "url",
16991
+ "start_s",
16992
+ "end_s"
16993
+ ],
16994
+ "title": "YoutubeUrlSource",
16995
+ "type": "object"
16996
+ }
16997
+ }
16998
+ },
16999
+ "annotations": {
17000
+ "readOnlyHint": false,
17001
+ "destructiveHint": false,
17002
+ "idempotentHint": false,
17003
+ "openWorldHint": false
17004
+ }
17005
+ },
17006
+ {
17007
+ "name": "democut_make_cuts",
17008
+ "description": "\uCEF7 N \uAC1C\uB97C \uB9CC\uB4E0\uB2E4(\uCCAD\uAD6C \u2014 \uC81C\uCD9C \uC2DC \uC794\uC561\uC5D0\uC11C \uCC28\uAC10, \uC2E4\uD328 \uC2DC \uD658\uBD88). \uAE30\uBCF8 \uBC29\uC2DD\uC740 ai_video. items \uB294 all-or-nothing \uC774\uB2E4. \uB3C8\uC774 \uB098\uAC00\uB294 \uB3C4\uAD6C\uB2E4: estimate_cuts(\uB610\uB294 \uC9DD\uC774 \uB418\uB294 estimate \uB3C4\uAD6C)\uB85C \uAE08\uC561\uC744 \uBCF4\uACE0 \uC0AC\uC6A9\uC790 \uB3D9\uC758\uB97C \uBC1B\uC740 \uB4A4 confirmed_*_krw \uC640 rate_version \uC744 \uADF8\uB300\uB85C \uB123\uC5B4\uB77C. \uC5B4\uAE0B\uB098\uBA74 409 QUOTE_MISMATCH \uB85C \uC0C8 \uACAC\uC801\uC744 \uC900\uB2E4(\uACFC\uAE08 \uC5C6\uC74C). \uC2E4\uD328\uD574\uB3C4 \uC7AC\uC81C\uCD9C\uD558\uC9C0 \uB9C8\uB77C \u2014 \uAC19\uC740 spec \uC774 \uD65C\uC131\uC774\uBA74 \uC11C\uBC84\uAC00 \uAE30\uC874 \uC7A1\uC744 \uB3CC\uB824\uC900\uB2E4(deduplicated=true). \uC751\uB2F5\uC740 202 \u2014 \uACB0\uACFC\uB294 democut_wait_jobs \uB85C \uBC1B\uB294\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_wait_jobs.",
17009
+ "inputSchema": {
17010
+ "type": "object",
17011
+ "properties": {
17012
+ "slug": {
17013
+ "type": "string",
17014
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
17015
+ },
17016
+ "items": {
17017
+ "items": {
17018
+ "$ref": "#/$defs/MakeItem"
17019
+ },
17020
+ "maxItems": 50,
17021
+ "minItems": 1,
17022
+ "title": "Items",
17023
+ "type": "array"
17024
+ },
17025
+ "confirmed_total_krw": {
17026
+ "description": "estimate_cuts \uC758 total_krw \uADF8\uB300\uB85C",
17027
+ "minimum": 0,
17028
+ "title": "Confirmed Total Krw",
17029
+ "type": "integer"
17030
+ },
17031
+ "rate_version": {
17032
+ "description": "estimate_cuts \uC758 rate_version \uADF8\uB300\uB85C",
17033
+ "minimum": 1,
17034
+ "title": "Rate Version",
17035
+ "type": "integer"
17036
+ }
17037
+ },
17038
+ "required": [
17039
+ "slug",
17040
+ "items",
17041
+ "confirmed_total_krw",
17042
+ "rate_version"
17043
+ ],
17044
+ "additionalProperties": false,
17045
+ "$defs": {
17046
+ "AiVideoSpec": {
17047
+ "additionalProperties": false,
17048
+ "properties": {
17049
+ "dialogue": {
17050
+ "items": {
17051
+ "$ref": "#/$defs/DialogueLine"
17052
+ },
17053
+ "title": "Dialogue",
17054
+ "type": "array"
17055
+ },
17056
+ "narration_asset_id": {
17057
+ "anyOf": [
17058
+ {
17059
+ "minLength": 1,
17060
+ "type": "string"
17061
+ },
17062
+ {
17063
+ "type": "null"
17064
+ }
17065
+ ],
17066
+ "default": null,
17067
+ "description": "BYO: \uCEF7 \uC804\uCCB4 \uB098\uB808\uC774\uC158 wav \uD55C \uAC1C(\uB300\uC0AC\uAC00 \uC788\uC5B4\uC57C \uD55C\uB2E4 \u2014 \uC790\uB9C9\xB7\uD0C0\uC774\uBC0D\uC758 \uADFC\uAC70). \uC904\uBCC4 audio_asset_id \uC640 \uB3D9\uC2DC \uC9C0\uC815 422",
17068
+ "title": "Narration Asset Id"
17069
+ },
17070
+ "subtitles": {
17071
+ "default": false,
17072
+ "title": "Subtitles",
17073
+ "type": "boolean"
17074
+ },
17075
+ "host": {
17076
+ "anyOf": [
17077
+ {
17078
+ "type": "string"
17079
+ },
17080
+ {
17081
+ "type": "null"
17082
+ }
17083
+ ],
17084
+ "default": null,
17085
+ "description": "\uC9C4\uD589 \u2014 \uD5C8\uC6A9 \uC9D1\uD569\uC740 \uCE74\uD0C8\uB85C\uADF8(\uBC29\uC2DD\uBCC4). \uBAA8\uC158\uADF8\uB798\uD53D\uC740 \uD544\uC218",
17086
+ "title": "Host"
17087
+ },
17088
+ "voice_id": {
17089
+ "anyOf": [
17090
+ {
17091
+ "minLength": 1,
17092
+ "type": "string"
17093
+ },
17094
+ {
17095
+ "type": "null"
17096
+ }
17097
+ ],
17098
+ "default": null,
17099
+ "description": "host\u2208{voice,avatar} \uC774\uACE0 BYO \uC624\uB514\uC624\uAC00 \uC5C6\uC744 \uB54C \uD544\uC218",
17100
+ "title": "Voice Id"
17101
+ },
17102
+ "pip": {
17103
+ "anyOf": [
17104
+ {
17105
+ "$ref": "#/$defs/PipSpec"
17106
+ },
17107
+ {
17108
+ "type": "null"
17109
+ }
17110
+ ],
17111
+ "default": null,
17112
+ "description": "host=avatar \uC77C \uB54C \uD544\uC218"
17113
+ },
17114
+ "image_asset_id": {
17115
+ "anyOf": [
17116
+ {
17117
+ "minLength": 1,
17118
+ "type": "string"
17119
+ },
17120
+ {
17121
+ "type": "null"
17122
+ }
17123
+ ],
17124
+ "default": null,
17125
+ "description": "\uCEF7 \uC774\uBBF8\uC9C0\uB97C spec \uC5D0\uC11C \uC9C1\uC811 \uC9C0\uC815(\uC5D0\uC774\uC804\uD2B8 \uC6D0\uC0F7\uC6A9)",
17126
+ "title": "Image Asset Id"
17127
+ },
17128
+ "duration_s": {
17129
+ "default": 5,
17130
+ "maximum": 15,
17131
+ "minimum": 4,
17132
+ "title": "Duration S",
17133
+ "type": "number"
17134
+ },
17135
+ "mode": {
17136
+ "const": "ai_video",
17137
+ "default": "ai_video",
17138
+ "title": "Mode",
17139
+ "type": "string"
17140
+ },
17141
+ "image_prompt": {
17142
+ "maxLength": 4e3,
17143
+ "minLength": 1,
17144
+ "title": "Image Prompt",
17145
+ "type": "string"
17146
+ },
17147
+ "provider": {
17148
+ "anyOf": [
17149
+ {
17150
+ "maxLength": 32,
17151
+ "minLength": 1,
17152
+ "type": "string"
17153
+ },
17154
+ {
17155
+ "type": "null"
17156
+ }
17157
+ ],
17158
+ "default": null,
17159
+ "description": "\uC601\uC0C1 \uC0DD\uC131 \uACF5\uAE09\uC790(\uC608: minimax). \uBE44\uC6B0\uBA74 \uC11C\uBC84 \uAE30\uBCF8\uAC12 \u2014 \uC4F8 \uC218 \uC788\uB294 \uBAA9\uB85D\uC740 GET \u2026/options \uC758 videogen_providers",
17160
+ "title": "Provider"
17161
+ },
17162
+ "seed": {
17163
+ "anyOf": [
17164
+ {
17165
+ "minimum": 0,
17166
+ "type": "integer"
17167
+ },
17168
+ {
17169
+ "type": "null"
17170
+ }
17171
+ ],
17172
+ "default": null,
17173
+ "title": "Seed"
17174
+ },
17175
+ "image": {
17176
+ "anyOf": [
17177
+ {
17178
+ "discriminator": {
17179
+ "mapping": {
17180
+ "asset": "#/$defs/AssetImageRef",
17181
+ "from_cut": "#/$defs/FromCutImageRef",
17182
+ "from_version": "#/$defs/FromVersionImageRef"
17183
+ },
17184
+ "propertyName": "kind"
17185
+ },
17186
+ "oneOf": [
17187
+ {
17188
+ "$ref": "#/$defs/AssetImageRef"
17189
+ },
17190
+ {
17191
+ "$ref": "#/$defs/FromCutImageRef"
17192
+ },
17193
+ {
17194
+ "$ref": "#/$defs/FromVersionImageRef"
17195
+ }
17196
+ ]
17197
+ },
17198
+ {
17199
+ "type": "null"
17200
+ }
17201
+ ],
17202
+ "default": null,
17203
+ "description": "\uCCAB \uD504\uB808\uC784. \uC5C6\uC73C\uBA74 image_asset_id \u2192 \uCEF7 \uC774\uBBF8\uC9C0 \u2192 t2v \uC21C",
17204
+ "title": "Image"
17205
+ },
17206
+ "end_image": {
17207
+ "anyOf": [
17208
+ {
17209
+ "discriminator": {
17210
+ "mapping": {
17211
+ "asset": "#/$defs/AssetImageRef",
17212
+ "from_cut": "#/$defs/FromCutImageRef",
17213
+ "from_version": "#/$defs/FromVersionImageRef"
17214
+ },
17215
+ "propertyName": "kind"
17216
+ },
17217
+ "oneOf": [
17218
+ {
17219
+ "$ref": "#/$defs/AssetImageRef"
17220
+ },
17221
+ {
17222
+ "$ref": "#/$defs/FromCutImageRef"
17223
+ },
17224
+ {
17225
+ "$ref": "#/$defs/FromVersionImageRef"
17226
+ }
17227
+ ]
17228
+ },
17229
+ {
17230
+ "type": "null"
17231
+ }
17232
+ ],
17233
+ "default": null,
17234
+ "title": "End Image"
17235
+ }
17236
+ },
17237
+ "required": [
17238
+ "image_prompt"
17239
+ ],
17240
+ "title": "AiVideoSpec",
17241
+ "type": "object"
17242
+ },
17243
+ "AssetImageRef": {
17244
+ "additionalProperties": false,
17245
+ "properties": {
17246
+ "kind": {
17247
+ "const": "asset",
17248
+ "default": "asset",
17249
+ "title": "Kind",
17250
+ "type": "string"
17251
+ },
17252
+ "asset_id": {
17253
+ "minLength": 1,
17254
+ "title": "Asset Id",
17255
+ "type": "string"
17256
+ }
17257
+ },
17258
+ "required": [
17259
+ "asset_id"
17260
+ ],
17261
+ "title": "AssetImageRef",
17262
+ "type": "object"
17263
+ },
17264
+ "DialogueLine": {
17265
+ "additionalProperties": false,
17266
+ "properties": {
17267
+ "id": {
17268
+ "description": "\uC904 id ln_<6> \u2014 \uC81C\uC548 diff \uC758 \uB300\uC870 \uD0A4",
17269
+ "pattern": "^ln_[a-z0-9]{6}$",
17270
+ "title": "Id",
17271
+ "type": "string",
17272
+ "x-diff": "ignore"
17273
+ },
17274
+ "text": {
17275
+ "description": "\uBC1C\uD654 \uD14D\uC2A4\uD2B8(\uC22B\uC790\uB294 \uC11C\uBC84\uAC00 \uC77D\uB294 \uBC95\uC744 \uC815\uD55C\uB2E4 \u2014 \uD480\uC5B4\uC4F0\uC9C0 \uC54A\uB294\uB2E4)",
17276
+ "maxLength": 2e3,
17277
+ "minLength": 1,
17278
+ "title": "Text",
17279
+ "type": "string"
17280
+ },
17281
+ "subtitle_text": {
17282
+ "anyOf": [
17283
+ {
17284
+ "maxLength": 2e3,
17285
+ "type": "string"
17286
+ },
17287
+ {
17288
+ "type": "null"
17289
+ }
17290
+ ],
17291
+ "default": null,
17292
+ "description": "\uC790\uB9C9 \uD45C\uAE30(\uC6D0\uBB38 \uD45C\uAE30). \uC5C6\uC73C\uBA74 text",
17293
+ "title": "Subtitle Text"
17294
+ },
17295
+ "audio_asset_id": {
17296
+ "anyOf": [
17297
+ {
17298
+ "minLength": 1,
17299
+ "type": "string"
17300
+ },
17301
+ {
17302
+ "type": "null"
17303
+ }
17304
+ ],
17305
+ "default": null,
17306
+ "description": "BYO: \uC774 \uC904\uC758 \uB098\uB808\uC774\uC158 \uC624\uB514\uC624 \uC790\uC0B0 \u2014 TTS \uD589 0\uC6D0, \uC815\uB82C \uD589\uB9CC",
17307
+ "title": "Audio Asset Id"
17308
+ }
17309
+ },
17310
+ "required": [
17311
+ "id",
17312
+ "text"
17313
+ ],
17314
+ "title": "DialogueLine",
17315
+ "type": "object"
17316
+ },
17317
+ "FromCutImageRef": {
17318
+ "additionalProperties": false,
17319
+ "properties": {
17320
+ "kind": {
17321
+ "const": "from_cut",
17322
+ "default": "from_cut",
17323
+ "title": "Kind",
17324
+ "type": "string"
17325
+ },
17326
+ "from_cut": {
17327
+ "description": "\uB2E4\uB978 \uCEF7\uC758 \uB300\uD45C \uBC84\uC804 \uD504\uB808\uC784(\uC5F0\uC18D\uC131 \uB3C4\uC6B0\uBBF8)",
17328
+ "minLength": 1,
17329
+ "title": "From Cut",
17330
+ "type": "string"
17331
+ },
17332
+ "frame": {
17333
+ "default": "last",
17334
+ "enum": [
17335
+ "first",
17336
+ "last"
17337
+ ],
17338
+ "title": "Frame",
17339
+ "type": "string"
17340
+ }
17341
+ },
17342
+ "required": [
17343
+ "from_cut"
17344
+ ],
17345
+ "title": "FromCutImageRef",
17346
+ "type": "object"
17347
+ },
17348
+ "FromVersionImageRef": {
17349
+ "additionalProperties": false,
17350
+ "properties": {
17351
+ "kind": {
17352
+ "const": "from_version",
17353
+ "default": "from_version",
17354
+ "title": "Kind",
17355
+ "type": "string"
17356
+ },
17357
+ "from_version": {
17358
+ "description": "\uC774 \uCEF7\uC758 \uD2B9\uC815 \uBC84\uC804 \uD504\uB808\uC784",
17359
+ "minimum": 1,
17360
+ "title": "From Version",
17361
+ "type": "integer"
17362
+ },
17363
+ "frame": {
17364
+ "default": "last",
17365
+ "enum": [
17366
+ "first",
17367
+ "last"
17368
+ ],
17369
+ "title": "Frame",
17370
+ "type": "string"
17371
+ }
17372
+ },
17373
+ "required": [
17374
+ "from_version"
17375
+ ],
17376
+ "title": "FromVersionImageRef",
17377
+ "type": "object"
17378
+ },
17379
+ "MakeItem": {
17380
+ "additionalProperties": false,
17381
+ "properties": {
17382
+ "cut_id": {
17383
+ "anyOf": [
17384
+ {
17385
+ "type": "string"
17386
+ },
17387
+ {
17388
+ "type": "null"
17389
+ }
17390
+ ],
17391
+ "default": null,
17392
+ "title": "Cut Id"
17393
+ },
17394
+ "spec": {
17395
+ "discriminator": {
17396
+ "mapping": {
17397
+ "ai_video": "#/$defs/AiVideoSpec",
17398
+ "motion_graphic": "#/$defs/MotionGraphicSpec",
17399
+ "youtube_clip": "#/$defs/YoutubeClipSpec"
17400
+ },
17401
+ "propertyName": "mode"
17402
+ },
17403
+ "oneOf": [
17404
+ {
17405
+ "$ref": "#/$defs/MotionGraphicSpec"
17406
+ },
17407
+ {
17408
+ "$ref": "#/$defs/AiVideoSpec"
17409
+ },
17410
+ {
17411
+ "$ref": "#/$defs/YoutubeClipSpec"
17412
+ }
17413
+ ],
17414
+ "title": "Spec"
17415
+ },
17416
+ "note": {
17417
+ "anyOf": [
17418
+ {
17419
+ "maxLength": 500,
17420
+ "type": "string"
17421
+ },
17422
+ {
17423
+ "type": "null"
17424
+ }
17425
+ ],
17426
+ "default": null,
17427
+ "title": "Note"
17428
+ }
17429
+ },
17430
+ "required": [
17431
+ "spec"
17432
+ ],
17433
+ "title": "MakeItem",
17434
+ "type": "object"
17435
+ },
17436
+ "MotionGraphicSpec": {
17437
+ "additionalProperties": false,
17438
+ "properties": {
17439
+ "dialogue": {
17440
+ "items": {
17441
+ "$ref": "#/$defs/DialogueLine"
17442
+ },
17443
+ "title": "Dialogue",
17444
+ "type": "array"
17445
+ },
17446
+ "narration_asset_id": {
17447
+ "anyOf": [
17448
+ {
17449
+ "minLength": 1,
17450
+ "type": "string"
17451
+ },
17452
+ {
17453
+ "type": "null"
17454
+ }
17455
+ ],
17456
+ "default": null,
17457
+ "description": "BYO: \uCEF7 \uC804\uCCB4 \uB098\uB808\uC774\uC158 wav \uD55C \uAC1C(\uB300\uC0AC\uAC00 \uC788\uC5B4\uC57C \uD55C\uB2E4 \u2014 \uC790\uB9C9\xB7\uD0C0\uC774\uBC0D\uC758 \uADFC\uAC70). \uC904\uBCC4 audio_asset_id \uC640 \uB3D9\uC2DC \uC9C0\uC815 422",
17458
+ "title": "Narration Asset Id"
17459
+ },
17460
+ "subtitles": {
17461
+ "default": false,
17462
+ "title": "Subtitles",
17463
+ "type": "boolean"
17464
+ },
17465
+ "host": {
17466
+ "anyOf": [
17467
+ {
17468
+ "type": "string"
17469
+ },
17470
+ {
17471
+ "type": "null"
17472
+ }
17473
+ ],
17474
+ "default": null,
17475
+ "description": "\uC9C4\uD589 \u2014 \uD5C8\uC6A9 \uC9D1\uD569\uC740 \uCE74\uD0C8\uB85C\uADF8(\uBC29\uC2DD\uBCC4). \uBAA8\uC158\uADF8\uB798\uD53D\uC740 \uD544\uC218",
17476
+ "title": "Host"
17477
+ },
17478
+ "voice_id": {
17479
+ "anyOf": [
17480
+ {
17481
+ "minLength": 1,
17482
+ "type": "string"
17483
+ },
17484
+ {
17485
+ "type": "null"
17486
+ }
17487
+ ],
17488
+ "default": null,
17489
+ "description": "host\u2208{voice,avatar} \uC774\uACE0 BYO \uC624\uB514\uC624\uAC00 \uC5C6\uC744 \uB54C \uD544\uC218",
17490
+ "title": "Voice Id"
17491
+ },
17492
+ "pip": {
17493
+ "anyOf": [
17494
+ {
17495
+ "$ref": "#/$defs/PipSpec"
17496
+ },
17497
+ {
17498
+ "type": "null"
17499
+ }
17500
+ ],
17501
+ "default": null,
17502
+ "description": "host=avatar \uC77C \uB54C \uD544\uC218"
17503
+ },
17504
+ "image_asset_id": {
17505
+ "anyOf": [
17506
+ {
17507
+ "minLength": 1,
17508
+ "type": "string"
17509
+ },
17510
+ {
17511
+ "type": "null"
17512
+ }
17513
+ ],
17514
+ "default": null,
17515
+ "description": "\uCEF7 \uC774\uBBF8\uC9C0\uB97C spec \uC5D0\uC11C \uC9C1\uC811 \uC9C0\uC815(\uC5D0\uC774\uC804\uD2B8 \uC6D0\uC0F7\uC6A9)",
17516
+ "title": "Image Asset Id"
17517
+ },
17518
+ "duration_s": {
17519
+ "anyOf": [
17520
+ {
17521
+ "exclusiveMinimum": 0,
17522
+ "maximum": 600,
17523
+ "type": "number"
17524
+ },
17525
+ {
17526
+ "type": "null"
17527
+ }
17528
+ ],
17529
+ "default": null,
17530
+ "title": "Duration S"
17531
+ },
17532
+ "mode": {
17533
+ "const": "motion_graphic",
17534
+ "default": "motion_graphic",
17535
+ "title": "Mode",
17536
+ "type": "string"
17537
+ },
17538
+ "motion_prompt": {
17539
+ "anyOf": [
17540
+ {
17541
+ "maxLength": 4e3,
17542
+ "type": "string"
17543
+ },
17544
+ {
17545
+ "type": "null"
17546
+ }
17547
+ ],
17548
+ "default": null,
17549
+ "title": "Motion Prompt"
17550
+ },
17551
+ "tsx": {
17552
+ "anyOf": [
17553
+ {
17554
+ "maxLength": 2e5,
17555
+ "type": "string"
17556
+ },
17557
+ {
17558
+ "type": "null"
17559
+ }
17560
+ ],
17561
+ "default": null,
17562
+ "description": "BYO Remotion \uCF54\uB4DC(UTF-8 \u2264 200KB) \u2014 codegen \uD589 0\uC6D0, \uAC8C\uC774\uD2B8\uB294 codegen \uACFC \uB3D9\uAE09",
17563
+ "title": "Tsx"
17564
+ },
17565
+ "brand_override": {
17566
+ "anyOf": [
17567
+ {
17568
+ "additionalProperties": true,
17569
+ "type": "object"
17570
+ },
17571
+ {
17572
+ "type": "null"
17573
+ }
17574
+ ],
17575
+ "default": null,
17576
+ "title": "Brand Override"
17577
+ }
17578
+ },
17579
+ "title": "MotionGraphicSpec",
17580
+ "type": "object"
17581
+ },
17582
+ "PipSpec": {
17583
+ "additionalProperties": false,
17584
+ "properties": {
17585
+ "avatar_id": {
17586
+ "minLength": 1,
17587
+ "title": "Avatar Id",
17588
+ "type": "string"
17589
+ },
17590
+ "background_asset_id": {
17591
+ "description": "\uBC30\uACBD\uC740 \uC5B8\uC81C\uB098 \uC790\uC0B0(origin=background \uCE74\uD0C8\uB85C\uADF8 \uB610\uB294 \uC62C\uB9B0 \uC774\uBBF8\uC9C0)",
17592
+ "minLength": 1,
17593
+ "title": "Background Asset Id",
17594
+ "type": "string"
17595
+ },
17596
+ "position": {
17597
+ "default": "br",
17598
+ "enum": [
17599
+ "tl",
17600
+ "tr",
17601
+ "bl",
17602
+ "br"
17603
+ ],
17604
+ "title": "Position",
17605
+ "type": "string"
17606
+ },
17607
+ "size": {
17608
+ "default": "m",
17609
+ "enum": [
17610
+ "s",
17611
+ "m",
17612
+ "l"
17613
+ ],
17614
+ "title": "Size",
17615
+ "type": "string"
17616
+ }
17617
+ },
17618
+ "required": [
17619
+ "avatar_id",
17620
+ "background_asset_id"
17621
+ ],
17622
+ "title": "PipSpec",
17623
+ "type": "object"
17624
+ },
17625
+ "YoutubeAssetSource": {
17626
+ "additionalProperties": false,
17627
+ "properties": {
17628
+ "kind": {
17629
+ "const": "asset",
17630
+ "default": "asset",
17631
+ "title": "Kind",
17632
+ "type": "string"
17633
+ },
17634
+ "asset_id": {
17635
+ "description": "BYO: \uC62C\uB9B0 \uC6D0\uBCF8 \uC601\uC0C1 \u2014 \uB0B4\uB824\uBC1B\uAE30 \uD589 0\uC6D0",
17636
+ "minLength": 1,
17637
+ "title": "Asset Id",
17638
+ "type": "string"
17639
+ },
17640
+ "start_s": {
17641
+ "anyOf": [
17642
+ {
17643
+ "minimum": 0,
17644
+ "type": "number"
17645
+ },
17646
+ {
17647
+ "type": "null"
17648
+ }
17649
+ ],
17650
+ "default": null,
17651
+ "title": "Start S"
17652
+ },
17653
+ "end_s": {
17654
+ "anyOf": [
17655
+ {
17656
+ "exclusiveMinimum": 0,
17657
+ "type": "number"
17658
+ },
17659
+ {
17660
+ "type": "null"
17661
+ }
17662
+ ],
17663
+ "default": null,
17664
+ "title": "End S"
17665
+ }
17666
+ },
17667
+ "required": [
17668
+ "asset_id"
17669
+ ],
17670
+ "title": "YoutubeAssetSource",
17671
+ "type": "object"
17672
+ },
17673
+ "YoutubeClipSpec": {
17674
+ "additionalProperties": false,
17675
+ "properties": {
17676
+ "dialogue": {
17677
+ "items": {
17678
+ "$ref": "#/$defs/DialogueLine"
17679
+ },
17680
+ "title": "Dialogue",
17681
+ "type": "array"
17682
+ },
17683
+ "narration_asset_id": {
17684
+ "anyOf": [
17685
+ {
17686
+ "minLength": 1,
17687
+ "type": "string"
17688
+ },
17689
+ {
17690
+ "type": "null"
17691
+ }
17692
+ ],
17693
+ "default": null,
17694
+ "description": "BYO: \uCEF7 \uC804\uCCB4 \uB098\uB808\uC774\uC158 wav \uD55C \uAC1C(\uB300\uC0AC\uAC00 \uC788\uC5B4\uC57C \uD55C\uB2E4 \u2014 \uC790\uB9C9\xB7\uD0C0\uC774\uBC0D\uC758 \uADFC\uAC70). \uC904\uBCC4 audio_asset_id \uC640 \uB3D9\uC2DC \uC9C0\uC815 422",
17695
+ "title": "Narration Asset Id"
17696
+ },
17697
+ "subtitles": {
17698
+ "default": false,
17699
+ "title": "Subtitles",
17700
+ "type": "boolean"
17701
+ },
17702
+ "host": {
17703
+ "anyOf": [
17704
+ {
17705
+ "type": "string"
17706
+ },
17707
+ {
17708
+ "type": "null"
17709
+ }
17710
+ ],
17711
+ "default": null,
17712
+ "description": "\uC9C4\uD589 \u2014 \uD5C8\uC6A9 \uC9D1\uD569\uC740 \uCE74\uD0C8\uB85C\uADF8(\uBC29\uC2DD\uBCC4). \uBAA8\uC158\uADF8\uB798\uD53D\uC740 \uD544\uC218",
17713
+ "title": "Host"
17714
+ },
17715
+ "voice_id": {
17716
+ "anyOf": [
17717
+ {
17718
+ "minLength": 1,
17719
+ "type": "string"
17720
+ },
17721
+ {
17722
+ "type": "null"
17723
+ }
17724
+ ],
17725
+ "default": null,
17726
+ "description": "host\u2208{voice,avatar} \uC774\uACE0 BYO \uC624\uB514\uC624\uAC00 \uC5C6\uC744 \uB54C \uD544\uC218",
17727
+ "title": "Voice Id"
17728
+ },
17729
+ "pip": {
17730
+ "anyOf": [
17731
+ {
17732
+ "$ref": "#/$defs/PipSpec"
17733
+ },
17734
+ {
17735
+ "type": "null"
17736
+ }
17737
+ ],
17738
+ "default": null,
17739
+ "description": "host=avatar \uC77C \uB54C \uD544\uC218"
17740
+ },
17741
+ "image_asset_id": {
17742
+ "anyOf": [
17743
+ {
17744
+ "minLength": 1,
17745
+ "type": "string"
17746
+ },
17747
+ {
17748
+ "type": "null"
17749
+ }
17750
+ ],
17751
+ "default": null,
17752
+ "description": "\uCEF7 \uC774\uBBF8\uC9C0\uB97C spec \uC5D0\uC11C \uC9C1\uC811 \uC9C0\uC815(\uC5D0\uC774\uC804\uD2B8 \uC6D0\uC0F7\uC6A9)",
17753
+ "title": "Image Asset Id"
17754
+ },
17755
+ "duration_s": {
17756
+ "anyOf": [
17757
+ {
17758
+ "exclusiveMinimum": 0,
17759
+ "maximum": 600,
17760
+ "type": "number"
17761
+ },
17762
+ {
17763
+ "type": "null"
17764
+ }
17765
+ ],
17766
+ "default": null,
17767
+ "title": "Duration S"
17768
+ },
17769
+ "mode": {
17770
+ "const": "youtube_clip",
17771
+ "default": "youtube_clip",
17772
+ "title": "Mode",
17773
+ "type": "string"
17774
+ },
17775
+ "source": {
17776
+ "discriminator": {
17777
+ "mapping": {
17778
+ "asset": "#/$defs/YoutubeAssetSource",
17779
+ "url": "#/$defs/YoutubeUrlSource"
17780
+ },
17781
+ "propertyName": "kind"
17782
+ },
17783
+ "oneOf": [
17784
+ {
17785
+ "$ref": "#/$defs/YoutubeUrlSource"
17786
+ },
17787
+ {
17788
+ "$ref": "#/$defs/YoutubeAssetSource"
17789
+ }
17790
+ ],
17791
+ "title": "Source"
17792
+ }
17793
+ },
17794
+ "required": [
17795
+ "source"
17796
+ ],
17797
+ "title": "YoutubeClipSpec",
17798
+ "type": "object"
17799
+ },
17800
+ "YoutubeUrlSource": {
17801
+ "additionalProperties": false,
17802
+ "properties": {
17803
+ "kind": {
17804
+ "const": "url",
17805
+ "default": "url",
17806
+ "title": "Kind",
17807
+ "type": "string"
17808
+ },
17809
+ "url": {
17810
+ "description": "https://youtube.com|youtu.be \uACF5\uAC1C \uC8FC\uC18C\uB9CC",
17811
+ "minLength": 1,
17812
+ "title": "Url",
17813
+ "type": "string"
17814
+ },
17815
+ "start_s": {
17816
+ "minimum": 0,
17817
+ "title": "Start S",
17818
+ "type": "number"
17819
+ },
17820
+ "end_s": {
17821
+ "exclusiveMinimum": 0,
17822
+ "title": "End S",
17823
+ "type": "number"
17824
+ }
17825
+ },
17826
+ "required": [
17827
+ "url",
17828
+ "start_s",
17829
+ "end_s"
17830
+ ],
17831
+ "title": "YoutubeUrlSource",
17832
+ "type": "object"
17833
+ }
17834
+ }
17835
+ },
17836
+ "annotations": {
17837
+ "readOnlyHint": false,
17838
+ "destructiveHint": false,
17839
+ "idempotentHint": false,
17840
+ "openWorldHint": false
17841
+ }
17842
+ },
17843
+ {
17844
+ "name": "democut_wait_jobs",
17845
+ "description": "\uC7A1\uC774 \uB05D\uB0A0 \uB54C\uAE4C\uC9C0 \uAE30\uB2E4\uB9B0\uB2E4(\uC694\uCCAD\uD55C \uBAA8\uB4E0 id \uC758 \uC2A4\uB0C5\uC0F7 + all_done). all_done=false \uBA74 \uC544\uC9C1 \uC548 \uB05D\uB09C id \uB9CC \uAC19\uC740 \uB3C4\uAD6C\uB85C \uB2E4\uC2DC \uBD80\uB978\uB2E4. \uB05D\uB09C \uC7A1\uC758 result.download \uB85C \uBC14\uB85C \uB0B4\uB824\uBC1B\uB294\uB2E4. job_ids\xB7batch_id\xB7project \uC911 \uD558\uB098\uB294 \uC788\uC5B4\uC57C \uD55C\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_download, democut_get_cut.",
17846
+ "inputSchema": {
17847
+ "type": "object",
17848
+ "properties": {
17849
+ "job_ids": {
17850
+ "anyOf": [
17851
+ {
17852
+ "items": {
17853
+ "type": "string"
17854
+ },
17855
+ "maxItems": 100,
17856
+ "minItems": 1,
17857
+ "type": "array"
17858
+ },
17859
+ {
17860
+ "type": "null"
17861
+ }
17862
+ ],
17863
+ "default": null,
17864
+ "title": "Job Ids"
17865
+ },
17866
+ "batch_id": {
17867
+ "anyOf": [
17868
+ {
17869
+ "type": "string"
17870
+ },
17871
+ {
17872
+ "type": "null"
17873
+ }
17874
+ ],
17875
+ "default": null,
17876
+ "title": "Batch Id"
17877
+ },
17878
+ "project": {
17879
+ "anyOf": [
17880
+ {
17881
+ "type": "string"
17882
+ },
17883
+ {
17884
+ "type": "null"
17885
+ }
17886
+ ],
17887
+ "default": null,
17888
+ "title": "Project"
17889
+ },
17890
+ "state": {
17891
+ "anyOf": [
17892
+ {
17893
+ "enum": [
17894
+ "queued",
17895
+ "running",
17896
+ "done",
17897
+ "error",
17898
+ "cancelled"
17899
+ ],
17900
+ "type": "string"
17901
+ },
17902
+ {
17903
+ "type": "null"
17904
+ }
17905
+ ],
17906
+ "default": null,
17907
+ "title": "State"
17908
+ },
17909
+ "timeout_s": {
17910
+ "default": 600,
17911
+ "description": "0 = \uAE30\uB2E4\uB9AC\uC9C0 \uC54A\uACE0 \uC9C0\uAE08 \uC0C1\uD0DC\uB9CC. all_done=false \uBA74 \uB0A8\uC740 id \uB9CC \uB2E4\uC2DC \uBD80\uB978\uB2E4",
17912
+ "maximum": 600,
17913
+ "minimum": 0,
17914
+ "title": "Timeout S",
17915
+ "type": "integer"
17916
+ }
17917
+ },
17918
+ "required": [],
17919
+ "additionalProperties": false,
17920
+ "anyOf": [
17921
+ {
17922
+ "required": [
17923
+ "job_ids"
17924
+ ]
17925
+ },
17926
+ {
17927
+ "required": [
17928
+ "batch_id"
17929
+ ]
17930
+ },
17931
+ {
17932
+ "required": [
17933
+ "project"
17934
+ ]
17935
+ }
17936
+ ]
17937
+ },
17938
+ "annotations": {
17939
+ "readOnlyHint": true,
17940
+ "destructiveHint": false,
17941
+ "idempotentHint": true,
17942
+ "openWorldHint": false
17943
+ }
17944
+ },
17945
+ {
17946
+ "name": "democut_get_cut",
17947
+ "description": "\uCEF7 \uD558\uB098 \u2014 \uBC84\uC804 \uBAA9\uB85D\uACFC \uBC84\uC804\uB9C8\uB2E4 download{video,audio,subtitle,still} \uC11C\uBA85 URL. \uD0C0\uC774\uBC0D\uC740 versions[].timing \uC5D0 \uC778\uB77C\uC778. current_version \uC774 \uC5C6\uC73C\uBA74 \uACC4\uD68D \uCEF7\uC774\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_download, democut_make_cuts.",
17948
+ "inputSchema": {
17949
+ "type": "object",
17950
+ "properties": {
17951
+ "slug": {
17952
+ "type": "string",
17953
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
17954
+ },
17955
+ "cut_id": {
17956
+ "type": "string",
17957
+ "description": "\uCEF7 id(cut_\u2026)"
17958
+ }
17959
+ },
17960
+ "required": [
17961
+ "slug",
17962
+ "cut_id"
17963
+ ],
17964
+ "additionalProperties": false
17965
+ },
17966
+ "annotations": {
17967
+ "readOnlyHint": true,
17968
+ "destructiveHint": false,
17969
+ "idempotentHint": true,
17970
+ "openWorldHint": false
17971
+ }
17972
+ },
17973
+ {
17974
+ "name": "democut_download",
17975
+ "description": "\uBC84\uC804 \uC0B0\uCD9C\uBB3C \uD558\uB098\uB97C \uB0B4\uB824\uBC1B\uB294\uB2E4(kind: video|audio|subtitle|still). stdio \uB294 output_path \uC5D0 \uC800\uC7A5, \uC6D0\uACA9\uC740 \uC11C\uBA85 URL(1\uC2DC\uAC04).",
17976
+ "inputSchema": {
17977
+ "type": "object",
17978
+ "properties": {
17979
+ "slug": {
17980
+ "type": "string",
17981
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
17982
+ },
17983
+ "cut_id": {
17984
+ "type": "string",
17985
+ "description": "\uCEF7 id(cut_\u2026)"
17986
+ },
17987
+ "version": {
17988
+ "type": "string",
17989
+ "description": "\uBC84\uC804 \uBC88\uD638(1\uBD80\uD130)"
17990
+ },
17991
+ "kind": {
17992
+ "default": "video",
17993
+ "enum": [
17994
+ "video",
17995
+ "audio",
17996
+ "subtitle",
17997
+ "still"
17998
+ ],
17999
+ "title": "Kind",
18000
+ "type": "string"
18001
+ },
18002
+ "output_path": {
18003
+ "type": "string",
18004
+ "description": "\uC800\uC7A5\uD560 \uB85C\uCEEC \uACBD\uB85C(stdio \uC804\uC6A9). \uC5C6\uC73C\uBA74 URL \uB9CC \uB3CC\uB824\uC900\uB2E4"
18005
+ }
18006
+ },
18007
+ "required": [
18008
+ "slug",
18009
+ "cut_id",
18010
+ "version"
18011
+ ],
18012
+ "additionalProperties": false
18013
+ },
18014
+ "annotations": {
18015
+ "readOnlyHint": true,
18016
+ "destructiveHint": false,
18017
+ "idempotentHint": true,
18018
+ "openWorldHint": false
18019
+ }
18020
+ },
18021
+ {
18022
+ "name": "democut_import_cut",
18023
+ "description": "\uC0AC\uC6A9\uC790\uAC00 \uB9CC\uB4E0 \uC644\uC131 \uCEF7 \uC601\uC0C1\uC744 0\uC6D0 \uBC84\uC804\uC73C\uB85C \uB4F1\uB85D\uD55C\uB2E4(S3: \uC7AC\uB8CC\uB294 \uB0B4\uAC00, \uC870\uB9BD\uC740 DemoCut). transcribe=true \uBA74 \uC790\uB9C9 \uC804\uC0AC \uD589\uB9CC \uCCAD\uAD6C(democut_estimate_cuts \uC758 imports \uB85C \uBA3C\uC800 \uBCF8\uB2E4). \uC751\uB2F5\uC740 202 \u2014 \uACB0\uACFC\uB294 democut_wait_jobs \uB85C \uBC1B\uB294\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_wait_jobs, democut_get_cut.",
18024
+ "inputSchema": {
18025
+ "type": "object",
18026
+ "properties": {
18027
+ "slug": {
18028
+ "type": "string",
18029
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
18030
+ },
18031
+ "cut_id": {
18032
+ "type": "string",
18033
+ "description": "\uCEF7 id(cut_\u2026)"
18034
+ },
18035
+ "video_asset_id": {
18036
+ "title": "Video Asset Id",
18037
+ "type": "string"
18038
+ },
18039
+ "dialogue": {
18040
+ "anyOf": [
18041
+ {
18042
+ "items": {
18043
+ "additionalProperties": true,
18044
+ "type": "object"
18045
+ },
18046
+ "type": "array"
18047
+ },
18048
+ {
18049
+ "type": "null"
18050
+ }
18051
+ ],
18052
+ "default": null,
18053
+ "description": "[{id?, text}] \u2014 \uC790\uB9C9\xB7\uD0C0\uC774\uBC0D \uADFC\uAC70",
18054
+ "title": "Dialogue"
18055
+ },
18056
+ "transcribe": {
18057
+ "default": false,
18058
+ "description": "True \uBA74 asr:transcribe \uD589 \uCCAD\uAD6C",
18059
+ "title": "Transcribe",
18060
+ "type": "boolean"
18061
+ },
18062
+ "confirmed_total_krw": {
18063
+ "default": 0,
18064
+ "minimum": 0,
18065
+ "title": "Confirmed Total Krw",
18066
+ "type": "integer"
18067
+ },
18068
+ "rate_version": {
18069
+ "anyOf": [
18070
+ {
18071
+ "type": "integer"
18072
+ },
18073
+ {
18074
+ "type": "null"
18075
+ }
18076
+ ],
18077
+ "default": null,
18078
+ "title": "Rate Version"
18079
+ }
18080
+ },
18081
+ "required": [
18082
+ "slug",
18083
+ "cut_id",
18084
+ "video_asset_id"
18085
+ ],
18086
+ "additionalProperties": false
18087
+ },
18088
+ "annotations": {
18089
+ "readOnlyHint": false,
18090
+ "destructiveHint": false,
18091
+ "idempotentHint": false,
18092
+ "openWorldHint": false
18093
+ }
18094
+ },
18095
+ {
18096
+ "name": "democut_cancel_job",
18097
+ "description": "\uC7A1\uC744 \uCDE8\uC18C\uD55C\uB2E4. queued \uB294 \uC989\uC2DC \uD658\uBD88, running \uC740 \uC2E4\uD589\uAE30\uAC00 1\uCD08 \uC548\uC5D0 \uBA48\uCD94\uACE0 \uC815\uC0B0(\uACF5\uAE09\uC790\uAC00 \uACFC\uAE08\uD55C \uD589\uC740 \uBE44\uD658\uBD88). AI \uC601\uC0C1\uC740 \uACF5\uAE09\uC790 \uC81C\uCD9C \uB4A4 \uCDE8\uC18C \uBD88\uAC00(409 NOT_CANCELLABLE).",
18098
+ "inputSchema": {
18099
+ "type": "object",
18100
+ "properties": {
18101
+ "job_id": {
18102
+ "type": "string",
18103
+ "description": "\uC7A1 id(job_\u2026)"
18104
+ }
18105
+ },
18106
+ "required": [
18107
+ "job_id"
18108
+ ],
18109
+ "additionalProperties": false
18110
+ },
18111
+ "annotations": {
18112
+ "readOnlyHint": false,
18113
+ "destructiveHint": true,
18114
+ "idempotentHint": true,
18115
+ "openWorldHint": false
18116
+ }
18117
+ },
18118
+ {
18119
+ "name": "democut_credit_balance",
18120
+ "description": "\uB0B4 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC758 \uD06C\uB808\uB527 \uC794\uC561. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. \uB3C8\uC774 \uB098\uAC00\uB294 \uC791\uC5C5(democut_make_cuts \uB4F1)\uC744 \uC81C\uCD9C\uD558\uAE30 **\uC804\uC5D0** \uD655\uC778\uD558\uB77C \u2014 \uBD80\uC871\uD558\uBA74 \uC81C\uCD9C\uC774 402 \uB85C \uAC70\uBD80\uB418\uACE0, \uADF8\uAC83\uC744 \uBBF8\uB9AC \uC544\uB294 \uD3B8\uC774 \uB0AB\uB2E4(democut_estimate_cuts \uC758 can_afford \uAC00 \uC788\uC73C\uBA74 \uB9E4\uBC88 \uBD80\uB97C \uD544\uC694\uB294 \uC5C6\uB2E4). \uBAA8\uC790\uB77C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC54C\uB9AC\uACE0 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uAD00\uB9AC\uC790\uC5D0\uAC8C \uCDA9\uC804\uC744 \uC694\uCCAD\uD558\uB3C4\uB85D \uC548\uB0B4\uD558\uB77C \u2014 \uB124\uAC00 \uC9C1\uC811 \uCDA9\uC804\uD560 \uC218\uB294 \uC5C6\uB2E4.",
18121
+ "inputSchema": {
18122
+ "type": "object",
18123
+ "properties": {},
18124
+ "required": [],
18125
+ "additionalProperties": false
18126
+ },
18127
+ "annotations": {
18128
+ "readOnlyHint": true,
18129
+ "destructiveHint": false,
18130
+ "idempotentHint": true,
18131
+ "openWorldHint": false
18132
+ }
18133
+ },
18134
+ {
18135
+ "name": "democut_credit_ledger",
18136
+ "description": "\uD06C\uB808\uB527 \uC0AC\uC6A9 \uB0B4\uC5ED(\uCD5C\uC2E0\uC21C, keyset). \u300C\uC65C \uC794\uC561\uC774 \uC774\uB9CC\uD07C \uC904\uC5C8\uB098\u300D \uB97C \uB2F5\uD560 \uB54C \uC4F4\uB2E4 \u2014 \uD589\uB9C8\uB2E4 \uBB34\uC5C7\uC5D0\xB7\uC5B8\uC81C\xB7\uC5BC\uB9C8\uC778\uC9C0\uAC00 \uC788\uB2E4.",
18137
+ "inputSchema": {
18138
+ "type": "object",
18139
+ "properties": {
18140
+ "cursor": {
18141
+ "anyOf": [
18142
+ {
18143
+ "type": "string"
18144
+ },
18145
+ {
18146
+ "type": "null"
18147
+ }
18148
+ ],
18149
+ "default": null,
18150
+ "title": "Cursor"
18151
+ },
18152
+ "limit": {
18153
+ "default": 50,
18154
+ "maximum": 200,
18155
+ "minimum": 1,
18156
+ "title": "Limit",
18157
+ "type": "integer"
18158
+ }
18159
+ },
18160
+ "required": [],
18161
+ "additionalProperties": false
18162
+ },
18163
+ "annotations": {
18164
+ "readOnlyHint": true,
18165
+ "destructiveHint": false,
18166
+ "idempotentHint": true,
18167
+ "openWorldHint": false
18168
+ }
18169
+ },
18170
+ {
18171
+ "name": "democut_list_characters",
18172
+ "description": "\uC544\uBC14\uD0C0 \uBAA9\uB85D.",
18173
+ "inputSchema": {
18174
+ "type": "object",
18175
+ "properties": {},
18176
+ "required": [],
18177
+ "additionalProperties": false
18178
+ },
18179
+ "annotations": {
18180
+ "readOnlyHint": true,
18181
+ "destructiveHint": false,
18182
+ "idempotentHint": true,
18183
+ "openWorldHint": false
18184
+ }
18185
+ },
18186
+ {
18187
+ "name": "democut_create_character",
18188
+ "description": "\uC544\uBC14\uD0C0\uB97C \uB9CC\uB4E0\uB2E4(0\uC6D0).",
18189
+ "inputSchema": {
18190
+ "type": "object",
18191
+ "properties": {
18192
+ "name": {
18193
+ "maxLength": 100,
18194
+ "minLength": 1,
18195
+ "title": "Name",
18196
+ "type": "string"
18197
+ },
18198
+ "role": {
18199
+ "default": "",
18200
+ "title": "Role",
18201
+ "type": "string"
18202
+ },
18203
+ "voice_id": {
18204
+ "anyOf": [
18205
+ {
18206
+ "type": "string"
18207
+ },
18208
+ {
18209
+ "type": "null"
18210
+ }
18211
+ ],
18212
+ "default": null,
18213
+ "title": "Voice Id"
18214
+ },
18215
+ "persona_text": {
18216
+ "default": "",
18217
+ "title": "Persona Text",
18218
+ "type": "string"
18219
+ },
18220
+ "look_text": {
18221
+ "default": "",
18222
+ "title": "Look Text",
18223
+ "type": "string"
18224
+ }
18225
+ },
18226
+ "required": [
18227
+ "name"
18228
+ ],
18229
+ "additionalProperties": false
18230
+ },
18231
+ "annotations": {
18232
+ "readOnlyHint": false,
18233
+ "destructiveHint": false,
18234
+ "idempotentHint": false,
18235
+ "openWorldHint": false
18236
+ }
18237
+ },
18238
+ {
18239
+ "name": "democut_get_character",
18240
+ "description": "\uC544\uBC14\uD0C0 \uD558\uB098(\uC0AC\uC9C4 \uD310).",
18241
+ "inputSchema": {
18242
+ "type": "object",
18243
+ "properties": {
18244
+ "character_id": {
18245
+ "type": "string",
18246
+ "description": "\uC544\uBC14\uD0C0 id(chr_\u2026)"
18247
+ }
18248
+ },
18249
+ "required": [
18250
+ "character_id"
18251
+ ],
18252
+ "additionalProperties": false
18253
+ },
18254
+ "annotations": {
18255
+ "readOnlyHint": true,
18256
+ "destructiveHint": false,
18257
+ "idempotentHint": true,
18258
+ "openWorldHint": false
18259
+ }
18260
+ },
18261
+ {
18262
+ "name": "democut_put_character",
18263
+ "description": "\uC544\uBC14\uD0C0\uB97C \uC804\uCCB4 \uAD50\uCCB4\uD55C\uB2E4(If-Match rev). democut_get_character \uC758 rev \uB97C \uADF8\uB300\uB85C \uB123\uC5B4\uB77C \u2014 \uADF8 \uC0AC\uC774 \uB204\uAC00 \uBC14\uAFE8\uC73C\uBA74 409 \uC774\uACE0 \uBCD1\uD569\uD558\uC9C0 \uC54A\uB294\uB2E4.",
18264
+ "inputSchema": {
18265
+ "type": "object",
18266
+ "properties": {
18267
+ "character_id": {
18268
+ "type": "string",
18269
+ "description": "\uC544\uBC14\uD0C0 id(chr_\u2026)"
18270
+ },
18271
+ "name": {
18272
+ "maxLength": 100,
18273
+ "minLength": 1,
18274
+ "title": "Name",
18275
+ "type": "string"
18276
+ },
18277
+ "role": {
18278
+ "default": "",
18279
+ "title": "Role",
18280
+ "type": "string"
18281
+ },
18282
+ "voice_id": {
18283
+ "anyOf": [
18284
+ {
18285
+ "type": "string"
18286
+ },
18287
+ {
18288
+ "type": "null"
18289
+ }
18290
+ ],
18291
+ "default": null,
18292
+ "title": "Voice Id"
18293
+ },
18294
+ "persona_text": {
18295
+ "default": "",
18296
+ "title": "Persona Text",
18297
+ "type": "string"
18298
+ },
18299
+ "look_text": {
18300
+ "default": "",
18301
+ "title": "Look Text",
18302
+ "type": "string"
18303
+ },
18304
+ "rev": {
18305
+ "type": "integer",
18306
+ "minimum": 0,
18307
+ "description": "\uD604\uC7AC rev(get_character \uC758 \uAC12 \uADF8\uB300\uB85C). \uADF8 \uC0AC\uC774 \uBC14\uB00C\uC5C8\uC73C\uBA74 409 REV_MISMATCH"
18308
+ }
18309
+ },
18310
+ "required": [
18311
+ "character_id",
18312
+ "name",
18313
+ "rev"
18314
+ ],
18315
+ "additionalProperties": false
18316
+ },
18317
+ "annotations": {
18318
+ "readOnlyHint": false,
18319
+ "destructiveHint": false,
18320
+ "idempotentHint": true,
18321
+ "openWorldHint": false
18322
+ }
18323
+ },
18324
+ {
18325
+ "name": "democut_delete_character",
18326
+ "description": "\uC544\uBC14\uD0C0\uB97C \uC9C0\uC6B4\uB2E4.",
18327
+ "inputSchema": {
18328
+ "type": "object",
18329
+ "properties": {
18330
+ "character_id": {
18331
+ "type": "string",
18332
+ "description": "\uC544\uBC14\uD0C0 id(chr_\u2026)"
18333
+ }
18334
+ },
18335
+ "required": [
18336
+ "character_id"
18337
+ ],
18338
+ "additionalProperties": false
18339
+ },
18340
+ "annotations": {
18341
+ "readOnlyHint": false,
18342
+ "destructiveHint": true,
18343
+ "idempotentHint": true,
18344
+ "openWorldHint": false
18345
+ }
18346
+ }
18347
+ ];
18348
+
18349
+ // src/api-errors.ts
18350
+ var TOOL_BASE_NAMES = GENERATED_TOOLS.map((t) => t.name.replace(/^democut_/, "")).sort((a, b) => b.length - a.length);
18351
+ var escapeRe = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
18352
+ var NAME_PATTERNS = TOOL_BASE_NAMES.map((name) => [
18353
+ new RegExp(`(?<!democut_)(?<![\\w.])${escapeRe(name)}(?![\\w{(])`, "g"),
18354
+ `democut_${name}`
18355
+ ]);
18356
+ function callableToolNames(text) {
18357
+ let out2 = text;
18358
+ for (const [re, replacement] of NAME_PATTERNS) out2 = out2.replace(re, replacement);
18359
+ return out2;
18360
+ }
18361
+ function usd(v) {
18362
+ return v < 0.01 ? `$${v.toFixed(4)}` : `$${v.toFixed(2)}`;
18363
+ }
18364
+ function classifyApiError(e, ctx) {
18365
+ const hint = ctx.statusHint ?? "\uC0C1\uD0DC \uC870\uD68C";
18366
+ const contractHint = typeof e.extra.hint === "string" ? callableToolNames(e.extra.hint) : null;
18367
+ if (contractHint) {
18368
+ const lines = [contractHint];
18369
+ if (ctx.submitted) {
18370
+ lines.push(
18371
+ e.status < 500 ? "\uC544\uC9C1 \uC544\uBB34\uAC83\uB3C4 \uC81C\uCD9C\uB418\uC9C0 \uC54A\uC558\uACE0 \uACFC\uAE08\uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC694\uCCAD\uC744 \uACE0\uCCD0 \uB2E4\uC2DC \uD638\uCD9C\uD558\uC138\uC694." : `\u26A0\uFE0F \uC81C\uCD9C\uC774 \uC811\uC218\uB410\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uBCF4\uB0B4\uC9C0 \uB9D0\uACE0 ${hint} \uB85C \uC0C1\uD0DC\uB97C \uBA3C\uC800 \uD655\uC778\uD558\uC138\uC694.`
18372
+ );
18373
+ }
18374
+ return {
18375
+ safety: e.status >= 500 && ctx.submitted ? "unsafe" : e.retriable === false ? "fixable" : "safe",
18376
+ notCharged: e.status < 500,
18377
+ lines
18378
+ };
18379
+ }
18380
+ if (e.status === 422 && e.code === "VIDEOGEN_UPSTREAM_REJECTED") {
18381
+ return {
18382
+ safety: "unsafe",
18383
+ // 돈이 나갔다가 돌아왔다 — "애초에 과금이 없었다" 와는 다르다. 그 구분을 흐리면
18384
+ // 원장을 보는 사람이 이 거래를 설명하지 못한다.
18385
+ notCharged: false,
18386
+ lines: [
18387
+ "\uC5C5\uC2A4\uD2B8\uB9BC\uC774 \uC774 \uC791\uC5C5\uC744 \uC601\uAD6C \uAC70\uBD80\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC870\uD68C\uD574\uB3C4 \uBCF5\uAD6C\uB418\uC9C0 \uC54A\uC73C\uBA70, \uACFC\uAE08\uC740 \uD658\uBD88\uB410\uC2B5\uB2C8\uB2E4.",
18388
+ "\uACE0\uCE60 \uD30C\uB77C\uBBF8\uD130\uAC00 \uC788\uB294 \uC624\uB958\uAC00 \uC544\uB2D9\uB2C8\uB2E4 \u2014 \uC0C8\uB85C \uB9CC\uB4E4\uB824\uBA74 \uD504\uB86C\uD504\uD2B8\xB7\uC124\uC815\uC744 \uBC14\uAFD4 **\uC0C8\uB85C \uC81C\uCD9C**\uD574\uC57C \uD558\uACE0, \uADF8\uAC74 \uB2E4\uC2DC \uACFC\uAE08\uB429\uB2C8\uB2E4(\uC0AC\uC6A9\uC790 \uB3D9\uC758\uB97C \uBC1B\uC73C\uC138\uC694)."
18389
+ ]
18390
+ };
18391
+ }
18392
+ if (e.status === 404 && e.code === "VIDEOGEN_JOB_NOT_FOUND") {
18393
+ return {
18394
+ safety: "unsafe",
18395
+ notCharged: false,
18396
+ lines: [
18397
+ "\uADF8 \uC791\uC5C5\uC744 \uD655\uC778\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. job_id \uAC00 \uB9DE\uB294\uC9C0 \uBA3C\uC800 \uD655\uC778\uD558\uC138\uC694.",
18398
+ "\u26A0\uFE0F \uC791\uC5C5\uC774 \uC0B4\uC544 \uC788\uB294\uB370 \uC870\uD68C\uB9CC \uC5B4\uAE0B\uB0AC\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4 \u2014 \uC0C8\uB85C \uC81C\uCD9C\uD558\uBA74 **\uBCC4\uB3C4 \uC791\uC5C5\uC73C\uB85C \uB2E4\uC2DC \uACFC\uAE08**\uB429\uB2C8\uB2E4."
18399
+ ]
18400
+ };
18401
+ }
18402
+ if (e.status === 402) {
18403
+ const lines = [];
18404
+ const limit = e.extra.limit_usd;
18405
+ const would = e.extra.would_cost_usd;
18406
+ if (typeof limit === "number" && typeof would === "number") {
18407
+ lines.push(`\uC0C1\uD55C ${usd(limit)} \xB7 \uC774 \uC694\uCCAD ${usd(would)}`);
18408
+ }
18409
+ lines.push("\uD574\uC0C1\uB3C4\uB098 \uAE38\uC774\uB97C \uB0AE\uCDB0 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694. \uC544\uC9C1 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
18410
+ return { safety: "fixable", notCharged: true, lines };
18411
+ }
18412
+ if (e.status === 422) {
18413
+ return {
18414
+ safety: "fixable",
18415
+ notCharged: true,
18416
+ lines: ["\uD30C\uB77C\uBBF8\uD130\uB97C \uACE0\uCCD0 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694. \uC544\uC9C1 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4."]
18417
+ };
18418
+ }
18419
+ if (e.status === 503) {
18420
+ return {
18421
+ safety: "safe",
18422
+ notCharged: true,
18423
+ lines: ["\uC77C\uC2DC\uC801\uC778 \uC624\uB958\uC785\uB2C8\uB2E4. \uC7A0\uC2DC \uD6C4 \uADF8\uB300\uB85C \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uB3C4 \uC548\uC804\uD569\uB2C8\uB2E4."]
18424
+ };
18425
+ }
18426
+ if (e.status === 502) {
18427
+ return ctx.submitted ? {
18428
+ safety: "unsafe",
18429
+ notCharged: false,
18430
+ lines: [
18431
+ "\u26A0\uFE0F \uC81C\uCD9C\uC774 \uC774\uBBF8 \uC811\uC218\uB410\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uC81C\uCD9C\uD558\uBA74 \uB450 \uBC88 \uACFC\uAE08\uB429\uB2C8\uB2E4 \u2014",
18432
+ `\uC7AC\uC2DC\uB3C4\uD558\uC9C0 \uB9D0\uACE0 ${hint} \uB85C \uD655\uC778\uD558\uAC70\uB098 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB38\uC758\uD558\uC138\uC694.`
18433
+ ]
18434
+ } : {
18435
+ safety: "safe",
18436
+ notCharged: true,
18437
+ lines: [
18438
+ "\uC5C5\uC2A4\uD2B8\uB9BC \uC624\uB958\uC785\uB2C8\uB2E4. \uC774 \uC694\uCCAD\uC740 \uBD80\uC791\uC6A9\uC774 \uC5C6\uC73C\uBBC0\uB85C \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uB3C4 \uC548\uC804\uD569\uB2C8\uB2E4."
18439
+ ]
18440
+ };
18441
+ }
18442
+ if (e.status === 404) {
18443
+ const lines = [];
18444
+ if (e.code === "VIDEOGEN_PROJECT_NOT_FOUND") {
18445
+ lines.push(
18446
+ "democut_list_projects \uB85C \uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC758 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D\uC744 \uD655\uC778\uD558\uACE0 \uADF8\uC911 \uD558\uB098\uC758 \uC2AC\uB7EC\uADF8\uB97C \uC4F0\uC138\uC694. \uBAA9\uB85D\uC774 \uBE44\uC5B4 \uC788\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uD504\uB85C\uC81D\uD2B8\uB97C \uBA3C\uC800 \uB9CC\uB4E4\uC5B4 \uB2EC\uB77C\uACE0 \uC54C\uB9AC\uC138\uC694."
18447
+ );
18448
+ }
18449
+ lines.push("\uC544\uC9C1 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 \uAC12\uC744 \uACE0\uCCD0 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.");
18450
+ return { safety: "fixable", notCharged: true, lines };
16235
18451
  }
16236
- async sendPromptListChanged() {
16237
- return this.notification({ method: "notifications/prompts/list_changed" });
18452
+ if (e.status === 403) {
18453
+ return {
18454
+ safety: "unknown",
18455
+ notCharged: true,
18456
+ lines: ["\uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC5D0\uC11C \uC601\uC0C1\uC744 \uC0DD\uC131\uD560 \uAD8C\uD55C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(\uBA64\uBC84 \uC774\uC0C1 \uD544\uC694)."]
18457
+ };
16238
18458
  }
16239
- };
18459
+ return { safety: "unknown", notCharged: false, lines: [] };
18460
+ }
16240
18461
 
16241
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
16242
- import process3 from "process";
18462
+ // src/mcp/tools.ts
18463
+ import { createWriteStream, existsSync as existsSync2 } from "fs";
18464
+ import { readFile } from "fs/promises";
18465
+ import { basename } from "path";
18466
+ import { Readable } from "stream";
18467
+ import { pipeline as streamPipeline } from "stream/promises";
16243
18468
 
16244
- // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
16245
- var STDIO_DEFAULT_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
16246
- var ReadBuffer = class {
16247
- constructor(options) {
16248
- this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
18469
+ // src/api-client.ts
18470
+ var ApiError = class extends Error {
18471
+ constructor(status, code, message, retriable, extra = {}) {
18472
+ super(message);
18473
+ this.status = status;
18474
+ this.code = code;
18475
+ this.retriable = retriable;
18476
+ this.extra = extra;
18477
+ this.name = "ApiError";
16249
18478
  }
16250
- append(chunk) {
16251
- const newSize = (this._buffer?.length ?? 0) + chunk.length;
16252
- if (newSize > this._maxBufferSize) {
16253
- this.clear();
16254
- throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
18479
+ status;
18480
+ code;
18481
+ retriable;
18482
+ extra;
18483
+ };
18484
+ function parseDetail(status, body) {
18485
+ const wrapped = body?.error;
18486
+ if (wrapped && typeof wrapped === "object" && !Array.isArray(wrapped)) {
18487
+ const w = wrapped;
18488
+ if (typeof w.code === "string") {
18489
+ const data = w.data && typeof w.data === "object" ? w.data : {};
18490
+ return new ApiError(
18491
+ status,
18492
+ w.code,
18493
+ typeof w.message === "string" ? w.message : `HTTP ${status}`,
18494
+ typeof w.retry_safe === "boolean" ? w.retry_safe : null,
18495
+ { ...data, ...typeof w.hint === "string" ? { hint: w.hint } : {} }
18496
+ );
16255
18497
  }
16256
- this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
16257
18498
  }
16258
- readMessage() {
16259
- if (!this._buffer) {
16260
- return null;
16261
- }
16262
- const index = this._buffer.indexOf("\n");
16263
- if (index === -1) {
16264
- return null;
18499
+ const detail = body?.detail;
18500
+ if (detail && typeof detail === "object" && !Array.isArray(detail)) {
18501
+ const d = detail;
18502
+ if (typeof d.code === "string" || typeof d.message === "string") {
18503
+ const { code, message, retriable, ...extra } = d;
18504
+ return new ApiError(
18505
+ status,
18506
+ typeof code === "string" ? code : `HTTP_${status}`,
18507
+ typeof message === "string" ? message : `HTTP ${status}`,
18508
+ typeof retriable === "boolean" ? retriable : null,
18509
+ extra
18510
+ );
16265
18511
  }
16266
- const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
16267
- this._buffer = this._buffer.subarray(index + 1);
16268
- return deserializeMessage(line);
16269
- }
16270
- clear() {
16271
- this._buffer = void 0;
16272
18512
  }
16273
- };
16274
- function deserializeMessage(line) {
16275
- return JSONRPCMessageSchema.parse(JSON.parse(line));
16276
- }
16277
- function serializeMessage(message) {
16278
- return JSON.stringify(message) + "\n";
16279
- }
16280
-
16281
- // node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
16282
- var StdioServerTransport = class {
16283
- constructor(_stdin = process3.stdin, _stdout = process3.stdout, options) {
16284
- this._stdin = _stdin;
16285
- this._stdout = _stdout;
16286
- this._started = false;
16287
- this._ondata = (chunk) => {
16288
- try {
16289
- this._readBuffer.append(chunk);
16290
- this.processReadBuffer();
16291
- } catch (error2) {
16292
- this.onerror?.(error2);
16293
- this.close().catch(() => {
16294
- });
16295
- }
16296
- };
16297
- this._onerror = (error2) => {
16298
- this.onerror?.(error2);
16299
- };
16300
- this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
18513
+ if (typeof detail === "string") {
18514
+ return new ApiError(status, `HTTP_${status}`, detail, null);
16301
18515
  }
16302
- /**
16303
- * Starts listening for messages on stdin.
16304
- */
16305
- async start() {
16306
- if (this._started) {
16307
- throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
16308
- }
16309
- this._started = true;
16310
- this._stdin.on("data", this._ondata);
16311
- this._stdin.on("error", this._onerror);
18516
+ if (Array.isArray(detail)) {
18517
+ const lines = detail.map((e) => {
18518
+ const item = e;
18519
+ const where = Array.isArray(item.loc) ? item.loc.filter((p) => p !== "body").join(".") : "";
18520
+ const msg = typeof item.msg === "string" ? item.msg : JSON.stringify(e);
18521
+ return where ? `${where}: ${msg}` : msg;
18522
+ });
18523
+ return new ApiError(status, "VALIDATION_ERROR", lines.join("\n"), true);
16312
18524
  }
16313
- processReadBuffer() {
16314
- while (true) {
16315
- try {
16316
- const message = this._readBuffer.readMessage();
16317
- if (message === null) {
16318
- break;
16319
- }
16320
- this.onmessage?.(message);
16321
- } catch (error2) {
16322
- this.onerror?.(error2);
16323
- }
18525
+ return new ApiError(status, `HTTP_${status}`, `\uC694\uCCAD\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (HTTP ${status}).`, null);
18526
+ }
18527
+ async function apiRequest(baseUrl, path, init = {}, deps = {}) {
18528
+ const fetchImpl = deps.fetchImpl ?? fetch;
18529
+ const token = await getValidAccessToken(baseUrl, deps);
18530
+ const headers = {
18531
+ ...init.headers ?? {},
18532
+ Authorization: `Bearer ${token}`,
18533
+ "User-Agent": `democut/${VERSION}`
18534
+ };
18535
+ if (init.body !== void 0) headers["Content-Type"] = "application/json";
18536
+ const res = await fetchImpl(`${baseUrl}${path}`, {
18537
+ method: init.method ?? "GET",
18538
+ headers,
18539
+ ...init.body === void 0 ? {} : { body: JSON.stringify(init.body) }
18540
+ });
18541
+ const text = await res.text();
18542
+ let json = null;
18543
+ if (text) {
18544
+ try {
18545
+ json = JSON.parse(text);
18546
+ } catch {
18547
+ json = null;
16324
18548
  }
16325
18549
  }
16326
- async close() {
16327
- this._stdin.off("data", this._ondata);
16328
- this._stdin.off("error", this._onerror);
16329
- const remainingDataListeners = this._stdin.listenerCount("data");
16330
- if (remainingDataListeners === 0) {
16331
- this._stdin.pause();
18550
+ if (!res.ok) {
18551
+ if (res.status === 401) {
18552
+ throw new ApiError(
18553
+ 401,
18554
+ "UNAUTHENTICATED",
18555
+ "\uC778\uC99D\uC774 \uB9CC\uB8CC\uB418\uC5C8\uAC70\uB098 \uC720\uD6A8\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. 'democut auth login' \uC73C\uB85C \uB2E4\uC2DC \uB85C\uADF8\uC778\uD558\uC138\uC694.",
18556
+ false
18557
+ );
16332
18558
  }
16333
- this._readBuffer.clear();
16334
- this.onclose?.();
16335
- }
16336
- send(message) {
16337
- return new Promise((resolve) => {
16338
- const json = serializeMessage(message);
16339
- if (this._stdout.write(json)) {
16340
- resolve();
16341
- } else {
16342
- this._stdout.once("drain", resolve);
16343
- }
16344
- });
18559
+ throw parseDetail(res.status, json);
16345
18560
  }
16346
- };
16347
-
16348
- // src/mcp/tools.ts
16349
- import { existsSync as existsSync2 } from "fs";
18561
+ return json;
18562
+ }
16350
18563
 
16351
18564
  // src/credits.ts
16352
18565
  var LEDGER_MAX_LIMIT = 200;
@@ -16362,7 +18575,7 @@ function balance(baseUrl, workspaceId, deps = {}) {
16362
18575
  function ledger(baseUrl, workspaceId, opts = {}, deps = {}) {
16363
18576
  const q = new URLSearchParams();
16364
18577
  q.set("limit", String(opts.limit ?? LEDGER_DEFAULT_LIMIT));
16365
- if (opts.beforeId !== void 0) q.set("before_id", String(opts.beforeId));
18578
+ if (opts.cursor !== void 0) q.set("cursor", opts.cursor);
16366
18579
  return apiRequest(
16367
18580
  baseUrl,
16368
18581
  `/api/workspaces/${encodeURIComponent(workspaceId)}/credits/ledger?${q}`,
@@ -16381,13 +18594,13 @@ function create(baseUrl, body, deps = {}) {
16381
18594
  return apiRequest(baseUrl, "/api/projects", { method: "POST", body }, deps);
16382
18595
  }
16383
18596
  async function defaultVoiceId(baseUrl, deps = {}) {
16384
- const out3 = await apiRequest(
18597
+ const out2 = await apiRequest(
16385
18598
  baseUrl,
16386
18599
  "/api/projects/voices",
16387
18600
  {},
16388
18601
  deps
16389
18602
  );
16390
- const id = out3.default_voice_id;
18603
+ const id = out2.default_voice_id;
16391
18604
  if (!id) {
16392
18605
  throw new Error("\uC11C\uBC84\uAC00 \uAE30\uBCF8 \uC74C\uC131\uC744 \uC54C\uB824\uC8FC\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 (default_voice_id \uC5C6\uC74C).");
16393
18606
  }
@@ -16395,10 +18608,6 @@ async function defaultVoiceId(baseUrl, deps = {}) {
16395
18608
  }
16396
18609
 
16397
18610
  // src/mcp/tools.ts
16398
- var COST_TOLERANCE_USD = 5e-3;
16399
- function usd3(v) {
16400
- return v < 0.01 ? `$${v.toFixed(4)}` : `$${v.toFixed(2)}`;
16401
- }
16402
18611
  function describeError2(e, ctx) {
16403
18612
  if (e instanceof NotLoggedInError) {
16404
18613
  return {
@@ -16412,188 +18621,64 @@ function describeError2(e, ctx) {
16412
18621
  }
16413
18622
  return { isError: true, text: `\uC624\uB958: ${e?.message ?? String(e)}` };
16414
18623
  }
16415
- async function guarded2(ctx, fn) {
16416
- try {
16417
- return await fn();
16418
- } catch (e) {
16419
- return describeError2(e, ctx);
18624
+ async function saveUrlToFile(url, outPath, fetchImpl = fetch) {
18625
+ const res = await fetchImpl(url);
18626
+ if (!res.ok || !res.body) {
18627
+ throw new Error(`\uB0B4\uB824\uBC1B\uAE30 \uC2E4\uD328: ${res.status} ${res.statusText}`);
16420
18628
  }
18629
+ await streamPipeline(Readable.fromWeb(res.body), createWriteStream(outPath));
16421
18630
  }
16422
- var READ_ONLY = { submitted: false };
16423
- var SUBMITTING = {
16424
- submitted: true,
16425
- statusHint: "democut_get_video_status"
16426
- };
16427
- function authStatus(deps = {}) {
16428
- return guarded2(READ_ONLY, async () => {
16429
- const base = resolveBaseUrl(deps.baseUrl);
16430
- const token = await getValidAccessToken(base, deps);
16431
- const me = await whoami(base, token, deps.fetchImpl);
16432
- return {
16433
- text: [
16434
- `\uB85C\uADF8\uC778\uB428 (${base})`,
16435
- `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4: ${me.workspace_id ?? "-"}`,
16436
- `\uC815\uCCB4: ${me.kind} \xB7 \uC5ED\uD560: ${me.role ?? "-"} \xB7 \uD2F0\uC5B4: ${me.tier ?? "-"}`
16437
- ].join("\n")
16438
- };
16439
- });
16440
- }
16441
- function toEstimateIn(a) {
16442
- return {
16443
- duration_s: a.duration_s ?? 5,
16444
- resolution: a.resolution ?? "720p",
16445
- ratio: a.ratio ?? "16:9",
16446
- ...a.model ? { model: a.model } : {},
16447
- // ★ 추정과 생성이 **같은 모델 계열**을 봐야 confirmed_cost_usd 대조가 성립한다.
16448
- // 생성 경로는 `image_urls` 를, 추정 전용 호출은 `has_image` 를 준다.
16449
- has_image: Boolean(a.has_image || a.image_urls?.length)
16450
- };
16451
- }
16452
- var MOCK_BANNER = "\u26A0\uFE0F \uC774 \uBC30\uD3EC\uB294 mock \uBAA8\uB4DC\uC785\uB2C8\uB2E4 \u2014 \uC601\uC0C1\uC774 **\uC2E4\uC81C\uB85C \uC0DD\uC131\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4**. \uC544\uB798 \uAE08\uC561\xB7job_id\xB7URL \uC740 \uC804\uBD80 \uAC00\uC9DC\uC774\uBA70 \uC2E4\uC81C\uB85C \uACFC\uAE08\uB418\uC9C0\uB3C4 \uC54A\uC2B5\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC0DD\uC131\uC774 \uB418\uC5C8\uB2E4\uACE0 \uBCF4\uACE0\uD558\uC9C0 \uB9C8\uC138\uC694.";
16453
- function estimateCost(a, deps = {}) {
16454
- return guarded2(READ_ONLY, async () => {
16455
- const base = resolveBaseUrl(deps.baseUrl);
16456
- const r = await estimate(base, toEstimateIn(a), deps);
16457
- if (r.mock) {
16458
- return {
16459
- text: [
16460
- MOCK_BANNER,
16461
- "",
16462
- `(\uCC38\uACE0\uC6A9 \uCD94\uC815\uCE58: ${usd3(r.cost_usd)} \xB7 ${r.model})`,
16463
- "",
16464
- "\uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBE44\uC6A9 \uB3D9\uC758\uB97C \uAD6C\uD558\uC9C0 \uB9C8\uC138\uC694 \u2014 \uC774 \uBC30\uD3EC\uC5D0\uC11C\uB294 \uC81C\uCD9C\uD574\uB3C4 \uC2E4\uC81C \uC601\uC0C1\uC774 \uB9CC\uB4E4\uC5B4\uC9C0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC6B4\uC601\uC790\uC5D0\uAC8C API \uD0A4 \uC124\uC815\uC744 \uC694\uCCAD\uD558\uC138\uC694."
16465
- ].join("\n")
16466
- };
16467
- }
16468
- return {
16469
- text: [
16470
- `\uC608\uC0C1 \uBE44\uC6A9: ${usd3(r.cost_usd)} (${r.tokens.toLocaleString()} tokens \xB7 ${r.model})`,
16471
- `cost_usd \uC6D0\uAC12: ${r.cost_usd}`,
16472
- "",
16473
- `\uC0DD\uC131\uD558\uB824\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC774 \uAE08\uC561\uC744 \uC54C\uB9AC\uACE0 \uB3D9\uC758\uB97C \uBC1B\uC740 \uB4A4, generate_video \uC5D0 confirmed_cost_usd=${r.cost_usd} \uB97C \uADF8\uB300\uB85C \uB123\uC5B4 \uD638\uCD9C\uD558\uC138\uC694.`
16474
- ].join("\n")
16475
- };
18631
+ async function uploadFile(base, path, meta2, deps) {
18632
+ const fetchImpl = deps.fetchImpl ?? fetch;
18633
+ const token = await getValidAccessToken(base, deps);
18634
+ const bytes = await readFile(path);
18635
+ const form = new FormData();
18636
+ form.set("kind", meta2.kind);
18637
+ if (meta2.projectSlug) form.set("project_slug", meta2.projectSlug);
18638
+ form.set("file", new Blob([bytes]), meta2.filename ?? basename(path));
18639
+ const res = await fetchImpl(`${base}/api/assets`, {
18640
+ method: "POST",
18641
+ headers: { Authorization: `Bearer ${token}`, "User-Agent": `democut/${VERSION}` },
18642
+ body: form
16476
18643
  });
16477
- }
16478
- function generateVideo(a, deps = {}) {
16479
- return guarded2(SUBMITTING, async () => {
16480
- if (!a.prompt?.trim()) {
16481
- return { isError: true, text: "prompt \uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4." };
16482
- }
16483
- if (typeof a.project_slug !== "string" || !a.project_slug.trim()) {
16484
- return {
16485
- isError: true,
16486
- text: "project_slug \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uBE44\uC6A9\uC744 \uADC0\uC18D\uC2DC\uD0AC \uBCF8\uC778 \uC18C\uC720 \uD504\uB85C\uC81D\uD2B8\uC758 \uC2AC\uB7EC\uADF8\uB97C \uB123\uC5B4 \uB2E4\uC2DC \uD638\uCD9C\uD558\uC138\uC694. \uC544\uC9C1 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.\n\uC2AC\uB7EC\uADF8\uB97C \uBAA8\uB974\uBA74 democut_list_projects \uB85C \uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC758 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D\uC744 \uD655\uC778\uD558\uC138\uC694. \uBAA9\uB85D\uC774 \uBE44\uC5B4 \uC788\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uD504\uB85C\uC81D\uD2B8\uB97C \uBA3C\uC800 \uB9CC\uB4E4\uC5B4 \uB2EC\uB77C\uACE0 \uC54C\uB9AC\uC138\uC694."
16487
- };
16488
- }
16489
- const base = resolveBaseUrl(deps.baseUrl);
16490
- const est = toEstimateIn(a);
16491
- const quote = await estimate(base, est, deps);
16492
- if (typeof a.confirmed_cost_usd !== "number") {
16493
- return {
16494
- isError: true,
16495
- text: `confirmed_cost_usd \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC774 \uC694\uCCAD\uC758 \uC608\uC0C1 \uBE44\uC6A9\uC740 ${usd3(quote.cost_usd)} (\uC6D0\uAC12 ${quote.cost_usd}) \uC785\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC54C\uB9AC\uACE0 \uB3D9\uC758\uB97C \uBC1B\uC740 \uB4A4 \uADF8 \uAC12\uC744 \uB123\uC5B4 \uB2E4\uC2DC \uD638\uCD9C\uD558\uC138\uC694.`
16496
- };
16497
- }
16498
- if (Math.abs(a.confirmed_cost_usd - quote.cost_usd) > COST_TOLERANCE_USD) {
16499
- return {
16500
- isError: true,
16501
- text: `\uD655\uC778\uD55C \uAE08\uC561(${usd3(a.confirmed_cost_usd)})\uC774 \uC2E4\uC81C \uC608\uC0C1 \uBE44\uC6A9(${usd3(quote.cost_usd)})\uACFC \uB2E4\uB985\uB2C8\uB2E4. \uD30C\uB77C\uBBF8\uD130\uAC00 \uADF8 \uC0AC\uC774 \uBC14\uB00C\uC5C8\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4. estimate_video_cost \uB97C \uB2E4\uC2DC \uD638\uCD9C\uD574 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC0C8 \uAE08\uC561\uC744 \uD655\uC778\uBC1B\uC73C\uC138\uC694. \uC544\uC9C1 \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.`
16502
- };
16503
- }
16504
- const body = {
16505
- prompt: a.prompt,
16506
- duration_s: est.duration_s,
16507
- resolution: est.resolution,
16508
- ratio: est.ratio,
16509
- generate_audio: Boolean(a.generate_audio),
16510
- watermark: Boolean(a.watermark),
16511
- ...a.model ? { model: a.model } : {},
16512
- ...a.seed !== void 0 ? { seed: a.seed } : {},
16513
- ...a.image_urls?.length ? { image_urls: a.image_urls } : {},
16514
- project_slug: a.project_slug.trim()
16515
- };
16516
- const job = await submit(base, body, deps);
16517
- if (job.duplicate) {
16518
- return {
16519
- text: job.pending ? "\uAC19\uC740 \uC694\uCCAD\uC774 \uBC29\uAE08 \uC81C\uCD9C\uB418\uC5B4 \uC9C4\uD589 \uC911\uC785\uB2C8\uB2E4. job_id \uAC00 \uC544\uC9C1 \uC5C6\uC73C\uB2C8 \uC7A0\uC2DC \uD6C4 \uAC19\uC740 \uD30C\uB77C\uBBF8\uD130\uB85C \uB2E4\uC2DC \uD638\uCD9C\uD558\uC9C0 \uB9D0\uACE0 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC54C\uB9AC\uC138\uC694(\uC0C8\uB85C \uB9CC\uB4E4\uBA74 \uB2E4\uC2DC \uACFC\uAE08\uB429\uB2C8\uB2E4)." : `\uAC19\uC740 \uC694\uCCAD\uC774 \uC774\uBBF8 \uC9C4\uD589 \uC911\uC785\uB2C8\uB2E4 (job_id: ${job.job_id}). \uC0C8\uB85C \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. get_video_status \uB85C \uD655\uC778\uD558\uC138\uC694.`
16520
- };
16521
- }
16522
- if (job.mock) {
16523
- return {
16524
- text: [
16525
- MOCK_BANNER,
16526
- "",
16527
- `(\uAC00\uC9DC job_id: ${job.job_id} \xB7 \uBAA8\uB378 ${job.model})`,
16528
- "",
16529
- "\uC2E4\uC81C\uB85C \uC81C\uCD9C\uB418\uC9C0 \uC54A\uC558\uACE0 \uACFC\uAE08\uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4. \uC774 job_id \uB85C \uC0C1\uD0DC\uB97C \uC870\uD68C\uD558\uBA74 \uAC00\uC9DC URL \uC774 \uB098\uC635\uB2C8\uB2E4 \u2014 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC601\uC0C1\uC774 \uB9CC\uB4E4\uC5B4\uC84C\uB2E4\uACE0 \uB9D0\uD558\uC9C0 \uB9C8\uC138\uC694."
16530
- ].join("\n")
16531
- };
18644
+ const text = await res.text();
18645
+ let json = null;
18646
+ if (text) {
18647
+ try {
18648
+ json = JSON.parse(text);
18649
+ } catch {
18650
+ json = null;
16532
18651
  }
18652
+ }
18653
+ if (!res.ok) throw parseDetail(res.status, json);
18654
+ return json;
18655
+ }
18656
+ async function guarded(ctx, fn) {
18657
+ try {
18658
+ return await fn();
18659
+ } catch (e) {
18660
+ return describeError2(e, ctx);
18661
+ }
18662
+ }
18663
+ var READ_ONLY = { submitted: false };
18664
+ var SUBMITTING = {
18665
+ submitted: true,
18666
+ statusHint: "democut_credit_ledger"
18667
+ };
18668
+ function authStatus(deps = {}) {
18669
+ return guarded(READ_ONLY, async () => {
18670
+ const base = resolveBaseUrl(deps.baseUrl);
18671
+ const token = await getValidAccessToken(base, deps);
18672
+ const me = await whoami(base, token, deps.fetchImpl);
16533
18673
  return {
16534
18674
  text: [
16535
- `\uC81C\uCD9C\uB428 \u2014 job_id: ${job.job_id}`,
16536
- `\uC608\uC0C1 \uBE44\uC6A9 ${usd3(job.estimated_cost_usd)} \xB7 \uBAA8\uB378 ${job.model}`,
16537
- "",
16538
- "\uC0DD\uC131\uC5D0\uB294 \uBCF4\uD1B5 90\uCD08 \uC774\uC0C1 \uAC78\uB9BD\uB2C8\uB2E4. get_video_status \uB85C \uD655\uC778\uD558\uC138\uC694.",
16539
- "\u26A0\uFE0F \uC2E4\uD328\uD574 \uBCF4\uC5EC\uB3C4 \uB2E4\uC2DC \uC81C\uCD9C\uD558\uC9C0 \uB9C8\uC138\uC694 \u2014 \uC7AC\uC81C\uCD9C\uC740 \uBCC4\uAC1C \uC0DD\uC131\uC774\uB77C \uB2E4\uC2DC \uACFC\uAE08\uB429\uB2C8\uB2E4."
18675
+ `\uB85C\uADF8\uC778\uB428 (${base})`,
18676
+ `\uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4: ${me.workspace_id ?? "-"}`,
18677
+ `\uC815\uCCB4: ${me.kind} \xB7 \uC5ED\uD560: ${me.role ?? "-"} \xB7 \uD2F0\uC5B4: ${me.tier ?? "-"}`
16540
18678
  ].join("\n")
16541
18679
  };
16542
18680
  });
16543
18681
  }
16544
- function videoStatus(a, deps = {}) {
16545
- return guarded2(READ_ONLY, async () => {
16546
- if (!a.job_id?.trim()) return { isError: true, text: "job_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
16547
- const base = resolveBaseUrl(deps.baseUrl);
16548
- const job = await status(base, a.job_id, a.project_slug, deps);
16549
- if (job.mock) {
16550
- return {
16551
- text: [
16552
- MOCK_BANNER,
16553
- "",
16554
- `(\uAC00\uC9DC \uC0C1\uD0DC: ${job.status} \xB7 \uAC00\uC9DC \uACB0\uACFC: ${job.video_url ?? "\uC5C6\uC74C"})`,
16555
- "",
16556
- "\uC774 URL \uC740 \uC2E4\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uB0B4\uB824\uBC1B\uC9C0 \uC54A\uC558\uACE0, \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC804\uB2EC\uD558\uC9C0 \uB9C8\uC138\uC694. \uC644\uB8CC\uB97C \uAE30\uB2E4\uB9AC\uBA70 \uB2E4\uC2DC \uC870\uD68C\uD558\uC9C0\uB3C4 \uB9C8\uC138\uC694."
16557
- ].join("\n")
16558
- };
16559
- }
16560
- if (job.status === "failed" || job.status === "cancelled") {
16561
- return {
16562
- isError: true,
16563
- text: `\uC0DD\uC131 \uC2E4\uD328 (${job.status}): ${job.error ?? "\uC0AC\uC720 \uBBF8\uC0C1"}`
16564
- };
16565
- }
16566
- if (job.status !== "succeeded") {
16567
- return { text: `\uC544\uC9C1 \uC9C4\uD589 \uC911\uC785\uB2C8\uB2E4 (${job.status}). \uC7A0\uC2DC \uD6C4 \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.` };
16568
- }
16569
- const lines = [`\uC644\uB8CC \u2014 ${job.status}`];
16570
- if (job.cost_usd != null) {
16571
- lines.push(
16572
- `\uC2E4\uC81C \uBE44\uC6A9 ${usd3(job.cost_usd)}${job.tokens != null ? ` (${job.tokens.toLocaleString()} tokens)` : ""}`
16573
- );
16574
- }
16575
- if (job.video_url && a.output_path) {
16576
- if (existsSync2(a.output_path)) {
16577
- lines.push(`\uC800\uC7A5\uD558\uC9C0 \uC54A\uC74C: ${a.output_path} \uC5D0 \uC774\uBBF8 \uD30C\uC77C\uC774 \uC788\uC2B5\uB2C8\uB2E4(\uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4).`);
16578
- lines.push(`URL: ${job.video_url}`);
16579
- lines.push("\uB2E4\uB978 \uACBD\uB85C\uB97C \uC9C0\uC815\uD558\uAC70\uB098 \uC704 URL \uB85C \uC9C1\uC811 \uBC1B\uC73C\uC138\uC694 \u2014 \uC11C\uBC84\uB294 \uBCF4\uAD00\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.");
16580
- return { text: lines.join("\n") };
16581
- }
16582
- try {
16583
- await (deps.downloadImpl ?? download)(job.video_url, a.output_path);
16584
- lines.push(`\uC800\uC7A5\uB428: ${a.output_path}`);
16585
- } catch (e) {
16586
- lines.push(`\uB0B4\uB824\uBC1B\uAE30 \uC2E4\uD328: ${e?.message ?? String(e)}`);
16587
- lines.push(`URL: ${job.video_url}`);
16588
- lines.push("\u26A0\uFE0F \uC704 URL \uB85C \uC9C1\uC811 \uBC1B\uC73C\uC138\uC694 \u2014 \uC11C\uBC84\uB294 \uBCF4\uAD00\uD558\uC9C0 \uC54A\uC73C\uBA70 \uB2E4\uC2DC \uB9CC\uB4E4\uBA74 \uB610 \uACFC\uAE08\uB429\uB2C8\uB2E4.");
16589
- }
16590
- } else if (job.video_url) {
16591
- lines.push(`URL: ${job.video_url}`);
16592
- lines.push("\u26A0\uFE0F \uC11C\uBC84\uB294 \uC774 \uC0B0\uCD9C\uBB3C\uC744 \uBCF4\uAD00\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 output_path \uB97C \uC8FC\uBA74 \uBC14\uB85C \uC800\uC7A5\uD569\uB2C8\uB2E4.");
16593
- }
16594
- return { text: lines.join("\n") };
16595
- });
16596
- }
16597
18682
  var krw = (v) => `${v.toLocaleString("ko-KR")}\uC6D0`;
16598
18683
  var NO_WORKSPACE = {
16599
18684
  isError: true,
@@ -16605,7 +18690,7 @@ async function resolveWorkspace(base, deps) {
16605
18690
  return me.workspace_id ?? null;
16606
18691
  }
16607
18692
  function creditBalance(deps = {}) {
16608
- return guarded2(READ_ONLY, async () => {
18693
+ return guarded(READ_ONLY, async () => {
16609
18694
  const base = resolveBaseUrl(deps.baseUrl);
16610
18695
  const ws = await resolveWorkspace(base, deps);
16611
18696
  if (!ws) return NO_WORKSPACE;
@@ -16630,46 +18715,53 @@ function creditBalance(deps = {}) {
16630
18715
  );
16631
18716
  } else {
16632
18717
  lines.push(
16633
- "\uB3C8\uC774 \uB098\uAC00\uB294 \uC791\uC5C5 \uC804\uC5D0 democut_estimate_video_cost \uB85C \uAE08\uC561\uC744 \uD655\uC778\uD558\uACE0 \uC774 \uC794\uC561\uACFC \uACAC\uC8FC\uC138\uC694. \uD06C\uB808\uB527\uC740 \uC6D0(KRW)\uC774\uACE0 \uACAC\uC801\uC740 USD \uB77C \uB2E8\uC704\uAC00 \uB2E4\uB985\uB2C8\uB2E4 \u2014 \uD655\uC2E4\uD558\uC9C0 \uC54A\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uB450 \uAC12\uC744 \uADF8\uB300\uB85C \uBCF4\uC5EC \uC8FC\uC138\uC694."
18718
+ "\uB3C8\uC774 \uB098\uAC00\uB294 \uC791\uC5C5 \uC804\uC5D0 \uACAC\uC801 \uB3C4\uAD6C(S1 \uC5D0\uC11C \uC81C\uACF5)\uB85C \uAE08\uC561\uC744 \uD655\uC778\uD558\uACE0 \uC774 \uC794\uC561\uACFC \uACAC\uC8FC\uC138\uC694. \uD06C\uB808\uB527\uC740 \uC6D0(KRW)\uC774\uACE0 \uACAC\uC801\uC740 USD \uB77C \uB2E8\uC704\uAC00 \uB2E4\uB985\uB2C8\uB2E4 \u2014 \uD655\uC2E4\uD558\uC9C0 \uC54A\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uB450 \uAC12\uC744 \uADF8\uB300\uB85C \uBCF4\uC5EC \uC8FC\uC138\uC694."
16634
18719
  );
16635
18720
  }
16636
18721
  return { text: lines.join("\n") };
16637
18722
  });
16638
18723
  }
18724
+ function nextPage(out2) {
18725
+ if (out2.next_cursor != null) return out2.next_cursor;
18726
+ return out2.next_before_id != null ? String(out2.next_before_id) : null;
18727
+ }
16639
18728
  function creditLedger(a = {}, deps = {}) {
16640
- return guarded2(READ_ONLY, async () => {
18729
+ return guarded(READ_ONLY, async () => {
16641
18730
  if (a.limit !== void 0 && !Number.isFinite(a.limit)) {
16642
18731
  return { isError: true, text: `limit \uC740 \uC22B\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(a.limit)}` };
16643
18732
  }
16644
- if (a.before_id !== void 0 && !Number.isFinite(a.before_id)) {
18733
+ const pageKey = a.cursor !== void 0 ? "cursor" : "before_id";
18734
+ const rawPage = a.cursor !== void 0 ? a.cursor : a.before_id;
18735
+ const pageNum = rawPage === void 0 ? void 0 : Number(rawPage);
18736
+ if (pageNum !== void 0 && (!Number.isFinite(pageNum) || typeof rawPage === "boolean")) {
16645
18737
  return {
16646
18738
  isError: true,
16647
- text: `before_id \uB294 \uC22B\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(a.before_id)}`
18739
+ text: `${pageKey} \uB294 \uC774\uC804 \uC751\uB2F5\uC774 \uC900 \uAC12\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(rawPage)}`
16648
18740
  };
16649
18741
  }
16650
18742
  const limit = Math.max(
16651
18743
  1,
16652
18744
  Math.min(Math.trunc(a.limit ?? LEDGER_DEFAULT_LIMIT), LEDGER_MAX_LIMIT)
16653
18745
  );
16654
- if (a.before_id !== void 0 && a.before_id < 1) {
16655
- return { isError: true, text: "before_id \uB294 1 \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4." };
18746
+ if (pageNum !== void 0 && (!Number.isInteger(pageNum) || pageNum < 1)) {
18747
+ return { isError: true, text: `${pageKey} \uB294 1 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4.` };
16656
18748
  }
16657
18749
  const base = resolveBaseUrl(deps.baseUrl);
16658
18750
  const ws = await resolveWorkspace(base, deps);
16659
18751
  if (!ws) return NO_WORKSPACE;
16660
- const out3 = await ledger(
18752
+ const out2 = await ledger(
16661
18753
  base,
16662
18754
  ws,
16663
- { limit, ...a.before_id !== void 0 ? { beforeId: Math.trunc(a.before_id) } : {} },
18755
+ { limit, ...pageNum !== void 0 ? { cursor: String(pageNum) } : {} },
16664
18756
  deps
16665
18757
  );
16666
- if (out3.entries.length === 0) {
18758
+ if (out2.entries.length === 0) {
16667
18759
  return {
16668
- text: !out3.enabled && out3.next_before_id == null ? "\uC774 \uBC30\uD3EC\uC5D0\uB294 \uD06C\uB808\uB527 \uAE30\uB2A5\uC774 \uC5C6\uC5B4 \uC0AC\uC6A9 \uB0B4\uC5ED\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(0\uAC74\uC774 \uC544\uB2C8\uB77C \uAC1C\uB150 \uBD80\uC7AC)." : "\uC0AC\uC6A9 \uB0B4\uC5ED\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
18760
+ text: !out2.enabled && nextPage(out2) == null ? "\uC774 \uBC30\uD3EC\uC5D0\uB294 \uD06C\uB808\uB527 \uAE30\uB2A5\uC774 \uC5C6\uC5B4 \uC0AC\uC6A9 \uB0B4\uC5ED\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(0\uAC74\uC774 \uC544\uB2C8\uB77C \uAC1C\uB150 \uBD80\uC7AC)." : "\uC0AC\uC6A9 \uB0B4\uC5ED\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."
16669
18761
  };
16670
18762
  }
16671
18763
  const lines = ["\uD06C\uB808\uB527 \uC0AC\uC6A9 \uB0B4\uC5ED (\uCD5C\uC2E0\uC21C)", ""];
16672
- for (const e of out3.entries) {
18764
+ for (const e of out2.entries) {
16673
18765
  const when = (e.created_at ?? "").slice(0, 16).replace("T", " ");
16674
18766
  const parts = [e.display_name];
16675
18767
  if (e.units_label) parts.push(e.units_label);
@@ -16680,8 +18772,9 @@ function creditLedger(a = {}, deps = {}) {
16680
18772
  `${when} \xB7 ${parts.join(" \xB7 ")} \xB7 ${sign}${e.amount_krw.toLocaleString("ko-KR")}\uC6D0 (\uC794\uC561 ${e.balance_after_krw.toLocaleString("ko-KR")}\uC6D0)`
16681
18773
  );
16682
18774
  }
16683
- if (out3.next_before_id != null) {
16684
- lines.push("", `\uB354 \uC788\uC2B5\uB2C8\uB2E4 \u2014 before_id=${out3.next_before_id} \uB85C \uB2E4\uC2DC \uD638\uCD9C\uD558\uC138\uC694.`);
18775
+ const next = nextPage(out2);
18776
+ if (next != null) {
18777
+ lines.push("", `\uB354 \uC788\uC2B5\uB2C8\uB2E4 \u2014 ${pageKey}=${next} \uB85C \uB2E4\uC2DC \uD638\uCD9C\uD558\uC138\uC694.`);
16685
18778
  }
16686
18779
  return { text: lines.join("\n") };
16687
18780
  });
@@ -16695,7 +18788,7 @@ function projectLine(p) {
16695
18788
  return parts.join(" \xB7 ");
16696
18789
  }
16697
18790
  function listProjects(a = {}, deps = {}) {
16698
- return guarded2(READ_ONLY, async () => {
18791
+ return guarded(READ_ONLY, async () => {
16699
18792
  if (a.limit !== void 0 && !Number.isFinite(a.limit)) {
16700
18793
  return { isError: true, text: `limit \uC740 \uC22B\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(a.limit)}` };
16701
18794
  }
@@ -16705,8 +18798,8 @@ function listProjects(a = {}, deps = {}) {
16705
18798
  );
16706
18799
  const query = (a.query ?? "").trim().toLowerCase();
16707
18800
  const base = resolveBaseUrl(deps.baseUrl);
16708
- const out3 = await list(base, deps);
16709
- const all = out3.projects ?? [];
18801
+ const out2 = await list(base, deps);
18802
+ const all = out2.projects ?? [];
16710
18803
  const total = all.length;
16711
18804
  const matched = query ? all.filter(
16712
18805
  (p) => (p.slug ?? "").toLowerCase().includes(query) || (p.title ?? "").toLowerCase().includes(query)
@@ -16727,13 +18820,26 @@ function listProjects(a = {}, deps = {}) {
16727
18820
  );
16728
18821
  }
16729
18822
  lines.push(
16730
- "democut_generate_video \uC758 project_slug \uC5D0\uB294 \uC704 **slug**(\uB9E8 \uC55E \uAC12)\uB97C \uADF8\uB300\uB85C \uB123\uC73C\uC138\uC694. \uC5B4\uB290 \uAC83\uC5D0 \uADC0\uC18D\uC2DC\uD0AC\uC9C0 \uBD84\uBA85\uD558\uC9C0 \uC54A\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB3C\uC73C\uC138\uC694."
18823
+ "\uD504\uB85C\uC81D\uD2B8\uB97C \uC694\uAD6C\uD558\uB294 \uB3C4\uAD6C\uC758 project_slug \uC5D0\uB294 \uC704 **slug**(\uB9E8 \uC55E \uAC12)\uB97C \uADF8\uB300\uB85C \uB123\uC73C\uC138\uC694. \uC5B4\uB290 \uAC83\uC5D0 \uADC0\uC18D\uC2DC\uD0AC\uC9C0 \uBD84\uBA85\uD558\uC9C0 \uC54A\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB3C\uC73C\uC138\uC694."
16731
18824
  );
16732
18825
  return { text: lines.join("\n") };
16733
18826
  });
16734
18827
  }
18828
+ var PROJECT_FIELD_DEFAULTS = {
18829
+ ratio: "16:9",
18830
+ resolution: "1080p",
18831
+ folder_id: null,
18832
+ defaults: null
18833
+ };
18834
+ function unsupportedProjectFields(a) {
18835
+ const given = a;
18836
+ return Object.keys(PROJECT_FIELD_DEFAULTS).filter((key) => {
18837
+ const v = given[key];
18838
+ return v !== void 0 && v !== null && v !== PROJECT_FIELD_DEFAULTS[key];
18839
+ });
18840
+ }
16735
18841
  function createProject(a = {}, deps = {}) {
16736
- return guarded2(READ_ONLY, async () => {
18842
+ return guarded(READ_ONLY, async () => {
16737
18843
  const title = (a.title ?? "").trim();
16738
18844
  if (!title) {
16739
18845
  return {
@@ -16741,6 +18847,13 @@ function createProject(a = {}, deps = {}) {
16741
18847
  text: "title \uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uC54C\uC544\uBCFC \uC218 \uC788\uB294 \uD504\uB85C\uC81D\uD2B8 \uC774\uB984\uC744 \uB123\uC5B4 \uB2E4\uC2DC \uD638\uCD9C\uD558\uC138\uC694."
16742
18848
  };
16743
18849
  }
18850
+ const unsupported = unsupportedProjectFields(a);
18851
+ if (unsupported.length > 0) {
18852
+ return {
18853
+ isError: true,
18854
+ text: `${unsupported.join(", ")} \uC740 \uC544\uC9C1 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uAE30\uBCF8\uAC12\uB9CC \uAC00\uB2A5). \uADF8 \uC778\uC790\uB97C \uBE7C\uACE0 \uB2E4\uC2DC \uD638\uCD9C\uD558\uBA74 ${PROJECT_FIELD_DEFAULTS.ratio}\xB7${PROJECT_FIELD_DEFAULTS.resolution} \uB85C \uB9CC\uB4E4\uC5B4\uC9D1\uB2C8\uB2E4.`
18855
+ };
18856
+ }
16744
18857
  const base = resolveBaseUrl(deps.baseUrl);
16745
18858
  const voiceId = await defaultVoiceId(base, deps);
16746
18859
  const p = await create(
@@ -16753,156 +18866,407 @@ function createProject(a = {}, deps = {}) {
16753
18866
  `\uD504\uB85C\uC81D\uD2B8 \uC900\uBE44\uB428 \u2014 slug: ${p.slug}`,
16754
18867
  `\uC81C\uBAA9: ${p.title}`,
16755
18868
  "",
16756
- "democut_generate_video \uC758 project_slug \uC5D0 \uC704 slug \uB97C \uADF8\uB300\uB85C \uB123\uC73C\uC138\uC694.",
18869
+ "\uD504\uB85C\uC81D\uD2B8\uB97C \uC694\uAD6C\uD558\uB294 \uB3C4\uAD6C\uC758 project_slug \uC5D0 \uC704 slug \uB97C \uADF8\uB300\uB85C \uB123\uC73C\uC138\uC694.",
16757
18870
  "\uAC19\uC740 \uC81C\uBAA9\uC73C\uB85C \uC774 \uB3C4\uAD6C\uB97C \uB2E4\uC2DC \uBD88\uB7EC\uB3C4 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uC54A\uACE0 \uC774 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB098\uC635\uB2C8\uB2E4."
16758
18871
  ].join("\n")
16759
18872
  };
16760
18873
  });
16761
18874
  }
16762
-
16763
- // src/mcp/server.ts
16764
- var RESOLUTIONS = ["480p", "720p", "1080p", "4k"];
16765
- var RATIOS = ["16:9", "9:16", "1:1", "4:3", "21:9", "adaptive"];
16766
- var GENERATION_PARAMS = {
16767
- duration_s: {
16768
- type: "number",
16769
- description: "\uC601\uC0C1 \uAE38\uC774(\uCD08). \uAE30\uBCF8 5. \uBAA8\uB378\uBCC4 \uD5C8\uC6A9 \uBC94\uC704\uAC00 \uB2E4\uB974\uB2E4(2.0 \uACC4\uC5F4 4~15, 2.5 \uACC4\uC5F4 4~30)."
16770
- },
16771
- resolution: { type: "string", enum: RESOLUTIONS, description: "\uAE30\uBCF8 720p." },
16772
- ratio: { type: "string", enum: RATIOS, description: "\uAE30\uBCF8 16:9." },
16773
- model: {
16774
- type: "string",
16775
- description: "\uC0DD\uB7B5\uD558\uBA74 image_urls \uC720\uBB34\uB85C \uC790\uB3D9 \uC120\uD0DD\uB41C\uB2E4(\uC788\uC73C\uBA74 image-to-video, \uC5C6\uC73C\uBA74 text-to-video). \uBA85\uC2DC\uD558\uBA74 \uADF8 \uBAA8\uB378\uC744 \uC4F0\uB418 \uACC4\uC5F4\uC774 \uC5B4\uAE0B\uB098\uBA74 \uAC70\uBD80\uB41C\uB2E4."
18875
+ var projectPath = (slug, tail) => `/api/projects/${encodeURIComponent(slug)}${tail}`;
18876
+ function needSlug(a) {
18877
+ const slug = (a.slug ?? "").trim();
18878
+ if (!slug) {
18879
+ return { isError: true, text: "slug \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 democut_list_projects \uB85C \uD655\uC778\uD558\uC138\uC694." };
16776
18880
  }
16777
- };
16778
- var TOOLS = [
16779
- {
16780
- name: "democut_auth_status",
16781
- description: "DemoCut \uB85C\uADF8\uC778 \uC0C1\uD0DC\uC640 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\xB7\uC5ED\uD560\xB7\uD2F0\uC5B4\uB97C \uD655\uC778\uD55C\uB2E4. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. \uB2E4\uB978 \uB3C4\uAD6C\uAC00 '\uAD8C\uD55C \uC5C6\uC74C' \uC73C\uB85C \uC2E4\uD328\uD558\uBA74 \uC774\uAC78\uB85C \uC0C1\uD0DC\uB97C \uBA3C\uC800 \uD655\uC778\uD558\uB77C.",
16782
- inputSchema: { type: "object", properties: {}, additionalProperties: false }
16783
- },
16784
- {
16785
- name: "democut_estimate_video_cost",
16786
- description: "\uC601\uC0C1 \uC0DD\uC131 \uC608\uC0C1 \uBE44\uC6A9\uC744 \uACC4\uC0B0\uD55C\uB2E4. **\uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4.** \uBE44\uC6A9\uC740 \uD574\uC0C1\uB3C4\xB7\uAE38\uC774\xB7\uBE44\uC728\uC5D0 \uB354\uD574 **\uBAA8\uB378 \uACC4\uC5F4**\uB85C \uACB0\uC815\uB41C\uB2E4 \u2014 \uCC38\uC870 \uC774\uBBF8\uC9C0\uB97C \uB123\uC744 \uAC70\uBA74 has_image=true \uB85C \uACC4\uC0B0\uD574\uC57C \uC2E4\uC81C \uCCAD\uAD6C\uC640 \uB9DE\uB294\uB2E4(\uACC4\uC5F4\uB9C8\uB2E4 \uD1A0\uD070 \uB2E8\uAC00\uAC00 \uB2E4\uB974\uB2E4). democut_generate_video \uB97C \uBD80\uB974\uAE30 \uC804\uC5D0 \uBA3C\uC800 \uD638\uCD9C\uD574 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uAE08\uC561\uC744 \uC54C\uB9AC\uACE0 \uB3D9\uC758\uB97C \uBC1B\uC544\uB77C.",
16787
- inputSchema: {
16788
- type: "object",
16789
- properties: {
16790
- ...GENERATION_PARAMS,
16791
- has_image: {
16792
- type: "boolean",
16793
- description: "\uC0DD\uC131 \uC2DC \uCC38\uC870 \uC774\uBBF8\uC9C0\uB97C \uB123\uC744 \uC608\uC815\uC778\uAC00(\uAE30\uBCF8 false). \u2605 \uAE08\uC561\uC774 \uB2EC\uB77C\uC9C4\uB2E4 \u2014 \uC774\uBBF8\uC9C0 \uC720\uBB34\uAC00 \uBAA8\uB378 \uACC4\uC5F4\uC744 \uC815\uD558\uACE0 \uACC4\uC5F4\uB9C8\uB2E4 \uD1A0\uD070 \uB2E8\uAC00\uAC00 \uB2E4\uB974\uB2E4. \uC0DD\uC131 \uB54C image_urls \uB97C \uB123\uC744 \uAC70\uBA74 \uC5EC\uAE30\uC11C\uB3C4 true \uB85C \uB450\uC5B4\uC57C \uCD94\uC815 \uAE08\uC561\uACFC \uC2E4\uC81C \uCCAD\uAD6C\uAC00 \uC77C\uCE58\uD55C\uB2E4."
16794
- }
16795
- },
16796
- additionalProperties: false
18881
+ return slug;
18882
+ }
18883
+ function getOptions(a = {}, deps = {}) {
18884
+ return guarded(READ_ONLY, async () => {
18885
+ const slug = needSlug(a);
18886
+ if (typeof slug !== "string") return slug;
18887
+ const base = resolveBaseUrl(deps.baseUrl);
18888
+ const out2 = await apiRequest(base, projectPath(slug, "/options"), {}, deps);
18889
+ const modes = (out2.modes ?? []).map((m) => String(m.mode ?? "?")).join(", ") || "-";
18890
+ return {
18891
+ text: [
18892
+ `\uD504\uB85C\uC81D\uD2B8 ${out2.project.slug} \u2014 ${out2.project.ratio} ${out2.project.resolution}`,
18893
+ `\uAD8C\uC7A5 \uBC29\uC2DD: ${out2.recommended_mode} \xB7 \uAC00\uB2A5\uD55C \uBC29\uC2DD: ${modes}`,
18894
+ `\uBCF4\uC774\uC2A4 ${(out2.voices ?? []).length}\uAC1C \xB7 \uC544\uBC14\uD0C0 ${(out2.characters ?? []).length}\uAC1C \xB7 \uBC30\uACBD ${(out2.backgrounds ?? []).length}\uAC1C`,
18895
+ `\uC794\uC561 ${krw(out2.balance_krw)} \xB7 \uC694\uC728 v${out2.rate_version}`,
18896
+ "\uB2E8\uAC00\uB294 \uCC38\uACE0\uAC12\uC785\uB2C8\uB2E4 \u2014 \uCCAD\uAD6C\uB294 democut_estimate_cuts \uAC00 \uC900 total_krw\xB7rate_version \uC73C\uB85C \uD569\uB2C8\uB2E4."
18897
+ ].join("\n")
18898
+ };
18899
+ });
18900
+ }
18901
+ function uploadAsset(a = {}, deps = {}) {
18902
+ return guarded(READ_ONLY, async () => {
18903
+ const base = resolveBaseUrl(deps.baseUrl);
18904
+ if (!a.kind) return { isError: true, text: "kind \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 (image\xB7audio\xB7video\xB7subtitle\xB7code \uB4F1)." };
18905
+ if (a.local_path && a.source_url) {
18906
+ return { isError: true, text: "local_path \uC640 source_url \uC911 \uD558\uB098\uB9CC \uC8FC\uC138\uC694." };
16797
18907
  }
16798
- },
16799
- {
16800
- name: "democut_generate_video",
16801
- description: "\uC601\uC0C1 \uC0DD\uC131\uC744 \uC81C\uCD9C\uD55C\uB2E4. **\uC2E4\uC81C\uB85C \uB3C8\uC774 \uB098\uAC04\uB2E4.** \uBA3C\uC800 democut_estimate_video_cost \uB85C \uAE08\uC561\uC744 \uD655\uC778\uD558\uACE0 \uC0AC\uC6A9\uC790 \uB3D9\uC758\uB97C \uBC1B\uC740 \uB4A4, \uADF8 \uAE08\uC561\uC744 confirmed_cost_usd \uC5D0 \uADF8\uB300\uB85C \uB123\uC5B4 \uD638\uCD9C\uD558\uB77C \u2014 \uC11C\uBC84\uAC00 \uB2E4\uC2DC \uACC4\uC0B0\uD574 \uB300\uC870\uD558\uACE0 \uC5B4\uAE0B\uB098\uBA74 \uAC70\uBD80\uD55C\uB2E4. \uC2E4\uD328\uD574\uB3C4 **\uB2E4\uC2DC \uC81C\uCD9C\uD558\uC9C0 \uB9C8\uB77C**: \uC7AC\uC81C\uCD9C\uC740 \uBCC4\uAC1C \uC0DD\uC131\uC774\uB77C \uB2E4\uC2DC \uACFC\uAE08\uB41C\uB2E4. \uC911\uBCF5 \uC81C\uCD9C \uBC29\uC5B4\uB294 \uC11C\uBC84 \uD504\uB85C\uC138\uC2A4 \uC548\uC5D0\uC11C\uB9CC \uB3D9\uC791\uD558\uBBC0\uB85C, \uAC19\uC740 \uC694\uCCAD\uC744 \uB3D9\uC2DC\uC5D0 \uB450 \uBC88 \uBCF4\uB0B4\uBA74 \uB450 \uAC74\uC774 \uC81C\uCD9C\uB420 \uC218 \uC788\uB2E4 \u2014 \uD55C \uBC88\uB9CC \uBCF4\uB0B4\uACE0 \uACB0\uACFC\uB97C \uC870\uD68C\uD558\uB77C.",
16802
- inputSchema: {
16803
- type: "object",
16804
- properties: {
16805
- prompt: { type: "string", description: "\uC0DD\uC131\uD560 \uC601\uC0C1 \uC124\uBA85." },
16806
- confirmed_cost_usd: {
16807
- type: "number",
16808
- description: "democut_estimate_video_cost \uAC00 \uB3CC\uB824\uC900 cost_usd \uC6D0\uAC12. \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC774 \uAE08\uC561\uC744 \uC54C\uB9AC\uACE0 \uB3D9\uC758\uB97C \uBC1B\uC740 \uB4A4\uC5D0 \uB123\uC5B4\uB77C."
16809
- },
16810
- ...GENERATION_PARAMS,
16811
- seed: { type: "number", description: "\uACB0\uC815\uB860\uC801 \uC0DD\uC131\uC6A9 seed." },
16812
- image_urls: {
16813
- type: "array",
16814
- items: { type: "string" },
16815
- description: "\uCC38\uC870 \uC774\uBBF8\uC9C0. **\uACF5\uAC1C HTTPS URL** \uB9CC \uAC00\uB2A5(\uC2DC\uC791 \uD504\uB808\uC784 1\uC7A5 + \uB05D \uD504\uB808\uC784 1\uC7A5, \uCD5C\uB300 2\uAC1C). \u2605 \uC774 \uAC12\uC774 **\uBAA8\uB378\uACFC \uB2E8\uAC00\uB97C \uC815\uD55C\uB2E4** \u2014 \uC8FC\uBA74 image-to-video, \uBE44\uC6B0\uBA74 text-to-video \uB85C \uC790\uB3D9 \uC120\uD0DD\uB418\uACE0 \uD1A0\uD070 \uB2E8\uAC00\uAC00 \uB2E4\uB974\uB2E4. \uC778\uBB3C\xB7\uC81C\uD488 \uB4F1 \uD2B9\uC815 \uB300\uC0C1\uC744 \uC720\uC9C0\uD574\uC57C \uD558\uBA74 \uBC18\uB4DC\uC2DC \uB123\uC5B4\uB77C."
16816
- },
16817
- generate_audio: { type: "boolean", description: "\uC624\uB514\uC624 \uD568\uAED8 \uC0DD\uC131. \uAE30\uBCF8 false." },
16818
- watermark: { type: "boolean", description: "\uC6CC\uD130\uB9C8\uD06C. \uAE30\uBCF8 false." },
16819
- project_slug: {
16820
- type: "string",
16821
- description: "\uBE44\uC6A9\uC774 \uADC0\uC18D\uB420 \uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8 \u2014 **\uD544\uC218**. \uBCF8\uC778 \uC18C\uC720\uAC00 \uC544\uB2C8\uBA74 404. \uC601\uC0C1 \uC0DD\uC131\uC740 \uACFC\uAE08 \uB300\uC0C1\uC774\uB77C \uADC0\uC18D \uC5C6\uB294 \uC9C0\uCD9C\uC740 \uB300\uC870\xB7\uC815\uC0B0\uC774 \uBD88\uAC00\uB2A5\uD558\uB2E4. \uC2AC\uB7EC\uADF8\uB97C \uBAA8\uB974\uBA74 democut_list_projects \uB85C \uBA3C\uC800 \uD655\uC778\uD558\uB77C \u2014 \uCD94\uCE21\uD558\uC9C0 \uB9C8\uB77C."
16822
- }
16823
- },
16824
- required: ["prompt", "confirmed_cost_usd", "project_slug"],
16825
- additionalProperties: false
18908
+ if (a.local_path) {
18909
+ const path = a.local_path;
18910
+ if (!existsSync2(path)) {
18911
+ return { isError: true, text: `\uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4: ${path}` };
18912
+ }
18913
+ const view2 = await uploadFile(base, path, { kind: a.kind, projectSlug: a.project_slug, filename: a.filename }, deps);
18914
+ return {
18915
+ text: [
18916
+ `\uC790\uC0B0 ${view2.id} (${view2.kind}) \uB97C \uC62C\uB838\uC2B5\uB2C8\uB2E4 \u2014 state=${view2.state}`,
18917
+ `${view2.mime} \xB7 ${view2.bytes.toLocaleString("ko-KR")} \uBC14\uC774\uD2B8`,
18918
+ "\uC774 id \uB97C spec \uC758 BYO \uD544\uB4DC(image_asset_id\xB7narration_asset_id\xB7source.asset_id \uB4F1)\uC5D0 \uC4F0\uC138\uC694."
18919
+ ].join("\n")
18920
+ };
16826
18921
  }
16827
- },
16828
- {
16829
- name: "democut_get_video_status",
16830
- description: "\uC0DD\uC131 \uC791\uC5C5 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0, \uC644\uB8CC\uB410\uC73C\uBA74 \uC0B0\uCD9C\uBB3C\uC744 \uB0B4\uB824\uBC1B\uB294\uB2E4. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. \uC11C\uBC84\uB294 \uC0B0\uCD9C\uBB3C\uC744 \uBCF4\uAD00\uD558\uC9C0 \uC54A\uC73C\uBBC0\uB85C \uC644\uB8CC \uC989\uC2DC output_path \uB85C \uC800\uC7A5\uD558\uB77C.",
16831
- inputSchema: {
16832
- type: "object",
16833
- properties: {
16834
- job_id: { type: "string", description: "democut_generate_video \uAC00 \uB3CC\uB824\uC900 job_id." },
16835
- output_path: { type: "string", description: "\uC800\uC7A5\uD560 \uB85C\uCEEC \uACBD\uB85C(\uC808\uB300\uACBD\uB85C \uAD8C\uC7A5)." },
16836
- project_slug: {
16837
- type: "string",
16838
- description: "(\uBB34\uC2DC\uB428) \uADC0\uC18D\uC740 \uC81C\uCD9C \uC2DC\uC810 \uAC12\uC73C\uB85C \uC11C\uBC84\uAC00 \uACB0\uC815\uD55C\uB2E4."
16839
- }
16840
- },
16841
- required: ["job_id"],
16842
- additionalProperties: false
18922
+ if (!a.source_url) {
18923
+ return { isError: true, text: "local_path \uB610\uB294 source_url \uC774 \uD544\uC694\uD569\uB2C8\uB2E4." };
16843
18924
  }
16844
- },
16845
- {
16846
- name: "democut_credit_balance",
16847
- description: "DemoCut \uD06C\uB808\uB527 \uC794\uC561\uC744 \uD655\uC778\uD55C\uB2E4. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. \uB3C8\uC774 \uB098\uAC00\uB294 \uC791\uC5C5(democut_generate_video)\uC744 \uC81C\uCD9C\uD558\uAE30 **\uC804\uC5D0** \uD638\uCD9C\uD574 \uC794\uC561\uC774 \uCDA9\uBD84\uD55C\uC9C0 \uBCF4\uB77C \u2014 \uBD80\uC871\uD558\uBA74 \uC81C\uCD9C\uC774 402 \uB85C \uAC70\uBD80\uB418\uACE0, \uADF8\uAC83\uC744 \uBBF8\uB9AC \uC544\uB294 \uD3B8\uC774 \uB0AB\uB2E4. \uC794\uC561\uC774 \uBAA8\uC790\uB77C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC54C\uB9AC\uACE0 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uAD00\uB9AC\uC790\uC5D0\uAC8C \uCDA9\uC804\uC744 \uC694\uCCAD\uD558\uB3C4\uB85D \uC548\uB0B4\uD558\uB77C. \uB124\uAC00 \uC9C1\uC811 \uCDA9\uC804\uD560 \uC218\uB294 \uC5C6\uB2E4.",
16848
- inputSchema: { type: "object", properties: {}, additionalProperties: false }
16849
- },
16850
- {
16851
- name: "democut_credit_ledger",
16852
- description: '\uD06C\uB808\uB527 \uC0AC\uC6A9 \uB0B4\uC5ED\uC744 \uCD5C\uC2E0\uC21C\uC73C\uB85C \uD655\uC778\uD55C\uB2E4. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. "\uC65C \uC794\uC561\uC774 \uC774\uB9CC\uD07C \uC904\uC5C8\uB098" \uB97C \uB2F5\uD560 \uB54C \uC4F4\uB2E4 \u2014 \uAC01 \uD589\uC740 \uBB34\uC5C7\uC5D0\xB7\uC5B8\uC81C\xB7\uC5BC\uB9C8\uC640, \uAC00\uB2A5\uD558\uBA74 \uC0AC\uC6A9\uB7C9(\uC608: 40,594 tokens)\uAE4C\uC9C0 \uB9D0\uD55C\uB2E4.',
16853
- inputSchema: {
16854
- type: "object",
16855
- properties: {
16856
- limit: { type: "number", description: "\uAC00\uC838\uC62C \uAC74\uC218 1~200. \uAE30\uBCF8 10." },
16857
- before_id: {
16858
- type: "number",
16859
- description: "\uC774\uC804 \uD638\uCD9C\uC774 \uB3CC\uB824\uC900 next_before_id. \uB2E4\uC74C \uD398\uC774\uC9C0\uB97C \uBCFC \uB54C\uB9CC \uB123\uC5B4\uB77C."
16860
- }
16861
- },
16862
- additionalProperties: false
18925
+ const view = await apiRequest(
18926
+ base,
18927
+ "/api/assets/fetch",
18928
+ { method: "POST", body: { kind: a.kind, project_slug: a.project_slug, filename: a.filename, source_url: a.source_url } },
18929
+ deps
18930
+ );
18931
+ return {
18932
+ text: [
18933
+ `\uC790\uC0B0 ${view.id} (${view.kind}) \uB97C \uAC00\uC838\uC624\uB294 \uC911\uC785\uB2C8\uB2E4 \u2014 state=${view.state}`,
18934
+ "democut_get_cut \uC774 \uC544\uB2C8\uB77C \uC790\uC0B0 \uC870\uD68C\uB85C state \uAC00 ready \uAC00 \uB420 \uB54C\uAE4C\uC9C0 \uAE30\uB2E4\uB9B0 \uB4A4 \uC4F0\uC138\uC694.",
18935
+ "\uC2E4\uD328\uD558\uBA74 state=deleted \uAC00 \uB418\uACE0 \uC0AC\uC720\uB294 meta.error \uC5D0 \uB0A8\uC2B5\uB2C8\uB2E4."
18936
+ ].join("\n")
18937
+ };
18938
+ });
18939
+ }
18940
+ function estimateCuts(a = {}, deps = {}) {
18941
+ return guarded(READ_ONLY, async () => {
18942
+ const slug = needSlug(a);
18943
+ if (typeof slug !== "string") return slug;
18944
+ const base = resolveBaseUrl(deps.baseUrl);
18945
+ const out2 = await apiRequest(
18946
+ base,
18947
+ projectPath(slug, "/cuts/estimate"),
18948
+ { method: "POST", body: { items: a.items ?? [], imports: a.imports ?? [] } },
18949
+ deps
18950
+ );
18951
+ const lines = [`\uACAC\uC801 (\uC694\uC728 v${out2.rate_version}) \u2014 \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4`];
18952
+ for (const item of out2.items ?? []) {
18953
+ const label = item.cut_id ?? "(\uC0C8 \uCEF7)";
18954
+ if (item.blocked_reason) {
18955
+ lines.push(` ${label}: \uACAC\uC801 \uBD88\uAC00 \u2014 ${item.blocked_reason}`);
18956
+ continue;
18957
+ }
18958
+ const rows = (item.rows ?? []).map((r) => `${r.key} ${krw(r.krw)}`).join(", ") || "\uD589 \uC5C6\uC74C";
18959
+ lines.push(` ${label}: ${krw(item.total_krw ?? 0)} (${rows})`);
16863
18960
  }
16864
- },
16865
- {
16866
- name: "democut_list_projects",
16867
- description: "\uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC758 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D\uC744 \uCD5C\uADFC \uC218\uC815\uC21C\uC73C\uB85C \uD655\uC778\uD55C\uB2E4. \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uB2E4. democut_generate_video \uC758 project_slug \uB294 **\uC2E4\uC7AC\uD558\uB294 \uBCF8\uC778 \uD504\uB85C\uC81D\uD2B8\uC5EC\uC57C** \uD558\uACE0 \uD2C0\uB9AC\uBA74 404 \uB2E4 \u2014 \uC2AC\uB7EC\uADF8\uB97C \uBAA8\uB974\uBA74 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 \uC774\uAC78\uB85C \uBA3C\uC800 \uD655\uC778\uD558\uB77C. \uBAA9\uB85D\uC774 \uBE44\uC5B4 \uC788\uAC70\uB098 \uB9C8\uB545\uD55C \uAC83\uC774 \uC5C6\uC73C\uBA74 democut_create_project \uB85C \uB9CC\uB4E4 \uC218 \uC788\uB2E4 \u2014 \uB2E8 \uBA3C\uC800 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC5B4\uB290 \uAC83\uC5D0 \uB123\uC744\uC9C0, \uC0C8\uB85C \uB9CC\uB4E0\uB2E4\uBA74 \uC5B4\uB5A4 \uC774\uB984\uC73C\uB85C \uD560\uC9C0 \uBB3C\uC5B4\uB77C.",
16868
- inputSchema: {
16869
- type: "object",
16870
- properties: {
16871
- limit: { type: "number", description: "\uAC00\uC838\uC62C \uAC74\uC218 1~100. \uAE30\uBCF8 30." },
16872
- query: {
16873
- type: "string",
16874
- description: "\uC2AC\uB7EC\uADF8\xB7\uC81C\uBAA9\uC5D0 \uC774 \uBB38\uC790\uC5F4\uC774 \uB4E0 \uAC83\uB9CC (\uB300\uC18C\uBB38\uC790 \uBB34\uC2DC). \uCC3E\uB294 \uD504\uB85C\uC81D\uD2B8 \uC774\uB984\uC744 \uC54C \uB54C\uB9CC \uC4F0\uB77C \u2014 \uBE44\uC6B0\uBA74 \uCD5C\uADFC \uC218\uC815\uC21C \uC804\uCCB4\uB2E4."
18961
+ lines.push(
18962
+ `\uCD1D\uC561 ${krw(out2.total_krw)} \xB7 \uC794\uC561 ${krw(out2.balance_krw)} \u2192 \uB0A8\uC744 \uC794\uC561 ${krw(out2.balance_after_krw)}`,
18963
+ out2.can_afford ? "\uCDA9\uBD84\uD569\uB2C8\uB2E4." : "\u26A0\uFE0F \uC794\uC561\uC774 \uBD80\uC871\uD569\uB2C8\uB2E4 \u2014 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uAD00\uB9AC\uC790\uC5D0\uAC8C \uCDA9\uC804\uC744 \uC694\uCCAD\uD558\uC138\uC694.",
18964
+ "\uC774 total_krw\xB7rate_version \uC744 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBCF4\uC5EC \uC8FC\uACE0 **\uADF8\uB300\uB85C** democut_make_cuts \uC5D0 \uB123\uC73C\uC138\uC694."
18965
+ );
18966
+ if (out2.mock) lines.push("(mock \uB2E8\uAC00\uC785\uB2C8\uB2E4 \u2014 \uC2E4\uC81C \uCCAD\uAD6C\uC640 \uB2E4\uB97C \uC218 \uC788\uC2B5\uB2C8\uB2E4.)");
18967
+ return { text: lines.join("\n") };
18968
+ });
18969
+ }
18970
+ function makeCuts(a = {}, deps = {}) {
18971
+ return guarded(SUBMITTING, async () => {
18972
+ const slug = needSlug(a);
18973
+ if (typeof slug !== "string") return slug;
18974
+ const base = resolveBaseUrl(deps.baseUrl);
18975
+ const out2 = await apiRequest(
18976
+ base,
18977
+ projectPath(slug, "/cuts/make"),
18978
+ {
18979
+ method: "POST",
18980
+ body: {
18981
+ items: a.items ?? [],
18982
+ confirmed_total_krw: a.confirmed_total_krw,
18983
+ rate_version: a.rate_version
16875
18984
  }
16876
18985
  },
16877
- additionalProperties: false
18986
+ deps
18987
+ );
18988
+ const lines = [`\uCEF7 ${(out2.jobs ?? []).length}\uAC1C\uB97C \uC81C\uCD9C\uD588\uC2B5\uB2C8\uB2E4 (batch ${out2.batch_id}) \u2014 \uC794\uC561\uC5D0\uC11C \uCC28\uAC10\uB410\uC2B5\uB2C8\uB2E4`];
18989
+ for (const ref of out2.jobs ?? []) {
18990
+ const tail = ref.deduplicated ? " (\uC774\uBBF8 \uAC19\uC740 \uC791\uC5C5\uC774 \uB3CC\uACE0 \uC788\uC5B4 \uC7AC\uC0AC\uC6A9)" : "";
18991
+ lines.push(` ${ref.cut_id} \u2192 ${ref.job_id} ${krw(ref.quote.total_krw)}${tail}`);
16878
18992
  }
16879
- },
16880
- {
16881
- name: "democut_create_project",
16882
- description: "\uD504\uB85C\uC81D\uD2B8\uB97C \uC0C8\uB85C \uB9CC\uB4E0\uB2E4. **\uACFC\uAE08\uC740 \uC5C6\uC9C0\uB9CC \uACC4\uC815\uC5D0 \uB0A8\uB294 \uC4F0\uAE30 \uC791\uC5C5\uC774\uB2E4.** \uC601\uC0C1 \uC0DD\uC131\uC740 \uBE44\uC6A9\uC744 \uADC0\uC18D\uC2DC\uD0AC \uD504\uB85C\uC81D\uD2B8\uAC00 \uC788\uC5B4\uC57C \uD558\uBBC0\uB85C, democut_list_projects \uAC00 \uBE44\uC5B4 \uC788\uAC70\uB098 \uB9C8\uB545\uD55C \uAC83\uC774 \uC5C6\uC744 \uB54C \uC4F4\uB2E4. \u2605 \uBA3C\uC800 democut_list_projects \uB85C **\uC4F8 \uB9CC\uD55C \uAC83\uC774 \uC774\uBBF8 \uC788\uB294\uC9C0 \uBCF4\uACE0**, \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC5B4\uB290 \uAC83\uC5D0 \uB123\uC744\uC9C0 \uBB3C\uC5B4\uB77C \u2014 \uBB3C\uC5B4\uBCF4\uC9C0 \uC54A\uACE0 \uC0C8\uB85C \uB9CC\uB4E4\uBA74 \uBE44\uC2B7\uD55C \uD504\uB85C\uC81D\uD2B8\uAC00 \uC313\uC778\uB2E4. \uAC19\uC740 \uC81C\uBAA9\uC73C\uB85C \uB2E4\uC2DC \uBD80\uB974\uBA74 \uC0C8\uB85C \uB9CC\uB4E4\uC9C0 \uC54A\uACE0 **\uAE30\uC874 \uAC83\uC744 \uB3CC\uB824\uC900\uB2E4**(\uC7AC\uC2DC\uB3C4 \uC548\uC804).",
16883
- inputSchema: {
16884
- type: "object",
16885
- properties: {
16886
- title: {
16887
- type: "string",
16888
- description: "\uD504\uB85C\uC81D\uD2B8 \uC774\uB984 1~100\uC790. \uC0AC\uC6A9\uC790\uAC00 \uC54C\uC544\uBCFC \uC218 \uC788\uAC8C \uC9D3\uACE0, \uAC00\uB2A5\uD558\uBA74 \uC0AC\uC6A9\uC790\uAC00 \uBD80\uB978 \uC774\uB984\uC744 \uADF8\uB300\uB85C \uC4F0\uB77C."
18993
+ lines.push("\uB2E4\uC74C \uD638\uCD9C: democut_wait_jobs \uC5D0 \uC704 job_id \uB4E4\uC744 \uB123\uC73C\uC138\uC694.");
18994
+ return { text: lines.join("\n") };
18995
+ });
18996
+ }
18997
+ var WAIT_CHUNK_S = 30;
18998
+ var LIST_LINES = 20;
18999
+ function listing(lines) {
19000
+ if (lines.length <= LIST_LINES) return lines;
19001
+ return [...lines.slice(0, LIST_LINES), ` \u2026\uC678 ${lines.length - LIST_LINES}\uAC1C`];
19002
+ }
19003
+ var ACTIVE_JOB_STATES = /* @__PURE__ */ new Set(["queued", "running"]);
19004
+ function jobLine(j) {
19005
+ const bits = [`${j.job_id} [${j.state}] ${j.kind}`];
19006
+ if (j.progress?.pct != null) bits.push(`${Math.round(j.progress.pct)}%`);
19007
+ if (j.error) bits.push(`\uC624\uB958 ${j.error.code}: ${j.error.message}`);
19008
+ if (j.result?.version != null) bits.push(`\u2192 v${j.result.version}`);
19009
+ return bits.join(" \xB7 ");
19010
+ }
19011
+ function waitJobs(a = {}, deps = {}) {
19012
+ return guarded(READ_ONLY, async () => {
19013
+ const base = resolveBaseUrl(deps.baseUrl);
19014
+ const budget = Math.max(0, Math.min(Math.trunc(a.timeout_s ?? 600), 600));
19015
+ const deadline = Date.now() + budget * 1e3;
19016
+ let ids = [...a.job_ids ?? []];
19017
+ let narrowed = false;
19018
+ const settled = /* @__PURE__ */ new Map();
19019
+ let pending = [];
19020
+ const exploreState = ids.length ? void 0 : a.state;
19021
+ const ignoredState = ids.length && a.state ? a.state : void 0;
19022
+ for (; ; ) {
19023
+ const left = Math.max(0, Math.floor((deadline - Date.now()) / 1e3));
19024
+ const q = new URLSearchParams();
19025
+ if (ids.length) q.set("ids", ids.join(","));
19026
+ if (!narrowed && a.batch_id) q.set("batch_id", a.batch_id);
19027
+ if (!narrowed && a.project) q.set("project", a.project);
19028
+ if (!narrowed && exploreState) q.set("state", exploreState);
19029
+ q.set("wait", String(Math.min(WAIT_CHUNK_S, left)));
19030
+ const out2 = await apiRequest(base, `/api/jobs?${q}`, {}, deps);
19031
+ pending = (out2.jobs ?? []).filter((j) => ACTIVE_JOB_STATES.has(j.state));
19032
+ for (const j of out2.jobs ?? []) {
19033
+ if (!ACTIVE_JOB_STATES.has(j.state)) settled.set(j.job_id, j);
19034
+ }
19035
+ if (pending.length === 0 || left <= 0) break;
19036
+ ids = pending.map((j) => j.job_id);
19037
+ narrowed = true;
19038
+ }
19039
+ const jobs = [...settled.values(), ...pending];
19040
+ const allDone = pending.length === 0;
19041
+ const ordered = [...jobs].sort(
19042
+ (x, y) => Number(!ACTIVE_JOB_STATES.has(x.state)) - Number(!ACTIVE_JOB_STATES.has(y.state))
19043
+ );
19044
+ const lines = [`\uC7A1 ${jobs.length}\uAC1C \u2014 ${allDone ? "\uC804\uBD80 \uB05D\uB0AC\uC2B5\uB2C8\uB2E4" : "\uC544\uC9C1 \uC9C4\uD589 \uC911\uC785\uB2C8\uB2E4"}`];
19045
+ lines.push(...listing(ordered.map((j) => ` ${jobLine(j)}`)));
19046
+ if (ignoredState !== void 0) {
19047
+ lines.push(`(job_ids \uB97C \uC8FC\uC168\uC73C\uBBC0\uB85C state=${ignoredState} \uD544\uD130\uB294 \uC4F0\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 \uC694\uCCAD\uD55C id \uC804\uBD80\uB97C \uBD05\uB2C8\uB2E4.)`);
19048
+ }
19049
+ lines.push(
19050
+ allDone ? "\uB05D\uB09C \uC7A1\uC758 \uACB0\uACFC\uB294 democut_get_cut \uC758 versions \uB85C \uD655\uC778\uD558\uACE0 democut_download \uB85C \uB0B4\uB824\uBC1B\uC2B5\uB2C8\uB2E4." : "\uC544\uC9C1 \uC548 \uB05D\uB09C job_ids \uB85C democut_wait_jobs \uB97C \uB2E4\uC2DC \uBD80\uB974\uC138\uC694."
19051
+ );
19052
+ return { text: lines.join("\n") };
19053
+ });
19054
+ }
19055
+ function getCut(a = {}, deps = {}) {
19056
+ return guarded(READ_ONLY, async () => {
19057
+ const slug = needSlug(a);
19058
+ if (typeof slug !== "string") return slug;
19059
+ const cutId = (a.cut_id ?? "").trim();
19060
+ if (!cutId) return { isError: true, text: "cut_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
19061
+ const base = resolveBaseUrl(deps.baseUrl);
19062
+ const cut = await apiRequest(base, projectPath(slug, `/cuts/${encodeURIComponent(cutId)}`), {}, deps);
19063
+ const head = [`${cut.id} [${cut.state}] ${cut.mode}`];
19064
+ if (cut.title) head.push(`\u300C${cut.title}\u300D`);
19065
+ if (cut.current_version != null) head.push(`\uB300\uD45C v${cut.current_version}`);
19066
+ if (cut.dirty_fields?.length) head.push(`\uB2EC\uB77C\uC9C4 \uD544\uB4DC: ${cut.dirty_fields.join(", ")}`);
19067
+ if (cut.estimated_cost_krw != null) head.push(`\uC608\uC0C1 ${krw(cut.estimated_cost_krw)}`);
19068
+ if (cut.blocked_reason) head.push(`\uB9C9\uD798: ${cut.blocked_reason}`);
19069
+ const versions = [...cut.versions ?? []].sort((x, y) => y.version - x.version);
19070
+ const lines = [head.join(" \xB7 ")];
19071
+ lines.push(
19072
+ ...listing(
19073
+ versions.map((v) => {
19074
+ const roles = ["video", "audio", "subtitle", "still"].filter((r) => v.download?.[r]);
19075
+ return ` v${v.version} (${v.origin}) ${v.width}x${v.height} ${v.duration_ms}ms \xB7 \uB0B4\uB824\uBC1B\uAE30: ${roles.join(", ") || "\uC5C6\uC74C"}`;
19076
+ })
19077
+ )
19078
+ );
19079
+ if (cut.next_calls?.length) lines.push(`\uB2E4\uC74C \uD638\uCD9C: ${cut.next_calls.join(", ")}`);
19080
+ return { text: lines.join("\n") };
19081
+ });
19082
+ }
19083
+ function download(a = {}, deps = {}) {
19084
+ return guarded(READ_ONLY, async () => {
19085
+ const slug = needSlug(a);
19086
+ if (typeof slug !== "string") return slug;
19087
+ const cutId = (a.cut_id ?? "").trim();
19088
+ if (!cutId) return { isError: true, text: "cut_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
19089
+ if (typeof a.version === "boolean" || !Number.isInteger(Number(a.version)) || Number(a.version) < 1) {
19090
+ return { isError: true, text: `version \uC740 1 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(a.version)}` };
19091
+ }
19092
+ const version2 = Number(a.version);
19093
+ const kind = a.kind ?? "video";
19094
+ const base = resolveBaseUrl(deps.baseUrl);
19095
+ const q = new URLSearchParams({ kind });
19096
+ const out2 = await apiRequest(
19097
+ base,
19098
+ projectPath(slug, `/cuts/${encodeURIComponent(cutId)}/versions/${version2}/download?${q}`),
19099
+ {},
19100
+ deps
19101
+ );
19102
+ if (a.output_path) {
19103
+ await (deps.downloadImpl ? deps.downloadImpl(out2.url, a.output_path) : saveUrlToFile(out2.url, a.output_path, deps.fetchImpl ?? fetch));
19104
+ return { text: `${kind} \uB97C \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4: ${a.output_path}` };
19105
+ }
19106
+ return {
19107
+ text: [
19108
+ `${kind} \uB0B4\uB824\uBC1B\uAE30 \uC8FC\uC18C (\uB9CC\uB8CC ${out2.expires_at}):`,
19109
+ out2.url,
19110
+ "output_path \uB97C \uC8FC\uBA74 \uC774 \uD30C\uC77C\uC744 \uADF8 \uACBD\uB85C\uC5D0 \uBC14\uB85C \uC800\uC7A5\uD569\uB2C8\uB2E4."
19111
+ ].join("\n")
19112
+ };
19113
+ });
19114
+ }
19115
+ function importCut(a = {}, deps = {}) {
19116
+ return guarded(SUBMITTING, async () => {
19117
+ const slug = needSlug(a);
19118
+ if (typeof slug !== "string") return slug;
19119
+ const cutId = (a.cut_id ?? "").trim();
19120
+ if (!cutId) return { isError: true, text: "cut_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 \uB4F1\uB85D\uD560 \uCEF7\uC774 \uC774\uBBF8 \uC788\uC5B4\uC57C \uD569\uB2C8\uB2E4." };
19121
+ const base = resolveBaseUrl(deps.baseUrl);
19122
+ const out2 = await apiRequest(
19123
+ base,
19124
+ projectPath(slug, `/cuts/${encodeURIComponent(cutId)}/import`),
19125
+ {
19126
+ method: "POST",
19127
+ body: {
19128
+ video_asset_id: a.video_asset_id,
19129
+ dialogue: a.dialogue,
19130
+ transcribe: a.transcribe ?? false,
19131
+ confirmed_total_krw: a.confirmed_total_krw ?? 0,
19132
+ rate_version: a.rate_version
16889
19133
  }
16890
19134
  },
16891
- required: ["title"],
16892
- additionalProperties: false
19135
+ deps
19136
+ );
19137
+ const total = out2.quote?.total_krw ?? 0;
19138
+ return {
19139
+ text: [
19140
+ `\uCEF7 ${out2.cut_id} \uC5D0 \uC601\uC0C1\uC744 \uB4F1\uB85D\uD558\uB294 \uC911\uC785\uB2C8\uB2E4 \u2014 ${out2.job_id}`,
19141
+ `\uCCAD\uAD6C ${krw(total)}${total === 0 ? " (\uD569\uC131\uC740 \uD558\uC9C0 \uC54A\uC73C\uBBC0\uB85C 0\uC6D0\uC785\uB2C8\uB2E4)" : " (\uC790\uB9C9 \uC804\uC0AC)"}`,
19142
+ "democut_wait_jobs \uB85C \uB05D\uB098\uBA74 democut_get_cut \uC758 versions \uC5D0 \uC0C8 \uBC84\uC804\uC774 \uC0DD\uAE41\uB2C8\uB2E4."
19143
+ ].join("\n")
19144
+ };
19145
+ });
19146
+ }
19147
+ function cancelJob(a = {}, deps = {}) {
19148
+ return guarded(READ_ONLY, async () => {
19149
+ const jobId = (a.job_id ?? "").trim();
19150
+ if (!jobId) return { isError: true, text: "job_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
19151
+ const base = resolveBaseUrl(deps.baseUrl);
19152
+ const out2 = await apiRequest(
19153
+ base,
19154
+ `/api/jobs/${encodeURIComponent(jobId)}`,
19155
+ { method: "DELETE" },
19156
+ deps
19157
+ );
19158
+ const lines = [];
19159
+ if (out2.cancelled?.length) lines.push(`\uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4: ${out2.cancelled.join(", ")}`);
19160
+ if (out2.not_cancellable?.length) lines.push(`\uCDE8\uC18C\uD560 \uC218 \uC5C6\uC5C8\uC2B5\uB2C8\uB2E4: ${out2.not_cancellable.join(", ")}`);
19161
+ if (lines.length === 0) {
19162
+ lines.push("\uC774\uBBF8 \uB05D\uB09C \uC7A1\uC785\uB2C8\uB2E4 \u2014 \uCDE8\uC18C\uD560 \uAC83\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(\uAC19\uC740 \uC694\uCCAD\uC744 \uB2E4\uC2DC \uBCF4\uB0B4\uB3C4 \uC548\uC804\uD569\uB2C8\uB2E4).");
16893
19163
  }
16894
- }
16895
- ];
19164
+ lines.push(
19165
+ `\uD658\uBD88 ${krw(out2.refunded_krw ?? 0)}`,
19166
+ "queued \uC600\uB2E4\uBA74 \uC804\uC561, running \uC774\uBA74 \uC2E4\uD589\uAE30\uAC00 \uBA48\uCD98 \uB4A4 \uC815\uC0B0\uD569\uB2C8\uB2E4 \u2014 \uACF5\uAE09\uC790\uAC00 \uC774\uBBF8 \uACFC\uAE08\uD55C \uD589\uC740 \uD658\uBD88\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(AI \uC601\uC0C1\uC740 \uC81C\uCD9C \uB4A4 \uCDE8\uC18C\uAC00 \uB9C9\uD799\uB2C8\uB2E4)."
19167
+ );
19168
+ return { text: lines.join("\n") };
19169
+ });
19170
+ }
19171
+ function characterLine(c) {
19172
+ const photos = c.photos?.length ? `\uC0AC\uC9C4 ${c.photos.length}\uC7A5` : "\uC0AC\uC9C4 \uC5C6\uC74C";
19173
+ return `${c.name} [${c.id}] rev=${c.rev} \xB7 ${photos}${c.current_photo_id ? " (\uB300\uD45C \uC788\uC74C)" : ""}`;
19174
+ }
19175
+ function listCharacters(_a3 = {}, deps = {}) {
19176
+ return guarded(READ_ONLY, async () => {
19177
+ const base = resolveBaseUrl(deps.baseUrl);
19178
+ const out2 = await apiRequest(base, "/api/characters", {}, deps);
19179
+ if (!out2.characters?.length) {
19180
+ return { text: "\uC544\uBC14\uD0C0\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. democut_create_character \uB85C \uB9CC\uB4DC\uC138\uC694." };
19181
+ }
19182
+ return {
19183
+ text: [`\uC544\uBC14\uD0C0 ${out2.characters.length}\uAC1C:`, ...out2.characters.map((c) => ` ${characterLine(c)}`)].join("\n")
19184
+ };
19185
+ });
19186
+ }
19187
+ function characterBody(a) {
19188
+ return {
19189
+ name: a.name,
19190
+ role: a.role ?? "",
19191
+ voice_id: a.voice_id ?? null,
19192
+ persona_text: a.persona_text ?? "",
19193
+ look_text: a.look_text ?? ""
19194
+ };
19195
+ }
19196
+ function createCharacter(a = {}, deps = {}) {
19197
+ return guarded(READ_ONLY, async () => {
19198
+ if (!(a.name ?? "").trim()) return { isError: true, text: "name \uC774 \uD544\uC694\uD569\uB2C8\uB2E4." };
19199
+ const base = resolveBaseUrl(deps.baseUrl);
19200
+ const out2 = await apiRequest(
19201
+ base,
19202
+ "/api/characters",
19203
+ { method: "POST", body: characterBody(a) },
19204
+ deps
19205
+ );
19206
+ return {
19207
+ text: [
19208
+ `\uC544\uBC14\uD0C0\uB97C \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4: ${characterLine(out2)}`,
19209
+ `\uCEF7\uC5D0\uC11C \uC4F0\uB824\uBA74 spec.pip.avatar_id \uC5D0 ${out2.id} \uB97C \uB123\uC73C\uC138\uC694.`
19210
+ ].join("\n")
19211
+ };
19212
+ });
19213
+ }
19214
+ function getCharacter(a = {}, deps = {}) {
19215
+ return guarded(READ_ONLY, async () => {
19216
+ const id = (a.character_id ?? "").trim();
19217
+ if (!id) return { isError: true, text: "character_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
19218
+ const base = resolveBaseUrl(deps.baseUrl);
19219
+ const out2 = await apiRequest(base, `/api/characters/${encodeURIComponent(id)}`, {}, deps);
19220
+ const lines = [characterLine(out2)];
19221
+ if (out2.role) lines.push(` \uC5ED\uD560: ${out2.role}`);
19222
+ if (out2.voice_id) lines.push(` \uBCF4\uC774\uC2A4: ${out2.voice_id}`);
19223
+ for (const p of out2.photos ?? []) {
19224
+ lines.push(` \uC0AC\uC9C4 ${p.seq}: ${p.asset_id} (${p.source})${p.id === out2.current_photo_id ? " \u2190 \uB300\uD45C" : ""}`);
19225
+ }
19226
+ return { text: lines.join("\n") };
19227
+ });
19228
+ }
19229
+ function putCharacter(a = {}, deps = {}) {
19230
+ return guarded(READ_ONLY, async () => {
19231
+ const id = (a.character_id ?? "").trim();
19232
+ if (!id) return { isError: true, text: "character_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
19233
+ if (!(a.name ?? "").trim()) return { isError: true, text: "name \uC774 \uD544\uC694\uD569\uB2C8\uB2E4(\uC804\uCCB4 \uAD50\uCCB4\uC785\uB2C8\uB2E4)." };
19234
+ if (a.rev === void 0 || a.rev === null) {
19235
+ return { isError: true, text: "rev \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 democut_get_character \uB85C \uD604\uC7AC rev \uB97C \uC77D\uC5B4 \uADF8\uB300\uB85C \uB123\uC73C\uC138\uC694." };
19236
+ }
19237
+ const base = resolveBaseUrl(deps.baseUrl);
19238
+ const out2 = await apiRequest(
19239
+ base,
19240
+ `/api/characters/${encodeURIComponent(id)}`,
19241
+ { method: "PUT", body: characterBody(a), headers: { "If-Match": String(a.rev) } },
19242
+ deps
19243
+ );
19244
+ return { text: `\uC544\uBC14\uD0C0\uB97C \uBC14\uAFE8\uC2B5\uB2C8\uB2E4: ${characterLine(out2)}` };
19245
+ });
19246
+ }
19247
+ function deleteCharacter(a = {}, deps = {}) {
19248
+ return guarded(READ_ONLY, async () => {
19249
+ const id = (a.character_id ?? "").trim();
19250
+ if (!id) return { isError: true, text: "character_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
19251
+ const base = resolveBaseUrl(deps.baseUrl);
19252
+ await apiRequest(
19253
+ base,
19254
+ `/api/characters/${encodeURIComponent(id)}`,
19255
+ { method: "DELETE" },
19256
+ deps
19257
+ );
19258
+ return {
19259
+ text: `\uC544\uBC14\uD0C0 ${id} \uB97C \uC9C0\uC6E0\uC2B5\uB2C8\uB2E4. \uC774\uBBF8 \uB9CC\uB4E0 \uCEF7\uC740 \uADF8\uB300\uB85C\uC785\uB2C8\uB2E4(\uADF8\uB54C \uC4F4 \uC790\uC0B0\uC744 \uC790\uAE30 \uD589\uC5D0 \uAC16\uACE0 \uC788\uC2B5\uB2C8\uB2E4).`
19260
+ };
19261
+ });
19262
+ }
19263
+
19264
+ // src/mcp/server.ts
19265
+ var TOOLS = GENERATED_TOOLS;
16896
19266
  function dispatch(name, args, deps = {}) {
16897
19267
  switch (name) {
16898
19268
  case "democut_auth_status":
16899
19269
  return authStatus(deps);
16900
- case "democut_estimate_video_cost":
16901
- return estimateCost(args, deps);
16902
- case "democut_generate_video":
16903
- return generateVideo(args, deps);
16904
- case "democut_get_video_status":
16905
- return videoStatus(args, deps);
16906
19270
  case "democut_credit_balance":
16907
19271
  return creditBalance(deps);
16908
19272
  case "democut_credit_ledger":
@@ -16911,6 +19275,35 @@ function dispatch(name, args, deps = {}) {
16911
19275
  return listProjects(args, deps);
16912
19276
  case "democut_create_project":
16913
19277
  return createProject(args, deps);
19278
+ case "democut_get_options":
19279
+ return getOptions(args, deps);
19280
+ case "democut_upload_asset":
19281
+ return uploadAsset(args, deps);
19282
+ case "democut_estimate_cuts":
19283
+ return estimateCuts(args, deps);
19284
+ case "democut_make_cuts":
19285
+ return makeCuts(args, deps);
19286
+ case "democut_wait_jobs":
19287
+ return waitJobs(args, deps);
19288
+ case "democut_get_cut":
19289
+ return getCut(args, deps);
19290
+ case "democut_download":
19291
+ return download(args, deps);
19292
+ case "democut_import_cut":
19293
+ return importCut(args, deps);
19294
+ case "democut_cancel_job":
19295
+ return cancelJob(args, deps);
19296
+ // ── 아바타(캐릭터) CRUD (MR 19a) ──
19297
+ case "democut_list_characters":
19298
+ return listCharacters(args, deps);
19299
+ case "democut_create_character":
19300
+ return createCharacter(args, deps);
19301
+ case "democut_get_character":
19302
+ return getCharacter(args, deps);
19303
+ case "democut_put_character":
19304
+ return putCharacter(args, deps);
19305
+ case "democut_delete_character":
19306
+ return deleteCharacter(args, deps);
16914
19307
  default:
16915
19308
  return Promise.resolve({ isError: true, text: `\uC54C \uC218 \uC5C6\uB294 \uB3C4\uAD6C: ${name}` });
16916
19309
  }
@@ -16938,37 +19331,18 @@ async function runMcpServer(deps = {}) {
16938
19331
  }
16939
19332
 
16940
19333
  // src/cli.ts
16941
- var HELP = `democut \u2014 DemoCut \uC5D0\uC774\uC804\uD2B8 CLI (OAuth2 device flow + \uC601\uC0C1 \uC0DD\uC131)
19334
+ var HELP = `democut \u2014 DemoCut \uC5D0\uC774\uC804\uD2B8 CLI (OAuth2 device flow + MCP)
16942
19335
 
16943
19336
  \uC0AC\uC6A9\uBC95:
16944
19337
  democut auth login [--no-browser] [--json] [--base-url <url>]
16945
19338
  democut auth status [--json] [--base-url <url>]
16946
19339
  democut auth logout [--base-url <url>]
16947
19340
 
16948
- democut video estimate [--duration <\uCD08>] [--resolution <\uD574\uC0C1\uB3C4>] [--ratio <\uBE44\uC728>] [--model <id>]
16949
- democut video generate "<\uD504\uB86C\uD504\uD2B8>" --project <slug> [--yes] [--wait] [--output <\uACBD\uB85C>] [\uC0DD\uC131 \uC635\uC158\u2026]
16950
- democut video status <job_id> [--wait] [--output <\uACBD\uB85C>]
16951
-
16952
19341
  democut mcp MCP \uC11C\uBC84(stdio) \u2014 \uC5D0\uC774\uC804\uD2B8\uC5D0 \uB3C4\uAD6C\uB85C \uBD99\uC778\uB2E4
16953
19342
  \uB4F1\uB85D: claude mcp add democut -- npx -y democut@latest mcp
16954
19343
  (@latest \uD544\uC218 \u2014 -y \uB294 npx \uCE90\uC2DC\uC758 \uC61B \uBC84\uC804\uC744 \uADF8\uB300\uB85C \uB744\uC6B4\uB2E4)
16955
19344
 
16956
- \uC0DD\uC131 \uC635\uC158:
16957
- --duration <\uCD08> \uAE30\uBCF8 5 (\uBAA8\uB378\uBCC4 \uD5C8\uC6A9 \uBC94\uC704 \uB2E4\uB984: 2.0=4~15, 2.5=4~30)
16958
- --resolution <r> 480p | 720p(\uAE30\uBCF8) | 1080p | 4k
16959
- --ratio <a> 16:9(\uAE30\uBCF8) | 9:16 | 1:1 | 4:3 | 21:9 | adaptive
16960
- --model <id> \uAE30\uBCF8 \uC11C\uBC84 \uC124\uC815\uAC12
16961
- --seed <n> \uACB0\uC815\uB860\uC801 \uC0DD\uC131\uC6A9 seed
16962
- --image-url <url> image\u2192video \uCC38\uC870 (\uACF5\uAC1C HTTPS URL, \uCD5C\uB300 4\uD68C \uBC18\uBCF5)
16963
- --audio \uC624\uB514\uC624 \uD568\uAED8 \uC0DD\uC131
16964
- --watermark \uC6CC\uD130\uB9C8\uD06C \uB123\uAE30
16965
- --project <slug> \uBE44\uC6A9\uC744 \uC774 \uD504\uB85C\uC81D\uD2B8\uB85C \uADC0\uC18D (generate \uD544\uC218 \u2014 \uBCF8\uC778 \uC18C\uC720 \uC2AC\uB7EC\uADF8)
16966
-
16967
19345
  \uACF5\uD1B5 \uC635\uC158:
16968
- -y, --yes \uBE44\uC6A9 \uD655\uC778 \uC5C6\uC774 \uC9C4\uD589 (\uBE44\uB300\uD654\uD615\uC5D0\uC11C\uB294 \uD544\uC218)
16969
- --wait \uC644\uB8CC\uAE4C\uC9C0 \uAE30\uB2E4\uB9BC
16970
- --timeout <\uCD08> --wait \uC2DC\uD55C (\uAE30\uBCF8 900)
16971
- -o, --output <\uACBD\uB85C> \uC0B0\uCD9C\uBB3C \uC800\uC7A5 (\uC11C\uBC84\uB294 \uBCF4\uAD00\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 \uBC1B\uC544 \uB450\uC138\uC694)
16972
19346
  --json \uAE30\uACC4 \uD310\uB3C5\uC6A9 JSON \uD55C \uC904
16973
19347
  --base-url <u> DemoCut \uC11C\uBC84 URL (\uAE30\uBCF8: $DEMOCUT_BASE_URL \uB610\uB294 prod)
16974
19348
  -h, --help \uB3C4\uC6C0\uB9D0
@@ -16977,32 +19351,18 @@ var HELP = `democut \u2014 DemoCut \uC5D0\uC774\uC804\uD2B8 CLI (OAuth2 device f
16977
19351
  \uC885\uB8CC \uCF54\uB4DC:
16978
19352
  0 \uC131\uACF5 1 \uC77C\uBC18 \uC624\uB958(\uBBF8\uB85C\uADF8\uC778\xB7\uCDE8\uC18C\xB7\uC0DD\uC131 \uC2E4\uD328) 2 \uACE0\uCCD0\uC11C \uC7AC\uC2DC\uB3C4 \uAC00\uB2A5(\uACFC\uAE08 \uC5C6\uC74C)
16979
19353
  3 \uC77C\uC2DC \uC624\uB958(\uADF8\uB300\uB85C \uC7AC\uC2DC\uB3C4 \uC548\uC804) 4 \uC5C5\uC2A4\uD2B8\uB9BC \uAC70\uBD80(\uC7AC\uC2DC\uB3C4 \uC2DC \uC7AC\uACFC\uAE08 \uC704\uD5D8)
16980
- 5 --wait \uC2DC\uD55C \uCD08\uACFC \u2014 \uC2E4\uD328 \uC544\uB2D8. \uC791\uC5C5\uC740 \uACC4\uC18D \uC9C4\uD589 \uC911\uC774\uB2C8 status \uB85C \uD655\uC778(\uC7AC\uC81C\uCD9C \uAE08\uC9C0)`;
19354
+ 5 \uB300\uAE30 \uC2DC\uD55C \uCD08\uACFC(\uC608\uC57D \u2014 \uC61B video --wait \uC758 \uCF54\uB4DC, \uC2E4\uD328 \uC544\uB2D8\xB7\uC7AC\uC81C\uCD9C \uAE08\uC9C0 \uC758\uBBF8\uB294 \uC720\uC9C0)`;
16981
19355
  var VALUE_FLAGS = {
16982
- "--base-url": "baseUrl",
16983
- "--duration": "duration",
16984
- "--resolution": "resolution",
16985
- "--ratio": "ratio",
16986
- "--model": "model",
16987
- "--seed": "seed",
16988
- "--project": "project",
16989
- "--output": "output",
16990
- "-o": "output",
16991
- "--timeout": "timeout"
19356
+ "--base-url": "baseUrl"
16992
19357
  };
16993
19358
  var BOOL_FLAGS = {
16994
19359
  "--no-browser": "noBrowser",
16995
19360
  "--device": "noBrowser",
16996
- "--json": "json",
16997
- "--yes": "yes",
16998
- "-y": "yes",
16999
- "--wait": "wait",
17000
- "--audio": "audio",
17001
- "--watermark": "watermark"
19361
+ "--json": "json"
17002
19362
  };
17003
19363
  var HELP_FLAGS = /* @__PURE__ */ new Set(["-h", "--help", "-v", "--version"]);
17004
19364
  function isKnownFlag(token) {
17005
- return token in VALUE_FLAGS || token in BOOL_FLAGS || HELP_FLAGS.has(token) || token === "--image-url" || token.startsWith("--image-url=");
19365
+ return token in VALUE_FLAGS || token in BOOL_FLAGS || HELP_FLAGS.has(token);
17006
19366
  }
17007
19367
  function parseArgs(argv) {
17008
19368
  const positional = [];
@@ -17020,11 +19380,6 @@ function parseArgs(argv) {
17020
19380
  version2 = true;
17021
19381
  continue;
17022
19382
  }
17023
- if (a === "--image-url" || a.startsWith("--image-url=")) {
17024
- const v = a.startsWith("--image-url=") ? a.slice("--image-url=".length) : argv[++i];
17025
- if (v) (options.imageUrls ??= []).push(v);
17026
- continue;
17027
- }
17028
19383
  const boolKey = BOOL_FLAGS[a];
17029
19384
  if (boolKey) {
17030
19385
  options[boolKey] = true;
@@ -17085,15 +19440,6 @@ ${HELP}
17085
19440
  return EXIT.FIXABLE;
17086
19441
  }
17087
19442
  if (group === "mcp") return runMcpServer({ ...deps, baseUrl: options.baseUrl });
17088
- if (group === "video") {
17089
- if (sub === "estimate") return estimateCommand(options, deps);
17090
- if (sub === "generate") return generateCommand(arg, options, deps);
17091
- if (sub === "status") return statusCommand2(arg, options, deps);
17092
- process.stderr.write(`\uC54C \uC218 \uC5C6\uB294 video \uBA85\uB839: ${sub ?? "(\uC5C6\uC74C)"}
17093
- ${HELP}
17094
- `);
17095
- return EXIT.FIXABLE;
17096
- }
17097
19443
  process.stderr.write(`\uC54C \uC218 \uC5C6\uB294 \uBA85\uB839: ${group}
17098
19444
  ${HELP}
17099
19445
  `);