@curvet/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 Curvet
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,160 @@
1
+ # @curvet/sdk
2
+
3
+ Official TypeScript SDK for the [Curvet](https://curvet.ai) Unified Playground API — chat, image, and video generation across multiple providers (OpenAI, Anthropic, Perplexity, DeepInfra) with **one API key and one balance**.
4
+
5
+ ```ts
6
+ import { Curvet } from "@curvet/sdk";
7
+
8
+ const curvet = new Curvet({ appKey: process.env.CURVET_APP_KEY });
9
+
10
+ const { response } = await curvet.chat.create({
11
+ model: "gpt-4o-mini",
12
+ messages: [{ role: "user", content: "Write a tagline for a freelance marketplace." }],
13
+ });
14
+ console.log(response);
15
+ ```
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npm install @curvet/sdk
21
+ ```
22
+
23
+ Requires Node 18+ (uses the built-in `fetch`). For older runtimes, pass a `fetch` implementation.
24
+
25
+ ## Authentication
26
+
27
+ Get an **App Key** from the Curvet Developer Portal (with Playground API access enabled). Provide it directly or via the `CURVET_APP_KEY` environment variable.
28
+
29
+ ```ts
30
+ const curvet = new Curvet({ appKey: "cvt_app_..." });
31
+ // or: export CURVET_APP_KEY=cvt_app_... then new Curvet()
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Chat
37
+
38
+ ```ts
39
+ const res = await curvet.chat.create({
40
+ model: "claude-sonnet-4-6",
41
+ messages: [
42
+ { role: "system", content: "You are concise." },
43
+ { role: "user", content: "Explain vector databases in one sentence." },
44
+ ],
45
+ temperature: 0.7,
46
+ maxTokens: 200,
47
+ });
48
+ console.log(res.response, res.usage.credits);
49
+ ```
50
+
51
+ ### Image
52
+
53
+ ```ts
54
+ const img = await curvet.image.generate({
55
+ model: "flux-2-klein-4b",
56
+ prompt: "An astronaut riding a unicorn on Mars, cinematic",
57
+ size: "1024x1024", // single field — not width/height
58
+ });
59
+ console.log(img.imageUrl);
60
+ ```
61
+
62
+ ### Video (async, handled for you)
63
+
64
+ Video runs as a background job. `generate()` submits **and polls to completion** — you just `await` it:
65
+
66
+ ```ts
67
+ const video = await curvet.video.generate(
68
+ { model: "wan-2.2", prompt: "Neon Tokyo street in the rain", mode: "text_to_video" },
69
+ { onProgress: (pct) => console.log(`${pct}%`) },
70
+ );
71
+ console.log(video.mediaUrl);
72
+ ```
73
+
74
+ Prefer fire-and-forget? Submit and poll yourself:
75
+
76
+ ```ts
77
+ const job = await curvet.video.submit({ model: "wan-2.2", prompt: "..." });
78
+ if (job.status !== "completed") {
79
+ const done = await curvet.jobs.handle(job.jobId!).wait();
80
+ console.log(done.mediaUrl);
81
+ }
82
+ // ...or check once later:
83
+ const status = await curvet.jobs.retrieve(job.jobId!);
84
+ ```
85
+
86
+ ### Models & balance
87
+
88
+ ```ts
89
+ const chatModels = await curvet.models.list({ type: "chat" });
90
+ const balance = await curvet.balance.get();
91
+ ```
92
+
93
+ ## Errors
94
+
95
+ Every failure throws a typed subclass of `CurvetError`:
96
+
97
+ ```ts
98
+ import { InsufficientBalanceError, RateLimitError, AuthError } from "@curvet/sdk";
99
+
100
+ try {
101
+ await curvet.image.generate({ model: "flux-2-klein-4b", prompt: "..." });
102
+ } catch (err) {
103
+ if (err instanceof InsufficientBalanceError) {
104
+ console.error(`Need ${err.required}, have ${err.available}`);
105
+ } else if (err instanceof RateLimitError) {
106
+ console.error(`Rate limited; resets at ${err.resetsAt}`);
107
+ } else if (err instanceof AuthError) {
108
+ console.error("Bad app key");
109
+ } else {
110
+ throw err;
111
+ }
112
+ }
113
+ ```
114
+
115
+ | Class | When |
116
+ |---|---|
117
+ | `AuthError` | 401 — missing/invalid app key |
118
+ | `PermissionError` | 403 — app inactive, playground disabled, model/category not allowed |
119
+ | `BadRequestError` | 400 — invalid/unknown model or payload |
120
+ | `InsufficientBalanceError` | 402 — not enough credits (`.required`, `.available`) |
121
+ | `RateLimitError` | 429 — rate/cost cap (`.kind`, `.resetsAt`, `.retryAfterMs`) |
122
+ | `NotFoundError` | 404 — job/workflow not found |
123
+ | `APIError` | 5xx — upstream error |
124
+ | `ConnectionError` | network failure / timeout |
125
+ | `JobFailedError` | async media job failed (`.jobId`) |
126
+ | `JobTimeoutError` | async job exceeded poll timeout (`.jobId`) |
127
+
128
+ `429` and `5xx` (and pre-response network errors) are retried automatically with exponential backoff + jitter, respecting rate-limit resets. `4xx` are never retried.
129
+
130
+ ## Configuration
131
+
132
+ ```ts
133
+ new Curvet({
134
+ appKey: "cvt_app_...",
135
+ baseURL: "https://curvet.ai/api/v1/playground", // override for staging
136
+ timeout: 60_000, // per-request, ms
137
+ maxRetries: 2,
138
+ defaultPollIntervalMs: 2500, // async job polling
139
+ defaultPollTimeoutMs: 180_000,
140
+ fetch: customFetch, // for Node < 18 / testing
141
+ });
142
+ ```
143
+
144
+ Per-call overrides: every method accepts a final `options` arg (`{ signal, timeout, maxRetries }`; media methods also take `{ pollIntervalMs, pollTimeoutMs, onProgress }`).
145
+
146
+ ## Development
147
+
148
+ ```bash
149
+ npm install
150
+ npm run typecheck
151
+ npm test # unit tests (mocked HTTP) — no network, no credits
152
+ npm run build # ESM + CJS + d.ts via tsup
153
+
154
+ # live contract test (spends a few credits):
155
+ CURVET_TEST_APP_KEY=cvt_app_xxx npm test
156
+ ```
157
+
158
+ ## License
159
+
160
+ MIT