@onlyworlds/sdk 4.20.0 → 4.22.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
@@ -50,7 +50,13 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
50
50
  - Sort (since 4.18.0, account token): `account.sort({ worldId, notes, slice })` turns unsorted
51
51
  notes (text, or a picture already uploaded into the world) into rows to review: `make`,
52
52
  `add_to`, `link`, `ask`, plus `not_proposed` with reasons. Ids come only from your `slice`
53
- (up to 100 elements your own lookup found); nothing is written. Counts as one ask.
53
+ (up to 100 elements your own lookup found); nothing is written. Spends from the same
54
+ allowance as ask.
55
+ - Allowance (since 4.21.0, account token): `account.allowance()` reads the daily AI allowance
56
+ without spending: `{ token_rating, tokens_used_today, tokens_remaining, resets_at }`.
57
+ - Who am I (since 4.22.0, a world key): `client.me()` is `{ world, scope, kind, role,
58
+ membership, character }` (`membership` is what `created_by` holds for what you create; null
59
+ for the owner); `client.members()` is the roster's rows. An account token is a TypeError.
54
60
  - Invite links (since 4.12.0): `previewJoin(code)` (no credential sent) shows who invites, to
55
61
  which world, in what role; `acceptJoin(code)` with an `ow_a_` account token joins. Bad code:
