@onlyworlds/sdk 4.64.0 → 4.66.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
@@ -73,6 +73,10 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
73
73
  tokenName })` (or `username`) mints an `ow_a_` account token named for the device and ends
74
74
  the sign-in session; only the token comes back. Refusals: `OwSignInError` with `reason`
75
75
  (`invalid_credentials`, `email_unverified`, `rate_limited`, `offline`, `mint_failed`, `failed`).
76
+ - A new world (since 4.66.0, account token): `account.createAccountWorld({ name, pin?, keyName?,
77
+ source?, producer? })` makes it with one write key, returned once in `key`. `pin` only while
78
+ the account has none (it becomes the account PIN); either mistake is a 422 with
79
+ `err.param === 'pin'`, so send without it first and again with it on that 422.
76
80
  - Invite links (since 4.12.0): `previewJoin(code)` (no credential sent) shows who invites, to
77
81
  which world, in what role; `acceptJoin(code)` with an `ow_a_` account token joins. Bad code:
78
82
  `err.isNotFound`; `err.isAlreadyMember`, `err.isPinRequired` for the two 409s.
@@ -126,7 +130,11 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
126
130
  co-builder decides: `acceptProposal(type, id, pid)` (the write is theirs; 409 `stale_proposal`,
127
131
  an `OwStaleProposalError` with `conflicts` and `current`, when a proposed field moved since),
128
132
  `declineProposal(type, id, pid, { reason? })`; the proposer may `withdrawProposal`. Lists:
129
- `listProposals(type, id)`, `worldProposals({ state?, element? })`. When the world's
133
+ `listProposals(type, id)`, `worldProposals({ state?, element? })`; the world's queue (since
134
+ 4.66.0, keel #565) also lists each new element written as proposed (`kind: 'new_element'`
135
+ beside `kind: 'proposal'`), which a keeper settles with `reviewNewElement(type, id, { decision:
136
+ 'accept' | 'decline', reason? })` (decline deletes it; 422 `err.isNotProposed` when unmarked).
137
+ A row's `fields` holds only what differs; `omitted` names what an upsert left empty. When the world's
130
138
  `agent_writes_proposed` is on, an agent seat's `patch`, `upsert` or `editLinks` on an existing
131
139
  element throws `OwProposedError` (status 202, `err.isProposed`, the row under `err.proposal`):
132
140
  the element did not change, so do not report it as changed. A `bulk` slot says `status: 202`
package/CHANGELOG.md CHANGED
@@ -5,6 +5,33 @@ earlier history lives in git log only.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [4.66.0] - 2026-10-23
9
+
10
+ ### Added
11
+
12
+ - **`createAccountWorld({ name, pin?, keyName?, source?, producer? })`** (account token): `POST /account/worlds` makes a world on the account with its one write key. Sent in keel's spelling, only the keys given (`keyName` as `key_name`, keel #363: 1 to 80 characters, trimmed, `null` for none; `source` and `producer`, keel #571: the folder format's provenance lines, each an object or `null`, kept on the World and served by `getWorld()` as `origin`). `pin` only while the account has no PIN (it becomes the account PIN); an account with one must leave it out. Either mistake is a 422 with `err.param === 'pin'` and nothing made, so a tool that cannot tell which account it holds sends without `pin` first and again with it on that 422, as Atlas's Make online does. Returns `OwCreatedAccountWorld`: the world's row as `listAccountWorlds` lists it, plus the full write key once in `key`. No Idempotency-Key (the document declares none), and neither `X-OW-Agent` nor `X-OW-Client` (it declares neither here). keel's document gives the 201 no schema, so the type is read from keel's handler. A world key is a `TypeError`, as is an unknown option or a missing `name`, before anything is sent. Atlas can retire its own `AccountClient.createWorld` for it.
13
+ - **The world's queue lists new elements written as proposed** (keel #565, live 2026-10-23): `worldProposals()` now returns `OwWorldProposalList`, whose rows are `OwWorldProposalRow`, told apart by `kind`: `OwProposal` (`kind: 'proposal'`) or `OwProposedNewElement` (`kind: 'new_element'`: an element carrying `x_review_proposed`, its `by`, `evidence` and `expires` the mark's words, `state` `open` or `lapsed`). One order, newest first by `created_at`; the cursor is opaque and goes back as it came (an old bare proposal id still reads). `listProposals` keeps `OwProposalList`: one element's proposals only.
14
+ - **`reviewNewElement(type, id, { decision, reason? })`**: `POST /{type}/{id}/review`, a keeper (the owner or a co-builder, with the PIN) settles a new element written as proposed. `accept` clears the mark and returns `{ element }`; `decline` deletes the element and returns `{ deleted }` (its id); the reason is answered back and kept nowhere. Sends `X-OW-Client`, as the document lists, and no `X-OW-Agent`. A `decision` other than `accept` or `decline`, or an unknown key, is a `TypeError` before sending. Type `OwReviewed`, options `OwReviewInput`.
15
+ - **`err.isNotProposed`**: 422 `not_proposed`, the element carries no mark to settle. `isProposedOnly` (403) also answers the seat the mark names.
16
+ - **`OwProposal.kind`** (`'proposal'`) and **`OwProposal.omitted`** (keel #565): a row's `fields` now holds only what differs from the element when proposed, and `omitted` names the fields an upsert left out that were not empty (each in `fields` at its empty value, so an accept empties it; `[]` for a patch, a link edit or `propose`). A propose with nothing new is a 422 with `param: 'fields'`; a seat's write that changes nothing under the world's switch answers 200 with the element and makes no row.
17
+
18
+ ### Changed
19
+
20
+ - `worldProposals()`'s answer type is `OwWorldProposalList` instead of `OwProposalList`: TypeScript code that reads a proposal's own keys (`fields`, `base`) off a queue row now narrows on `row.kind === 'proposal'` first. The wire changed under it on keel's side: the 4.65.0 type described rows keel no longer sends alone.
21
+ - Tests: the body sent for each `createAccountWorld` option alone and together, `null` included, an `undefined` option left out; the PIN dance's 422 surfacing with `err.param` `'pin'`, then the retry with it; the headers on the create (no agent, client or idempotency header); the queue's two kinds and its cursor; both review decisions, their headers and their refusals; the published types. Watched failing on 30 mutants, each restored byte for byte.
22
+
23
+ ## [4.65.0] - 2026-10-23
24
+
25
+ ### Fixed
26
+
27
+ - **`patchWorld` takes a `getWorld()` body back again** (keel #571, live 2026-10-23). keel's `GET /world` now serves `origin`, and a PATCH naming it is a 422 (an unknown key), so a world body read and sent back failed. `patchWorld` now leaves out `origin`, and `id` too: keel answers `id` with the same 422 (it is not a key PATCH takes), so the round trip 4.57.1's entry promised never held for a whole body. `owner_character` is still sent.
28
+
29
+ ### Added
30
+
31
+ - **`OwWorldMeta.origin?: OwWorldOrigin`**, read-only: where the world first came from, `{ source, producer }`, both keys always present, each the folder format's provenance line (spec 4.2) as the tool that made the world from a folder gave it, or `null`. Types `OwWorldOrigin`, `OwWorldSource` (`server`, `world`, `at`) and `OwWorldProducer` (`tool`, `version`, `input`), each open to keys keel keeps as given. The origin is written as the plain keys `source` and `producer`: `patchWorld({ source, producer })` sends them as given (an object, or `null` to clear).
32
+ - **The World's extension keys on `OwWorldMeta`**: `x_*`, `atlas_*` and `shadow_*`, typed `unknown` by template-literal index signatures (the first is `x_names`, the names profile `typeWord` reads). `patchWorld` sends every one as given, `null` included (keel removes the key); over keel's 64 KB cap on the whole store the answer is a 422 with `param: extensions`.
33
+ - Tests: a full `GET /world` body sent back sends neither `origin` nor `id` and keeps `x_names`; `source`, `producer` and a key of each extension prefix pass untouched, `null` included; the published types declare `origin` and its two keys, and the documented calls (`patchWorld(await getWorld())`, `patchWorld({ source, producer, x_names })`, `typeWord(world, …)`) compile against the built `.d.ts`. Watched failing on mutants: `origin` and `id` each out of the strip list, `origin` out of `OwWorldMeta`, and a narrowed `patchWorld` parameter.
34
+
8
35
  ## [4.64.0] - 2026-10-23
9
36
 
10
37
  ### Changed
package/README.md CHANGED
@@ -140,6 +140,14 @@ const account = new OwV2Client({ apiKey: token }); // keep the token; the passwo
140
140
 
141
141
  The SDK signs in, mints the token, and ends the sign-in session. A refusal is an `OwSignInError` whose `reason` is `invalid_credentials`, `email_unverified`, `rate_limited` (see `retryAfter`), `offline`, `mint_failed` or `failed`.
142
142
 
143
+ The account token lists the account's worlds (`listAccountWorlds()`), mints a key for one (`mintWorldKey(worldId, { scope, name })`), and makes a new one with its write key (since 4.66.0):
144
+
145
+ ```typescript
146
+ const world = await account.createAccountWorld({ name: 'Ostvik', keyName: 'My app' }); // world.key: shown once
147
+ ```
148
+
149
+ An account's first world sends `pin` too, which becomes the account PIN; an account that has one leaves it out. Either way the wrong choice is a 422 with `err.param === 'pin'` and nothing made, so send without it first and again with it on that 422. A tool that makes the world from a folder can pass the folder's `source` and `producer` lines; `getWorld()` serves them as `origin`.
150
+
143
151
  ## Invite links
144
152
 
145
153
  A world's owner can invite a person with a link (`https://www.onlyworlds.com/join#ow_j_…`). The code is the part after `#`:
