@onlyworlds/sdk 4.14.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 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,18 @@ 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
+
8
20
  ## [4.14.0] — 2026-10-12
9
21
 
10
22
  ### Fixed
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
@@ -2363,6 +2363,19 @@ declare class OwV2Client {
2363
2363
  since?: string;
2364
2364
  limit?: number;
2365
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
+ }>;
2366
2379
  /**
2367
2380
  * Walk the feed from `since` (or from zero = full export) to the current
2368
2381
  * tail, yielding ops in order. Returns the final cursor via the generator's
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onlyworlds/sdk",
3
- "version": "4.14.0",
3
+ "version": "4.15.0",
4
4
  "description": "TypeScript SDK for the OnlyWorlds API - build world-building applications with type safety",
5
5
  "type": "module",
6
6
  "exports": {