@onlyworlds/sdk 4.6.0 → 4.7.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/AGENTS.md +1 -1
- package/CHANGELOG.md +21 -3
- package/README.md +3 -3
- package/dist/index.d.ts +28 -20
- package/dist/index.js +21 -10
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -21,7 +21,7 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
|
|
|
21
21
|
- Known, deterministic operations (CRUD, sync, bulk) → **this SDK**. Typed calls, typed
|
|
22
22
|
responses, far cheaper than tool-schema reasoning.
|
|
23
23
|
- Live exploration of a user's world from a chat/agent context → the **MCP server** at
|
|
24
|
-
`https://www.onlyworlds.com/mcp` (same `API-Key`/`API-Pin` headers,
|
|
24
|
+
`https://www.onlyworlds.com/mcp` (same `API-Key`/`API-Pin` headers, 12 tools).
|
|
25
25
|
|
|
26
26
|
**Wire facts that bite** (full details in README):
|
|
27
27
|
- Never send a `"world"` field in payloads — world identity comes from the API key (422 otherwise).
|
package/CHANGELOG.md
CHANGED
|
@@ -5,13 +5,31 @@ earlier history lives in git log only.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
-
## [4.
|
|
8
|
+
## [4.7.0] — 2026-10-08
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`OwApiError.isResyncRequired`**: 409 `resync_required` from `/changes`. Guests can follow the
|
|
12
|
+
feed since keel D79; when a guest's view or a key's role changes, its stored cursor is refused. Drop
|
|
13
|
+
it, walk from zero, and replace the local copy rather than merging.
|
|
14
|
+
|
|
15
|
+
### Documented
|
|
16
|
+
- `uploadImage` accepts webp, png, jpeg and avif. 4.6.0's JSDoc and README also listed gif, which
|
|
17
|
+
the edge refuses (415 `unsupported_type`); checked against the Worker's type table.
|
|
18
|
+
- `changes()`: the old rewind rule compared a stored cursor with `head`, which an opaque cursor
|
|
19
|
+
cannot do; replaced with the reset rule (`isResyncRequired`).
|
|
20
|
+
- The doc comments of `OwClientConfig`, `create` and `uploadImage` are written for users: internal
|
|
21
|
+
ruling numbers and test-harness notes are gone, and each opens with what the option or method does.
|
|
22
|
+
The docs site's TypeScript reference is generated from these comments.
|
|
23
|
+
|
|
24
|
+
## [4.6.0] — 2026-10-06
|
|
25
|
+
|
|
26
|
+
Published from `e198298` (tag `v4.6.0`); the tarball was checked against a build of that commit.
|
|
9
27
|
|
|
10
28
|
Includes 4.5.1's documentation fixes: 4.5.1 was staged and never published.
|
|
11
29
|
|
|
12
30
|
### Added
|
|
13
|
-
- **`uploadImage(image, { key?, ticket? })`**: upload one image (webp, png, jpeg, avif
|
|
14
|
-
never SVG) and get its permanent public URL. Two requests: a ticket from keel
|
|
31
|
+
- **`uploadImage(image, { key?, ticket? })`**: upload one image (webp, png, jpeg, avif;
|
|
32
|
+
never SVG; 4.6.0's docs also said gif, which the edge refuses with 415) and get its permanent public URL. Two requests: a ticket from keel
|
|
15
33
|
(`POST /media/ticket`), then the bytes straight to the edge at the ticket's `upload_url`
|
|
16
34
|
(keel never sees them). Only the ticket goes to the edge, never the API key or PIN. An image
|
|
17
35
|
larger than the ticket's `max_bytes` throws 413 `too_large` before anything is sent; the edge's
|
package/README.md
CHANGED
|
@@ -98,8 +98,8 @@ await writer.patch('character', id, { image_url: image.url });
|
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
Two requests: a single-use ticket from keel, then the bytes straight to the edge (keel never
|
|
101
|
-
sees them, and the edge never sees your key). webp, png, jpeg
|
|
102
|
-
bytes
|
|
101
|
+
sees them, and the edge never sees your key). webp, png, jpeg or avif (never SVG or gif), read from the
|
|
102
|
+
bytes. Each ticket counts toward the world's daily limit and the account's image
|
|
103
103
|
storage. To upload yourself (for a progress bar), take `createMediaTicket()` and POST the bytes to
|
|
104
104
|
its `upload_url` with `Authorization: Bearer <ticket>`.
|
|
105
105
|
|
|
@@ -151,7 +151,7 @@ const status = await tokens.getStatus();
|
|
|
151
151
|
|
|
152
152
|
For **known, deterministic operations** (CRUD, sync, bulk) use this SDK — typed calls, no
|
|
153
153
|
tool-schema overhead. For **live exploration of a user's world from a chat/agent context**, use
|
|
154
|
-
the MCP server at `https://www.onlyworlds.com/mcp` (same `API-Key`/`API-Pin` headers,
|
|
154
|
+
the MCP server at `https://www.onlyworlds.com/mcp` (same `API-Key`/`API-Pin` headers, 12 tools;
|
|
155
155
|
unaffected by SDK versioning).
|
|
156
156
|
|
|
157
157
|
## License
|
package/dist/index.d.ts
CHANGED
|
@@ -2000,27 +2000,26 @@ interface ListParams {
|
|
|
2000
2000
|
filter?: Record<string, string | number | boolean>;
|
|
2001
2001
|
}
|
|
2002
2002
|
interface OwClientConfig {
|
|
2003
|
-
/** ow_w_
|
|
2003
|
+
/** The key: an ow_w_ (write) or ow_r_ (read) world key, an ow_a_ account token (sent as a Bearer token, for the account routes), or a 10-digit legacy key. */
|
|
2004
2004
|
apiKey: string;
|
|
2005
2005
|
/**
|
|
2006
|
-
*
|
|
2007
|
-
*
|
|
2008
|
-
* '0123' !== 123.
|
|
2006
|
+
* The PIN, needed for writes when the world has one, and for legacy-key reads of private worlds.
|
|
2007
|
+
* Prefixed keys read without a PIN. A string, not a number: '0123' !== 123.
|
|
2009
2008
|
*/
|
|
2010
2009
|
apiPin?: string;
|
|
2011
|
-
/**
|
|
2010
|
+
/** The API's base URL, default https://www.onlyworlds.com/api/v2. */
|
|
2012
2011
|
baseUrl?: string;
|
|
2013
2012
|
/**
|
|
2014
|
-
* Page size for element lists
|
|
2015
|
-
*
|
|
2013
|
+
* Page size for element lists, default 100 (the server's default; at most 1000).
|
|
2014
|
+
* It is in the config on purpose: page size decides the load a client puts on the server.
|
|
2016
2015
|
*/
|
|
2017
2016
|
pageSize?: number;
|
|
2018
2017
|
/**
|
|
2019
|
-
* Page size for /changes pulls
|
|
2020
|
-
*
|
|
2018
|
+
* Page size for /changes pulls, default 100. Tools in use pick 25 to 250; the change feed
|
|
2019
|
+
* is the platform's heaviest route, so keep it modest.
|
|
2021
2020
|
*/
|
|
2022
2021
|
changesPageSize?: number;
|
|
2023
|
-
/**
|
|
2022
|
+
/** A fetch implementation to use instead of globalThis.fetch (for tests and other runtimes). */
|
|
2024
2023
|
fetch?: typeof globalThis.fetch;
|
|
2025
2024
|
}
|
|
2026
2025
|
|
|
@@ -2079,6 +2078,13 @@ declare class OwApiError extends Error {
|
|
|
2079
2078
|
* per-item slot `{status: 409, error: {code: 'id_conflict'}}` — check the slot.
|
|
2080
2079
|
*/
|
|
2081
2080
|
get isIdConflict(): boolean;
|
|
2081
|
+
/**
|
|
2082
|
+
* `/changes` refused the cursor (409 `resync_required`): a guest's view of the world
|
|
2083
|
+
* changed, or the key's role did (a guest's cursor has another shape). Drop the stored
|
|
2084
|
+
* cursor, walk again from the start, and REPLACE the local copy rather than merging into
|
|
2085
|
+
* it: a guest never receives delete ops, so only the replace removes what it no longer sees.
|
|
2086
|
+
*/
|
|
2087
|
+
get isResyncRequired(): boolean;
|
|
2082
2088
|
/** keel's admission control turned the request away (503 `server_busy`); see retryAfter. */
|
|
2083
2089
|
get isBusy(): boolean;
|
|
2084
2090
|
/**
|
|
@@ -2175,11 +2181,11 @@ declare class OwV2Client {
|
|
|
2175
2181
|
/** GET /{type}/{id}/ -- optional one-level stub expansion / sparse fields. */
|
|
2176
2182
|
get(type: ElementType | string, id: string, opts?: Pick<ListParams, 'expand' | 'fields'>): Promise<OwElement>;
|
|
2177
2183
|
/**
|
|
2178
|
-
* POST /{type}/ -- create
|
|
2179
|
-
*
|
|
2180
|
-
*
|
|
2184
|
+
* POST /{type}/ -- create one element, minting a UUIDv7 id on the client when you leave id out.
|
|
2185
|
+
* The client-side id makes a retry carrying the same Idempotency-Key safe: it rewrites
|
|
2186
|
+
* the same element instead of creating a second one. You may still supply your own id.
|
|
2181
2187
|
* `name` is the one required field, and required means the key is present: `''` and
|
|
2182
|
-
* `null` are accepted and stored as `''` (nameless Markers exist
|
|
2188
|
+
* `null` are accepted and stored as `''` (nameless Markers exist).
|
|
2183
2189
|
*/
|
|
2184
2190
|
create(type: ElementType | string, element: OwElement | Record<string, unknown>, opts?: {
|
|
2185
2191
|
idempotencyKey?: string;
|
|
@@ -2223,10 +2229,12 @@ declare class OwV2Client {
|
|
|
2223
2229
|
}): Promise<OwBulkResponse>;
|
|
2224
2230
|
/**
|
|
2225
2231
|
* GET /changes -- one page of the world's ordered change feed.
|
|
2226
|
-
* Cursor is OPAQUE
|
|
2232
|
+
* Cursor is OPAQUE: persist verbatim, never parse or build one (a guest's has
|
|
2233
|
+
* another shape than everyone else's).
|
|
2227
2234
|
* Zero/absent cursor = full export (byte-aligned with the Folder Format).
|
|
2228
|
-
*
|
|
2229
|
-
*
|
|
2235
|
+
* Reset rule: a 409 `resync_required` (err.isResyncRequired) means the key's
|
|
2236
|
+
* view changed (a guest's, or its role): drop the cursor, walk from zero, and
|
|
2237
|
+
* replace the local copy rather than merging into it.
|
|
2230
2238
|
* Citizenship: heaviest route on the platform; default page size is polite.
|
|
2231
2239
|
*/
|
|
2232
2240
|
changes(opts?: {
|
|
@@ -2254,12 +2262,12 @@ declare class OwV2Client {
|
|
|
2254
2262
|
*/
|
|
2255
2263
|
createMediaTicket(): Promise<OwMediaTicket>;
|
|
2256
2264
|
/**
|
|
2257
|
-
* Upload one image and get its permanent public URL: a ticket from
|
|
2258
|
-
* bytes straight to the edge (
|
|
2265
|
+
* Upload one image and get its permanent public URL: a ticket from the API, then the
|
|
2266
|
+
* bytes straight to the media edge (the API never sees them). Pass a ticket from
|
|
2259
2267
|
* createMediaTicket() to use it instead of fetching one. Returns the edge's 201;
|
|
2260
2268
|
* set `url` as an element's `image_url` yourself (`patch(type, id, { image_url })`).
|
|
2261
2269
|
*
|
|
2262
|
-
* webp, png, jpeg
|
|
2270
|
+
* webp, png, jpeg or avif, read from the bytes (never SVG or gif). `key` names the
|
|
2263
2271
|
* object (it must start with the ticket's `prefix`; without it the edge picks one).
|
|
2264
2272
|
* An image larger than the ticket's `max_bytes` throws 413 `too_large` before any
|
|
2265
2273
|
* byte is sent. The edge's refusals arrive as OwApiError with its code: 401
|
package/dist/index.js
CHANGED
|
@@ -35,6 +35,15 @@ var OwApiError = class extends Error {
|
|
|
35
35
|
get isIdConflict() {
|
|
36
36
|
return this.status === 409 && this.code === "id_conflict";
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* `/changes` refused the cursor (409 `resync_required`): a guest's view of the world
|
|
40
|
+
* changed, or the key's role did (a guest's cursor has another shape). Drop the stored
|
|
41
|
+
* cursor, walk again from the start, and REPLACE the local copy rather than merging into
|
|
42
|
+
* it: a guest never receives delete ops, so only the replace removes what it no longer sees.
|
|
43
|
+
*/
|
|
44
|
+
get isResyncRequired() {
|
|
45
|
+
return this.status === 409 && this.code === "resync_required";
|
|
46
|
+
}
|
|
38
47
|
/** keel's admission control turned the request away (503 `server_busy`); see retryAfter. */
|
|
39
48
|
get isBusy() {
|
|
40
49
|
return this.status === 503 && this.code === "server_busy";
|
|
@@ -188,11 +197,11 @@ var OwV2Client = class {
|
|
|
188
197
|
return this.request("GET", `/${type}/${id}/`, { query });
|
|
189
198
|
}
|
|
190
199
|
/**
|
|
191
|
-
* POST /{type}/ -- create
|
|
192
|
-
*
|
|
193
|
-
*
|
|
200
|
+
* POST /{type}/ -- create one element, minting a UUIDv7 id on the client when you leave id out.
|
|
201
|
+
* The client-side id makes a retry carrying the same Idempotency-Key safe: it rewrites
|
|
202
|
+
* the same element instead of creating a second one. You may still supply your own id.
|
|
194
203
|
* `name` is the one required field, and required means the key is present: `''` and
|
|
195
|
-
* `null` are accepted and stored as `''` (nameless Markers exist
|
|
204
|
+
* `null` are accepted and stored as `''` (nameless Markers exist).
|
|
196
205
|
*/
|
|
197
206
|
async create(type, element, opts = {}) {
|
|
198
207
|
const body = sanitizePayload(element);
|
|
@@ -260,10 +269,12 @@ var OwV2Client = class {
|
|
|
260
269
|
// -- Changes feed --------------------------------------------------------
|
|
261
270
|
/**
|
|
262
271
|
* GET /changes -- one page of the world's ordered change feed.
|
|
263
|
-
* Cursor is OPAQUE
|
|
272
|
+
* Cursor is OPAQUE: persist verbatim, never parse or build one (a guest's has
|
|
273
|
+
* another shape than everyone else's).
|
|
264
274
|
* Zero/absent cursor = full export (byte-aligned with the Folder Format).
|
|
265
|
-
*
|
|
266
|
-
*
|
|
275
|
+
* Reset rule: a 409 `resync_required` (err.isResyncRequired) means the key's
|
|
276
|
+
* view changed (a guest's, or its role): drop the cursor, walk from zero, and
|
|
277
|
+
* replace the local copy rather than merging into it.
|
|
267
278
|
* Citizenship: heaviest route on the platform; default page size is polite.
|
|
268
279
|
*/
|
|
269
280
|
async changes(opts = {}) {
|
|
@@ -300,12 +311,12 @@ var OwV2Client = class {
|
|
|
300
311
|
return this.request("POST", "/media/ticket");
|
|
301
312
|
}
|
|
302
313
|
/**
|
|
303
|
-
* Upload one image and get its permanent public URL: a ticket from
|
|
304
|
-
* bytes straight to the edge (
|
|
314
|
+
* Upload one image and get its permanent public URL: a ticket from the API, then the
|
|
315
|
+
* bytes straight to the media edge (the API never sees them). Pass a ticket from
|
|
305
316
|
* createMediaTicket() to use it instead of fetching one. Returns the edge's 201;
|
|
306
317
|
* set `url` as an element's `image_url` yourself (`patch(type, id, { image_url })`).
|
|
307
318
|
*
|
|
308
|
-
* webp, png, jpeg
|
|
319
|
+
* webp, png, jpeg or avif, read from the bytes (never SVG or gif). `key` names the
|
|
309
320
|
* object (it must start with the ticket's `prefix`; without it the edge picks one).
|
|
310
321
|
* An image larger than the ticket's `max_bytes` throws 413 `too_large` before any
|
|
311
322
|
* byte is sent. The edge's refusals arrive as OwApiError with its code: 401
|