@onlyworlds/sdk 4.71.0 → 4.72.1

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.33.0-dist.57** (canonical 00.33.00).
3
+ **Current as of**: SDK **4.x** · schema-dist **v0.33.0-dist.59** (canonical 00.33.00).
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
 
@@ -56,6 +56,11 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
56
56
  account's daily token rating (`tokens_remaining`, `token_rating`; `remaining` counts answers of
57
57
  this size still in it); used up → `err.isQuotaExceeded`. `isAskUnavailable`, `isAskFailed`
58
58
  count nothing. Custom fields (`x_*`) are in the lookup and the context; `atlas_*` is not.
59
+ Since 4.72.0 `buildAskContext` leaves proposed (`x_review_proposed` not absent or null), hidden
60
+ (`hidden` not absent, null or false) and room elements out unless asked
61
+ (`{ includeProposed, includeHidden, includeRoom }`), lists their ids in `leftOut.proposed`,
62
+ `.hidden`, `.room` (hidden and proposed: under `hidden` only), and labels a proposed element it
63
+ sends `[proposed, not yet reviewed]` on its first line; say how many were held back.
59
64
  - Sort (since 4.18.0, account token): `account.sort({ worldId, notes, slice })` turns unsorted
60
65
  notes (text, or a picture already uploaded into the world) into rows to review: `make`,