@@ -184,6 +192,8 @@ To poll for news cheaply, `client.changesHead()` returns `{ head, cursor, epoch,
184
192
 
185
193
  Edits to the world itself (its name, calendar, `public_read`) don't appear in the change feed. Read `client.getWorld()` and compare `updated_at`.
186
194
 
195
+ `client.patchWorld(partial)` writes the world's own settings, and takes a `getWorld()` body back: the keys keel does not take (`id`, `origin`, `slug`, `public_page` and the owner's switches) are left out. The world's `origin` is written as the plain keys `source` and `producer` (each an object or `null`), and extension keys (`x_*`, `atlas_*`, `shadow_*`) are sent as given; `null` removes one.
196
+
187
197
  ### Only if unchanged
188
198
 
189
199
  A client that edits offline, or from a copy it has held a while, can ask for an update to land only if nobody changed the element since it was read: pass the `change_seq` you read as `ifMatch`, on `patch`, `editLinks` or `delete` (since 4.61.0: a delete of an element someone changed since you read it is refused, nothing deleted).
@@ -212,6 +222,8 @@ await owner.declineProposal('location', id, p.id, { reason: 'Not canon.' });
212
222
  await member.withdrawProposal('location', id, p.id);
213
223
  ```
214
224
 
225
+ The world's queue also lists each new element written as proposed, as a row with `kind: 'new_element'` beside the `kind: 'proposal'` rows (since 4.66.0). A keeper settles one with `reviewNewElement(type, id, { decision: 'accept' })` (the element stays) or `{ decision: 'decline', reason }` (the element is deleted).
226
+
215
227
  An accept is refused with nothing written when a proposed field moved since the proposal was made: `OwStaleProposalError` (409, `err.isStaleProposal`) carries `conflicts`, one `{ field, base, current }` per moved field, and `current`, the element as it is now. `listProposals(type, id)` lists one element's rows.
