@onlyworlds/sdk 4.8.0 → 4.9.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 CHANGED
@@ -1,63 +1,66 @@
1
- # For AI agents using @onlyworlds/sdk
2
-
3
- **Current as of**: SDK **4.x** · schema-dist **v0.31.0-dist.19** (canonical 00.31.00).
4
- This line is asserted by `codegen:check` in CI — if the pin moves and this file is not
5
- re-read against it, the check fails rather than letting this document rot quietly.
6
-
7
- **Start with [SCHEMA.md](SCHEMA.md)** (in this package): the full generated schema reference —
8
- every type, every field with its meaning, link directions, families, icons, display sections.
9
- It is generated from the same canonical YAML as the types, so it cannot drift.
10
-
11
- **What this package is**: the canonical typed TypeScript client for the OnlyWorlds v2 API,
12
- plus the canonical constants (element types, icons, colour families, field schema).
13
- OnlyWorlds is an open standard for portable world data — 22 element types, UUID-linked.
14
-
15
- **Use the v2 surface.** `OwV2Client` + the `V2ElementType` slug union + the generated
16
- interfaces in `types.generated.ts` (emitted from the canonical schema YAML, validated
17
- against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum) is not in
18
- 4.x — it was removed at 4.0.0 and lives only in 3.x. Do not build new work on it.
19
-
20
- **SDK vs MCP server — pick correctly**:
21
- - Known, deterministic operations (CRUD, sync, bulk) → **this SDK**. Typed calls, typed
22
- responses, far cheaper than tool-schema reasoning.
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, 12 tools).
25
-
26
- **Wire facts that bite** (full details in README):
27
- - Never send a `"world"` field in payloads — world identity comes from the API key (422 otherwise).
28
- - v2 link fields use ONE name both directions (no `_ids` suffix — that is v1 dialect only).
29
- - PATCH is destructive on sent fields; use `editLinks` (atomic add/remove) for relationships.
30
- - World-meta changes do NOT appear in `/changes` — poll `GET /world` separately.
31
- - Extension fields: `x_<toolname>_*` is the sanctioned namespace for tool-specific state;
32
- unknown unprefixed fields 422. Extensions are capped at **64 KB per element** (422,
33
- `param: extensions`).
34
- - List filters: `name` (exact), `name__icontains`, `supertype`, `subtype`, and
35
- `characters=<id>` on types with a `characters` link. Any other filter key — and
36
- `?ordering=` — returns 422 naming the accepted ones. Sort client-side.
37
- - Images: `uploadImage(bytes)` returns `{ url, ... }`; set `url` as `image_url`. The bytes go
38
- to the edge with a single-use ticket from keel, never with the API key. `removeImage(urlOrKey)`
39
- takes one back (its uploader or the world's owner); it leaves `image_url` on elements as is.
40
- - Ids: the client mints **UUIDv7** on an id-less `create` (since 4.2.0; keel mints v7 too).
41
- A v4 or v7 id you supply is accepted. **Never sort elements by id**: worlds mix v7, v4
42
- and legacy `06x…` ids (nibble 7 too, but seconds-first). For creation order use
43
- `created_at`; `change_seq` is last-write order, not creation.
44
- A create with an id that already exists, or a PUT whose id belongs to **another world**,
45
- returns 409 `id_conflict` (`err.isIdConflict`; retrying won't help). `/bulk` never throws:
46
- check each slot for `status: 409` with `error.code: 'id_conflict'`. A different 409, `idempotency_error`, means an
47
- Idempotency-Key was reused with another body (`err.isIdempotencyConflict`).
48
- - Under load keel answers 503 `server_busy` with `Retry-After` (`err.isBusy`, `err.retryAfter`
49
- in seconds). The client does not retry for you; back off and retry yourself. Works the same
50
- in browsers.
51
- - `created_by` rides every element read: the id of the membership that created it, `null` for
52
- the world's owner and for anything made before memberships existed. It is read-only; a write
53
- body that carries it has it dropped, never an error. A **contributor** can change only what
54
- they created: anything else is 403 `not_author` (`err.isNotAuthor`; retrying will not help).
55
- `/bulk` reports it per slot, not as a throw.
56
- - A string holding an unpaired surrogate (text cut mid-emoji) is a 422 naming the field.
57
- Slice strings by code point, not by UTF-16 unit.
58
- - Colour carries the element's FAMILY (`elementColor(type, mode)`); the icon
59
- (`ELEMENT_ICONS`) carries the TYPE. Icon + label are required alongside colour, not optional.
60
-
61
- **Auth**: prefixed keys — `ow_w_` (read+write), `ow_r_` (read-only, no PIN — the share
62
- primitive), `ow_a_` (account Bearer). Demo keys `0000000000`–`0000000009` are read-only
63
- test credentials against real data.
1
+ # For AI agents using @onlyworlds/sdk
2
+
3
+ **Current as of**: SDK **4.x** · schema-dist **v0.32.0-dist.20** (canonical 00.32.00).
4
+ This line is asserted by `codegen:check` in CI — if the pin moves and this file is not
5
+ re-read against it, the check fails rather than letting this document rot quietly.
6
+
7
+ **Start with [SCHEMA.md](SCHEMA.md)** (in this package): the full generated schema reference —
8
+ every type, every field with its meaning, link directions, families, icons, display sections.
9
+ It is generated from the same canonical YAML as the types, so it cannot drift.
10
+
11
+ **What this package is**: the canonical typed TypeScript client for the OnlyWorlds v2 API,
12
+ plus the canonical constants (element types, icons, colour families, field schema).
13
+ OnlyWorlds is an open standard for portable world data — 22 element types, UUID-linked.
14
+
15
+ **Use the v2 surface.** `OwV2Client` + the `V2ElementType` slug union + the generated
16
+ interfaces in `types.generated.ts` (emitted from the canonical schema YAML, validated
17
+ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum) is not in
18
+ 4.x — it was removed at 4.0.0 and lives only in 3.x. Do not build new work on it.
19
+
20
+ **SDK vs MCP server — pick correctly**:
21
+ - Known, deterministic operations (CRUD, sync, bulk) → **this SDK**. Typed calls, typed
22
+ responses, far cheaper than tool-schema reasoning.
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, 12 tools).
25
+
26
+ **Wire facts that bite** (full details in README):
27
+ - Never send a `"world"` field in payloads — world identity comes from the API key (422 otherwise).
28
+ - v2 link fields use ONE name both directions (no `_ids` suffix — that is v1 dialect only).
29
+ - PATCH is destructive on sent fields; use `editLinks` (atomic add/remove) for relationships.
30
+ - Offline or stale edits: pass `{ ifMatch: el.change_seq }` to `patch`/`editLinks` (since 4.9.0).
31
+ If the element moved, nothing is written and `OwPreconditionFailedError` (412) carries
32
+ `current`; the server never merges, the client decides.
33
+ - World-meta changes do NOT appear in `/changes` — poll `GET /world` separately.
34
+ - Extension fields: `x_<toolname>_*` is the sanctioned namespace for tool-specific state;
35
+ unknown unprefixed fields 422. Extensions are capped at **64 KB per element** (422,
36
+ `param: extensions`).
37
+ - List filters: `name` (exact), `name__icontains`, `supertype`, `subtype`, and
38
+ `characters=<id>` on types with a `characters` link. Any other filter key — and
39
+ `?ordering=` — returns 422 naming the accepted ones. Sort client-side.
40
+ - Images: `uploadImage(bytes)` returns `{ url, ... }`; set `url` as `image_url`. The bytes go
41
+ to the edge with a single-use ticket from keel, never with the API key. `removeImage(urlOrKey)`
42
+ takes one back (its uploader or the world's owner); it leaves `image_url` on elements as is.
43
+ - Ids: the client mints **UUIDv7** on an id-less `create` (since 4.2.0; keel mints v7 too).
44
+ A v4 or v7 id you supply is accepted. **Never sort elements by id**: worlds mix v7, v4
45
+ and legacy `06x…` ids (nibble 7 too, but seconds-first). For creation order use
46
+ `created_at`; `change_seq` is last-write order, not creation.
47
+ A create with an id that already exists, or a PUT whose id belongs to **another world**,
48
+ returns 409 `id_conflict` (`err.isIdConflict`; retrying won't help). `/bulk` never throws:
49
+ check each slot for `status: 409` with `error.code: 'id_conflict'`. A different 409, `idempotency_error`, means an
50
+ Idempotency-Key was reused with another body (`err.isIdempotencyConflict`).
51
+ - Under load keel answers 503 `server_busy` with `Retry-After` (`err.isBusy`, `err.retryAfter`
52
+ in seconds). The client does not retry for you; back off and retry yourself. Works the same
53
+ in browsers.
54
+ - `created_by` rides every element read: the id of the membership that created it, `null` for
55
+ the world's owner and for anything made before memberships existed. It is read-only; a write
56
+ body that carries it has it dropped, never an error. A **contributor** can change only what
57
+ they created: anything else is 403 `not_author` (`err.isNotAuthor`; retrying will not help).
58
+ `/bulk` reports it per slot, not as a throw.
59
+ - A string holding an unpaired surrogate (text cut mid-emoji) is a 422 naming the field.
60
+ Slice strings by code point, not by UTF-16 unit.
61
+ - Colour carries the element's FAMILY (`elementColor(type, mode)`); the icon
62
+ (`ELEMENT_ICONS`) carries the TYPE. Icon + label are required alongside colour, not optional.
63
+
64
+ **Auth**: prefixed keys — `ow_w_` (read+write), `ow_r_` (read-only, no PIN — the share
65
+ primitive), `ow_a_` (account Bearer). Demo keys `0000000000`–`0000000009` are read-only
66
+ test credentials against real data.