democut 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -15
- package/dist/cli.js +385 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,11 +7,15 @@ DemoCut(democut) 에이전트 인증 CLI — OAuth2 **Device Flow**(RFC 8628). H
|
|
|
7
7
|
## 설치
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install -g democut
|
|
10
|
+
npm install -g democut # 전역 설치 (선택)
|
|
11
|
+
npx -y democut@latest auth login # 설치 없이 바로 (@latest 필수 — 아래 MCP 절 참고)
|
|
11
12
|
```
|
|
12
13
|
|
|
13
14
|
## 사용
|
|
14
15
|
|
|
16
|
+
아래 예시는 **전역 설치한 경우**다. npx 로 쓰고 있다면 `democut` 을
|
|
17
|
+
`npx -y democut@latest` 로 바꿔 읽으면 된다.
|
|
18
|
+
|
|
15
19
|
```bash
|
|
16
20
|
democut auth login # device flow 로 로그인 → 토큰 저장
|
|
17
21
|
democut auth status # 현재 정체/워크스페이스/티어
|
|
@@ -80,7 +84,7 @@ democut video status <job_id> [--wait] [--output <경로>]
|
|
|
80
84
|
- **생성이 성공하면 과금된다** — 서버는 성공을 처음 관측한 시점에 원장에 기록한다(폴링을 반복해도 한 번).
|
|
81
85
|
실패한 생성은 원장에 남지 않지만, 제출이 업스트림에 접수된 뒤의 재시도는 별개 생성이라 다시 과금된다.
|
|
82
86
|
- **산출물 URL 은 24시간 후 만료된다** — `--output` 으로 즉시 받아두지 않으면 재생성해야 한다(재과금).
|
|
83
|
-
- **CLI 는 제출을 자동 재시도하지 않는다** —
|
|
87
|
+
- **CLI 는 제출을 자동 재시도하지 않는다** — 공급자가 멱등키(Idempotency-Key)를 지원하지 않아 재시도가 곧 재과금이다.
|
|
84
88
|
실패해 보여도 먼저 `democut video status <job_id>` 로 확인할 것.
|
|
85
89
|
- **`--wait` 시한 초과는 실패가 아니다** — 작업은 서버에서 계속 진행된다(종료 코드 5). 새로 제출하지 말고 `status` 로 확인한다.
|
|
86
90
|
|
|
@@ -123,17 +127,36 @@ npm run build # dist/cli.js (bin: democut) 번들
|
|
|
123
127
|
에이전트가 도구로 직접 영상을 만든다.
|
|
124
128
|
|
|
125
129
|
```bash
|
|
126
|
-
claude mcp add democut -- democut mcp
|
|
130
|
+
claude mcp add democut -- npx -y democut@latest mcp
|
|
127
131
|
```
|
|
128
132
|
|
|
129
|
-
|
|
133
|
+
`npx` 를 쓰는 이유는 전역 설치가 **연결의 선행 조건이 되지 않게** 하기 위해서다.
|
|
134
|
+
설치가 빠지면 등록은 성립하는데(등록은 바이너리 존재를 검사하지 않는다) 연결만 실패하고,
|
|
135
|
+
그 실패는 클라이언트의 `Failed to reconnect …` 한 줄로만 드러난다 — 서버가 뜨지 못하므로
|
|
136
|
+
진단을 낼 주체가 없다. 자격증명은 패키지가 아니라 `~/.democut/credentials.json` 에 있어
|
|
137
|
+
실행 방식을 바꿔도 로그인 상태는 그대로다. 전역 설치는 선택이다.
|
|
138
|
+
|
|
139
|
+
★ **`@latest` 를 빼지 마라.** `-y` 는 설치 확인 프롬프트를 자동 승인할 뿐 **버전을 다시
|
|
140
|
+
해석하지 않는다** — 태그를 빼면 `~/.npm/_npx` 캐시에 남은 옛 버전이 그대로 뜬다
|
|
141
|
+
(2026-08-31 실측: 게시본이 0.4.0 인데 캐시는 0.3.0). 그 스큐가 실제로 사고를 냈다. 서버가
|
|
142
|
+
`project_slug` 를 필수화한 뒤 게시본이 갱신되기까지 **2시간 45분** 동안 stdio 사용자의 영상
|
|
143
|
+
생성이 전부 422 였고, 원격 HTTP 사용자는 아무 영향이 없었다. 대가로 실행할 때마다
|
|
144
|
+
레지스트리를 한 번 보므로 npm 에 닿지 못하면 서버가 아예 뜨지 않는데, **조용히 옛 도구를
|
|
145
|
+
쓰는 것보다 큰 소리로 안 뜨는 편이 낫다**(레지스트리가 막힌 사내망이면 아래 원격 HTTP 나
|
|
146
|
+
전역 설치를 쓴다).
|
|
147
|
+
|
|
148
|
+
노출 도구 8개 — 쓰기는 둘뿐이고 과금은 하나뿐이다:
|
|
130
149
|
|
|
131
150
|
| 도구 | 부작용 |
|
|
132
151
|
|---|---|
|
|
133
152
|
| `democut_auth_status` | 없음 — 로그인·워크스페이스·티어 확인 |
|
|
134
|
-
| `democut_estimate_video_cost` |
|
|
135
|
-
| `
|
|
153
|
+
| `democut_estimate_video_cost` | 없음 — 비용만 계산 |
|
|
154
|
+
| `democut_credit_balance` | 없음 — 크레딧 잔액 |
|
|
155
|
+
| `democut_credit_ledger` | 없음 — 크레딧 사용 내역 |
|
|
156
|
+
| `democut_list_projects` | 없음 — 프로젝트 목록(최근 수정순) |
|
|
136
157
|
| `democut_get_video_status` | 없음 — 상태 조회 + 선택적 저장 |
|
|
158
|
+
| `democut_create_project` | **쓰기**(과금 없음) — 같은 제목이면 기존 것을 돌려준다 |
|
|
159
|
+
| `democut_generate_video` | **과금** — `confirmed_cost_usd` 필수 |
|
|
137
160
|
|
|
138
161
|
### 비용 승인이 프로토콜에 맞게 바뀐다
|
|
139
162
|
|
|
@@ -145,18 +168,53 @@ CLI 는 TTY 에 `y/N` 을 물어 사람을 막지만 MCP 에는 물어볼 화면
|
|
|
145
168
|
보내야 하고, 서버가 방금 계산한 값과 대조해 어긋나면 거부한다. 모델이 추정을 건너뛰고
|
|
146
169
|
바로 생성하는 것을 막고, 사람에게 보여준 금액과 실제 청구액이 갈라지지 않게 한다.
|
|
147
170
|
|
|
148
|
-
###
|
|
171
|
+
### stdio 와 원격 HTTP — 어느 쪽을 언제 쓰나
|
|
149
172
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
쌓아야 하고, 정적 Bearer 를 클라이언트 설정에 박는 우회는 **access token 이 1시간이면
|
|
153
|
-
만료**돼 곧 깨진다.
|
|
173
|
+
둘은 **대체가 아니라 병존**이고, 도구 이름·인자도 같다. 고르는 기준은 취향이 아니라
|
|
174
|
+
**클라이언트가 도는 자리**다.
|
|
154
175
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
176
|
+
| | 사람이 쓰는 클라이언트<br>(노트북의 Claude Code·Cursor…) | 헤드리스·자동화 호스트<br>(게이트웨이·CI·서버 박스) |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| **권장** | **원격 HTTP** | **stdio (이 CLI)** |
|
|
179
|
+
| 로그인 | 붙는 순간 브라우저가 열려 끝난다 | `democut auth login --no-browser` 1회 (device flow, RFC 8628) |
|
|
180
|
+
| 브라우저 없는 자리 | **불가** — 비대화형에서는 OAuth 흐름이 안 돈다 | **가능** — 코드를 다른 기기에서 승인 |
|
|
181
|
+
| 사전 준비 | 아래 두 옵션을 그대로 복사 | 없음 — redirect URI 등록도 브라우저도 불필요 |
|
|
182
|
+
| 버전 스큐 | **없다** — 띄울 로컬 바이너리가 없다 | `@latest` 로 막는다(위 참고) |
|
|
183
|
+
| 산출물 | 만료되는 링크로만 받는다 | `--output` 으로 디스크에 저장된다 |
|
|
184
|
+
|
|
185
|
+
헤드리스에서 갈리는 것은 편의가 아니라 **가능/불가능**이다. 원격 HTTP 의 OAuth 는 호스트가
|
|
186
|
+
브라우저를 띄워야 시작되는데, Claude Code 문서가 비대화형에서는 그 흐름을 돌릴 수 없다고
|
|
187
|
+
명시한다 — *"In non-interactive mode there's no `/mcp` panel, so Claude Code can't run the
|
|
188
|
+
OAuth flow for you."* 사람이 대화형 세션에서 **미리** 인증해 두는 것(`claude mcp login`)이
|
|
189
|
+
유일한 우회다. 거기에 Clerk 이 loopback redirect 의 포트를 정확 일치로 요구하므로 그 호스트가
|
|
190
|
+
쓸 포트의 redirect URI 도 OAuth 애플리케이션에 미리 등록해야 한다.
|
|
191
|
+
|
|
192
|
+
stdio 는 device flow(RFC 8628)라 redirect URI 자체가 없고, `--no-browser` 가 코드와 URL 을
|
|
193
|
+
출력하면 사람이 **다른 기기에서** 승인한다 — 그래서 브라우저가 없는 자리에서도 성립한다.
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
claude mcp add --transport http --client-id 7ovjLP6E85qLNAyq --callback-port 33418 \
|
|
197
|
+
democut https://democut.ai/mcp
|
|
198
|
+
```
|
|
158
199
|
|
|
159
|
-
|
|
200
|
+
두 옵션은 **생략할 수 없고 임의로 바꿀 수도 없다.** `--client-id` 는 이 서버가 아무
|
|
201
|
+
클라이언트나 받지 않기 때문이고(동적 클라이언트 등록(DCR)을 **일부러 꺼 두었다** —
|
|
202
|
+
켜면 아무나 등록해 통과하는 confused-deputy 표면이 열린다), `--callback-port` 는 그 포트의
|
|
203
|
+
redirect URI 가 사전 등록돼 있어야 하기 때문이다. 미등록이면 Clerk 이 400
|
|
204
|
+
`redirect_uri … does not match … pre-registered redirect urls` 로 거부한다. 위 두 값은
|
|
205
|
+
공개값이고 웹 문서(<https://democut.ai/docs/agents>)가 같은 쌍을 안내한다. 설계 근거의
|
|
206
|
+
SSOT 는 `apps/api/app/mcp/auth.py` docstring.
|
|
207
|
+
|
|
208
|
+
> ⚠️ **"클라이언트 설정 파일에 토큰이 남지 않는다" 는 stdio 의 고유 장점이 아니다.**
|
|
209
|
+
> 이 문서가 한동안 그렇게 적고 있었는데 **사실이 아니다** — 원격 HTTP 등록도 설정에는
|
|
210
|
+
> 공개값 둘(`clientId`·`callbackPort`)만 남고 액세스 토큰은 호스트의 자격증명 저장소에
|
|
211
|
+
> 있다(2026-08-31 실측). 두 전송이 같으므로 선택 근거가 되지 못한다. 위 표의 기준으로 골라라.
|
|
212
|
+
|
|
213
|
+
> ⚠️ 이 문단은 원래 "원격은 동적 클라이언트 등록을 요구해서 체인을 새로 쌓아야 한다" 고
|
|
214
|
+
> 적혀 있었는데 **틀렸다.** DCR 은 MCP 명세에서 MUST 가 아니라 SHOULD 이고, 무엇보다 우리
|
|
215
|
+
> 인증 공급자(Clerk)가 이미 완전한 OAuth 2.1 인가서버라 **우리가 만든 AS 는 0줄**이다.
|
|
216
|
+
> 오류의 모양이 재발 포인트라 남긴다 — *우리 코드*만 재고 조사하고 **이미 구입한 SaaS
|
|
217
|
+
> 기능은 세지 않았다.**
|
|
160
218
|
|
|
161
219
|
## 게시 (npm publish)
|
|
162
220
|
|
package/dist/cli.js
CHANGED
|
@@ -6885,8 +6885,8 @@ var require_dist = __commonJS({
|
|
|
6885
6885
|
return ajv;
|
|
6886
6886
|
}
|
|
6887
6887
|
const [formats, exportName] = opts.mode === "fast" ? [formats_1.fastFormats, fastName] : [formats_1.fullFormats, fullName];
|
|
6888
|
-
const
|
|
6889
|
-
addFormats(ajv,
|
|
6888
|
+
const list2 = opts.formats || formats_1.formatNames;
|
|
6889
|
+
addFormats(ajv, list2, formats, exportName);
|
|
6890
6890
|
if (opts.keywords)
|
|
6891
6891
|
(0, limit_1.default)(ajv);
|
|
6892
6892
|
return ajv;
|
|
@@ -6898,11 +6898,11 @@ var require_dist = __commonJS({
|
|
|
6898
6898
|
throw new Error(`Unknown format "${name}"`);
|
|
6899
6899
|
return f;
|
|
6900
6900
|
};
|
|
6901
|
-
function addFormats(ajv,
|
|
6901
|
+
function addFormats(ajv, list2, fs, exportName) {
|
|
6902
6902
|
var _a3;
|
|
6903
6903
|
var _b;
|
|
6904
6904
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6905
|
-
for (const f of
|
|
6905
|
+
for (const f of list2)
|
|
6906
6906
|
ajv.addFormat(f, fs[f]);
|
|
6907
6907
|
}
|
|
6908
6908
|
module.exports = exports = formatsPlugin;
|
|
@@ -7362,6 +7362,16 @@ function classifyApiError(e, ctx) {
|
|
|
7362
7362
|
]
|
|
7363
7363
|
};
|
|
7364
7364
|
}
|
|
7365
|
+
if (e.status === 404) {
|
|
7366
|
+
const lines = [];
|
|
7367
|
+
if (e.code === "VIDEOGEN_PROJECT_NOT_FOUND") {
|
|
7368
|
+
lines.push(
|
|
7369
|
+
"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."
|
|
7370
|
+
);
|
|
7371
|
+
}
|
|
7372
|
+
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.");
|
|
7373
|
+
return { safety: "fixable", notCharged: true, lines };
|
|
7374
|
+
}
|
|
7365
7375
|
if (e.status === 403) {
|
|
7366
7376
|
return {
|
|
7367
7377
|
safety: "unknown",
|
|
@@ -7437,13 +7447,14 @@ async function download(videoUrl, outPath, fetchImpl = fetch) {
|
|
|
7437
7447
|
const res = await fetchImpl(videoUrl);
|
|
7438
7448
|
if (!res.ok) {
|
|
7439
7449
|
throw new Error(
|
|
7440
|
-
`\uC0B0\uCD9C\uBB3C \uB0B4\uB824\uBC1B\uAE30 \uC2E4\uD328 (HTTP ${res.status})
|
|
7450
|
+
`\uC0B0\uCD9C\uBB3C \uB0B4\uB824\uBC1B\uAE30 \uC2E4\uD328 (HTTP ${res.status}).`
|
|
7441
7451
|
);
|
|
7442
7452
|
}
|
|
7443
7453
|
await writeFile(outPath, Buffer.from(await res.arrayBuffer()));
|
|
7444
7454
|
}
|
|
7445
7455
|
|
|
7446
7456
|
// src/commands/video.ts
|
|
7457
|
+
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.";
|
|
7447
7458
|
var EXIT = {
|
|
7448
7459
|
OK: 0,
|
|
7449
7460
|
/** 일반 오류 — 미로그인·사용자 취소·생성 실패·알 수 없음. */
|
|
@@ -7550,8 +7561,9 @@ function estimateCommand(opts, deps = {}) {
|
|
|
7550
7561
|
const base = resolveBaseUrl(opts.baseUrl);
|
|
7551
7562
|
const r = await estimate(base, buildEstimateIn(opts), deps);
|
|
7552
7563
|
if (opts.json) {
|
|
7553
|
-
emit(opts, true, { tokens: r.tokens, cost_usd: r.cost_usd, model: r.model });
|
|
7564
|
+
emit(opts, true, { tokens: r.tokens, cost_usd: r.cost_usd, model: r.model, mock: r.mock });
|
|
7554
7565
|
} else {
|
|
7566
|
+
if (r.mock) err2(MOCK_NOTICE);
|
|
7555
7567
|
out2(`\uC608\uC0C1 \uBE44\uC6A9: ${usd2(r.cost_usd)} (${r.tokens.toLocaleString()} tokens \xB7 ${r.model})`);
|
|
7556
7568
|
}
|
|
7557
7569
|
return EXIT.OK;
|
|
@@ -7562,10 +7574,16 @@ function generateCommand(prompt, opts, deps = {}) {
|
|
|
7562
7574
|
if (!prompt || !prompt.trim()) {
|
|
7563
7575
|
throw new UsageError('\uD504\uB86C\uD504\uD2B8\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC608: democut video generate "\uACE0\uC591\uC774\uAC00 \uCDA4\uCD98\uB2E4"');
|
|
7564
7576
|
}
|
|
7577
|
+
if (!opts.project || !opts.project.trim()) {
|
|
7578
|
+
throw new UsageError(
|
|
7579
|
+
"--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."
|
|
7580
|
+
);
|
|
7581
|
+
}
|
|
7565
7582
|
const base = resolveBaseUrl(opts.baseUrl);
|
|
7566
7583
|
const est = buildEstimateIn(opts);
|
|
7567
7584
|
const quote = await estimate(base, est, deps);
|
|
7568
7585
|
if (!opts.json) {
|
|
7586
|
+
if (quote.mock) err2(MOCK_NOTICE);
|
|
7569
7587
|
out2(`\uC608\uC0C1 \uBE44\uC6A9: ${usd2(quote.cost_usd)} (${quote.tokens.toLocaleString()} tokens \xB7 ${quote.model})`);
|
|
7570
7588
|
out2(` ${est.duration_s}\uCD08 \xB7 ${est.resolution} \xB7 ${est.ratio}`);
|
|
7571
7589
|
}
|
|
@@ -7591,7 +7609,8 @@ function generateCommand(prompt, opts, deps = {}) {
|
|
|
7591
7609
|
return EXIT.FIXABLE;
|
|
7592
7610
|
}
|
|
7593
7611
|
const ask = deps.confirmImpl ?? confirm;
|
|
7594
|
-
|
|
7612
|
+
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?`;
|
|
7613
|
+
if (!await ask(question)) {
|
|
7595
7614
|
out2("\uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4. \uACFC\uAE08\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
|
|
7596
7615
|
return EXIT.GENERAL;
|
|
7597
7616
|
}
|
|
@@ -7606,7 +7625,7 @@ function generateCommand(prompt, opts, deps = {}) {
|
|
|
7606
7625
|
...opts.model ? { model: opts.model } : {},
|
|
7607
7626
|
...opts.seed !== void 0 ? { seed: parseIntOpt(opts.seed, "seed") } : {},
|
|
7608
7627
|
...opts.imageUrls?.length ? { image_urls: opts.imageUrls } : {},
|
|
7609
|
-
|
|
7628
|
+
project_slug: opts.project
|
|
7610
7629
|
};
|
|
7611
7630
|
const job = await submit(base, body, deps);
|
|
7612
7631
|
if (job.duplicate) {
|
|
@@ -7618,6 +7637,7 @@ function generateCommand(prompt, opts, deps = {}) {
|
|
|
7618
7637
|
}
|
|
7619
7638
|
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.`);
|
|
7620
7639
|
} else if (!opts.json) {
|
|
7640
|
+
if (job.mock) err2(MOCK_NOTICE);
|
|
7621
7641
|
out2(`\uC81C\uCD9C\uB428: job ${job.job_id} (\uC608\uC0C1 ${usd2(job.estimated_cost_usd)})`);
|
|
7622
7642
|
}
|
|
7623
7643
|
if (!opts.wait) {
|
|
@@ -7628,11 +7648,11 @@ function generateCommand(prompt, opts, deps = {}) {
|
|
|
7628
7648
|
model: job.model,
|
|
7629
7649
|
estimated_cost_usd: job.estimated_cost_usd,
|
|
7630
7650
|
duplicate: job.duplicate,
|
|
7631
|
-
pending: job.pending
|
|
7651
|
+
pending: job.pending,
|
|
7652
|
+
mock: job.mock
|
|
7632
7653
|
});
|
|
7633
7654
|
} else {
|
|
7634
|
-
|
|
7635
|
-
out2(`\uC644\uB8CC \uD655\uC778: democut video status ${job.job_id}${projectFlag}`);
|
|
7655
|
+
out2(`\uC644\uB8CC \uD655\uC778: democut video status ${job.job_id}`);
|
|
7636
7656
|
}
|
|
7637
7657
|
return EXIT.OK;
|
|
7638
7658
|
}
|
|
@@ -7669,6 +7689,24 @@ async function report(job, opts, deps = {}) {
|
|
|
7669
7689
|
}
|
|
7670
7690
|
return EXIT.GENERAL;
|
|
7671
7691
|
}
|
|
7692
|
+
if (job.mock) {
|
|
7693
|
+
if (opts.json) {
|
|
7694
|
+
emit(opts, true, {
|
|
7695
|
+
job_id: job.job_id,
|
|
7696
|
+
status: job.status,
|
|
7697
|
+
model: job.model,
|
|
7698
|
+
video_url: job.video_url ?? null,
|
|
7699
|
+
saved_to: null,
|
|
7700
|
+
mock: true
|
|
7701
|
+
});
|
|
7702
|
+
} else {
|
|
7703
|
+
err2(MOCK_NOTICE);
|
|
7704
|
+
out2(`\uC0C1\uD0DC: ${job.status} (\uAC00\uC9DC)`);
|
|
7705
|
+
if (job.video_url) out2(` URL : ${job.video_url} \u2190 \uC2E4\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4`);
|
|
7706
|
+
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.");
|
|
7707
|
+
}
|
|
7708
|
+
return EXIT.OK;
|
|
7709
|
+
}
|
|
7672
7710
|
let saved = null;
|
|
7673
7711
|
let downloadError = null;
|
|
7674
7712
|
if (job.video_url && opts.output) {
|
|
@@ -7699,9 +7737,9 @@ async function report(job, opts, deps = {}) {
|
|
|
7699
7737
|
out2(` URL : ${job.video_url}`);
|
|
7700
7738
|
if (downloadError) {
|
|
7701
7739
|
err2(` \uB0B4\uB824\uBC1B\uAE30 \uC2E4\uD328: ${downloadError}`);
|
|
7702
|
-
err2(" \u26A0\uFE0F \uC704 URL \uB85C \uC9C1\uC811 \uBC1B\uC73C\uC138\uC694 \u2014
|
|
7740
|
+
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.");
|
|
7703
7741
|
} else {
|
|
7704
|
-
out2(" \u26A0\uFE0F \
|
|
7742
|
+
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>).");
|
|
7705
7743
|
}
|
|
7706
7744
|
}
|
|
7707
7745
|
}
|
|
@@ -16275,10 +16313,58 @@ var StdioServerTransport = class {
|
|
|
16275
16313
|
};
|
|
16276
16314
|
|
|
16277
16315
|
// src/version.ts
|
|
16278
|
-
var VERSION = "0.
|
|
16316
|
+
var VERSION = "0.5.0";
|
|
16279
16317
|
|
|
16280
16318
|
// src/mcp/tools.ts
|
|
16281
16319
|
import { existsSync as existsSync2 } from "fs";
|
|
16320
|
+
|
|
16321
|
+
// src/credits.ts
|
|
16322
|
+
var LEDGER_MAX_LIMIT = 200;
|
|
16323
|
+
var LEDGER_DEFAULT_LIMIT = 10;
|
|
16324
|
+
function balance(baseUrl, workspaceId, deps = {}) {
|
|
16325
|
+
return apiRequest(
|
|
16326
|
+
baseUrl,
|
|
16327
|
+
`/api/workspaces/${encodeURIComponent(workspaceId)}/credits`,
|
|
16328
|
+
{},
|
|
16329
|
+
deps
|
|
16330
|
+
);
|
|
16331
|
+
}
|
|
16332
|
+
function ledger(baseUrl, workspaceId, opts = {}, deps = {}) {
|
|
16333
|
+
const q = new URLSearchParams();
|
|
16334
|
+
q.set("limit", String(opts.limit ?? LEDGER_DEFAULT_LIMIT));
|
|
16335
|
+
if (opts.beforeId !== void 0) q.set("before_id", String(opts.beforeId));
|
|
16336
|
+
return apiRequest(
|
|
16337
|
+
baseUrl,
|
|
16338
|
+
`/api/workspaces/${encodeURIComponent(workspaceId)}/credits/ledger?${q}`,
|
|
16339
|
+
{},
|
|
16340
|
+
deps
|
|
16341
|
+
);
|
|
16342
|
+
}
|
|
16343
|
+
|
|
16344
|
+
// src/projects.ts
|
|
16345
|
+
var PROJECTS_DEFAULT_LIMIT = 30;
|
|
16346
|
+
var PROJECTS_MAX_LIMIT = 100;
|
|
16347
|
+
function list(baseUrl, deps = {}) {
|
|
16348
|
+
return apiRequest(baseUrl, "/api/projects", {}, deps);
|
|
16349
|
+
}
|
|
16350
|
+
function create(baseUrl, body, deps = {}) {
|
|
16351
|
+
return apiRequest(baseUrl, "/api/projects", { method: "POST", body }, deps);
|
|
16352
|
+
}
|
|
16353
|
+
async function defaultVoiceId(baseUrl, deps = {}) {
|
|
16354
|
+
const out3 = await apiRequest(
|
|
16355
|
+
baseUrl,
|
|
16356
|
+
"/api/projects/voices",
|
|
16357
|
+
{},
|
|
16358
|
+
deps
|
|
16359
|
+
);
|
|
16360
|
+
const id = out3.default_voice_id;
|
|
16361
|
+
if (!id) {
|
|
16362
|
+
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).");
|
|
16363
|
+
}
|
|
16364
|
+
return id;
|
|
16365
|
+
}
|
|
16366
|
+
|
|
16367
|
+
// src/mcp/tools.ts
|
|
16282
16368
|
var COST_TOLERANCE_USD = 5e-3;
|
|
16283
16369
|
function usd3(v) {
|
|
16284
16370
|
return v < 0.01 ? `$${v.toFixed(4)}` : `$${v.toFixed(2)}`;
|
|
@@ -16330,10 +16416,22 @@ function toEstimateIn(a) {
|
|
|
16330
16416
|
...a.model ? { model: a.model } : {}
|
|
16331
16417
|
};
|
|
16332
16418
|
}
|
|
16419
|
+
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.";
|
|
16333
16420
|
function estimateCost(a, deps = {}) {
|
|
16334
16421
|
return guarded2(READ_ONLY, async () => {
|
|
16335
16422
|
const base = resolveBaseUrl(deps.baseUrl);
|
|
16336
16423
|
const r = await estimate(base, toEstimateIn(a), deps);
|
|
16424
|
+
if (r.mock) {
|
|
16425
|
+
return {
|
|
16426
|
+
text: [
|
|
16427
|
+
MOCK_BANNER,
|
|
16428
|
+
"",
|
|
16429
|
+
`(\uCC38\uACE0\uC6A9 \uCD94\uC815\uCE58: ${usd3(r.cost_usd)} \xB7 ${r.model})`,
|
|
16430
|
+
"",
|
|
16431
|
+
"\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."
|
|
16432
|
+
].join("\n")
|
|
16433
|
+
};
|
|
16434
|
+
}
|
|
16337
16435
|
return {
|
|
16338
16436
|
text: [
|
|
16339
16437
|
`\uC608\uC0C1 \uBE44\uC6A9: ${usd3(r.cost_usd)} (${r.tokens.toLocaleString()} tokens \xB7 ${r.model})`,
|
|
@@ -16349,6 +16447,12 @@ function generateVideo(a, deps = {}) {
|
|
|
16349
16447
|
if (!a.prompt?.trim()) {
|
|
16350
16448
|
return { isError: true, text: "prompt \uAC00 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4." };
|
|
16351
16449
|
}
|
|
16450
|
+
if (typeof a.project_slug !== "string" || !a.project_slug.trim()) {
|
|
16451
|
+
return {
|
|
16452
|
+
isError: true,
|
|
16453
|
+
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."
|
|
16454
|
+
};
|
|
16455
|
+
}
|
|
16352
16456
|
const base = resolveBaseUrl(deps.baseUrl);
|
|
16353
16457
|
const est = toEstimateIn(a);
|
|
16354
16458
|
const quote = await estimate(base, est, deps);
|
|
@@ -16374,7 +16478,7 @@ function generateVideo(a, deps = {}) {
|
|
|
16374
16478
|
...a.model ? { model: a.model } : {},
|
|
16375
16479
|
...a.seed !== void 0 ? { seed: a.seed } : {},
|
|
16376
16480
|
...a.image_urls?.length ? { image_urls: a.image_urls } : {},
|
|
16377
|
-
|
|
16481
|
+
project_slug: a.project_slug.trim()
|
|
16378
16482
|
};
|
|
16379
16483
|
const job = await submit(base, body, deps);
|
|
16380
16484
|
if (job.duplicate) {
|
|
@@ -16382,6 +16486,17 @@ function generateVideo(a, deps = {}) {
|
|
|
16382
16486
|
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.`
|
|
16383
16487
|
};
|
|
16384
16488
|
}
|
|
16489
|
+
if (job.mock) {
|
|
16490
|
+
return {
|
|
16491
|
+
text: [
|
|
16492
|
+
MOCK_BANNER,
|
|
16493
|
+
"",
|
|
16494
|
+
`(\uAC00\uC9DC job_id: ${job.job_id} \xB7 \uBAA8\uB378 ${job.model})`,
|
|
16495
|
+
"",
|
|
16496
|
+
"\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."
|
|
16497
|
+
].join("\n")
|
|
16498
|
+
};
|
|
16499
|
+
}
|
|
16385
16500
|
return {
|
|
16386
16501
|
text: [
|
|
16387
16502
|
`\uC81C\uCD9C\uB428 \u2014 job_id: ${job.job_id}`,
|
|
@@ -16398,6 +16513,17 @@ function videoStatus(a, deps = {}) {
|
|
|
16398
16513
|
if (!a.job_id?.trim()) return { isError: true, text: "job_id \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4." };
|
|
16399
16514
|
const base = resolveBaseUrl(deps.baseUrl);
|
|
16400
16515
|
const job = await status(base, a.job_id, a.project_slug, deps);
|
|
16516
|
+
if (job.mock) {
|
|
16517
|
+
return {
|
|
16518
|
+
text: [
|
|
16519
|
+
MOCK_BANNER,
|
|
16520
|
+
"",
|
|
16521
|
+
`(\uAC00\uC9DC \uC0C1\uD0DC: ${job.status} \xB7 \uAC00\uC9DC \uACB0\uACFC: ${job.video_url ?? "\uC5C6\uC74C"})`,
|
|
16522
|
+
"",
|
|
16523
|
+
"\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."
|
|
16524
|
+
].join("\n")
|
|
16525
|
+
};
|
|
16526
|
+
}
|
|
16401
16527
|
if (job.status === "failed" || job.status === "cancelled") {
|
|
16402
16528
|
return {
|
|
16403
16529
|
isError: true,
|
|
@@ -16417,7 +16543,7 @@ function videoStatus(a, deps = {}) {
|
|
|
16417
16543
|
if (existsSync2(a.output_path)) {
|
|
16418
16544
|
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).`);
|
|
16419
16545
|
lines.push(`URL: ${job.video_url}`);
|
|
16420
|
-
lines.push("\uB2E4\uB978 \uACBD\uB85C\uB97C \uC9C0\uC815\uD558\uAC70\uB098 \uC704 URL \uB85C \uC9C1\uC811 \uBC1B\uC73C\uC138\uC694 \u2014
|
|
16546
|
+
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.");
|
|
16421
16547
|
return { text: lines.join("\n") };
|
|
16422
16548
|
}
|
|
16423
16549
|
try {
|
|
@@ -16426,15 +16552,180 @@ function videoStatus(a, deps = {}) {
|
|
|
16426
16552
|
} catch (e) {
|
|
16427
16553
|
lines.push(`\uB0B4\uB824\uBC1B\uAE30 \uC2E4\uD328: ${e?.message ?? String(e)}`);
|
|
16428
16554
|
lines.push(`URL: ${job.video_url}`);
|
|
16429
|
-
lines.push("\u26A0\uFE0F \uC704 URL \uB85C \uC9C1\uC811 \uBC1B\uC73C\uC138\uC694 \u2014
|
|
16555
|
+
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.");
|
|
16430
16556
|
}
|
|
16431
16557
|
} else if (job.video_url) {
|
|
16432
16558
|
lines.push(`URL: ${job.video_url}`);
|
|
16433
|
-
lines.push("\u26A0\uFE0F \
|
|
16559
|
+
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.");
|
|
16434
16560
|
}
|
|
16435
16561
|
return { text: lines.join("\n") };
|
|
16436
16562
|
});
|
|
16437
16563
|
}
|
|
16564
|
+
var krw = (v) => `${v.toLocaleString("ko-KR")}\uC6D0`;
|
|
16565
|
+
var NO_WORKSPACE = {
|
|
16566
|
+
isError: true,
|
|
16567
|
+
text: "\uD65C\uC131 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. democut_auth_status \uB85C \uB85C\uADF8\uC778 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0, \uC18C\uC18D\uB41C \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uAC00 \uC5C6\uB2E4\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uCD08\uB300\uB97C \uBC1B\uC544\uC57C \uD55C\uB2E4\uACE0 \uC54C\uB9AC\uC138\uC694."
|
|
16568
|
+
};
|
|
16569
|
+
async function resolveWorkspace(base, deps) {
|
|
16570
|
+
const token = await getValidAccessToken(base, deps);
|
|
16571
|
+
const me = await whoami(base, token, deps.fetchImpl);
|
|
16572
|
+
return me.workspace_id ?? null;
|
|
16573
|
+
}
|
|
16574
|
+
function creditBalance(deps = {}) {
|
|
16575
|
+
return guarded2(READ_ONLY, async () => {
|
|
16576
|
+
const base = resolveBaseUrl(deps.baseUrl);
|
|
16577
|
+
const ws = await resolveWorkspace(base, deps);
|
|
16578
|
+
if (!ws) return NO_WORKSPACE;
|
|
16579
|
+
const b = await balance(base, ws, deps);
|
|
16580
|
+
if (b.total_krw == null) {
|
|
16581
|
+
return {
|
|
16582
|
+
text: "\uC774 \uBC30\uD3EC\uC5D0\uB294 \uD06C\uB808\uB527 \uAE30\uB2A5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC794\uC561\uC774\uB77C\uB294 \uAC1C\uB150 \uC790\uCCB4\uAC00 \uC5C6\uACE0, \uC794\uC561 \uBD80\uC871\uC73C\uB85C \uC791\uC5C5\uC774 \uB9C9\uD788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC794\uC561\uC744 0\uC6D0\uC73C\uB85C \uC77D\uC9C0 \uB9C8\uC138\uC694."
|
|
16583
|
+
};
|
|
16584
|
+
}
|
|
16585
|
+
const lines = [
|
|
16586
|
+
`\uC794\uC561: ${krw(b.total_krw)} (\uAD6C\uB3C5 ${krw(b.subscription_krw ?? 0)} \xB7 \uCDA9\uC804 ${krw(b.topup_krw ?? 0)})`,
|
|
16587
|
+
`\uC694\uAE08\uC81C: ${b.tier ?? "-"} \xB7 \uC9C0\uAE09 \uC8FC\uAE30: ${b.period_key ?? "\uC5C6\uC74C"}`,
|
|
16588
|
+
""
|
|
16589
|
+
];
|
|
16590
|
+
if (!b.enabled) {
|
|
16591
|
+
lines.push(
|
|
16592
|
+
"\uACFC\uAE08 \uCC28\uB2E8\uC774 **\uAEBC\uC838 \uC788\uC2B5\uB2C8\uB2E4** \u2014 \uC794\uC561\uC774 \uBAA8\uC790\uB77C\uB3C4 \uC791\uC5C5\uC774 \uAC70\uBD80\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC704 \uC794\uC561\uC740 \uCC38\uACE0\uC6A9\uC774\uBA70, \uC794\uC561 \uBD80\uC871\uC744 \uC774\uC720\uB85C \uC791\uC5C5\uC744 \uD3EC\uAE30\uD558\uC9C0 \uB9C8\uC138\uC694."
|
|
16593
|
+
);
|
|
16594
|
+
} else if (b.total_krw <= 0) {
|
|
16595
|
+
lines.push(
|
|
16596
|
+
"\uC794\uC561\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uB3C8\uC774 \uB098\uAC00\uB294 \uC791\uC5C5\uC740 402 \uB85C \uAC70\uBD80\uB429\uB2C8\uB2E4. \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\uC138\uC694. \uC81C\uCD9C\uC744 \uBC18\uBCF5\uD558\uC9C0 \uB9C8\uC138\uC694."
|
|
16597
|
+
);
|
|
16598
|
+
} else {
|
|
16599
|
+
lines.push(
|
|
16600
|
+
"\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."
|
|
16601
|
+
);
|
|
16602
|
+
}
|
|
16603
|
+
return { text: lines.join("\n") };
|
|
16604
|
+
});
|
|
16605
|
+
}
|
|
16606
|
+
function creditLedger(a = {}, deps = {}) {
|
|
16607
|
+
return guarded2(READ_ONLY, async () => {
|
|
16608
|
+
if (a.limit !== void 0 && !Number.isFinite(a.limit)) {
|
|
16609
|
+
return { isError: true, text: `limit \uC740 \uC22B\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(a.limit)}` };
|
|
16610
|
+
}
|
|
16611
|
+
if (a.before_id !== void 0 && !Number.isFinite(a.before_id)) {
|
|
16612
|
+
return {
|
|
16613
|
+
isError: true,
|
|
16614
|
+
text: `before_id \uB294 \uC22B\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(a.before_id)}`
|
|
16615
|
+
};
|
|
16616
|
+
}
|
|
16617
|
+
const limit = Math.max(
|
|
16618
|
+
1,
|
|
16619
|
+
Math.min(Math.trunc(a.limit ?? LEDGER_DEFAULT_LIMIT), LEDGER_MAX_LIMIT)
|
|
16620
|
+
);
|
|
16621
|
+
if (a.before_id !== void 0 && a.before_id < 1) {
|
|
16622
|
+
return { isError: true, text: "before_id \uB294 1 \uC774\uC0C1\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4." };
|
|
16623
|
+
}
|
|
16624
|
+
const base = resolveBaseUrl(deps.baseUrl);
|
|
16625
|
+
const ws = await resolveWorkspace(base, deps);
|
|
16626
|
+
if (!ws) return NO_WORKSPACE;
|
|
16627
|
+
const out3 = await ledger(
|
|
16628
|
+
base,
|
|
16629
|
+
ws,
|
|
16630
|
+
{ limit, ...a.before_id !== void 0 ? { beforeId: Math.trunc(a.before_id) } : {} },
|
|
16631
|
+
deps
|
|
16632
|
+
);
|
|
16633
|
+
if (out3.entries.length === 0) {
|
|
16634
|
+
return {
|
|
16635
|
+
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."
|
|
16636
|
+
};
|
|
16637
|
+
}
|
|
16638
|
+
const lines = ["\uD06C\uB808\uB527 \uC0AC\uC6A9 \uB0B4\uC5ED (\uCD5C\uC2E0\uC21C)", ""];
|
|
16639
|
+
for (const e of out3.entries) {
|
|
16640
|
+
const when = (e.created_at ?? "").slice(0, 16).replace("T", " ");
|
|
16641
|
+
const parts = [e.display_name];
|
|
16642
|
+
if (e.units_label) parts.push(e.units_label);
|
|
16643
|
+
if (e.project_slug) parts.push(e.project_slug);
|
|
16644
|
+
if (e.reason) parts.push(e.reason);
|
|
16645
|
+
const sign = e.amount_krw > 0 ? "+" : "";
|
|
16646
|
+
lines.push(
|
|
16647
|
+
`${when} \xB7 ${parts.join(" \xB7 ")} \xB7 ${sign}${e.amount_krw.toLocaleString("ko-KR")}\uC6D0 (\uC794\uC561 ${e.balance_after_krw.toLocaleString("ko-KR")}\uC6D0)`
|
|
16648
|
+
);
|
|
16649
|
+
}
|
|
16650
|
+
if (out3.next_before_id != null) {
|
|
16651
|
+
lines.push("", `\uB354 \uC788\uC2B5\uB2C8\uB2E4 \u2014 before_id=${out3.next_before_id} \uB85C \uB2E4\uC2DC \uD638\uCD9C\uD558\uC138\uC694.`);
|
|
16652
|
+
}
|
|
16653
|
+
return { text: lines.join("\n") };
|
|
16654
|
+
});
|
|
16655
|
+
}
|
|
16656
|
+
function projectLine(p) {
|
|
16657
|
+
const parts = [p.slug ?? "?", p.title || "(\uC81C\uBAA9 \uC5C6\uC74C)"];
|
|
16658
|
+
if (p.status) parts.push(p.status);
|
|
16659
|
+
if (p.kind === "shorts") parts.push("shorts");
|
|
16660
|
+
const updated = (p.updated_at ?? "").slice(0, 10);
|
|
16661
|
+
if (updated) parts.push(updated);
|
|
16662
|
+
return parts.join(" \xB7 ");
|
|
16663
|
+
}
|
|
16664
|
+
function listProjects(a = {}, deps = {}) {
|
|
16665
|
+
return guarded2(READ_ONLY, async () => {
|
|
16666
|
+
if (a.limit !== void 0 && !Number.isFinite(a.limit)) {
|
|
16667
|
+
return { isError: true, text: `limit \uC740 \uC22B\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4: ${JSON.stringify(a.limit)}` };
|
|
16668
|
+
}
|
|
16669
|
+
const limit = Math.max(
|
|
16670
|
+
1,
|
|
16671
|
+
Math.min(Math.trunc(a.limit ?? PROJECTS_DEFAULT_LIMIT), PROJECTS_MAX_LIMIT)
|
|
16672
|
+
);
|
|
16673
|
+
const query = (a.query ?? "").trim().toLowerCase();
|
|
16674
|
+
const base = resolveBaseUrl(deps.baseUrl);
|
|
16675
|
+
const out3 = await list(base, deps);
|
|
16676
|
+
const all = out3.projects ?? [];
|
|
16677
|
+
const total = all.length;
|
|
16678
|
+
const matched = query ? all.filter(
|
|
16679
|
+
(p) => (p.slug ?? "").toLowerCase().includes(query) || (p.title ?? "").toLowerCase().includes(query)
|
|
16680
|
+
) : all.slice();
|
|
16681
|
+
matched.sort((x, y) => (y.updated_at ?? "").localeCompare(x.updated_at ?? ""));
|
|
16682
|
+
const shown = matched.slice(0, limit);
|
|
16683
|
+
if (shown.length === 0) {
|
|
16684
|
+
return {
|
|
16685
|
+
text: query ? `'${query}' \uC640 \uC77C\uCE58\uD558\uB294 \uD504\uB85C\uC81D\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. (\uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC5D0 \uD504\uB85C\uC81D\uD2B8 ${total}\uAC1C) query \uB97C \uBE7C\uACE0 \uB2E4\uC2DC \uD638\uCD9C\uD574 \uC804\uCCB4\uB97C \uBCF4\uC138\uC694.` : "\uC774 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4\uC5D0\uB294 \uC544\uC9C1 \uD504\uB85C\uC81D\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uC5D0\uAC8C democut.ai \uC5D0\uC11C \uD504\uB85C\uC81D\uD2B8\uB97C \uD558\uB098 \uB9CC\uB4E0 \uB4A4 \uB2E4\uC2DC \uC694\uCCAD\uD574 \uB2EC\uB77C\uACE0 \uC54C\uB9AC\uC138\uC694 \u2014 \uB124\uAC00 \uC9C1\uC811 \uB9CC\uB4E4 \uC218\uB294 \uC5C6\uC2B5\uB2C8\uB2E4. \uC601\uC0C1 \uC0DD\uC131\uC740 \uADC0\uC18D\uC2DC\uD0AC \uD504\uB85C\uC81D\uD2B8\uAC00 \uC788\uC5B4\uC57C \uD569\uB2C8\uB2E4."
|
|
16686
|
+
};
|
|
16687
|
+
}
|
|
16688
|
+
const lines = ["\uD504\uB85C\uC81D\uD2B8 (\uCD5C\uADFC \uC218\uC815\uC21C) \u2014 slug \xB7 \uC81C\uBAA9 \xB7 \uC0C1\uD0DC \xB7 \uC218\uC815\uC77C", ""];
|
|
16689
|
+
for (const p of shown) lines.push(projectLine(p));
|
|
16690
|
+
lines.push("");
|
|
16691
|
+
if (matched.length > shown.length) {
|
|
16692
|
+
lines.push(
|
|
16693
|
+
`\uCD1D ${matched.length}\uAC1C \uC911 ${shown.length}\uAC1C\uB9CC \uD45C\uC2DC\uD588\uC2B5\uB2C8\uB2E4 \u2014 limit \uC744 \uC62C\uB9AC\uAC70\uB098 query \uB85C \uC881\uD788\uC138\uC694.`
|
|
16694
|
+
);
|
|
16695
|
+
}
|
|
16696
|
+
lines.push(
|
|
16697
|
+
"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."
|
|
16698
|
+
);
|
|
16699
|
+
return { text: lines.join("\n") };
|
|
16700
|
+
});
|
|
16701
|
+
}
|
|
16702
|
+
function createProject(a = {}, deps = {}) {
|
|
16703
|
+
return guarded2(READ_ONLY, async () => {
|
|
16704
|
+
const title = (a.title ?? "").trim();
|
|
16705
|
+
if (!title) {
|
|
16706
|
+
return {
|
|
16707
|
+
isError: true,
|
|
16708
|
+
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."
|
|
16709
|
+
};
|
|
16710
|
+
}
|
|
16711
|
+
const base = resolveBaseUrl(deps.baseUrl);
|
|
16712
|
+
const voiceId = await defaultVoiceId(base, deps);
|
|
16713
|
+
const p = await create(
|
|
16714
|
+
base,
|
|
16715
|
+
{ title, voice_id: voiceId, external_ref: `mcp:project:${title}` },
|
|
16716
|
+
deps
|
|
16717
|
+
);
|
|
16718
|
+
return {
|
|
16719
|
+
text: [
|
|
16720
|
+
`\uD504\uB85C\uC81D\uD2B8 \uC900\uBE44\uB428 \u2014 slug: ${p.slug}`,
|
|
16721
|
+
`\uC81C\uBAA9: ${p.title}`,
|
|
16722
|
+
"",
|
|
16723
|
+
"democut_generate_video \uC758 project_slug \uC5D0 \uC704 slug \uB97C \uADF8\uB300\uB85C \uB123\uC73C\uC138\uC694.",
|
|
16724
|
+
"\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."
|
|
16725
|
+
].join("\n")
|
|
16726
|
+
};
|
|
16727
|
+
});
|
|
16728
|
+
}
|
|
16438
16729
|
|
|
16439
16730
|
// src/mcp/server.ts
|
|
16440
16731
|
var RESOLUTIONS = ["480p", "720p", "1080p", "4k"];
|
|
@@ -16451,7 +16742,7 @@ var GENERATION_PARAMS = {
|
|
|
16451
16742
|
var TOOLS = [
|
|
16452
16743
|
{
|
|
16453
16744
|
name: "democut_auth_status",
|
|
16454
|
-
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 '\
|
|
16745
|
+
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.",
|
|
16455
16746
|
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
16456
16747
|
},
|
|
16457
16748
|
{
|
|
@@ -16465,7 +16756,7 @@ var TOOLS = [
|
|
|
16465
16756
|
},
|
|
16466
16757
|
{
|
|
16467
16758
|
name: "democut_generate_video",
|
|
16468
|
-
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.",
|
|
16759
|
+
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.",
|
|
16469
16760
|
inputSchema: {
|
|
16470
16761
|
type: "object",
|
|
16471
16762
|
properties: {
|
|
@@ -16483,25 +16774,81 @@ var TOOLS = [
|
|
|
16483
16774
|
},
|
|
16484
16775
|
generate_audio: { type: "boolean", description: "\uC624\uB514\uC624 \uD568\uAED8 \uC0DD\uC131. \uAE30\uBCF8 false." },
|
|
16485
16776
|
watermark: { type: "boolean", description: "\uC6CC\uD130\uB9C8\uD06C. \uAE30\uBCF8 false." },
|
|
16486
|
-
project_slug: {
|
|
16777
|
+
project_slug: {
|
|
16778
|
+
type: "string",
|
|
16779
|
+
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."
|
|
16780
|
+
}
|
|
16487
16781
|
},
|
|
16488
|
-
required: ["prompt", "confirmed_cost_usd"],
|
|
16782
|
+
required: ["prompt", "confirmed_cost_usd", "project_slug"],
|
|
16489
16783
|
additionalProperties: false
|
|
16490
16784
|
}
|
|
16491
16785
|
},
|
|
16492
16786
|
{
|
|
16493
16787
|
name: "democut_get_video_status",
|
|
16494
|
-
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. \uC0B0\uCD9C\uBB3C
|
|
16788
|
+
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.",
|
|
16495
16789
|
inputSchema: {
|
|
16496
16790
|
type: "object",
|
|
16497
16791
|
properties: {
|
|
16498
16792
|
job_id: { type: "string", description: "democut_generate_video \uAC00 \uB3CC\uB824\uC900 job_id." },
|
|
16499
16793
|
output_path: { type: "string", description: "\uC800\uC7A5\uD560 \uB85C\uCEEC \uACBD\uB85C(\uC808\uB300\uACBD\uB85C \uAD8C\uC7A5)." },
|
|
16500
|
-
project_slug: {
|
|
16794
|
+
project_slug: {
|
|
16795
|
+
type: "string",
|
|
16796
|
+
description: "(\uBB34\uC2DC\uB428) \uADC0\uC18D\uC740 \uC81C\uCD9C \uC2DC\uC810 \uAC12\uC73C\uB85C \uC11C\uBC84\uAC00 \uACB0\uC815\uD55C\uB2E4."
|
|
16797
|
+
}
|
|
16501
16798
|
},
|
|
16502
16799
|
required: ["job_id"],
|
|
16503
16800
|
additionalProperties: false
|
|
16504
16801
|
}
|
|
16802
|
+
},
|
|
16803
|
+
{
|
|
16804
|
+
name: "democut_credit_balance",
|
|
16805
|
+
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.",
|
|
16806
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
16807
|
+
},
|
|
16808
|
+
{
|
|
16809
|
+
name: "democut_credit_ledger",
|
|
16810
|
+
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.',
|
|
16811
|
+
inputSchema: {
|
|
16812
|
+
type: "object",
|
|
16813
|
+
properties: {
|
|
16814
|
+
limit: { type: "number", description: "\uAC00\uC838\uC62C \uAC74\uC218 1~200. \uAE30\uBCF8 10." },
|
|
16815
|
+
before_id: {
|
|
16816
|
+
type: "number",
|
|
16817
|
+
description: "\uC774\uC804 \uD638\uCD9C\uC774 \uB3CC\uB824\uC900 next_before_id. \uB2E4\uC74C \uD398\uC774\uC9C0\uB97C \uBCFC \uB54C\uB9CC \uB123\uC5B4\uB77C."
|
|
16818
|
+
}
|
|
16819
|
+
},
|
|
16820
|
+
additionalProperties: false
|
|
16821
|
+
}
|
|
16822
|
+
},
|
|
16823
|
+
{
|
|
16824
|
+
name: "democut_list_projects",
|
|
16825
|
+
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.",
|
|
16826
|
+
inputSchema: {
|
|
16827
|
+
type: "object",
|
|
16828
|
+
properties: {
|
|
16829
|
+
limit: { type: "number", description: "\uAC00\uC838\uC62C \uAC74\uC218 1~100. \uAE30\uBCF8 30." },
|
|
16830
|
+
query: {
|
|
16831
|
+
type: "string",
|
|
16832
|
+
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."
|
|
16833
|
+
}
|
|
16834
|
+
},
|
|
16835
|
+
additionalProperties: false
|
|
16836
|
+
}
|
|
16837
|
+
},
|
|
16838
|
+
{
|
|
16839
|
+
name: "democut_create_project",
|
|
16840
|
+
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).",
|
|
16841
|
+
inputSchema: {
|
|
16842
|
+
type: "object",
|
|
16843
|
+
properties: {
|
|
16844
|
+
title: {
|
|
16845
|
+
type: "string",
|
|
16846
|
+
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."
|
|
16847
|
+
}
|
|
16848
|
+
},
|
|
16849
|
+
required: ["title"],
|
|
16850
|
+
additionalProperties: false
|
|
16851
|
+
}
|
|
16505
16852
|
}
|
|
16506
16853
|
];
|
|
16507
16854
|
function dispatch(name, args, deps = {}) {
|
|
@@ -16514,6 +16861,14 @@ function dispatch(name, args, deps = {}) {
|
|
|
16514
16861
|
return generateVideo(args, deps);
|
|
16515
16862
|
case "democut_get_video_status":
|
|
16516
16863
|
return videoStatus(args, deps);
|
|
16864
|
+
case "democut_credit_balance":
|
|
16865
|
+
return creditBalance(deps);
|
|
16866
|
+
case "democut_credit_ledger":
|
|
16867
|
+
return creditLedger(args, deps);
|
|
16868
|
+
case "democut_list_projects":
|
|
16869
|
+
return listProjects(args, deps);
|
|
16870
|
+
case "democut_create_project":
|
|
16871
|
+
return createProject(args, deps);
|
|
16517
16872
|
default:
|
|
16518
16873
|
return Promise.resolve({ isError: true, text: `\uC54C \uC218 \uC5C6\uB294 \uB3C4\uAD6C: ${name}` });
|
|
16519
16874
|
}
|
|
@@ -16549,11 +16904,12 @@ var HELP = `democut \u2014 DemoCut \uC5D0\uC774\uC804\uD2B8 CLI (OAuth2 device f
|
|
|
16549
16904
|
democut auth logout [--base-url <url>]
|
|
16550
16905
|
|
|
16551
16906
|
democut video estimate [--duration <\uCD08>] [--resolution <\uD574\uC0C1\uB3C4>] [--ratio <\uBE44\uC728>] [--model <id>]
|
|
16552
|
-
democut video generate "<\uD504\uB86C\uD504\uD2B8>" [--yes] [--wait] [--output <\uACBD\uB85C>] [\uC0DD\uC131 \uC635\uC158\u2026]
|
|
16553
|
-
democut video status <job_id> [--wait] [--output <\uACBD\uB85C>]
|
|
16907
|
+
democut video generate "<\uD504\uB86C\uD504\uD2B8>" --project <slug> [--yes] [--wait] [--output <\uACBD\uB85C>] [\uC0DD\uC131 \uC635\uC158\u2026]
|
|
16908
|
+
democut video status <job_id> [--wait] [--output <\uACBD\uB85C>]
|
|
16554
16909
|
|
|
16555
16910
|
democut mcp MCP \uC11C\uBC84(stdio) \u2014 \uC5D0\uC774\uC804\uD2B8\uC5D0 \uB3C4\uAD6C\uB85C \uBD99\uC778\uB2E4
|
|
16556
|
-
\uB4F1\uB85D: claude mcp add democut -- democut mcp
|
|
16911
|
+
\uB4F1\uB85D: claude mcp add democut -- npx -y democut@latest mcp
|
|
16912
|
+
(@latest \uD544\uC218 \u2014 -y \uB294 npx \uCE90\uC2DC\uC758 \uC61B \uBC84\uC804\uC744 \uADF8\uB300\uB85C \uB744\uC6B4\uB2E4)
|
|
16557
16913
|
|
|
16558
16914
|
\uC0DD\uC131 \uC635\uC158:
|
|
16559
16915
|
--duration <\uCD08> \uAE30\uBCF8 5 (\uBAA8\uB378\uBCC4 \uD5C8\uC6A9 \uBC94\uC704 \uB2E4\uB984: 2.0=4~15, 2.5=4~30)
|
|
@@ -16564,13 +16920,13 @@ var HELP = `democut \u2014 DemoCut \uC5D0\uC774\uC804\uD2B8 CLI (OAuth2 device f
|
|
|
16564
16920
|
--image-url <url> image\u2192video \uCC38\uC870 (\uACF5\uAC1C HTTPS URL, \uCD5C\uB300 4\uD68C \uBC18\uBCF5)
|
|
16565
16921
|
--audio \uC624\uB514\uC624 \uD568\uAED8 \uC0DD\uC131
|
|
16566
16922
|
--watermark \uC6CC\uD130\uB9C8\uD06C \uB123\uAE30
|
|
16567
|
-
--project <slug> \uBE44\uC6A9\uC744 \uC774 \uD504\uB85C\uC81D\uD2B8\uB85C \uADC0\uC18D
|
|
16923
|
+
--project <slug> \uBE44\uC6A9\uC744 \uC774 \uD504\uB85C\uC81D\uD2B8\uB85C \uADC0\uC18D (generate \uD544\uC218 \u2014 \uBCF8\uC778 \uC18C\uC720 \uC2AC\uB7EC\uADF8)
|
|
16568
16924
|
|
|
16569
16925
|
\uACF5\uD1B5 \uC635\uC158:
|
|
16570
16926
|
-y, --yes \uBE44\uC6A9 \uD655\uC778 \uC5C6\uC774 \uC9C4\uD589 (\uBE44\uB300\uD654\uD615\uC5D0\uC11C\uB294 \uD544\uC218)
|
|
16571
16927
|
--wait \uC644\uB8CC\uAE4C\uC9C0 \uAE30\uB2E4\uB9BC
|
|
16572
16928
|
--timeout <\uCD08> --wait \uC2DC\uD55C (\uAE30\uBCF8 900)
|
|
16573
|
-
-o, --output <\uACBD\uB85C> \uC0B0\uCD9C\uBB3C \uC800\uC7A5 (\uC11C\
|
|
16929
|
+
-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)
|
|
16574
16930
|
--json \uAE30\uACC4 \uD310\uB3C5\uC6A9 JSON \uD55C \uC904
|
|
16575
16931
|
--base-url <u> DemoCut \uC11C\uBC84 URL (\uAE30\uBCF8: $DEMOCUT_BASE_URL \uB610\uB294 prod)
|
|
16576
16932
|
-h, --help \uB3C4\uC6C0\uB9D0
|