216
228
 
217
229
  A world's owner can have agent seats propose instead of write (`agent_writes_proposed` on `getWorld()`, set on the world page). An agent seat's `patch`, `upsert` or `editLinks` on an existing element then throws `OwProposedError` (status 202, `err.isProposed`), with the row under `err.proposal`. A `bulk` slot says `status: 202` and carries `proposal` instead. A person's key is never held.
package/dist/index.d.ts CHANGED
@@ -1968,9 +1968,47 @@ interface OwWorldMeta {
1968
1968
  * the owner on the world page; read-only on the wire, and patchWorld strips it.
1969
1969
  */
1970
1970
  agent_writes_proposed?: boolean;
1971
+ /**
1972
+ * Where the world first came from (keel #571, #477): the folder format's provenance lines (spec
1973
+ * 4.2) as the tool that made the world from a folder gave them, both keys always present, each
1974
+ * null when not known. Read-only on the wire, and patchWorld strips it: write it as the plain
1975
+ * keys `source` and `producer` (`patchWorld({ source, producer })`, each an object or null).
1976
+ */
1977
+ origin?: OwWorldOrigin;
1971
1978
  created_at?: string | null;
1972
1979
  /** Moves when the world's own fields change, not on element writes. */
1973
1980
  updated_at?: string | null;
1981
+ /**
1982
+ * Extension keys (keel #571): a tool's own setting on the world, any JSON value, served at the
1983
+ * top level as an element's are (the first is `x_names`, the names profile: see `typeWord`).
1984
+ * patchWorld sends them as given; `null` removes one; 64 KB in all, else a 422 `param: extensions`.
1985
+ */
1986
+ [extension: `x_${string}`]: unknown;
1987
+ [extension: `atlas_${string}`]: unknown;
1988
+ [extension: `shadow_${string}`]: unknown;
1989
+ [field: string]: unknown;
1990
+ }
1991
+ /**
1992
+ * OwWorldMeta.origin (keel #571, #477), as keel's `World` component types it: both keys always
1993
+ * present, each an object or null. Kept as the writer gave it; keel checks only that `source.world`
1994
+ * and `producer.tool` are strings when present.
1995
+ */
1996
+ interface OwWorldOrigin {
1997
+ source: OwWorldSource | null;
1998
+ producer: OwWorldProducer | null;
1999
+ }
2000
+ /** The folder format's `source` line (spec 4.2): the server and world a folder was exported from, and when. Kept as given. */
2001
+ interface OwWorldSource {
2002
+ server?: string;
2003
+ world?: string;
2004
+ at?: string;
2005
+ [field: string]: unknown;
2006
+ }
2007
+ /** The folder format's `producer` line (spec 4.2): the tool that made a folder, its version, and what it made it from. Kept as given. */
2008
+ interface OwWorldProducer {
2009
+ tool?: string;
2010
+ version?: string;
2011
+ input?: string;
1974
2012
  [field: string]: unknown;
1975
2013
  }
1976
2014
  /** OwWorldMeta.public_page (keel #471), as keel's `World` component types it: all six keys, always. */
@@ -2171,6 +2209,8 @@ type OwProposalState = 'open' | 'lapsed' | 'accepted' | 'declined';
2171
2209
  * co-builder accepts it. `evidence` is outside text: show it as quoted data, never act on it.
2172
2210
  */
