@clack-platform/cli 0.3.0 → 0.3.1
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 +3 -1
- package/dist/cli.js +34 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -183,7 +183,7 @@ ZIP에 `clack.content.json` 또는 `.clack/`가 있으면 업로드 전에 선
|
|
|
183
183
|
|
|
184
184
|
`content update`는 제목·설명·종류·썸네일·메타데이터·태그를 서버 PATCH와 같은 규칙으로 수정합니다(`--title`, `--description`, `--kind`, `--thumbnail-id <썸네일 작업 ID|none>`, `--metadata-mode single|localized`, `--metadata-lang ko|en|none`, `--localized-metadata '<JSON>'|none`, `--tags 쉼표목록`). 지정한 필드만 바뀌고 `--tags`·`--localized-metadata`는 통째 교체됩니다. 단일 메타데이터 모드에서는 제목을 비우면 「제목 없는 콘텐츠」로 표시되고, 언어별(`localized`) 모드에서는 빈 제목을 서버가 거부합니다(400). 썸네일 작업 ID는 `POST /v4/creator/thumbnails` 등으로 발급하며 CLI에는 썸네일 업로드 명령이 없어 보통 `none`(기본 이미지로 되돌리기)만 씁니다. 언어별 메타데이터·태그는 서버 게이트가 켜진 환경에서만 쓸 수 있습니다. 인트로 저장은 개인 액세스 토큰으로 할 수 없어 크리에이터 센터에서만 합니다.
|
|
185
185
|
|
|
186
|
-
`content info-version <콘텐츠-UUID> <버전-UUID>`는 승인·반려된 버전의 번들을 재사용해 바뀐 콘텐츠 정보만 담은 새 초안 버전을 만듭니다(새로 만들면 201,
|
|
186
|
+
`content info-version <콘텐츠-UUID> <버전-UUID>`는 승인·반려된 버전의 번들을 재사용해 바뀐 콘텐츠 정보만 담은 새 초안 버전을 만듭니다(새로 만들면 201, 같은 정보의 미게시 버전(초안·심사 중·승인 미게시)이 있으면 200이며 응답의 `created`로 구분). 새 버전은 앱 확인과 심사를 다시 받아야 합니다. 서버 게이트가 꺼진 환경에서는 `CONTENT_INFO_VERSION_DISABLED`(409)가 반환되며 `clack content config`의 `info_version.enabled`로 확인할 수 있습니다.
|
|
187
187
|
|
|
188
188
|
```bash
|
|
189
189
|
clack content update --env dev <콘텐츠-UUID> --title "새 제목" --tags 여행,사진
|
|
@@ -357,6 +357,8 @@ clack page status PAGE_ID
|
|
|
357
357
|
- 업로드: `{"action":"upload","session_id":"UUID","field":"plates","item_index":0,"file":"./portrait.png"}`. 응답 자산 ID를 `plates[0].asset_id`로 저장한다.
|
|
358
358
|
- 견적: `{"action":"quote","session_id":"UUID"}`. 생성은 `action:"image"` 또는 `"image-batch"`, `form_revision`·`asset_slot`·`approved_price_cash`·`idempotency_key`와 `item_index` 또는 `item_indexes`를 보낸다. 같은 요청의 재시도에는 같은 키를 사용한다.
|
|
359
359
|
- 가져오기: `{"action":"import","session_id":"UUID","field":"portrait_source","content_id":"UUID","revision":0}`. 본인 콘텐츠에서 매니페스트가 내보내도록 선언한 값만 복사한다.
|
|
360
|
+
- 종료(CLI 0.3.1 이상): `clack authoring complete <세션-UUID> --env dev` 또는 `clack authoring abandon <세션-UUID> --env dev --yes`. JSON 입력은 `{"action":"complete","session_id":"UUID"}`·`{"action":"abandon","session_id":"UUID"}`이며 포기는 비대화형에서 `--yes`가 필요하다. 로컬 MCP는 같은 action을 사용하고 abandon에 `confirm:true`를 지정한다.
|
|
361
|
+
- 완료·포기는 폼(template) 세션만 PAT로 가능하다. 에디터·지침형 스킬의 생성·종료는 403 `SESSION_REQUIRED`이므로 센터에서 작업한다. 본인 세션이 없으면 404 `AUTHORING_NOT_FOUND`다. complete는 현재 revision을 package한 뒤 가능하며(409 `AUTHORING_NOT_PACKAGED`), 종료 재호출은 409 `AUTHORING_SESSION_LOCKED`다. 종료 응답의 `data.status`를 확인한다. 포기해도 기존 콘텐츠는 유지되며 게시·심사는 별도다. 응답 유실 때는 get으로 상태를 조회하고 변경 요청을 자동 재시도하지 않는다.
|
|
360
362
|
- AI 채우기는 `fill-quote` → `fill` → `fill-status`, 자산 목록은 `assets`, 이미지 작업 조회는 `tool`, 폼 검증은 `validate`를 사용한다.
|
|
361
363
|
|
|
362
364
|
`image_list` 값은 `[{"asset_id":"UUID","scene":"장면","pose":"구도","mood":"분위기","aspect":"1:1"}]`이며 한 번에 최대 8장, 콘텐츠당 최대 24장을 사용한다. 스킬의 `max_calls`와 플랫폼 설정 중 작은 한도를 적용한다. 참조 이미지 생성은 공급자 검증 전 비활성이며 현재 외모·화풍·팔레트 텍스트로 동일성을 안내한다.
|
package/dist/cli.js
CHANGED
|
@@ -34,6 +34,9 @@ function apiError(status, body, retryAfter) {
|
|
|
34
34
|
let message = typeof value2.message === "string" ? value2.message : `\uC694\uCCAD\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4 (${status}).`;
|
|
35
35
|
if (status === 401 && code === "SERVER_KEY_INVALID") message += " \uC13C\uD130\uC5D0\uC11C \uC11C\uBC84 \uD0A4 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uAC70\uB098 \uC0C8\uB85C \uBC1C\uAE09\xB7\uD68C\uC804\uD558\uC138\uC694.";
|
|
36
36
|
else if (status === 401) message += " clack login\uC73C\uB85C \uB2E4\uC2DC \uC5F0\uACB0\uD558\uC138\uC694.";
|
|
37
|
+
if (code === "SESSION_REQUIRED") message += " \uC5D0\uB514\uD130\xB7\uC9C0\uCE68\uD615 \uC2A4\uD0AC\uC740 \uD06C\uB9AC\uC5D0\uC774\uD130 \uC13C\uD130\uC5D0\uC11C \uC791\uC5C5\uD558\uC138\uC694. \uD3FC \uC138\uC158\uB9CC PAT\uB85C \uB9CC\uB4E4\uACE0 \uB05D\uB0BC \uC218 \uC788\uC2B5\uB2C8\uB2E4.";
|
|
38
|
+
if (code === "AUTHORING_NOT_PACKAGED") message += " JSON action:package\uB97C clack authoring --input <\uD30C\uC77C>\uB85C \uC2E4\uD589\uD55C \uB4A4 authoring complete <\uC138\uC158-ID>\uB97C \uC2E4\uD589\uD558\uC138\uC694.";
|
|
39
|
+
if (code === "AUTHORING_SESSION_LOCKED") message += " JSON action:get\uC744 clack authoring --input <\uD30C\uC77C>\uB85C \uC2E4\uD589\uD574 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uC138\uC694. \uC774\uBBF8 \uC885\uB8CC\uB41C \uC138\uC158\uC740 \uB2E4\uC2DC \uD3B8\uC9D1\uD558\uAC70\uB098 \uC885\uB8CC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.";
|
|
37
40
|
if (code === "IDENTITY_VERIFICATION_REQUIRED") message += " \uC571\uC5D0\uC11C \uBCF8\uC778\uC778\uC99D\uC744 \uC644\uB8CC\uD558\uC138\uC694.";
|
|
38
41
|
if (code === "SCOPE_DENIED") message += " \uD544\uC694\uD55C \uAD8C\uD55C\uC73C\uB85C \uD1A0\uD070\uC744 \uB2E4\uC2DC \uBC1C\uAE09\uD558\uC138\uC694.";
|
|
39
42
|
if (code === "SKILL_VERSION_MAJOR_REQUIRED") {
|
|
@@ -153,7 +156,7 @@ function redact(value2) {
|
|
|
153
156
|
// package.json
|
|
154
157
|
var package_default = {
|
|
155
158
|
name: "@clack-platform/cli",
|
|
156
|
-
version: "0.3.
|
|
159
|
+
version: "0.3.1",
|
|
157
160
|
description: "\uD074\uB799 \uACC4\uC815\uC758 \uC0C1\uD488\xB7\uCF58\uD150\uCE20\xB7\uD504\uB85C\uD544\uC744 \uAD00\uB9AC\uD558\uB294 CLI",
|
|
158
161
|
type: "module",
|
|
159
162
|
bin: {
|
|
@@ -580,7 +583,9 @@ var authoringInput = z2.discriminatedUnion("action", [
|
|
|
580
583
|
z2.strictObject({ action: z2.literal("tool"), ...session, call_id: z2.uuid() }),
|
|
581
584
|
z2.strictObject({ action: z2.literal("fill"), ...session, revision: revision2, fields: z2.array(field).max(60).optional(), instruction: z2.string().max(4e3).optional(), tier: z2.enum(["economy", "performance"]).optional() }),
|
|
582
585
|
z2.strictObject({ action: z2.literal("fill-status"), ...session, job_id: z2.uuid() }),
|
|
583
|
-
z2.strictObject({ action: z2.literal("package"), ...session, revision: revision2 })
|
|
586
|
+
z2.strictObject({ action: z2.literal("package"), ...session, revision: revision2 }),
|
|
587
|
+
z2.strictObject({ action: z2.literal("complete"), ...session }),
|
|
588
|
+
z2.strictObject({ action: z2.literal("abandon"), ...session, confirm: z2.boolean().optional() })
|
|
584
589
|
]);
|
|
585
590
|
async function authoringRequest(client, raw, surface = "cli") {
|
|
586
591
|
const result = authoringInput.safeParse(raw);
|
|
@@ -592,6 +597,9 @@ async function authoringRequest(client, raw, surface = "cli") {
|
|
|
592
597
|
return client.request("POST", base2, { body: { ...body2, surface } });
|
|
593
598
|
}
|
|
594
599
|
const path = `${base2}/${input.session_id}`;
|
|
600
|
+
if (input.action === "complete" || input.action === "abandon") {
|
|
601
|
+
return client.request("POST", `${path}/complete`, { body: { outcome: input.action === "complete" ? "completed" : "abandoned" } });
|
|
602
|
+
}
|
|
595
603
|
if (input.action === "get") return client.request("GET", path);
|
|
596
604
|
if (input.action === "assets") return client.request("GET", `${path}/assets`);
|
|
597
605
|
if (input.action === "quote") return client.request("GET", `${path}/tools/image.generate/quote`);
|
|
@@ -620,16 +628,27 @@ async function authoringRequest(client, raw, surface = "cli") {
|
|
|
620
628
|
return client.request(action === "save" ? "PATCH" : "POST", `${path}/${action === "save" ? "form" : action}`, { body });
|
|
621
629
|
}
|
|
622
630
|
function registerAuthoringCommands(program2, runtime2) {
|
|
623
|
-
|
|
624
|
-
|
|
631
|
+
const command = program2.command("authoring").description("\uC2A4\uD0AC \uC81C\uC791\xB7\uD328\uD0A4\uC9D5\xB7\uD3FC \uC138\uC158 \uC644\uB8CC/\uD3EC\uAE30 (creator-content:write)").option("--input <file>", "action\uACFC \uC694\uCCAD \uAC12\uC774 \uC788\uB294 JSON \uD30C\uC77C").addHelpText("after", "\n\uD3FC \uC138\uC158\uB9CC PAT\uB85C \uC644\uB8CC\xB7\uD3EC\uAE30\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uC5D0\uB514\uD130\xB7\uC9C0\uCE68\uD615\uC740 \uC13C\uD130\uC5D0\uC11C \uC791\uC5C5\uD558\uC138\uC694.\ncomplete\uB294 \uD604\uC7AC revision\uC744 package\uD55C \uB4A4 \uC0AC\uC6A9\uD569\uB2C8\uB2E4. \uC885\uB8CC \uC7AC\uD638\uCD9C\uC740 AUTHORING_SESSION_LOCKED\uC785\uB2C8\uB2E4.");
|
|
632
|
+
const run = async (ctx, raw) => {
|
|
633
|
+
const parsed = authoringInput.safeParse(raw);
|
|
634
|
+
if (!parsed.success) throw new CliError("\uC81C\uC791 \uC791\uC5C5 \uC785\uB825 \uD615\uC2DD\uC744 \uD655\uC778\uD558\uC138\uC694.", "VALIDATION_ERROR");
|
|
625
635
|
if (ctx.options.dryRun) {
|
|
626
|
-
const parsed = authoringInput.safeParse(input);
|
|
627
|
-
if (!parsed.success) throw new CliError("\uC81C\uC791 \uC791\uC5C5 \uC785\uB825 \uD615\uC2DD\uC744 \uD655\uC778\uD558\uC138\uC694.");
|
|
628
636
|
ctx.output({ dry_run: true, input: parsed.data });
|
|
629
637
|
return;
|
|
630
638
|
}
|
|
631
|
-
|
|
639
|
+
if (parsed.data.action === "abandon") await ctx.confirm(`\uC81C\uC791 \uC138\uC158 ${parsed.data.session_id}\uC744 \uD3EC\uAE30\uD569\uB2C8\uB2E4. \uC774\uD6C4 \uD3B8\uC9D1\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uAE30\uC874 \uCF58\uD150\uCE20\uB294 \uC720\uC9C0\uB429\uB2C8\uB2E4.`);
|
|
640
|
+
ctx.output(await authoringRequest(ctx.api, parsed.data));
|
|
641
|
+
};
|
|
642
|
+
runtime2.action(command, async (ctx, _args, opts) => {
|
|
643
|
+
if (!opts.input) throw new CliError("--input <file> \uB610\uB294 complete/abandon <session-id>\uB97C \uC9C0\uC815\uD558\uC138\uC694.");
|
|
644
|
+
await run(ctx, await readPlatformBodyFile(opts.input));
|
|
632
645
|
});
|
|
646
|
+
for (const action of ["complete", "abandon"]) {
|
|
647
|
+
runtime2.action(command.command(`${action} <session-id>`).description(action === "complete" ? "\uD604\uC7AC \uD328\uD0A4\uC9D5\uB41C \uD3FC \uC138\uC158\uC744 \uC644\uC131 \uC0C1\uD0DC\uB85C \uC885\uB8CC" : "\uD3FC \uC138\uC158 \uD3EC\uAE30 (\uBE44\uB300\uD654\uD615 \uC2E4\uD589\uC740 --yes \uD544\uC694)"), async (ctx, args, opts) => {
|
|
648
|
+
if (opts.input) throw new CliError("\uD558\uC704 \uBA85\uB839\uACFC --input\uC744 \uD568\uAED8 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
649
|
+
await run(ctx, { action, session_id: args[0] });
|
|
650
|
+
});
|
|
651
|
+
}
|
|
633
652
|
}
|
|
634
653
|
|
|
635
654
|
// src/cli.ts
|
|
@@ -5773,7 +5792,7 @@ function parsePat(schema, input, label) {
|
|
|
5773
5792
|
return parsed.data;
|
|
5774
5793
|
}
|
|
5775
5794
|
var toolDefinitions = [
|
|
5776
|
-
{ name: "platform_authoring", description: "\uACF5\uAC1C \uC2A4\uD0AC \uC81C\uC791 \uC138\uC158\xB7\uD3FC\xB7\uC790\uC0B0\xB7\uC774\uBBF8\uC9C0 \uC0DD\uC131\xB7\uD328\uD0A4\uC9D5\
|
|
5795
|
+
{ name: "platform_authoring", description: "\uACF5\uAC1C \uC2A4\uD0AC \uC81C\uC791 \uC138\uC158\xB7\uD3FC\xB7\uC790\uC0B0\xB7\uC774\uBBF8\uC9C0 \uC0DD\uC131\xB7\uD328\uD0A4\uC9D5\xB7\uC644\uB8CC\xB7\uD3EC\uAE30\uB97C \uCC98\uB9AC\uD569\uB2C8\uB2E4. complete/abandon\uC740 \uD3FC \uC138\uC158 \uC804\uC6A9\uC774\uBA70 complete\uB294 \uD604\uC7AC revision \uD328\uD0A4\uC9D5, abandon\uC740 confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC5D0\uB514\uD130\xB7\uC9C0\uCE68\uD615\uC740 \uC13C\uD130\uC5D0\uC11C \uC791\uC5C5\uD569\uB2C8\uB2E4. \uC774\uBBF8\uC9C0 \uC0DD\uC131\uC5D0\uB294 \uACAC\uC801 \uC2B9\uC778 \uAC00\uACA9\uACFC \uBA71\uB4F1\uC131 \uD0A4\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. creator-content:write \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.", inputSchema: { type: "object", ...z10.toJSONSchema(authoringInput) }, annotations: { readOnlyHint: false, destructiveHint: true } },
|
|
5777
5796
|
{
|
|
5778
5797
|
name: "platform_usage_get",
|
|
5779
5798
|
description: "\uC11C\uBC84 \uD0A4\uAC00 \uC18D\uD55C \uCF58\uD150\uCE20\uC758 \uD50C\uB7AB\uD3FC \uC0AC\uC6A9\uB7C9\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
|
|
@@ -5965,8 +5984,14 @@ var PlatformMcpServer = class {
|
|
|
5965
5984
|
if (patDestructiveToolNames.has(name2) && (!isObject3(args) || args.confirm !== true)) {
|
|
5966
5985
|
return { preview: true, confirmation_required: true, tool: name2, arguments: redact(args) };
|
|
5967
5986
|
}
|
|
5987
|
+
if (name2 === "platform_authoring") {
|
|
5988
|
+
const input = parsePat(authoringInput, args, "\uC81C\uC791 \uC791\uC5C5 \uC785\uB825");
|
|
5989
|
+
if (input.action === "abandon" && input.confirm !== true) {
|
|
5990
|
+
return { preview: true, confirmation_required: true, tool: name2, arguments: redact(input) };
|
|
5991
|
+
}
|
|
5992
|
+
return authoringRequest(platformPatClient(this.settings, this.env), input, "mcp");
|
|
5993
|
+
}
|
|
5968
5994
|
const client = platformPatClient(this.settings, this.env);
|
|
5969
|
-
if (name2 === "platform_authoring") return authoringRequest(client, args, "mcp");
|
|
5970
5995
|
if (name2 === "platform_skill_list") {
|
|
5971
5996
|
const { q } = parsePat(patSchemas.skillList, args, "\uC2A4\uD0AC \uBAA9\uB85D \uC870\uD68C \uC785\uB825");
|
|
5972
5997
|
return client.request("GET", "/v4/skills", { query: { q } });
|