@clack-platform/cli 0.3.2 → 0.3.3
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 +5 -2
- package/dist/cli.js +361 -189
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -149,7 +149,7 @@ pnpm check # typecheck → 스키마 동기화 확인 → 테스트 →
|
|
|
149
149
|
npm pack --dry-run
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
-
`pnpm check`는 나란히 체크아웃한 클랙 모노레포가 있으면(`CLACK_MONOREPO_DIR`, 기본 `../clack`) MCP 입력 스키마 일치도 함께 확인하고, 없으면 건너뛴다. 배포 전 로컬에서 이 확인을 강제하려면 `pnpm check:release`를
|
|
152
|
+
`pnpm check`는 나란히 체크아웃한 클랙 모노레포가 있으면(`CLACK_MONOREPO_DIR`, 기본 `../clack`) MCP 입력 스키마 일치도 함께 확인하고, 없으면 건너뛴다. 배포 전 로컬에서 이 확인을 강제하려면 `pnpm check:release`를 쓴다(스키마 일치 엄격 검사와 `src/vendor/` 사본 `sync-vendor-types.mjs --check`를 함께 실행한다). `scripts/sync-vendor-types.mjs [--check]`는 `src/vendor/` 아래 복사해 둔 클랙 공개 타입·계약 파일을 같은 방식으로 모노레포와 동기화한다.
|
|
153
153
|
|
|
154
154
|
GitHub Actions는 Linux·macOS·Windows × Node 20·22에서 `pnpm check`와 패키지 설치 스모크를 실행한다(`.github/workflows/ci.yml`). 배포는 `v0.1.0` 형태의 버전 태그를 push하면 `.github/workflows/publish.yml`이 태그와 `package.json` 버전 일치를 확인한 뒤 GitHub Actions의 OIDC 신뢰 게시로 npm에 공개한다.
|
|
155
155
|
|
|
@@ -181,11 +181,14 @@ clack content preview --env dev <콘텐츠-UUID> <버전-UUID>
|
|
|
181
181
|
|
|
182
182
|
ZIP에 `clack.content.json` 또는 `.clack/`가 있으면 업로드 전에 선언·경로·크기와 프로필 파일 대응을 확인하고 표준 오류에 경고합니다. 선언이 없는 기존 정적 ZIP도 계속 업로드할 수 있습니다. 경고는 업로드를 막지 않으며 서버의 최종 검증·심사 결과를 대신하지 않습니다. 전송 없이 확인하려면 `content upload ... --dry-run`을 사용하세요.
|
|
183
183
|
|
|
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
|
|
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). CLI 0.3.3부터 `content thumbnail <파일>`로 본인 썸네일 작업 ID를 발급합니다. `--content <콘텐츠-UUID>`를 함께 주면 업로드 후 연결까지 수행합니다. `create`·`update`의 `--thumbnail-file <파일>`도 같은 경로를 사용하며 `--thumbnail-id`와 함께 지정할 수 없습니다. 일반 `clack upload`의 CDN URL은 썸네일 작업 ID가 아닙니다. 서버 `content config`의 `thumbnail_upload` 형식·용량·픽셀 조건을 조회하고 업로드합니다. `--dry-run`은 설정 GET과 로컬 검사만 수행합니다. 연결 실패는 오류의 `recovery.thumbnail_id`와 재연결 명령을 제공하므로 상태를 확인한 뒤 ID를 재사용하고 이미지를 다시 올리지 마세요. 언어별 메타데이터·태그는 서버 게이트가 켜진 환경에서만 쓸 수 있습니다. 인트로 저장은 개인 액세스 토큰으로 할 수 없어 크리에이터 센터에서만 합니다.
|
|
185
185
|
|
|
186
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
|
+
clack content thumbnail --env dev ./cover.png --content <콘텐츠-UUID> --json
|
|
190
|
+
clack content update --env dev <콘텐츠-UUID> --thumbnail-file ./cover.webp
|
|
191
|
+
clack content create --env dev --title "내 작품" --policy-version 2026-09-22 --thumbnail-file ./cover.png
|
|
189
192
|
clack content update --env dev <콘텐츠-UUID> --title "새 제목" --tags 여행,사진
|
|
190
193
|
clack content info-version --env dev <콘텐츠-UUID> <버전-UUID>
|
|
191
194
|
```
|
package/dist/cli.js
CHANGED
|
@@ -7,16 +7,18 @@ import { z as z2 } from "zod";
|
|
|
7
7
|
|
|
8
8
|
// src/core/errors.ts
|
|
9
9
|
var CliError = class extends Error {
|
|
10
|
-
constructor(message, code = "VALIDATION_ERROR", status = 400, retryAfter) {
|
|
10
|
+
constructor(message, code = "VALIDATION_ERROR", status = 400, retryAfter, recovery) {
|
|
11
11
|
super(message);
|
|
12
12
|
this.code = code;
|
|
13
13
|
this.status = status;
|
|
14
14
|
this.retryAfter = retryAfter;
|
|
15
|
+
this.recovery = recovery;
|
|
15
16
|
this.name = "CliError";
|
|
16
17
|
}
|
|
17
18
|
code;
|
|
18
19
|
status;
|
|
19
20
|
retryAfter;
|
|
21
|
+
recovery;
|
|
20
22
|
get exitCode() {
|
|
21
23
|
if (this.code === "USER_API_UNAVAILABLE") return 8;
|
|
22
24
|
if (this.status === 401) return 3;
|
|
@@ -184,7 +186,7 @@ function redact(value2) {
|
|
|
184
186
|
// package.json
|
|
185
187
|
var package_default = {
|
|
186
188
|
name: "@clack-platform/cli",
|
|
187
|
-
version: "0.3.
|
|
189
|
+
version: "0.3.3",
|
|
188
190
|
description: "\uD074\uB799 \uACC4\uC815\uC758 \uC0C1\uD488\xB7\uCF58\uD150\uCE20\xB7\uD504\uB85C\uD544\uC744 \uAD00\uB9AC\uD558\uB294 CLI",
|
|
189
191
|
type: "module",
|
|
190
192
|
bin: {
|
|
@@ -223,7 +225,7 @@ var package_default = {
|
|
|
223
225
|
test: "node scripts/test.mjs",
|
|
224
226
|
build: "tsup src/cli.ts --format esm --target node20 --clean",
|
|
225
227
|
check: "pnpm typecheck && node scripts/check-schema-sync.mjs && pnpm test && pnpm build",
|
|
226
|
-
"check:release": "pnpm typecheck && node scripts/check-schema-sync.mjs --strict && pnpm test && pnpm build",
|
|
228
|
+
"check:release": "pnpm typecheck && node scripts/check-schema-sync.mjs --strict && node scripts/sync-vendor-types.mjs --check && pnpm test && pnpm build",
|
|
227
229
|
prepack: "pnpm build"
|
|
228
230
|
},
|
|
229
231
|
dependencies: {
|
|
@@ -635,8 +637,8 @@ async function authoringRequest(client, raw, surface = "cli") {
|
|
|
635
637
|
if (input.action === "tool") return client.request("GET", `${path}/tools/${input.call_id}`);
|
|
636
638
|
if (input.action === "fill-status") return client.request("GET", `${path}/fill/${input.job_id}`);
|
|
637
639
|
if (input.action === "upload") {
|
|
638
|
-
const
|
|
639
|
-
if (!
|
|
640
|
+
const stat4 = await lstat2(input.file);
|
|
641
|
+
if (!stat4.isFile() || stat4.isSymbolicLink() || stat4.size > 4 * 1024 * 1024 || !stat4.size) throw new CliError("\uC774\uBBF8\uC9C0\uB294 \uC77C\uBC18 \uD30C\uC77C\uC774\uBA70 4 MiB \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.");
|
|
640
642
|
const bytes2 = await readFile2(input.file);
|
|
641
643
|
const body2 = new FormData();
|
|
642
644
|
body2.append("field", input.field);
|
|
@@ -726,8 +728,8 @@ var ConfigStore = class {
|
|
|
726
728
|
async read(name2) {
|
|
727
729
|
const path = join(this.directory, name2);
|
|
728
730
|
try {
|
|
729
|
-
const
|
|
730
|
-
if (!
|
|
731
|
+
const stat4 = await lstat3(path);
|
|
732
|
+
if (!stat4.isFile() || stat4.isSymbolicLink()) throw new CliError("\uC124\uC815 \uD30C\uC77C\uC740 \uC77C\uBC18 \uD30C\uC77C\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.", "CONFIG_UNSAFE");
|
|
731
733
|
if ((name2 === "credentials.json" || name2 === "device-request.json") && process.platform !== "win32") await chmod(path, 384);
|
|
732
734
|
const body = JSON.parse(await readFile3(path, "utf8"));
|
|
733
735
|
if (!body || typeof body !== "object" || !("profiles" in body) || !body.profiles || typeof body.profiles !== "object" || Array.isArray(body.profiles)) throw new Error("\uD615\uC2DD");
|
|
@@ -2045,22 +2047,87 @@ import { Option as Option2 } from "commander";
|
|
|
2045
2047
|
|
|
2046
2048
|
// src/lib/platform-mcp.ts
|
|
2047
2049
|
import { createInterface } from "readline";
|
|
2048
|
-
import { z as
|
|
2050
|
+
import { z as z11 } from "zod";
|
|
2049
2051
|
|
|
2050
2052
|
// src/commands/skill.ts
|
|
2051
2053
|
import { spawn } from "child_process";
|
|
2052
2054
|
import { existsSync } from "fs";
|
|
2053
2055
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
2054
2056
|
import { createRequire } from "module";
|
|
2055
|
-
import { join as join3, resolve as
|
|
2056
|
-
import { z as
|
|
2057
|
+
import { join as join3, resolve as resolve9 } from "path";
|
|
2058
|
+
import { z as z10 } from "zod";
|
|
2059
|
+
|
|
2060
|
+
// src/lib/content-thumbnail.ts
|
|
2061
|
+
import { readFile as readFile8, stat as stat2 } from "fs/promises";
|
|
2062
|
+
import { basename as basename3, resolve as resolve6 } from "path";
|
|
2063
|
+
import { imageSize as imageSize2 } from "image-size";
|
|
2064
|
+
import { z as z8 } from "zod";
|
|
2065
|
+
var policySchema = z8.object({
|
|
2066
|
+
thumbnail_upload_enabled: z8.boolean(),
|
|
2067
|
+
thumbnail_upload: z8.object({
|
|
2068
|
+
max_upload_bytes: z8.number().int().positive(),
|
|
2069
|
+
max_input_pixels: z8.number().int().positive(),
|
|
2070
|
+
formats: z8.array(z8.enum(["image/png", "image/jpeg", "image/webp"])).min(1)
|
|
2071
|
+
})
|
|
2072
|
+
});
|
|
2073
|
+
var thumbnailSchema = z8.object({ id: z8.uuid(), status: z8.literal("succeeded"), image_url: z8.url() });
|
|
2074
|
+
async function prepareContentThumbnail(ctx, source) {
|
|
2075
|
+
const response = await ctx.api.request("GET", "/v4/creator/config", { auth: false });
|
|
2076
|
+
const result = policySchema.safeParse(response.data);
|
|
2077
|
+
if (!result.success) throw new CliError("\uC11C\uBC84 \uC378\uB124\uC77C \uC5C5\uB85C\uB4DC \uC124\uC815\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uC11C\uBC84 \uC5C5\uB370\uC774\uD2B8 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.", "THUMBNAIL_CONFIG_REQUIRED", 409);
|
|
2078
|
+
if (!result.data.thumbnail_upload_enabled) throw new CliError("\uC774 \uD658\uACBD\uC5D0\uC11C\uB294 \uC378\uB124\uC77C \uC5C5\uB85C\uB4DC\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. content config\uB85C \uAE30\uB2A5 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uC138\uC694.", "THUMBNAIL_UPLOAD_DISABLED", 503);
|
|
2079
|
+
const policy = result.data.thumbnail_upload;
|
|
2080
|
+
const path = resolve6(source);
|
|
2081
|
+
const info = await stat2(path).catch(() => {
|
|
2082
|
+
throw new CliError("\uC378\uB124\uC77C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.", "THUMBNAIL_FILE_NOT_FOUND", 400);
|
|
2083
|
+
});
|
|
2084
|
+
if (!info.isFile() || !info.size) throw new CliError("\uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uB85C\uCEEC \uC774\uBBF8\uC9C0 \uD30C\uC77C\uC744 \uC9C0\uC815\uD558\uC138\uC694.", "THUMBNAIL_EMPTY_FILE", 400);
|
|
2085
|
+
if (info.size > policy.max_upload_bytes) throw new CliError(`\uC378\uB124\uC77C\uC740 ${policy.max_upload_bytes}\uBC14\uC774\uD2B8 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.`, "THUMBNAIL_TOO_LARGE", 413);
|
|
2086
|
+
const bytes2 = await readFile8(path).catch(() => {
|
|
2087
|
+
throw new CliError("\uC378\uB124\uC77C \uD30C\uC77C\uC744 \uC77D\uC744 \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.", "THUMBNAIL_FILE_UNREADABLE", 400);
|
|
2088
|
+
});
|
|
2089
|
+
if (!bytes2.length || bytes2.length > policy.max_upload_bytes) throw new CliError("\uC77D\uB294 \uB3D9\uC548 \uC378\uB124\uC77C \uD06C\uAE30\uAC00 \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uD30C\uC77C\uC744 \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694.", "THUMBNAIL_TOO_LARGE", 413);
|
|
2090
|
+
let mime;
|
|
2091
|
+
try {
|
|
2092
|
+
const image2 = imageSize2(bytes2);
|
|
2093
|
+
mime = { png: "image/png", jpg: "image/jpeg", webp: "image/webp" }[image2.type ?? ""] ?? "";
|
|
2094
|
+
if (!policy.formats.includes(mime) || !image2.width || !image2.height || image2.width * image2.height > policy.max_input_pixels) throw new Error();
|
|
2095
|
+
} catch {
|
|
2096
|
+
throw new CliError("\uC11C\uBC84\uAC00 \uC9C0\uC6D0\uD558\uB294 PNG\xB7JPEG\xB7WebP \uC774\uBBF8\uC9C0\uC640 \uC720\uD6A8\uD55C \uD06C\uAE30\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC190\uC0C1\uB41C \uD30C\uC77C\uC740 \uB2E4\uC2DC \uC800\uC7A5\uD558\uC138\uC694.", "THUMBNAIL_INVALID_IMAGE", 422);
|
|
2097
|
+
}
|
|
2098
|
+
return { path, bytes: bytes2, mime };
|
|
2099
|
+
}
|
|
2100
|
+
async function uploadContentThumbnail(ctx, image2) {
|
|
2101
|
+
const body = new FormData();
|
|
2102
|
+
body.append("file", new Blob([new Uint8Array(image2.bytes)], { type: image2.mime }), basename3(image2.path));
|
|
2103
|
+
const response = await ctx.api.request("POST", "/v4/creator/thumbnails", { body });
|
|
2104
|
+
const parsed = thumbnailSchema.safeParse(response.data);
|
|
2105
|
+
if (!parsed.success) throw new CliError("\uC644\uB8CC\uB41C \uC378\uB124\uC77C \uC791\uC5C5 ID\uB97C \uC751\uB2F5\uC5D0\uC11C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC790\uB3D9 \uC7AC\uC5C5\uB85C\uB4DC\uD558\uC9C0 \uB9C8\uC138\uC694.", "INVALID_RESPONSE", 502);
|
|
2106
|
+
return { data: parsed.data, time_contract: response.time_contract };
|
|
2107
|
+
}
|
|
2108
|
+
function thumbnailLinkFailure(ctx, cause, thumbnailId, contentId, creation) {
|
|
2109
|
+
const failure = asCliError(cause);
|
|
2110
|
+
const quote = (value2) => `'${value2.replaceAll("'", "'\\''")}'`;
|
|
2111
|
+
const prefix = `clack --base-url ${quote(ctx.api.settings.baseUrl)}${ctx.options.profile ? ` --profile ${quote(ctx.options.profile)}` : ""}`;
|
|
2112
|
+
const createArgs = ["title", "description", "kind", "policy_version"].flatMap((key) => creation?.[key] === void 0 ? [] : [`--${key.replaceAll("_", "-")} ${quote(String(creation[key]))}`]).join(" ");
|
|
2113
|
+
const command = contentId ? `${prefix} content update ${contentId} --thumbnail-id ${thumbnailId}` : `${prefix} content create ${createArgs} --thumbnail-id ${thumbnailId}`;
|
|
2114
|
+
const verify = contentId ? `${prefix} content status ${contentId}` : `${prefix} content list`;
|
|
2115
|
+
return new CliError(
|
|
2116
|
+
`${failure.message}
|
|
2117
|
+
\uC378\uB124\uC77C \uC5C5\uB85C\uB4DC\uB294 \uC644\uB8CC\uB410\uC2B5\uB2C8\uB2E4 (ID: ${thumbnailId}). ${verify}\uB85C \uC800\uC7A5 \uC5EC\uBD80\uB97C \uD655\uC778\uD55C \uB4A4 ${command}\uB85C \uC5F0\uACB0\uD558\uC138\uC694.`,
|
|
2118
|
+
failure.code,
|
|
2119
|
+
failure.status,
|
|
2120
|
+
failure.retryAfter,
|
|
2121
|
+
{ thumbnail_id: thumbnailId, ...contentId ? { content_id: contentId } : {}, verification_command: verify, retry_command: command }
|
|
2122
|
+
);
|
|
2123
|
+
}
|
|
2057
2124
|
|
|
2058
2125
|
// src/commands/content.ts
|
|
2059
2126
|
import { createHash as createHash2 } from "crypto";
|
|
2060
|
-
import { readFile as
|
|
2061
|
-
import { basename as
|
|
2127
|
+
import { readFile as readFile9, stat as stat3 } from "fs/promises";
|
|
2128
|
+
import { basename as basename4, extname, resolve as resolve7 } from "path";
|
|
2062
2129
|
import { Option } from "commander";
|
|
2063
|
-
import { z as
|
|
2130
|
+
import { z as z9 } from "zod";
|
|
2064
2131
|
|
|
2065
2132
|
// src/lib/content-package.ts
|
|
2066
2133
|
import { unzipSync } from "fflate";
|
|
@@ -2192,28 +2259,29 @@ function inspectContentPackage(bytes2) {
|
|
|
2192
2259
|
|
|
2193
2260
|
// src/commands/content.ts
|
|
2194
2261
|
var MAX_BYTES = 30 * 1024 * 1024;
|
|
2195
|
-
var uuid = (value2) => parse(
|
|
2196
|
-
var createSchema =
|
|
2197
|
-
title:
|
|
2198
|
-
description:
|
|
2199
|
-
kind:
|
|
2200
|
-
policy_version:
|
|
2262
|
+
var uuid = (value2) => parse(z9.uuid(), value2);
|
|
2263
|
+
var createSchema = z9.object({
|
|
2264
|
+
title: z9.string().trim().min(1).max(120),
|
|
2265
|
+
description: z9.string().trim().max(2e3).default(""),
|
|
2266
|
+
kind: z9.enum(["html", "gallery", "slideshow", "video"]).default("html"),
|
|
2267
|
+
policy_version: z9.literal("2026-09-22"),
|
|
2268
|
+
thumbnail_id: z9.uuid().nullable().optional()
|
|
2201
2269
|
}).strict();
|
|
2202
2270
|
var METADATA_LANGS = ["ko", "en"];
|
|
2203
2271
|
var TAG_PATTERN = /^[\p{L}\p{M}\p{N}_]{1,30}$/u;
|
|
2204
|
-
var localizedEntry =
|
|
2205
|
-
title:
|
|
2206
|
-
description:
|
|
2272
|
+
var localizedEntry = z9.object({
|
|
2273
|
+
title: z9.string().trim().max(120),
|
|
2274
|
+
description: z9.string().trim().max(2e3).optional()
|
|
2207
2275
|
}).strict();
|
|
2208
|
-
var updateSchema =
|
|
2209
|
-
title:
|
|
2210
|
-
description:
|
|
2211
|
-
kind:
|
|
2212
|
-
thumbnail_id:
|
|
2213
|
-
metadata_mode:
|
|
2214
|
-
metadata_lang:
|
|
2215
|
-
localized_metadata:
|
|
2216
|
-
tags:
|
|
2276
|
+
var updateSchema = z9.object({
|
|
2277
|
+
title: z9.string().trim().max(120).optional(),
|
|
2278
|
+
description: z9.string().trim().max(2e3).optional(),
|
|
2279
|
+
kind: z9.enum(["html", "gallery", "slideshow", "video"]).optional(),
|
|
2280
|
+
thumbnail_id: z9.uuid().nullable().optional(),
|
|
2281
|
+
metadata_mode: z9.enum(["single", "localized"]).optional(),
|
|
2282
|
+
metadata_lang: z9.enum(METADATA_LANGS).nullable().optional(),
|
|
2283
|
+
localized_metadata: z9.partialRecord(z9.enum(METADATA_LANGS), localizedEntry).nullable().optional(),
|
|
2284
|
+
tags: z9.array(z9.string().max(64)).max(50).optional()
|
|
2217
2285
|
}).strict().superRefine((value2, ctx) => {
|
|
2218
2286
|
const issue = (message) => ctx.addIssue({ code: "custom", message });
|
|
2219
2287
|
if (!Object.values(value2).some((entry) => entry !== void 0)) issue("\uBCC0\uACBD\uD560 \uD544\uB4DC\uB97C \uD558\uB098 \uC774\uC0C1 \uC9C0\uC815\uD558\uC138\uC694.");
|
|
@@ -2249,14 +2317,14 @@ function jsonOption(name2, value2) {
|
|
|
2249
2317
|
}
|
|
2250
2318
|
}
|
|
2251
2319
|
async function prepareContentFile(source) {
|
|
2252
|
-
const file =
|
|
2320
|
+
const file = resolve7(source);
|
|
2253
2321
|
const extension = extname(file).toLowerCase();
|
|
2254
2322
|
if (![".html", ".htm", ".zip"].includes(extension)) throw new CliError("HTML \uB610\uB294 ZIP \uD30C\uC77C\uC744 \uC9C0\uC815\uD558\uC138\uC694.");
|
|
2255
2323
|
let bytes2;
|
|
2256
2324
|
try {
|
|
2257
|
-
const info = await
|
|
2325
|
+
const info = await stat3(file);
|
|
2258
2326
|
if (!info.isFile() || info.size === 0 || info.size > MAX_BYTES) throw new Error();
|
|
2259
|
-
bytes2 = await
|
|
2327
|
+
bytes2 = await readFile9(file);
|
|
2260
2328
|
if (!bytes2.length || bytes2.length > MAX_BYTES) throw new Error();
|
|
2261
2329
|
} catch {
|
|
2262
2330
|
throw new CliError("30 MiB \uC774\uD558\uC758 \uBE44\uC5B4 \uC788\uC9C0 \uC54A\uC740 \uD30C\uC77C\uC744 \uC77D\uC744 \uC218 \uC788\uC5B4\uC57C \uD569\uB2C8\uB2E4.");
|
|
@@ -2265,7 +2333,7 @@ async function prepareContentFile(source) {
|
|
|
2265
2333
|
bytes: bytes2,
|
|
2266
2334
|
warnings: extension === ".zip" ? inspectContentPackage(bytes2) : [],
|
|
2267
2335
|
metadata: {
|
|
2268
|
-
filename:
|
|
2336
|
+
filename: basename4(file),
|
|
2269
2337
|
content_type: extension === ".zip" ? "application/zip" : "text/html",
|
|
2270
2338
|
byte_size: bytes2.length,
|
|
2271
2339
|
sha256: createHash2("sha256").update(bytes2).digest("hex")
|
|
@@ -2300,8 +2368,25 @@ async function putContentFile(session2, bytes2, fetcher = fetch) {
|
|
|
2300
2368
|
throw new CliError("\uD30C\uC77C \uC5C5\uB85C\uB4DC\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uC0C8 \uC5C5\uB85C\uB4DC\uB97C \uC2DC\uC791\uD558\uC138\uC694.", "CONTENT_UPLOAD_FAILED", 0);
|
|
2301
2369
|
}
|
|
2302
2370
|
}
|
|
2371
|
+
async function saveWithThumbnail(ctx, method, path, body, file, contentId) {
|
|
2372
|
+
if (!file) {
|
|
2373
|
+
await mutate(ctx, method, path, body);
|
|
2374
|
+
return;
|
|
2375
|
+
}
|
|
2376
|
+
const image2 = await prepareContentThumbnail(ctx, file);
|
|
2377
|
+
if (ctx.options.dryRun) {
|
|
2378
|
+
ctx.output({ dry_run: true, method, path, body: { ...body, thumbnail_id: "<\uC5C5\uB85C\uB4DC \uD6C4 \uBC1C\uAE09>" }, thumbnail: { file: image2.path, byte_size: image2.bytes.length } });
|
|
2379
|
+
return;
|
|
2380
|
+
}
|
|
2381
|
+
const uploaded = await uploadContentThumbnail(ctx, image2);
|
|
2382
|
+
try {
|
|
2383
|
+
ctx.output(await ctx.api.request(method, path, { body: { ...body, thumbnail_id: uploaded.data.id } }));
|
|
2384
|
+
} catch (failure) {
|
|
2385
|
+
throw thumbnailLinkFailure(ctx, failure, uploaded.data.id, contentId, method === "POST" ? body : void 0);
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2303
2388
|
var SERVER_KEY_CENTER_ONLY = "\uC11C\uBC84 \uD0A4 \uBC1C\uAE09\xB7\uD68C\uC804\uC740 \uD06C\uB9AC\uC5D0\uC774\uD130 \uC13C\uD130(\uB0B4 \uCF58\uD150\uCE20 \u2192 \uC11C\uBC84 \uD0A4)\uC5D0\uC11C\uB9CC \uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. CLI\xB7MCP\uC758 \uAC1C\uC778 \uC561\uC138\uC2A4 \uD1A0\uD070\uC73C\uB85C\uB294 \uC11C\uBC84 \uD0A4 \uC870\uD68C\xB7\uD3D0\uAE30\uB9CC \uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.";
|
|
2304
|
-
var collection =
|
|
2389
|
+
var collection = z9.string().regex(/^[A-Za-z0-9_-]{1,64}$/, "\uC774\uB984\uC740 \uC601\uC22B\uC790\xB7\uBC11\uC904\xB7\uBD99\uC784\uD45C 64\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.");
|
|
2305
2390
|
var documentKey = collection;
|
|
2306
2391
|
var keyId = (value2) => {
|
|
2307
2392
|
const id2 = String(value2);
|
|
@@ -2313,22 +2398,41 @@ function registerContentCommands(program2, runtime2) {
|
|
|
2313
2398
|
runtime2.action(content.command("config").description("\uCF58\uD150\uCE20 \uAE30\uB2A5 \uC81C\uACF5 \uC5EC\uBD80\xB7\uC124\uC815 \uC870\uD68C (\uB85C\uADF8\uC778 \uBD88\uD544\uC694)"), async (ctx) => ctx.output(await ctx.api.request("GET", "/v4/creator/config", { auth: false })));
|
|
2314
2399
|
runtime2.action(content.command("list").description("\uB0B4 \uCF58\uD150\uCE20 \uBAA9\uB85D (creator-content:read)"), async (ctx) => ctx.output(await ctx.api.request("GET", "/v4/creator/contents")));
|
|
2315
2400
|
runtime2.action(content.command("status <id>").description("\uCF58\uD150\uCE20\uC640 \uBC84\uC804\uBCC4 \uC5C5\uB85C\uB4DC\xB7\uC2EC\uC0AC\xB7\uACF5\uAC1C \uC0C1\uD0DC (creator-content:read)"), async (ctx, [id2]) => ctx.output(await ctx.api.request("GET", `/v4/creator/contents/${uuid(id2)}`)));
|
|
2316
|
-
runtime2.action(content.command("create").description("\uCF58\uD150\uCE20 \uCD08\uC548 \uB4F1\uB85D (creator-content:write)").requiredOption("--title <text>", "\uC81C\uBAA9").option("--description <text>", "\uC124\uBA85", "").option("--kind <kind>", "html|gallery|slideshow|video", "html").requiredOption("--policy-version <version>", "\uB3D9\uC758\uD55C \uCF58\uD150\uCE20 \uC81C\uACF5 \uC815\uCC45 \uBC84\uC804"), async (ctx, _args, opts) => {
|
|
2317
|
-
const body = parse(createSchema, { title: opts.title, description: opts.description, kind: opts.kind, policy_version: opts.policyVersion });
|
|
2318
|
-
await
|
|
2401
|
+
runtime2.action(content.command("create").description("\uCF58\uD150\uCE20 \uCD08\uC548 \uB4F1\uB85D (creator-content:write)").requiredOption("--title <text>", "\uC81C\uBAA9").option("--description <text>", "\uC124\uBA85", "").option("--kind <kind>", "html|gallery|slideshow|video", "html").requiredOption("--policy-version <version>", "\uB3D9\uC758\uD55C \uCF58\uD150\uCE20 \uC81C\uACF5 \uC815\uCC45 \uBC84\uC804").addOption(new Option("--thumbnail-file <file>", "\uB85C\uCEEC \uC378\uB124\uC77C \uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC \uD6C4 \uC5F0\uACB0").conflicts("thumbnailId")).addOption(new Option("--thumbnail-id <uuid|none>", "\uBC1C\uAE09\uBC1B\uC740 \uC378\uB124\uC77C ID \uB610\uB294 \uAE30\uBCF8 \uC774\uBBF8\uC9C0").conflicts("thumbnailFile")), async (ctx, _args, opts) => {
|
|
2402
|
+
const body = parse(createSchema, { title: opts.title, description: opts.description, kind: opts.kind, policy_version: opts.policyVersion, thumbnail_id: opts.thumbnailId === void 0 ? void 0 : opts.thumbnailId === "none" ? null : opts.thumbnailId });
|
|
2403
|
+
await saveWithThumbnail(ctx, "POST", "/v4/creator/contents", body, opts.thumbnailFile);
|
|
2319
2404
|
});
|
|
2320
|
-
runtime2.action(content.command("update <id>").description("\uCF58\uD150\uCE20 \uC815\uBCF4(\uC81C\uBAA9\xB7\uC124\uBA85\xB7\uC885\uB958\xB7\uC378\uB124\uC77C\xB7\uBA54\uD0C0\uB370\uC774\uD130\xB7\uD0DC\uADF8) \uC218\uC815 (creator-content:write)").option("--title <text>", "\uC81C\uBAA9 (120\uC790 \uC774\uD558, \uBE48 \uAC12\uC774\uBA74 \uC81C\uBAA9 \uC5C6\uC74C)").option("--description <text>", "\uC124\uBA85 (2000\uC790 \uC774\uD558)").addOption(new Option("--kind <kind>", "\uCF58\uD150\uCE20 \uC885\uB958").choices(["html", "gallery", "slideshow", "video"])).
|
|
2405
|
+
runtime2.action(content.command("update <id>").description("\uCF58\uD150\uCE20 \uC815\uBCF4(\uC81C\uBAA9\xB7\uC124\uBA85\xB7\uC885\uB958\xB7\uC378\uB124\uC77C\xB7\uBA54\uD0C0\uB370\uC774\uD130\xB7\uD0DC\uADF8) \uC218\uC815 (creator-content:write)").option("--title <text>", "\uC81C\uBAA9 (120\uC790 \uC774\uD558, \uBE48 \uAC12\uC774\uBA74 \uC81C\uBAA9 \uC5C6\uC74C)").option("--description <text>", "\uC124\uBA85 (2000\uC790 \uC774\uD558)").addOption(new Option("--kind <kind>", "\uCF58\uD150\uCE20 \uC885\uB958").choices(["html", "gallery", "slideshow", "video"])).addOption(new Option("--thumbnail-id <uuid|none>", "\uC378\uB124\uC77C \uC791\uC5C5 ID, none\uC774\uBA74 \uAE30\uBCF8 \uC774\uBBF8\uC9C0\uB85C \uB418\uB3CC\uB9BC").conflicts("thumbnailFile")).addOption(new Option("--thumbnail-file <file>", "\uB85C\uCEEC \uC378\uB124\uC77C \uC774\uBBF8\uC9C0 \uC5C5\uB85C\uB4DC \uD6C4 \uC5F0\uACB0").conflicts("thumbnailId")).addOption(new Option("--metadata-mode <mode>", "\uBA54\uD0C0\uB370\uC774\uD130 \uC785\uB825 \uBC29\uC2DD").choices(["single", "localized"])).option("--metadata-lang <ko|en|none>", "\uB300\uD45C \uC5B8\uC5B4").option("--localized-metadata <json|none>", `\uB300\uD45C \uC5B8\uC5B4 \uC678 \uC5B8\uC5B4\uBCC4 \uC81C\uBAA9\xB7\uC124\uBA85 JSON, \uC608: '{"en":{"title":"Title","description":"About"}}'`).option("--tags <list>", "\uD574\uC2DC\uD0DC\uADF8\uB97C \uC27C\uD45C\uB85C \uAD6C\uBD84\uD574 \uD1B5\uC9F8 \uAD50\uCCB4, \uBE48 \uBB38\uC790\uC5F4\uC774\uBA74 \uBAA8\uB450 \uC0AD\uC81C"), async (ctx, [id2], opts) => {
|
|
2321
2406
|
const body = parse(updateSchema, {
|
|
2322
2407
|
title: opts.title,
|
|
2323
2408
|
description: opts.description,
|
|
2324
2409
|
kind: opts.kind,
|
|
2325
|
-
thumbnail_id: opts.thumbnailId === void 0 ? void 0 : opts.thumbnailId === "none" ? null : opts.thumbnailId,
|
|
2410
|
+
thumbnail_id: opts.thumbnailFile ? null : opts.thumbnailId === void 0 ? void 0 : opts.thumbnailId === "none" ? null : opts.thumbnailId,
|
|
2326
2411
|
metadata_mode: opts.metadataMode,
|
|
2327
2412
|
metadata_lang: opts.metadataLang === void 0 ? void 0 : opts.metadataLang === "none" ? null : opts.metadataLang,
|
|
2328
2413
|
localized_metadata: opts.localizedMetadata === void 0 ? void 0 : jsonOption("--localized-metadata", opts.localizedMetadata),
|
|
2329
2414
|
tags: opts.tags === void 0 ? void 0 : csv(opts.tags)
|
|
2330
2415
|
});
|
|
2331
|
-
await
|
|
2416
|
+
await saveWithThumbnail(ctx, "PATCH", `/v4/creator/contents/${uuid(id2)}`, body, opts.thumbnailFile, uuid(id2));
|
|
2417
|
+
});
|
|
2418
|
+
runtime2.action(content.command("thumbnail <file>").description("\uB85C\uCEEC \uC378\uB124\uC77C \uC5C5\uB85C\uB4DC\uC640 \uC120\uD0DD\uC801 \uCF58\uD150\uCE20 \uC5F0\uACB0 (creator-content:write)").option("--content <uuid>", "\uC5C5\uB85C\uB4DC \uD6C4 \uC774 \uCF58\uD150\uCE20\uC5D0 \uC5F0\uACB0"), async (ctx, [file], opts) => {
|
|
2419
|
+
const contentId = opts.content === void 0 ? void 0 : uuid(opts.content);
|
|
2420
|
+
const image2 = await prepareContentThumbnail(ctx, file);
|
|
2421
|
+
if (ctx.options.dryRun) {
|
|
2422
|
+
ctx.output({ dry_run: true, path: "/v4/creator/thumbnails", file: image2.path, byte_size: image2.bytes.length, ...contentId ? { content_id: contentId } : {} });
|
|
2423
|
+
return;
|
|
2424
|
+
}
|
|
2425
|
+
const uploaded = await uploadContentThumbnail(ctx, image2);
|
|
2426
|
+
if (!contentId) {
|
|
2427
|
+
ctx.output(uploaded);
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2430
|
+
try {
|
|
2431
|
+
const result = await ctx.api.request("PATCH", `/v4/creator/contents/${contentId}`, { body: { thumbnail_id: uploaded.data.id } });
|
|
2432
|
+
ctx.output({ ...result, thumbnail: uploaded.data });
|
|
2433
|
+
} catch (failure) {
|
|
2434
|
+
throw thumbnailLinkFailure(ctx, failure, uploaded.data.id, contentId);
|
|
2435
|
+
}
|
|
2332
2436
|
});
|
|
2333
2437
|
runtime2.action(content.command("upload <id> <file>").description("HTML/ZIP \uC5C5\uB85C\uB4DC\uB85C \uC0C8 \uBE44\uACF5\uAC1C \uBC84\uC804 \uC0DD\uC131 (creator-content:write)").addOption(new Option("--header <mode>", "\uD5E4\uB354 \uD45C\uC2DC").choices(["fixed", "scroll_hide", "translucent_scroll_hide", "floating_close", "floating_close_safe_area"])).addOption(new Option("--color <scheme>", "\uD5E4\uB354 \uC0C9\uC0C1").choices(["light", "dark"])), async (ctx, [id2, file], opts) => {
|
|
2334
2438
|
const path = `/v4/creator/contents/${uuid(id2)}`;
|
|
@@ -2434,15 +2538,52 @@ function dataRootField(schema, name2) {
|
|
|
2434
2538
|
}
|
|
2435
2539
|
return field2;
|
|
2436
2540
|
}
|
|
2437
|
-
|
|
2541
|
+
var SEMANTICS_NOTES = {
|
|
2542
|
+
// 스킬 에디터 선언
|
|
2543
|
+
editor_document_permissions: () => "\uC5D0\uB514\uD130\uC5D0\uB294 document.read\uC640 document.write \uAD8C\uD55C\uC774 \uBAA8\uB450 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2544
|
+
ai_suggest_needs_ai_fill: () => "ai.suggest \uAD8C\uD55C\uC5D0\uB294 authoring.ai_fill.enabled\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2545
|
+
image_permission_needs_tool: () => "tools.image.generate \uAD8C\uD55C\uC5D0\uB294 authoring.tools\uC758 image.generate \uC120\uC5B8\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2546
|
+
editor_slot_aspect: () => "\uC5D0\uB514\uD130 \uC2A4\uD0AC\uC740 \uC2AC\uB86F \uBE44\uC728(aspect: slot)\uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC790\uC0B0 \uB178\uB4DC\uC758 x-clack-asset.aspect\uB97C \uC4F0\uC138\uC694.",
|
|
2547
|
+
asset_limits_missing: () => "\uC790\uC0B0 \uB178\uB4DC\uAC00 \uC788\uB294 \uB370\uC774\uD130 \uC2A4\uD0A4\uB9C8\uC5D0\uB294 output.data.assets \uD55C\uB3C4\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2548
|
+
asset_limits_unused: () => "\uC790\uC0B0 \uB178\uB4DC\uAC00 \uC5C6\uB294\uB370 \uC790\uC0B0 \uD55C\uB3C4\uB97C \uC120\uC5B8\uD588\uC2B5\uB2C8\uB2E4.",
|
|
2549
|
+
image_permission_no_asset: () => "\uC774\uBBF8\uC9C0\uB97C \uB123\uC744 \uC790\uC0B0 \uB178\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2550
|
+
ai_suggest_no_node: () => "x-clack-ai.suggest\uAC00 \uCF1C\uC9C4 \uB178\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2551
|
+
metadata_text_key: () => "\uACF5\uAC1C \uBB38\uC790\uC5F4 \uB8E8\uD2B8 \uD0A4\uB97C \uAC00\uB9AC\uCF1C\uC57C \uD569\uB2C8\uB2E4.",
|
|
2552
|
+
metadata_asset_key: () => "\uACF5\uAC1C \uC790\uC0B0 \uB8E8\uD2B8 \uD0A4\uB97C \uAC00\uB9AC\uCF1C\uC57C \uD569\uB2C8\uB2E4(\uC778\uB371\uC2A4 \uD45C\uAE30 \uBD88\uAC00).",
|
|
2553
|
+
// 콘텐츠 인트로
|
|
2554
|
+
intro_image_not_slot: () => "\uC778\uD2B8\uB85C \uC774\uBBF8\uC9C0\uB294 output.asset_slots\uC758 \uD544\uB4DC\uB9CC \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
2555
|
+
intro_images_over: ({ max }) => `\uC778\uD2B8\uB85C \uC774\uBBF8\uC9C0\uB294 \uC2AC\uB86F \uCD5C\uB300 \uC7A5\uC218 \uD569\uACC4\uAC00 ${max}\uC7A5 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.`,
|
|
2556
|
+
intro_text_field: () => "\uACF5\uAC1C \uBB38\uC790\uC5F4(text\xB7textarea) \uD3FC \uD544\uB4DC\uB97C \uAC00\uB9AC\uCF1C\uC57C \uD569\uB2C8\uB2E4.",
|
|
2557
|
+
intro_text_too_long: ({ max }) => `\uAC00\uB9AC\uD0A4\uB294 \uD3FC \uD544\uB4DC\uC758 \uCD5C\uB300 \uAE38\uC774\uAC00 ${max}\uC790 \uC774\uD558\uC5EC\uC57C \uD569\uB2C8\uB2E4.`,
|
|
2558
|
+
intro_section_field: () => "\uC18C\uAC1C \uC139\uC158\uC740 \uACF5\uAC1C \uBB38\uC790\uC5F4(text\xB7textarea) \uD3FC \uD544\uB4DC\uB9CC \uAC00\uB9AC\uD0AC \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
2559
|
+
intro_section_too_long: () => "\uC18C\uAC1C \uC139\uC158\uC758 \uCD5C\uB300 \uAE38\uC774\uB294 2,000\uC790\uC785\uB2C8\uB2E4.",
|
|
2560
|
+
intro_sections_total: () => "\uC18C\uAC1C \uC139\uC158\uC758 \uCD5C\uB300 \uAE38\uC774 \uD569\uACC4\uB294 6,000\uC790\uC785\uB2C8\uB2E4.",
|
|
2561
|
+
intro_fallback_field: () => "\uBB38\uC790\uC5F4(text\xB7textarea) \uD3FC \uD544\uB4DC\uB9CC \uC790\uB3D9 \uAD6C\uC131\uC5D0 \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
2562
|
+
intro_fallback_too_long: ({ max }) => `\uC790\uB3D9 \uAD6C\uC131 \uCD5C\uB300 \uAE38\uC774(\uB77C\uBCA8 \uD3EC\uD568)\uAC00 ${max}\uC790\uB97C \uB118\uC2B5\uB2C8\uB2E4.`,
|
|
2563
|
+
// 도구·이미지 슬롯
|
|
2564
|
+
tool_duplicate: () => "\uB3C4\uAD6C \uC774\uB984\uC744 \uC911\uBCF5 \uC120\uC5B8\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2565
|
+
tool_batch_over_calls: () => "\uC77C\uAD04 \uC0DD\uC131 \uC218\uB294 \uC138\uC158 \uD638\uCD9C \uC218\uB97C \uB118\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2566
|
+
slot_field_duplicate: () => "\uC2AC\uB86F \uD544\uB4DC\uB294 \uC911\uBCF5\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2567
|
+
slot_multiple_range: () => "\uB2E4\uC911 \uC2AC\uB86F \uCD5C\uC18C \uC218\uB294 \uCD5C\uB300 \uC218\uBCF4\uB2E4 \uD074 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2568
|
+
slot_path_duplicate: () => "\uC2AC\uB86F \uD30C\uC77C \uACBD\uB85C\uB294 \uC911\uBCF5\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2569
|
+
slot_widget_mismatch: () => "\uC2AC\uB86F\uACFC \uC774\uBBF8\uC9C0 \uC704\uC82F \uC885\uB958\uAC00 \uC77C\uCE58\uD574\uC57C \uD569\uB2C8\uB2E4.",
|
|
2570
|
+
// 폼 필드 참조
|
|
2571
|
+
form_field_missing: () => "\uC120\uC5B8\uD55C \uD3FC \uD544\uB4DC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2572
|
+
slot_index_invalid: () => "\uB2E4\uC911 \uC774\uBBF8\uC9C0 \uC2AC\uB86F\uC758 \uC720\uD6A8\uD55C \uC778\uB371\uC2A4\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2573
|
+
content_ref_declaration: () => "content_ref\uC5D0\uB294 \uBB38\uC790\uC5F4\uACFC x-clack-source \uC120\uC5B8\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2574
|
+
content_ref_import_chain: () => "\uB2E4\uB978 content_ref \uD544\uB4DC\uB85C \uAC00\uC838\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2575
|
+
source_without_content_ref: () => "x-clack-source\uB294 content_ref\uC5D0\uB9CC \uC120\uC5B8\uD569\uB2C8\uB2E4.",
|
|
2576
|
+
image_list_declaration: () => "image_list\uC5D0\uB294 \uAC1D\uCCB4 \uBC30\uC5F4\uACFC \uC790\uC0B0 \uC120\uC5B8\uC774 \uD544\uC694\uD569\uB2C8\uB2E4."
|
|
2577
|
+
};
|
|
2578
|
+
function inspectEditorSemantics(skill, data, fail) {
|
|
2438
2579
|
const editor = skill.authoring?.editor;
|
|
2439
2580
|
if (!editor) return;
|
|
2440
2581
|
const permissions = new Set(editor.permissions ?? []);
|
|
2441
|
-
if (!permissions.has("document.read") || !permissions.has("document.write"))
|
|
2442
|
-
if (permissions.has("ai.suggest") && skill.authoring?.ai_fill?.enabled !== true)
|
|
2582
|
+
if (!permissions.has("document.read") || !permissions.has("document.write")) fail("/authoring/editor/permissions", "editor_document_permissions");
|
|
2583
|
+
if (permissions.has("ai.suggest") && skill.authoring?.ai_fill?.enabled !== true) fail("/authoring/editor/permissions", "ai_suggest_needs_ai_fill");
|
|
2443
2584
|
const imageTool = (skill.authoring?.tools ?? []).find((tool) => tool.tool === "image.generate");
|
|
2444
|
-
if (permissions.has("tools.image.generate") && !imageTool)
|
|
2445
|
-
if (imageTool?.aspect === "slot")
|
|
2585
|
+
if (permissions.has("tools.image.generate") && !imageTool) fail("/authoring/editor/permissions", "image_permission_needs_tool");
|
|
2586
|
+
if (imageTool?.aspect === "slot") fail("/authoring/tools", "editor_slot_aspect");
|
|
2446
2587
|
if (!data) return;
|
|
2447
2588
|
let assets = 0;
|
|
2448
2589
|
let suggest = 0;
|
|
@@ -2450,20 +2591,20 @@ function inspectEditorSemantics(skill, data, fail2) {
|
|
|
2450
2591
|
if (node["x-clack-asset"]) assets++;
|
|
2451
2592
|
if (node["x-clack-ai"]?.suggest === true) suggest++;
|
|
2452
2593
|
});
|
|
2453
|
-
if (assets > 0 && !skill.output?.data?.assets)
|
|
2454
|
-
if (assets === 0 && skill.output?.data?.assets)
|
|
2455
|
-
if (assets === 0 && permissions.has("tools.image.generate"))
|
|
2456
|
-
if (suggest === 0 && permissions.has("ai.suggest"))
|
|
2594
|
+
if (assets > 0 && !skill.output?.data?.assets) fail("/output/data/assets", "asset_limits_missing");
|
|
2595
|
+
if (assets === 0 && skill.output?.data?.assets) fail("/output/data/assets", "asset_limits_unused");
|
|
2596
|
+
if (assets === 0 && permissions.has("tools.image.generate")) fail("/authoring/editor/permissions", "image_permission_no_asset");
|
|
2597
|
+
if (suggest === 0 && permissions.has("ai.suggest")) fail("/authoring/editor/permissions", "ai_suggest_no_node");
|
|
2457
2598
|
const metadata = skill.output?.metadata ?? {};
|
|
2458
2599
|
for (const key of ["title", "description"]) {
|
|
2459
2600
|
if (metadata[key] === void 0) continue;
|
|
2460
2601
|
const field2 = dataRootField(data, metadata[key]);
|
|
2461
|
-
if (!field2 || field2.type !== "string" || field2["x-clack-asset"] || field2["x-clack-visibility"] !== "public")
|
|
2602
|
+
if (!field2 || field2.type !== "string" || field2["x-clack-asset"] || field2["x-clack-visibility"] !== "public") fail(`/output/metadata/${key}`, "metadata_text_key");
|
|
2462
2603
|
}
|
|
2463
2604
|
for (const key of ["thumbnail", "thumbnail_fallback"]) {
|
|
2464
2605
|
if (metadata[key] === void 0) continue;
|
|
2465
2606
|
const field2 = dataRootField(data, metadata[key]);
|
|
2466
|
-
if (!field2 || !field2["x-clack-asset"] || field2["x-clack-visibility"] !== "public")
|
|
2607
|
+
if (!field2 || !field2["x-clack-asset"] || field2["x-clack-visibility"] !== "public") fail(`/output/metadata/${key}`, "metadata_asset_key");
|
|
2467
2608
|
}
|
|
2468
2609
|
}
|
|
2469
2610
|
var INTRO_MAX_IMAGES = 8;
|
|
@@ -2480,19 +2621,19 @@ function introFieldLabelMaxLength(name2, field2) {
|
|
|
2480
2621
|
}
|
|
2481
2622
|
return Math.max(...lengths);
|
|
2482
2623
|
}
|
|
2483
|
-
function inspectIntroSemantics(skill, form, slots,
|
|
2624
|
+
function inspectIntroSemantics(skill, form, slots, fail) {
|
|
2484
2625
|
const intro = skill.output?.intro;
|
|
2485
2626
|
if (!intro) return;
|
|
2486
2627
|
let images = 0;
|
|
2487
2628
|
for (const name2 of intro.images ?? []) {
|
|
2488
2629
|
const slot = slots.find((entry) => entry.field === name2);
|
|
2489
2630
|
if (!slot) {
|
|
2490
|
-
|
|
2631
|
+
fail("/output/intro/images", "intro_image_not_slot");
|
|
2491
2632
|
continue;
|
|
2492
2633
|
}
|
|
2493
2634
|
images += slot.multiple ? slot.multiple.max : 1;
|
|
2494
2635
|
}
|
|
2495
|
-
if (images > INTRO_MAX_IMAGES)
|
|
2636
|
+
if (images > INTRO_MAX_IMAGES) fail("/output/intro/images", "intro_images_over", { max: INTRO_MAX_IMAGES });
|
|
2496
2637
|
if (!form) return;
|
|
2497
2638
|
const properties = form.properties ?? {};
|
|
2498
2639
|
const textField = (name2) => {
|
|
@@ -2502,64 +2643,64 @@ function inspectIntroSemantics(skill, form, slots, fail2) {
|
|
|
2502
2643
|
for (const [key, max] of [["creator_comment", INTRO_CREATOR_COMMENT_MAX], ["description", INTRO_DESCRIPTION_MAX]]) {
|
|
2503
2644
|
if (intro[key] === void 0) continue;
|
|
2504
2645
|
const field2 = textField(intro[key]);
|
|
2505
|
-
if (!field2 || field2["x-clack-visibility"] !== "public")
|
|
2506
|
-
else if (field2.maxLength > max)
|
|
2646
|
+
if (!field2 || field2["x-clack-visibility"] !== "public") fail(`/output/intro/${key}`, "intro_text_field");
|
|
2647
|
+
else if (field2.maxLength > max) fail(`/output/intro/${key}`, "intro_text_too_long", { max });
|
|
2507
2648
|
}
|
|
2508
2649
|
let sectionLength = 0;
|
|
2509
2650
|
for (const [key, name2] of Object.entries(intro.sections ?? {})) {
|
|
2510
2651
|
const field2 = textField(name2);
|
|
2511
|
-
if (!field2 || field2["x-clack-visibility"] !== "public")
|
|
2652
|
+
if (!field2 || field2["x-clack-visibility"] !== "public") fail(`/output/intro/sections/${key}`, "intro_section_field");
|
|
2512
2653
|
else {
|
|
2513
|
-
if (field2.maxLength > 2e3)
|
|
2654
|
+
if (field2.maxLength > 2e3) fail(`/output/intro/sections/${key}`, "intro_section_too_long");
|
|
2514
2655
|
sectionLength += field2.maxLength;
|
|
2515
2656
|
}
|
|
2516
2657
|
}
|
|
2517
|
-
if (sectionLength > 6e3)
|
|
2658
|
+
if (sectionLength > 6e3) fail("/output/intro/sections", "intro_sections_total");
|
|
2518
2659
|
const fallback = intro.description_fallback ?? [];
|
|
2519
2660
|
let composed = 0;
|
|
2520
2661
|
for (const name2 of fallback) {
|
|
2521
2662
|
const field2 = textField(name2);
|
|
2522
2663
|
if (!field2) {
|
|
2523
|
-
|
|
2664
|
+
fail("/output/intro/description_fallback", "intro_fallback_field");
|
|
2524
2665
|
continue;
|
|
2525
2666
|
}
|
|
2526
2667
|
composed += introFieldLabelMaxLength(name2, field2) + 1 + field2.maxLength;
|
|
2527
2668
|
}
|
|
2528
2669
|
composed += Math.max(0, fallback.length - 1) * 2;
|
|
2529
|
-
if (composed > INTRO_DESCRIPTION_MAX)
|
|
2670
|
+
if (composed > INTRO_DESCRIPTION_MAX) fail("/output/intro/description_fallback", "intro_fallback_too_long", { max: INTRO_DESCRIPTION_MAX });
|
|
2530
2671
|
}
|
|
2531
2672
|
function inspectAuthoringSemantics(skill, form, data) {
|
|
2532
2673
|
const errors = [];
|
|
2533
|
-
const
|
|
2534
|
-
inspectEditorSemantics(skill, data,
|
|
2674
|
+
const fail = (path, code, args) => errors.push({ path, message: SEMANTICS_NOTES[code](args ?? {}), code, ...args ? { args } : {} });
|
|
2675
|
+
inspectEditorSemantics(skill, data, fail);
|
|
2535
2676
|
const tools = skill.authoring?.tools ?? [];
|
|
2536
|
-
if (new Set(tools.map((tool) => tool.tool)).size !== tools.length)
|
|
2537
|
-
for (const tool of tools) if (tool.batch_max > tool.max_calls)
|
|
2677
|
+
if (new Set(tools.map((tool) => tool.tool)).size !== tools.length) fail("/authoring/tools", "tool_duplicate");
|
|
2678
|
+
for (const tool of tools) if (tool.batch_max > tool.max_calls) fail("/authoring/tools", "tool_batch_over_calls");
|
|
2538
2679
|
const slots = skill.output?.asset_slots ?? [];
|
|
2539
2680
|
const paths = /* @__PURE__ */ new Set();
|
|
2540
2681
|
const fields3 = /* @__PURE__ */ new Set();
|
|
2541
2682
|
for (const slot of slots) {
|
|
2542
|
-
if (fields3.has(slot.field))
|
|
2683
|
+
if (fields3.has(slot.field)) fail("/output/asset_slots", "slot_field_duplicate");
|
|
2543
2684
|
fields3.add(slot.field);
|
|
2544
|
-
if (slot.multiple && slot.multiple.min > slot.multiple.max)
|
|
2685
|
+
if (slot.multiple && slot.multiple.min > slot.multiple.max) fail("/output/asset_slots", "slot_multiple_range");
|
|
2545
2686
|
for (let index = 0; index < (slot.multiple?.max ?? 1); index++) {
|
|
2546
2687
|
const path = slot.multiple ? slot.multiple.path.replace("{n}", String(index)) : slot.path;
|
|
2547
|
-
if (paths.has(path))
|
|
2688
|
+
if (paths.has(path)) fail("/output/asset_slots", "slot_path_duplicate");
|
|
2548
2689
|
paths.add(path);
|
|
2549
2690
|
}
|
|
2550
2691
|
}
|
|
2551
|
-
inspectIntroSemantics(skill, form, slots,
|
|
2692
|
+
inspectIntroSemantics(skill, form, slots, fail);
|
|
2552
2693
|
if (!form) return errors;
|
|
2553
2694
|
const properties = form.properties ?? {};
|
|
2554
2695
|
const exists = (expression, path) => {
|
|
2555
2696
|
const match = /^([a-z][a-z0-9_-]*)(?:\[(\d+)\])?$/.exec(expression);
|
|
2556
2697
|
if (!match || !Object.hasOwn(properties, match[1])) {
|
|
2557
|
-
|
|
2698
|
+
fail(path, "form_field_missing");
|
|
2558
2699
|
return;
|
|
2559
2700
|
}
|
|
2560
2701
|
if (match[2] !== void 0) {
|
|
2561
2702
|
const slot = slots.find((value2) => value2.field === match[1]);
|
|
2562
|
-
if (!slot?.multiple || Number(match[2]) >= slot.multiple.max)
|
|
2703
|
+
if (!slot?.multiple || Number(match[2]) >= slot.multiple.max) fail(path, "slot_index_invalid");
|
|
2563
2704
|
}
|
|
2564
2705
|
};
|
|
2565
2706
|
const entity = skill.output?.entity_map;
|
|
@@ -2569,17 +2710,17 @@ function inspectAuthoringSemantics(skill, form, data) {
|
|
|
2569
2710
|
}
|
|
2570
2711
|
for (const slot of slots) {
|
|
2571
2712
|
const node = properties[slot.field];
|
|
2572
|
-
if (!node || node["x-clack-widget"] !== (slot.multiple ? "image_list" : "image"))
|
|
2713
|
+
if (!node || node["x-clack-widget"] !== (slot.multiple ? "image_list" : "image")) fail("/output/asset_slots", "slot_widget_mismatch");
|
|
2573
2714
|
}
|
|
2574
2715
|
for (const [name2, node] of Object.entries(properties)) {
|
|
2575
2716
|
if (node["x-clack-widget"] === "content_ref") {
|
|
2576
|
-
if (node.type !== "string" || !node["x-clack-source"])
|
|
2717
|
+
if (node.type !== "string" || !node["x-clack-source"]) fail(`/properties/${name2}`, "content_ref_declaration");
|
|
2577
2718
|
for (const target of Object.keys(node["x-clack-source"]?.import ?? {})) {
|
|
2578
2719
|
exists(target, `/properties/${name2}/x-clack-source/import`);
|
|
2579
|
-
if (properties[target]?.["x-clack-widget"] === "content_ref")
|
|
2720
|
+
if (properties[target]?.["x-clack-widget"] === "content_ref") fail(`/properties/${name2}`, "content_ref_import_chain");
|
|
2580
2721
|
}
|
|
2581
|
-
} else if (node["x-clack-source"])
|
|
2582
|
-
if (node["x-clack-widget"] === "image_list" && (node.type !== "array" || node.items?.type !== "object" || !node["x-clack-asset"]))
|
|
2722
|
+
} else if (node["x-clack-source"]) fail(`/properties/${name2}`, "source_without_content_ref");
|
|
2723
|
+
if (node["x-clack-widget"] === "image_list" && (node.type !== "array" || node.items?.type !== "object" || !node["x-clack-asset"])) fail(`/properties/${name2}`, "image_list_declaration");
|
|
2583
2724
|
}
|
|
2584
2725
|
return errors;
|
|
2585
2726
|
}
|
|
@@ -2588,7 +2729,7 @@ function inspectAuthoringSemantics(skill, form, data) {
|
|
|
2588
2729
|
import { createHash as createHash4 } from "crypto";
|
|
2589
2730
|
import { lstat as lstat4, open as open3, readdir } from "fs/promises";
|
|
2590
2731
|
import { constants } from "fs";
|
|
2591
|
-
import { basename as
|
|
2732
|
+
import { basename as basename5, extname as extname2, join as join2, resolve as resolve8 } from "path";
|
|
2592
2733
|
import { Ajv2020 as Ajv20202 } from "ajv/dist/2020.js";
|
|
2593
2734
|
import { unzipSync as unzipSync2, zipSync } from "fflate";
|
|
2594
2735
|
import { parseDocument } from "yaml";
|
|
@@ -2599,7 +2740,6 @@ import { Ajv2020 } from "ajv/dist/2020.js";
|
|
|
2599
2740
|
|
|
2600
2741
|
// src/vendor/clack-api-v4-contracts/output-data-inspect.mjs
|
|
2601
2742
|
var bytes = (value2) => Buffer.byteLength(JSON.stringify(value2), "utf8");
|
|
2602
|
-
var fail = (path, message) => ({ path, message });
|
|
2603
2743
|
var OUTPUT_DATA_LIMITS = { schema_bytes: 65536, depth: 6, properties: 400, public_bytes: 262144, private_bytes: 65536, ui_state_bytes: 262144 };
|
|
2604
2744
|
var SCALAR_TYPES = /* @__PURE__ */ new Set(["string", "integer", "number", "boolean"]);
|
|
2605
2745
|
var SCALAR_KEYS = {
|
|
@@ -2611,84 +2751,115 @@ var SCALAR_KEYS = {
|
|
|
2611
2751
|
boolean: []
|
|
2612
2752
|
};
|
|
2613
2753
|
var TYPED_KEYS = new Set(Object.values(SCALAR_KEYS).flat());
|
|
2754
|
+
var RANGE_LABELS = { length: "\uAE38\uC774", items: "\uD56D\uBAA9 \uC218", value: "\uAC12" };
|
|
2755
|
+
var OUTPUT_DATA_NOTES = {
|
|
2756
|
+
schema_too_large: () => "\uB370\uC774\uD130 \uC2A4\uD0A4\uB9C8\uB294 64 KiB \uC774\uD558\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
2757
|
+
root_required_undeclared: ({ key }) => `\uC120\uC5B8\uD558\uC9C0 \uC54A\uC740 \uB8E8\uD2B8 \uD0A4 ${key}\uC785\uB2C8\uB2E4.`,
|
|
2758
|
+
public_root_key_missing: () => "\uACF5\uAC1C \uB8E8\uD2B8 \uD0A4\uAC00 \uD558\uB098 \uC774\uC0C1 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2759
|
+
ref_cycle: () => "\uC21C\uD658 \uCC38\uC870\uB294 \uD5C8\uC6A9\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
2760
|
+
ref_not_local: () => "\uB85C\uCEEC $defs \uCC38\uC870\uB9CC \uD5C8\uC6A9\uD569\uB2C8\uB2E4.",
|
|
2761
|
+
depth_over: () => "\uB370\uC774\uD130 \uBB38\uC11C \uAE4A\uC774\uB294 \uB8E8\uD2B8 \uC544\uB798 6 \uC774\uD558\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
2762
|
+
ref_extra_keys: () => "$ref\uC5D0\uB294 \uC124\uBA85 \uD0A4\uB9CC \uD568\uAED8 \uB458 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
2763
|
+
one_of_discriminator_missing: () => "oneOf\uC5D0\uB294 x-clack-discriminator\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2764
|
+
one_of_typed_keys: () => "oneOf \uB178\uB4DC\uC5D0\uB294 \uD615\uC2DD \uD0A4\uB97C \uD568\uAED8 \uB458 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2765
|
+
one_of_branch_shape: () => "\uAC01 oneOf \uBD84\uAE30\uB294 \uD310\uBCC4\uC790 \uBB38\uC790\uC5F4 const\uB97C \uD544\uC218\uB85C \uAC00\uC9C4 \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
2766
|
+
discriminator_duplicate: ({ value: value2 }) => `\uD310\uBCC4\uC790 \uAC12 ${value2}\uC774 \uC911\uBCF5\uB429\uB2C8\uB2E4.`,
|
|
2767
|
+
discriminator_misplaced: () => "x-clack-discriminator\uB294 oneOf\uC5D0\uB9CC \uB461\uB2C8\uB2E4.",
|
|
2768
|
+
type_missing: () => "type\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2769
|
+
key_not_for_type: ({ type }) => `${type}\uC5D0 \uC4F8 \uC218 \uC5C6\uB294 \uD0A4\uC785\uB2C8\uB2E4.`,
|
|
2770
|
+
range_invalid: ({ range }) => `${RANGE_LABELS[range]} \uBC94\uC704\uAC00 \uC798\uBABB\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`,
|
|
2771
|
+
string_max_length_missing: () => "\uBB38\uC790\uC5F4 maxLength\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2772
|
+
array_items_missing: () => "\uBC30\uC5F4\uC5D0\uB294 items\uC640 maxItems\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2773
|
+
unique_items_not_scalar: () => "uniqueItems\uB294 \uC2A4\uCE7C\uB77C \uBC30\uC5F4\uC5D0\uB9CC \uC4F8 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
2774
|
+
object_shape: () => "\uAC1D\uCCB4\uC5D0\uB294 properties\uC640 additionalProperties: false\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
2775
|
+
required_undeclared: ({ key }) => `\uC120\uC5B8\uD558\uC9C0 \uC54A\uC740 \uD0A4 ${key}\uC744 required\uC5D0 \uB450\uC5C8\uC2B5\uB2C8\uB2E4.`,
|
|
2776
|
+
enum_type_mismatch: () => "enum \uAC12\uC758 \uD615\uC2DD\uC774 type\uACFC \uB2E4\uB985\uB2C8\uB2E4.",
|
|
2777
|
+
asset_node_shape: () => "\uC790\uC0B0 \uB178\uB4DC\uB294 {type:string, format:uuid, maxLength:36}\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
2778
|
+
asset_in_private: () => "\uBE44\uACF5\uAC1C \uD0A4\uC5D0\uB294 \uC790\uC0B0\uC744 \uB458 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
2779
|
+
format_not_string: () => "format\uC740 \uBB38\uC790\uC5F4\uC5D0\uB9CC \uC501\uB2C8\uB2E4.",
|
|
2780
|
+
ai_suggest_private: () => "AI \uC81C\uC548\uC740 \uACF5\uAC1C \uD0A4\uC5D0\uB9CC \uCF24 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
|
|
2781
|
+
properties_over: () => "\uB370\uC774\uD130 \uC2A4\uD0A4\uB9C8 \uC18D\uC131\uC740 400\uAC1C \uC774\uD558\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
2782
|
+
ai_suggest_has_asset: () => "AI \uC81C\uC548 \uD558\uC704 \uD2B8\uB9AC\uC5D0 \uC790\uC0B0 \uB178\uB4DC\uB97C \uB458 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."
|
|
2783
|
+
};
|
|
2614
2784
|
function inspectOutputData(schema) {
|
|
2615
2785
|
const errors = [];
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
if (!Object.
|
|
2786
|
+
const note = (path, code, args) => errors.push({ path, message: OUTPUT_DATA_NOTES[code](args ?? {}), code, ...args ? { args } : {} });
|
|
2787
|
+
if (bytes(schema) > OUTPUT_DATA_LIMITS.schema_bytes) note("/", "schema_too_large");
|
|
2788
|
+
for (const name2 of schema.required ?? []) if (!Object.hasOwn(schema.properties, name2)) note("/required", "root_required_undeclared", { key: name2 });
|
|
2789
|
+
if (!Object.values(schema.properties).some((field2) => field2["x-clack-visibility"] === "public")) note("/properties", "public_root_key_missing");
|
|
2619
2790
|
const defs = schema.$defs ?? {};
|
|
2620
|
-
const
|
|
2791
|
+
const resolve10 = (node) => typeof node?.$ref === "string" ? defs[node.$ref.slice("#/$defs/".length)] : node;
|
|
2621
2792
|
let properties = 0;
|
|
2622
2793
|
const suggestRoots = [];
|
|
2623
2794
|
const assetPointers = [];
|
|
2624
2795
|
walkDataSchema(schema, (node, info) => {
|
|
2625
2796
|
const at = info.pointer || "/";
|
|
2626
2797
|
if (info.cycle) {
|
|
2627
|
-
|
|
2798
|
+
note(at, "ref_cycle");
|
|
2628
2799
|
return;
|
|
2629
2800
|
}
|
|
2630
2801
|
if (info.unresolved) {
|
|
2631
|
-
|
|
2802
|
+
note(at, "ref_not_local");
|
|
2632
2803
|
return;
|
|
2633
2804
|
}
|
|
2634
|
-
if (info.depth > OUTPUT_DATA_LIMITS.depth)
|
|
2805
|
+
if (info.depth > OUTPUT_DATA_LIMITS.depth) note(at, "depth_over");
|
|
2635
2806
|
if (info.depth === 0) return;
|
|
2636
2807
|
if (typeof node.$ref === "string") {
|
|
2637
|
-
if (Object.keys(node).some((key) => !["$ref", "title", "description", "x-clack-i18n", "x-clack-visibility"].includes(key)))
|
|
2808
|
+
if (Object.keys(node).some((key) => !["$ref", "title", "description", "x-clack-i18n", "x-clack-visibility"].includes(key))) note(at, "ref_extra_keys");
|
|
2638
2809
|
return;
|
|
2639
2810
|
}
|
|
2640
2811
|
if (!info.branch) properties++;
|
|
2641
2812
|
if (Array.isArray(node.oneOf)) {
|
|
2642
2813
|
const discriminator = node["x-clack-discriminator"];
|
|
2643
|
-
if (!discriminator)
|
|
2644
|
-
if (node.type || node.properties || node.items || node.enum || Object.hasOwn(node, "const"))
|
|
2814
|
+
if (!discriminator) note(at, "one_of_discriminator_missing");
|
|
2815
|
+
if (node.type || node.properties || node.items || node.enum || Object.hasOwn(node, "const")) note(at, "one_of_typed_keys");
|
|
2645
2816
|
const seen = /* @__PURE__ */ new Set();
|
|
2646
2817
|
for (const raw of node.oneOf) {
|
|
2647
|
-
const branch =
|
|
2818
|
+
const branch = resolve10(raw);
|
|
2648
2819
|
const tag = branch?.properties?.[discriminator];
|
|
2649
2820
|
if (branch?.type !== "object" || typeof tag?.const !== "string" || tag.type !== "string" || !(branch.required ?? []).includes(discriminator)) {
|
|
2650
|
-
|
|
2651
|
-
} else if (seen.has(tag.const))
|
|
2821
|
+
note(at, "one_of_branch_shape");
|
|
2822
|
+
} else if (seen.has(tag.const)) note(at, "discriminator_duplicate", { value: tag.const });
|
|
2652
2823
|
else seen.add(tag.const);
|
|
2653
2824
|
}
|
|
2654
2825
|
return;
|
|
2655
2826
|
}
|
|
2656
|
-
if (node["x-clack-discriminator"] !== void 0)
|
|
2827
|
+
if (node["x-clack-discriminator"] !== void 0) note(at, "discriminator_misplaced");
|
|
2657
2828
|
if (!node.type) {
|
|
2658
|
-
|
|
2829
|
+
note(at, "type_missing");
|
|
2659
2830
|
return;
|
|
2660
2831
|
}
|
|
2661
|
-
for (const key of Object.keys(node)) if (TYPED_KEYS.has(key) && !SCALAR_KEYS[node.type].includes(key))
|
|
2662
|
-
const range = (low, high,
|
|
2663
|
-
if (typeof node[low] === "number" && typeof node[high] === "number" && node[low] > node[high])
|
|
2832
|
+
for (const key of Object.keys(node)) if (TYPED_KEYS.has(key) && !SCALAR_KEYS[node.type].includes(key)) note(`${at}/${key}`, "key_not_for_type", { type: node.type });
|
|
2833
|
+
const range = (low, high, kind) => {
|
|
2834
|
+
if (typeof node[low] === "number" && typeof node[high] === "number" && node[low] > node[high]) note(at, "range_invalid", { range: kind });
|
|
2664
2835
|
};
|
|
2665
|
-
range("minLength", "maxLength", "
|
|
2666
|
-
range("minItems", "maxItems", "
|
|
2667
|
-
range("minimum", "maximum", "
|
|
2668
|
-
if (node.type === "string" && typeof node.maxLength !== "number")
|
|
2669
|
-
if (node.type === "array" && (!node.items || typeof node.maxItems !== "number"))
|
|
2836
|
+
range("minLength", "maxLength", "length");
|
|
2837
|
+
range("minItems", "maxItems", "items");
|
|
2838
|
+
range("minimum", "maximum", "value");
|
|
2839
|
+
if (node.type === "string" && typeof node.maxLength !== "number") note(at, "string_max_length_missing");
|
|
2840
|
+
if (node.type === "array" && (!node.items || typeof node.maxItems !== "number")) note(at, "array_items_missing");
|
|
2670
2841
|
if (node.type === "array" && node.uniqueItems === true) {
|
|
2671
2842
|
let items = node.items;
|
|
2672
|
-
for (let hops = 0; typeof items?.$ref === "string" && hops < 64; hops++) items =
|
|
2673
|
-
if (!items || Array.isArray(items.oneOf) || !SCALAR_TYPES.has(items.type))
|
|
2843
|
+
for (let hops = 0; typeof items?.$ref === "string" && hops < 64; hops++) items = resolve10(items);
|
|
2844
|
+
if (!items || Array.isArray(items.oneOf) || !SCALAR_TYPES.has(items.type)) note(`${at}/uniqueItems`, "unique_items_not_scalar");
|
|
2674
2845
|
}
|
|
2675
2846
|
if (node.type === "object") {
|
|
2676
|
-
if (node.additionalProperties !== false || !node.properties || !Object.keys(node.properties).length)
|
|
2677
|
-
for (const name2 of node.required ?? []) if (!Object.hasOwn(node.properties ?? {}, name2))
|
|
2847
|
+
if (node.additionalProperties !== false || !node.properties || !Object.keys(node.properties).length) note(at, "object_shape");
|
|
2848
|
+
for (const name2 of node.required ?? []) if (!Object.hasOwn(node.properties ?? {}, name2)) note(at, "required_undeclared", { key: name2 });
|
|
2678
2849
|
}
|
|
2679
|
-
for (const value2 of node.enum ?? []) if (typeof value2 !== (node.type === "integer" ? "number" : node.type))
|
|
2850
|
+
for (const value2 of node.enum ?? []) if (typeof value2 !== (node.type === "integer" ? "number" : node.type)) note(at, "enum_type_mismatch");
|
|
2680
2851
|
if (node["x-clack-asset"]) {
|
|
2681
2852
|
assetPointers.push(at);
|
|
2682
|
-
if (node.type !== "string" || node.format !== "uuid" || node.maxLength !== 36 || node.enum)
|
|
2683
|
-
if (info.visibility === "private")
|
|
2684
|
-
} else if (node.format === "uuid" && node.type !== "string")
|
|
2853
|
+
if (node.type !== "string" || node.format !== "uuid" || node.maxLength !== 36 || node.enum) note(at, "asset_node_shape");
|
|
2854
|
+
if (info.visibility === "private") note(at, "asset_in_private");
|
|
2855
|
+
} else if (node.format === "uuid" && node.type !== "string") note(at, "format_not_string");
|
|
2685
2856
|
if (node["x-clack-ai"]?.suggest === true) {
|
|
2686
|
-
if (info.visibility !== "public")
|
|
2857
|
+
if (info.visibility !== "public") note(at, "ai_suggest_private");
|
|
2687
2858
|
suggestRoots.push(at);
|
|
2688
2859
|
}
|
|
2689
2860
|
});
|
|
2690
|
-
if (properties > OUTPUT_DATA_LIMITS.properties)
|
|
2691
|
-
for (const root of suggestRoots) if (assetPointers.some((asset) => asset === root || asset.startsWith(`${root}/`)))
|
|
2861
|
+
if (properties > OUTPUT_DATA_LIMITS.properties) note("/", "properties_over");
|
|
2862
|
+
for (const root of suggestRoots) if (assetPointers.some((asset) => asset === root || asset.startsWith(`${root}/`))) note(root, "ai_suggest_has_asset");
|
|
2692
2863
|
return errors;
|
|
2693
2864
|
}
|
|
2694
2865
|
var ZWJ_AFTER = new RegExp("\\p{Extended_Pictographic}", "u");
|
|
@@ -5426,7 +5597,7 @@ function fillEditorHash(files) {
|
|
|
5426
5597
|
return new TextEncoder().encode(next);
|
|
5427
5598
|
}
|
|
5428
5599
|
async function prepareSkillPackage(source, options2 = {}) {
|
|
5429
|
-
const path =
|
|
5600
|
+
const path = resolve8(source);
|
|
5430
5601
|
let info;
|
|
5431
5602
|
try {
|
|
5432
5603
|
info = await lstat4(path);
|
|
@@ -5451,34 +5622,34 @@ async function prepareSkillPackage(source, options2 = {}) {
|
|
|
5451
5622
|
else return invalid2("\uC2A4\uD0AC \uB514\uB809\uD130\uB9AC \uB610\uB294 ZIP \uD30C\uC77C\uC744 \uC9C0\uC815\uD558\uC138\uC694.");
|
|
5452
5623
|
const inspected = inspectZip(
|
|
5453
5624
|
bytes2,
|
|
5454
|
-
info.isDirectory() ?
|
|
5625
|
+
info.isDirectory() ? basename5(path) : void 0,
|
|
5455
5626
|
info.isDirectory() && !options2.fillEditorHash ? "warn" : "error"
|
|
5456
5627
|
);
|
|
5457
5628
|
return { bytes: bytes2, sha256: hash(bytes2), ...inspected, ...filledManifest ? { filled_manifest: filledManifest } : {} };
|
|
5458
5629
|
}
|
|
5459
5630
|
|
|
5460
5631
|
// src/commands/skill.ts
|
|
5461
|
-
var uuid2 =
|
|
5462
|
-
var createdSchema =
|
|
5463
|
-
var uploadSchema =
|
|
5632
|
+
var uuid2 = z10.uuid();
|
|
5633
|
+
var createdSchema = z10.object({ id: uuid2, slug: z10.string(), type: z10.string() });
|
|
5634
|
+
var uploadSchema = z10.object({
|
|
5464
5635
|
version_id: uuid2,
|
|
5465
|
-
upload_url:
|
|
5466
|
-
headers:
|
|
5467
|
-
expires_at:
|
|
5468
|
-
max_upload_bytes:
|
|
5636
|
+
upload_url: z10.url(),
|
|
5637
|
+
headers: z10.record(z10.string(), z10.string()),
|
|
5638
|
+
expires_at: z10.string(),
|
|
5639
|
+
max_upload_bytes: z10.number().int().positive()
|
|
5469
5640
|
});
|
|
5470
|
-
var versionSchema =
|
|
5471
|
-
var skillSlug =
|
|
5472
|
-
var semver =
|
|
5473
|
-
var category =
|
|
5474
|
-
var visibility =
|
|
5475
|
-
var managedVersionSchema =
|
|
5641
|
+
var versionSchema = z10.object({ id: uuid2, skill_id: uuid2, version: z10.string(), review_status: z10.string() });
|
|
5642
|
+
var skillSlug = z10.string().regex(/^[a-z][a-z0-9-]{0,63}$/);
|
|
5643
|
+
var semver = z10.string().regex(/^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?$/);
|
|
5644
|
+
var category = z10.enum(["character_chat", "quiz", "worldbuilding", "gallery", "story", "agent_tool"]);
|
|
5645
|
+
var visibility = z10.enum(["private", "unlisted", "public"]);
|
|
5646
|
+
var managedVersionSchema = z10.object({
|
|
5476
5647
|
id: uuid2,
|
|
5477
5648
|
skill_id: uuid2,
|
|
5478
|
-
version:
|
|
5479
|
-
review_status:
|
|
5480
|
-
release_status:
|
|
5481
|
-
package_hash:
|
|
5649
|
+
version: z10.string(),
|
|
5650
|
+
review_status: z10.string(),
|
|
5651
|
+
release_status: z10.string(),
|
|
5652
|
+
package_hash: z10.string().nullable()
|
|
5482
5653
|
});
|
|
5483
5654
|
function serverData(schema, value2) {
|
|
5484
5655
|
const parsed = schema.safeParse(value2);
|
|
@@ -5578,7 +5749,7 @@ ${hint}`, error2.code, error2.status, error2.retryAfter);
|
|
|
5578
5749
|
function registerSkillCommands(program2, runtime2) {
|
|
5579
5750
|
const skill = program2.command("skill").description("\uC2A4\uD0AC \uD328\uD0A4\uC9C0 \uAC80\uC0AC\xB7\uC5C5\uB85C\uB4DC\xB7\uC2EC\uC0AC\xB7\uAC8C\uC2DC (skill:read\xB7write\xB7publish)");
|
|
5580
5751
|
runtime2.action(skill.command("list").description("\uC2A4\uD0AC \uBAA9\uB85D \uAC80\uC0C9 (skill:read)").option("-q, --query <text>", "\uC2A4\uD0AC \uC774\uB984 \uAC80\uC0C9").option("--category <category>", "\uBD84\uB958").option("--entity <entity>", "\uC0B0\uCD9C\uBB3C \uC5D4\uD2F0\uD2F0(character)").option("--type <type>", "\uC2A4\uD0AC \uC720\uD615(template|instruction|tool)").option("--official <value>", "\uACF5\uC2DD \uC2A4\uD0AC\uB9CC true \uB610\uB294 false").option("--cursor <id>", "\uB2E4\uC74C \uD398\uC774\uC9C0 UUID").option("--all", "\uBAA8\uB4E0 \uD398\uC774\uC9C0 \uC870\uD68C"), async (ctx, _args, opts) => {
|
|
5581
|
-
const query = opts.query === void 0 ? void 0 :
|
|
5752
|
+
const query = opts.query === void 0 ? void 0 : z10.string().trim().min(1).max(100).safeParse(opts.query);
|
|
5582
5753
|
if (query && !query.success) throw new CliError("\uAC80\uC0C9\uC5B4\uB294 1~100\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4.");
|
|
5583
5754
|
const selectedCategory = opts.category === void 0 ? void 0 : category.safeParse(opts.category);
|
|
5584
5755
|
if (selectedCategory && !selectedCategory.success) throw new CliError("\uC2A4\uD0AC \uBD84\uB958\uB97C \uD655\uC778\uD558\uC138\uC694.");
|
|
@@ -5653,11 +5824,11 @@ function registerSkillCommands(program2, runtime2) {
|
|
|
5653
5824
|
runtime2.action(skill.command("pack [dir]").description("\uC2A4\uD0AC \uD328\uD0A4\uC9C0 ZIP \uB9CC\uB4E4\uAE30 (\uB85C\uADF8\uC778 \uBD88\uD544\uC694, \uC5D0\uB514\uD130 \uC2A4\uD0AC\uC740 authoring.editor.sha256\uC744 \uCC44\uC6C0)").option("-o, --out <file>", "ZIP \uC800\uC7A5 \uACBD\uB85C (\uAE30\uBCF8: <\uC774\uB984>-<\uBC84\uC804>.zip)").option("--write-manifest", "\uCC44\uC6B4 sha256\uC744 \uB514\uB809\uD130\uB9AC\uC758 clack.skill.json\uC5D0\uB3C4 \uAE30\uB85D"), async (ctx, [dir], opts) => {
|
|
5654
5825
|
const source = dir ?? ".";
|
|
5655
5826
|
const prepared = await prepareSkillPackage(source, { fillEditorHash: true });
|
|
5656
|
-
const out =
|
|
5827
|
+
const out = resolve9(opts.out ?? `${prepared.manifest.name}-${prepared.manifest.version}.zip`);
|
|
5657
5828
|
const writeManifest = Boolean(opts.writeManifest && prepared.filled_manifest);
|
|
5658
5829
|
if (!ctx.options.dryRun) {
|
|
5659
5830
|
await writeFile2(out, prepared.bytes);
|
|
5660
|
-
if (writeManifest) await writeFile2(join3(
|
|
5831
|
+
if (writeManifest) await writeFile2(join3(resolve9(source), "clack.skill.json"), prepared.filled_manifest);
|
|
5661
5832
|
}
|
|
5662
5833
|
ctx.output({
|
|
5663
5834
|
...ctx.options.dryRun ? { dry_run: true } : {},
|
|
@@ -5687,7 +5858,7 @@ ${SDK_LOCATION_HELP}
|
|
|
5687
5858
|
]) {
|
|
5688
5859
|
if (value2 === void 0) continue;
|
|
5689
5860
|
if ((flag === "host-port" || flag === "editor-port") && !/^\d{2,5}$/.test(value2)) throw new CliError("\uD3EC\uD2B8\uB294 \uC22B\uC790\uC5EC\uC57C \uD569\uB2C8\uB2E4.");
|
|
5690
|
-
args.push(`--${flag}`, flag.endsWith("port") ? value2 :
|
|
5861
|
+
args.push(`--${flag}`, flag.endsWith("port") ? value2 : resolve9(value2));
|
|
5691
5862
|
}
|
|
5692
5863
|
const sdkDir = resolveSdkDir(opts.sdkDir);
|
|
5693
5864
|
const serve = join3(sdkDir, "mock-host/serve.mjs");
|
|
@@ -5695,10 +5866,10 @@ ${SDK_LOCATION_HELP}
|
|
|
5695
5866
|
ctx.output({ dry_run: true, sdk_dir: sdkDir, command: ["node", serve, ...args] });
|
|
5696
5867
|
return;
|
|
5697
5868
|
}
|
|
5698
|
-
await new Promise((done,
|
|
5869
|
+
await new Promise((done, fail) => {
|
|
5699
5870
|
const child = spawn(process.execPath, [serve, ...args], { stdio: "inherit" });
|
|
5700
|
-
child.on("error", () =>
|
|
5701
|
-
child.on("exit", (code) => code ?
|
|
5871
|
+
child.on("error", () => fail(new CliError("\uBAA8\uC758 \uD638\uC2A4\uD2B8\uB97C \uC2E4\uD589\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.", "SKILL_EDITOR_DEV_FAILED")));
|
|
5872
|
+
child.on("exit", (code) => code ? fail(new CliError(`\uBAA8\uC758 \uD638\uC2A4\uD2B8\uAC00 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4(\uCF54\uB4DC ${code}). SDK\uC5D0\uC11C pnpm build\uB97C \uBA3C\uC800 \uC2E4\uD589\uD588\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694.`, "SKILL_EDITOR_DEV_FAILED")) : done());
|
|
5702
5873
|
});
|
|
5703
5874
|
}
|
|
5704
5875
|
);
|
|
@@ -5827,14 +5998,14 @@ function editorReport(prepared) {
|
|
|
5827
5998
|
var SDK_LOCATION_HELP = "SDK\uB294 \uC544\uC9C1 npm\uC5D0 \uACF5\uAC1C\uB418\uC9C0 \uC54A\uC544 CLI\uC5D0 \uD3EC\uD568\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. SDK \uC18C\uC2A4 \uB514\uB809\uD130\uB9AC(\uD074\uB799 \uB0B4\uBD80 \uC791\uC5C5\uC790\uB294 \uB0B4\uBD80 \uC800\uC7A5\uC18C\uC758 clack-skill-editor-sdk)\uC5D0\uC11C pnpm install && pnpm build\uB97C \uC2E4\uD589\uD55C \uB4A4 --sdk-dir <SDK \uB514\uB809\uD130\uB9AC>, CLACK_SKILL_EDITOR_SDK_DIR=<SDK \uB514\uB809\uD130\uB9AC>, CLACK_MONOREPO_DIR=<\uB0B4\uBD80 \uC800\uC7A5\uC18C> \uC911 \uD558\uB098\uB85C \uC704\uCE58\uB97C \uC9C0\uC815\uD558\uC138\uC694.";
|
|
5828
5999
|
function resolveSdkDir(option) {
|
|
5829
6000
|
const candidates = [];
|
|
5830
|
-
if (option) candidates.push(
|
|
6001
|
+
if (option) candidates.push(resolve9(option));
|
|
5831
6002
|
else {
|
|
5832
|
-
if (process.env.CLACK_SKILL_EDITOR_SDK_DIR) candidates.push(
|
|
6003
|
+
if (process.env.CLACK_SKILL_EDITOR_SDK_DIR) candidates.push(resolve9(process.env.CLACK_SKILL_EDITOR_SDK_DIR));
|
|
5833
6004
|
try {
|
|
5834
|
-
candidates.push(
|
|
6005
|
+
candidates.push(resolve9(createRequire(join3(process.cwd(), "noop.js")).resolve("@clack/skill-editor-sdk/package.json"), ".."));
|
|
5835
6006
|
} catch {
|
|
5836
6007
|
}
|
|
5837
|
-
if (process.env.CLACK_MONOREPO_DIR) candidates.push(
|
|
6008
|
+
if (process.env.CLACK_MONOREPO_DIR) candidates.push(resolve9(process.env.CLACK_MONOREPO_DIR, "clack-skill-editor-sdk"));
|
|
5838
6009
|
}
|
|
5839
6010
|
const found = candidates.find((dir) => existsSync(join3(dir, "mock-host/serve.mjs")));
|
|
5840
6011
|
if (!found) throw new CliError(`\uC2A4\uD0AC \uC5D0\uB514\uD130 SDK(@clack/skill-editor-sdk)\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. ${SDK_LOCATION_HELP}`, "SKILL_EDITOR_SDK_NOT_FOUND");
|
|
@@ -5850,24 +6021,24 @@ function skillVersionIds(skillId, versionId) {
|
|
|
5850
6021
|
// src/lib/platform-mcp.ts
|
|
5851
6022
|
var protocolVersions = /* @__PURE__ */ new Set(["2024-11-05", "2025-03-26", "2025-06-18", "2025-11-25"]);
|
|
5852
6023
|
var maxLineBytes = 1024 * 1024;
|
|
5853
|
-
var collectionKey =
|
|
6024
|
+
var collectionKey = z11.string().regex(/^[A-Za-z0-9_-]{1,64}$/);
|
|
5854
6025
|
var patSchemas = {
|
|
5855
|
-
skillList:
|
|
5856
|
-
skillGet:
|
|
5857
|
-
skillPush:
|
|
5858
|
-
skillVersionRef:
|
|
5859
|
-
skillSubmit:
|
|
5860
|
-
skillRelease:
|
|
5861
|
-
skill_id:
|
|
5862
|
-
version_id:
|
|
5863
|
-
visibility:
|
|
5864
|
-
confirm:
|
|
6026
|
+
skillList: z11.object({ q: z11.string().trim().min(1).max(100).optional() }).strict(),
|
|
6027
|
+
skillGet: z11.object({ slug: z11.string().regex(/^[a-z][a-z0-9-]{0,63}$/) }).strict(),
|
|
6028
|
+
skillPush: z11.object({ dir: z11.string().min(1).max(4096).optional(), skill_id: z11.uuid().optional() }).strict(),
|
|
6029
|
+
skillVersionRef: z11.object({ skill_id: z11.uuid(), version_id: z11.uuid() }).strict(),
|
|
6030
|
+
skillSubmit: z11.object({ skill_id: z11.uuid(), version_id: z11.uuid(), confirm: z11.boolean().optional() }).strict(),
|
|
6031
|
+
skillRelease: z11.object({
|
|
6032
|
+
skill_id: z11.uuid(),
|
|
6033
|
+
version_id: z11.uuid(),
|
|
6034
|
+
visibility: z11.enum(["private", "unlisted", "public"]),
|
|
6035
|
+
confirm: z11.boolean().optional()
|
|
5865
6036
|
}).strict(),
|
|
5866
|
-
contentPublish:
|
|
5867
|
-
sharedCollections:
|
|
5868
|
-
sharedList:
|
|
5869
|
-
sharedDocument:
|
|
5870
|
-
sharedModerate:
|
|
6037
|
+
contentPublish: z11.object({ content_id: z11.uuid(), version_id: z11.uuid(), confirm: z11.boolean().optional() }).strict(),
|
|
6038
|
+
sharedCollections: z11.object({ content_id: z11.uuid() }).strict(),
|
|
6039
|
+
sharedList: z11.object({ content_id: z11.uuid(), collection: collectionKey, limit: z11.number().int().min(1).max(100).optional() }).strict(),
|
|
6040
|
+
sharedDocument: z11.object({ content_id: z11.uuid(), collection: collectionKey, key: collectionKey }).strict(),
|
|
6041
|
+
sharedModerate: z11.object({ content_id: z11.uuid(), collection: collectionKey, key: collectionKey, confirm: z11.boolean().optional() }).strict()
|
|
5871
6042
|
};
|
|
5872
6043
|
var patToolNames = /* @__PURE__ */ new Set([
|
|
5873
6044
|
"platform_authoring",
|
|
@@ -5897,120 +6068,120 @@ function parsePat(schema, input, label) {
|
|
|
5897
6068
|
return parsed.data;
|
|
5898
6069
|
}
|
|
5899
6070
|
var toolDefinitions = [
|
|
5900
|
-
{ 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", ...
|
|
6071
|
+
{ 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", ...z11.toJSONSchema(authoringInput) }, annotations: { readOnlyHint: false, destructiveHint: true } },
|
|
5901
6072
|
{
|
|
5902
6073
|
name: "platform_usage_get",
|
|
5903
6074
|
description: "\uC11C\uBC84 \uD0A4\uAC00 \uC18D\uD55C \uCF58\uD150\uCE20\uC758 \uD50C\uB7AB\uD3FC \uC0AC\uC6A9\uB7C9\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4.",
|
|
5904
|
-
inputSchema:
|
|
6075
|
+
inputSchema: z11.toJSONSchema(platformReadSchemas.usage),
|
|
5905
6076
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5906
6077
|
},
|
|
5907
6078
|
{
|
|
5908
6079
|
name: "platform_server_data_get",
|
|
5909
6080
|
description: "\uC11C\uBC84 \uD0A4\uB85C \uCF58\uD150\uCE20 \uB370\uC774\uD130 \uBB38\uC11C\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4. data:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5910
|
-
inputSchema:
|
|
6081
|
+
inputSchema: z11.toJSONSchema(platformReadSchemas.get),
|
|
5911
6082
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5912
6083
|
},
|
|
5913
6084
|
{
|
|
5914
6085
|
name: "platform_server_data_list",
|
|
5915
6086
|
description: "\uC11C\uBC84 \uD0A4\uB85C \uCF58\uD150\uCE20 \uB370\uC774\uD130 \uBB38\uC11C \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. data:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5916
|
-
inputSchema:
|
|
6087
|
+
inputSchema: z11.toJSONSchema(platformReadSchemas.list),
|
|
5917
6088
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5918
6089
|
},
|
|
5919
6090
|
{
|
|
5920
6091
|
name: "platform_server_data_leaderboard",
|
|
5921
6092
|
description: "\uC11C\uBC84 \uD0A4\uB85C \uACF5\uC720 \uB370\uC774\uD130 \uC21C\uC704\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4. data:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5922
|
-
inputSchema:
|
|
6093
|
+
inputSchema: z11.toJSONSchema(platformReadSchemas.leaderboard),
|
|
5923
6094
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5924
6095
|
},
|
|
5925
6096
|
{
|
|
5926
6097
|
name: "platform_server_data_put",
|
|
5927
6098
|
description: "\uC11C\uBC84 \uD0A4\uB85C \uB2E8\uC77C \uBB38\uC11C \uC804\uCCB4\uB97C \uC800\uC7A5\uD569\uB2C8\uB2E4. \uAC1C\uC815 \uBC88\uD638 \uB610\uB294 \uBD80\uC7AC \uC870\uAC74\uACFC confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5928
|
-
inputSchema:
|
|
6099
|
+
inputSchema: z11.toJSONSchema(platformReadSchemas.put),
|
|
5929
6100
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
5930
6101
|
},
|
|
5931
6102
|
{
|
|
5932
6103
|
name: "platform_server_data_patch",
|
|
5933
6104
|
description: "\uC11C\uBC84 \uD0A4\uB85C \uB2E8\uC77C \uBB38\uC11C\uB97C \uBCD1\uD569 \uC218\uC815\uD569\uB2C8\uB2E4. \uAC1C\uC815 \uBC88\uD638\uC640 confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5934
|
-
inputSchema:
|
|
6105
|
+
inputSchema: z11.toJSONSchema(platformReadSchemas.patch),
|
|
5935
6106
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
5936
6107
|
},
|
|
5937
6108
|
{
|
|
5938
6109
|
name: "platform_server_data_delete",
|
|
5939
6110
|
description: "\uC11C\uBC84 \uD0A4\uB85C \uB2E8\uC77C \uBB38\uC11C\uB97C \uC0AD\uC81C\uD558\uAC70\uB098 \uC228\uAE41\uB2C8\uB2E4. confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5940
|
-
inputSchema:
|
|
6111
|
+
inputSchema: z11.toJSONSchema(platformReadSchemas.delete),
|
|
5941
6112
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
5942
6113
|
},
|
|
5943
6114
|
// 아래는 개인 액세스 토큰(CLACK_TOKEN, pat_)으로 동작하는 개인 도구다. 서버 키 도구와 인증 평면이 다르다.
|
|
5944
6115
|
{
|
|
5945
6116
|
name: "platform_skill_list",
|
|
5946
6117
|
description: "\uACF5\uAC1C \uC2A4\uD0AC \uBAA9\uB85D\uC744 \uC774\uB984\uC73C\uB85C \uAC80\uC0C9\uD569\uB2C8\uB2E4. skill:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5947
|
-
inputSchema:
|
|
6118
|
+
inputSchema: z11.toJSONSchema(patSchemas.skillList),
|
|
5948
6119
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5949
6120
|
},
|
|
5950
6121
|
{
|
|
5951
6122
|
name: "platform_skill_get",
|
|
5952
6123
|
description: "\uC2A4\uD0AC \uC0C1\uC138\uB97C \uC774\uB984(slug)\uC73C\uB85C \uC870\uD68C\uD569\uB2C8\uB2E4. skill:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5953
|
-
inputSchema:
|
|
6124
|
+
inputSchema: z11.toJSONSchema(patSchemas.skillGet),
|
|
5954
6125
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5955
6126
|
},
|
|
5956
6127
|
{
|
|
5957
6128
|
name: "platform_skill_push",
|
|
5958
6129
|
description: "\uB85C\uCEEC \uC2A4\uD0AC \uB514\uB809\uD130\uB9AC\uB97C \uAC80\uC99D\uD558\uACE0 \uC0C8 \uBC84\uC804\uC73C\uB85C \uC5C5\uB85C\uB4DC\uD569\uB2C8\uB2E4. dir\uC744 \uC0DD\uB7B5\uD558\uBA74 \uD604\uC7AC \uB514\uB809\uD130\uB9AC\uB97C \uC0AC\uC6A9\uD569\uB2C8\uB2E4. skill:write \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5959
|
-
inputSchema:
|
|
6130
|
+
inputSchema: z11.toJSONSchema(patSchemas.skillPush),
|
|
5960
6131
|
annotations: { readOnlyHint: false, destructiveHint: false }
|
|
5961
6132
|
},
|
|
5962
6133
|
{
|
|
5963
6134
|
name: "platform_skill_status",
|
|
5964
6135
|
description: "\uB0B4 \uC2A4\uD0AC \uBC84\uC804\uC758 \uC2EC\uC0AC\xB7\uAC8C\uC2DC \uC0C1\uD0DC\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4. skill:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5965
|
-
inputSchema:
|
|
6136
|
+
inputSchema: z11.toJSONSchema(patSchemas.skillVersionRef),
|
|
5966
6137
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5967
6138
|
},
|
|
5968
6139
|
{
|
|
5969
6140
|
name: "platform_skill_submit",
|
|
5970
6141
|
description: "\uAC80\uC99D \uC644\uB8CC\uD55C \uC2A4\uD0AC \uBC84\uC804\uC744 \uC2EC\uC0AC\uC5D0 \uC81C\uCD9C\uD569\uB2C8\uB2E4. skill:write\uC640 skill:publish \uAD8C\uD55C(\uB458 \uB2E4)\uACFC confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5971
|
-
inputSchema:
|
|
6142
|
+
inputSchema: z11.toJSONSchema(patSchemas.skillSubmit),
|
|
5972
6143
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
5973
6144
|
},
|
|
5974
6145
|
{
|
|
5975
6146
|
name: "platform_skill_release",
|
|
5976
6147
|
description: "\uC2B9\uC778\uB41C \uC2A4\uD0AC \uBC84\uC804\uC744 \uACF5\uAC1C \uBC94\uC704\uB85C \uAC8C\uC2DC\uD569\uB2C8\uB2E4. skill:publish \uAD8C\uD55C\uACFC confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5977
|
-
inputSchema:
|
|
6148
|
+
inputSchema: z11.toJSONSchema(patSchemas.skillRelease),
|
|
5978
6149
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
5979
6150
|
},
|
|
5980
6151
|
{
|
|
5981
6152
|
name: "platform_content_publish",
|
|
5982
6153
|
description: "\uC2B9\uC778\uB41C \uB0B4 HTML \uCF58\uD150\uCE20 \uBC84\uC804\uC744 \uACF5\uAC1C\uD569\uB2C8\uB2E4. creator-content:publish \uAD8C\uD55C\uACFC confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5983
|
-
inputSchema:
|
|
6154
|
+
inputSchema: z11.toJSONSchema(patSchemas.contentPublish),
|
|
5984
6155
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
5985
6156
|
},
|
|
5986
6157
|
{
|
|
5987
6158
|
name: "platform_shared_collections_list",
|
|
5988
6159
|
description: "\uB0B4 \uCF58\uD150\uCE20\uC758 \uC774\uC6A9\uC790 \uACF5\uAC1C(shared) \uBB38\uC11C \uCEEC\uB809\uC158 \uC774\uB984\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. platform:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5989
|
-
inputSchema:
|
|
6160
|
+
inputSchema: z11.toJSONSchema(patSchemas.sharedCollections),
|
|
5990
6161
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5991
6162
|
},
|
|
5992
6163
|
{
|
|
5993
6164
|
name: "platform_shared_documents_list",
|
|
5994
6165
|
description: "\uB0B4 \uCF58\uD150\uCE20\uC758 \uACF5\uC720 \uBB38\uC11C \uBAA9\uB85D\uC744 \uC870\uD68C\uD569\uB2C8\uB2E4. platform:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
5995
|
-
inputSchema:
|
|
6166
|
+
inputSchema: z11.toJSONSchema(patSchemas.sharedList),
|
|
5996
6167
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
5997
6168
|
},
|
|
5998
6169
|
{
|
|
5999
6170
|
name: "platform_shared_document_get",
|
|
6000
6171
|
description: "\uB0B4 \uCF58\uD150\uCE20\uC758 \uACF5\uC720 \uBB38\uC11C \uD558\uB098\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4. platform:read \uAD8C\uD55C\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
6001
|
-
inputSchema:
|
|
6172
|
+
inputSchema: z11.toJSONSchema(patSchemas.sharedDocument),
|
|
6002
6173
|
annotations: { readOnlyHint: true, destructiveHint: false }
|
|
6003
6174
|
},
|
|
6004
6175
|
{
|
|
6005
6176
|
name: "platform_shared_document_hide",
|
|
6006
6177
|
description: "\uC774\uC6A9\uC790\uAC00 \uC4F4 \uACF5\uC720 \uBB38\uC11C\uB97C \uC228\uAE41\uB2C8\uB2E4. platform:write \uAD8C\uD55C\uACFC confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
6007
|
-
inputSchema:
|
|
6178
|
+
inputSchema: z11.toJSONSchema(patSchemas.sharedModerate),
|
|
6008
6179
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
6009
6180
|
},
|
|
6010
6181
|
{
|
|
6011
6182
|
name: "platform_shared_document_delete",
|
|
6012
6183
|
description: "\uC774\uC6A9\uC790\uAC00 \uC4F4 \uACF5\uC720 \uBB38\uC11C\uB97C \uC601\uAD6C \uC0AD\uC81C\uD569\uB2C8\uB2E4. platform:write \uAD8C\uD55C\uACFC confirm:true\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
6013
|
-
inputSchema:
|
|
6184
|
+
inputSchema: z11.toJSONSchema(patSchemas.sharedModerate),
|
|
6014
6185
|
annotations: { readOnlyHint: false, destructiveHint: true }
|
|
6015
6186
|
}
|
|
6016
6187
|
];
|
|
@@ -6251,14 +6422,14 @@ function registerIntegrationCommands(program2, runtime2) {
|
|
|
6251
6422
|
|
|
6252
6423
|
// src/commands/page.ts
|
|
6253
6424
|
import { Option as Option3 } from "commander";
|
|
6254
|
-
import { z as
|
|
6255
|
-
var uuid3 = (value2) => parse(
|
|
6256
|
-
var revision3 = (value2) => parse(
|
|
6425
|
+
import { z as z12 } from "zod";
|
|
6426
|
+
var uuid3 = (value2) => parse(z12.uuid(), value2);
|
|
6427
|
+
var revision3 = (value2) => parse(z12.coerce.number().int().nonnegative().max(4294967295), value2);
|
|
6257
6428
|
var base = "/v4/creator/custom-pages";
|
|
6258
|
-
var presentationSchema =
|
|
6259
|
-
schema_version:
|
|
6260
|
-
header_mode:
|
|
6261
|
-
color_scheme:
|
|
6429
|
+
var presentationSchema = z12.object({
|
|
6430
|
+
schema_version: z12.literal(1),
|
|
6431
|
+
header_mode: z12.enum(["fixed", "scroll_hide", "translucent_scroll_hide", "floating_close", "floating_close_safe_area"]),
|
|
6432
|
+
color_scheme: z12.enum(["light", "dark"])
|
|
6262
6433
|
}).strict();
|
|
6263
6434
|
function registerPageCommands(program2, runtime2) {
|
|
6264
6435
|
const page = program2.command("page").description("\uC138\uACC4\uAD00\xB7\uB0B4 \uACF5\uAC1C \uD648 HTML \uAFB8\uBBF8\uAE30 (custom-page:read\xB7write\xB7publish)");
|
|
@@ -6266,7 +6437,7 @@ function registerPageCommands(program2, runtime2) {
|
|
|
6266
6437
|
runtime2.action(page.command("status <id>").description("\uD398\uC774\uC9C0\uC640 \uBC84\uC804\xB7\uC218\uC815 \uBC88\uD638 \uC0C1\uD0DC (custom-page:read)"), async (ctx, [id2]) => ctx.output(await ctx.api.request("GET", `${base}/${uuid3(id2)}`)));
|
|
6267
6438
|
runtime2.action(page.command("create").description("\uAFB8\uBC00 \uD398\uC774\uC9C0 \uB4F1\uB85D (custom-page:write)").addOption(new Option3("--target <type>", "\uAFB8\uBC00 \uB300\uC0C1").choices(["profile", "space"]).makeOptionMandatory()).option("--space-id <uuid>", "\uC138\uACC4\uAD00 ID").requiredOption("--policy-version <version>", "\uB3D9\uC758\uD55C \uCF58\uD150\uCE20 \uC81C\uACF5 \uC815\uCC45 \uBC84\uC804"), async (ctx, _args, opts) => {
|
|
6268
6439
|
if (opts.target === "profile" && opts.spaceId) throw new CliError("\uB0B4 \uACF5\uAC1C \uD648\uC5D0\uB294 \uC138\uACC4\uAD00 ID\uB97C \uC9C0\uC815\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.");
|
|
6269
|
-
const policy = parse(
|
|
6440
|
+
const policy = parse(z12.literal("2026-09-22"), opts.policyVersion);
|
|
6270
6441
|
await mutate(ctx, "POST", base, { target_type: opts.target, ...opts.target === "space" ? { space_id: uuid3(opts.spaceId) } : {}, policy_version: policy });
|
|
6271
6442
|
});
|
|
6272
6443
|
runtime2.action(page.command("upload <id> <file>").description("HTML/ZIP \uC5C5\uB85C\uB4DC\uB85C \uC0C8 \uBE44\uACF5\uAC1C \uBC84\uC804 \uC0DD\uC131 (custom-page:write)").addOption(new Option3("--header <mode>", "\uD5E4\uB354 \uD45C\uC2DC").choices(["fixed", "scroll_hide", "translucent_scroll_hide", "floating_close", "floating_close_safe_area"]).default("fixed")).addOption(new Option3("--color <scheme>", "\uD5E4\uB354 \uC0C9\uC0C1").choices(["light", "dark"]).default("light")), async (ctx, [id2, file], opts) => {
|
|
@@ -6331,7 +6502,8 @@ try {
|
|
|
6331
6502
|
status: failure.status,
|
|
6332
6503
|
code: failure.code,
|
|
6333
6504
|
message: failure.message,
|
|
6334
|
-
...failure.retryAfter ? { retry_after: failure.retryAfter } : {}
|
|
6505
|
+
...failure.retryAfter ? { retry_after: failure.retryAfter } : {},
|
|
6506
|
+
...failure.recovery ? { recovery: failure.recovery } : {}
|
|
6335
6507
|
});
|
|
6336
6508
|
const json2 = program.opts().json || process.argv.includes("--json") || await store.resolve(program.opts(), true).then((value2) => value2.options.json).catch(() => false);
|
|
6337
6509
|
if (json2) process.stdout.write(JSON.stringify(envelope) + "\n");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clack-platform/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "클랙 계정의 상품·콘텐츠·프로필을 관리하는 CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"test": "node scripts/test.mjs",
|
|
40
40
|
"build": "tsup src/cli.ts --format esm --target node20 --clean",
|
|
41
41
|
"check": "pnpm typecheck && node scripts/check-schema-sync.mjs && pnpm test && pnpm build",
|
|
42
|
-
"check:release": "pnpm typecheck && node scripts/check-schema-sync.mjs --strict && pnpm test && pnpm build",
|
|
42
|
+
"check:release": "pnpm typecheck && node scripts/check-schema-sync.mjs --strict && node scripts/sync-vendor-types.mjs --check && pnpm test && pnpm build",
|
|
43
43
|
"prepack": "pnpm build"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|