democut 0.6.24 → 0.6.29

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 (2) hide show
  1. package/dist/cli.js +382 -2
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -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.24";
6919
+ var VERSION = "0.6.29";
6920
6920
 
6921
6921
  // src/device-flow.ts
6922
6922
  var DeviceFlowError = class extends Error {
@@ -18281,6 +18281,172 @@ var GENERATED_TOOLS = [
18281
18281
  "openWorldHint": false
18282
18282
  }
18283
18283
  },
18284
+ {
18285
+ "name": "democut_estimate_cut_image",
18286
+ "description": "AI \uC774\uBBF8\uC9C0 \uACAC\uC801(0\uC6D0).",
18287
+ "inputSchema": {
18288
+ "type": "object",
18289
+ "properties": {
18290
+ "slug": {
18291
+ "type": "string",
18292
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
18293
+ },
18294
+ "cut_id": {
18295
+ "type": "string",
18296
+ "description": "\uCEF7 id(cut_\u2026)"
18297
+ },
18298
+ "prompt": {
18299
+ "anyOf": [
18300
+ {
18301
+ "maxLength": 4e3,
18302
+ "type": "string"
18303
+ },
18304
+ {
18305
+ "type": "null"
18306
+ }
18307
+ ],
18308
+ "default": null,
18309
+ "title": "Prompt"
18310
+ },
18311
+ "character_id": {
18312
+ "anyOf": [
18313
+ {
18314
+ "type": "string"
18315
+ },
18316
+ {
18317
+ "type": "null"
18318
+ }
18319
+ ],
18320
+ "default": null,
18321
+ "description": "\uC544\uC9C1 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC8FC\uBA74 501",
18322
+ "title": "Character Id"
18323
+ },
18324
+ "quality": {
18325
+ "default": "medium",
18326
+ "enum": [
18327
+ "low",
18328
+ "medium",
18329
+ "high"
18330
+ ],
18331
+ "title": "Quality",
18332
+ "type": "string"
18333
+ },
18334
+ "model": {
18335
+ "anyOf": [
18336
+ {
18337
+ "maxLength": 64,
18338
+ "type": "string"
18339
+ },
18340
+ {
18341
+ "type": "null"
18342
+ }
18343
+ ],
18344
+ "default": null,
18345
+ "title": "Model"
18346
+ }
18347
+ },
18348
+ "required": [
18349
+ "slug",
18350
+ "cut_id"
18351
+ ],
18352
+ "additionalProperties": false
18353
+ },
18354
+ "annotations": {
18355
+ "readOnlyHint": false,
18356
+ "destructiveHint": false,
18357
+ "idempotentHint": false,
18358
+ "openWorldHint": false
18359
+ }
18360
+ },
18361
+ {
18362
+ "name": "democut_make_cut_image",
18363
+ "description": "AI \uB85C \uCEF7 \uC774\uBBF8\uC9C0\uB97C \uB9CC\uB4E0\uB2E4(\uCCAD\uAD6C). \uAE08\uC561\uC740 \uC0C1\uD55C\uC774\uACE0 \uC2E4\uCE21\uC73C\uB85C \uCC28\uC561\uC744 \uB3CC\uB824\uC900\uB2E4. \uC778\uBB3C \uD2B9\uC9D5\uC740 prompt \uB85C \uBB18\uC0AC\uD55C\uB2E4(character_id \uB294 \uC544\uC9C1 \uC5C6\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.",
18364
+ "inputSchema": {
18365
+ "type": "object",
18366
+ "properties": {
18367
+ "slug": {
18368
+ "type": "string",
18369
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
18370
+ },
18371
+ "cut_id": {
18372
+ "type": "string",
18373
+ "description": "\uCEF7 id(cut_\u2026)"
18374
+ },
18375
+ "prompt": {
18376
+ "anyOf": [
18377
+ {
18378
+ "maxLength": 4e3,
18379
+ "type": "string"
18380
+ },
18381
+ {
18382
+ "type": "null"
18383
+ }
18384
+ ],
18385
+ "default": null,
18386
+ "title": "Prompt"
18387
+ },
18388
+ "character_id": {
18389
+ "anyOf": [
18390
+ {
18391
+ "type": "string"
18392
+ },
18393
+ {
18394
+ "type": "null"
18395
+ }
18396
+ ],
18397
+ "default": null,
18398
+ "description": "\uC544\uC9C1 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC8FC\uBA74 501",
18399
+ "title": "Character Id"
18400
+ },
18401
+ "quality": {
18402
+ "default": "medium",
18403
+ "enum": [
18404
+ "low",
18405
+ "medium",
18406
+ "high"
18407
+ ],
18408
+ "title": "Quality",
18409
+ "type": "string"
18410
+ },
18411
+ "model": {
18412
+ "anyOf": [
18413
+ {
18414
+ "maxLength": 64,
18415
+ "type": "string"
18416
+ },
18417
+ {
18418
+ "type": "null"
18419
+ }
18420
+ ],
18421
+ "default": null,
18422
+ "title": "Model"
18423
+ },
18424
+ "confirmed_cost_krw": {
18425
+ "minimum": 0,
18426
+ "title": "Confirmed Cost Krw",
18427
+ "type": "integer"
18428
+ },
18429
+ "rate_version": {
18430
+ "minimum": 1,
18431
+ "title": "Rate Version",
18432
+ "type": "integer"
18433
+ }
18434
+ },
18435
+ "required": [
18436
+ "slug",
18437
+ "cut_id",
18438
+ "confirmed_cost_krw",
18439
+ "rate_version"
18440
+ ],
18441
+ "additionalProperties": false
18442
+ },
18443
+ "annotations": {
18444
+ "readOnlyHint": false,
18445
+ "destructiveHint": false,
18446
+ "idempotentHint": false,
18447
+ "openWorldHint": false
18448
+ }
18449
+ },
18284
18450
  {
18285
18451
  "name": "democut_credit_balance",
18286
18452
  "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.",
@@ -18580,7 +18746,7 @@ var GENERATED_TOOLS = [
18580
18746
  },
18581
18747
  {
18582
18748
  "name": "democut_get_storyboard",
18583
- "description": "\uC2A4\uD1A0\uB9AC\uBCF4\uB4DC \u2014 rev\xB7\uC21C\uC11C\xB7\uCEF7(\uD30C\uC0DD \uD544\uB4DC)\xB7\uB300\uAE30 \uC81C\uC548\xB7\uC0AC\uC6A9\uB7C9. If-Match \uC5D0 \uC4F8 rev \uAC00 \uC5EC\uAE30 \uC788\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_add_cut, democut_put_cut_draft.",
18749
+ "description": "\uC2A4\uD1A0\uB9AC\uBCF4\uB4DC \u2014 rev\xB7\uC21C\uC11C\xB7\uCEF7(\uD30C\uC0DD \uD544\uB4DC)\xB7\uB300\uAE30 \uC81C\uC548\xB7\uC0AC\uC6A9\uB7C9. If-Match \uC5D0 \uC4F8 rev \uAC00 \uC5EC\uAE30 \uC788\uB2E4. \uB2E4\uC74C \uD638\uCD9C: democut_add_cut, democut_put_cut_draft, democut_reorder_cuts.",
18584
18750
  "inputSchema": {
18585
18751
  "type": "object",
18586
18752
  "properties": {
@@ -20332,6 +20498,79 @@ var GENERATED_TOOLS = [
20332
20498
  "idempotentHint": true,
20333
20499
  "openWorldHint": false
20334
20500
  }
20501
+ },
20502
+ {
20503
+ "name": "democut_reorder_cuts",
20504
+ "description": "\uC5F0\uACB0 \uC21C\uC11C\uB97C \uD1B5\uC9F8\uB85C \uB2E4\uC2DC \uC4F4\uB2E4(If-Match rev). \uBE60\uC9C4 \uCEF7\uC740 \uB5BC\uC5B4 \uB454 \uCEF7\uC774 \uB41C\uB2E4.",
20505
+ "inputSchema": {
20506
+ "type": "object",
20507
+ "properties": {
20508
+ "slug": {
20509
+ "type": "string",
20510
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
20511
+ },
20512
+ "cut_ids": {
20513
+ "description": "\uC804\uCCB4 \uC21C\uC11C. \uBE60\uC9C4 \uCEF7\uC740 position=NULL(\uB5BC\uC5B4 \uB460)",
20514
+ "items": {
20515
+ "type": "string"
20516
+ },
20517
+ "title": "Cut Ids",
20518
+ "type": "array"
20519
+ },
20520
+ "rev": {
20521
+ "type": "integer",
20522
+ "minimum": 0,
20523
+ "description": "\uD604\uC7AC rev(get_storyboard \uC758 \uAC12 \uADF8\uB300\uB85C). \uADF8 \uC0AC\uC774 \uBC14\uB00C\uC5C8\uC73C\uBA74 409 REV_MISMATCH"
20524
+ }
20525
+ },
20526
+ "required": [
20527
+ "slug",
20528
+ "cut_ids",
20529
+ "rev"
20530
+ ],
20531
+ "additionalProperties": false
20532
+ },
20533
+ "annotations": {
20534
+ "readOnlyHint": false,
20535
+ "destructiveHint": false,
20536
+ "idempotentHint": true,
20537
+ "openWorldHint": false
20538
+ }
20539
+ },
20540
+ {
20541
+ "name": "democut_get_silence",
20542
+ "description": "\uB300\uD45C \uBC84\uC804\uC758 \uBB34\uC74C \uAD6C\uAC04 \uBBF8\uB9AC\uBCF4\uAE30(threshold_ms).",
20543
+ "inputSchema": {
20544
+ "type": "object",
20545
+ "properties": {
20546
+ "slug": {
20547
+ "type": "string",
20548
+ "description": "\uD504\uB85C\uC81D\uD2B8 \uC2AC\uB7EC\uADF8(list_projects)"
20549
+ },
20550
+ "cut_id": {
20551
+ "type": "string",
20552
+ "description": "\uCEF7 id(cut_\u2026)"
20553
+ },
20554
+ "threshold_ms": {
20555
+ "default": 800,
20556
+ "maximum": 5e3,
20557
+ "minimum": 100,
20558
+ "title": "Threshold Ms",
20559
+ "type": "integer"
20560
+ }
20561
+ },
20562
+ "required": [
20563
+ "slug",
20564
+ "cut_id"
20565
+ ],
20566
+ "additionalProperties": false
20567
+ },
20568
+ "annotations": {
20569
+ "readOnlyHint": true,
20570
+ "destructiveHint": false,
20571
+ "idempotentHint": true,
20572
+ "openWorldHint": false
20573
+ }
20335
20574
  }
20336
20575
  ];
20337
20576
 
@@ -21001,6 +21240,85 @@ function estimateCuts(a = {}, deps = {}) {
21001
21240
  return { text: lines.join("\n") };
21002
21241
  });
21003
21242
  }
