@onlyworlds/sdk 4.13.0 → 4.15.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 +2 -0
- package/CHANGELOG.md +23 -0
- package/README.md +2 -0
- package/dist/index.d.ts +21 -3
- package/dist/index.js +13 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -30,6 +30,8 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
|
|
|
30
30
|
- Offline or stale edits: pass `{ ifMatch: el.change_seq }` to `patch`/`editLinks` (since 4.9.0).
|
|
31
31
|
If the element moved, nothing is written and `OwPreconditionFailedError` (412) carries
|
|
32
32
|
`current`; the server never merges, the client decides.
|
|
33
|
+
- Polling: `changesHead()` (since 4.15.0) gives `{head, cursor}` without a page; walk only
|
|
34
|
+
when `head` moved past the head you last applied.
|
|
33
35
|
- World-meta changes do NOT appear in `/changes` — poll `GET /world` separately.
|
|
34
36
|
- Extension fields: `x_<toolname>_*` is the sanctioned namespace for tool-specific state;
|
|
35
37
|
unknown unprefixed fields 422. Extensions are capped at **64 KB per element** (422,
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ earlier history lives in git log only.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.15.0] — 2026-10-12
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **`changesHead()`**: `GET /changes?head=true`, the feed's position now without a page
|
|
12
|
+
(keel reads no element). Returns `{ head, cursor }`: `head` is the world's `change_seq`,
|
|
13
|
+
`cursor` a position to pass as `since` that re-sends nothing (a guest's carries its view's
|
|
14
|
+
epoch). The cheap "anything new?" for a poll: compare `head` with the head you last applied
|
|
15
|
+
and walk `changesAll` only when it moved. keel sends the owner's cursor as a number; it comes
|
|
16
|
+
back as a string, like every cursor the SDK hands out. Checked live on Moppetopia: a walk
|
|
17
|
+
from the returned cursor brings nothing. Asked for by Lantern's 20-second poll (Temper,
|
|
18
|
+
Skeld's S15).
|
|
19
|
+
|
|
20
|
+
## [4.14.0] — 2026-10-12
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
- **The co-builder role is `co_builder` on the wire.** `OwJoinPreview.role` and
|
|
24
|
+
`OwJoinedMembership.role` listed `'co-builder'`, which is only the label keel shows (keel
|
|
25
|
+
`MemberRole.CO_BUILDER = "co_builder"`). The types were open, so nothing broke at runtime, but
|
|
26
|
+
a comparison written from them would never match. Caught by Temper from Lantern's fakes.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
- `OwMemberRole` (`'co_builder' | 'contributor' | 'guest'`, open), the type both now use.
|
|
30
|
+
|
|
8
31
|
## [4.13.0] — 2026-10-12
|
|
9
32
|
|
|
10
33
|
### Added
|
package/README.md
CHANGED
|
@@ -130,6 +130,8 @@ for await (const change of client.changesAll(cursor)) {
|
|
|
130
130
|
}
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
+
To poll for news cheaply, `client.changesHead()` returns `{ head, cursor }` without reading any element: walk `changesAll` only when `head` moved past the head you last applied.
|
|
134
|
+
|
|
133
135
|
Edits to the world itself (its name, calendar, `public_read`) don't appear in the change feed. Read `client.getWorld()` and compare `updated_at`.
|
|
134
136
|
|
|
135
137
|
### Only if unchanged
|
package/dist/index.d.ts
CHANGED
|
@@ -1988,6 +1988,11 @@ 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 & {});
|
|
1991
1996
|
/** POST /account/ask: keel's AI proxy's answer (keel #159). */
|
|
1992
1997
|
interface OwAskAnswer {
|
|
1993
1998
|
/** The answer, from the context only; "The world doesn't say." when it does not hold one. */
|
|
@@ -2014,7 +2019,7 @@ interface OwJoinPreview {
|
|
|
2014
2019
|
invited_by: string | null;
|
|
2015
2020
|
/** The world owner's chosen Character's name, never a username; null when none is set. */
|
|
2016
2021
|
owner_character: string | null;
|
|
2017
|
-
role:
|
|
2022
|
+
role: OwMemberRole;
|
|
2018
2023
|
/** Whether joining gives the joiner a Character of their own (agent links). */
|
|
2019
2024
|
with_character: boolean | null;
|
|
2020
2025
|
/** ISO 8601, UTC. */
|
|
@@ -2027,7 +2032,7 @@ interface OwJoinedMembership {
|
|
|
2027
2032
|
id: string;
|
|
2028
2033
|
world_id: string;
|
|
2029
2034
|
world_name: string;
|
|
2030
|
-
role:
|
|
2035
|
+
role: OwMemberRole;
|
|
2031
2036
|
joined_at: string | null;
|
|
2032
2037
|
/** The id of the joiner's roster Character, or null. */
|
|
2033
2038
|
roster_character: string | null;
|
|
@@ -2358,6 +2363,19 @@ declare class OwV2Client {
|
|
|
2358
2363
|
since?: string;
|
|
2359
2364
|
limit?: number;
|
|
2360
2365
|
}): Promise<OwChangesPage>;
|
|
2366
|
+
/**
|
|
2367
|
+
* GET /changes?head=true -- where the feed is now, without a page: no element is read.
|
|
2368
|
+
* `head` is the world's change_seq; `cursor` is a position to pass as `since` that
|
|
2369
|
+
* re-sends nothing at the head (a guest's carries its view's epoch). The cheap "anything
|
|
2370
|
+
* new?" for a poll: compare `head` with the head you last APPLIED (not the previous
|
|
2371
|
+
* poll's, so a missed tick never drops a change) and walk changesAll only when it moved;
|
|
2372
|
+
* a head below yours means the server rewound: walk again from zero. keel returns the
|
|
2373
|
+
* owner's cursor as a number; it is handed back as a string, like every cursor here.
|
|
2374
|
+
*/
|
|
2375
|
+
changesHead(): Promise<{
|
|
2376
|
+
head: number;
|
|
2377
|
+
cursor: string;
|
|
2378
|
+
}>;
|
|
2361
2379
|
/**
|
|
2362
2380
|
* Walk the feed from `since` (or from zero = full export) to the current
|
|
2363
2381
|
* tail, yielding ops in order. Returns the final cursor via the generator's
|
|
@@ -3137,4 +3155,4 @@ declare class TokenResource {
|
|
|
3137
3155
|
getEncryptionInfo(): Promise<EncryptionInfo>;
|
|
3138
3156
|
}
|
|
3139
3157
|
|
|
3140
|
-
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, 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 };
|
|
3158
|
+
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
|
@@ -329,6 +329,19 @@ var OwV2Client = class {
|
|
|
329
329
|
const query = buildQuery({ since: opts.since, limit: opts.limit ?? this.changesPageSize });
|
|
330
330
|
return this.request("GET", "/changes/", { query });
|
|
331
331
|
}
|
|
332
|
+
/**
|
|
333
|
+
* GET /changes?head=true -- where the feed is now, without a page: no element is read.
|
|
334
|
+
* `head` is the world's change_seq; `cursor` is a position to pass as `since` that
|
|
335
|
+
* re-sends nothing at the head (a guest's carries its view's epoch). The cheap "anything
|
|
336
|
+
* new?" for a poll: compare `head` with the head you last APPLIED (not the previous
|
|
337
|
+
* poll's, so a missed tick never drops a change) and walk changesAll only when it moved;
|
|
338
|
+
* a head below yours means the server rewound: walk again from zero. keel returns the
|
|
339
|
+
* owner's cursor as a number; it is handed back as a string, like every cursor here.
|
|
340
|
+
*/
|
|
341
|
+
async changesHead() {
|
|
342
|
+
const page = await this.request("GET", "/changes/", { query: buildQuery({ head: "true" }) });
|
|
343
|
+
return { head: page.head, cursor: String(page.cursor) };
|
|
344
|
+
}
|
|
332
345
|
/**
|
|
333
346
|
* Walk the feed from `since` (or from zero = full export) to the current
|
|
334
347
|
* tail, yielding ops in order. Returns the final cursor via the generator's
|