61
66
  `add_to`, `link`, `ask`, plus `not_proposed` with reasons. Ids come only from your `slice`
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ earlier history lives in git log only.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [4.72.1] - 2026-10-24
9
+
10
+ ### Fixed
11
+
12
+ - **`readWorldFile` refuses a deflate stream that ends before its entry's declared compressed size** (folder spec §4.7, OW-14, its size bullet; ruled 2026-10-24, published at schema-dist serial 58). The size bullet speaks of every size an entry declares, the compressed one too. fflate stopped at the stream's end and ignored the bytes after it, so an entry whose stream ended four bytes early, those bytes junk and its sizes and CRC honest, was read (`fail-OW-14-deflate-early-end`); it is now `not_openable`. fflate never says where a stream ended, so each deflated entry is inflated twice: once whole, as before, then again short of its last byte (in 64 KiB chunks past that size, the output dropped), where a stream that ends at its declared size runs out and fflate refuses it, and one that ends sooner still inflates. A stream that never ends (`fail-OW-14-deflate-no-end`) was already refused, as `not_openable`. A world file whose streams end where their entries say reads as before.
13
+ - Tests: the whole `.owworld` set, 96 cases, through the reader, the count floor 96; built streams with 1 and 4 junk bytes after their end, short and past 64 KiB, refused, and the same streams with nothing after them read. The three zips the fix was tested on before the serial was vendored (`test/fixtures/owworld-next/`) are gone: the set carries them.
14
+
15
+ ### Changed
16
+
17
+ - **Schema repinned to schema-dist `v0.33.0-dist.59`** (commit a40a5f3; same canonical 00.33.00; no schema file moved, `schema.json` and `presentation.json` unchanged, no generated type changed, `ONLYWORLDS_VERSION` still `'00.33.00'`; generated output moves only its source header and SCHEMA.md's line). Serials 58 and 59 together bring what follows; 59's own change is text only (the set's generator and verdicts regenerated with the same 96 zips byte for byte, and the profile pages, the checks fixture's note and the folder lint say when a rule was ruled). The `.owworld` set at 96 zips: the two deflate cases above, and `pass-OW-18-nfc-unassigned`, U+11383 beside U+11382 U+113C9, two names at Unicode 15.1, which 4.71.0's `nfc` already keeps apart; none of the earlier 93 zips moved. The spine profile's serial-58 sentences: `x_spine_owner` the keeping seat's name, the projection's World mark `x_spine_projection`, the audit's one Seat and folded-name uniqueness, the Retirement Event's typed link. The dist's README, LICENSE and SECURITY.md, written by its publisher.
18
+
19
+ ## [4.72.0] - 2026-10-24
20
+
21
+ ### Changed
22
+
23
+ - **`buildAskContext` now leaves proposed, hidden and room elements out of the context unless asked.** A caller that passes such elements gets fewer items in `context` and `kept` than before: an element whose `x_review_proposed` is anything but absent or null (the review profile, rules 1 and 4: a value that is not a proper mark is a doubt and counts as proposed), one whose `hidden` is anything but absent, null or false (folder format §4.8, the same test as `writeWorldFile`'s `includeHidden`), and a room element (`isRoomElement`, the room profile, rules 1 and 4) are not sent. Their ids come back in the new `leftOut: { proposed, hidden, room }`, in the order given, so a tool can say how many it held back. An element carrying more than one mark is listed once, in the first of hidden, proposed, room whose option is off: a hidden proposed element is under `hidden`, so `includeProposed` alone never sends it. A sent element's link to an element a mark leaves out, anywhere in the index, reads as "not present in the world data", never by its name. `dropped` keeps its meaning (the 8 items and the 12,000 characters), counted over what remains. Until now the SDK relied on the caller (Lantern) to filter first; the rules bind the exported function itself.
24
+
25
+ ### Added
26
+
27
+ - **`buildAskContext(items, index, { includeProposed, includeHidden, includeRoom })`**, each default false: true sends that kind again. A proposed element sent carries the review profile's label on its first line, `[proposed, not yet reviewed] Name (type)`, where the AI reading the text sees it. An option that is not a boolean is a TypeError, and an unknown key is refused by name (the options fence, `test/options.test.mjs`). Types `OwAskContextOptions` and `OwAskLeftOut`.
28
+ - **`REVIEW_PROPOSED_LABEL`** (`'proposed, not yet reviewed'`), generated into `types.generated.ts` from rule 1's own sentence in the vendored `profiles/review.md` ("labels each one it keeps **"…"**"); codegen exits 1 if the sentence is missing or occurs twice.
29
+ - **`minted_by: string | null` on `OwWorldLink` and `OwCreatedWorldLink`** (keel PR 215): the membership (its id in GET /api/v2/members) of the co-builder who minted the link over POST /api/v2/links; null for a link the owner made. Served by `createWorldLink` and `listWorldLinks`. No client for `/api/v2/links` itself yet.
30
+ - Tests: each mark left out by default and listed; `hidden` as §4.8 reads it (`"true"` and 1 out, false and null in); a doubt (`"yes"`, `{}`) treated as proposed and labelled when asked, a cleared `null` settled; each `include*` bringing back its own kind only; the label on the first line; a hidden proposed element counted once, under hidden; a kept element's links to a hidden element and from a room element read without their names; the limits over what remains; the fence and the boolean check. Ten mutants, each red on its own test: no proposed filter, no hidden filter, no room filter, no label, a doubt not proposed, proposed checked before hidden, left-out elements counted toward the total, no link view, no option fence, no boolean check.
31
+
8
32
  ## [4.71.0] - 2026-10-24
9
33
 
10
34
  ### Added
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024-2025 OnlyWorlds
3
+ Copyright (c) 2021-2026 Titus Oosting
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  OnlyWorlds is an open standard for worldbuilding data: 22 element types (characters, locations, events, laws and the rest) that any tool can read and write. This is a typed client for its API, with the schema's constants (element types, icons, colour families, field metadata) generated from the published [schema distribution](https://github.com/OnlyWorlds/schema-dist). It runs in Node 18+ and in the browser through a bundler (ESM only).
7
7
 
8
+ **Who writes this repository.** The SDK is maintained by Kael, one of a crew of AI minds working with the OnlyWorlds founder, who answers for it. Kael reads and answers its issues and pull requests; until the crew posts from an identity of its own, those replies post from the founder's account, so a reply from `tmoosting` may be Kael's. `CHANGELOG.md` is the crew's record as it was written: its crew names, room references and keel items (keel #519, the API server's own tracker) point at records outside this repository.
9
+
8
10
  ## Install
9
11
 
10
12
  ```bash
@@ -247,11 +249,13 @@ To have an answer written from what you found, OnlyWorlds runs a small AI proxy
247
249
 
248
250
  ```typescript
249
251
  const shown = hits.slice(0, 8); // what your screen lists
250
- const { context, kept } = buildAskContext(shown, index); // within the proxy's limits; kept = what was sent
252
+ const { context, kept, leftOut } = buildAskContext(shown, index); // within the proxy's limits; kept = what was sent
251
253
  const reply = await account.ask({ worldId, question, context }); // account: a client with an ow_a_ token
252
254
  reply.answer; // from those elements only, or "The world doesn't say."
253
255
  ```
254
256
 
257
+ `buildAskContext` hands world elements to an AI, so it leaves three kinds out unless you ask (since 4.72.0): elements marked proposed (`x_review_proposed` anything but absent or null), elements marked hidden (`hidden` anything but absent, null or false) and room elements (`isRoomElement`). Their ids come back in `leftOut.proposed`, `leftOut.hidden` and `leftOut.room`, so you can say how many were held back; an element both hidden and proposed is listed under `hidden` only. Pass `{ includeProposed: true }`, `{ includeHidden: true }` or `{ includeRoom: true }` to send them; a proposed element sent carries `[proposed, not yet reviewed]` (`REVIEW_PROPOSED_LABEL`) on its first line. A sent element's link to one left out reads as not present, never by its name. `dropped` stays the proxy's limits: past the 8th, or past the 12,000 characters, counted over what remains.
258
+
255
259
  The same proxy sorts loose notes into changes for the user to review. Send the elements your own lookup found for them as the `slice`; every id in a row comes from it, and nothing is written until your app applies what the user accepts.
256
260
 
257
261
  ```typescript
@@ -398,6 +402,6 @@ Use this SDK for known operations in your own code (CRUD, sync, bulk). To let an
398
402
 
399
403
  [Docs](https://onlyworlds.github.io/docs/development/typescript) · [Games](https://onlyworlds.github.io/docs/development/games) · [API reference](https://www.onlyworlds.com/api/docs) · [Issues](https://github.com/OnlyWorlds/sdk/issues) · [Changelog](CHANGELOG.md)
400
404
 
401
- ## License
405
+ ## Licence and contributions
402
406
 
403
- MIT
407
+ The code is MIT (`LICENSE`). Issues are welcome: a bug, a wrong word, a thing you could not do. Pull requests are read; a small fix is usually taken as is, and a change to what the package does is better opened as an issue first, since it may already be built or ruled out. A reply can take a few days. A vulnerability goes privately, never in an issue: `SECURITY.md`.
package/SCHEMA.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # OnlyWorlds Schema Reference
2
2
 
3
- **Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.33.0-dist.57** — canonical schema **00.33.00**, published 2026-10-24.
3
+ **Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.33.0-dist.59** — canonical schema **00.33.00**, published 2026-10-24.
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.
package/dist/index.d.ts CHANGED
@@ -102,6 +102,12 @@ declare const ROOM_PAIRS: ReadonlyArray<{
102
102
  readonly type: ElementType;
103
103
  readonly supertype: string;
104
104
  }>;
105
+ /** The review profile's label (schema-dist `profiles/review.md`, rule 1): the words a reader that
106
+ * hands a world on (a context for an AI, a pack, a share) puts on each proposed element it keeps,
107
+ * one whose `x_review_proposed` is anything but absent or null (a doubt, rule 4, included).
108
+ * buildAskContext writes it on the element's first line. Source: rule 1's own sentence, read at
109
+ * codegen. */
110
+ declare const REVIEW_PROPOSED_LABEL: "proposed, not yet reviewed";
105
111
  /** Field type definitions for OnlyWorlds elements. */
106
112
  type FieldType = 'text' | 'integer'
107
113
  /**
@@ -2635,6 +2641,8 @@ interface OwWorldLink {
2635
2641
  uses: number;
2636
2642
  /** A table is `pending` while `uses < max_uses` (and neither revoked nor expired), `used` once full. */
2637
2643
  status: 'pending' | 'used' | 'revoked' | 'expired';
2644
+ /** The membership (its id in GET /api/v2/members) of the co-builder who minted the link over POST /api/v2/links; null for a link the owner made (keel PR 215). */
2645
+ minted_by: string | null;
2638
2646
  /** 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. */
2639
2647
  preview?: boolean;
2640
2648
  /** 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). */
@@ -4285,7 +4293,7 @@ declare class OwV2Client {
4285
4293
  /**
4286
4294
  * POST /account/ask -- a question about a world the account owns or is in, answered by
4287
4295
  * keel's AI proxy from `context` only (build it with buildAskContext from the elements
4288
- * the user sees). The answer is "The world doesn't say." when the context does not hold
4296
+ * the user sees; it leaves proposed, hidden and room elements out unless asked). The answer is "The world doesn't say." when the context does not hold
4289
4297
  * it. Needs the client's `ow_a_` token (a world key is a TypeError before sending).
4290
4298
  * Refusals: 429 `quota_exceeded` (`err.isQuotaExceeded`, the account's token rating used up for the day;
4291
4299
  * Retry-After runs to midnight UTC), 503 `ask_unavailable` (`err.isAskUnavailable`:
@@ -4814,11 +4822,20 @@ declare function renderElement<T extends OwLookupElement>(element: T, index: OwW
4814
4822
  * the answer's sources are what the user saw, never a second lookup's.
4815
4823
  *
4816
4824
  * const hits = lookupWorld(index, question).slice(0, 8); // what the screen lists
4817
- * const { context, kept } = buildAskContext(hits, index);
4825
+ * const { context, kept, leftOut } = buildAskContext(hits, index);
4818
4826
  * const reply = await account.ask({ worldId, question, context });
4819
4827
  *
4828
+ * It is a reader that hands a world on, so three published rules hold here, not only in
4829
+ * the caller: an element marked proposed (the review profile, rules 1 and 4: any
4830
+ * `x_review_proposed` but absent or null, a doubt included), one marked hidden (folder
4831
+ * format §4.8: a `hidden` but absent, null or false) and a room element (the room
4832
+ * profile, rules 1 and 4: `isRoomElement`) are left out unless asked for, and listed in
4833
+ * `leftOut`. A kept proposed element carries REVIEW_PROPOSED_LABEL on its first line. A
4834
+ * kept element's link to one left out reads as not present, never by its name.
4835
+ *
4820
4836
  * The limits are keel's (accounts/ask.py), counted the way keel counts (characters,
4821
- * not UTF-16 units): at most 8 items, 2,000 characters each, 12,000 in all.
4837
+ * not UTF-16 units): at most 8 items, 2,000 characters each, 12,000 in all. They apply
4838
+ * to what remains after the three rules.
4822
4839
  */
4823
4840
 
4824
4841
  /** keel's limits on one ask. */
@@ -4828,23 +4845,56 @@ declare const ASK_LIMITS: {
4828
4845
  readonly itemMax: 2000;
4829
4846
  readonly totalMax: 12000;
4830
4847
  };
4848
+ interface OwAskContextOptions {
4849
+ /**
4850
+ * Send proposed elements: those whose `x_review_proposed` is anything but absent or null
4851
+ * (the review profile; a value that is not a proper mark is a doubt, rule 4, and counts as
4852
+ * proposed). Each one sent carries REVIEW_PROPOSED_LABEL on its first line. Default false:
4853
+ * left out and listed in `leftOut.proposed`.
4854
+ */
4855
+ includeProposed?: boolean;
4856
+ /**
4857
+ * Send elements marked hidden: a `hidden` that is anything but absent, null or false (folder
4858
+ * format §4.8, the same test as writeWorldFile's `includeHidden`). Default false: left out and
4859
+ * listed in `leftOut.hidden`.
4860
+ */
4861
+ includeHidden?: boolean;
4862
+ /** Send room elements (`isRoomElement`, the room profile). Default false: left out and listed in `leftOut.room`. */
4863
+ includeRoom?: boolean;
4864
+ }
4865
+ /** Ids left out by a mark, in the order given. An element carrying several marks is listed once, in the first of hidden, proposed, room whose `include*` is off. */
4866
+ interface OwAskLeftOut {
4867
+ proposed: string[];
4868
+ hidden: string[];
4869
+ room: string[];
4870
+ }
4831
4871
  interface OwAskContext {
4832
4872
  /** The texts to send as `context`, in the order given. */
4833
4873
  context: string[];
4834
4874
  /** Ids of the elements sent, in order (one per `context` item). */
4835
4875
  kept: string[];
4836
- /** Ids of the elements left out: past the 8th, or from the first one the 12,000 total could not hold. */
4876
+ /** Ids of the elements the limits left out: past the 8th, or from the first one the 12,000 total could not hold. Never an element `leftOut` holds. */
4837
4877
  dropped: string[];
4838
4878
  /** Ids among `kept` whose text was cut to 2,000 characters. */
4839
4879
  truncated: string[];
4880
+ /** Ids of the elements a mark left out (proposed, hidden, room), before the limits were counted. */
4881
+ leftOut: OwAskLeftOut;
4840
4882
  }
4841
4883
  /**
4842
4884
  * Turn the elements on screen into the proxy's `context`. Takes lookup hits or plain
4843
- * elements, keeps their order, renders each with `renderElement`, cuts a text over
4844
- * 2,000 characters, and stops at the 8th or at the first one the 12,000 total cannot
4845
- * hold, so what is sent is always the top of the list as shown.
4885
+ * elements and keeps their order. First the three marks: an element marked hidden
4886
+ * (§4.8), proposed (the review profile, a doubt included) or a room element (the room
4887
+ * profile) is left out unless its `include*` option is true, and its id goes to
4888
+ * `leftOut` (one bucket each, in the order hidden, proposed, room: a hidden proposed
4889
+ * element is listed under `hidden` only, since the owner's hide is the stronger
4890
+ * withholding and `includeProposed` alone never sends it). Then each remaining element
4891
+ * is rendered with `renderElement` (a proposed one with REVIEW_PROPOSED_LABEL on its
4892
+ * first line; a link to an element a mark leaves out, anywhere in the index, reads as
4893
+ * not present), a text over 2,000 characters is cut, and the list stops at the 8th or
4894
+ * at the first the 12,000 total cannot hold, so what is sent is always the top of the
4895
+ * list as shown. An unknown option, or one that is not a boolean, is a TypeError.
4846
4896
  */
4847
- declare function buildAskContext<T extends OwLookupElement>(items: Array<OwLookupHit<T> | T>, index: OwWorldIndex<T>): OwAskContext;
4897
+ declare function buildAskContext<T extends OwLookupElement>(items: Array<OwLookupHit<T> | T>, index: OwWorldIndex<T>, opts?: OwAskContextOptions): OwAskContext;
4848
4898
 
4849
4899
  /**
4850
4900
  * Photo preparation: make a picture from a phone's camera or files ready for
@@ -5483,4 +5533,4 @@ declare class TokenResource {
5483
5533
  getEncryptionInfo(): Promise<EncryptionInfo>;
5484
5534
  }
5485
5535
 
5486
- 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 OwDraughtCompact, 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, type OwWriteWorldFileReport, 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, nfc, parseDate, parseErrorEnvelope, pinExpectation, pkceChallenge, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, simpleCaseFold, typeWord, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
5536
+ 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 OwAskContextOptions, type OwAskLeftOut, 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 OwDraughtCompact, 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, type OwWriteWorldFileReport, PHOTO_MAX_BYTES, PHOTO_TYPES, PUBLIC_FIELDS, type ParseError, type ParseOptions, type ParseResult, REVIEW_PROPOSED_LABEL, 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, nfc, 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
@@ -1746,7 +1746,7 @@ var OwV2Client = class {
1746
1746
  /**
1747
1747
  * POST /account/ask -- a question about a world the account owns or is in, answered by
1748
1748
  * keel's AI proxy from `context` only (build it with buildAskContext from the elements
1749
- * the user sees). The answer is "The world doesn't say." when the context does not hold
1749
+ * the user sees; it leaves proposed, hidden and room elements out unless asked). The answer is "The world doesn't say." when the context does not hold
1750
1750
  * it. Needs the client's `ow_a_` token (a world key is a TypeError before sending).
1751
1751
  * Refusals: 429 `quota_exceeded` (`err.isQuotaExceeded`, the account's token rating used up for the day;
1752
1752
  * Retry-After runs to midnight UTC), 503 `ask_unavailable` (`err.isAskUnavailable`:
@@ -2244,6 +2244,7 @@ var ROOM_PAIRS = [
2244
2244
  { type: "character", supertype: "Member" }
2245
2245
  ];
2246
2246
  var ROOM_MARK = "x_room_of";
2247
+ var REVIEW_PROPOSED_LABEL = "proposed, not yet reviewed";
2247
2248
  var FIELD_SCHEMA = {
2248
2249
  ability: {
2249
2250
  // Base fields (shared by all elements)
@@ -3277,6 +3278,24 @@ function crc32(data) {
3277
3278
  return (c ^ -1) >>> 0;
3278
3279
  }
3279
3280
  var CHUNK = 64 * 1024;
3281
+ function endsEarly(payload) {
3282
+ const short = payload.subarray(0, payload.length - 1);
3283
+ try {
3284
+ if (short.length <= CHUNK) {
3285
+ inflateSync(short);
3286
+ } else {
3287
+ const inf = new Inflate(() => {
3288
+ });
3289
+ for (let i = 0; i < short.length; i += CHUNK) {
3290
+ const stop = Math.min(i + CHUNK, short.length);
3291
+ inf.push(short.subarray(i, stop), stop === short.length);
3292
+ }
3293
+ }
3294
+ } catch {
3295
+ return false;
3296
+ }
3297
+ return true;
3298
+ }
3280
3299
  function inflateEntry(bytes, e) {
3281
3300
  const off = e.offset;
3282
3301
  if (off + 30 > bytes.length || u32(bytes, off) !== SIG_LOCAL) refuse("not_openable", `${e.name}: no local header at its offset.`);
@@ -3315,6 +3334,9 @@ function inflateEntry(bytes, e) {
3315
3334
  }
3316
3335
  if (data.length > e.usize) refuse("too_big", `${e.name} holds more than the ${e.usize} bytes it declares.`);
3317
3336
  if (data.length !== e.usize) refuse("not_openable", `${e.name} holds ${data.length} bytes and declares ${e.usize}.`);
3337
+ if (e.method !== 0 && payload.length > 0 && endsEarly(payload)) {
3338
+ refuse("not_openable", `${e.name}: its deflate stream ends before its declared compressed size.`);
3339
+ }
3318
3340
  if (crc32(data) !== e.crc) refuse("not_openable", `${e.name} fails its CRC.`);
3319
3341
  return e.method === 0 ? data.slice() : data;
3320
3342
  }
@@ -4118,19 +4140,60 @@ function renderElement(element, index, opts = {}) {
4118
4140
 
4119
4141
  // src/ask.ts
4120
4142
  var ASK_LIMITS = { questionMax: 500, itemsMax: 8, itemMax: 2e3, totalMax: 12e3 };
4143
+ var ASK_OPTION_KEYS = ["includeProposed", "includeHidden", "includeRoom"];
4121
4144
  var chars = (s) => [...s].length;
4122
4145
  var cut = (s, n) => [...s].slice(0, n).join("");
4123
- function buildAskContext(items, index) {
4124
- const out = { context: [], kept: [], dropped: [], truncated: [] };
4146
+ var isHidden = (el) => el.hidden !== void 0 && el.hidden !== null && el.hidden !== false;
4147
+ var isProposed = (el) => el.x_review_proposed !== void 0 && el.x_review_proposed !== null;
4148
+ function readOptions(opts) {
4149
+ refuseUnknownOptions("buildAskContext", opts, ASK_OPTION_KEYS);
4150
+ const o = opts ?? {};
4151
+ for (const k of ASK_OPTION_KEYS) {
4152
+ if (o[k] !== void 0 && typeof o[k] !== "boolean") {
4153
+ throw new TypeError(`buildAskContext: ${k} must be a boolean; got ${JSON.stringify(o[k]) ?? String(o[k])}.`);
4154
+ }
4155
+ }
4156
+ return { includeProposed: o.includeProposed === true, includeHidden: o.includeHidden === true, includeRoom: o.includeRoom === true };
4157
+ }
4158
+ function buildAskContext(items, index, opts = {}) {
4159
+ const o = readOptions(opts);
4160
+ const markOf = (el) => {
4161
+ if (!o.includeHidden && isHidden(el)) return "hidden";
4162
+ if (!o.includeProposed && isProposed(el)) return "proposed";
4163
+ if (!o.includeRoom && isRoomElement(el)) return "room";
4164
+ return null;
4165
+ };
4166
+ const withheld = (id) => {
4167
+ const el = index.byId.get(id);
4168
+ return el !== void 0 && markOf(el) !== null;
4169
+ };
4170
+ const viewFor = (el) => {
4171
+ const out2 = index.out.get(el.id) ?? [];
4172
+ const gone = out2.filter((l) => withheld(l.id));
4173
+ if (!gone.length && !(index.inn.get(el.id) ?? []).some((l) => withheld(l.id))) return index;
4174
+ return {
4175
+ ...index,
4176
+ out: /* @__PURE__ */ new Map([[el.id, out2.filter((l) => !withheld(l.id))]]),
4177
+ inn: /* @__PURE__ */ new Map([[el.id, (index.inn.get(el.id) ?? []).filter((l) => !withheld(l.id))]]),
4178
+ unresolved: /* @__PURE__ */ new Map([[el.id, [...index.unresolved.get(el.id) ?? [], ...gone]]])
4179
+ };
4180
+ };
4181
+ const out = { context: [], kept: [], dropped: [], truncated: [], leftOut: { proposed: [], hidden: [], room: [] } };
4125
4182
  let total = 0;
4126
4183
  let full = false;
4127
4184
  for (const item of items) {
4128
4185
  const el = item && typeof item === "object" && "element" in item ? item.element : item;
4186
+ const mark = markOf(el);
4187
+ if (mark) {
4188
+ out.leftOut[mark].push(el.id);
4189
+ continue;
4190
+ }
4129
4191
  if (full || out.context.length >= ASK_LIMITS.itemsMax) {
4130
4192
  out.dropped.push(el.id);
4131
4193
  continue;
4132
4194
  }
4133
- let text = renderElement(el, index);
4195
+ let text = renderElement(el, viewFor(el));
4196
+ if (isProposed(el)) text = `[${REVIEW_PROPOSED_LABEL}] ${text}`;
4134
4197
  if (chars(text) > ASK_LIMITS.itemMax) {
4135
4198
  text = cut(text, ASK_LIMITS.itemMax);
4136
4199
  out.truncated.push(el.id);
@@ -4889,6 +4952,7 @@ export {
4889
4952
  PHOTO_MAX_BYTES,
4890
4953
  PHOTO_TYPES,
4891
4954
  PUBLIC_FIELDS,
4955
+ REVIEW_PROPOSED_LABEL,
4892
4956
  ROOM_PAIRS,
4893
4957
  SPATIAL_TYPES,
4894
4958
  TokenResource,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlyworlds/sdk",
3
- "version": "4.71.0",
3
+ "version": "4.72.1",
4
4
  "description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
5
5
  "type": "module",
6
6
  "exports": {