@onlyworlds/sdk 3.0.0 → 4.0.0-alpha.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 ADDED
@@ -0,0 +1,34 @@
1
+ # For AI agents using @onlyworlds/sdk
2
+
3
+ **Start with [SCHEMA.md](SCHEMA.md)** (in this package): the full generated schema reference —
4
+ every type, every field with its meaning, link directions, families, icons, display sections.
5
+ It is generated from the same canonical YAML as the types, so it cannot drift.
6
+
7
+ **What this package is**: the canonical typed TypeScript client for the OnlyWorlds v2 API,
8
+ plus the canonical constants (element types, icons, colour families, field schema).
9
+ OnlyWorlds is an open standard for portable world data — 22 element types, UUID-linked.
10
+
11
+ **Use the v2 surface.** `OwV2Client` + the `V2ElementType` slug union + the generated
12
+ interfaces in `types.generated.ts` (emitted from the canonical schema YAML, validated
13
+ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum) is frozen
14
+ legacy — do not build new work on it.
15
+
16
+ **SDK vs MCP server — pick correctly**:
17
+ - Known, deterministic operations (CRUD, sync, bulk) → **this SDK**. Typed calls, typed
18
+ responses, far cheaper than tool-schema reasoning.
19
+ - Live exploration of a user's world from a chat/agent context → the **MCP server** at
20
+ `https://www.onlyworlds.com/mcp` (same `API-Key`/`API-Pin` headers, 11 tools).
21
+
22
+ **Wire facts that bite** (full details in README):
23
+ - Never send a `"world"` field in payloads — world identity comes from the API key (422 otherwise).
24
+ - v2 link fields use ONE name both directions (no `_ids` suffix — that is v1 dialect only).
25
+ - PATCH is destructive on sent fields; use `editLinks` (atomic add/remove) for relationships.
26
+ - World-meta changes do NOT appear in `/changes` — poll `GET /world` separately.
27
+ - Extension fields: `x_<toolname>_*` is the sanctioned namespace for tool-specific state;
28
+ unknown unprefixed fields 422.
29
+ - Colour carries the element's FAMILY (`elementColor(type, mode)`); the icon
30
+ (`ELEMENT_ICONS`) carries the TYPE. Icon + label are required alongside colour, not optional.
31
+
32
+ **Auth**: prefixed keys — `ow_w_` (read+write), `ow_r_` (read-only, no PIN — the share
33
+ primitive), `ow_a_` (account Bearer). Demo keys `0000000000`–`0000000009` are read-only
34
+ test credentials against real data.
package/CHANGELOG.md ADDED
@@ -0,0 +1,86 @@
1
+ # Changelog
2
+
3
+ All notable changes to `@onlyworlds/sdk`. Maintained from 3.1.0 onward (Kael, Assembly);
4
+ earlier history lives in git log only.
5
+
6
+ ## [Unreleased — 4.0.0] (branch `v4`)
7
+
8
+ **v2-native only.** See `docs/migrating-3-to-4.md`. 3.x stays published forever for
9
+ pinned consumers.
10
+
11
+ ### Removed (BREAKING)
12
+ - The v1 client (`OnlyWorldsClient`), the v1 `ElementType` enum, `icon-utils`.
13
+ `ElementType` at the root is now THE v2 slug union (was `V2ElementType` alias in 3.x).
14
+ - CJS build — the package is ESM-only with a sealed `exports` map (`"type": "module"`,
15
+ `sideEffects: false`).
16
+
17
+ ### Changed
18
+ - Metadata tables (`ELEMENT_ICONS`, `ELEMENT_LABELS`, `ELEMENT_SECTIONS`, `FIELD_SCHEMA`,
19
+ `getElementIcon`, `getElementLabel`) ported onto the v2 slug union — same export names,
20
+ same shapes, contents byte-identical EXCEPT: `FIELD_SCHEMA` `type: 'number'` →
21
+ `'integer'` (70 entries; 'number' dropped from `FieldType`). Migration: consumers
22
+ switching on `'number'` switch on `'integer'`.
23
+ - `TokenResource` now takes a structural `TokenTransport` (`{ request<T>(method, path,
24
+ body?) }`) instead of the removed v1 client. Token surface retained pending the
25
+ wire-fate ruling (RFC-001 §5) — may be removed in a later 4.x.
26
+
27
+ ### Added (post-alpha.0, same night)
28
+ - **`ELEMENT_ICONS` GENERATED** from keel's `icon:` wrapper key (keel `56c124a`).
29
+ - **`ELEMENT_SECTIONS` DERIVED** from the canonical schema's own document structure
30
+ (Skeld's ruling: sections are the standard tier's property groups; document order is
31
+ display order). Divergence check vs the old hand table found and fixed three fossils:
32
+ creature "Behaviour"→"Behavior", pin's triple-listed generic link → `element`,
33
+ relation "Involves" listing a nonexistent `relations` field. Canonical is truth.
34
+ - **`SCHEMA.md`** — full generated schema reference (every field with its canonical
35
+ description, link directions, families, icons, sections), ships in the tarball;
36
+ covered by the codegen drift guard. AGENTS.md points agents at it first.
37
+ - **`OwV2Client.request()` is public** (typed escape hatch; does not sanitize) and
38
+ structurally satisfies `TokenTransport` — `new TokenResource(client)` just works.
39
+ Token ruling (Skeld): keel keeps `/tokens/*` long-term; ported, not deleted.
40
+ - README rewritten v2-native (v1 sections, branded types, and the encrypted-key
41
+ walkthrough removed; bulk partial-failure and idempotency-key hygiene promoted).
42
+
43
+ ### Planned before release (RFC-001 gates)
44
+ - Skeld's live wire-log v1-traffic query (gate 3). Alpha publishes to the `alpha`
45
+ dist-tag only — never `latest`. **No `npm deprecate` on 3.x** (amended per landscape
46
+ research — 3.x stays plainly supported; README framing carries the message).
47
+
48
+ ## [3.1.0] — 2026-07-23
49
+
50
+ ### Added
51
+ - **Canonical element colour palette** (`src/v2/palette.ts`, exported from root):
52
+ `ELEMENT_FAMILIES` (type → family), `FAMILY_COLORS` (family → `{light, dark}` hex),
53
+ `familyOf(type)`, `elementColor(type, mode)`, `FAMILY_ORDER`, type `ElementFamily`.
54
+ Four semantic families (agents / world / abstract / temporal) ruled 2026-07-22 after
55
+ CVD-validated measurement (Orrery `product/schema/element-palette-measurements.md`).
56
+ Colour carries the FAMILY; `ELEMENT_ICONS` carries the TYPE. Keyed on the v2 slug
57
+ union. First proven live in atlas and council, whose local copies become re-exports.
58
+ **`ELEMENT_FAMILIES` is GENERATED** from the `family:` key in keel's schema YAML
59
+ (keel `c69366b`, a keel presentation-wrapper key — not part of the council-governed
60
+ OnlyWorlds standard); hexes are hand-authored design constants beside it. Membership
61
+ and hex invariants test-gated (`test/palette.test.mjs`); light hexes render-proven on
62
+ the ruled OnlyWorlds light mode (ow-house-light) 2026-07-23.
63
+ - **Codegen drift guard**: `python codegen/generate_types.py --check` fails if
64
+ `types.generated.ts` doesn't match the schema YAMLs (release gate; mirrors keel's
65
+ schema CI job). Codegen also hard-fails on missing/invalid `family:` keys — the
66
+ canary for a canonical-refresh that overwrote keel's wrapper layer.
67
+ - **CI**: GitHub Action building + running the full suite against the compiled bundle.
68
+ - **AGENTS.md** shipped in the tarball — usage guide for AI agents reading the package
69
+ locally, including the SDK-vs-MCP division of labor and the wire gotchas.
70
+ - README: worked create→link→read-back round-trip, schema-verified field by field
71
+ (also fixes the old example patching `'character'` with a location's id); canonical
72
+ colour section; SDK-vs-MCP guidance.
73
+ - This CHANGELOG.
74
+
75
+ ### Fixed
76
+ - `FieldType` union now includes `'number'` — the legacy alias that 70 `FIELD_SCHEMA`
77
+ entries actually carry (consumers switch on it; data normalization deferred to 4.0).
78
+ - `generate_types.py` exits with a clear message when the sibling keel checkout is
79
+ absent instead of a bare traceback.
80
+
81
+ ## [3.0.0] — 2026-07-18
82
+
83
+ - v2-native client (`OwV2Client`) absorbed from Assembly's ow-v2-client v0.9.0 (Kael),
84
+ wire-corrected against live staging fixtures (S22). Generated element types from the
85
+ canonical keel schema YAML (`src/v2/types.generated.ts`), validated against all 1,086
86
+ live W11 elements. v1 surface unchanged and frozen.
package/README.md CHANGED
@@ -3,12 +3,13 @@
3
3
  [![npm version](https://badge.fury.io/js/@onlyworlds%2Fsdk.svg)](https://www.npmjs.com/package/@onlyworlds/sdk)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- A type-safe TypeScript SDK for building world-building applications with the OnlyWorlds API.
6
+ The canonical typed client for the [OnlyWorlds](https://onlyworlds.github.io) v2 API, plus the
7
+ canonical constants (element types, icons, colour families, field schema) — generated from the
8
+ same schema source the server runs on.
7
9
 
8
- The SDK speaks two dialects of the same API:
9
-
10
- - **v2 (`OwV2Client`)** -- the current, recommended default. Local-first shape: one-shape read/write (no `_ids` suffix), an opaque `/changes` sync feed, atomic bulk writes, and client-side UUID minting for safe retries. Base URL `https://www.onlyworlds.com/api/v2`.
11
- - **v1 (`OnlyWorldsClient`)** -- the original resource-style client. Fully served forever; kept below as the legacy section. Existing 2.x code keeps working unchanged -- v2 is purely additive.
10
+ **4.x is v2-native and ESM-only (Node 18+).** If you need the legacy v1 API dialect
11
+ (`OnlyWorldsClient`) or CommonJS `require()`, stay on 3.x — it remains published and the v1 API
12
+ remains served. See [docs/migrating-3-to-4.md](docs/migrating-3-to-4.md).
12
13
 
13
14
  ## Installation
14
15
 
@@ -16,294 +17,128 @@ The SDK speaks two dialects of the same API:
16
17
  npm install @onlyworlds/sdk
17
18
  ```
18
19
 
19
- ## Quick Start (v2 -- recommended)
20
+ ## Quick Start
20
21
 
21
22
  ```typescript
22
23
  import { OwV2Client } from '@onlyworlds/sdk';
23
24
 
24
- const client = new OwV2Client({
25
- apiKey: 'ow_w_your_world_key', // ow_w_ write / ow_r_ read / ow_a_ account / 10-digit legacy
26
- apiPin: '1234', // needed for writes on a PIN-protected world
27
- });
28
- // baseUrl defaults to https://www.onlyworlds.com/api/v2
29
-
30
- // Read a page, or walk every page of a type
31
- const page = await client.list('character'); // { data, has_more, next_cursor }
32
- for await (const character of client.listAll('character')) {
33
- // ...
34
- }
35
-
36
- // Create -- id is minted client-side when omitted (retries stay idempotent)
37
- const location = await client.create('location', {
38
- name: 'Dragon Peak',
39
- description: 'A treacherous mountain peak where dragons nest',
40
- });
41
-
42
- // Partial update (arrays replace wholesale -- for links prefer editLinks)
43
- await client.patch('character', location.id, { name: 'Updated Name' });
44
-
45
- // Atomic link merge -- returns the full updated element
46
- await client.editLinks('event', eventId, 'objects', { add: [swordId], remove: [] });
47
-
48
- // Bulk write (up to ~1000; partial success by default, atomic:true for all-or-nothing)
49
- const res = await client.bulk([
50
- { type: 'character', element: { name: 'A' } },
51
- { type: 'event', element: { name: 'B' } },
52
- ]);
53
- // res.items[i].status is the per-slot HTTP status; res.errors flags any failure
54
-
55
- // Sync: walk the opaque change feed and persist the final cursor
56
- let cursor;
57
- for await (const change of client.changesAll(cursor)) {
58
- // apply change in order
59
- }
25
+ const client = new OwV2Client({ apiKey: 'ow_r_your_key' }); // read-only key: that's all you need
26
+ const page = await client.list('character'); // { data, has_more, next_cursor }
60
27
  ```
61
28
 
62
- ### AI-assistant access (MCP)
63
-
64
- An MCP server exists at `https://www.onlyworlds.com/mcp` for AI assistants (Claude and other MCP clients) to read and write worlds directly -- no SDK code required. See the [docs](https://onlyworlds.github.io) for setup.
29
+ Key kinds: `ow_w_` write / `ow_r_` read-only (no PIN — the "give this to your players" key) /
30
+ `ow_a_` account Bearer / 10-digit legacy. Writes on a PIN-protected world also pass `apiPin`.
31
+ Demo keys `0000000000`–`0000000009` read real sample worlds.
65
32
 
66
- ## Legacy: v1 client (`OnlyWorldsClient`)
67
-
68
- The v1 resource-style client remains fully supported and served forever. Prefer `OwV2Client` for new code.
33
+ ## The full round-trip
69
34
 
70
35
  ```typescript
71
- import { OnlyWorldsClient } from '@onlyworlds/sdk';
72
-
73
- const client = new OnlyWorldsClient({
74
- apiKey: 'your-api-key',
75
- apiPin: '1234'
76
- });
77
- // baseUrl defaults to https://www.onlyworlds.com/api/worldapi — only override it
78
- // when pointing at a different host (it must include the full API path)
79
-
80
- // Get your world (API keys are world-scoped)
81
- const world = await client.worlds.get();
82
-
83
- // Fetch characters (paginated)
84
- const characters = await client.characters.list();
36
+ const writer = new OwV2Client({ apiKey: 'ow_w_your_key', apiPin: '1234' });
85
37
 
86
- // Create a new location
87
- const location = await client.locations.create({
38
+ // v2 dialect rules, worth internalizing once:
39
+ // - link fields use ONE bare name both directions (no _ids suffix — that's v1)
40
+ // - NEVER send a "world" field (identity comes from the key; the client strips it anyway)
41
+ const location = await writer.create('location', {
88
42
  name: 'Dragon Peak',
89
43
  description: 'A treacherous mountain peak where dragons nest',
90
- supertype: 'mountain'
91
- });
92
-
93
- // Get a specific element
94
- const character = await client.characters.get('element-id');
44
+ }); // id minted client-side when omitted (retries stay idempotent)
95
45
 
96
- // Update an element
97
- await client.characters.update('element-id', {
98
- name: 'Updated Name'
46
+ const dragon = await writer.create('creature', {
47
+ name: 'Vorrath the Ember-Scaled',
48
+ location: location.id, // single link: UUID (or null)
99
49
  });
100
50
 
101
- // Delete an element
102
- await client.characters.delete('element-id');
103
- ```
104
-
105
- ## Features
106
-
107
- - ✅ **Full Type Safety** - Complete TypeScript definitions for all 22 OnlyWorlds element types
108
- - ✅ **Schema-Aligned Types** - Type definitions track the OnlyWorlds schema
109
- - ✅ **CRUD Operations** - Create, read, update, and delete operations for all elements
110
- - ✅ **Token Management** - Built-in support for OnlyWorlds token rating system
111
- - ✅ **Branded Types** - Compile-time safety for element relationships
112
- - ✅ **Zero Runtime Overhead** - Type system has no runtime cost
113
- - ✅ **Modern ESM/CJS** - Supports both ES modules and CommonJS
114
-
115
- ## API Reference
116
-
117
- ### World Endpoint
118
-
119
- The `worlds` resource is special because API keys are world-scoped (one key = one world). The endpoint returns a single `World` object directly, not a paginated list.
120
-
121
- ```typescript
122
- // Get your world
123
- const world = await client.worlds.get();
124
-
125
- // Update your world
126
- const updated = await client.worlds.update({
127
- description: 'A dark fantasy realm'
128
- });
129
- ```
130
-
131
- **Note**: The `worlds` resource only has `get()` and `update()` methods (no `list()`, `create()`, or `delete()`) because API keys are world-scoped.
51
+ const fetched = await writer.get('creature', dragon.id);
52
+ // fetched.location === location.id — reads the way it writes
132
53
 
133
- ### Element Endpoints
54
+ // PATCH is destructive on sent fields; arrays replace wholesale
55
+ await writer.patch('location', location.id, { supertype: 'Mountain' });
134
56
 
135
- All other element types return paginated results:
57
+ // For relationships, use the atomic link merge — returns the full updated element
58
+ const fireBreath = await writer.create('ability', { name: 'Ember Breath' });
59
+ await writer.editLinks('creature', dragon.id, 'abilities', { add: [fireBreath.id], remove: [] });
136
60
 
137
- ```typescript
138
- // List with pagination
139
- const response = await client.characters.list({
140
- limit: 10,
141
- offset: 0,
142
- ordering: '-created_at',
143
- search: 'dragon'
144
- });
145
-
146
- console.log(response.count); // Total count
147
- console.log(response.results); // Array of Characters
148
- console.log(response.next); // URL for next page
149
- console.log(response.previous); // URL for previous page
61
+ // Walk every page of a type
62
+ for await (const character of writer.listAll('character')) { /* ... */ }
150
63
  ```
151
64
 
152
- ## Type-Safe Relationships
153
-
154
- ```typescript
155
- import { ElementId, Character, Location } from '@onlyworlds/sdk';
156
-
157
- // Branded types ensure you can't mix up element IDs
158
- const locationId: ElementId<'Location'> = 'some-location-id';
159
- const character: Character = {
160
- name: 'Aragorn',
161
- location: locationId // Type-safe!
162
- };
163
- ```
164
-
165
- ## Token Management
166
-
167
- OnlyWorlds provides a token rating system for tracking API usage and enabling AI-powered features. Users get a daily token allowance (default: 10,000 tokens) that resets every day.
168
-
169
- ### Working Reference Implementation
65
+ ## Bulk writes — always check `errors`
170
66
 
171
- See [base-tool/src/llm/token-service.ts](https://github.com/OnlyWorlds/base-tool) for the complete working implementation that this SDK enables.
172
-
173
- ### Check Token Status
67
+ `/bulk` **succeeds partially by default** (HTTP 200 with per-slot statuses). The one mistake to
68
+ never make: treating a 200 as "everything landed."
174
69
 
175
70
  ```typescript
176
- // Get current token status
177
- const status = await client.tokens.getStatus();
178
-
179
- console.log(`Available: ${status.tokens_available_today}/${status.token_rating}`);
180
- console.log(`Used today: ${status.tokens_used_today}`);
181
- console.log(`Active sessions: ${status.sessions_active}`);
182
- console.log(`Last reset: ${status.last_reset}`);
71
+ const res = await writer.bulk(
72
+ [
73
+ { type: 'character', element: { name: 'A' } },
74
+ { type: 'event', element: { name: 'B' } },
75
+ ],
76
+ { idempotencyKey: crypto.randomUUID() }, // mint FRESH per attempt — a failed batch is
77
+ ); // cached under its key; never reuse across retries
78
+ if (res.errors) {
79
+ for (const slot of res.items.filter((s) => s.status >= 400)) {
80
+ console.warn(slot.error?.code, slot.error?.message, slot.error?.doc_url);
81
+ }
82
+ }
83
+ // Pass { atomic: true } for all-or-nothing instead. res.wasReplay flags idempotent replays.
183
84
  ```
184
85
 
185
- ### Consume Tokens
186
-
187
- Report token consumption when your tool uses AI features or other token-tracked services:
86
+ ## Sync
188
87
 
189
88
  ```typescript
190
- // Report token usage
191
- const result = await client.tokens.consume({
192
- amount: 500,
193
- service: 'my_worldbuilding_tool',
194
- metadata: {
195
- feature: 'character_generation',
196
- model: 'gpt-4',
197
- prompt_tokens: 300,
198
- completion_tokens: 200
199
- }
200
- });
201
-
202
- // Check if consumption succeeded
203
- if (result.error) {
204
- console.warn('Token warning:', result.error);
89
+ let cursor; // opaque, never expires; persist it
90
+ for await (const change of client.changesAll(cursor)) {
91
+ // ops arrive in (change_seq, id) order — apply in order → convergence
205
92
  }
206
-
207
- console.log(`Consumed ${result.tokens_consumed} tokens`);
208
- console.log(`${result.tokens_remaining} tokens remaining`);
93
+ // GOTCHA: world-meta edits (name, calendar, public_read) do NOT enter /changes.
94
+ // Poll client.getWorld() and compare updated_at separately.
209
95
  ```
210
96
 
211
- **Important**: The API allows consumption even when exceeding available tokens (tracks as debt), but returns a warning in the `error` field.
97
+ ## Errors
212
98
 
213
- ### Advanced: Encrypted API Key Access
99
+ Every non-2xx throws `OwApiError` carrying the platform envelope: `.status`, `.type`, `.code`,
100
+ `.param` (the exact field that failed), and `.docUrl` — surface `docUrl` in your UX. Transport
101
+ failures throw `OwNetworkError`. `err.isValidationError` is the common branch.
214
102
 
215
- For tools that need direct OpenAI API access using OnlyWorlds tokens:
103
+ ## Canonical constants (all generated or test-gated from schema)
216
104
 
217
105
  ```typescript
218
- // Get encrypted OpenAI key (requires 100+ tokens)
219
- const access = await client.tokens.getAccessKey();
220
-
221
- console.log('Session ID:', access.session_id);
222
- console.log('Expires:', access.expires_at);
223
- console.log('Available tokens:', access.tokens_available);
224
-
225
- // Decrypt the key client-side (see base-tool for full implementation)
226
- // 1. Derive decryption key from world ID using SHA-256
227
- // 2. Use 'fernet' npm package to decrypt
228
- // 3. Use decrypted OpenAI key for direct API calls
229
- // 4. Report usage with session_id
230
-
231
- // See base-tool/src/llm/token-service.ts:99-235 for complete example
106
+ import {
107
+ ELEMENT_TYPES, // the 22 slugs (and the ElementType union)
108
+ ELEMENT_ICONS, // Material Symbols icon per type
109
+ ELEMENT_LABELS, // plural display labels
110
+ ELEMENT_SECTIONS, // canonical field grouping + display order
111
+ FIELD_SCHEMA, // per-field type/target metadata
112
+ elementColor, // canonical colour: family carries COLOUR, icon carries TYPE
113
+ } from '@onlyworlds/sdk';
114
+
115
+ elementColor('character', 'dark'); // '#3987e5' — four CVD-validated families
116
+ // Always pair colour with icon + label; colour alone is not accessible.
232
117
  ```
233
118
 
234
- **Full decryption implementation** (based on base-tool):
119
+ The full schema with per-field meaning lives in [SCHEMA.md](SCHEMA.md) (generated, ships in this
120
+ package). AI agents: read [AGENTS.md](AGENTS.md) first.
235
121
 
236
- ```typescript
237
- import { fernet } from 'fernet';
238
-
239
- // Derive decryption key from world ID
240
- async function deriveKey(worldId: string): Promise<string> {
241
- const salt = 'onlyworlds-token-api-2024-public-salt';
242
- const keyMaterial = `${worldId}:${salt}`;
243
- const encoder = new TextEncoder();
244
- const data = encoder.encode(keyMaterial);
245
- const hashBuffer = await crypto.subtle.digest('SHA-256', data);
246
- const hashArray = Array.from(new Uint8Array(hashBuffer));
247
- const base64 = btoa(String.fromCharCode(...hashArray));
248
- return base64.replace(/\+/g, '-').replace(/\//g, '_');
249
- }
250
-
251
- // Decrypt the API key
252
- async function decryptApiKey(encryptedKey: string, worldId: string): Promise<string> {
253
- const derivedKey = await deriveKey(worldId);
254
- const secret = new fernet.Secret(derivedKey);
255
- const token = new fernet.Token({
256
- secret: secret,
257
- token: encryptedKey,
258
- ttl: 0 // Don't enforce TTL client-side
259
- });
260
- return token.decode();
261
- }
262
-
263
- // Usage
264
- const world = await client.worlds.get();
265
- const access = await client.tokens.getAccessKey();
266
- const apiKey = await decryptApiKey(access.encrypted_key, world.id);
267
-
268
- // Use apiKey for OpenAI API calls, then report usage:
269
- await client.tokens.consume({
270
- amount: tokensUsed,
271
- sessionId: access.session_id,
272
- service: 'direct_openai',
273
- metadata: { model: 'gpt-4', /* ... */ }
274
- });
275
- ```
276
-
277
- ### Session Management
122
+ ## Token rating system
278
123
 
279
124
  ```typescript
280
- // Revoke a specific session
281
- await client.tokens.revokeSession(sessionId);
282
-
283
- // Revoke all sessions (emergency cleanup)
284
- const result = await client.tokens.revokeAllSessions();
285
- console.log(`Revoked ${result.sessions_revoked} sessions`);
125
+ import { TokenResource } from '@onlyworlds/sdk';
126
+ const tokens = new TokenResource(writer); // OwV2Client.request() satisfies TokenTransport
127
+ const status = await tokens.getStatus();
286
128
  ```
287
129
 
288
- ### Encryption Info
289
-
290
- Get public encryption details (no auth required):
130
+ ## AI access — when to use which
291
131
 
292
- ```typescript
293
- const info = await client.tokens.getEncryptionInfo();
294
- console.log('Algorithm:', info.algorithm);
295
- console.log('Key derivation:', info.key_derivation);
296
- console.log('Public salt:', info.salt);
297
- console.log(info.javascript_example);
298
- ```
132
+ For **known, deterministic operations** (CRUD, sync, bulk) use this SDK — typed calls, no
133
+ tool-schema overhead. For **live exploration of a user's world from a chat/agent context**, use
134
+ the MCP server at `https://www.onlyworlds.com/mcp` (same `API-Key`/`API-Pin` headers, 11 tools;
135
+ unaffected by SDK versioning).
299
136
 
300
137
  ## License
301
138
 
302
- MIT License - see [LICENSE](LICENSE) file for details
139
+ MIT
303
140
 
304
141
  ## Links
305
142
 
306
- - [OnlyWorlds Website](https://onlyworlds.com)
307
- - [Documentation](https://onlyworlds.github.io/)
308
- - [NPM Package](https://www.npmjs.com/package/@onlyworlds/sdk)
309
- - [Report Issues](https://github.com/OnlyWorlds/sdk/issues)
143
+ - [OnlyWorlds](https://www.onlyworlds.com) · [Docs](https://onlyworlds.github.io) · [API reference](https://www.onlyworlds.com/api/docs)
144
+ - [Issues](https://github.com/OnlyWorlds/sdk/issues) · [CHANGELOG](CHANGELOG.md) · [Migration 3→4](docs/migrating-3-to-4.md)