@onlyworlds/sdk 4.12.0 → 4.14.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 +3 -0
- package/CHANGELOG.md +28 -0
- package/README.md +10 -1
- package/dist/index.d.ts +82 -3
- package/dist/index.js +65 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -40,6 +40,9 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
|
|
|
40
40
|
- Images: `uploadImage(bytes)` returns `{ url, ... }`; set `url` as `image_url`. The bytes go
|
|
41
41
|
to the edge with a single-use ticket from keel, never with the API key. `removeImage(urlOrKey)`
|
|
42
42
|
takes one back (its uploader or the world's owner); it leaves `image_url` on elements as is.
|
|
43
|
+
- Ask (since 4.13.0, account token): `buildAskContext(hits, index)` then
|
|
44
|
+
`account.ask({ worldId, question, context })`; answers only from the context. 50 a day per
|
|
45
|
+
account (`err.isQuotaExceeded`); `isAskUnavailable`, `isAskFailed` count nothing.
|
|
43
46
|
- Invite links (since 4.12.0): `previewJoin(code)` (no credential sent) shows who invites, to
|
|
44
47
|
which world, in what role; `acceptJoin(code)` with an `ow_a_` account token joins. Bad code:
|
|
45
48
|
`err.isNotFound`; `err.isAlreadyMember`, `err.isPinRequired` for the two 409s.
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,34 @@ earlier history lives in git log only.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.14.0] — 2026-10-12
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **The co-builder role is `co_builder` on the wire.** `OwJoinPreview.role` and
|
|
12
|
+
`OwJoinedMembership.role` listed `'co-builder'`, which is only the label keel shows (keel
|
|
13
|
+
`MemberRole.CO_BUILDER = "co_builder"`). The types were open, so nothing broke at runtime, but
|
|
14
|
+
a comparison written from them would never match. Caught by Temper from Lantern's fakes.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- `OwMemberRole` (`'co_builder' | 'contributor' | 'guest'`, open), the type both now use.
|
|
18
|
+
|
|
19
|
+
## [4.13.0] — 2026-10-12
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- **Ask your world (keel #159).** `client.ask({ worldId, question, context })` sends a
|
|
23
|
+
question to keel's AI proxy with the account's `ow_a_` token (a world key is a `TypeError`
|
|
24
|
+
before sending) and returns `OwAskAnswer` (`answer`, `model`, `stop_reason`, `usage`,
|
|
25
|
+
`remaining`). The answer comes from `context` only, or is "The world doesn't say.".
|
|
26
|
+
`buildAskContext(items, index)` turns the elements the user sees (lookup hits or plain
|
|
27
|
+
elements, in the caller's order, never re-looked-up) into that `context` within keel's
|
|
28
|
+
limits (`ASK_LIMITS`: 8 items, 2,000 characters each, 12,000 in all, counted in characters
|
|
29
|
+
as keel counts them) and says what it did: `kept`, `dropped` (past the 8th, or from the first
|
|
30
|
+
one the total cannot hold, so what is sent is always the top of the list) and `truncated`.
|
|
31
|
+
New getters: `isQuotaExceeded` (429; `retryAfter` runs to midnight UTC), `isAskUnavailable`
|
|
32
|
+
(503), `isAskFailed` (502). keel's document gives no request schema for `/account/ask`, so
|
|
33
|
+
the body (`world_id`, `question`, `context`) is read from keel's code (`accounts/ask.py`).
|
|
34
|
+
Not yet run live: no crew session holds an account token.
|
|
35
|
+
|
|
8
36
|
## [4.12.0] — 2026-10-12
|
|
9
37
|
|
|
10
38
|
### Added
|
package/README.md
CHANGED
|
@@ -161,7 +161,16 @@ hits[0].element; hits[0].reasons; // best first, with why each m
|
|
|
161
161
|
renderElement(hits[0].element, index); // a short text card, links by name
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
Names come first, then supertype and subtype, then one link step in either direction, then the elements' other text.
|
|
164
|
+
Names come first, then supertype and subtype, then one link step in either direction, then the elements' other text.
|
|
165
|
+
|
|
166
|
+
To have an answer written from what you found, OnlyWorlds runs a small AI proxy for signed-in accounts (50 questions a day):
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const shown = hits.slice(0, 8); // what your screen lists
|
|
170
|
+
const { context, kept } = buildAskContext(shown, index); // within the proxy's limits; kept = what was sent
|
|
171
|
+
const reply = await account.ask({ worldId, question, context }); // account: a client with an ow_a_ token
|
|
172
|
+
reply.answer; // from those elements only, or "The world doesn't say."
|
|
173
|
+
```
|
|
165
174
|
|
|
166
175
|
## World files
|
|
167
176
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1988,6 +1988,25 @@ interface OwRemovalTicket {
|
|
|
1988
1988
|
referenced: number;
|
|
1989
1989
|
}
|
|
1990
1990
|
/** The edge's 200 for one removal. */
|
|
1991
|
+
/**
|
|
1992
|
+
* A member's role as the wire sends it (keel `MemberRole`, accounts/models.py). `co_builder`
|
|
1993
|
+
* is the value; "co-builder" is only its label in prose. Open, so a new role still types.
|
|
1994
|
+
*/
|
|
1995
|
+
type OwMemberRole = 'co_builder' | 'contributor' | 'guest' | (string & {});
|
|
1996
|
+
/** POST /account/ask: keel's AI proxy's answer (keel #159). */
|
|
1997
|
+
interface OwAskAnswer {
|
|
1998
|
+
/** The answer, from the context only; "The world doesn't say." when it does not hold one. */
|
|
1999
|
+
answer: string;
|
|
2000
|
+
model: string;
|
|
2001
|
+
stop_reason: string | null;
|
|
2002
|
+
usage: {
|
|
2003
|
+
input_tokens: number;
|
|
2004
|
+
output_tokens: number;
|
|
2005
|
+
};
|
|
2006
|
+
/** Questions the account has left today. */
|
|
2007
|
+
remaining: number;
|
|
2008
|
+
[k: string]: unknown;
|
|
2009
|
+
}
|
|
1991
2010
|
/** POST /join/preview: what a join code holds, read without using it (keel #212). */
|
|
1992
2011
|
interface OwJoinPreview {
|
|
1993
2012
|
/** `person`: an invite link, accepted with acceptJoin. `agent`: redeemed by an AI agent at POST /join. */
|
|
@@ -2000,7 +2019,7 @@ interface OwJoinPreview {
|
|
|
2000
2019
|
invited_by: string | null;
|
|
2001
2020
|
/** The world owner's chosen Character's name, never a username; null when none is set. */
|
|
2002
2021
|
owner_character: string | null;
|
|
2003
|
-
role:
|
|
2022
|
+
role: OwMemberRole;
|
|
2004
2023
|
/** Whether joining gives the joiner a Character of their own (agent links). */
|
|
2005
2024
|
with_character: boolean | null;
|
|
2006
2025
|
/** ISO 8601, UTC. */
|
|
@@ -2013,7 +2032,7 @@ interface OwJoinedMembership {
|
|
|
2013
2032
|
id: string;
|
|
2014
2033
|
world_id: string;
|
|
2015
2034
|
world_name: string;
|
|
2016
|
-
role:
|
|
2035
|
+
role: OwMemberRole;
|
|
2017
2036
|
joined_at: string | null;
|
|
2018
2037
|
/** The id of the joiner's roster Character, or null. */
|
|
2019
2038
|
roster_character: string | null;
|
|
@@ -2176,6 +2195,12 @@ declare class OwApiError extends Error {
|
|
|
2176
2195
|
get isAlreadyMember(): boolean;
|
|
2177
2196
|
/** acceptJoin: the account has no PIN yet, and a member writes with their own (409 `pin_required`). The code is not spent. */
|
|
2178
2197
|
get isPinRequired(): boolean;
|
|
2198
|
+
/** A daily allowance is used up (429 `quota_exceeded`): the world's image tickets, or the account's asks. See retryAfter. */
|
|
2199
|
+
get isQuotaExceeded(): boolean;
|
|
2200
|
+
/** ask: the proxy is switched off, or paused for the day by the server-wide cap (503 `ask_unavailable`). Not counted. */
|
|
2201
|
+
get isAskUnavailable(): boolean;
|
|
2202
|
+
/** ask: the model gave no answer (502 `ask_failed`). Not counted; try again in a moment. */
|
|
2203
|
+
get isAskFailed(): boolean;
|
|
2179
2204
|
}
|
|
2180
2205
|
/**
|
|
2181
2206
|
* 412 `precondition_failed` (keel #210): the element changed since the `change_seq` sent as
|
|
@@ -2422,6 +2447,21 @@ declare class OwV2Client {
|
|
|
2422
2447
|
* before anything is sent.
|
|
2423
2448
|
*/
|
|
2424
2449
|
acceptJoin(code: string): Promise<OwJoinedMembership>;
|
|
2450
|
+
/**
|
|
2451
|
+
* POST /account/ask -- a question about a world the account owns or is in, answered by
|
|
2452
|
+
* keel's AI proxy from `context` only (build it with buildAskContext from the elements
|
|
2453
|
+
* the user sees). The answer is "The world doesn't say." when the context does not hold
|
|
2454
|
+
* it. Needs the client's `ow_a_` token (a world key is a TypeError before sending).
|
|
2455
|
+
* Refusals: 429 `quota_exceeded` (`err.isQuotaExceeded`, the account's daily allowance;
|
|
2456
|
+
* Retry-After runs to midnight UTC), 503 `ask_unavailable` (`err.isAskUnavailable`:
|
|
2457
|
+
* switched off, or paused for the day), 502 `ask_failed` (`err.isAskFailed`); none of
|
|
2458
|
+
* them counts. 422 for a question over 500 characters or context past its limits.
|
|
2459
|
+
*/
|
|
2460
|
+
ask(req: {
|
|
2461
|
+
worldId: string;
|
|
2462
|
+
question: string;
|
|
2463
|
+
context: string[];
|
|
2464
|
+
}): Promise<OwAskAnswer>;
|
|
2425
2465
|
/**
|
|
2426
2466
|
* Raw authenticated request against this client's baseUrl. Public since 4.0
|
|
2427
2467
|
* so auxiliary resources can ride the same transport — it structurally
|
|
@@ -2714,6 +2754,45 @@ declare function lookupWorld<T extends OwLookupElement>(index: OwWorldIndex<T>,
|
|
|
2714
2754
|
*/
|
|
2715
2755
|
declare function renderElement<T extends OwLookupElement>(element: T, index: OwWorldIndex<T>, { descMax, linkMax, incomingMax }?: OwRenderOptions): string;
|
|
2716
2756
|
|
|
2757
|
+
/**
|
|
2758
|
+
* Context for keel's AI proxy (POST /api/v2/account/ask, Keel #159): the elements a
|
|
2759
|
+
* question is about, as text, within the proxy's limits. The caller passes the
|
|
2760
|
+
* elements it shows the user, in its own order, and gets back exactly which were sent:
|
|
2761
|
+
* the answer's sources are what the user saw, never a second lookup's.
|
|
2762
|
+
*
|
|
2763
|
+
* const hits = lookupWorld(index, question).slice(0, 8); // what the screen lists
|
|
2764
|
+
* const { context, kept } = buildAskContext(hits, index);
|
|
2765
|
+
* const reply = await account.ask({ worldId, question, context });
|
|
2766
|
+
*
|
|
2767
|
+
* The limits are keel's (accounts/ask.py), counted the way keel counts (characters,
|
|
2768
|
+
* not UTF-16 units): at most 8 items, 2,000 characters each, 12,000 in all.
|
|
2769
|
+
*/
|
|
2770
|
+
|
|
2771
|
+
/** keel's limits on one ask. */
|
|
2772
|
+
declare const ASK_LIMITS: {
|
|
2773
|
+
readonly questionMax: 500;
|
|
2774
|
+
readonly itemsMax: 8;
|
|
2775
|
+
readonly itemMax: 2000;
|
|
2776
|
+
readonly totalMax: 12000;
|
|
2777
|
+
};
|
|
2778
|
+
interface OwAskContext {
|
|
2779
|
+
/** The texts to send as `context`, in the order given. */
|
|
2780
|
+
context: string[];
|
|
2781
|
+
/** Ids of the elements sent, in order (one per `context` item). */
|
|
2782
|
+
kept: string[];
|
|
2783
|
+
/** Ids of the elements left out: past the 8th, or from the first one the 12,000 total could not hold. */
|
|
2784
|
+
dropped: string[];
|
|
2785
|
+
/** Ids among `kept` whose text was cut to 2,000 characters. */
|
|
2786
|
+
truncated: string[];
|
|
2787
|
+
}
|
|
2788
|
+
/**
|
|
2789
|
+
* Turn the elements on screen into the proxy's `context`. Takes lookup hits or plain
|
|
2790
|
+
* elements, keeps their order, renders each with `renderElement`, cuts a text over
|
|
2791
|
+
* 2,000 characters, and stops at the 8th or at the first one the 12,000 total cannot
|
|
2792
|
+
* hold, so what is sent is always the top of the list as shown.
|
|
2793
|
+
*/
|
|
2794
|
+
declare function buildAskContext<T extends OwLookupElement>(items: Array<OwLookupHit<T> | T>, index: OwWorldIndex<T>): OwAskContext;
|
|
2795
|
+
|
|
2717
2796
|
/**
|
|
2718
2797
|
* Photo preparation: make a picture from a phone's camera or files ready for
|
|
2719
2798
|
* `uploadImage` (webp, png, jpeg or avif, at most 15 MB), in the browser,
|
|
@@ -3063,4 +3142,4 @@ declare class TokenResource {
|
|
|
3063
3142
|
getEncryptionInfo(): Promise<EncryptionInfo>;
|
|
3064
3143
|
}
|
|
3065
3144
|
|
|
3066
|
-
export { type AccessKeyResponse, ELEMENT_FAMILIES, ELEMENT_ICONS, ELEMENT_LABELS, ELEMENT_SECTIONS, ELEMENT_TYPES, type ElementFamily, type ElementType, type EncryptionInfo, FAMILY_COLORS, FAMILY_ORDER, FIELD_SCHEMA, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, OwApiError, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwChange, type OwChangesPage, type OwClientConfig, type OwElement, type OwElementBase, type OwErrorBody, type OwJoinPreview, type OwJoinedMembership, type OwKeyKind, type OwLinkEdit, type OwLookupElement, type OwLookupHit, type OwLookupLink, type OwLookupOptions, type OwLookupReason, type OwMediaTicket, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, OwPreconditionFailedError, type OwPreparedPhoto, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwUploadedImage, OwV2Client, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldIndex, type OwWorldMeta, PHOTO_MAX_BYTES, PHOTO_TYPES, type RevokeAllSessionsResponse, type RevokeSessionResponse, SPATIAL_TYPES, type SectionInfo, type TokenConsumeParams, type TokenConsumeResponse, TokenResource, type TokenStatus, type TokenTransport, WORLD_FILE_MAX_BYTES, WORLD_FILE_MAX_ENTRIES, buildWorldIndex, detectKeyKind, elementColor, errorFromResponse, familyOf, getElementIcon, getElementLabel, isDemoKey, kindCanWrite, lookupWorld, parseErrorEnvelope, pinExpectation, planPhoto, preparePhoto, readWorldFile, renderElement, writeWorldFile };
|
|
3145
|
+
export { ASK_LIMITS, type AccessKeyResponse, ELEMENT_FAMILIES, ELEMENT_ICONS, ELEMENT_LABELS, ELEMENT_SECTIONS, ELEMENT_TYPES, type ElementFamily, type ElementType, type EncryptionInfo, FAMILY_COLORS, FAMILY_ORDER, FIELD_SCHEMA, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, OwApiError, type OwAskAnswer, type OwAskContext, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwChange, type OwChangesPage, type OwClientConfig, type OwElement, type OwElementBase, type OwErrorBody, type OwJoinPreview, type OwJoinedMembership, type OwKeyKind, type OwLinkEdit, type OwLookupElement, type OwLookupHit, type OwLookupLink, type OwLookupOptions, type OwLookupReason, type OwMediaTicket, type OwMemberRole, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, OwPreconditionFailedError, type OwPreparedPhoto, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwUploadedImage, OwV2Client, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldIndex, type OwWorldMeta, PHOTO_MAX_BYTES, PHOTO_TYPES, type RevokeAllSessionsResponse, type RevokeSessionResponse, SPATIAL_TYPES, type SectionInfo, type TokenConsumeParams, type TokenConsumeResponse, TokenResource, type TokenStatus, type TokenTransport, WORLD_FILE_MAX_BYTES, WORLD_FILE_MAX_ENTRIES, buildAskContext, buildWorldIndex, detectKeyKind, elementColor, errorFromResponse, familyOf, getElementIcon, getElementLabel, isDemoKey, kindCanWrite, lookupWorld, parseErrorEnvelope, pinExpectation, planPhoto, preparePhoto, readWorldFile, renderElement, writeWorldFile };
|
package/dist/index.js
CHANGED
|
@@ -87,6 +87,18 @@ var OwApiError = class extends Error {
|
|
|
87
87
|
get isPinRequired() {
|
|
88
88
|
return this.status === 409 && this.code === "pin_required";
|
|
89
89
|
}
|
|
90
|
+
/** A daily allowance is used up (429 `quota_exceeded`): the world's image tickets, or the account's asks. See retryAfter. */
|
|
91
|
+
get isQuotaExceeded() {
|
|
92
|
+
return this.status === 429 && this.code === "quota_exceeded";
|
|
93
|
+
}
|
|
94
|
+
/** ask: the proxy is switched off, or paused for the day by the server-wide cap (503 `ask_unavailable`). Not counted. */
|
|
95
|
+
get isAskUnavailable() {
|
|
96
|
+
return this.status === 503 && this.code === "ask_unavailable";
|
|
97
|
+
}
|
|
98
|
+
/** ask: the model gave no answer (502 `ask_failed`). Not counted; try again in a moment. */
|
|
99
|
+
get isAskFailed() {
|
|
100
|
+
return this.status === 502 && this.code === "ask_failed";
|
|
101
|
+
}
|
|
90
102
|
};
|
|
91
103
|
var OwPreconditionFailedError = class extends OwApiError {
|
|
92
104
|
constructor(status, code, message, docUrl, detail, type = null, param = null, retryAfter = null) {
|
|
@@ -447,6 +459,25 @@ var OwV2Client = class {
|
|
|
447
459
|
}
|
|
448
460
|
return this.request("POST", "/account/join", { body: { code } });
|
|
449
461
|
}
|
|
462
|
+
// -- Ask your world (keel #159) -------------------------------------------
|
|
463
|
+
/**
|
|
464
|
+
* POST /account/ask -- a question about a world the account owns or is in, answered by
|
|
465
|
+
* keel's AI proxy from `context` only (build it with buildAskContext from the elements
|
|
466
|
+
* the user sees). The answer is "The world doesn't say." when the context does not hold
|
|
467
|
+
* it. Needs the client's `ow_a_` token (a world key is a TypeError before sending).
|
|
468
|
+
* Refusals: 429 `quota_exceeded` (`err.isQuotaExceeded`, the account's daily allowance;
|
|
469
|
+
* Retry-After runs to midnight UTC), 503 `ask_unavailable` (`err.isAskUnavailable`:
|
|
470
|
+
* switched off, or paused for the day), 502 `ask_failed` (`err.isAskFailed`); none of
|
|
471
|
+
* them counts. 422 for a question over 500 characters or context past its limits.
|
|
472
|
+
*/
|
|
473
|
+
async ask(req) {
|
|
474
|
+
if (this.keyKind !== "account") {
|
|
475
|
+
throw new TypeError("ask needs an account token (ow_a_): the proxy meters per account");
|
|
476
|
+
}
|
|
477
|
+
return this.request("POST", "/account/ask", {
|
|
478
|
+
body: { world_id: req.worldId, question: req.question, context: req.context }
|
|
479
|
+
});
|
|
480
|
+
}
|
|
450
481
|
// -- Core request machinery ----------------------------------------------
|
|
451
482
|
/**
|
|
452
483
|
* Raw authenticated request against this client's baseUrl. Public since 4.0
|
|
@@ -1871,6 +1902,38 @@ function renderElement(element, index, { descMax = 500, linkMax = 12, incomingMa
|
|
|
1871
1902
|
return lines.join("\n");
|
|
1872
1903
|
}
|
|
1873
1904
|
|
|
1905
|
+
// src/ask.ts
|
|
1906
|
+
var ASK_LIMITS = { questionMax: 500, itemsMax: 8, itemMax: 2e3, totalMax: 12e3 };
|
|
1907
|
+
var chars = (s) => [...s].length;
|
|
1908
|
+
var cut = (s, n) => [...s].slice(0, n).join("");
|
|
1909
|
+
function buildAskContext(items, index) {
|
|
1910
|
+
const out = { context: [], kept: [], dropped: [], truncated: [] };
|
|
1911
|
+
let total = 0;
|
|
1912
|
+
let full = false;
|
|
1913
|
+
for (const item of items) {
|
|
1914
|
+
const el = item && typeof item === "object" && "element" in item ? item.element : item;
|
|
1915
|
+
if (full || out.context.length >= ASK_LIMITS.itemsMax) {
|
|
1916
|
+
out.dropped.push(el.id);
|
|
1917
|
+
continue;
|
|
1918
|
+
}
|
|
1919
|
+
let text = renderElement(el, index);
|
|
1920
|
+
if (chars(text) > ASK_LIMITS.itemMax) {
|
|
1921
|
+
text = cut(text, ASK_LIMITS.itemMax);
|
|
1922
|
+
out.truncated.push(el.id);
|
|
1923
|
+
}
|
|
1924
|
+
if (total + chars(text) > ASK_LIMITS.totalMax) {
|
|
1925
|
+
full = true;
|
|
1926
|
+
out.truncated = out.truncated.filter((id) => id !== el.id);
|
|
1927
|
+
out.dropped.push(el.id);
|
|
1928
|
+
continue;
|
|
1929
|
+
}
|
|
1930
|
+
total += chars(text);
|
|
1931
|
+
out.context.push(text);
|
|
1932
|
+
out.kept.push(el.id);
|
|
1933
|
+
}
|
|
1934
|
+
return out;
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1874
1937
|
// src/photo.ts
|
|
1875
1938
|
var PHOTO_TYPES = ["image/webp", "image/png", "image/jpeg", "image/avif"];
|
|
1876
1939
|
var PHOTO_MAX_BYTES = 15 * 1024 * 1024;
|
|
@@ -2105,6 +2168,7 @@ var GameTier = /* @__PURE__ */ ((GameTier2) => {
|
|
|
2105
2168
|
return GameTier2;
|
|
2106
2169
|
})(GameTier || {});
|
|
2107
2170
|
export {
|
|
2171
|
+
ASK_LIMITS,
|
|
2108
2172
|
ELEMENT_FAMILIES,
|
|
2109
2173
|
ELEMENT_ICONS,
|
|
2110
2174
|
ELEMENT_LABELS,
|
|
@@ -2126,6 +2190,7 @@ export {
|
|
|
2126
2190
|
TokenResource,
|
|
2127
2191
|
WORLD_FILE_MAX_BYTES,
|
|
2128
2192
|
WORLD_FILE_MAX_ENTRIES,
|
|
2193
|
+
buildAskContext,
|
|
2129
2194
|
buildWorldIndex,
|
|
2130
2195
|
detectKeyKind,
|
|
2131
2196
|
elementColor,
|