@clipwright/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dimantika LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # @clipwright/sdk
2
+
3
+ TypeScript client for the [Clipwright](https://clipwright.io) UGC video API.
4
+
5
+ ```ts
6
+ import { ClipwrightClient } from "@clipwright/sdk";
7
+
8
+ const client = new ClipwrightClient({ apiKey: process.env.CLIPWRIGHT_API_KEY! });
9
+
10
+ const quote = await client.quoteUgc({ script: "Hello from Clipwright." });
11
+ const run = await client.makeUgc({ script: "Hello from Clipwright." });
12
+ ```
13
+
14
+ `makeUgc` renders a clip and **costs money**; `quoteUgc` does not. Every call
15
+ carries an idempotency key derived from the input and from this installation's
16
+ id, so a retried request returns the original run instead of paying twice. Pass
17
+ `idempotencyKey` explicitly when you deliberately want a fresh run.
18
+
19
+ Requires `CLIPWRIGHT_CLIENT_ID`, or a writable `~/.clipwright/` for the SDK to
20
+ create one on first use. It fails loudly rather than generating a throwaway id,
21
+ because a per-process id would disable duplicate protection without saying so.
@@ -0,0 +1 @@
1
+ export declare function resolveClientId(): string;
@@ -0,0 +1,51 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import { join } from "node:path";
5
+ /**
6
+ * Устойчивая идентичность УСТАНОВКИ клиента — префикс ключа идемпотентности.
7
+ *
8
+ * ЗАЧЕМ ЭТО ВООБЩЕ СУЩЕСТВУЕТ (C1): ключ идемпотентности склеивается из хеша
9
+ * входа И идентичности клиента. Хеш входа один и тот же на любой машине, поэтому
10
+ * без стабильного per-установка `clientId` дедупликация повторного `POST /run`
11
+ * либо не работает между перезапусками процесса, либо, наоборот, схлопывает
12
+ * раны разных пользователей. Одна установка = одна идентичность = один денежный
13
+ * контур дедупа.
14
+ *
15
+ * ПОЧЕМУ ПАДЕНИЕ, А НЕ ЭФЕМЕРНЫЙ id ПРИ ОШИБКЕ ФС: тихий фолбэк на случайный
16
+ * id при каждом запуске ВЫКЛЮЧАЕТ C1 целиком (каждый старт — новый клиент →
17
+ * дедуп мёртв → повторный рендер за деньги). Лучше громко потребовать выставить
18
+ * `CLIPWRIGHT_CLIENT_ID`, чем молча жечь кредиты.
19
+ */
20
+ /** Приоритетный источник — явный env: не читает и не пишет файл вовсе. */
21
+ const ENV_VAR = "CLIPWRIGHT_CLIENT_ID";
22
+ export function resolveClientId() {
23
+ const fromEnv = process.env[ENV_VAR];
24
+ if (fromEnv !== undefined && fromEnv.trim().length > 0) {
25
+ return fromEnv.trim();
26
+ }
27
+ const dir = join(homedir(), ".clipwright");
28
+ const file = join(dir, "client-id");
29
+ try {
30
+ if (existsSync(file)) {
31
+ const existing = readFileSync(file, "utf8").trim();
32
+ if (existing.length > 0) {
33
+ return existing;
34
+ }
35
+ }
36
+ // Первый запуск на этой установке: рождаем стабильный id и закрепляем его
37
+ // на диске. UUID без дефисов — компактнее в заголовке Idempotency-Key.
38
+ const id = randomUUID().replace(/-/g, "");
39
+ mkdirSync(dir, { recursive: true });
40
+ writeFileSync(file, id, "utf8");
41
+ return id;
42
+ }
43
+ catch (cause) {
44
+ // ЛЮБАЯ невозможность прочитать/создать файл (read-only HOME в чужом хосте,
45
+ // нет прав) — это НЕ повод на тихий эфемерный id (см. заголовок модуля).
46
+ throw new Error(`Cannot read or create ~/.clipwright/client-id. Set the ${ENV_VAR} ` +
47
+ `environment variable to a stable per-install identifier so idempotent ` +
48
+ `retries deduplicate instead of billing twice.`, { cause });
49
+ }
50
+ }
51
+ //# sourceMappingURL=client-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-id.js","sourceRoot":"","sources":["../src/client-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;;;;;;GAcG;AAEH,0EAA0E;AAC1E,MAAM,OAAO,GAAG,sBAAsB,CAAC;AAEvC,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvD,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAEpC,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;YACnD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxB,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,uEAAuE;QACvE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1C,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,aAAa,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4EAA4E;QAC5E,yEAAyE;QACzE,MAAM,IAAI,KAAK,CACb,0DAA0D,OAAO,GAAG;YAClE,wEAAwE;YACxE,+CAA+C,EACjD,EAAE,KAAK,EAAE,CACV,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,67 @@
1
+ import { type MakeUgcInput, type MakeUgcInputArgs, type QuoteResponse, type Run, type RunRead, type VoicePreset, type VoicePresetName } from "@clipwright/core";
2
+ export interface ClipwrightClientOptions {
3
+ apiKey: string;
4
+ baseUrl?: string | undefined;
5
+ /** Интервал поллинга статуса рана, мс. */
6
+ pollIntervalMs?: number | undefined;
7
+ }
8
+ /** Опции старта рана. `attempt` даёт суффикс `:N`; явный ключ его перекрывает. */
9
+ export interface StartUgcOptions {
10
+ /** Номер попытки (дефолт 1) → суффикс `:N` у ключа идемпотентности. */
11
+ attempt?: number | undefined;
12
+ /** Явный ключ «намеренно новый ран» — перекрывает вычисленный. */
13
+ idempotencyKey?: string | undefined;
14
+ }
15
+ /** Опции синхронного `makeUgc`: проброс `attempt` + дедлайн поллинга. */
16
+ export interface MakeUgcOptions {
17
+ attempt?: number | undefined;
18
+ /** Дедлайн ожидания терминального состояния, мс (дефолт 10 мин). */
19
+ maxWaitMs?: number | undefined;
20
+ }
21
+ /** Один пресет каталога `/v1/voices`, с именем — как отдаёт GET /v1/voices. */
22
+ export interface VoiceCatalogEntry extends VoicePreset {
23
+ name: VoicePresetName;
24
+ }
25
+ export declare class ClipwrightClient {
26
+ #private;
27
+ constructor(opts: ClipwrightClientOptions);
28
+ /** Оценка стоимости без списания кредитов. */
29
+ quoteUgc(input: MakeUgcInputArgs): Promise<QuoteResponse>;
30
+ /**
31
+ * Запуск генерации; возвращает ран сразу (state=queued).
32
+ *
33
+ * Ключ идемпотентности формируется ЗДЕСЬ, а не на вызывающей поверхности:
34
+ * суффикс `:N` (по `attempt`, дефолт 1) пишется ВСЕГДА, иначе MCP дал бы
35
+ * `<hash>`, а CLI `<hash>:1` — межповерхностный шов, в котором дедуп ломается.
36
+ */
37
+ startUgc(input: MakeUgcInputArgs, opts?: StartUgcOptions): Promise<Run>;
38
+ /**
39
+ * Курируемый каталог голосов для `voice`/`voice_id` (US-516). Отдаёт то же,
40
+ * что и `/v1/voices` — статический список из @clipwright/core, БЕЗ вендорских
41
+ * id (они не покидают адаптер воркера). Каталог курируемый по дизайну: это
42
+ * не полный список голосов вендора — остальные достижимы сырым `voice_id`.
43
+ */
44
+ listVoices(): Promise<VoiceCatalogEntry[]>;
45
+ /**
46
+ * Чтение рана в ТОЛЕРАНТНОЙ проекции (`runRead`, `state: string`): сервер мог
47
+ * добавить стадию, которой не знает установленный SDK (docs/12:198). Поэтому
48
+ * `safeParse` с деградацией к сырому телу вместо строгого `run.parse` — иначе
49
+ * неизвестная стадия уронила бы `getRun` у каждого уже установленного MCP.
50
+ * Тип возврата — `RunRead` (`state: string`), а НЕ узкий `Run` (условие
51
+ * Architect №3): иначе `isTerminal(state)` не типчекнулся бы и потребители
52
+ * приняли бы `state` за закрытый enum.
53
+ */
54
+ getRun(runId: string): Promise<RunRead>;
55
+ /**
56
+ * Запуск + поллинг до терминального состояния.
57
+ *
58
+ * [C-5] `attempt` ПРОБРАСЫВАЕТСЯ во внутренний `startUgc`: CLI `make` зовёт
59
+ * именно `makeUgc`, а не `startUgc`, — без проброса `--retry` молча терялся бы.
60
+ * [US-207] `maxWaitMs` — дедлайн: застрявший ран иначе вешал бы `clipwright
61
+ * make` навсегда. Проверка дедлайна ДО сна (и сон не длиннее остатка), чтобы
62
+ * бросок случался вовремя, а не через целый интервал поллинга.
63
+ */
64
+ makeUgc(input: MakeUgcInputArgs, opts?: MakeUgcOptions, onProgress?: (run: RunRead) => void): Promise<RunRead>;
65
+ }
66
+ export { resolveClientId } from "./client-id.js";
67
+ export type { MakeUgcInput, MakeUgcInputArgs, QuoteResponse, Run, RunRead };
package/dist/index.js ADDED
@@ -0,0 +1,134 @@
1
+ import { run as runSchema, runRead as runReadSchema, isTerminal, FAILED_STATE, quoteResponse, } from "@clipwright/core";
2
+ import { idempotencyKeyFor } from "@clipwright/core/idempotency";
3
+ import { resolveClientId } from "./client-id.js";
4
+ /** Прод-API по умолчанию: SDK «просто работает» без явного baseUrl. */
5
+ const DEFAULT_BASE_URL = "https://api-production-7e69.up.railway.app";
6
+ /** Дефолтный дедлайн поллинга: ≥5× над проекцией рендера (~113 с, docs/13). */
7
+ const DEFAULT_MAX_WAIT_MS = 600_000;
8
+ export class ClipwrightClient {
9
+ #apiKey;
10
+ #baseUrl;
11
+ #pollIntervalMs;
12
+ /**
13
+ * [A5] Идентичность установки резолвится ЛЕНИВО (при первом старте рана) и
14
+ * кэшируется здесь. Конструктор её НЕ трогает: MCP-сервер строит клиент НА
15
+ * ИМПОРТЕ модуля, ДО `server.connect`; если бы резолвер (пишущий в ~/.clipwright)
16
+ * падал в конструкторе на read-only HOME, он убил бы ВЕСЬ MCP, включая
17
+ * `quote_ugc`, которому clientId вообще не нужен.
18
+ */
19
+ #clientId;
20
+ constructor(opts) {
21
+ this.#apiKey = opts.apiKey;
22
+ this.#baseUrl = opts.baseUrl ?? DEFAULT_BASE_URL;
23
+ this.#pollIntervalMs = opts.pollIntervalMs ?? 5_000;
24
+ }
25
+ /** Ленивый резолв + кэш идентичности установки (см. `#clientId`). */
26
+ #getClientId() {
27
+ if (this.#clientId === undefined) {
28
+ this.#clientId = resolveClientId();
29
+ }
30
+ return this.#clientId;
31
+ }
32
+ async #request(path, init) {
33
+ const res = await fetch(`${this.#baseUrl}${path}`, {
34
+ ...init,
35
+ headers: {
36
+ Authorization: `Bearer ${this.#apiKey}`,
37
+ "Content-Type": "application/json",
38
+ ...init?.headers,
39
+ },
40
+ });
41
+ const body = (await res.json());
42
+ if (!res.ok) {
43
+ throw new Error(body.error?.message ?? `HTTP ${res.status} on ${path}`);
44
+ }
45
+ return body;
46
+ }
47
+ /** Оценка стоимости без списания кредитов. */
48
+ async quoteUgc(input) {
49
+ const body = await this.#request("/v1/skills/make_ugc/quote", {
50
+ method: "POST",
51
+ body: JSON.stringify(input),
52
+ });
53
+ return quoteResponse.parse(body);
54
+ }
55
+ /**
56
+ * Запуск генерации; возвращает ран сразу (state=queued).
57
+ *
58
+ * Ключ идемпотентности формируется ЗДЕСЬ, а не на вызывающей поверхности:
59
+ * суффикс `:N` (по `attempt`, дефолт 1) пишется ВСЕГДА, иначе MCP дал бы
60
+ * `<hash>`, а CLI `<hash>:1` — межповерхностный шов, в котором дедуп ломается.
61
+ */
62
+ async startUgc(input, opts) {
63
+ const key = opts?.idempotencyKey ??
64
+ `${idempotencyKeyFor(input, this.#getClientId())}:${opts?.attempt ?? 1}`;
65
+ const body = await this.#request("/v1/skills/make_ugc/run", {
66
+ method: "POST",
67
+ body: JSON.stringify(input),
68
+ headers: { "Idempotency-Key": key },
69
+ });
70
+ return runSchema.parse(body);
71
+ }
72
+ /**
73
+ * Курируемый каталог голосов для `voice`/`voice_id` (US-516). Отдаёт то же,
74
+ * что и `/v1/voices` — статический список из @clipwright/core, БЕЗ вендорских
75
+ * id (они не покидают адаптер воркера). Каталог курируемый по дизайну: это
76
+ * не полный список голосов вендора — остальные достижимы сырым `voice_id`.
77
+ */
78
+ async listVoices() {
79
+ const body = (await this.#request("/v1/voices"));
80
+ return body.voices;
81
+ }
82
+ /**
83
+ * Чтение рана в ТОЛЕРАНТНОЙ проекции (`runRead`, `state: string`): сервер мог
84
+ * добавить стадию, которой не знает установленный SDK (docs/12:198). Поэтому
85
+ * `safeParse` с деградацией к сырому телу вместо строгого `run.parse` — иначе
86
+ * неизвестная стадия уронила бы `getRun` у каждого уже установленного MCP.
87
+ * Тип возврата — `RunRead` (`state: string`), а НЕ узкий `Run` (условие
88
+ * Architect №3): иначе `isTerminal(state)` не типчекнулся бы и потребители
89
+ * приняли бы `state` за закрытый enum.
90
+ */
91
+ async getRun(runId) {
92
+ const body = await this.#request(`/v1/runs/${runId}`);
93
+ const parsed = runReadSchema.safeParse(body);
94
+ return parsed.success ? parsed.data : body;
95
+ }
96
+ /**
97
+ * Запуск + поллинг до терминального состояния.
98
+ *
99
+ * [C-5] `attempt` ПРОБРАСЫВАЕТСЯ во внутренний `startUgc`: CLI `make` зовёт
100
+ * именно `makeUgc`, а не `startUgc`, — без проброса `--retry` молча терялся бы.
101
+ * [US-207] `maxWaitMs` — дедлайн: застрявший ран иначе вешал бы `clipwright
102
+ * make` навсегда. Проверка дедлайна ДО сна (и сон не длиннее остатка), чтобы
103
+ * бросок случался вовремя, а не через целый интервал поллинга.
104
+ */
105
+ async makeUgc(input, opts, onProgress) {
106
+ const maxWaitMs = opts?.maxWaitMs ?? DEFAULT_MAX_WAIT_MS;
107
+ const deadline = Date.now() + maxWaitMs;
108
+ // Начальный ран приходит строгим `Run` из `startUgc`; расширяем тип до
109
+ // `RunRead`, т.к. дальше присваиваем сюда толерантный результат `getRun`.
110
+ let current = await this.startUgc(input, { attempt: opts?.attempt });
111
+ // Терминальность — через разделяемый `isTerminal`, а не литералы: неизвестный
112
+ // ТЕРМИНАЛЬНЫЙ статус сервера (`isTerminal=false`) осознанно поллится до
113
+ // `maxWaitMs` и даёт чистый таймаут с `run_id`, а не вечный цикл (PM4).
114
+ while (!isTerminal(current.state)) {
115
+ const remaining = deadline - Date.now();
116
+ if (remaining <= 0) {
117
+ throw new Error(`makeUgc timed out after ${maxWaitMs}ms; run ${current.run_id} is still ` +
118
+ `${current.state}. Poll it later with getRun("${current.run_id}").`);
119
+ }
120
+ await new Promise((r) => setTimeout(r, Math.min(this.#pollIntervalMs, remaining)));
121
+ current = await this.getRun(current.run_id);
122
+ onProgress?.(current);
123
+ }
124
+ // Терминально: различение исхода — именованной константой core (не
125
+ // позиционным индексом массива: переупорядочивание молча инвертировало бы
126
+ // успех/провал).
127
+ if (current.state === FAILED_STATE) {
128
+ throw new Error(current.error ?? "run failed");
129
+ }
130
+ return current;
131
+ }
132
+ }
133
+ export { resolveClientId } from "./client-id.js";
134
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@clipwright/sdk",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript client for the Clipwright UGC video API",
5
+ "license": "MIT",
6
+ "author": "Dimantika LLC",
7
+ "homepage": "https://clipwright.io",
8
+ "type": "module",
9
+ "publishConfig": {
10
+ "access": "public"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "engines": {
16
+ "node": ">=20"
17
+ },
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ }
23
+ },
24
+ "dependencies": {
25
+ "zod": "^4.4.3",
26
+ "@clipwright/core": "0.1.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^26.1.1"
30
+ },
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.json",
33
+ "typecheck": "tsc -p tsconfig.typecheck.json --noEmit"
34
+ }
35
+ }