@onlyworlds/sdk 4.38.0 → 4.40.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 +6 -1
- package/CHANGELOG.md +40 -0
- package/SCHEMA.md +3 -1
- package/dist/index.d.ts +94 -7
- package/dist/index.js +74 -4
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# For AI agents using @onlyworlds/sdk
|
|
2
2
|
|
|
3
|
-
**Current as of**: SDK **4.x** · schema-dist **v0.32.1-dist.
|
|
3
|
+
**Current as of**: SDK **4.x** · schema-dist **v0.32.1-dist.27** (canonical 00.32.01).
|
|
4
4
|
This line is asserted by `codegen:check` in CI — if the pin moves and this file is not
|
|
5
5
|
re-read against it, the check fails rather than letting this document rot quietly.
|
|
6
6
|
|
|
@@ -106,6 +106,11 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
|
|
|
106
106
|
`mcp`, `declared`, `api`, `v1`, `sync`, `server`), and a `/changes` delete carries
|
|
107
107
|
`deleted_by` and `deleted_via`; `isAgentDoor(door)` is true for the first three. An agent
|
|
108
108
|
seat's key is recorded as an agent without the option. Never set it in a tool people use.
|
|
109
|
+
- A guest or player reads what its own Character's sheet links to as a **stub**, marked
|
|
110
|
+
`known_of: true` (`isKnownOf(el)`): only `id`, `type`, `name`, `description`, `supertype`,
|
|
111
|
+
`subtype`, `image_url` and the timestamps are real; every other field reads unset, and its
|
|
112
|
+
files are 404. Render it as known of, never merge its empties over a whole copy, and never
|
|
113
|
+
write it back: `upsert`, `patch`, `create` and `bulk` throw a TypeError on one before sending.
|
|
109
114
|
- A string holding an unpaired surrogate (text cut mid-emoji) is a 422 naming the field.
|
|
110
115
|
Slice strings by code point, not by UTF-16 unit.
|
|
111
116
|
- Colour carries the element's FAMILY (`elementColor(type, mode)`); the icon
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,46 @@ earlier history lives in git log only.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.40.0] - 2026-10-20
|
|
9
|
+
|
|
10
|
+
The "known of" stub's client half (keel PR 113, B16; keel #421 §7g), live in production since 2026-10-20 13:47.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- **`known_of?: true`** on `OwElementBase` (generated; `SCHEMA.md` says it too): present, and true, only on a
|
|
14
|
+
stub, an element a guest or player reaches only through its own Character's sheet, one step out. A stub
|
|
15
|
+
keeps `id`, `type`, `name`, `description`, `supertype`, `subtype`, `image_url`, `created_at`, `updated_at`
|
|
16
|
+
and `change_seq`; every other field reads unset (`""`, `null`, `[]`), `created_by`, `changed_by` and
|
|
17
|
+
`changed_via` are null, it has no extension fields, and its files are 404. For Lantern and Atlas, which
|
|
18
|
+
render stubs (Temper).
|
|
19
|
+
- **`isKnownOf(el)`**: true only for `known_of: true`; absent or anything else is a whole element.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- **A stub is never written**: `upsert`, `patch`, `create` and `bulk` throw a `TypeError` before sending a
|
|
23
|
+
body with `known_of: true` (`bulk` names the item, and sends none of the batch). Stripping the marker would
|
|
24
|
+
turn keel's 422 into a write that blanks the element for any key that may write it (an owner pushing a
|
|
25
|
+
player's copy). `known_of` joins the strip list, so any other value of it is never sent.
|
|
26
|
+
|
|
27
|
+
## [4.39.0] - 2026-10-20
|
|
28
|
+
|
|
29
|
+
The party link (keel #422 PR 2, keel PR 110), live in production since 2026-10-20 13:15.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
- The party link (keel #422 PR 2, keel PR 110; for Lantern's pick screen, Temper): one player link for a
|
|
33
|
+
table of players. `createWorldLink(worldId, { reader: 'player', maxUses, characters })`, sent as `max_uses`
|
|
34
|
+
and `characters`: 2 to 50 uses, each player picking one Character from the owner's list, in its order; no
|
|
35
|
+
list, each player names a fresh Character after themselves. A table takes no `character`. A link for one
|
|
36
|
+
sends what it sent before. `OwWorldLink` and `OwCreatedWorldLink` gain a table's `max_uses` and
|
|
37
|
+
`characters` (`{ id, name, taken }`); `uses` counts a table's seats. `OwJoinPreview` gains a table's
|
|
38
|
+
`max_uses`, `uses_left`, `name_required` and `characters` (`{ id, name, image_url, taken }`).
|
|
39
|
+
`redeemJoin(code, { character })` sends the pick; with `name_required`, `name` alone. A pick a live seat
|
|
40
|
+
already plays is 422 `character_taken` (`err.isCharacterTaken`); a pick off the list, hidden or deleted
|
|
41
|
+
since the link was made, or missing, is 422 `invalid_request` with param `character`
|
|
42
|
+
(`err.isCharacterInvalid`, true for that param only); a world with its 50 players is 422 `world_full` (`err.isWorldFull`, its own code at my ask, Skeld h29 #8394); the last place
|
|
43
|
+
lost to another player is the one 404 (`err.isNotFound`).
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
- Repinned to schema-dist v0.32.1-dist.27: only `example/world-export.json` moved (its `schema_version` now 00.32.01, Skeld h29 #8455); no schema file moved, so the generated files change only their source lines.
|
|
47
|
+
|
|
8
48
|
## [4.38.0] - 2026-10-20
|
|
9
49
|
|
|
10
50
|
Schema 00.32.01 (the Captain's word, h55 #8395): repinned to schema-dist v0.32.1-dist.26.
|
package/SCHEMA.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# OnlyWorlds Schema Reference
|
|
2
2
|
|
|
3
|
-
**Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.32.1-dist.
|
|
3
|
+
**Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.32.1-dist.27** — canonical schema **00.32.01**, published 2026-10-20.
|
|
4
4
|
|
|
5
5
|
GENERATED from the canonical schema YAML — do not hand-edit (regenerate: `python codegen/generate_types.py`).
|
|
6
6
|
Written for both humans and AI agents reading this package locally.
|
|
7
7
|
|
|
8
8
|
**The shape rules** (v2 wire dialect): every element carries `id` (UUID), `name`, optional
|
|
9
9
|
`description`/`supertype`/`subtype`/`image_url`, server-managed `type`/`created_at`/`updated_at`/`change_seq`/`created_by`,
|
|
10
|
+
`known_of: true` only on a stub (an element a guest knows of through its Character's sheet:
|
|
11
|
+
its other fields read unset and are not values; never write a stub back),
|
|
10
12
|
and namespaced extension fields (`x_*` etc.) returned verbatim. Link fields use ONE bare
|
|
11
13
|
name in both read and write (no `_ids` suffix). Single links are `UUID | null`; multi links
|
|
12
14
|
are `UUID[]`. **Links are owned one-way**: the type listed below owns the field (e.g.
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* pass-through fields (atlas_* / shadow_* / x_*) returned verbatim by the server.
|
|
3
3
|
* Derived from base_properties.yaml: `World` is dropped (the API rejects it in
|
|
4
4
|
* bodies -- the key determines the world) and the seven server-managed fields are
|
|
5
|
-
* added, since they ride every wire body and appear in no element YAML
|
|
5
|
+
* added, since they ride every wire body and appear in no element YAML; `known_of`
|
|
6
|
+
* rides only a stub. */
|
|
6
7
|
interface OwElementBase {
|
|
7
8
|
/** Element type slug (server-managed, read-only). */
|
|
8
9
|
type: string;
|
|
@@ -30,6 +31,8 @@ interface OwElementBase {
|
|
|
30
31
|
changed_by?: string | null;
|
|
31
32
|
/** The door of the last write (server-managed, read-only): `seat` (an agent seat), `mcp`, `declared` (a client that sent X-OW-Agent), then `api`, `v1`, `sync`, or `server` (keel's own writes). The first three are agent-made. Null for anything last changed before writes recorded it. */
|
|
32
33
|
changed_via?: 'seat' | 'mcp' | 'declared' | 'api' | 'v1' | 'sync' | 'server' | null;
|
|
34
|
+
/** Present, and true, only on a stub (server-managed, read-only): an element a guest or player reaches only through its own Character's sheet. A stub keeps id, type, name, description, supertype, subtype, image_url, created_at, updated_at and change_seq; every other field reads unset ("", null, []), created_by/changed_by/changed_via null, no extension fields, and its files are 404. Its empties are not values and not a deletion: never write a stub back. Absent: the element is whole. See isKnownOf(). */
|
|
35
|
+
known_of?: true;
|
|
33
36
|
/** Namespaced extension fields (atlas_* / shadow_* / x_*), returned verbatim. */
|
|
34
37
|
[ext: string]: unknown;
|
|
35
38
|
}
|
|
@@ -1955,6 +1958,19 @@ type OwWriteDoor = NonNullable<OwElementBase['changed_via']>;
|
|
|
1955
1958
|
declare const AGENT_DOORS: readonly OwWriteDoor[];
|
|
1956
1959
|
/** Whether a write came through an agent's door (`changed_via` or `deleted_via`); false for null. */
|
|
1957
1960
|
declare function isAgentDoor(door: OwWriteDoor | null | undefined): boolean;
|
|
1961
|
+
/**
|
|
1962
|
+
* Whether an element body is a stub the reader only knows of (keel PR 113, B16; keel #421
|
|
1963
|
+
* §7g): a guest or player reaches it only through its own Character's sheet, one step out.
|
|
1964
|
+
* A stub keeps `id`, `type`, `name`, `description`, `supertype`, `subtype`, `image_url`,
|
|
1965
|
+
* `created_at`, `updated_at` and `change_seq`; every other field reads unset (`""`, `null`,
|
|
1966
|
+
* `[]`), `created_by`, `changed_by` and `changed_via` are null, it carries no extension
|
|
1967
|
+
* fields, and its files answer 404. Those empties are not the element's values and not a
|
|
1968
|
+
* deletion: never merge them over a whole copy, and never write a stub back (this client
|
|
1969
|
+
* refuses to). True only for `known_of: true`; absent or anything else is a whole element.
|
|
1970
|
+
*/
|
|
1971
|
+
declare function isKnownOf(element: {
|
|
1972
|
+
known_of?: unknown;
|
|
1973
|
+
} | null | undefined): boolean;
|
|
1958
1974
|
/**
|
|
1959
1975
|
* /changes response. Wire shape verified in keel source (core/changes.py) and
|
|
1960
1976
|
* pinned here: {cursor, changes, has_more, head}.
|
|
@@ -2254,6 +2270,19 @@ interface OwJoinPreview {
|
|
|
2254
2270
|
with_character: boolean | null;
|
|
2255
2271
|
/** ISO 8601, UTC. */
|
|
2256
2272
|
expires_at: string;
|
|
2273
|
+
/** A table only (a player link that works 2 to 50 times, keel #422 PR 2): how many times it works. Absent on a link for one. */
|
|
2274
|
+
max_uses?: number;
|
|
2275
|
+
/** A table only: how many places are left. */
|
|
2276
|
+
uses_left?: number;
|
|
2277
|
+
/** A table only: true when the owner listed no Characters, so each player sends a `name` to redeemJoin and gets a fresh Character with it. */
|
|
2278
|
+
name_required?: boolean;
|
|
2279
|
+
/** A table only: the Characters a player may pick, in the owner's order; empty when `name_required`. `taken` while a live seat in the world plays it (a pick screen keeps the order and puts taken ones last). A Character hidden or deleted since the link was made is left out. */
|
|
2280
|
+
characters?: Array<{
|
|
2281
|
+
id: string;
|
|
2282
|
+
name: string;
|
|
2283
|
+
image_url: string | null;
|
|
2284
|
+
taken: boolean;
|
|
2285
|
+
}>;
|
|
2257
2286
|
[k: string]: unknown;
|
|
2258
2287
|
}
|
|
2259
2288
|
/** One of a world's invite links, as GET /account/worlds/{id}/links lists it (keel C1, 48c10d4). */
|
|
@@ -2275,16 +2304,25 @@ interface OwWorldLink {
|
|
|
2275
2304
|
created_at: string;
|
|
2276
2305
|
/** ISO 8601, UTC. */
|
|
2277
2306
|
expires_at: string;
|
|
2278
|
-
/** 0 or 1
|
|
2307
|
+
/** 0 or 1 for a link for one; a table's seats made, removed ones included (keel #422 PR 2). */
|
|
2279
2308
|
uses: number;
|
|
2309
|
+
/** A table is `pending` while `uses < max_uses` (and neither revoked nor expired), `used` once full. */
|
|
2280
2310
|
status: 'pending' | 'used' | 'revoked' | 'expired';
|
|
2281
2311
|
/** Whether the link shows the world's name and picture when it is pasted into a chat (keel #422): then the link is `/join/<world_id>#<code>`, else `/join#<code>`. Never on an agent link. */
|
|
2282
2312
|
preview?: boolean;
|
|
2283
|
-
/** A player link only: the Character the player reads as; null while a link for a fresh Character is unused. `name` is null if that Character was deleted (the redeem then makes a fresh one). */
|
|
2313
|
+
/** A player link only: the Character the player reads as; null while a link for a fresh Character is unused, and always null on a table. `name` is null if that Character was deleted (the redeem then makes a fresh one). */
|
|
2284
2314
|
character?: {
|
|
2285
2315
|
id: string;
|
|
2286
2316
|
name: string | null;
|
|
2287
2317
|
} | null;
|
|
2318
|
+
/** A table only (a player link that works 2 to 50 times, keel #422 PR 2): how many times it works. Absent on a link for one. */
|
|
2319
|
+
max_uses?: number;
|
|
2320
|
+
/** A table only: the Characters its players may pick, in the owner's order; empty when each player gets a fresh Character named after them. `taken`: a live seat in the world plays it. `name` is null if the Character was deleted. */
|
|
2321
|
+
characters?: Array<{
|
|
2322
|
+
id: string;
|
|
2323
|
+
name: string | null;
|
|
2324
|
+
taken: boolean;
|
|
2325
|
+
}>;
|
|
2288
2326
|
[k: string]: unknown;
|
|
2289
2327
|
}
|
|
2290
2328
|
/** POST /account/worlds/{id}/links: the new link, with its code. The code is in this answer only: keel keeps a hash. */
|
|
@@ -2715,6 +2753,28 @@ declare class OwApiError extends Error {
|
|
|
2715
2753
|
get isPreconditionFailed(): boolean;
|
|
2716
2754
|
/** 404 `not_found`: no such element or route, or a join code that is unknown, used, revoked or expired. */
|
|
2717
2755
|
get isNotFound(): boolean;
|
|
2756
|
+
/**
|
|
2757
|
+
* redeemJoin on a table (keel #422 PR 2): the picked Character is one a live seat in the
|
|
2758
|
+
* world already plays (422 `character_taken`, `param` character). Pick another from a fresh
|
|
2759
|
+
* previewJoin, whose `characters` mark each `taken`. The code is not spent.
|
|
2760
|
+
*/
|
|
2761
|
+
get isCharacterTaken(): boolean;
|
|
2762
|
+
/**
|
|
2763
|
+
* The `character` sent was refused (422 `invalid_request`, `param` character). On redeemJoin
|
|
2764
|
+
* at a table (keel #422 PR 2): the pick is off the link's list, hidden or deleted since the
|
|
2765
|
+
* link was made, or missing, or sent to a table with no list (send `name` instead); one
|
|
2766
|
+
* answer for all, so read previewJoin again and pick from its `characters`. The code is not
|
|
2767
|
+
* spent. On createWorldLink: a `character` keel refused (not a Character of the world, a
|
|
2768
|
+
* hidden one, or any `character` on a table). Never true for another param's 422, nor for
|
|
2769
|
+
* `character_taken` (see isCharacterTaken).
|
|
2770
|
+
*/
|
|
2771
|
+
get isCharacterInvalid(): boolean;
|
|
2772
|
+
/**
|
|
2773
|
+
* redeemJoin (keel #422 PR 2): the world already has its 50 live players (422 `world_full`),
|
|
2774
|
+
* at any player link, a table's or a link for one's. Nothing is spent; a place frees when the
|
|
2775
|
+
* owner removes a player.
|
|
2776
|
+
*/
|
|
2777
|
+
get isWorldFull(): boolean;
|
|
2718
2778
|
/** acceptJoin: the account is already a member of that world (409 `already_member`). The code is not spent. */
|
|
2719
2779
|
get isAlreadyMember(): boolean;
|
|
2720
2780
|
/** acceptJoin: the account has no PIN yet, and a member writes with their own (409 `pin_required`). The code is not spent. */
|
|
@@ -2897,7 +2957,11 @@ declare class OwV2Client {
|
|
|
2897
2957
|
create(type: ElementType | string, element: OwElement | Record<string, unknown>, opts?: {
|
|
2898
2958
|
idempotencyKey?: string;
|
|
2899
2959
|
}): Promise<OwElement>;
|
|
2900
|
-
/**
|
|
2960
|
+
/**
|
|
2961
|
+
* PUT /{type}/{id}/ -- upsert-by-client-id. The local-first write primitive. A known-of
|
|
2962
|
+
* stub (`known_of: true`, see isKnownOf) is a TypeError before sending, here and on every
|
|
2963
|
+
* element write: a PUT of one would blank every field it does not keep.
|
|
2964
|
+
*/
|
|
2901
2965
|
upsert(type: ElementType | string, id: string, element: OwElement | Record<string, unknown>): Promise<OwElement>;
|
|
2902
2966
|
/**
|
|
2903
2967
|
* PATCH /{type}/{id}/ -- partial update. DESTRUCTIVE on sent fields: arrays
|
|
@@ -3155,7 +3219,9 @@ declare class OwV2Client {
|
|
|
3155
3219
|
* which world, in what role, and `reader` (`person`: accept it with acceptJoin;
|
|
3156
3220
|
* `agent`: an AI agent redeems it at POST /join). Sends no credential, whatever key
|
|
3157
3221
|
* this client holds. Every bad code (unknown, used, revoked, expired) is the same
|
|
3158
|
-
* 404 `not_found` (`err.isNotFound`). `code` is the part of the link after `#`.
|
|
3222
|
+
* 404 `not_found` (`err.isNotFound`). `code` is the part of the link after `#`. A table
|
|
3223
|
+
* (keel #422 PR 2) adds `max_uses`, `uses_left`, `name_required` and `characters`, the
|
|
3224
|
+
* pick screen's list; a link for one answers without them.
|
|
3159
3225
|
*/
|
|
3160
3226
|
previewJoin(code: string): Promise<OwJoinPreview>;
|
|
3161
3227
|
/**
|
|
@@ -3168,10 +3234,22 @@ declare class OwV2Client {
|
|
|
3168
3234
|
* Character's name or "Player" when left out) and `agentName` (an agent's, required for an
|
|
3169
3235
|
* agent code). Every bad code is the same 404 `not_found`; a person's code is redeemed with
|
|
3170
3236
|
* acceptJoin instead.
|
|
3237
|
+
*
|
|
3238
|
+
* A table (a player code whose preview carries `max_uses`, keel #422 PR 2) seats one player
|
|
3239
|
+
* per redeem, until `uses_left` is 0. With a list, `character` is the player's pick, the `id`
|
|
3240
|
+
* of one of the preview's `characters` not `taken`: a Character a live seat already plays is
|
|
3241
|
+
* 422 `character_taken` (`err.isCharacterTaken`; pick another), one off the list, hidden or
|
|
3242
|
+
* deleted since, or none sent, is 422 `invalid_request`, param `character`
|
|
3243
|
+
* (`err.isCharacterInvalid`; read the preview again). With no list
|
|
3244
|
+
* (`name_required`), send `name` and no `character`: the player's fresh Character takes the
|
|
3245
|
+
* name (missing: 422, param `name`). A world with its 50 players is 422 `invalid_request`;
|
|
3246
|
+
* the last place taken by someone else first is the one 404. A refusal spends nothing. A link
|
|
3247
|
+
* for one ignores `character`.
|
|
3171
3248
|
*/
|
|
3172
3249
|
redeemJoin(code: string, opts?: {
|
|
3173
3250
|
name?: string;
|
|
3174
3251
|
agentName?: string;
|
|
3252
|
+
character?: string;
|
|
3175
3253
|
}): Promise<OwJoined>;
|
|
3176
3254
|
/**
|
|
3177
3255
|
* Sign in with an email address (or a username) and password, and get a new account token
|
|
@@ -3218,7 +3296,14 @@ declare class OwV2Client {
|
|
|
3218
3296
|
* whoever opens the link first reads as it, until removed. `preview` (person and player links,
|
|
3219
3297
|
* keel #422) to false: true puts the world's id in the link's path, so a chat that unfurls it
|
|
3220
3298
|
* shows the world's name and picture (the code stays after `#`); true on an agent link is
|
|
3221
|
-
* 422, param `preview`.
|
|
3299
|
+
* 422, param `preview`. `maxUses` (player links only, keel #422 PR 2) to 1, a link for one:
|
|
3300
|
+
* 2 to 50 makes a table, one link that seats that many players, each picking one of
|
|
3301
|
+
* `characters` (Character ids of the world, in the order a pick screen shows them; a hidden
|
|
3302
|
+
* one is 422, param `characters`). `characters` empty or left out: each player names a fresh
|
|
3303
|
+
* Character after themselves. A table takes no `character`, not even `new` (422, param
|
|
3304
|
+
* `character`), and `characters` on a link for one is 422, even empty. A table counts once
|
|
3305
|
+
* against the 50 pending invites; its seats count against the world's 50 players as each is
|
|
3306
|
+
* made, so a full world refuses the pick, never the link. 201 with the code, shown in this
|
|
3222
3307
|
* answer only. Owner only: anyone else, and a world that doesn't exist, gets 404
|
|
3223
3308
|
* `not_found` (`err.isNotFound`). A world key is a TypeError before anything is sent.
|
|
3224
3309
|
*/
|
|
@@ -3230,6 +3315,8 @@ declare class OwV2Client {
|
|
|
3230
3315
|
withCharacter?: boolean;
|
|
3231
3316
|
character?: string;
|
|
3232
3317
|
preview?: boolean;
|
|
3318
|
+
maxUses?: number;
|
|
3319
|
+
characters?: string[];
|
|
3233
3320
|
}): Promise<OwCreatedWorldLink>;
|
|
3234
3321
|
/**
|
|
3235
3322
|
* GET /account/worlds/{worldId}/links -- the world's invite links, without their codes:
|
|
@@ -4316,4 +4403,4 @@ declare class TokenResource {
|
|
|
4316
4403
|
getEncryptionInfo(): Promise<EncryptionInfo>;
|
|
4317
4404
|
}
|
|
4318
4405
|
|
|
4319
|
-
export { AGENT_DOORS, ASK_LIMITS, type AccessKeyResponse, CALENDAR_FIELD, CALENDAR_SUPERTYPE, type CalendarConfig, type CalendarEra, type CalendarIntercalary, type CalendarMonths, type CalendarWeek, ELEMENT_FAMILIES, ELEMENT_ICONS, ELEMENT_LABELS, ELEMENT_SECTIONS, ELEMENT_TYPES, type ElementFamily, type ElementType, type EncryptionInfo, type EraDomain, FAMILY_COLORS, FAMILY_ORDER, FIELD_ACRONYMS, FIELD_SCHEMA, FILE_EXTENSIONS, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, type OwAgentJoined, type OwAllowance, OwApiError, type OwAskAnswer, type OwAskContext, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwCalendarElement, type OwChange, type OwChangeDelete, type OwChangeUpsert, type OwChangesPage, type OwClientConfig, type OwCreatedWorldLink, type OwDeleteReason, type OwElement, type OwElementBase, type OwErrorBody, type OwFileAddedBy, type OwFileDownload, type OwFileKind, type OwFileRow, type OwFileTicket, type OwJoinPreview, type OwJoined, type OwJoinedMembership, type OwKeyKind, type OwLinkEdit, type OwLookupElement, type OwLookupHit, type OwLookupLink, type OwLookupOptions, type OwLookupReason, type OwMe, type OwMediaTicket, type OwMember, type OwMemberRole, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, type OwPlayerJoined, OwPreconditionFailedError, type OwPreparedPhoto, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwResyncReason, type OwSeat, type OwSeatCreated, OwSignInError, type OwSignInReason, type OwSignedIn, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, type OwUploadedFile, type OwUploadedImage, OwV2Client, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldFileRow, type OwWorldFiles, type OwWorldIndex, type OwWorldLink, type OwWorldMeta, type OwWriteDoor, PHOTO_MAX_BYTES, PHOTO_TYPES, type ParseError, type ParseOptions, type ParseResult, type RevokeAllSessionsResponse, type RevokeSessionResponse, SPATIAL_TYPES, type SectionInfo, type StepBreakdown, type TokenConsumeParams, type TokenConsumeResponse, TokenResource, type TokenStatus, type TokenTransport, WORLD_FILE_MAX_BYTES, WORLD_FILE_MAX_ENTRIES, type WorldCalendar, absYearForEraYear, absoluteYear, approxYearLength, breakdownStep, buildAskContext, buildWorldIndex, detectKeyKind, displayYear, elementColor, eraForStep, errorFromResponse, familyOf, fieldLabel, fileKindOf, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, isAgentDoor, isDemoKey, isLeapYear, isParseError, kindCanWrite, lookupWorld, monthStartSteps, parseDate, parseErrorEnvelope, pinExpectation, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
|
|
4406
|
+
export { AGENT_DOORS, ASK_LIMITS, type AccessKeyResponse, CALENDAR_FIELD, CALENDAR_SUPERTYPE, type CalendarConfig, type CalendarEra, type CalendarIntercalary, type CalendarMonths, type CalendarWeek, ELEMENT_FAMILIES, ELEMENT_ICONS, ELEMENT_LABELS, ELEMENT_SECTIONS, ELEMENT_TYPES, type ElementFamily, type ElementType, type EncryptionInfo, type EraDomain, FAMILY_COLORS, FAMILY_ORDER, FIELD_ACRONYMS, FIELD_SCHEMA, FILE_EXTENSIONS, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, type OwAgentJoined, type OwAllowance, OwApiError, type OwAskAnswer, type OwAskContext, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwCalendarElement, type OwChange, type OwChangeDelete, type OwChangeUpsert, type OwChangesPage, type OwClientConfig, type OwCreatedWorldLink, type OwDeleteReason, type OwElement, type OwElementBase, type OwErrorBody, type OwFileAddedBy, type OwFileDownload, type OwFileKind, type OwFileRow, type OwFileTicket, type OwJoinPreview, type OwJoined, type OwJoinedMembership, type OwKeyKind, type OwLinkEdit, type OwLookupElement, type OwLookupHit, type OwLookupLink, type OwLookupOptions, type OwLookupReason, type OwMe, type OwMediaTicket, type OwMember, type OwMemberRole, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, type OwPlayerJoined, OwPreconditionFailedError, type OwPreparedPhoto, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwResyncReason, type OwSeat, type OwSeatCreated, OwSignInError, type OwSignInReason, type OwSignedIn, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, type OwUploadedFile, type OwUploadedImage, OwV2Client, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldFileRow, type OwWorldFiles, type OwWorldIndex, type OwWorldLink, type OwWorldMeta, type OwWriteDoor, PHOTO_MAX_BYTES, PHOTO_TYPES, type ParseError, type ParseOptions, type ParseResult, type RevokeAllSessionsResponse, type RevokeSessionResponse, SPATIAL_TYPES, type SectionInfo, type StepBreakdown, type TokenConsumeParams, type TokenConsumeResponse, TokenResource, type TokenStatus, type TokenTransport, WORLD_FILE_MAX_BYTES, WORLD_FILE_MAX_ENTRIES, type WorldCalendar, absYearForEraYear, absoluteYear, approxYearLength, breakdownStep, buildAskContext, buildWorldIndex, detectKeyKind, displayYear, elementColor, eraForStep, errorFromResponse, familyOf, fieldLabel, fileKindOf, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, isAgentDoor, isDemoKey, isKnownOf, isLeapYear, isParseError, kindCanWrite, lookupWorld, monthStartSteps, parseDate, parseErrorEnvelope, pinExpectation, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
|
package/dist/index.js
CHANGED
|
@@ -173,6 +173,34 @@ var OwApiError = class extends Error {
|
|
|
173
173
|
get isNotFound() {
|
|
174
174
|
return this.status === 404 && this.code === "not_found";
|
|
175
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* redeemJoin on a table (keel #422 PR 2): the picked Character is one a live seat in the
|
|
178
|
+
* world already plays (422 `character_taken`, `param` character). Pick another from a fresh
|
|
179
|
+
* previewJoin, whose `characters` mark each `taken`. The code is not spent.
|
|
180
|
+
*/
|
|
181
|
+
get isCharacterTaken() {
|
|
182
|
+
return this.status === 422 && this.code === "character_taken";
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The `character` sent was refused (422 `invalid_request`, `param` character). On redeemJoin
|
|
186
|
+
* at a table (keel #422 PR 2): the pick is off the link's list, hidden or deleted since the
|
|
187
|
+
* link was made, or missing, or sent to a table with no list (send `name` instead); one
|
|
188
|
+
* answer for all, so read previewJoin again and pick from its `characters`. The code is not
|
|
189
|
+
* spent. On createWorldLink: a `character` keel refused (not a Character of the world, a
|
|
190
|
+
* hidden one, or any `character` on a table). Never true for another param's 422, nor for
|
|
191
|
+
* `character_taken` (see isCharacterTaken).
|
|
192
|
+
*/
|
|
193
|
+
get isCharacterInvalid() {
|
|
194
|
+
return this.status === 422 && this.code === "invalid_request" && this.param === "character";
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* redeemJoin (keel #422 PR 2): the world already has its 50 live players (422 `world_full`),
|
|
198
|
+
* at any player link, a table's or a link for one's. Nothing is spent; a place frees when the
|
|
199
|
+
* owner removes a player.
|
|
200
|
+
*/
|
|
201
|
+
get isWorldFull() {
|
|
202
|
+
return this.status === 422 && this.code === "world_full";
|
|
203
|
+
}
|
|
176
204
|
/** acceptJoin: the account is already a member of that world (409 `already_member`). The code is not spent. */
|
|
177
205
|
get isAlreadyMember() {
|
|
178
206
|
return this.status === 409 && this.code === "already_member";
|
|
@@ -401,6 +429,7 @@ var OwV2Client = class {
|
|
|
401
429
|
* `null` are accepted and stored as `''` (nameless Markers exist).
|
|
402
430
|
*/
|
|
403
431
|
async create(type, element, opts = {}) {
|
|
432
|
+
refuseKnownOf(element, "create");
|
|
404
433
|
const body = sanitizePayload(element);
|
|
405
434
|
if (body.id === void 0 || body.id === null || body.id === "") {
|
|
406
435
|
body.id = opts.idempotencyKey ? keyedId(opts.idempotencyKey, 0) : mintUuid();
|
|
@@ -411,8 +440,13 @@ var OwV2Client = class {
|
|
|
411
440
|
idempotencyKey: opts.idempotencyKey
|
|
412
441
|
});
|
|
413
442
|
}
|
|
414
|
-
/**
|
|
443
|
+
/**
|
|
444
|
+
* PUT /{type}/{id}/ -- upsert-by-client-id. The local-first write primitive. A known-of
|
|
445
|
+
* stub (`known_of: true`, see isKnownOf) is a TypeError before sending, here and on every
|
|
446
|
+
* element write: a PUT of one would blank every field it does not keep.
|
|
447
|
+
*/
|
|
415
448
|
async upsert(type, id, element) {
|
|
449
|
+
refuseKnownOf(element, "upsert");
|
|
416
450
|
return this.request("PUT", `/${type}/${id}/`, { write: true, body: sanitizePayload(element) });
|
|
417
451
|
}
|
|
418
452
|
/**
|
|
@@ -426,6 +460,7 @@ var OwV2Client = class {
|
|
|
426
460
|
* it for today's unconditional write.
|
|
427
461
|
*/
|
|
428
462
|
async patch(type, id, partial, opts = {}) {
|
|
463
|
+
refuseKnownOf(partial, "patch");
|
|
429
464
|
return this.request("PATCH", `/${type}/${id}/`, { write: true, body: sanitizePayload(partial), ifMatch: opts.ifMatch });
|
|
430
465
|
}
|
|
431
466
|
/**
|
|
@@ -464,6 +499,7 @@ var OwV2Client = class {
|
|
|
464
499
|
* fresh UUIDv7. Ids you supply are kept.
|
|
465
500
|
*/
|
|
466
501
|
async bulk(items, opts = {}) {
|
|
502
|
+
items.forEach((it, index) => refuseKnownOf(it.element, `bulk: items[${index}]`));
|
|
467
503
|
const body = {
|
|
468
504
|
items: items.map((it, index) => {
|
|
469
505
|
const element = sanitizePayload(it.element);
|
|
@@ -772,7 +808,9 @@ var OwV2Client = class {
|
|
|
772
808
|
* which world, in what role, and `reader` (`person`: accept it with acceptJoin;
|
|
773
809
|
* `agent`: an AI agent redeems it at POST /join). Sends no credential, whatever key
|
|
774
810
|
* this client holds. Every bad code (unknown, used, revoked, expired) is the same
|
|
775
|
-
* 404 `not_found` (`err.isNotFound`). `code` is the part of the link after `#`.
|
|
811
|
+
* 404 `not_found` (`err.isNotFound`). `code` is the part of the link after `#`. A table
|
|
812
|
+
* (keel #422 PR 2) adds `max_uses`, `uses_left`, `name_required` and `characters`, the
|
|
813
|
+
* pick screen's list; a link for one answers without them.
|
|
776
814
|
*/
|
|
777
815
|
async previewJoin(code) {
|
|
778
816
|
return this.request("POST", "/join/preview", { auth: false, body: { code } });
|
|
@@ -787,11 +825,23 @@ var OwV2Client = class {
|
|
|
787
825
|
* Character's name or "Player" when left out) and `agentName` (an agent's, required for an
|
|
788
826
|
* agent code). Every bad code is the same 404 `not_found`; a person's code is redeemed with
|
|
789
827
|
* acceptJoin instead.
|
|
828
|
+
*
|
|
829
|
+
* A table (a player code whose preview carries `max_uses`, keel #422 PR 2) seats one player
|
|
830
|
+
* per redeem, until `uses_left` is 0. With a list, `character` is the player's pick, the `id`
|
|
831
|
+
* of one of the preview's `characters` not `taken`: a Character a live seat already plays is
|
|
832
|
+
* 422 `character_taken` (`err.isCharacterTaken`; pick another), one off the list, hidden or
|
|
833
|
+
* deleted since, or none sent, is 422 `invalid_request`, param `character`
|
|
834
|
+
* (`err.isCharacterInvalid`; read the preview again). With no list
|
|
835
|
+
* (`name_required`), send `name` and no `character`: the player's fresh Character takes the
|
|
836
|
+
* name (missing: 422, param `name`). A world with its 50 players is 422 `invalid_request`;
|
|
837
|
+
* the last place taken by someone else first is the one 404. A refusal spends nothing. A link
|
|
838
|
+
* for one ignores `character`.
|
|
790
839
|
*/
|
|
791
840
|
async redeemJoin(code, opts = {}) {
|
|
792
841
|
const body = { code };
|
|
793
842
|
if (opts.name !== void 0) body.name = opts.name;
|
|
794
843
|
if (opts.agentName !== void 0) body.agent_name = opts.agentName;
|
|
844
|
+
if (opts.character !== void 0) body.character = opts.character;
|
|
795
845
|
return this.request("POST", "/join", { auth: false, body });
|
|
796
846
|
}
|
|
797
847
|
// -- Signing in with a password (keel #211) --------------------------------
|
|
@@ -943,7 +993,14 @@ var OwV2Client = class {
|
|
|
943
993
|
* whoever opens the link first reads as it, until removed. `preview` (person and player links,
|
|
944
994
|
* keel #422) to false: true puts the world's id in the link's path, so a chat that unfurls it
|
|
945
995
|
* shows the world's name and picture (the code stays after `#`); true on an agent link is
|
|
946
|
-
* 422, param `preview`.
|
|
996
|
+
* 422, param `preview`. `maxUses` (player links only, keel #422 PR 2) to 1, a link for one:
|
|
997
|
+
* 2 to 50 makes a table, one link that seats that many players, each picking one of
|
|
998
|
+
* `characters` (Character ids of the world, in the order a pick screen shows them; a hidden
|
|
999
|
+
* one is 422, param `characters`). `characters` empty or left out: each player names a fresh
|
|
1000
|
+
* Character after themselves. A table takes no `character`, not even `new` (422, param
|
|
1001
|
+
* `character`), and `characters` on a link for one is 422, even empty. A table counts once
|
|
1002
|
+
* against the 50 pending invites; its seats count against the world's 50 players as each is
|
|
1003
|
+
* made, so a full world refuses the pick, never the link. 201 with the code, shown in this
|
|
947
1004
|
* answer only. Owner only: anyone else, and a world that doesn't exist, gets 404
|
|
948
1005
|
* `not_found` (`err.isNotFound`). A world key is a TypeError before anything is sent.
|
|
949
1006
|
*/
|
|
@@ -958,6 +1015,8 @@ var OwV2Client = class {
|
|
|
958
1015
|
if (opts.withCharacter !== void 0) body.with_character = opts.withCharacter;
|
|
959
1016
|
if (opts.character !== void 0) body.character = opts.character;
|
|
960
1017
|
if (opts.preview !== void 0) body.preview = opts.preview;
|
|
1018
|
+
if (opts.maxUses !== void 0) body.max_uses = opts.maxUses;
|
|
1019
|
+
if (opts.characters !== void 0) body.characters = opts.characters;
|
|
961
1020
|
return this.request("POST", `/account/worlds/${encodeURIComponent(worldId)}/links`, { body });
|
|
962
1021
|
}
|
|
963
1022
|
/**
|
|
@@ -1140,13 +1199,20 @@ var OwV2Client = class {
|
|
|
1140
1199
|
return parsed;
|
|
1141
1200
|
}
|
|
1142
1201
|
};
|
|
1143
|
-
var READ_ONLY_FIELDS = ["world", "type", "created_at", "updated_at", "change_seq"];
|
|
1202
|
+
var READ_ONLY_FIELDS = ["world", "type", "created_at", "updated_at", "change_seq", "known_of"];
|
|
1144
1203
|
function sanitizePayload(payload) {
|
|
1145
1204
|
if (!payload || typeof payload !== "object") return payload;
|
|
1146
1205
|
const rest = { ...payload };
|
|
1147
1206
|
for (const field of READ_ONLY_FIELDS) delete rest[field];
|
|
1148
1207
|
return rest;
|
|
1149
1208
|
}
|
|
1209
|
+
function refuseKnownOf(payload, where) {
|
|
1210
|
+
if (payload && typeof payload === "object" && payload.known_of === true) {
|
|
1211
|
+
throw new TypeError(
|
|
1212
|
+
`${where}: this body is a known-of stub (known_of: true), not the element: its empty fields are not its values, and writing it would blank them. Write from a whole copy, or send only the fields you mean to change.`
|
|
1213
|
+
);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1150
1216
|
async function endAuthSession(fetchImpl, auth, session) {
|
|
1151
1217
|
const abort = new AbortController();
|
|
1152
1218
|
const timer = setTimeout(() => abort.abort(), 5e3);
|
|
@@ -2021,6 +2087,9 @@ var AGENT_DOORS = ["seat", "mcp", "declared"];
|
|
|
2021
2087
|
function isAgentDoor(door) {
|
|
2022
2088
|
return door != null && AGENT_DOORS.includes(door);
|
|
2023
2089
|
}
|
|
2090
|
+
function isKnownOf(element) {
|
|
2091
|
+
return element != null && element.known_of === true;
|
|
2092
|
+
}
|
|
2024
2093
|
|
|
2025
2094
|
// src/v2/palette.ts
|
|
2026
2095
|
var FAMILY_COLORS = {
|
|
@@ -3516,6 +3585,7 @@ export {
|
|
|
3516
3585
|
getElementLabel,
|
|
3517
3586
|
isAgentDoor,
|
|
3518
3587
|
isDemoKey,
|
|
3588
|
+
isKnownOf,
|
|
3519
3589
|
isLeapYear,
|
|
3520
3590
|
isParseError,
|
|
3521
3591
|
kindCanWrite,
|