@lumavox/server 0.0.0-stage → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +134 -2
- package/dist/client.d.ts +59 -0
- package/dist/client.js +52 -0
- package/dist/errors.d.ts +86 -0
- package/dist/errors.js +137 -0
- package/dist/gen/index.d.ts +1 -0
- package/dist/gen/index.js +2 -0
- package/dist/gen/types.gen.d.ts +6563 -0
- package/dist/gen/types.gen.js +2 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +8 -0
- package/dist/paging.d.ts +34 -0
- package/dist/paging.js +41 -0
- package/dist/refuse.d.ts +11 -0
- package/dist/refuse.js +12 -0
- package/dist/resources/agents.d.ts +34 -0
- package/dist/resources/agents.js +33 -0
- package/dist/resources/assets.d.ts +59 -0
- package/dist/resources/assets.js +80 -0
- package/dist/resources/end-users.d.ts +73 -0
- package/dist/resources/end-users.js +139 -0
- package/dist/resources/ephemeral-keys.d.ts +65 -0
- package/dist/resources/ephemeral-keys.js +129 -0
- package/dist/resources/generations.d.ts +40 -0
- package/dist/resources/generations.js +55 -0
- package/dist/resources/knowledge.d.ts +58 -0
- package/dist/resources/knowledge.js +91 -0
- package/dist/resources/resource.d.ts +52 -0
- package/dist/resources/resource.js +68 -0
- package/dist/resources/speech.d.ts +80 -0
- package/dist/resources/speech.js +64 -0
- package/dist/resources/templates.d.ts +37 -0
- package/dist/resources/templates.js +50 -0
- package/dist/resources/usage.d.ts +15 -0
- package/dist/resources/usage.js +16 -0
- package/dist/resources/voices.d.ts +41 -0
- package/dist/resources/voices.js +53 -0
- package/dist/runtime.d.ts +22 -0
- package/dist/runtime.js +24 -0
- package/dist/stream.d.ts +6 -0
- package/dist/stream.js +37 -0
- package/dist/transport.d.ts +79 -0
- package/dist/transport.js +215 -0
- package/dist/upload.d.ts +37 -0
- package/dist/upload.js +34 -0
- package/dist/wait.d.ts +42 -0
- package/dist/wait.js +51 -0
- package/package.json +50 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Lumavox
|
|
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
CHANGED
|
@@ -1,3 +1,135 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @lumavox/server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Lumavox API from your server, with your organisation's API key: speech,
|
|
4
|
+
images and video, voices, your asset library, agents, knowledge, end users
|
|
5
|
+
and the ephemeral keys their devices talk to agents with — every operation
|
|
6
|
+
a key may call, typed from the published OpenAPI document. **Zero
|
|
7
|
+
dependencies**: `fetch` and the web platform only — Node 20.3 or later,
|
|
8
|
+
Cloudflare Workers, Deno, Bun.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install @lumavox/server
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import { createClient } from "@lumavox/server";
|
|
16
|
+
|
|
17
|
+
const lumavox = createClient({ apiKey: process.env.LUMAVOX_API_KEY! });
|
|
18
|
+
|
|
19
|
+
// A queued job, created and waited on.
|
|
20
|
+
const image = await lumavox.images.generate({ prompt: "A paper boat on a rain-soaked street" });
|
|
21
|
+
|
|
22
|
+
// At sign-in: your own id makes this idempotent — the same person every time.
|
|
23
|
+
const person = await lumavox.endUsers.create({ external_id: user.id });
|
|
24
|
+
|
|
25
|
+
// Their device talks to agents with a key of its own, never yours.
|
|
26
|
+
const { key } = await lumavox.ephemeralKeys.create({
|
|
27
|
+
end_user_id: user.id,
|
|
28
|
+
credit_limit: "5",
|
|
29
|
+
expires_in_seconds: 900,
|
|
30
|
+
});
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Server only.** The client holds your API key, which spends your whole
|
|
34
|
+
balance and reads every end user, so it refuses to run in a browser or a
|
|
35
|
+
React Native app: bundlers resolve it to a module that fails the build and
|
|
36
|
+
throws when loaded, and `createClient` checks again. Give the device an
|
|
37
|
+
ephemeral key and use `@lumavox/client` there.
|
|
38
|
+
|
|
39
|
+
The guide, with every example: the docs' **SDKs** tab, *Server SDK*.
|
|
40
|
+
|
|
41
|
+
## The client
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
createClient({
|
|
45
|
+
apiKey, // an org API key; nothing is read from the environment
|
|
46
|
+
baseUrl: "https://api.lumavox.ai", // the default
|
|
47
|
+
timeoutMs: 30_000, // per attempt
|
|
48
|
+
maxRetries: 2,
|
|
49
|
+
fetch, // the runtime's own by default
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Bodies and answers are the API's own JSON, field for field, as the API
|
|
54
|
+
reference shows them; methods are camelCase, and the SDK's options go in a
|
|
55
|
+
last argument on every call: `{ timeoutMs, signal, maxRetries, requestId }`.
|
|
56
|
+
Amounts are decimal strings and times ISO strings, as on the wire. Every
|
|
57
|
+
schema is exported as a type: `GenerationInfo`, `AssetDetail`, `EndUserInfo`, …
|
|
58
|
+
|
|
59
|
+
| Resource | Methods |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `endUsers` | `create`, `get`, `update`, `delete`, `list`, `page`, `export` |
|
|
62
|
+
| `ephemeralKeys` | `limits`, `create`, `revoke`, `inspect`, `list`, `page` |
|
|
63
|
+
| `images`, `videos`, `audio`, `skybox`, `transcriptions` | `create`, `get`, `wait`, `generate`; `skybox.styles` |
|
|
64
|
+
| `generations` | `get`, `wait`, `list`, `page` |
|
|
65
|
+
| `templates` | `list`, `get`, `create`, `generate`, `file` |
|
|
66
|
+
| `tts`, `stt` | `create` |
|
|
67
|
+
| `voices` | `list`, `get`, `create`, `uploadUrl`, `upload`, `update`, `delete`, `resample`, `design`, `saveDesign`, `wait` |
|
|
68
|
+
| `assets` | `list`, `page`, `get`, `uploadUrl`, `confirm`, `upload`, `update`, `delete`, `deleteMany`, `move`, `wait`; `assets.folders.*` |
|
|
69
|
+
| `agents` | `list`, `get`, `create`, `update`, `delete`; `agents.settings.get/update`; `agents.knowledge.list/set` |
|
|
70
|
+
| `knowledge` | `list`, `page`, `get`, `create`, `bulk`, `fromUrl`, `uploadUrl`, `fromFile`, `upload`, `update`, `delete`, `reindex`, `refresh`, `setAgents`, `search`, `categories`, `insights`, `wait` |
|
|
71
|
+
| `usage` | `get`, `plan` |
|
|
72
|
+
| the client | `health()` |
|
|
73
|
+
|
|
74
|
+
- **`list()` is an async iterator over every item**, page after page;
|
|
75
|
+
`page()` is one page.
|
|
76
|
+
- **`generate(body)` creates a job and waits for it**; `wait(id)` waits for
|
|
77
|
+
one you made. Both answer the finished job — read its `status`; a failed
|
|
78
|
+
one is refunded. Give a long one a `signal: AbortSignal.timeout(…)`.
|
|
79
|
+
- **`upload(data, fields, { wait, size })`** is a signed URL, the bytes
|
|
80
|
+
sent straight to storage, and the confirm: for an asset, a voice's
|
|
81
|
+
recording and a knowledge file. A `Blob`, an `ArrayBuffer` or a typed
|
|
82
|
+
array; a stream with its `size`.
|
|
83
|
+
- **`tts.create({ …, stream: true })`** answers a `ReadableStream` of PCM;
|
|
84
|
+
**`stt.create(audio, { stream: true })`** an async iterator of the
|
|
85
|
+
transcript's events.
|
|
86
|
+
- **A `delete` of something already gone answers `null`** (a voice's,
|
|
87
|
+
`false`).
|
|
88
|
+
|
|
89
|
+
## Errors
|
|
90
|
+
|
|
91
|
+
Everything thrown is a `PlatformError`: `status`, `type` (the API's —
|
|
92
|
+
`validation_error`, `insufficient_credits`, …), `message`, `requestId`,
|
|
93
|
+
`details` (a 422's fields) and `retryAfter` (seconds).
|
|
94
|
+
|
|
95
|
+
| Class | When |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `ValidationError` | 400, 422 |
|
|
98
|
+
| `AuthenticationError` | 401 |
|
|
99
|
+
| `InsufficientCreditsError` | 402 |
|
|
100
|
+
| `PermissionError` | 403 |
|
|
101
|
+
| `NotFoundError` | 404 |
|
|
102
|
+
| `ConflictError` | 409: a plan's maximum, or an id already taken |
|
|
103
|
+
| `RateLimitError` | 429 |
|
|
104
|
+
| `ServerError` | 5xx |
|
|
105
|
+
| `ConnectionError` | no response; `cause` is what `fetch` threw |
|
|
106
|
+
| `TimeoutError` | no response within `timeoutMs`, on the last attempt |
|
|
107
|
+
|
|
108
|
+
Quote `requestId` when you report a problem: every attempt of a call carries
|
|
109
|
+
the same one. Your own `signal` aborting throws its reason, not an error of
|
|
110
|
+
ours.
|
|
111
|
+
|
|
112
|
+
## Retries
|
|
113
|
+
|
|
114
|
+
Only what cannot happen twice is retried, up to `maxRetries`: a GET, PUT,
|
|
115
|
+
PATCH or DELETE after a failed connection, a timeout, 429, 502, 503 or 504;
|
|
116
|
+
a POST after a 429 only, which is refused before any work — and
|
|
117
|
+
`endUsers.create` with an `external_id`, which is idempotent. The wait
|
|
118
|
+
doubles from 0.5 s to 8 s with jitter; `Retry-After` wins, up to a minute,
|
|
119
|
+
and a longer one is thrown at once as a `RateLimitError` with its
|
|
120
|
+
`retryAfter`.
|
|
121
|
+
|
|
122
|
+
## End users and ephemeral keys
|
|
123
|
+
|
|
124
|
+
- **A key is prepaid**: its `credit_limit` is set aside from your balance
|
|
125
|
+
when it is minted, and what it does not spend comes back when it settles.
|
|
126
|
+
`create` clamps the lifetime to the platform's maximum (`clampTtl: false`
|
|
127
|
+
sends your body as written); your plan's own caps for one person's key
|
|
128
|
+
are not reported yet, so a key within the platform's can still be refused.
|
|
129
|
+
- **`revoke` answers at once**, with the figures from before the key's last
|
|
130
|
+
spend is settled; **`inspect` shows the spend as of the last
|
|
131
|
+
settlement**, so a key in use reads as unspent for now.
|
|
132
|
+
- **`endUsers.export(id)`** reads every conversation and fact about a
|
|
133
|
+
person with a five-minute key of their own, revoked after — on failure
|
|
134
|
+
too. The key is an ordinary one: at the person's live-key cap the export
|
|
135
|
+
fails as the mint does. Facts are the first 100 for now.
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createClient`: one org API key, one base URL, and a resource per area of
|
|
3
|
+
* the API — every operation an API key may call (`test/coverage.test.ts`
|
|
4
|
+
* holds the document to it), and `health()`, which needs none.
|
|
5
|
+
*
|
|
6
|
+
* - **Nothing is read from `process.env`**: Workers has none, and a key
|
|
7
|
+
* that arrives by argument is one the caller can see arrive.
|
|
8
|
+
* - **The default `fetch` is the global one, called through a wrapper**:
|
|
9
|
+
* an unbound `fetch` is an illegal invocation on Workers. A `fetch`
|
|
10
|
+
* passed in is called the same way, so a service binding's goes in as
|
|
11
|
+
* `(url, init) => env.API.fetch(url, init)`.
|
|
12
|
+
* - **It refuses a browser and React Native** (`runtime.ts`).
|
|
13
|
+
*/
|
|
14
|
+
import type { AudioRequest, HealthResponse, ImageRequest, SkyboxRequest, TranscribeAssetRequest, VideoRequest } from "./gen/index.js";
|
|
15
|
+
import { Agents } from "./resources/agents.js";
|
|
16
|
+
import { Assets } from "./resources/assets.js";
|
|
17
|
+
import { EndUsers } from "./resources/end-users.js";
|
|
18
|
+
import { EphemeralKeys } from "./resources/ephemeral-keys.js";
|
|
19
|
+
import { Generations, Jobs, Skybox } from "./resources/generations.js";
|
|
20
|
+
import { Knowledge } from "./resources/knowledge.js";
|
|
21
|
+
import { Stt, Tts } from "./resources/speech.js";
|
|
22
|
+
import { Templates } from "./resources/templates.js";
|
|
23
|
+
import { Usage } from "./resources/usage.js";
|
|
24
|
+
import { Voices } from "./resources/voices.js";
|
|
25
|
+
import { type Fetch, type RequestOptions } from "./transport.js";
|
|
26
|
+
export declare const DEFAULT_BASE_URL = "https://api.lumavox.ai";
|
|
27
|
+
export interface ClientOptions {
|
|
28
|
+
/** An org API key (`Bearer`). Keep it on your server. */
|
|
29
|
+
apiKey: string;
|
|
30
|
+
/** `https://api.lumavox.ai` by default; staging is `https://stg-api.lumavox.ai`. */
|
|
31
|
+
baseUrl?: string;
|
|
32
|
+
/** Per attempt, in milliseconds: 30 s by default. */
|
|
33
|
+
timeoutMs?: number;
|
|
34
|
+
/** Retries of a call that can be sent again safely: 2 by default. */
|
|
35
|
+
maxRetries?: number;
|
|
36
|
+
/** The `fetch` to call: the runtime's own by default. */
|
|
37
|
+
fetch?: Fetch;
|
|
38
|
+
}
|
|
39
|
+
export interface Client {
|
|
40
|
+
readonly endUsers: EndUsers;
|
|
41
|
+
readonly ephemeralKeys: EphemeralKeys;
|
|
42
|
+
readonly usage: Usage;
|
|
43
|
+
readonly images: Jobs<ImageRequest>;
|
|
44
|
+
readonly videos: Jobs<VideoRequest>;
|
|
45
|
+
readonly audio: Jobs<AudioRequest>;
|
|
46
|
+
readonly skybox: Skybox<SkyboxRequest>;
|
|
47
|
+
readonly transcriptions: Jobs<TranscribeAssetRequest>;
|
|
48
|
+
readonly generations: Generations;
|
|
49
|
+
readonly templates: Templates;
|
|
50
|
+
readonly tts: Tts;
|
|
51
|
+
readonly stt: Stt;
|
|
52
|
+
readonly voices: Voices;
|
|
53
|
+
readonly assets: Assets;
|
|
54
|
+
readonly agents: Agents;
|
|
55
|
+
readonly knowledge: Knowledge;
|
|
56
|
+
/** Whether the API is up, and its version. Sends no key. */
|
|
57
|
+
health(options?: RequestOptions): Promise<HealthResponse>;
|
|
58
|
+
}
|
|
59
|
+
export declare function createClient(options: ClientOptions): Client;
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Agents } from "./resources/agents.js";
|
|
2
|
+
import { Assets } from "./resources/assets.js";
|
|
3
|
+
import { EndUsers } from "./resources/end-users.js";
|
|
4
|
+
import { EphemeralKeys } from "./resources/ephemeral-keys.js";
|
|
5
|
+
import { Generations, Jobs, Skybox } from "./resources/generations.js";
|
|
6
|
+
import { Knowledge } from "./resources/knowledge.js";
|
|
7
|
+
import { Stt, Tts } from "./resources/speech.js";
|
|
8
|
+
import { Templates } from "./resources/templates.js";
|
|
9
|
+
import { Usage } from "./resources/usage.js";
|
|
10
|
+
import { Voices } from "./resources/voices.js";
|
|
11
|
+
import { REFUSAL, refusedHere } from "./runtime.js";
|
|
12
|
+
import { Transport } from "./transport.js";
|
|
13
|
+
export const DEFAULT_BASE_URL = "https://api.lumavox.ai";
|
|
14
|
+
export function createClient(options) {
|
|
15
|
+
const where = refusedHere();
|
|
16
|
+
if (where)
|
|
17
|
+
throw new Error(`${REFUSAL} (This is ${where}.)`);
|
|
18
|
+
if (typeof options.apiKey !== "string" || !options.apiKey.trim()) {
|
|
19
|
+
throw new TypeError("createClient needs an apiKey: an org API key.");
|
|
20
|
+
}
|
|
21
|
+
const own = options.fetch;
|
|
22
|
+
const transport = new Transport({
|
|
23
|
+
apiKey: options.apiKey,
|
|
24
|
+
baseUrl: (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, ""),
|
|
25
|
+
timeoutMs: options.timeoutMs ?? 30_000,
|
|
26
|
+
maxRetries: options.maxRetries ?? 2,
|
|
27
|
+
fetch: (url, init) => (own ?? fetch)(url, init),
|
|
28
|
+
});
|
|
29
|
+
const ephemeralKeys = new EphemeralKeys(transport, "/v1/ephemeral-keys");
|
|
30
|
+
const generations = new Generations(transport, "/v1/generations");
|
|
31
|
+
return {
|
|
32
|
+
endUsers: new EndUsers(transport, "/v1/end-users", ephemeralKeys),
|
|
33
|
+
ephemeralKeys,
|
|
34
|
+
usage: new Usage(transport, "/v1"),
|
|
35
|
+
images: new Jobs(transport, "/v1/images"),
|
|
36
|
+
videos: new Jobs(transport, "/v1/videos"),
|
|
37
|
+
audio: new Jobs(transport, "/v1/audio"),
|
|
38
|
+
skybox: new Skybox(transport, "/v1/skybox"),
|
|
39
|
+
transcriptions: new Jobs(transport, "/v1/transcriptions"),
|
|
40
|
+
generations,
|
|
41
|
+
templates: new Templates(transport, "/v1/templates", generations),
|
|
42
|
+
tts: new Tts(transport, "/v1/tts"),
|
|
43
|
+
stt: new Stt(transport, "/v1/stt"),
|
|
44
|
+
voices: new Voices(transport, "/v1/voices"),
|
|
45
|
+
assets: new Assets(transport, "/v1/assets"),
|
|
46
|
+
agents: new Agents(transport, "/v1/agents"),
|
|
47
|
+
knowledge: new Knowledge(transport, "/v1/knowledge"),
|
|
48
|
+
health: (request) => transport
|
|
49
|
+
.request({ method: "GET", path: "/health", open: true }, request)
|
|
50
|
+
.then((answer) => answer.data),
|
|
51
|
+
};
|
|
52
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every failure the SDK throws: a `PlatformError`, so one `catch` with
|
|
3
|
+
* `instanceof PlatformError` sees them all, and a subclass per status a
|
|
4
|
+
* caller acts on differently.
|
|
5
|
+
*
|
|
6
|
+
* The API answers its errors in one envelope —
|
|
7
|
+
* `{"error":{"type","message","request_id","details"?}}`
|
|
8
|
+
* (`apps/api/src/http/errors.ts`) — and `type` is the thing to switch on.
|
|
9
|
+
* Two bodies are not that envelope, and are read here too:
|
|
10
|
+
* - **the 400 the document declares** on every route with a body or a path
|
|
11
|
+
* parameter, `{status_code, detail, extra}`;
|
|
12
|
+
* - **Cloudflare's own refusal**, `error code: 1010` as plain text with no
|
|
13
|
+
* `X-Request-Id`: the request never reached the API, so there is no id
|
|
14
|
+
* to report.
|
|
15
|
+
*/
|
|
16
|
+
/** What one error says, as the SDK read it. */
|
|
17
|
+
export interface PlatformErrorInit {
|
|
18
|
+
status: number;
|
|
19
|
+
type: string;
|
|
20
|
+
message: string;
|
|
21
|
+
requestId: string | null;
|
|
22
|
+
details?: unknown;
|
|
23
|
+
retryAfter?: number | null;
|
|
24
|
+
cause?: unknown;
|
|
25
|
+
}
|
|
26
|
+
export declare class PlatformError extends Error {
|
|
27
|
+
name: string;
|
|
28
|
+
/** The HTTP status; `0` when no response came back. */
|
|
29
|
+
readonly status: number;
|
|
30
|
+
/** The API's machine-readable category: `validation_error`, `rate_limit_error`, … */
|
|
31
|
+
readonly type: string;
|
|
32
|
+
/**
|
|
33
|
+
* The request's `X-Request-Id` — the one the SDK sent, which the API
|
|
34
|
+
* keeps. `null` only when Cloudflare refused it before the API saw it.
|
|
35
|
+
*/
|
|
36
|
+
readonly requestId: string | null;
|
|
37
|
+
/** Field-level problems on a 422; the 400's `extra`; otherwise `undefined`. */
|
|
38
|
+
readonly details: unknown;
|
|
39
|
+
/** Seconds to wait before trying again, from `Retry-After`; `null` without one. */
|
|
40
|
+
readonly retryAfter: number | null;
|
|
41
|
+
constructor(init: PlatformErrorInit);
|
|
42
|
+
}
|
|
43
|
+
/** 400 or 422: the request is malformed or failed validation; `details` says where. */
|
|
44
|
+
export declare class ValidationError extends PlatformError {
|
|
45
|
+
name: string;
|
|
46
|
+
}
|
|
47
|
+
/** 401: no credential, a wrong one, or one that expired or was revoked. */
|
|
48
|
+
export declare class AuthenticationError extends PlatformError {
|
|
49
|
+
name: string;
|
|
50
|
+
}
|
|
51
|
+
/** 402: the balance cannot cover it, or the organisation is suspended or on no plan. */
|
|
52
|
+
export declare class InsufficientCreditsError extends PlatformError {
|
|
53
|
+
name: string;
|
|
54
|
+
}
|
|
55
|
+
/** 403: the key's scopes do not cover this, or the waitlist holds the organisation. */
|
|
56
|
+
export declare class PermissionError extends PlatformError {
|
|
57
|
+
name: string;
|
|
58
|
+
}
|
|
59
|
+
/** 404: nothing by that id in this organisation. */
|
|
60
|
+
export declare class NotFoundError extends PlatformError {
|
|
61
|
+
name: string;
|
|
62
|
+
}
|
|
63
|
+
/** 409: a plan's maximum, or an id already taken. */
|
|
64
|
+
export declare class ConflictError extends PlatformError {
|
|
65
|
+
name: string;
|
|
66
|
+
}
|
|
67
|
+
/** 429: a request window or the plan's mint rate; `retryAfter` says when. */
|
|
68
|
+
export declare class RateLimitError extends PlatformError {
|
|
69
|
+
name: string;
|
|
70
|
+
}
|
|
71
|
+
/** 5xx: the API or something behind it failed. */
|
|
72
|
+
export declare class ServerError extends PlatformError {
|
|
73
|
+
name: string;
|
|
74
|
+
}
|
|
75
|
+
/** No response: DNS, TLS, a reset connection. `cause` is what `fetch` threw. */
|
|
76
|
+
export declare class ConnectionError extends PlatformError {
|
|
77
|
+
name: string;
|
|
78
|
+
}
|
|
79
|
+
/** No response within `timeoutMs`, on the last attempt. */
|
|
80
|
+
export declare class TimeoutError extends PlatformError {
|
|
81
|
+
name: string;
|
|
82
|
+
}
|
|
83
|
+
/** `Retry-After` as seconds: a number of them, or an HTTP date. */
|
|
84
|
+
export declare function retryAfterOf(headers: Headers): number | null;
|
|
85
|
+
/** The error a non-2xx response stands for, from its status, headers and body text. */
|
|
86
|
+
export declare function errorFromResponse(status: number, headers: Headers, text: string, sentRequestId: string): PlatformError;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every failure the SDK throws: a `PlatformError`, so one `catch` with
|
|
3
|
+
* `instanceof PlatformError` sees them all, and a subclass per status a
|
|
4
|
+
* caller acts on differently.
|
|
5
|
+
*
|
|
6
|
+
* The API answers its errors in one envelope —
|
|
7
|
+
* `{"error":{"type","message","request_id","details"?}}`
|
|
8
|
+
* (`apps/api/src/http/errors.ts`) — and `type` is the thing to switch on.
|
|
9
|
+
* Two bodies are not that envelope, and are read here too:
|
|
10
|
+
* - **the 400 the document declares** on every route with a body or a path
|
|
11
|
+
* parameter, `{status_code, detail, extra}`;
|
|
12
|
+
* - **Cloudflare's own refusal**, `error code: 1010` as plain text with no
|
|
13
|
+
* `X-Request-Id`: the request never reached the API, so there is no id
|
|
14
|
+
* to report.
|
|
15
|
+
*/
|
|
16
|
+
export class PlatformError extends Error {
|
|
17
|
+
// Written out, not `new.target.name`: a customer's minifier renames classes.
|
|
18
|
+
name = "PlatformError";
|
|
19
|
+
constructor(init) {
|
|
20
|
+
super(init.message, init.cause === undefined ? {} : { cause: init.cause });
|
|
21
|
+
this.status = init.status;
|
|
22
|
+
this.type = init.type;
|
|
23
|
+
this.requestId = init.requestId;
|
|
24
|
+
this.details = init.details;
|
|
25
|
+
this.retryAfter = init.retryAfter ?? null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** 400 or 422: the request is malformed or failed validation; `details` says where. */
|
|
29
|
+
export class ValidationError extends PlatformError {
|
|
30
|
+
name = "ValidationError";
|
|
31
|
+
}
|
|
32
|
+
/** 401: no credential, a wrong one, or one that expired or was revoked. */
|
|
33
|
+
export class AuthenticationError extends PlatformError {
|
|
34
|
+
name = "AuthenticationError";
|
|
35
|
+
}
|
|
36
|
+
/** 402: the balance cannot cover it, or the organisation is suspended or on no plan. */
|
|
37
|
+
export class InsufficientCreditsError extends PlatformError {
|
|
38
|
+
name = "InsufficientCreditsError";
|
|
39
|
+
}
|
|
40
|
+
/** 403: the key's scopes do not cover this, or the waitlist holds the organisation. */
|
|
41
|
+
export class PermissionError extends PlatformError {
|
|
42
|
+
name = "PermissionError";
|
|
43
|
+
}
|
|
44
|
+
/** 404: nothing by that id in this organisation. */
|
|
45
|
+
export class NotFoundError extends PlatformError {
|
|
46
|
+
name = "NotFoundError";
|
|
47
|
+
}
|
|
48
|
+
/** 409: a plan's maximum, or an id already taken. */
|
|
49
|
+
export class ConflictError extends PlatformError {
|
|
50
|
+
name = "ConflictError";
|
|
51
|
+
}
|
|
52
|
+
/** 429: a request window or the plan's mint rate; `retryAfter` says when. */
|
|
53
|
+
export class RateLimitError extends PlatformError {
|
|
54
|
+
name = "RateLimitError";
|
|
55
|
+
}
|
|
56
|
+
/** 5xx: the API or something behind it failed. */
|
|
57
|
+
export class ServerError extends PlatformError {
|
|
58
|
+
name = "ServerError";
|
|
59
|
+
}
|
|
60
|
+
/** No response: DNS, TLS, a reset connection. `cause` is what `fetch` threw. */
|
|
61
|
+
export class ConnectionError extends PlatformError {
|
|
62
|
+
name = "ConnectionError";
|
|
63
|
+
}
|
|
64
|
+
/** No response within `timeoutMs`, on the last attempt. */
|
|
65
|
+
export class TimeoutError extends PlatformError {
|
|
66
|
+
name = "TimeoutError";
|
|
67
|
+
}
|
|
68
|
+
const BY_STATUS = {
|
|
69
|
+
400: ValidationError,
|
|
70
|
+
401: AuthenticationError,
|
|
71
|
+
402: InsufficientCreditsError,
|
|
72
|
+
403: PermissionError,
|
|
73
|
+
404: NotFoundError,
|
|
74
|
+
409: ConflictError,
|
|
75
|
+
422: ValidationError,
|
|
76
|
+
429: RateLimitError,
|
|
77
|
+
};
|
|
78
|
+
const classOf = (status) => BY_STATUS[status] ?? (status >= 500 ? ServerError : PlatformError);
|
|
79
|
+
/** `Retry-After` as seconds: a number of them, or an HTTP date. */
|
|
80
|
+
export function retryAfterOf(headers) {
|
|
81
|
+
const value = headers.get("retry-after")?.trim();
|
|
82
|
+
if (!value)
|
|
83
|
+
return null;
|
|
84
|
+
if (/^\d+(\.\d+)?$/.test(value))
|
|
85
|
+
return Number(value);
|
|
86
|
+
const at = Date.parse(value);
|
|
87
|
+
return Number.isNaN(at) ? null : Math.max(0, (at - Date.now()) / 1000);
|
|
88
|
+
}
|
|
89
|
+
const isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
90
|
+
/** The error a non-2xx response stands for, from its status, headers and body text. */
|
|
91
|
+
export function errorFromResponse(status, headers, text, sentRequestId) {
|
|
92
|
+
const answered = headers.get("x-request-id");
|
|
93
|
+
const requestId = answered ?? sentRequestId;
|
|
94
|
+
const http = `HTTP ${status}`;
|
|
95
|
+
let body;
|
|
96
|
+
try {
|
|
97
|
+
body = JSON.parse(text);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
// swallowed: not JSON — Cloudflare's text, or a proxy's page; read below.
|
|
101
|
+
body = undefined;
|
|
102
|
+
}
|
|
103
|
+
const e = isObject(body) && isObject(body.error) ? body.error : null;
|
|
104
|
+
const code = /^error code: (\d+)/.exec(text.trim())?.[1];
|
|
105
|
+
const snippet = text.trim().slice(0, 200);
|
|
106
|
+
const said = e
|
|
107
|
+
? {
|
|
108
|
+
type: typeof e.type === "string" ? e.type : "unknown_error",
|
|
109
|
+
message: typeof e.message === "string" ? e.message : http,
|
|
110
|
+
requestId: typeof e.request_id === "string" ? e.request_id : requestId,
|
|
111
|
+
details: e.details ?? undefined,
|
|
112
|
+
}
|
|
113
|
+
: isObject(body) && typeof body.detail === "string"
|
|
114
|
+
? {
|
|
115
|
+
type: "invalid_request",
|
|
116
|
+
message: body.detail,
|
|
117
|
+
requestId,
|
|
118
|
+
details: body.extra ?? undefined,
|
|
119
|
+
}
|
|
120
|
+
: code && answered === null
|
|
121
|
+
? {
|
|
122
|
+
type: "cloudflare_error",
|
|
123
|
+
message: `Cloudflare refused the request with error code ${code} ` +
|
|
124
|
+
"before it reached the API.",
|
|
125
|
+
requestId: null,
|
|
126
|
+
}
|
|
127
|
+
: {
|
|
128
|
+
type: "http_error",
|
|
129
|
+
message: snippet ? `${http}: ${snippet}` : http,
|
|
130
|
+
requestId,
|
|
131
|
+
};
|
|
132
|
+
return new (classOf(status))({
|
|
133
|
+
...said,
|
|
134
|
+
status,
|
|
135
|
+
retryAfter: retryAfterOf(headers),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { AgentCreateRequest, AgentInfo, AgentList, AgentSettingsInfo, AgentSettingsUpdate, AgentStt, AgentSummary, AgentUpdate, AgentVoice, ApiKeySelf, AssetBulkRequest, AssetDeleted, AssetDetail, AssetMoveRequest, AssetPage, AssetsAffected, AssetSummary, AssetUpdate, AssignedAgent, AudioRequest, BulkKnowledgeData, BulkKnowledgeError, BulkKnowledgeErrors, BulkKnowledgeResponse, BulkKnowledgeResponses, ClientOptions, CompactData, CompactError, CompactErrors, CompactionInfo, CompactRequest, CompactResponse, CompactResponses, CreateAgentData, CreateAgentError, CreateAgentErrors, CreateAgentResponse, CreateAgentResponses, CreateAudioData, CreateAudioError, CreateAudioErrors, CreateAudioResponse, CreateAudioResponses, CreateEndUserData, CreateEndUserError, CreateEndUserErrors, CreateEndUserResponse, CreateEndUserResponses, CreateEphemeralKeyData, CreateEphemeralKeyError, CreateEphemeralKeyErrors, CreateEphemeralKeyResponse, CreateEphemeralKeyResponses, CreateFolderData, CreateFolderError, CreateFolderErrors, CreateFolderResponse, CreateFolderResponses, CreateImageData, CreateImageError, CreateImageErrors, CreateImageResponse, CreateImageResponses, CreateKnowledgeData, CreateKnowledgeError, CreateKnowledgeErrors, CreateKnowledgeFromFileData, CreateKnowledgeFromFileError, CreateKnowledgeFromFileErrors, CreateKnowledgeFromFileResponse, CreateKnowledgeFromFileResponses, CreateKnowledgeFromUrlData, CreateKnowledgeFromUrlError, CreateKnowledgeFromUrlErrors, CreateKnowledgeFromUrlResponse, CreateKnowledgeFromUrlResponses, CreateKnowledgeResponse, CreateKnowledgeResponses, CreateSessionData, CreateSessionError, CreateSessionErrors, CreateSessionResponse, CreateSessionResponses, CreateSkyboxData, CreateSkyboxError, CreateSkyboxErrors, CreateSkyboxResponse, CreateSkyboxResponses, CreateTranscriptionData, CreateTranscriptionError, CreateTranscriptionErrors, CreateTranscriptionResponse, CreateTranscriptionResponses, CreateVideoData, CreateVideoError, CreateVideoErrors, CreateVideoResponse, CreateVideoResponses, CreateVoiceData, CreateVoiceError, CreateVoiceErrors, CreateVoiceResponse, CreateVoiceResponses, DeleteAgentData, DeleteAgentError, DeleteAgentErrors, DeleteAgentResponse, DeleteAgentResponses, DeleteAssetData, DeleteAssetError, DeleteAssetErrors, DeleteAssetResponse, DeleteAssetResponses, DeleteAssetsData, DeleteAssetsError, DeleteAssetsErrors, DeleteAssetsResponse, DeleteAssetsResponses, DeleteEndUserData, DeleteEndUserError, DeleteEndUserErrors, DeleteEndUserResponse, DeleteEndUserResponses, DeleteFolderData, DeleteFolderError, DeleteFolderErrors, DeleteFolderResponse, DeleteFolderResponses, DeleteKnowledgeData, DeleteKnowledgeError, DeleteKnowledgeErrors, DeleteKnowledgeResponse, DeleteKnowledgeResponses, DeleteSessionData, DeleteSessionError, DeleteSessionErrors, DeleteSessionResponse, DeleteSessionResponses, DeleteVoiceData, DeleteVoiceError, DeleteVoiceErrors, DeleteVoiceResponse, DeleteVoiceResponses, DesignVoiceData, DesignVoiceError, DesignVoiceErrors, DesignVoiceResponse, DesignVoiceResponses, EndUserCreateRequest, EndUserDeleted, EndUserInfo, EndUserList, EndUserUpdateRequest, EphemeralKeyCreateRequest, EphemeralKeyCreateResponse, EphemeralKeyInfo, EphemeralKeyLimits, EphemeralTokenSelf, ErrorInfo, ErrorResponse, ExtractData, ExtractError, ExtractErrors, ExtractResponse, ExtractResponses, FactInfo, FactList, FolderCreate, FolderDeleted, FolderDetail, FolderLevel, FolderSummary, FolderUpdate, ForgetFactData, ForgetFactError, ForgetFactErrors, ForgetFactResponse, ForgetFactResponses, ForgetUserFactsData, ForgetUserFactsError, ForgetUserFactsErrors, ForgetUserFactsResponse, ForgetUserFactsResponses, ForgottenFacts, GenerateFromTemplateData, GenerateFromTemplateError, GenerateFromTemplateErrors, GenerateFromTemplateResponse, GenerateFromTemplateResponses, GenerationAudio, GenerationImage, GenerationInfo, GenerationPage, GenerationSkybox, GenerationTranscript, GenerationVideo, GetAgentData, GetAgentError, GetAgentErrors, GetAgentResponse, GetAgentResponses, GetAgentSettingsData, GetAgentSettingsError, GetAgentSettingsErrors, GetAgentSettingsResponse, GetAgentSettingsResponses, GetAssetData, GetAssetError, GetAssetErrors, GetAssetResponse, GetAssetResponses, GetEndUserData, GetEndUserError, GetEndUserErrors, GetEndUserResponse, GetEndUserResponses, GetFolderData, GetFolderError, GetFolderErrors, GetFolderResponse, GetFolderResponses, GetKnowledgeData, GetKnowledgeError, GetKnowledgeErrors, GetKnowledgeResponse, GetKnowledgeResponses, GetSessionDetailData, GetSessionDetailError, GetSessionDetailErrors, GetSessionDetailResponse, GetSessionDetailResponses, GetVoiceData, GetVoiceError, GetVoiceErrors, GetVoiceResponse, GetVoiceResponses, HealthData, HealthResponse, HealthResponse2, HealthResponses, ImageRequest, KnowledgeAssigned, KnowledgeAssignment, KnowledgeBulk, KnowledgeBulkResult, KnowledgeCategories, KnowledgeCitation, KnowledgeCreate, KnowledgeEntryUsage, KnowledgeFileCreate, KnowledgeInfo, KnowledgeInsights, KnowledgeInsightsData, KnowledgeInsightsError, KnowledgeInsightsErrors, KnowledgeInsightsResponse, KnowledgeInsightsResponses, KnowledgeList, KnowledgeLookupInfo, KnowledgeSearchHit, KnowledgeSearchList, KnowledgeSearchRequest, KnowledgeSearchResult, KnowledgeUpdate, KnowledgeUploadRequest, KnowledgeUploadTicket, KnowledgeUploadUrlData, KnowledgeUploadUrlError, KnowledgeUploadUrlErrors, KnowledgeUploadUrlResponse, KnowledgeUploadUrlResponses, KnowledgeUrlCreate, LimitsData, LimitsError, LimitsErrors, LimitsResponse, LimitsResponses, ListAgentKnowledgeData, ListAgentKnowledgeError, ListAgentKnowledgeErrors, ListAgentKnowledgeResponse, ListAgentKnowledgeResponses, ListAgentsData, ListAgentsError, ListAgentsErrors, ListAgentsResponse, ListAgentsResponses, ListAssetsData, ListAssetsError, ListAssetsErrors, ListAssetsResponse, ListAssetsResponses, ListEndUsersData, ListEndUsersError, ListEndUsersErrors, ListEndUsersResponse, ListEndUsersResponses, ListEphemeralKeysData, ListEphemeralKeysError, ListEphemeralKeysErrors, ListEphemeralKeysResponse, ListEphemeralKeysResponses, ListFactsData, ListFactsError, ListFactsErrors, ListFactsResponse, ListFactsResponses, ListFoldersData, ListFoldersError, ListFoldersErrors, ListFoldersResponse, ListFoldersResponses, ListGenerationsData, ListGenerationsError, ListGenerationsErrors, ListGenerationsResponse, ListGenerationsResponses, ListKnowledgeCategoriesData, ListKnowledgeCategoriesError, ListKnowledgeCategoriesErrors, ListKnowledgeCategoriesResponse, ListKnowledgeCategoriesResponses, ListKnowledgeData, ListKnowledgeError, ListKnowledgeErrors, ListKnowledgeResponse, ListKnowledgeResponses, ListRelationsData, ListRelationsError, ListRelationsErrors, ListRelationsResponse, ListRelationsResponses, ListSessionsData, ListSessionsError, ListSessionsErrors, ListSessionsResponse, ListSessionsResponses, ListStylesData, ListStylesError, ListStylesErrors, ListStylesResponse, ListStylesResponses, ListTemplatesData, ListTemplatesError, ListTemplatesErrors, ListTemplatesResponse, ListTemplatesResponses, ListVoicesData, ListVoicesError, ListVoicesErrors, ListVoicesResponse, ListVoicesResponses, MessageInfo, MessageKnowledge, MoveAssetsData, MoveAssetsError, MoveAssetsErrors, MoveAssetsResponse, MoveAssetsResponses, OrgPlan, PlanData, PlanError, PlanErrors, PlanResponse, PlanResponses, ProviderVoiceSettings, PutAgentSettingsData, PutAgentSettingsError, PutAgentSettingsErrors, PutAgentSettingsResponse, PutAgentSettingsResponses, ReadAudioData, ReadAudioError, ReadAudioErrors, ReadAudioResponse, ReadAudioResponses, ReadGenerationData, ReadGenerationError, ReadGenerationErrors, ReadGenerationResponse, ReadGenerationResponses, ReadImageData, ReadImageError, ReadImageErrors, ReadImageResponse, ReadImageResponses, ReadSkyboxData, ReadSkyboxError, ReadSkyboxErrors, ReadSkyboxResponse, ReadSkyboxResponses, ReadTemplateData, ReadTemplateError, ReadTemplateErrors, ReadTemplateResponse, ReadTemplateResponses, ReadTranscriptionData, ReadTranscriptionError, ReadTranscriptionErrors, ReadTranscriptionResponse, ReadTranscriptionResponses, ReadVideoData, ReadVideoError, ReadVideoErrors, ReadVideoResponse, ReadVideoResponses, Reference, RefreshKnowledgeData, RefreshKnowledgeError, RefreshKnowledgeErrors, RefreshKnowledgeResponse, RefreshKnowledgeResponses, ReindexKnowledgeData, ReindexKnowledgeError, ReindexKnowledgeErrors, ReindexKnowledgeResponse, ReindexKnowledgeResponses, RelationInfo, RelationList, ResampleVoiceData, ResampleVoiceError, ResampleVoiceErrors, ResampleVoiceResponse, ResampleVoiceResponses, RevokeEphemeralKeyData, RevokeEphemeralKeyError, RevokeEphemeralKeyErrors, RevokeEphemeralKeyResponse, RevokeEphemeralKeyResponses, SaveDesignedVoiceData, SaveDesignedVoiceError, SaveDesignedVoiceErrors, SaveDesignedVoiceResponse, SaveDesignedVoiceResponses, SearchKnowledgeData, SearchKnowledgeError, SearchKnowledgeErrors, SearchKnowledgeResponse, SearchKnowledgeResponses, SessionCreateRequest, SessionDetail, SessionInfo, SetAgentKnowledgeData, SetAgentKnowledgeError, SetAgentKnowledgeErrors, SetAgentKnowledgeResponse, SetAgentKnowledgeResponses, SetKnowledgeAgentsData, SetKnowledgeAgentsError, SetKnowledgeAgentsErrors, SetKnowledgeAgentsResponse, SetKnowledgeAgentsResponses, SkyboxFile, SkyboxRequest, SkyboxStyle, StreamDone, StreamError, StreamSegment, StreamTranscript, TemplateFileData, TemplateFileError, TemplateFileErrors, TemplateFileResponses, TemplateGenerateRequest, TemplateInfo, TemplateInput, TemplateList, TokenSelfData, TokenSelfError, TokenSelfErrors, TokenSelfResponse, TokenSelfResponses, TranscribeAssetRequest, TranscribeData, TranscribeError, TranscribeErrors, TranscribeResponses, TranscriptWord, TtsData, TtsError, TtsErrors, TtsOptions, TtsRequest, TtsResponse, TtsResponses, UnansweredQuestion, UpdateAgentData, UpdateAgentError, UpdateAgentErrors, UpdateAgentResponse, UpdateAgentResponses, UpdateAssetData, UpdateAssetError, UpdateAssetErrors, UpdateAssetResponse, UpdateAssetResponses, UpdateEndUserData, UpdateEndUserError, UpdateEndUserErrors, UpdateEndUserResponse, UpdateEndUserResponses, UpdateFolderData, UpdateFolderError, UpdateFolderErrors, UpdateFolderResponse, UpdateFolderResponses, UpdateKnowledgeData, UpdateKnowledgeError, UpdateKnowledgeErrors, UpdateKnowledgeResponse, UpdateKnowledgeResponses, UpdateVoiceData, UpdateVoiceError, UpdateVoiceErrors, UpdateVoiceResponse, UpdateVoiceResponses, UploadConfirm, UploadConfirmData, UploadConfirmError, UploadConfirmErrors, UploadConfirmResponse, UploadConfirmResponses, UploadTicket, UploadTicketRequest, UploadUrlData, UploadUrlError, UploadUrlErrors, UploadUrlResponse, UploadUrlResponses, UsageByKey, UsageData, UsageDay, UsageError, UsageErrors, UsageResponse, UsageResponse2, UsageResponses, UsageSummary, VariantInfo, VideoRequest, VoiceDesignPreview, VoiceDesignRequest, VoiceDesignResult, VoiceDesignSaveRequest, VoiceDetail, VoiceInfo, VoiceSample, VoiceUpdate, VoiceUpload, VoiceUploadRequest, VoiceUploadTicket, VoiceUploadUrlData, VoiceUploadUrlError, VoiceUploadUrlErrors, VoiceUploadUrlResponse, VoiceUploadUrlResponses } from './types.gen.js';
|