56
62
  `err.isNotFound`; `err.isAlreadyMember`, `err.isPinRequired` for the two 409s.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,35 @@ earlier history lives in git log only.
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [4.22.0] — 2026-10-14
9
+
10
+ ### Added
11
+ - **`client.me()` and `client.members()`**: GET /me (who this world key is: world, scope, kind,
12
+ role, membership id, Character) and GET /members (the roster's rows, unwrapped from `{ data }`).
13
+ Lantern reads a player's role from /me by hand today. Types `OwMe`, `OwMember`, typed from
14
+ keel's declared schemas and held to them by Assembly's wire gate. An account token is a
15
+ TypeError before sending; the tests fail with that guard removed, or with the rows left
16
+ wrapped.
17
+
18
+ ### Changed
19
+ - The calendar kernel is the SDK's own: Atlas 245aad3 deleted its `core/calendar.ts` and imports
20
+ this one (Temper, h37 #4472), so the copy record (`src/calendar/SOURCES.json`) and the re-copy
21
+ script (`codegen/atlas-calendar.mjs`) are gone. A kernel change is an SDK release now. No code
22
+ change.
23
+
24
+ ## [4.21.0] — 2026-10-14
25
+
26
+ ### Added
27
+ - **`client.allowance()`**: GET /account/allowance (keel 872431f, Skeld h37 #4308), the
28
+ account's daily AI allowance read without spending: `token_rating`, `tokens_used_today`,
29
+ `tokens_remaining`, `resets_at` (the next midnight UTC). Account token only, like ask and
30
+ sort. Type `OwAllowance`, held by Assembly's wire gate to the route's declared schema, as
31
+ `OwAskAnswer`, `OwSortAnswer` and `OwJoinPreview` now are to theirs.
32
+
33
+ ### Fixed
34
+ - README and AGENTS.md no longer say a sort counts as one ask: since keel a6244db both spend
35
+ tokens from the allowance.
36
+
8
37
  ## [4.20.0] — 2026-10-14
9
38
 
10
39
  ### Added
package/README.md CHANGED
@@ -121,6 +121,15 @@ const membership = await account.acceptJoin(code); // account = a client with an
121
121
 
122
122
  A bad code (unknown, used, revoked, expired) is one 404 (`err.isNotFound`). Accepting can answer `err.isAlreadyMember` or `err.isPinRequired` (set a PIN first); a refusal never uses up the code.
123
123
 
124
+ Once in, a world key can ask who it is and who else is there (since 4.22.0):
125
+
126
+ ```typescript
127
+ const me = await client.me(); // { world, scope, kind, role, membership, character }
128
+ const roster = await client.members(); // [{ id, kind, role, character, status }], the owner's id is null
129
+ ```
130
+
131
+ `me.membership` is what `created_by` holds on the elements this key creates; `me.role` decides what it may change.
132
+
124
133
  ## Sync
125
134
 
126
135
  ```typescript
@@ -174,7 +183,7 @@ const reply = await account.ask({ worldId, question, context }); // account: a c
174
183
  reply.answer; // from those elements only, or "The world doesn't say."
175
184
  ```
176
185
 
177
- 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. A sort counts as one question.
186
+ 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.
178
187
 
179
188
  ```typescript
180
189
  const slice = hits.slice(0, 100).map(({ element: e }) => ({ id: e.id, type: e.type, name: e.name }));
@@ -182,6 +191,12 @@ const { rows, not_proposed } = await account.sort({ worldId, notes: ['Mira moved
182
191
  // rows: make (a new element), add_to (text for a field), link (one element to another), ask (which one?)
183
192
  ```
184
193
 
194
+ Asking and sorting spend tokens from the account's daily AI allowance, the same meter the Council uses. Each answer carries `tokens_remaining` and `token_rating`; `allowance()` reads the meter without spending anything (since 4.21.0):
195
+
196
+ ```typescript
197
+ const { token_rating, tokens_remaining, resets_at } = await account.allowance(); // resets_at: the next midnight UTC
198
+ ```
199
+
185
200
  ## World files
186
201
 
187
202
  A world file is one `.zip` holding a whole world folder (`world.json` and `elements/<type>/*.json`, as Atlas keeps a world on disk), the way Atlas downloads and opens one. It needs no account and works in the browser and in Node.
package/dist/index.d.ts CHANGED
@@ -2104,6 +2104,49 @@ interface OwSortAnswer {
2104
2104
  token_rating: number;
2105
2105
  [k: string]: unknown;
2106
2106
  }
2107
+ /** GET /me: who this world key is. */
2108
+ interface OwMe {
2109
+ world: {
2110
+ id: string;
2111
+ name: string;
2112
+ };
2113
+ scope: 'read' | 'write';
2114
+ kind: 'owner' | 'person' | 'agent';
2115
+ role: 'owner' | OwMemberRole;
2116
+ /** The membership id (what `created_by` holds for what this key creates), or null for the owner. */
2117
+ membership: string | null;
2118
+ /** The member's Character, or null. */
2119
+ character: string | null;
2120
+ /** Agent seats only: the agent's name. */
2121
+ name?: string;
2122
+ [k: string]: unknown;
2123
+ }
2124
+ /** One row of GET /members, the world's roster. */
2125
+ interface OwMember {
2126
+ /** The membership id (what `created_by` holds), or null for the owner. */
2127
+ id: string | null;
2128
+ kind: 'owner' | 'person' | 'agent';
2129
+ role: 'owner' | OwMemberRole;
2130
+ /** The Character that is this member, or null. */
2131
+ character: string | null;
2132
+ /** `removed` rows stay, so their elements keep `created_by`. */
2133
+ status: 'active' | 'removed';
2134
+ /** Agent rows only: the agent's name. */
2135
+ name?: string;
2136
+ [k: string]: unknown;
2137
+ }
2138
+ /** GET /account/allowance: the account's daily AI allowance (keel 872431f, 2026-10-14). */
2139
+ interface OwAllowance {
2140
+ /** The account's daily allowance in tokens. */
2141
+ token_rating: number;
2142
+ /** Tokens spent today (UTC); may pass the rating by the size of the last call. */
2143
+ tokens_used_today: number;
2144
+ /** Tokens left today, never below 0. */
2145
+ tokens_remaining: number;
2146
+ /** When the allowance resets: the next midnight UTC (ISO 8601). */
2147
+ resets_at: string;
2148
+ [k: string]: unknown;
2149
+ }
2107
2150
  /** POST /join/preview: what a join code holds, read without using it (keel #212). */
2108
2151
  interface OwJoinPreview {
2109
2152
  /** `person`: an invite link, accepted with acceptJoin. `agent`: redeemed by an AI agent at POST /join. */
@@ -2383,6 +2426,19 @@ declare class OwV2Client {
2383
2426
  getWorld(): Promise<OwWorldMeta>;
2384
2427
  /** PATCH /world -- partial world-meta update. */
2385
2428
  patchWorld(partial: Record<string, unknown>): Promise<OwWorldMeta>;
2429
+ /**
2430
+ * GET /me -- who this world key is: the world, read or write scope, the kind (owner,
2431
+ * person, agent), the role, the membership id (what `created_by` holds for what this key
2432
+ * creates; null for the owner) and the member's Character. A world key's call; an account
2433
+ * token is a TypeError before sending.
2434
+ */
2435
+ me(): Promise<OwMe>;
2436
+ /**
2437
+ * GET /members -- the world's roster: each member's id (null for the owner), kind, role,
2438
+ * Character and status (`removed` rows stay, so their elements keep `created_by`). Returns
2439
+ * the rows; keel sends them as `{ data }` with no paging. A world key's call.
2440
+ */
2441
+ members(): Promise<OwMember[]>;
2386
2442
  /** GET /{type}/ -- one cursor page. */
2387
2443
  list(type: ElementType | string, params?: ListParams): Promise<OwPage>;
2388
2444
  /** Cursor-walk every page of a type. Politeness: uses config pageSize. */
@@ -2583,7 +2639,7 @@ declare class OwV2Client {
2583
2639
  * lookupWorld's hits), sorted by the same proxy as ask into rows to review: `make`, `add_to`,
2584
2640
  * `link`, `ask`. Nothing is written; the app applies what the user accepts. Every id in a
2585
2641
  * row is from the slice; keel moves any other row to `not_proposed` with its reason.
2586
- * A sort counts as one ask: the same account token, allowance and refusals as ask. 422
2642
+ * The same account token, allowance (it spends the tokens it uses) and refusals as ask. 422
2587
2643
  * names the param: notes 1 to 8, each up to 4,000 characters and 16,000 in all (text
2588
2644
  * only), at most four pictures, each uploaded into this world; slice up to 100, names up
2589
2645
  * to 200 characters, anchors up to 120.
@@ -2593,6 +2649,12 @@ declare class OwV2Client {
2593
2649
  notes: OwSortNote[];
2594
2650
  slice: OwSortRef[];
2595
2651
  }): Promise<OwSortAnswer>;
2652
+ /**
2653
+ * GET /account/allowance -- the account's daily AI allowance, the one meter ask, sort and
2654
+ * the Council spend from (keel 872431f): the rating, what is used and left today, and
2655
+ * when it resets (the next midnight UTC). Spends nothing. Needs the client's `ow_a_` token.
2656
+ */
2657
+ allowance(): Promise<OwAllowance>;
2596
2658
  /**
2597
2659
  * Raw authenticated request against this client's baseUrl. Public since 4.0
2598
2660
  * so auxiliary resources can ride the same transport — it structurally
@@ -3194,11 +3256,12 @@ declare function parseDate(cfg: CalendarConfig, input: string, opts?: ParseOptio
3194
3256
  declare function isParseError(r: ParseResult | ParseError): r is ParseError;
3195
3257
 
3196
3258
  /**
3197
- * World calendars: Atlas's calendar kernel, and which calendars a world holds.
3259
+ * World calendars: the calendar kernel, and which calendars a world holds.
3198
3260
  *
3199
- * `calendar.ts` beside this file is Atlas's `src/core/calendar.ts`, byte for byte
3200
- * (Forge/tools/atlas; recorded in `SOURCES.json`, checked with Assembly's copy-drift).
3201
- * Never edit it here: change Atlas's, then copy and re-record. This file adapts Atlas's
3261
+ * `calendar.ts` beside this file came from Atlas's `src/core/calendar.ts` in 4.20.0, and is
3262
+ * the one copy since Atlas 245aad3 deleted its own and imports this one (Temper, h37 #4472):
3263
+ * a kernel change is an SDK release, and Atlas's 48 kernel tests run against it there too.
3264
+ * Its contract is still Atlas's calendar design, §5 and §5b. This file adapts Atlas's
3202
3265
  * `src/core/calendar-lens.ts` (readCalendarValue, worldCalendars, resolveCalendarLens) to
3203
3266
  * any element shape, since the SDK has no Atlas `Element`.
3204
3267
  *
@@ -3534,4 +3597,4 @@ declare class TokenResource {
3534
3597
  getEncryptionInfo(): Promise<EncryptionInfo>;
3535
3598
  }
3536
3599
 
3537
- export { 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_SCHEMA, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, OwApiError, type OwAskAnswer, type OwAskContext, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwCalendarElement, 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 OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, type OwUploadedImage, OwV2Client, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldIndex, type OwWorldMeta, 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, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, isDemoKey, isLeapYear, isParseError, kindCanWrite, lookupWorld, monthStartSteps, parseDate, parseErrorEnvelope, pinExpectation, planPhoto, preparePhoto, readCalendarConfig, readCalendarValue, readWorldFile, renderElement, resolveCalendarLens, resolveEraDomains, validateCalendarConfig, weekdayForStep, worldCalendars, writeWorldFile, yearLength, yearStartStep };
3600
+ export { 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_SCHEMA, type FieldInfo, type FieldType, GameTier, type ListParams, ONLYWORLDS_VERSION, type OwAllowance, OwApiError, type OwAskAnswer, type OwAskContext, type OwAuthErrorCode, type OwBulkItem, type OwBulkItemResult, type OwBulkResponse, type OwCalendarElement, 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 OwMe, type OwMediaTicket, type OwMember, type OwMemberRole, OwNetworkError, type OwPage, type OwPhotoOptions, type OwPhotoPlan, OwPreconditionFailedError, type OwPreparedPhoto, type OwReadWorldFile, type OwReadWorldFileOptions, type OwRemovalTicket, type OwRemovedImage, type OwRenderOptions, type OwSortAddToRow, type OwSortAnswer, type OwSortAskRow, type OwSortLinkRow, type OwSortMakeRow, type OwSortNote, type OwSortRef, type OwSortRow, type OwUploadedImage, OwV2Client, type OwWorldFileEntry, OwWorldFileError, type OwWorldFileReason, type OwWorldIndex, type OwWorldMeta, 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, floorDiv, floorMod, formatDuration, formatMidLabel, formatStep, formatYearLabel, getElementIcon, getElementLabel, 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
@@ -212,6 +212,31 @@ var OwV2Client = class {
212
212
  async patchWorld(partial) {
213
213
  return this.request("PATCH", "/world/", { body: sanitizePayload(partial) });
214
214
  }
215
+ // -- Who am I, and who is here ---------------------------------------------
216
+ /**
217
+ * GET /me -- who this world key is: the world, read or write scope, the kind (owner,
218
+ * person, agent), the role, the membership id (what `created_by` holds for what this key
219
+ * creates; null for the owner) and the member's Character. A world key's call; an account
220
+ * token is a TypeError before sending.
221
+ */
222
+ async me() {
223
+ if (this.keyKind === "account") {
224
+ throw new TypeError("me needs a world key: an account token is not a member of one world");
225
+ }
226
+ return this.request("GET", "/me/");
227
+ }
228
+ /**
229
+ * GET /members -- the world's roster: each member's id (null for the owner), kind, role,
230
+ * Character and status (`removed` rows stay, so their elements keep `created_by`). Returns
231
+ * the rows; keel sends them as `{ data }` with no paging. A world key's call.
232
+ */
233
+ async members() {
234
+ if (this.keyKind === "account") {
235
+ throw new TypeError("members needs a world key: an account token is not a member of one world");
236
+ }
237
+ const page = await this.request("GET", "/members/");
238
+ return page.data ?? [];
239
+ }
215
240
  // -- Element CRUD --------------------------------------------------------
216
241
  /** GET /{type}/ -- one cursor page. */
217
242
  async list(type, params = {}) {
@@ -500,7 +525,7 @@ var OwV2Client = class {
500
525
  * lookupWorld's hits), sorted by the same proxy as ask into rows to review: `make`, `add_to`,
501
526
  * `link`, `ask`. Nothing is written; the app applies what the user accepts. Every id in a
502
527
  * row is from the slice; keel moves any other row to `not_proposed` with its reason.
503
- * A sort counts as one ask: the same account token, allowance and refusals as ask. 422
528
+ * The same account token, allowance (it spends the tokens it uses) and refusals as ask. 422
504
529
  * names the param: notes 1 to 8, each up to 4,000 characters and 16,000 in all (text
505
530
  * only), at most four pictures, each uploaded into this world; slice up to 100, names up
506
531
  * to 200 characters, anchors up to 120.
@@ -513,6 +538,17 @@ var OwV2Client = class {
513
538
  body: { world_id: req.worldId, notes: req.notes, slice: req.slice }
514
539
  });
515
540
  }
541
+ /**
542
+ * GET /account/allowance -- the account's daily AI allowance, the one meter ask, sort and
543
+ * the Council spend from (keel 872431f): the rating, what is used and left today, and
544
+ * when it resets (the next midnight UTC). Spends nothing. Needs the client's `ow_a_` token.
545
+ */
546
+ async allowance() {
547
+ if (this.keyKind !== "account") {
548
+ throw new TypeError("allowance needs an account token (ow_a_): the allowance is per account");
549
+ }
550
+ return this.request("GET", "/account/allowance");
551
+ }
516
552
  // -- Core request machinery ----------------------------------------------
517
553
  /**
518
554
  * Raw authenticated request against this client's baseUrl. Public since 4.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlyworlds/sdk",
3
- "version": "4.20.0",
3
+ "version": "4.22.0",
4
4
  "description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
5
5
  "type": "module",
6
6
  "exports": {