@onlyworlds/sdk 4.36.2 → 4.38.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,6 +1,6 @@
1
1
  # For AI agents using @onlyworlds/sdk
2
2
 
3
- **Current as of**: SDK **4.x** · schema-dist **v0.32.0-dist.23** (canonical 00.32.00).
3
+ **Current as of**: SDK **4.x** · schema-dist **v0.32.1-dist.26** (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
 
package/CHANGELOG.md CHANGED
@@ -5,6 +5,38 @@ earlier history lives in git log only.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [4.38.0] - 2026-10-20
9
+
10
+ Schema 00.32.01 (the Captain's word, h55 #8395): repinned to schema-dist v0.32.1-dist.26.
11
+
12
+ ### Changed
13
+ - **An Event's `characters`** reads "Characters who know about the event: they were present, aware of it, or involved in it" (it read "Key characters relevant to the event"), in the generated doc comment and `SCHEMA.md`. No field, type or link changed.
14
+ - **`ONLYWORLDS_VERSION`** is `'00.32.01'`. It is an `as const` export, so its literal type moves too, which is why this is a minor and not a patch.
15
+
16
+ ## [4.37.0] - 2026-10-20
17
+
18
+ The hidden mark (keel #421), live in production since 2026-10-20 09:24; walked on staging with the mark on, 25 of 25.
19
+
20
+ ### Added
21
+ - A `/changes` delete row's `reason` (`OwDeleteReason`: `deleted` | `hidden` | `out_of_view`; keel #421's hidden
22
+ mark): an element hidden from this reader leaves its copy as a deleted one does, and a GET of it answers 404,
23
+ not 410. `isResyncRequired`'s comment names every case keel now sends it for, not only a guest's.
24
+ - `viewAs` on `get`, `list` and `listAll`, sent as `as` (keel #421 PR 3, view as): the owner's key reads as a
25
+ member (a membership id), as a Character's guest (a Character id) or as the public (`'public'`). A member key
26
+ gets 403 `view_as_owner_only` (`err.isViewAsOwnerOnly`); an element hidden from that reader is 404, never 410;
27
+ an unknown value is 422. Until keel's hidden mark is on, keel answers 422 (an unknown parameter).
28
+ - `err.resyncReason` (`'role'` | `'view'` | `undefined`) and `OwResyncReason`: why `/changes` answered 409
29
+ `resync_required`, from the envelope's `reason` (keel #421, keel PR 103; only while keel's hidden mark is on).
30
+ `epoch_reason` beside `epoch` on `OwChangesPage` and on `changesHead()`'s answer: why the epoch last moved.
31
+
32
+ ### Changed
33
+ - The resync instruction adds the hidden mark's reasons to 4.36.1's keep (the Captain, 2026-10-20): after a
34
+ 409 `resync_required`, walk again from the start; reason `role` (the key's own role or membership moved):
35
+ keep what the local copy holds that the walk no longer names; reason `view`, or a delete row with reason
36
+ `hidden`: drop it; no reason (keel's hidden mark off): keep it, a reset never empties a copy. A tool never
37
+ empties a copy on its own. `isResyncRequired`'s comment and the `changes`,
38
+ `changesHead` and `OwChangesPage` comments say so.
39
+
8
40
  ## [4.36.2] - 2026-10-20
9
41
 
10
42
  ### Changed
package/SCHEMA.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # OnlyWorlds Schema Reference
2
2
 
3
- **Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.32.0-dist.23** — canonical schema **00.32.00**, published 2026-10-12.
3
+ **Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.32.1-dist.26** — 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.
@@ -206,7 +206,7 @@ Families (colour semantics; icon carries the type): agents · world · abstract
206
206
 
207
207
  ### Involves
208
208
 
209
- - `characters` (multi link → character) — Key characters relevant to the event
209
+ - `characters` (multi link → character) — Characters who know about the event: they were present, aware of it, or involved in it
210
210
  - `objects` (multi link → object) — Objects relevant to the event
211
211
  - `locations` (multi link → location) — Locations relevant to the event
212
212
  - `species` (multi link → species) — Species relevant to the event
package/dist/index.d.ts CHANGED
@@ -37,7 +37,7 @@ type ElementType = 'ability' | 'character' | 'collective' | 'construct' | 'creat
37
37
  declare const ELEMENT_TYPES: ElementType[];
38
38
  /** Canonical OnlyWorlds schema version. Source: the `canonical:` value of the pinned
39
39
  * distribution's VERSION file (see the provenance block at the top of this file). */
40
- declare const ONLYWORLDS_VERSION: "00.32.00";
40
+ declare const ONLYWORLDS_VERSION: "00.32.01";
41
41
  /** The four semantic families (colour carries the family; ELEMENT_ICONS carries the type). */
42
42
  type ElementFamily = 'agents' | 'world' | 'abstract' | 'temporal';
43
43
  /** Per-type semantic family. Source: the distribution's `presentation.json` sidecar
@@ -1895,7 +1895,7 @@ interface OwWorldMeta {
1895
1895
  * Character a 403 `guest_not_supported`.
1896
1896
  */
1897
1897
  agent_narrator_rule?: boolean;
1898
- /** The owner's "this Character is me": a Character id in this world, or null. */
1898
+ /** The owner's "this Character is me": a Character id in this world, or null (null too, to a reader it is hidden from: keel #421). */
1899
1899
  owner_character?: string | null;
1900
1900
  created_at?: string | null;
1901
1901
  /** Moves when the world's own fields change, not on element writes. */
@@ -1933,8 +1933,17 @@ interface OwChangeDelete {
1933
1933
  deleted_by?: string | null;
1934
1934
  /** The door the delete came through (see {@link OwWriteDoor}); null for deletes before writes recorded it. */
1935
1935
  deleted_via?: OwWriteDoor | null;
1936
+ /**
1937
+ * Why the element left this reader's view (keel #421): `deleted` (it is gone; a GET answers 410),
1938
+ * `hidden` (the world's owner or a co-builder hid it from this reader; it still exists, a GET answers
1939
+ * 404, and an unhide brings it back by a 409 `resync_required`), or `out_of_view` (declared, sent by
1940
+ * nothing yet). Remove the element from the local copy in every case.
1941
+ */
1942
+ reason?: OwDeleteReason;
1936
1943
  [k: string]: unknown;
1937
1944
  }
1945
+ /** Why a /changes delete row says the element left the reader's view (keel #421). */
1946
+ type OwDeleteReason = 'deleted' | 'hidden' | 'out_of_view';
1938
1947
  /**
1939
1948
  * The door a write came through, as keel records it on every element (`changed_via`) and on a
1940
1949
  * delete (`deleted_via`) since keel #299: `seat` (an agent seat), `mcp` (the MCP server),
@@ -1962,12 +1971,30 @@ interface OwChangesPage {
1962
1971
  */
1963
1972
  head: number;
1964
1973
  /**
1965
- * A guest's view epoch (an integer), null for every other key. It moves when what the
1966
- * guest may see changes, even with `head` unchanged (a Character given or taken, a role):
1974
+ * A guest's or a contributor's view epoch (an integer; a contributor's since keel #421), null for
1975
+ * every other key. It moves when what the key may see changes, even with `head` unchanged (a
1976
+ * Character given or taken, an element unhidden, a role):
1967
1977
  * walk again on either move. Compare it, never read it out of the cursor (keel, 2026-10-12).
1968
1978
  */
1969
1979
  epoch: number | null;
1980
+ /**
1981
+ * Why `epoch` last moved (keel #421, only while keel's hidden mark is on; null when `epoch` is
1982
+ * null): `role` (this key's own role or membership moved: keep what the local copy holds that a
1983
+ * walk from the start no longer names) or `view` (something left its view: drop it; also `view`
1984
+ * for an epoch that never moved). It names the last move only: when the epoch moved more than
1985
+ * once since the one you applied, walk with your cursor and read the 409's
1986
+ * `reason` (`err.resyncReason`), which covers every move since it. Never empty a copy on your own.
1987
+ */
1988
+ epoch_reason?: OwResyncReason | null;
1970
1989
  }
1990
+ /**
1991
+ * Why a key's view restarted (keel #421, only while keel's hidden mark is on): on a 409
1992
+ * `resync_required` as the envelope's `reason`, on a /changes page and the head as `epoch_reason`.
1993
+ * `role`: the key's own role or membership moved; keep what the new walk does not name (it is out
1994
+ * of view now, not gone). `view`: something left its view (a delete, a hide, an unhide, a
1995
+ * Character change); drop what the new walk does not name. Both since the cursor: `role`.
1996
+ */
1997
+ type OwResyncReason = 'role' | 'view';
1971
1998
  interface OwBulkItem {
1972
1999
  type: ElementType | string;
1973
2000
  element: OwElement | Record<string, unknown>;
@@ -1996,6 +2023,8 @@ interface OwErrorBody {
1996
2023
  message?: string;
1997
2024
  param?: string | null;
1998
2025
  doc_url?: string;
2026
+ /** On a 409 `resync_required` only, while keel's hidden mark is on: why (see {@link OwResyncReason}). */
2027
+ reason?: OwResyncReason;
1999
2028
  }
2000
2029
  /**
2001
2030
  * /bulk response. WIRE-CORRECTED (fixtures P2a/P2c): the array key is `items`,
@@ -2176,7 +2205,7 @@ interface OwMe {
2176
2205
  role: 'owner' | OwMemberRole;
2177
2206
  /** The membership id (what `created_by` holds for what this key creates), or null for the owner. */
2178
2207
  membership: string | null;
2179
- /** The member's Character, or null. */
2208
+ /** The member's Character, or null (null too when it is hidden from this key: keel #421). */
2180
2209
  character: string | null;
2181
2210
  /** Agent seats only: the agent's name. */
2182
2211
  name?: string;
@@ -2188,7 +2217,7 @@ interface OwMember {
2188
2217
  id: string | null;
2189
2218
  kind: 'owner' | 'person' | 'agent' | 'player';
2190
2219
  role: 'owner' | OwMemberRole;
2191
- /** The Character that is this member, or null. */
2220
+ /** The Character that is this member, or null (null too when it is hidden from the reader: keel #421). */
2192
2221
  character: string | null;
2193
2222
  /** `removed` rows stay, so their elements keep `created_by`. */
2194
2223
  status: 'active' | 'removed';
@@ -2218,7 +2247,7 @@ interface OwJoinPreview {
2218
2247
  };
2219
2248
  /** The name the inviter signed the link with, or null. */
2220
2249
  invited_by: string | null;
2221
- /** The world owner's chosen Character's name, never a username; null when none is set. */
2250
+ /** The world owner's chosen Character's name, never a username; null when none is set, or when it is hidden (keel #421). */
2222
2251
  owner_character: string | null;
2223
2252
  role: OwMemberRole;
2224
2253
  /** Whether joining gives the joiner a Character of their own (agent links). */
@@ -2524,6 +2553,16 @@ interface ListParams {
2524
2553
  * `__isnull` are designed in keel's spec but not built; `ordering` 422s too.)
2525
2554
  */
2526
2555
  filter?: Record<string, string | number | boolean>;
2556
+ /**
2557
+ * View as (keel #421), sent as `as`: read as another reader of this world would. A membership
2558
+ * id (a person, an agent seat or a player seat) reads as that member's own key; a Character id
2559
+ * reads as a guest of that Character with no membership; `'public'` reads everything not
2560
+ * hidden. The owner's keys only (a key with no member): a member key gets 403
2561
+ * `view_as_owner_only` (`err.isViewAsOwnerOnly`). An element hidden from that reader is 404,
2562
+ * never 410. An unknown value is 422 (`param` as). Only while keel's hidden mark is on; until
2563
+ * then keel answers 422 (an unknown parameter).
2564
+ */
2565
+ viewAs?: string;
2527
2566
  }
2528
2567
  interface OwClientConfig {
2529
2568
  /**
@@ -2572,6 +2611,7 @@ interface OwClientConfig {
2572
2611
  * envelope also carries `type` and `param` (fixtures P4a/P2c); both are
2573
2612
  * surfaced on the thrown error.
2574
2613
  */
2614
+
2575
2615
  /**
2576
2616
  * Auth codes are distinguishable by design; client recovery UX differs per code.
2577
2617
  * `world_gone` is RESERVED: keel's spec promises it but the server never emits it (a deleted
@@ -2625,13 +2665,25 @@ declare class OwApiError extends Error {
2625
2665
  */
2626
2666
  get isIdConflict(): boolean;
2627
2667
  /**
2628
- * `/changes` refused the cursor (409 `resync_required`): a guest's view of the world
2629
- * changed, or the key's role did (a guest's cursor has another shape). Drop the stored
2630
- * cursor, walk again from the start, and keep what the local copy holds that the new walk
2631
- * does not name: a reset never empties a copy (keel PR 104, the Captain's ruling: sharing
2632
- * is forward-only).
2668
+ * `/changes` refused the cursor (409 `resync_required`): what this key may see changed
2669
+ * (a guest's slice moved; an element hidden from a contributor was unhidden; the key's role
2670
+ * moved to or from guest or contributor, whose cursors have other shapes; keel #421). Drop
2671
+ * the stored cursor and walk again from the start. What to do with what the local copy holds
2672
+ * that the new walk does not name is `resyncReason`'s: `role`, keep it; `view`, drop it.
2673
+ * Without a reason (keel's hidden mark off), keep it: a reset never empties a copy (keel PR
2674
+ * 104, the Captain's ruling: sharing is forward-only). Never empty the copy on your own.
2633
2675
  */
2634
2676
  get isResyncRequired(): boolean;
2677
+ /**
2678
+ * Why `/changes` refused the cursor, from the 409 `resync_required` envelope's `reason`
2679
+ * (keel #421, only while keel's hidden mark is on): `role` (this key's own role or
2680
+ * membership moved: keep what the local copy holds that the new walk does not name; it is
2681
+ * out of view now, not gone) or `view` (something left this key's view: a delete, a hide, an
2682
+ * unhide, a Character change; drop what the new walk does not name). When both happened
2683
+ * since the cursor, keel says `role`. Undefined for any other error, or when keel sends no
2684
+ * reason.
2685
+ */
2686
+ get resyncReason(): OwResyncReason | undefined;
2635
2687
  /** keel's admission control turned the request away (503 `server_busy`); see retryAfter. */
2636
2688
  get isBusy(): boolean;
2637
2689
  /**
@@ -2648,6 +2700,12 @@ declare class OwApiError extends Error {
2648
2700
  * key never sees it.
2649
2701
  */
2650
2702
  get isOwnerOnly(): boolean;
2703
+ /**
2704
+ * A member key sent `viewAs` (403 `view_as_owner_only`, keel #421): reading as another
2705
+ * reader is the owner's, from a key with no member. Retrying will not help. Only while
2706
+ * keel's hidden mark is on; until then `viewAs` is an unknown parameter (422).
2707
+ */
2708
+ get isViewAsOwnerOnly(): boolean;
2651
2709
  /**
2652
2710
  * A `patch` or `editLinks` sent with `ifMatch` found the element moved past that
2653
2711
  * `change_seq` (412 `precondition_failed`, keel #210): nothing was written and nothing
@@ -2821,8 +2879,11 @@ declare class OwV2Client {
2821
2879
  list(type: ElementType | string, params?: ListParams): Promise<OwPage>;
2822
2880
  /** Cursor-walk every page of a type. Politeness: uses config pageSize. */
2823
2881
  listAll(type: ElementType | string, params?: Omit<ListParams, 'cursor'>): AsyncGenerator<OwElement>;
2824
- /** GET /{type}/{id}/ -- optional one-level stub expansion / sparse fields. */
2825
- get(type: ElementType | string, id: string, opts?: Pick<ListParams, 'expand' | 'fields'>): Promise<OwElement>;
2882
+ /**
2883
+ * GET /{type}/{id}/ -- optional one-level stub expansion / sparse fields, and `viewAs` (keel
2884
+ * #421: the owner reads as another reader; see ListParams.viewAs).
2885
+ */
2886
+ get(type: ElementType | string, id: string, opts?: Pick<ListParams, 'expand' | 'fields' | 'viewAs'>): Promise<OwElement>;
2826
2887
  /**
2827
2888
  * POST /{type}/ -- create one element, minting an id on the client when you leave id out.
2828
2889
  * With an `idempotencyKey`, the minted id is derived from the key (a UUIDv5, the same one the
@@ -2889,15 +2950,18 @@ declare class OwV2Client {
2889
2950
  }): Promise<OwBulkResponse>;
2890
2951
  /**
2891
2952
  * GET /changes -- one page of the world's ordered change feed.
2892
- * Cursor is OPAQUE: persist verbatim, never parse or build one (a guest's has
2893
- * another shape than everyone else's).
2953
+ * Cursor is OPAQUE: persist verbatim, never parse or build one (a guest's and a
2954
+ * contributor's carry their view's epoch, since keel #421 for a contributor).
2894
2955
  * Zero/absent cursor = full export (byte-aligned with the Folder Format).
2895
2956
  * Reset rule: a 409 `resync_required` (err.isResyncRequired) means the key's
2896
- * view changed (a guest's, or its role): drop the cursor, walk from zero, and keep what the
2897
- * local copy holds that the new walk does not name (keel's own words; sharing is forward-only).
2957
+ * view changed (a guest's slice, an element unhidden from a contributor, or its role): drop
2958
+ * the cursor and walk from zero. For what the local copy holds that the walk no longer names,
2959
+ * read err.resyncReason (keel #421, while keel's hidden mark is on): `role`, keep it; `view`,
2960
+ * drop it (as for a delete row with reason `hidden`). Without a reason, keep it (keel's own
2961
+ * words since PR 104; sharing is forward-only). Never empty a copy on your own.
2898
2962
  * Citizenship: heaviest route on the platform; default page size is polite.
2899
- * keel sends the cursor of a page at the head as a number (an empty page, for anyone
2900
- * but a guest); it is handed back as a string, like every cursor here.
2963
+ * keel sends the cursor of a page at the head as a number (an empty page, for a key
2964
+ * whose cursor carries no epoch); it is handed back as a string, like every cursor here.
2901
2965
  */
2902
2966
  changes(opts?: {
2903
2967
  since?: string;
@@ -2906,24 +2970,27 @@ declare class OwV2Client {
2906
2970
  /**
2907
2971
  * GET /changes?head=true -- where the feed is now, without a page: no element is read.
2908
2972
  * `head` is the world's change_seq; `cursor` is a position to pass as `since` that
2909
- * re-sends nothing at the head (a guest's carries its view's epoch). The cheap "anything
2973
+ * re-sends nothing at the head (a guest's or a contributor's carries its view's epoch). The cheap "anything
2910
2974
  * new?" for a poll: compare `head` with the head you last APPLIED (not the previous
2911
2975
  * poll's, so a missed tick never drops a change) and walk changesAll only when it moved;
2912
2976
  * a head below yours means the server rewound: walk again from zero. `epoch` is a
2913
- * guest's view epoch (null for other keys): it can move with `head` unchanged, so walk on
2914
- * either move. keel returns the owner's cursor as a number; it is handed back as a
2977
+ * guest's or a contributor's view epoch (null for other keys): it can move with `head` unchanged, so walk on
2978
+ * either move. `epoch_reason` (keel #421, while keel's hidden mark is on; absent otherwise)
2979
+ * says why the epoch last moved, `role` or `view` (see OwChangesPage.epoch_reason).
2980
+ * keel returns the owner's cursor as a number; it is handed back as a
2915
2981
  * string, like every cursor here.
2916
2982
  */
2917
2983
  changesHead(): Promise<{
2918
2984
  head: number;
2919
2985
  cursor: string;
2920
2986
  epoch: number | null;
2987
+ epoch_reason?: OwResyncReason | null;
2921
2988
  }>;
2922
2989
  /**
2923
2990
  * Walk the feed from `since` (or from zero = full export) to the current
2924
2991
  * tail, yielding ops in order. Returns the final cursor via the generator's
2925
2992
  * return value; persist it for the next incremental pull (with the last page's
2926
- * `head` and `epoch`: the view epoch the walk ran under, for a guest).
2993
+ * `head` and `epoch`: the view epoch the walk ran under, for a guest or a contributor).
2927
2994
  */
2928
2995
  changesAll(since?: string): AsyncGenerator<OwChange, {
2929
2996
  cursor: string;
@@ -4249,4 +4316,4 @@ declare class TokenResource {
4249
4316
  getEncryptionInfo(): Promise<EncryptionInfo>;
4250
4317
  }
4251
4318
 
4252
- 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 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 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 };
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 };
package/dist/index.js CHANGED
@@ -103,15 +103,33 @@ var OwApiError = class extends Error {
103
103
  return this.status === 409 && this.code === "id_conflict";
104
104
  }
105
105
  /**
106
- * `/changes` refused the cursor (409 `resync_required`): a guest's view of the world
107
- * changed, or the key's role did (a guest's cursor has another shape). Drop the stored
108
- * cursor, walk again from the start, and keep what the local copy holds that the new walk
109
- * does not name: a reset never empties a copy (keel PR 104, the Captain's ruling: sharing
110
- * is forward-only).
106
+ * `/changes` refused the cursor (409 `resync_required`): what this key may see changed
107
+ * (a guest's slice moved; an element hidden from a contributor was unhidden; the key's role
108
+ * moved to or from guest or contributor, whose cursors have other shapes; keel #421). Drop
109
+ * the stored cursor and walk again from the start. What to do with what the local copy holds
110
+ * that the new walk does not name is `resyncReason`'s: `role`, keep it; `view`, drop it.
111
+ * Without a reason (keel's hidden mark off), keep it: a reset never empties a copy (keel PR
112
+ * 104, the Captain's ruling: sharing is forward-only). Never empty the copy on your own.
111
113
  */
112
114
  get isResyncRequired() {
113
115
  return this.status === 409 && this.code === "resync_required";
114
116
  }
117
+ /**
118
+ * Why `/changes` refused the cursor, from the 409 `resync_required` envelope's `reason`
119
+ * (keel #421, only while keel's hidden mark is on): `role` (this key's own role or
120
+ * membership moved: keep what the local copy holds that the new walk does not name; it is
121
+ * out of view now, not gone) or `view` (something left this key's view: a delete, a hide, an
122
+ * unhide, a Character change; drop what the new walk does not name). When both happened
123
+ * since the cursor, keel says `role`. Undefined for any other error, or when keel sends no
124
+ * reason.
125
+ */
126
+ get resyncReason() {
127
+ if (!this.isResyncRequired) return void 0;
128
+ const env = this.detail && typeof this.detail === "object" ? this.detail : void 0;
129
+ const nested = env?.error && typeof env.error === "object" ? env.error : void 0;
130
+ const reason = nested?.reason;
131
+ return reason === "role" || reason === "view" ? reason : void 0;
132
+ }
115
133
  /** keel's admission control turned the request away (503 `server_busy`); see retryAfter. */
116
134
  get isBusy() {
117
135
  return this.status === 503 && this.code === "server_busy";
@@ -134,6 +152,14 @@ var OwApiError = class extends Error {
134
152
  get isOwnerOnly() {
135
153
  return this.status === 403 && this.code === "owner_only";
136
154
  }
155
+ /**
156
+ * A member key sent `viewAs` (403 `view_as_owner_only`, keel #421): reading as another
157
+ * reader is the owner's, from a key with no member. Retrying will not help. Only while
158
+ * keel's hidden mark is on; until then `viewAs` is an unknown parameter (422).
159
+ */
160
+ get isViewAsOwnerOnly() {
161
+ return this.status === 403 && this.code === "view_as_owner_only";
162
+ }
137
163
  /**
138
164
  * A `patch` or `editLinks` sent with `ifMatch` found the element moved past that
139
165
  * `change_seq` (412 `precondition_failed`, keel #210): nothing was written and nothing
@@ -342,7 +368,8 @@ var OwV2Client = class {
342
368
  cursor: params.cursor,
343
369
  expand: params.expand?.join(","),
344
370
  fields: params.fields?.join(","),
345
- ...params.filter
371
+ ...params.filter,
372
+ as: params.viewAs
346
373
  });
347
374
  return this.request("GET", `/${type}/`, { query });
348
375
  }
@@ -355,9 +382,12 @@ var OwV2Client = class {
355
382
  cursor = page.has_more && page.next_cursor ? page.next_cursor : void 0;
356
383
  } while (cursor);
357
384
  }
358
- /** GET /{type}/{id}/ -- optional one-level stub expansion / sparse fields. */
385
+ /**
386
+ * GET /{type}/{id}/ -- optional one-level stub expansion / sparse fields, and `viewAs` (keel
387
+ * #421: the owner reads as another reader; see ListParams.viewAs).
388
+ */
359
389
  async get(type, id, opts = {}) {
360
- const query = buildQuery({ expand: opts.expand?.join(","), fields: opts.fields?.join(",") });
390
+ const query = buildQuery({ expand: opts.expand?.join(","), fields: opts.fields?.join(","), as: opts.viewAs });
361
391
  return this.request("GET", `/${type}/${id}/`, { query });
362
392
  }
363
393
  /**
@@ -454,15 +484,18 @@ var OwV2Client = class {
454
484
  // -- Changes feed --------------------------------------------------------
455
485
  /**
456
486
  * GET /changes -- one page of the world's ordered change feed.
457
- * Cursor is OPAQUE: persist verbatim, never parse or build one (a guest's has
458
- * another shape than everyone else's).
487
+ * Cursor is OPAQUE: persist verbatim, never parse or build one (a guest's and a
488
+ * contributor's carry their view's epoch, since keel #421 for a contributor).
459
489
  * Zero/absent cursor = full export (byte-aligned with the Folder Format).
460
490
  * Reset rule: a 409 `resync_required` (err.isResyncRequired) means the key's
461
- * view changed (a guest's, or its role): drop the cursor, walk from zero, and keep what the
462
- * local copy holds that the new walk does not name (keel's own words; sharing is forward-only).
491
+ * view changed (a guest's slice, an element unhidden from a contributor, or its role): drop
492
+ * the cursor and walk from zero. For what the local copy holds that the walk no longer names,
493
+ * read err.resyncReason (keel #421, while keel's hidden mark is on): `role`, keep it; `view`,
494
+ * drop it (as for a delete row with reason `hidden`). Without a reason, keep it (keel's own
495
+ * words since PR 104; sharing is forward-only). Never empty a copy on your own.
463
496
  * Citizenship: heaviest route on the platform; default page size is polite.
464
- * keel sends the cursor of a page at the head as a number (an empty page, for anyone
465
- * but a guest); it is handed back as a string, like every cursor here.
497
+ * keel sends the cursor of a page at the head as a number (an empty page, for a key
498
+ * whose cursor carries no epoch); it is handed back as a string, like every cursor here.
466
499
  */
467
500
  async changes(opts = {}) {
468
501
  const query = buildQuery({ since: opts.since, limit: opts.limit ?? this.changesPageSize });
@@ -472,23 +505,27 @@ var OwV2Client = class {
472
505
  /**
473
506
  * GET /changes?head=true -- where the feed is now, without a page: no element is read.
474
507
  * `head` is the world's change_seq; `cursor` is a position to pass as `since` that
475
- * re-sends nothing at the head (a guest's carries its view's epoch). The cheap "anything
508
+ * re-sends nothing at the head (a guest's or a contributor's carries its view's epoch). The cheap "anything
476
509
  * new?" for a poll: compare `head` with the head you last APPLIED (not the previous
477
510
  * poll's, so a missed tick never drops a change) and walk changesAll only when it moved;
478
511
  * a head below yours means the server rewound: walk again from zero. `epoch` is a
479
- * guest's view epoch (null for other keys): it can move with `head` unchanged, so walk on
480
- * either move. keel returns the owner's cursor as a number; it is handed back as a
512
+ * guest's or a contributor's view epoch (null for other keys): it can move with `head` unchanged, so walk on
513
+ * either move. `epoch_reason` (keel #421, while keel's hidden mark is on; absent otherwise)
514
+ * says why the epoch last moved, `role` or `view` (see OwChangesPage.epoch_reason).
515
+ * keel returns the owner's cursor as a number; it is handed back as a
481
516
  * string, like every cursor here.
482
517
  */
483
518
  async changesHead() {
484
519
  const page = await this.request("GET", "/changes/", { query: buildQuery({ head: "true" }) });
485
- return { head: page.head, cursor: String(page.cursor), epoch: page.epoch ?? null };
520
+ const out = { head: page.head, cursor: String(page.cursor), epoch: page.epoch ?? null };
521
+ if (page.epoch_reason !== void 0) out.epoch_reason = page.epoch_reason;
522
+ return out;
486
523
  }
487
524
  /**
488
525
  * Walk the feed from `since` (or from zero = full export) to the current
489
526
  * tail, yielding ops in order. Returns the final cursor via the generator's
490
527
  * return value; persist it for the next incremental pull (with the last page's
491
- * `head` and `epoch`: the view epoch the walk ran under, for a guest).
528
+ * `head` and `epoch`: the view epoch the walk ran under, for a guest or a contributor).
492
529
  */
493
530
  async *changesAll(since) {
494
531
  let cursor = since;
@@ -1234,7 +1271,7 @@ function buildQuery(params) {
1234
1271
 
1235
1272
  // src/v2/types.generated.ts
1236
1273
  var ELEMENT_TYPES = ["ability", "character", "collective", "construct", "creature", "event", "family", "institution", "language", "law", "location", "map", "marker", "narrative", "object", "phenomenon", "pin", "relation", "species", "title", "trait", "zone"];
1237
- var ONLYWORLDS_VERSION = "00.32.00";
1274
+ var ONLYWORLDS_VERSION = "00.32.01";
1238
1275
  var ELEMENT_FAMILIES = {
1239
1276
  ability: "abstract",
1240
1277
  character: "agents",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlyworlds/sdk",
3
- "version": "4.36.2",
3
+ "version": "4.38.0",
4
4
  "description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
5
5
  "type": "module",
6
6
  "exports": {