craterview 0.4.26 → 0.4.29
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 +12 -11
- package/index.ts +62 -32
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# craterview
|
|
2
2
|
|
|
3
|
-
TypeScript client for the [CraterView](https://craterview.ai) image enhancement and
|
|
3
|
+
TypeScript client for the [CraterView.ai](https://craterview.ai) image enhancement and
|
|
4
4
|
restoration API.
|
|
5
5
|
|
|
6
6
|
```bash
|
|
@@ -45,7 +45,7 @@ reimplement.
|
|
|
45
45
|
Build against `echo` first. It costs no credits, needs no GPU and returns a real result — a
|
|
46
46
|
plain upscale — so the request, the parameters and the response are the ones a paid model
|
|
47
47
|
gives, and your integration needs no change when you switch. When you are ready, swap the
|
|
48
|
-
model
|
|
48
|
+
model id for the one you want.
|
|
49
49
|
|
|
50
50
|
```ts
|
|
51
51
|
const job = await cv.run(file, {
|
|
@@ -57,7 +57,7 @@ const job = await cv.run(file, {
|
|
|
57
57
|
const blob = await job.blob();
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
A parameter one model publishes is not one another accepts — `cv.models()` says which — and
|
|
60
|
+
A parameter one model publishes is not necessarily one another accepts — `cv.models()` says which — and
|
|
61
61
|
a value a model does not publish is refused at submit rather than ignored.
|
|
62
62
|
|
|
63
63
|
## An API key
|
|
@@ -109,7 +109,7 @@ a presigned URL and `blob()` GETs the result the same way; the API moves keys, n
|
|
|
109
109
|
|
|
110
110
|
## Retries are yours to write
|
|
111
111
|
|
|
112
|
-
**Outside `run()` and `waitFor()`, this client does not retry.** `run()`
|
|
112
|
+
**Outside `run()` and `waitFor()`, this client does not retry.** `run()` sends its submission
|
|
113
113
|
once more, under one idempotency key, when the first got no answer or a failure on the
|
|
114
114
|
platform's side, and `waitFor()` reads on through the same until its timeout; neither can make a
|
|
115
115
|
second job. Every other call is sent once. That is deliberate: only the caller knows where one
|
|
@@ -152,7 +152,7 @@ above tells the two apart.
|
|
|
152
152
|
|
|
153
153
|
| Class | Meaning |
|
|
154
154
|
|---|---|
|
|
155
|
-
| `RateLimited` | 429 — one of five limits, and `.code` says which: `rate_limited` (the
|
|
155
|
+
| `RateLimited` | 429 — one of five limits, and `.code` says which: `rate_limited` (the account's request rate), `too_many_uploads`, `too_many_keys`, `too_many_jobs` or `queue_full`. `.retryAfter` is seconds to wait: until the window rolls over for the two per-minute limits, until a new key can be made for the hourly one, or an interval to poll on for the other two. |
|
|
156
156
|
| `JobFailed` | The job ran and did not succeed. `.message` says what you can do about it; `.errorCode` is the half to branch on; `.jobId` is the job. |
|
|
157
157
|
| `InvalidSignature` | A webhook delivery did not verify. Do not act on its body. |
|
|
158
158
|
| `CraterViewError` | Everything else, including 4xx and 5xx from the API, and storage refusing an upload or a download. |
|
|
@@ -187,8 +187,9 @@ result's file are getters onto `result.output` rather than separate fields — t
|
|
|
187
187
|
those links once. A model with no file to hand back returns its answer in `result` and leaves
|
|
188
188
|
every one of them null; the fields it answers with are its `result_schema` in `cv.models()`.
|
|
189
189
|
|
|
190
|
-
`credits` is the only figure about cost the API states, and
|
|
191
|
-
|
|
190
|
+
`credits` is the only figure about cost the API states, and each model publishes its price in
|
|
191
|
+
`cv.models()` — `credits_per_image`, and `credit_steps` where a smaller image costs less — so
|
|
192
|
+
an invoice reconciles against `credits` alone. For how long a job took, subtract
|
|
192
193
|
`createdAt` from `finishedAt` — that is the wait you had, queue included.
|
|
193
194
|
|
|
194
195
|
**Uploads declare their size.** `upload()` and `run()` take the length from the `Blob`
|
|
@@ -197,8 +198,8 @@ accepts exactly that length and nothing else. You do not pass it — it is read
|
|
|
197
198
|
in hand, which is what makes it impossible to get wrong.
|
|
198
199
|
|
|
199
200
|
**Running out of credit does not stop you.** A job submitted against a balance of zero is
|
|
200
|
-
accepted and
|
|
201
|
-
on shared, free capacity and can wait longer at busy times. It comes back with `community`
|
|
201
|
+
accepted, and unless a subscription has work left this period it runs free on the community
|
|
202
|
+
queue, which runs on shared, free capacity and can wait longer at busy times. It comes back with `community`
|
|
202
203
|
set, and `usage()` reports the same flag for your next job before you send it. There is no
|
|
203
204
|
payment error to handle: paying — with credit, or with a subscription — moves work onto paid
|
|
204
205
|
compute that scales with demand, rather than buying the right to submit.
|
|
@@ -327,7 +328,7 @@ to storage and have five minutes.
|
|
|
327
328
|
## From Claude Code
|
|
328
329
|
|
|
329
330
|
This repository is also a Claude Code marketplace. Two plugins: `craterview` connects
|
|
330
|
-
CraterView's hosted tools so the assistant enhances images in the conversation, and
|
|
331
|
+
CraterView.ai's hosted tools so the assistant enhances images in the conversation, and
|
|
331
332
|
`craterview-api` teaches an agent to call the API from code with this client. See
|
|
332
333
|
[`plugins/`](plugins/) for what each does and how it finds a key.
|
|
333
334
|
|
|
@@ -340,7 +341,7 @@ CraterView's hosted tools so the assistant enhances images in the conversation,
|
|
|
340
341
|
## Versioning
|
|
341
342
|
|
|
342
343
|
Semver, from `0.1.0` on. A release that removes an exported member, renames a field on `Job`
|
|
343
|
-
or `ModelInfo`, or changes the type of one
|
|
344
|
+
or `ModelInfo`, or changes the type of one gets a minor bump while this is `0.x` and a major
|
|
344
345
|
bump after `1.0.0`; anything purely additive gets a patch. Pin what you depend on.
|
|
345
346
|
|
|
346
347
|
The API this wraps adds fields to its responses without warning, so treat an unfamiliar key in
|
package/index.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { imageSize } from "image-size";
|
|
|
18
18
|
// Mirrored from package.json, which is the number a release bumps. It cannot be imported
|
|
19
19
|
// from there — this ships as TypeScript, so the import would have to resolve in the
|
|
20
20
|
// consumer's toolchain — so test/version.test.ts asserts the two agree.
|
|
21
|
-
export const VERSION = "0.4.
|
|
21
|
+
export const VERSION = "0.4.29";
|
|
22
22
|
const DEFAULT_BASE_URL = "https://api.craterview.ai";
|
|
23
23
|
// The server rejects a longer wait outright, so asking for one costs a 422 rather than the
|
|
24
24
|
// wait you asked for. `run()` clamps to this rather than letting that happen.
|
|
@@ -154,7 +154,8 @@ export class CraterViewError extends Error {
|
|
|
154
154
|
* says which — `rate_limited`, `too_many_keys`, `too_many_uploads`, `too_many_jobs` or
|
|
155
155
|
* `queue_full`, in this order:
|
|
156
156
|
*
|
|
157
|
-
* - the
|
|
157
|
+
* - the account's request rate, per minute — counted across all its keys, for submitting
|
|
158
|
+
* jobs, creating keys and gallery calls. No other call counts;
|
|
158
159
|
* - the account's new keys, per hour — counted across all its keys, and only from
|
|
159
160
|
* `createKey`;
|
|
160
161
|
* - the account's upload URLs, per minute — counted across all its keys;
|
|
@@ -336,11 +337,19 @@ function timingSafeEqual(a: string, b: string): boolean {
|
|
|
336
337
|
* with `JobData` — there is no wrapper class here because there is no behavior to add.
|
|
337
338
|
*/
|
|
338
339
|
export interface ModelInfo {
|
|
339
|
-
/**
|
|
340
|
-
|
|
341
|
-
|
|
340
|
+
/** What you pass as `model` when submitting. Not for showing to a person; that is `title`. */
|
|
341
|
+
id: string;
|
|
342
|
+
/**
|
|
343
|
+
* Which revision of this model is in service. It changes when the same input gives a
|
|
344
|
+
* different result, while the id stays the same; record it to explain an old result later.
|
|
345
|
+
*/
|
|
346
|
+
revision: string;
|
|
347
|
+
/** What to call this model when talking to a person. */
|
|
342
348
|
title: string;
|
|
349
|
+
/** What this model is for and when to choose it over another; for a program or an agent. */
|
|
343
350
|
description: string;
|
|
351
|
+
/** What this model does, in one short line for a person choosing it in an app. */
|
|
352
|
+
help: string;
|
|
344
353
|
accepts: string[];
|
|
345
354
|
/**
|
|
346
355
|
* The media type a result usually comes back as, and advisory: a model that keeps the
|
|
@@ -365,6 +374,12 @@ export interface ModelInfo {
|
|
|
365
374
|
* utility or fun experiment.
|
|
366
375
|
*/
|
|
367
376
|
tenure?: "fixed" | "comet";
|
|
377
|
+
/**
|
|
378
|
+
* Whether this is a model for testing an integration rather than for use: free, and it
|
|
379
|
+
* returns a result of the right size without improving the picture. `echo` is one.
|
|
380
|
+
* CraterView's apps do not offer it; an app built on this catalog should leave it out too.
|
|
381
|
+
*/
|
|
382
|
+
test_model?: boolean;
|
|
368
383
|
max_input_bytes: number;
|
|
369
384
|
/**
|
|
370
385
|
* The ceilings **your key** is held to, not the model's widest. Community work is bounded
|
|
@@ -372,16 +387,16 @@ export interface ModelInfo {
|
|
|
372
387
|
* before uploading rather than learning them from a rejected job.
|
|
373
388
|
*
|
|
374
389
|
* `max_frame_megapixels` bounds one frame you send, and applies to images too since a
|
|
375
|
-
* still is one frame. `max_frames` bounds how many frames one job may carry.
|
|
376
|
-
* that axis is
|
|
390
|
+
* still is one frame. `max_frames` bounds how many frames one job may carry. Null means
|
|
391
|
+
* nothing bounds that axis for you; a limit is never 0.
|
|
377
392
|
*
|
|
378
393
|
* For a duration, divide: `max_frames / reference_fps` is the longest clip you may send, in
|
|
379
394
|
* seconds. It is not published as its own field on purpose — one limit with two spellings
|
|
380
395
|
* is one that can disagree with itself, and frames are what the platform counts, enforces
|
|
381
396
|
* and bills on.
|
|
382
397
|
*/
|
|
383
|
-
max_frame_megapixels: number;
|
|
384
|
-
max_frames: number;
|
|
398
|
+
max_frame_megapixels: number | null;
|
|
399
|
+
max_frames: number | null;
|
|
385
400
|
/**
|
|
386
401
|
* The largest frame you may get **back**, in megapixels, and for a model that enlarges it
|
|
387
402
|
* is the ceiling that decides whether a job runs: what returns is the frame you send
|
|
@@ -392,44 +407,53 @@ export interface ModelInfo {
|
|
|
392
407
|
*
|
|
393
408
|
* ```ts
|
|
394
409
|
* const result = megapixels * scale ** 2;
|
|
395
|
-
* if (model.max_output_megapixels && result > model.max_output_megapixels) {
|
|
410
|
+
* if (model.max_output_megapixels !== null && result > model.max_output_megapixels) {
|
|
396
411
|
* // send a smaller region of the image, or ask for less enlargement
|
|
397
412
|
* }
|
|
398
413
|
* ```
|
|
399
414
|
*
|
|
400
415
|
* Sending a smaller region keeps every pixel of what it covers; asking for less
|
|
401
|
-
* enlargement keeps the whole picture.
|
|
416
|
+
* enlargement keeps the whole picture. Null means nothing bounds it for you.
|
|
402
417
|
*/
|
|
403
|
-
max_output_megapixels: number;
|
|
418
|
+
max_output_megapixels: number | null;
|
|
404
419
|
/**
|
|
405
|
-
* The most of a picture
|
|
420
|
+
* The most of a picture one job may work on for you, in megapixels: the region you
|
|
406
421
|
* name with `roi`, or the whole image. Where it is set it binds at every enlargement, so
|
|
407
422
|
* the largest frame you may send is the smaller of this and `max_output_megapixels`
|
|
408
423
|
* divided by the square of the enlargement — and asking for less enlargement does not
|
|
409
|
-
* help with it, where a smaller region does.
|
|
424
|
+
* help with it, where a smaller region does. Null means nothing bounds it for you.
|
|
410
425
|
*/
|
|
411
|
-
max_input_megapixels: number;
|
|
426
|
+
max_input_megapixels: number | null;
|
|
412
427
|
/**
|
|
413
|
-
* The most of a picture
|
|
414
|
-
*
|
|
415
|
-
* `
|
|
428
|
+
* The most of a picture one job may work on for you at each `binning` value, in megapixels,
|
|
429
|
+
* keyed by the value ("2x2", "3x3", ...); `max_input_megapixels` applies with binning off.
|
|
430
|
+
* Each is `max_output_megapixels` divided by the square of the largest scale that binning
|
|
431
|
+
* allows. Null for a model that takes no `binning`, or when nothing bounds it for you.
|
|
416
432
|
*/
|
|
417
|
-
|
|
433
|
+
max_input_megapixels_by_binning?: Record<string, number> | null;
|
|
418
434
|
/**
|
|
419
|
-
* The
|
|
420
|
-
*
|
|
421
|
-
*
|
|
422
|
-
* rather than refused: see `working_megapixels`. Null for a model that takes no `tiled`.
|
|
435
|
+
* The shortest side, in pixels, of the part of a picture this model works on: the region
|
|
436
|
+
* you name with `roi`, or the whole image. A job with a shorter one fails before the model
|
|
437
|
+
* runs, as `input_too_small`, and is not charged. The same for every key.
|
|
423
438
|
*/
|
|
424
|
-
|
|
439
|
+
min_input_side: number;
|
|
425
440
|
/**
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
* unless `tiled` is sent as true. Null for a model that works at the size it is given.
|
|
441
|
+
* Whole credits: what one still image costs, or the most one costs where `credit_steps`
|
|
442
|
+
* charges less for a smaller one. Knowable before you send anything.
|
|
429
443
|
*/
|
|
430
|
-
working_megapixels?: number | null;
|
|
431
|
-
/** Whole credits. The price is flat and knowable before you send anything. */
|
|
432
444
|
credits_per_image: number;
|
|
445
|
+
/**
|
|
446
|
+
* A lower price for a smaller still image, or null where every one costs
|
|
447
|
+
* `credits_per_image`. `by` is `megapixels` — the part of the image a job works on, the
|
|
448
|
+
* region you name with `roi` or the whole image, in millions of pixels, divided by 4 at
|
|
449
|
+
* `binning` 2x2, 9 at 3x3 and 16 at 4x4 — or `faces`, the faces the model redraws, counted
|
|
450
|
+
* when the job finishes. A still costs the first step its measure is at or under, and
|
|
451
|
+
* `credits_per_image` past the last.
|
|
452
|
+
*/
|
|
453
|
+
credit_steps?: {
|
|
454
|
+
by: "megapixels" | "faces";
|
|
455
|
+
steps: { up_to: number; credits: number }[];
|
|
456
|
+
} | null;
|
|
433
457
|
/** Whole credits. Null means this model takes stills only. */
|
|
434
458
|
credits_per_video_second?: number | null;
|
|
435
459
|
reference_fps: number;
|
|
@@ -439,6 +463,12 @@ export interface ModelInfo {
|
|
|
439
463
|
* not order an object's keys, so a form drawn from the schema reads its order from here.
|
|
440
464
|
*/
|
|
441
465
|
params_order: string[];
|
|
466
|
+
/**
|
|
467
|
+
* A short line for a person choosing each setting in a form, keyed by parameter name: every
|
|
468
|
+
* parameter in `params_schema` that one control can set. Show it under the control. For what
|
|
469
|
+
* a value may be and what may be sent together, read `params_schema`.
|
|
470
|
+
*/
|
|
471
|
+
params_help: Record<string, string>;
|
|
442
472
|
/**
|
|
443
473
|
* JSON Schema for the fields a finished job of this model states under `result`, beside
|
|
444
474
|
* any files it links. Empty for a model whose whole answer is its file.
|
|
@@ -466,7 +496,6 @@ export interface KeyInfo {
|
|
|
466
496
|
created_at: string | null;
|
|
467
497
|
/** When it stopped working, or null while it still does. */
|
|
468
498
|
revoked_at?: string;
|
|
469
|
-
rate_limit_per_minute: number;
|
|
470
499
|
/**
|
|
471
500
|
* Whether this is the key you are calling with. It cannot be revoked by id while it is;
|
|
472
501
|
* `DELETE /v1/keys/current` ends it on request, unless it is the account's only way
|
|
@@ -482,7 +511,6 @@ export interface NewKey {
|
|
|
482
511
|
key: string;
|
|
483
512
|
prefix: string;
|
|
484
513
|
name: string;
|
|
485
|
-
rate_limit_per_minute: number;
|
|
486
514
|
}
|
|
487
515
|
|
|
488
516
|
/**
|
|
@@ -1023,7 +1051,9 @@ export class CraterView {
|
|
|
1023
1051
|
* charged when it succeeds, so queued and running work is not in the figures yet, and a
|
|
1024
1052
|
* failed job costs nothing.
|
|
1025
1053
|
*
|
|
1026
|
-
* `credits_remaining` is
|
|
1054
|
+
* The balance is `credits_remaining`; `credits_spent` is what the account has spent, all
|
|
1055
|
+
* time, and `credits_granted` what it has been given. `credits_remaining` is always a
|
|
1056
|
+
* number, floored at zero. A balance of zero never stops a
|
|
1027
1057
|
* submission: `community` says whether your next job runs on the community queue, which is
|
|
1028
1058
|
* free and can wait longer at busy times, or on paid compute. `jobs_in_flight` and
|
|
1029
1059
|
* `max_jobs_in_flight` are the state of the queue and are what a 429 on submit is about.
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "craterview",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.29",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"image-size": "^2.0.4"
|
|
6
6
|
},
|
|
7
|
-
"description": "TypeScript client for the CraterView image enhancement API",
|
|
7
|
+
"description": "TypeScript client for the CraterView.ai image enhancement API",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "index.ts",
|
|
10
10
|
"types": "index.ts",
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
"test": "vitest run"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@types/node": "^26.6.
|
|
28
|
+
"@types/node": "^26.6.6",
|
|
29
29
|
"esbuild": "^0.28.2",
|
|
30
30
|
"tsx": "^4.23.15",
|
|
31
31
|
"typescript": "^7.0.2",
|
|
32
|
-
"vitest": "^5.0.
|
|
32
|
+
"vitest": "^5.0.5"
|
|
33
33
|
}
|
|
34
34
|
}
|