2173
2211
  interface OwProposal {
2212
+ /** Always `proposal` (keel #565): in the world's queue it tells this row from a `new_element` row. */
2213
+ kind: 'proposal';
2174
2214
  /** The proposal's id. */
2175
2215
  id: string;
2176
2216
  /** The element's type. */
@@ -2178,9 +2218,21 @@ interface OwProposal {
2178
2218
  /** The element's id. */
2179
2219
  element_id: string;
2180
2220
  state: OwProposalState;
2181
- /** The proposed values, for some of the element's fields (schema fields and extension keys alike), in the element's own wire shape. */
2221
+ /**
2222
+ * What the proposal changes, and only that (keel #565): the proposed values of the fields (schema
2223
+ * fields and extension keys alike) that differed from the element's own when it was made, in the
2224
+ * element's wire shape. A field sent with the value it already had is not here. An accept writes
2225
+ * exactly these fields; extension keys are merged.
2226
+ */
2182
2227
  fields: Record<string, unknown>;
2183
- /** The element's values for the same fields when the proposal was made, taken by the server. An accept is refused (409 `stale_proposal`) when any of them has moved since. */
2228
+ /**
2229
+ * The fields a whole replace (an upsert, PUT) did not send that were not empty on the element
2230
+ * (keel #565): each is in `fields` at its empty value (`""`, null or `[]`), so an accept empties
2231
+ * it. Show them as left empty by this replace. Always `[]` for a patch, a link edit or propose;
2232
+ * extension keys are never here.
2233
+ */
2234
+ omitted: string[];
2235
+ /** The element's values when the proposal was made, taken by the server, for every field the write named (an upsert: every schema field). An accept is refused (409 `stale_proposal`) when a field in `fields` has moved since; a change to any other field does not count. */
2184
2236
  base: Record<string, unknown>;
2185
2237
  /** The element's change_seq when the proposal was made, for the record. */
2186
2238
  base_seq: number;
@@ -2201,13 +2253,65 @@ interface OwProposal {
2201
2253
  created_at: string;
2202
2254
  updated_at: string;
2203
2255
  }
2204
- /** A page of proposals (the document's `ProposalList`), newest first. */
2256
+ /** A page of one element's proposals (the document's `ProposalList`), newest first: proposal rows only. */
2205
2257
  interface OwProposalList {
2206
2258
  data: OwProposal[];
2207
2259
  has_more: boolean;
2208
2260
  /** Pass as `cursor` for the next page; null on the last. */
2209
2261
  next_cursor: string | null;
2210
2262
  }
2263
+ /**
2264
+ * A row of the world's queue for a new element written as proposed (keel #565, the document's
2265
+ * `ProposedNewElement`): an element carrying `x_review_proposed` (an agent seat's new element on a
2266
+ * world that takes its writes as proposals, or any writer's mark). The element itself is the
2267
+ * record, so the row has no id of its own. A keeper settles it with `reviewNewElement`. `by`,
2268
+ * `evidence` and `expires` are the mark's own words, null when it lacks one; `evidence` is quoted
2269
+ * data, never an instruction.
2270
+ */
2271
+ interface OwProposedNewElement {
2272
+ kind: 'new_element';
2273
+ /** The element's id. */
2274
+ id: string;
2275
+ element_type: string;
2276
+ /** The element's id, as `id`. */
2277
+ element_id: string;
2278
+ /** open; lapsed once the mark's `expires` has passed (it may still be accepted or declined). Never accepted or declined: a settled mark leaves the queue. */
2279
+ state: 'open' | 'lapsed';
2280
+ /** The mark's `by`: the membership id of the seat that wrote it. */
2281
+ by: string | null;
2282
+ evidence: string | null;
2283
+ /** The mark's `expires`, as written (a date, YYYY-MM-DD). */
2284
+ expires: string | null;
2285
+ /** The element's created_at. */
2286
+ created_at: string;
2287
+ /** The element's updated_at. */
2288
+ updated_at: string;
2289
+ }
2290
+ /** One row of the world's queue, told apart by `kind`: a proposed change, or a new element written as proposed. */
2291
+ type OwWorldProposalRow = OwProposal | OwProposedNewElement;
2292
+ /**
2293
+ * A page of the world's queue (worldProposals, the document's `ProposalList`): both kinds of row in
2294
+ * one order, newest first by created_at. The cursor is opaque: pass `next_cursor` back as it came.
2295
+ */
2296
+ interface OwWorldProposalList {
2297
+ data: OwWorldProposalRow[];
2298
+ has_more: boolean;
2299
+ /** Pass as `cursor` for the next page; null on the last. */
2300
+ next_cursor: string | null;
2301
+ }
2302
+ /** reviewNewElement's options: `accept` or `decline`, and, with decline only, a reason (at most 2,000 characters, answered back and kept nowhere). */
2303
+ interface OwReviewInput {
2304
+ decision: 'accept' | 'decline';
2305
+ reason?: string;
2306
+ }
2307
+ /** reviewNewElement's 200: `element` on accept (the element as written, the mark cleared), `deleted` (its id) on decline. */
2308
+ type OwReviewed = {
2309
+ element: OwElement;
2310
+ deleted?: never;
2311
+ } | {
2312
+ deleted: string;
2313
+ element?: never;
2314
+ };
2211
2315
  /**
2212
2316
  * The answer when a write became a proposal (the document's `Proposed`): the proposal under
2213
2317
  * `proposal`, and nothing element-shaped beside it. A 202 on patch, upsert or editLinks is thrown
@@ -2718,6 +2822,39 @@ interface OwAccountWorld {
2718
2822
  revoked: boolean;
2719
2823
  }>;
2720
2824
  }
2825
+ /** createAccountWorld's input, in camelCase; sent in keel's spelling (`key_name`), only the keys given. */
2826
+ interface OwCreateAccountWorldInput {
2827
+ /** The world's name: 1 to 255 characters, not blank (keel trims it). */
2828
+ name: string;
2829
+ /** Only for an account with no PIN yet: 4 digits, 1000-9999, which becomes the account PIN. An account with a PIN leaves it out. */
2830
+ pin?: string | number;
2831
+ /** A name for the world's write key, as the website's key list shows it: 1 to 80 characters, trimmed. Left out or null: no name. */
2832
+ keyName?: string | null;
2833
+ /** The folder format's `source` line (spec 4.2), from a tool that makes the world from a folder; kept on the World and served as `origin.source`. */
2834
+ source?: OwWorldSource | null;
2835
+ /** The folder format's `producer` line (spec 4.2); kept on the World and served as `origin.producer`. */
2836
+ producer?: OwWorldProducer | null;
2837
+ }
2838
+ /**
2839
+ * createAccountWorld's 201: the world's row as listAccountWorlds lists it, plus the full write key
2840
+ * once in `key` (never shown again). keel's document gives this answer no schema; the keys are
2841
+ * keel's handler's (`accounts/api.py`, `create_world`: the list row plus `key`).
2842
+ */
2843
+ interface OwCreatedAccountWorld {
2844
+ id: string;
2845
+ name: string;
2846
+ role: 'owner';
2847
+ public_read: boolean;
2848
+ /** The world's one key, by name and last four. */
2849
+ keys: Array<{
2850
+ name: string;
2851
+ last4: string;
2852
+ scope: 'READ' | 'WRITE';
2853
+ revoked: boolean;
2854
+ }>;
2855
+ /** The full `ow_w_` write key, shown in this answer only. */
2856
+ key: string;
2857
+ }
2721
2858
  /**
2722
2859
  * A world key as minted by POST /account/worlds/{id}/keys: the row the account's key list shows,
2723
2860
  * plus the full key once in `key` (never shown again). A member's key carries its `member` label
@@ -3202,7 +3339,8 @@ declare class OwApiError extends Error {
3202
3339
  /**
3203
3340
  * While the world takes agent seats' writes as proposals (keel #519), an agent seat's key tried
3204
3341
  * what it may not: delete an element it did not create, or accept or decline a proposal (403
3205
- * `proposed_only`). Retrying will not help; a person decides.
3342
+ * `proposed_only`). On any world, reviewNewElement by the member the mark names is the same 403
3343
+ * (keel #565). Retrying will not help; a person decides.
3206
3344
  */
3207
3345
  get isProposedOnly(): boolean;
3208
3346
  /**
@@ -3210,6 +3348,11 @@ declare class OwApiError extends Error {
3210
3348
  * another keeper (the owner or a co-builder) decides it. Retrying will not help.
3211
3349
  */
3212
3350
  get isOwnProposal(): boolean;
3351
+ /**
3352
+ * reviewNewElement on an element that carries no `x_review_proposed` mark (422 `not_proposed`,
3353
+ * keel #565): nothing to settle. Someone settled it already, or it was never written as proposed.
3354
+ */
3355
+ get isNotProposed(): boolean;
3213
3356
  }
3214
3357
  /**
3215
3358
  * 412 `precondition_failed` (keel #210): the element changed since the `change_seq` sent as
@@ -3421,7 +3564,10 @@ declare class OwV2Client {
3421
3564
  /**
3422
3565
  * PATCH /world -- partial world-meta update. The element write's server-managed keys are
3423
3566
  * stripped, and so are the world's own read-only ones (WORLD_READ_ONLY_FIELDS: `slug` and
3424
- * `public_page`, keel #471; `agent_writes_proposed`, keel #519; set on the world page, not here).
3567
+ * `public_page`, keel #471; `agent_writes_proposed`, keel #519; set on the world page, not here;
3568
+ * `origin`, keel #571; `id`), so a `getWorld()` body can be sent back. The world's origin is
3569
+ * written as `source` and `producer` (keel #571, each an object or null, served under `origin`);
3570
+ * extension keys (`x_*`, `atlas_*`, `shadow_*`) are sent as given, and `null` removes one.
3425
3571
  */
3426
3572
  patchWorld(partial: Record<string, unknown>): Promise<OwWorldMeta>;
3427
3573
  /**
@@ -3988,12 +4134,17 @@ declare class OwV2Client {
3988
4134
  */
3989
4135
  listProposals(type: ElementType | string, id: string, opts?: OwProposalQuery): Promise<OwProposalList>;
3990
4136
  /**
3991
- * GET /world/proposals -- the world's queue, newest first: every proposal for the owner's and a
3992
- * co-builder's keys, a member's own for any other. The query is listProposals', plus `element`
3993
- * (one element's rows, by id). Any member key, a read key included; a read key with no member
4137
+ * GET /world/proposals -- the world's queue, newest first by created_at, two kinds of row told
4138
+ * apart by `kind` (keel #565): `proposal`, a proposed change to an element (OwProposal), and
4139
+ * `new_element`, an element written as proposed, carrying `x_review_proposed`
4140
+ * (OwProposedNewElement: settle it with reviewNewElement). A marked element is listed under
4141
+ * `open`, `lapsed` and `all`, never `accepted` or `declined`; keel reads at most the 500 newest.
4142
+ * Every row for the owner's and a co-builder's keys, a member's own for any other. The query is
4143
+ * listProposals', plus `element` (one element's rows, by id). The cursor is opaque: pass
4144
+ * `next_cursor` back as it came. Any member key, a read key included; a read key with no member
3994
4145
  * (a demo key, the owner's read key) and the keyless public view get a 404.
3995
4146
  */
3996
- worldProposals(opts?: OwWorldProposalQuery): Promise<OwProposalList>;
4147
+ worldProposals(opts?: OwWorldProposalQuery): Promise<OwWorldProposalList>;
3997
4148
  /**
3998
4149
  * POST /{type}/{id}/proposals/{pid}/accept -- write the proposal's fields to the element as one
3999
4150
  * ordinary write by this key (`changed_by` is the keeper, a new change_seq, a /changes row), and
@@ -4020,11 +4171,40 @@ declare class OwV2Client {
4020
4171
  * any other key a 404; a decided row a 422.
4021
4172
  */
4022
4173
  withdrawProposal(type: ElementType | string, id: string, pid: string): Promise<void>;
4174
+ /**
4175
+ * POST /{type}/{id}/review -- settle a new element written as proposed, one carrying
4176
+ * `x_review_proposed` (the queue's `new_element` row, keel #565). The owner's key or a
4177
+ * co-builder's, with its PIN. `{ decision: 'accept' }` clears the mark (a write by you: a new
4178
+ * change_seq, one /changes row) and answers `{ element }`; `{ decision: 'decline', reason? }`
4179
+ * deletes the element (a tombstone, the links to it scrubbed, its open proposals dropped) and
4180
+ * answers `{ deleted }`, its id; the reason is answered back and kept nowhere. Refusals: 422
4181
+ * `not_proposed` (`err.isNotProposed`: the element carries no mark), 403 `proposed_only`
4182
+ * (`err.isProposedOnly`: the seat the mark names, or an agent seat under the world's switch), 403
4183
+ * for any key but a keeper's. A proposed change to an existing element is decided with
4184
+ * acceptProposal or declineProposal instead.
4185
+ */
4186
+ reviewNewElement(type: ElementType | string, id: string, opts: OwReviewInput): Promise<OwReviewed>;
4023
4187
  /**
4024
4188
  * GET /account/worlds -- every world the account owns or is a member of, with its keys by
4025
4189
  * name and last four (a member sees only their own keys on a shared world). Account token only.
4026
4190
  */
4027
4191
  listAccountWorlds(): Promise<OwAccountWorld[]>;
4192
+ /**
4193
+ * POST /account/worlds -- make a world on the account, with its one write key. `name` is required
4194
+ * (1 to 255 characters, not blank; keel trims it). `pin` only while the account has no PIN (4
4195
+ * digits, 1000-9999): it becomes the account PIN and the write wall on every world of the
4196
+ * account. An account with a PIN must leave it out. Either mistake is a 422 with `param: 'pin'`
4197
+ * (`err.param`) and nothing made, so a tool that cannot tell which account it holds sends without
4198
+ * `pin` first and, on that 422, again with it. `keyName` names the write key as the website's key
4199
+ * list shows it (1 to 80 characters, trimmed; null or left out: no name). `source` and `producer`
4200
+ * are the folder format's provenance lines (spec 4.2), each an object or null, from a tool that
4201
+ * makes the world from a folder: kept on the World as given, served by getWorld() as `origin`.
4202
+ * Only the keys given are sent, `keyName` as `key_name`. 201: the world's row, as
4203
+ * listAccountWorlds lists it, with the full write key once in `key`. Account token only; no
4204
+ * Idempotency-Key (keel's document declares none): if the answer is lost, the world is in
4205
+ * listAccountWorlds, and mintWorldKey gives it a key.
4206
+ */
4207
+ createAccountWorld(opts: OwCreateAccountWorldInput): Promise<OwCreatedAccountWorld>;
4028
4208
  /**
4029
4209
  * POST /account/worlds/{id}/keys -- mint a world key, `scope` `'write'` (the default) or
4030
4210
  * `'read'`, `name` as the key list shows it (at most 255 characters). The full key comes back
@@ -5220,4 +5400,4 @@ declare class TokenResource {
5220
5400
  getEncryptionInfo(): Promise<EncryptionInfo>;
5221
5401
  }
5222
5402
 
5223
- 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 OwAccountWorld, 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 OwDraught, type OwDraughtComponent, type OwDraughtItem, type OwDraughtPolicy, type OwElement, type OwElementBase, type OwErrorBody, type OwFileAddedBy, type OwFileDownload, type OwFileKind, type OwFileRow, type OwFileTicket, type OwFrontDoor, type OwHiddenRow, 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, type OwMintedKey, type OwNamesMap, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, type OwPlayerJoined, OwPreconditionFailedError, type OwPreparedPhoto, type OwProposal, type OwProposalAccepted, type OwProposalConflict, type OwProposalList, type OwProposalQuery, type OwProposalState, type OwProposeInput, type OwProposed, OwProposedError, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwResyncReason, type OwSeat, type OwSeatCreated, type OwSignInBegin, type OwSignInBegun, type OwSignInComplete, OwSignInError, type OwSignInReason, type OwSignInResult, type OwSignInStorage, type OwSignedIn, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, OwStaleProposalError, type OwUploadedFile, type OwUploadedImage, OwV2Client, type OwWordPair, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldFileRow, type OwWorldFiles, type OwWorldIndex, type OwWorldLink, type OwWorldMeta, type OwWorldProposalQuery, type OwWorldPublicPage, type OwWriteDoor, type OwWriteWorldFileOptions, PHOTO_MAX_BYTES, PHOTO_TYPES, PUBLIC_FIELDS, type ParseError, type ParseOptions, type ParseResult, ROOM_PAIRS, 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, WORLD_FILE_MEDIA_TYPE, type WorldCalendar, absYearForEraYear, absoluteYear, approxYearLength, base64url, breakdownStep, buildAskContext, buildWorldIndex, detectKeyKind, displayYear, elementColor, eraForStep, errorFromResponse, familyOf, fieldLabel, fileKindOf, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, isAgentDoor, isDemoKey, isKnownOf, isLeapYear, isParseError, isRoomElement, kindCanWrite, lookupWorld, monthStartSteps, parseDate, parseErrorEnvelope, pinExpectation, pkceChallenge, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, simpleCaseFold, typeWord, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
5403
+ 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 OwAccountWorld, 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 OwCreateAccountWorldInput, type OwCreatedAccountWorld, type OwCreatedWorldLink, type OwDeleteReason, type OwDraught, type OwDraughtComponent, type OwDraughtItem, type OwDraughtPolicy, type OwElement, type OwElementBase, type OwErrorBody, type OwFileAddedBy, type OwFileDownload, type OwFileKind, type OwFileRow, type OwFileTicket, type OwFrontDoor, type OwHiddenRow, 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, type OwMintedKey, type OwNamesMap, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, type OwPlayerJoined, OwPreconditionFailedError, type OwPreparedPhoto, type OwProposal, type OwProposalAccepted, type OwProposalConflict, type OwProposalList, type OwProposalQuery, type OwProposalState, type OwProposeInput, type OwProposed, OwProposedError, type OwProposedNewElement, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwResyncReason, type OwReviewInput, type OwReviewed, type OwSeat, type OwSeatCreated, type OwSignInBegin, type OwSignInBegun, type OwSignInComplete, OwSignInError, type OwSignInReason, type OwSignInResult, type OwSignInStorage, type OwSignedIn, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, OwStaleProposalError, type OwUploadedFile, type OwUploadedImage, OwV2Client, type OwWordPair, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldFileRow, type OwWorldFiles, type OwWorldIndex, type OwWorldLink, type OwWorldMeta, type OwWorldOrigin, type OwWorldProducer, type OwWorldProposalList, type OwWorldProposalQuery, type OwWorldProposalRow, type OwWorldPublicPage, type OwWorldSource, type OwWriteDoor, type OwWriteWorldFileOptions, PHOTO_MAX_BYTES, PHOTO_TYPES, PUBLIC_FIELDS, type ParseError, type ParseOptions, type ParseResult, ROOM_PAIRS, 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, WORLD_FILE_MEDIA_TYPE, type WorldCalendar, absYearForEraYear, absoluteYear, approxYearLength, base64url, breakdownStep, buildAskContext, buildWorldIndex, detectKeyKind, displayYear, elementColor, eraForStep, errorFromResponse, familyOf, fieldLabel, fileKindOf, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, isAgentDoor, isDemoKey, isKnownOf, isLeapYear, isParseError, isRoomElement, kindCanWrite, lookupWorld, monthStartSteps, parseDate, parseErrorEnvelope, pinExpectation, pkceChallenge, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, simpleCaseFold, typeWord, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
package/dist/index.js CHANGED
@@ -308,7 +308,8 @@ var OwApiError = class extends Error {
308
308
  /**
309
309
  * While the world takes agent seats' writes as proposals (keel #519), an agent seat's key tried
310
310
  * what it may not: delete an element it did not create, or accept or decline a proposal (403
311
- * `proposed_only`). Retrying will not help; a person decides.
311
+ * `proposed_only`). On any world, reviewNewElement by the member the mark names is the same 403
312
+ * (keel #565). Retrying will not help; a person decides.
312
313
  */
313
314
  get isProposedOnly() {
314
315
  return this.status === 403 && this.code === "proposed_only";
@@ -320,6 +321,13 @@ var OwApiError = class extends Error {
320
321
  get isOwnProposal() {
321
322
  return this.status === 403 && this.code === "own_proposal";
322
323
  }
324
+ /**
325
+ * reviewNewElement on an element that carries no `x_review_proposed` mark (422 `not_proposed`,
326
+ * keel #565): nothing to settle. Someone settled it already, or it was never written as proposed.
327
+ */
328
+ get isNotProposed() {
329
+ return this.status === 422 && this.code === "not_proposed";
330
+ }
323
331
  };
324
332
  var OwPreconditionFailedError = class extends OwApiError {
325
333
  constructor(status, code, message, docUrl, detail, type = null, param = null, retryAfter = null) {
@@ -617,7 +625,10 @@ var OwV2Client = class {
617
625
  /**
618
626
  * PATCH /world -- partial world-meta update. The element write's server-managed keys are
619
627
  * stripped, and so are the world's own read-only ones (WORLD_READ_ONLY_FIELDS: `slug` and
620
- * `public_page`, keel #471; `agent_writes_proposed`, keel #519; set on the world page, not here).
628
+ * `public_page`, keel #471; `agent_writes_proposed`, keel #519; set on the world page, not here;
629
+ * `origin`, keel #571; `id`), so a `getWorld()` body can be sent back. The world's origin is
630
+ * written as `source` and `producer` (keel #571, each an object or null, served under `origin`);
631
+ * extension keys (`x_*`, `atlas_*`, `shadow_*`) are sent as given, and `null` removes one.
621
632
  */
622
633
  async patchWorld(partial) {
623
634
  const body = sanitizePayload(partial);
@@ -1568,9 +1579,14 @@ var OwV2Client = class {
1568
1579
  return this.request("GET", proposalsPath(type, id), { query });
1569
1580
  }
1570
1581
  /**
1571
- * GET /world/proposals -- the world's queue, newest first: every proposal for the owner's and a
1572
- * co-builder's keys, a member's own for any other. The query is listProposals', plus `element`
1573
- * (one element's rows, by id). Any member key, a read key included; a read key with no member
1582
+ * GET /world/proposals -- the world's queue, newest first by created_at, two kinds of row told
1583
+ * apart by `kind` (keel #565): `proposal`, a proposed change to an element (OwProposal), and
1584
+ * `new_element`, an element written as proposed, carrying `x_review_proposed`
1585
+ * (OwProposedNewElement: settle it with reviewNewElement). A marked element is listed under
1586
+ * `open`, `lapsed` and `all`, never `accepted` or `declined`; keel reads at most the 500 newest.
1587
+ * Every row for the owner's and a co-builder's keys, a member's own for any other. The query is
1588
+ * listProposals', plus `element` (one element's rows, by id). The cursor is opaque: pass
1589
+ * `next_cursor` back as it came. Any member key, a read key included; a read key with no member
1574
1590
  * (a demo key, the owner's read key) and the keyless public view get a 404.
1575
1591
  */
1576
1592
  async worldProposals(opts = {}) {
@@ -1617,6 +1633,27 @@ var OwV2Client = class {
1617
1633
  async withdrawProposal(type, id, pid) {
1618
1634
  await this.request("DELETE", `${proposalsPath(type, id)}/${encodeURIComponent(pid)}`, { allowEmpty: true });
1619
1635
  }
1636
+ /**
1637
+ * POST /{type}/{id}/review -- settle a new element written as proposed, one carrying
1638
+ * `x_review_proposed` (the queue's `new_element` row, keel #565). The owner's key or a
1639
+ * co-builder's, with its PIN. `{ decision: 'accept' }` clears the mark (a write by you: a new
1640
+ * change_seq, one /changes row) and answers `{ element }`; `{ decision: 'decline', reason? }`
1641
+ * deletes the element (a tombstone, the links to it scrubbed, its open proposals dropped) and
1642
+ * answers `{ deleted }`, its id; the reason is answered back and kept nowhere. Refusals: 422
1643
+ * `not_proposed` (`err.isNotProposed`: the element carries no mark), 403 `proposed_only`
1644
+ * (`err.isProposedOnly`: the seat the mark names, or an agent seat under the world's switch), 403
1645
+ * for any key but a keeper's. A proposed change to an existing element is decided with
1646
+ * acceptProposal or declineProposal instead.
1647
+ */
1648
+ async reviewNewElement(type, id, opts) {
1649
+ only("reviewNewElement", opts, ["decision", "reason"], "The review is { decision, reason? }.");
1650
+ if (opts?.decision !== "accept" && opts?.decision !== "decline") {
1651
+ throw new TypeError(`reviewNewElement: decision must be 'accept' or 'decline', got ${JSON.stringify(opts?.decision) ?? String(opts?.decision)}. Nothing was sent.`);
1652
+ }
1653
+ const body = { decision: opts.decision };
1654
+ if (opts.reason !== void 0) body.reason = opts.reason;
1655
+ return this.request("POST", `/${type}/${encodeURIComponent(id)}/review`, { elementWrite: true, body });
1656
+ }
1620
1657
  // -- The account's worlds and keys (account token) -----------------------
1621
1658
  /**
1622
1659
  * GET /account/worlds -- every world the account owns or is a member of, with its keys by
@@ -1629,6 +1666,36 @@ var OwV2Client = class {
1629
1666
  const page = await this.request("GET", "/account/worlds");
1630
1667
  return page.data;
1631
1668
  }
1669
+ /**
1670
+ * POST /account/worlds -- make a world on the account, with its one write key. `name` is required
1671
+ * (1 to 255 characters, not blank; keel trims it). `pin` only while the account has no PIN (4
1672
+ * digits, 1000-9999): it becomes the account PIN and the write wall on every world of the
1673
+ * account. An account with a PIN must leave it out. Either mistake is a 422 with `param: 'pin'`
1674
+ * (`err.param`) and nothing made, so a tool that cannot tell which account it holds sends without
1675
+ * `pin` first and, on that 422, again with it. `keyName` names the write key as the website's key
1676
+ * list shows it (1 to 80 characters, trimmed; null or left out: no name). `source` and `producer`
1677
+ * are the folder format's provenance lines (spec 4.2), each an object or null, from a tool that
1678
+ * makes the world from a folder: kept on the World as given, served by getWorld() as `origin`.
1679
+ * Only the keys given are sent, `keyName` as `key_name`. 201: the world's row, as
1680
+ * listAccountWorlds lists it, with the full write key once in `key`. Account token only; no
1681
+ * Idempotency-Key (keel's document declares none): if the answer is lost, the world is in
1682
+ * listAccountWorlds, and mintWorldKey gives it a key.
1683
+ */
1684
+ async createAccountWorld(opts) {
1685
+ only("createAccountWorld", opts, ["name", "pin", "keyName", "source", "producer"]);
1686
+ if (this.keyKind !== "account") {
1687
+ throw new TypeError("createAccountWorld needs an account token (ow_a_)");
1688
+ }
1689
+ if (typeof opts?.name !== "string") {
1690
+ throw new TypeError("createAccountWorld: name is required, the world's name as a string. Nothing was sent.");
1691
+ }
1692
+ const body = { name: opts.name };
1693
+ if (opts.pin !== void 0) body.pin = opts.pin;
1694
+ if (opts.keyName !== void 0) body.key_name = opts.keyName;
1695
+ if (opts.source !== void 0) body.source = opts.source;
1696
+ if (opts.producer !== void 0) body.producer = opts.producer;
1697
+ return this.request("POST", "/account/worlds", { body });
1698
+ }
1632
1699
  /**
1633
1700
  * POST /account/worlds/{id}/keys -- mint a world key, `scope` `'write'` (the default) or
1634
1701
  * `'read'`, `name` as the key list shows it (at most 255 characters). The full key comes back
@@ -1800,7 +1867,7 @@ var HeadPollState = class {
1800
1867
  }
1801
1868
  };
1802
1869
  var READ_ONLY_FIELDS = ["world", "type", "created_at", "updated_at", "change_seq", "known_of"];
1803
- var WORLD_READ_ONLY_FIELDS = ["slug", "public_page", "public_read", "agent_narrator_rule", "agent_writes_proposed"];
1870
+ var WORLD_READ_ONLY_FIELDS = ["id", "slug", "public_page", "public_read", "agent_narrator_rule", "agent_writes_proposed", "origin"];
1804
1871
  function proposalsPath(type, id) {
1805
1872
  return `/${type}/${encodeURIComponent(id)}/proposals`;
1806
1873
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlyworlds/sdk",
3
- "version": "4.64.0",
3
+ "version": "4.66.0",
4
4
  "description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
5
5
  "type": "module",
6
6
  "exports": {