@onlyworlds/sdk 4.71.0 → 4.72.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
@@ -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,19 @@ earlier history lives in git log only.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [4.72.0] - 2026-10-24
9
+
10
+ ### Changed
11
+
12
+ - **`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.
13
+
14
+ ### Added
15
+
16
+ - **`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`.
17
+ - **`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.
18
+ - **`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.
19
+ - 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.
20
+
8
21
  ## [4.71.0] - 2026-10-24
9
22
 
10
23
  ### Added
package/README.md CHANGED
@@ -247,11 +247,13 @@ To have an answer written from what you found, OnlyWorlds runs a small AI proxy
247
247
 
248
248
  ```typescript
249
249
  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
250
+ const { context, kept, leftOut } = buildAskContext(shown, index); // within the proxy's limits; kept = what was sent
251
251
  const reply = await account.ask({ worldId, question, context }); // account: a client with an ow_a_ token
252
252
  reply.answer; // from those elements only, or "The world doesn't say."
253
253
  ```
254
254
 
255
+ `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.
256
+
255
257
  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
258
 
257
259
  ```typescript
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)
@@ -4118,19 +4119,60 @@ function renderElement(element, index, opts = {}) {
4118
4119
 
4119
4120
  // src/ask.ts
4120
4121
  var ASK_LIMITS = { questionMax: 500, itemsMax: 8, itemMax: 2e3, totalMax: 12e3 };
4122
+ var ASK_OPTION_KEYS = ["includeProposed", "includeHidden", "includeRoom"];
4121
4123
  var chars = (s) => [...s].length;
4122
4124
  var cut = (s, n) => [...s].slice(0, n).join("");
4123
- function buildAskContext(items, index) {
4124
- const out = { context: [], kept: [], dropped: [], truncated: [] };
4125
+ var isHidden = (el) => el.hidden !== void 0 && el.hidden !== null && el.hidden !== false;
4126
+ var isProposed = (el) => el.x_review_proposed !== void 0 && el.x_review_proposed !== null;
4127
+ function readOptions(opts) {
4128
+ refuseUnknownOptions("buildAskContext", opts, ASK_OPTION_KEYS);
4129
+ const o = opts ?? {};
4130
+ for (const k of ASK_OPTION_KEYS) {
4131
+ if (o[k] !== void 0 && typeof o[k] !== "boolean") {
4132
+ throw new TypeError(`buildAskContext: ${k} must be a boolean; got ${JSON.stringify(o[k]) ?? String(o[k])}.`);
4133
+ }
4134
+ }
4135
+ return { includeProposed: o.includeProposed === true, includeHidden: o.includeHidden === true, includeRoom: o.includeRoom === true };
4136
+ }
4137
+ function buildAskContext(items, index, opts = {}) {
4138
+ const o = readOptions(opts);
4139
+ const markOf = (el) => {
4140
+ if (!o.includeHidden && isHidden(el)) return "hidden";
4141
+ if (!o.includeProposed && isProposed(el)) return "proposed";
4142
+ if (!o.includeRoom && isRoomElement(el)) return "room";
4143
+ return null;
4144
+ };
4145
+ const withheld = (id) => {
4146
+ const el = index.byId.get(id);
4147
+ return el !== void 0 && markOf(el) !== null;
4148
+ };
4149
+ const viewFor = (el) => {
4150
+ const out2 = index.out.get(el.id) ?? [];
4151
+ const gone = out2.filter((l) => withheld(l.id));
4152
+ if (!gone.length && !(index.inn.get(el.id) ?? []).some((l) => withheld(l.id))) return index;
4153
+ return {
4154
+ ...index,
4155
+ out: /* @__PURE__ */ new Map([[el.id, out2.filter((l) => !withheld(l.id))]]),
4156
+ inn: /* @__PURE__ */ new Map([[el.id, (index.inn.get(el.id) ?? []).filter((l) => !withheld(l.id))]]),
4157
+ unresolved: /* @__PURE__ */ new Map([[el.id, [...index.unresolved.get(el.id) ?? [], ...gone]]])
4158
+ };
4159
+ };
4160
+ const out = { context: [], kept: [], dropped: [], truncated: [], leftOut: { proposed: [], hidden: [], room: [] } };
4125
4161
  let total = 0;
4126
4162
  let full = false;
4127
4163
  for (const item of items) {
4128
4164
  const el = item && typeof item === "object" && "element" in item ? item.element : item;
4165
+ const mark = markOf(el);
4166
+ if (mark) {
4167
+ out.leftOut[mark].push(el.id);
4168
+ continue;
4169
+ }
4129
4170
  if (full || out.context.length >= ASK_LIMITS.itemsMax) {
4130
4171
  out.dropped.push(el.id);
4131
4172
  continue;
4132
4173
  }
4133
- let text = renderElement(el, index);
4174
+ let text = renderElement(el, viewFor(el));
4175
+ if (isProposed(el)) text = `[${REVIEW_PROPOSED_LABEL}] ${text}`;
4134
4176
  if (chars(text) > ASK_LIMITS.itemMax) {
4135
4177
  text = cut(text, ASK_LIMITS.itemMax);
4136
4178
  out.truncated.push(el.id);
@@ -4889,6 +4931,7 @@ export {
4889
4931
  PHOTO_MAX_BYTES,
4890
4932
  PHOTO_TYPES,
4891
4933
  PUBLIC_FIELDS,
4934
+ REVIEW_PROPOSED_LABEL,
4892
4935
  ROOM_PAIRS,
4893
4936
  SPATIAL_TYPES,
4894
4937
  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.0",
4
4
  "description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
5
5
  "type": "module",
6
6
  "exports": {