21243
+ function estimateCutImage(a = {}, deps = {}) {
21244
+ return guarded(READ_ONLY, async () => {
21245
+ const slug = needSlug(a);
21246
+ if (typeof slug !== "string") return slug;
21247
+ const cutId = (a.cut_id ?? "").trim();
21248
+ if (!cutId) return { isError: true, text: "cut_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
21249
+ const base = resolveBaseUrl(deps.baseUrl);
21250
+ const out2 = await apiRequest(
21251
+ base,
21252
+ projectPath(slug, `/cuts/${encodeURIComponent(cutId)}/images/estimate`),
21253
+ {
21254
+ method: "POST",
21255
+ // ★ 광고한 인자는 전부 넘긴다 — 안 넘기면 모델이 값을 넣었는데 아무 일도 안 일어나고
21256
+ // 오류도 안 난다(`mcp-server.test.ts` 가드가 그 불일치를 잡는다).
21257
+ body: {
21258
+ ...a.prompt ? { prompt: a.prompt } : {},
21259
+ ...a.character_id ? { character_id: a.character_id } : {},
21260
+ ...a.quality ? { quality: a.quality } : {},
21261
+ ...a.model ? { model: a.model } : {}
21262
+ }
21263
+ },
21264
+ deps
21265
+ );
21266
+ const item = out2.items?.[0];
21267
+ if (!item || item.blocked_reason) {
21268
+ const reason = item?.blocked_reason ?? "\uACAC\uC801\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4";
21269
+ return {
21270
+ text: `\uC774 \uC870\uD569\uC740 \uC544\uC9C1 \uACAC\uC801\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 ${reason}
21271
+ democut_get_options \uC758 image_models \uC5D0\uC11C available \uC774 true \uC778 \uBAA8\uB378\uC744 \uACE0\uB974\uC138\uC694. \uC804\uBD80 false \uBA74 \uC544\uC9C1 \uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC5D0\uC11C AI \uC774\uBBF8\uC9C0 \uC0DD\uC131\uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uAD00\uB9AC\uC790 \uBB38\uC758).`
21272
+ };
21273
+ }
21274
+ const rows = (item.rows ?? []).map((r) => `${r.display_name || r.key} ${krw(r.krw)}`).join(", ") || "\uD589 \uC5C6\uC74C";
21275
+ const lines = [
21276
+ `AI \uCEF7 \uC774\uBBF8\uC9C0 \uACAC\uC801 (\uC694\uC728 v${out2.rate_version}) \u2014 \uBD80\uC791\uC6A9\uB3C4 \uACFC\uAE08\uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4`,
21277
+ ` ${item.cut_id}: ${krw(item.total_krw ?? 0)} (${rows})`,
21278
+ `\uC794\uC561 ${krw(out2.balance_krw)} \u2192 \uB0A8\uC744 \uC794\uC561 ${krw(out2.balance_after_krw)}`,
21279
+ 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.",
21280
+ // ★★ 상한임을 말하지 않으면 청구서를 보고 「견적과 다르다」 고 읽는다(적게 나와도 신뢰를 깎는다).
21281
+ "\uC774 \uAE08\uC561\uC740 \uC0C1\uD55C\uC785\uB2C8\uB2E4 \u2014 \uC2E4\uC81C \uC0AC\uC6A9\uB7C9\uC774 \uC801\uC73C\uBA74 \uCC28\uC561\uC744 \uC790\uB3D9\uC73C\uB85C \uB3CC\uB824\uB4DC\uB9BD\uB2C8\uB2E4."
21282
+ ];
21283
+ if (out2.mock) lines.push("(mock \uB2E8\uAC00\uC785\uB2C8\uB2E4 \u2014 \uC2E4\uC81C \uCCAD\uAD6C\uC640 \uB2E4\uB97C \uC218 \uC788\uC2B5\uB2C8\uB2E4.)");
21284
+ return { text: lines.join("\n") };
21285
+ });
21286
+ }
21287
+ function makeCutImage(a = {}, deps = {}) {
21288
+ return guarded(SUBMITTING, async () => {
21289
+ const slug = needSlug(a);
21290
+ if (typeof slug !== "string") return slug;
21291
+ const cutId = (a.cut_id ?? "").trim();
21292
+ if (!cutId) return { isError: true, text: "cut_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
21293
+ const base = resolveBaseUrl(deps.baseUrl);
21294
+ const out2 = await apiRequest(
21295
+ base,
21296
+ projectPath(slug, `/cuts/${encodeURIComponent(cutId)}/images/generate`),
21297
+ {
21298
+ method: "POST",
21299
+ body: {
21300
+ ...a.prompt ? { prompt: a.prompt } : {},
21301
+ ...a.character_id ? { character_id: a.character_id } : {},
21302
+ ...a.quality ? { quality: a.quality } : {},
21303
+ ...a.model ? { model: a.model } : {},
21304
+ // ★ 동의는 **명시**다 — 없으면 서버가 0원 동의로 읽고 409 로 거부한다(그것이 옳다).
21305
+ confirmed_cost_krw: a.confirmed_cost_krw ?? 0,
21306
+ rate_version: a.rate_version
21307
+ }
21308
+ },
21309
+ deps
21310
+ );
21311
+ const total = out2.quote?.total_krw ?? 0;
21312
+ return {
21313
+ text: [
21314
+ `\uCEF7 \uC774\uBBF8\uC9C0\uB97C \uB9CC\uB4DC\uB294 \uC911\uC785\uB2C8\uB2E4 \u2014 ${out2.job_id}`,
21315
+ // ★★ 상한임을 제출 자리에서도 말한다 — 견적을 건너뛴 호출자는 이 문장만 본다.
21316
+ `\uCCAD\uAD6C ${krw(total)} \u2014 \uC0C1\uD55C\uC785\uB2C8\uB2E4. \uC2E4\uC81C \uC0AC\uC6A9\uB7C9\uC774 \uC801\uC73C\uBA74 \uCC28\uC561\uC744 \uC790\uB3D9\uC73C\uB85C \uB3CC\uB824\uB4DC\uB9BD\uB2C8\uB2E4.`,
21317
+ "democut_wait_jobs \uB85C \uB05D\uB098\uBA74 democut_get_cut \uC758 images \uC5D0 \uC0C8 \uC774\uBBF8\uC9C0\uAC00 \uC0DD\uAE41\uB2C8\uB2E4 \u2014 \uCCAB \uC774\uBBF8\uC9C0\uBA74 \uB300\uD45C\uAC00 \uB418\uC5B4 \uB2E4\uC74C \uC601\uC0C1\uC758 \uCCAB \uD504\uB808\uC784\uC774 \uB429\uB2C8\uB2E4."
21318
+ ].join("\n")
21319
+ };
21320
+ });
21321
+ }
21004
21322
  function cutImageLine(cut) {
21005
21323
  const n = cut.images?.length ?? 0;
21006
21324
  if (!n) return `${cut.id}: \uC774\uBBF8\uC9C0 \uC5C6\uC74C \u2014 \uB2E4\uC74C \uC601\uC0C1\uC740 \uD14D\uC2A4\uD2B8\uB9CC\uC73C\uB85C \uB9CC\uB4ED\uB2C8\uB2E4(t2v).`;
@@ -21260,6 +21578,60 @@ function addCut(a = {}, deps = {}) {
21260
21578
  });
21261
21579
  }
21262
21580
  var EDIT_NOTE = "\uC774\uBBF8 \uB9CC\uB4E0 \uC601\uC0C1 \uD30C\uC77C\uC740 \uADF8\uB300\uB85C\uC785\uB2C8\uB2E4 \u2014 \uC7AC\uC0DD\xB7\uC644\uC131\uBCF8\uC5D0\uB9CC \uC801\uC6A9\uB418\uACE0 \uC7AC\uB80C\uB354\uB294 \uC5C6\uC2B5\uB2C8\uB2E4.";
21581
+ var SILENCE_NOTE = "\uBBF8\uB9AC\uBCF4\uAE30\uC785\uB2C8\uB2E4 \u2014 \uC2E4\uC81C\uB85C \uC9C0\uC6B0\uB824\uBA74 set_cut_edit \uC758 silence_removal \uC744 \uCF1C\uC138\uC694.";
21582
+ function getSilence(a = {}, deps = {}) {
21583
+ return guarded(READ_ONLY, async () => {
21584
+ const slug = needSlug(a);
21585
+ if (typeof slug !== "string") return slug;
21586
+ const cutId = (a.cut_id ?? "").trim();
21587
+ if (!cutId) return { isError: true, text: "cut_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
21588
+ const base = resolveBaseUrl(deps.baseUrl);
21589
+ const q = a.threshold_ms == null ? "" : `?threshold_ms=${encodeURIComponent(String(a.threshold_ms))}`;
21590
+ const view = await apiRequest(
21591
+ base,
21592
+ projectPath(slug, `/cuts/${encodeURIComponent(cutId)}/silence${q}`),
21593
+ {},
21594
+ deps
21595
+ );
21596
+ const spans = (view.audible_ranges ?? []).map(([s, e]) => `${(s / 1e3).toFixed(1)}~${(e / 1e3).toFixed(1)}s`).join(", ") || "(\uC5C6\uC74C)";
21597
+ return {
21598
+ text: [
21599
+ `\uBB34\uC74C ${view.threshold_ms}ms \uC774\uC0C1 \uAE30\uC900 \u2014 \uC9C0\uC6B0\uBA74 ${(view.removed_ms / 1e3).toFixed(1)}\uCD08 \uC904\uC5B4\uB4ED\uB2C8\uB2E4`,
21600
+ `\uB0A8\uB294 \uAD6C\uAC04: ${spans}`,
21601
+ // ★ **이 도구는 아무것도 바꾸지 않는다** — 안 말하면 모델이 이미 잘린 줄 알고 넘어간다.
21602
+ callableToolNames(SILENCE_NOTE)
21603
+ ].join("\n")
21604
+ };
21605
+ });
21606
+ }
21607
+ function reorderCuts(a = {}, deps = {}) {
21608
+ return guarded(READ_ONLY, async () => {
21609
+ const slug = needSlug(a);
21610
+ if (typeof slug !== "string") return slug;
21611
+ if (!Array.isArray(a.cut_ids)) {
21612
+ return { isError: true, text: "cut_ids \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 \uC804\uCCB4 \uC21C\uC11C\uB97C \uBC30\uC5F4\uB85C \uC8FC\uC138\uC694(\uBE60\uC9C4 \uCEF7\uC740 \uC21C\uC11C\uC5D0\uC11C \uBE60\uC9D1\uB2C8\uB2E4)." };
21613
+ }
21614
+ if (a.rev === void 0 || a.rev === null) {
21615
+ return {
21616
+ isError: true,
21617
+ text: callableToolNames("rev \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 get_storyboard \uB85C \uD604\uC7AC rev \uB97C \uC77D\uC5B4 \uADF8\uB300\uB85C \uB123\uC73C\uC138\uC694.")
21618
+ };
21619
+ }
21620
+ const base = resolveBaseUrl(deps.baseUrl);
21621
+ const board = await apiRequest(
21622
+ base,
21623
+ projectPath(slug, "/cuts/order"),
21624
+ { method: "PUT", body: { cut_ids: a.cut_ids }, headers: { "If-Match": String(a.rev) } },
21625
+ deps
21626
+ );
21627
+ const lines = [`\uC21C\uC11C\uB97C \uBC14\uAFE8\uC2B5\uB2C8\uB2E4 \u2014 rev ${board.rev}`, `\uC21C\uC11C: ${(board.order ?? []).join(", ") || "(\uBE44\uC5B4 \uC788\uC74C)"}`];
21628
+ const loose = (board.cuts ?? []).filter((c) => c.position == null).map((c) => c.id);
21629
+ if (loose.length) lines.push(`\uC21C\uC11C\uC5D0\uC11C \uBE90\uC2B5\uB2C8\uB2E4(\uC644\uC131\uBCF8 \uC81C\uC678, \uC9C0\uC6CC\uC9C0\uC9C0 \uC54A\uC74C): ${loose.join(", ")}`);
21630
+ if (board.next_calls?.length)
21631
+ lines.push(callableToolNames(`\uB2E4\uC74C \uD638\uCD9C: ${board.next_calls.join(", ")}`));
21632
+ return { text: lines.join("\n") };
21633
+ });
21634
+ }
21263
21635
  function putCutDraft(a = {}, deps = {}) {
21264
21636
  return guarded(READ_ONLY, async () => {
21265
21637
  const slug = needSlug(a);
@@ -21602,6 +21974,10 @@ function dispatch(name, args, deps = {}) {
21602
21974
  return makeCuts(args, deps);
21603
21975
  case "democut_wait_jobs":
21604
21976
  return waitJobs(args, deps);
21977
+ case "democut_estimate_cut_image":
21978
+ return estimateCutImage(args, deps);
21979
+ case "democut_make_cut_image":
21980
+ return makeCutImage(args, deps);
21605
21981
  case "democut_set_cut_image":
21606
21982
  return setCutImage(args, deps);
21607
21983
  case "democut_select_cut_image":
@@ -21614,6 +21990,10 @@ function dispatch(name, args, deps = {}) {
21614
21990
  return getStoryboard(args, deps);
21615
21991
  case "democut_add_cut":
21616
21992
  return addCut(args, deps);
21993
+ case "democut_get_silence":
21994
+ return getSilence(args, deps);
21995
+ case "democut_reorder_cuts":
21996
+ return reorderCuts(args, deps);
21617
21997
  case "democut_put_cut_draft":
21618
21998
  return putCutDraft(args, deps);
21619
21999
  case "democut_set_cut_edit":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "democut",
3
- "version": "0.6.24",
3
+ "version": "0.6.29",
4
4
  "description": "DemoCut 에이전트 CLI — device flow 로그인(RFC 8628) + 영상 생성",
5
5
  "license": "MIT",
6
6
  "author": "InfoGrab",