@onlyworlds/sdk 4.55.0 → 4.56.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 +6 -1
- package/CHANGELOG.md +12 -0
- package/SCHEMA.md +1 -1
- package/dist/index.d.ts +26 -2
- package/dist/index.js +20 -5
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# For AI agents using @onlyworlds/sdk
|
|
2
2
|
|
|
3
|
-
**Current as of**: SDK **4.x** · schema-dist **v0.33.0-dist.
|
|
3
|
+
**Current as of**: SDK **4.x** · schema-dist **v0.33.0-dist.46** (canonical 00.33.00).
|
|
4
4
|
This line is asserted by `codegen:check` in CI — if the pin moves and this file is not
|
|
5
5
|
re-read against it, the check fails rather than letting this document rot quietly.
|
|
6
6
|
|
|
@@ -109,6 +109,11 @@ against live data). The v1 surface (`OnlyWorldsClient`, the `ElementType` enum)
|
|
|
109
109
|
`mcp`, `declared`, `api`, `v1`, `sync`, `server`), and a `/changes` delete carries
|
|
110
110
|
`deleted_by` and `deleted_via`; `isAgentDoor(door)` is true for the first three. An agent
|
|
111
111
|
seat's key is recorded as an agent without the option. Never set it in a tool people use.
|
|
112
|
+
- **Name your tool** (since 4.56.0): `new OwV2Client({ ..., client: 'atlas' })` sends
|
|
113
|
+
`X-OW-Client: atlas` on every element write (never on a read); left out, it sends `sdk`. The name
|
|
114
|
+
is lower case letters, digits and hyphens, 1 to 32 characters, else a TypeError at construction.
|
|
115
|
+
keel stores it as `changed_client` on the element and `deleted_client` on a `/changes` delete:
|
|
116
|
+
the client's claim, never proof, and null when none was sent.
|
|
112
117
|
- A guest or player reads what its own Character's sheet links to as a **stub**, marked
|
|
113
118
|
`known_of: true` (`isKnownOf(el)`): only `id`, `type`, `name`, `description`, `supertype`,
|
|
114
119
|
`subtype`, `image_url`, the timestamps and the fields its type lists in `PUBLIC_FIELDS` are
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ earlier history lives in git log only.
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [4.56.0] - 2026-10-22
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **The client's name** (keel #520, live 2026-10-22; Orrery's `client-name.md`, decision 2): a constructor option `client`, default `'sdk'`, sent as `X-OW-Client` on every element write (`create`, `upsert`, `patch`, `delete`, `editLinks`, `bulk`, `adopt`) and on no read. keel stores it on the element as `changed_client`, so a reader can tell which tool made the last change (`new OwV2Client({ ..., client: 'atlas' })`). The rule is keel's, exact here: lower case letters, digits and hyphens, 1 to 32 characters (`[a-z0-9-]{1,32}`). Anything else, a capital, a space, an empty string, 33 characters or a value that is not a string, is a TypeError at construction naming the option and the rule, and nothing is trimmed; keel's own fence for a stranger's header is to store null, never a 422. The name is the client's claim about itself, never proof; it changes no door and no permission, and `agent` still decides `X-OW-Agent`.
|
|
13
|
+
- **`changed_client`** on `OwElementBase` (`string | null`, server-managed, read-only, beside `changed_by` and `changed_via`): the name the last write gave, null when it gave none or one outside the rule, for keel's own writes, and for changes from before names were recorded. Sent back in a write it is ignored. **`deleted_client`** on a `/changes` delete (`OwChangeDelete`, beside `deleted_by` and `deleted_via`), the same for the delete; null on a `hidden` row.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **The constructor refuses an unknown key by name**, as every options object has since 4.52.0: `new OwV2Client({ clinet: 'atlas' })` is a `TypeError` naming the key and the eight the constructor knows, where it fell back to the defaults silently before. Every known caller (Atlas, Lantern, the toolkit) passes known keys only.
|
|
18
|
+
- **Schema repinned to schema-dist v0.33.0-dist.46** (same canonical 00.33.00). The dist's example export (`example/world-export.json`) gains `changed_client: null` on its bodies, `walk/lint_folder.py`'s server-key set names `changed_client`, and the README's sentence on server keys names it; `VERSION` and `MANIFEST.json` carry the new serial; no schema file moved. Generated output moves its provenance lines and gains `changed_client`.
|
|
19
|
+
|
|
8
20
|
## [4.55.0] - 2026-10-22
|
|
9
21
|
|
|
10
22
|
### Added
|
package/SCHEMA.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OnlyWorlds Schema Reference
|
|
2
2
|
|
|
3
|
-
**Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.33.0-dist.
|
|
3
|
+
**Source**: https://github.com/OnlyWorlds/schema-dist @ **v0.33.0-dist.46** — canonical schema **00.33.00**, published 2026-10-22.
|
|
4
4
|
|
|
5
5
|
GENERATED from the canonical schema YAML — do not hand-edit (regenerate: `python codegen/generate_types.py`).
|
|
6
6
|
Written for both humans and AI agents reading this package locally.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Every element carries these. The extension index signature admits namespaced
|
|
2
2
|
* pass-through fields (atlas_* / shadow_* / x_*) returned verbatim by the server.
|
|
3
3
|
* Derived from base_properties.yaml: `World` is dropped (the API rejects it in
|
|
4
|
-
* bodies -- the key determines the world) and the
|
|
4
|
+
* bodies -- the key determines the world) and the eight server-managed fields are
|
|
5
5
|
* added, since they ride every wire body and appear in no element YAML; `known_of`
|
|
6
6
|
* rides only a stub. */
|
|
7
7
|
interface OwElementBase {
|
|
@@ -31,6 +31,8 @@ interface OwElementBase {
|
|
|
31
31
|
changed_by?: string | null;
|
|
32
32
|
/** The door of the last write (server-managed, read-only): `seat` (an agent seat), `mcp`, `declared` (a client that sent X-OW-Agent), then `api`, `v1`, `sync`, `server` (keel's own writes) or `site` (the owner signed in on onlyworlds.com; keel PR 160). The first three are agent-made. Null for anything last changed before writes recorded it. */
|
|
33
33
|
changed_via?: 'seat' | 'mcp' | 'declared' | 'api' | 'v1' | 'sync' | 'server' | 'site' | null;
|
|
34
|
+
/** The name the client gave in the X-OW-Client header on the last write (server-managed, read-only): lower case letters, digits and hyphens, 1 to 32 characters, such as `sdk` or `atlas`. It is the client's claim about itself, never proof, and says nothing about whether an agent drove the write (that is `changed_via`). Null when the last write sent no name or one outside the rule, for keel's own writes, and for anything last changed before names were recorded. Sent in a write it is ignored. This SDK sends its `client` option, `sdk` by default. */
|
|
35
|
+
changed_client?: string | null;
|
|
34
36
|
/** Present, and true, only when the world's owner or a co-builder hid this element and this reader still sees it (server-managed, read-only): the owner, a co-builder, a key the owner minted, or the member who made it; to every other reader the element does not exist. Absent otherwise, whatever `fields` asked; on the read, the list, the change feed's upserts and MCP, never in the download, world sync or v1. Sent in a write it is ignored. */
|
|
35
37
|
hidden?: true;
|
|
36
38
|
/** Present, and true, only on a stub (server-managed, read-only): an element a guest or player reaches only through its own Character's sheet. A stub keeps id, type, name, description, supertype, subtype, image_url, created_at, updated_at and change_seq, and the fields its type lists in PUBLIC_FIELDS with their values; every other field reads unset ("", null, []), created_by/changed_by/changed_via null, no extension fields, and its files are 404. Its empties are not values and not a deletion: never write a stub back. Absent: the element is whole. See isKnownOf(). */
|
|
@@ -1981,6 +1983,12 @@ interface OwChangeDelete {
|
|
|
1981
1983
|
deleted_by?: string | null;
|
|
1982
1984
|
/** The door the delete came through (see {@link OwWriteDoor}); null for deletes before writes recorded it. */
|
|
1983
1985
|
deleted_via?: OwWriteDoor | null;
|
|
1986
|
+
/**
|
|
1987
|
+
* The name the deleting client gave in its `X-OW-Client` header (keel #520), as an element's
|
|
1988
|
+
* `changed_client`: the client's claim, never proof. Null when none was recorded, and on a
|
|
1989
|
+
* `hidden` row (a hide carries no client).
|
|
1990
|
+
*/
|
|
1991
|
+
deleted_client?: string | null;
|
|
1984
1992
|
/**
|
|
1985
1993
|
* Why the element left this reader's view (keel #421): `deleted` (it is gone; a GET answers 410),
|
|
1986
1994
|
* `hidden` (the world's owner or a co-builder hid it from this reader; it still exists, a GET answers
|
|
@@ -2812,6 +2820,18 @@ interface OwClientConfig {
|
|
|
2812
2820
|
* as an agent without it.
|
|
2813
2821
|
*/
|
|
2814
2822
|
agent?: boolean;
|
|
2823
|
+
/**
|
|
2824
|
+
* This client's own name, sent as `X-OW-Client` on every element write (create, upsert, patch,
|
|
2825
|
+
* delete, editLinks, bulk, adopt) and on no read (keel #520). keel stores it on the element as
|
|
2826
|
+
* `changed_client`, and on a /changes delete as `deleted_client`, so a reader can tell which tool
|
|
2827
|
+
* made a change: `'atlas'`, `'lantern'`, your app's name. Default `'sdk'`.
|
|
2828
|
+
*
|
|
2829
|
+
* The rule: lower case letters, digits and hyphens, 1 to 32 characters (`[a-z0-9-]{1,32}`), no
|
|
2830
|
+
* version (`'atlas'`, not `'atlas-1.76'`). Anything else is a TypeError when the client is
|
|
2831
|
+
* constructed, and nothing is trimmed. It is the client's claim about itself, not proof, and it
|
|
2832
|
+
* changes no permission and no door: whether an agent made a write is `agent`'s business.
|
|
2833
|
+
*/
|
|
2834
|
+
client?: string;
|
|
2815
2835
|
}
|
|
2816
2836
|
|
|
2817
2837
|
/**
|
|
@@ -3158,6 +3178,8 @@ declare class OwV2Client {
|
|
|
3158
3178
|
private readonly apiPin;
|
|
3159
3179
|
private readonly fetchImpl;
|
|
3160
3180
|
private readonly agent;
|
|
3181
|
+
/** The name sent as X-OW-Client on element writes (keel #520), checked at construction. */
|
|
3182
|
+
private readonly clientName;
|
|
3161
3183
|
constructor(config?: OwClientConfig);
|
|
3162
3184
|
/** GET /health -- unauthenticated liveness pulse. */
|
|
3163
3185
|
health(): Promise<unknown>;
|
|
@@ -3763,8 +3785,10 @@ declare class OwV2Client {
|
|
|
3763
3785
|
allowEmpty?: boolean;
|
|
3764
3786
|
replayAware?: boolean;
|
|
3765
3787
|
/** A `change_seq` to send as `If-Match` (keel #210); a whole number, else TypeError before sending. */
|
|
3766
|
-
/**
|
|
3788
|
+
/** A write keel's document lists X-OW-Agent on (the element writes, hide and unhide, the file ticket, setMyCharacter, mintWorldKey): where an agent client sends it. */
|
|
3767
3789
|
write?: boolean;
|
|
3790
|
+
/** One of the seven element writes keel reads X-OW-Client on (keel #520: create, put, patch, delete, links, bulk, adopt): where the client's name goes. */
|
|
3791
|
+
elementWrite?: boolean;
|
|
3768
3792
|
ifMatch?: number;
|
|
3769
3793
|
}): Promise<T>;
|
|
3770
3794
|
}
|
package/dist/index.js
CHANGED
|
@@ -504,6 +504,8 @@ var DEFAULT_PAGE_SIZE = 100;
|
|
|
504
504
|
var DEFAULT_CHANGES_PAGE_SIZE = 100;
|
|
505
505
|
var OwV2Client = class {
|
|
506
506
|
constructor(config = {}) {
|
|
507
|
+
only("new OwV2Client", config, CLIENT_CONFIG_KEYS);
|
|
508
|
+
this.clientName = clientNameOf(config.client);
|
|
507
509
|
this.apiKey = config.apiKey ?? "";
|
|
508
510
|
this.apiPin = config.apiPin || void 0;
|
|
509
511
|
this.keyKind = config.apiKey ? detectKeyKind(config.apiKey) : "none";
|
|
@@ -649,6 +651,7 @@ var OwV2Client = class {
|
|
|
649
651
|
}
|
|
650
652
|
return this.request("POST", `/${type}/`, {
|
|
651
653
|
write: true,
|
|
654
|
+
elementWrite: true,
|
|
652
655
|
body,
|
|
653
656
|
idempotencyKey: opts.idempotencyKey
|
|
654
657
|
});
|
|
@@ -660,7 +663,7 @@ var OwV2Client = class {
|
|
|
660
663
|
*/
|
|
661
664
|
async upsert(type, id, element) {
|
|
662
665
|
refuseKnownOf(element, "upsert");
|
|
663
|
-
return this.request("PUT", `/${type}/${id}/`, { write: true, body: sanitizePayload(element) });
|
|
666
|
+
return this.request("PUT", `/${type}/${id}/`, { write: true, elementWrite: true, body: sanitizePayload(element) });
|
|
664
667
|
}
|
|
665
668
|
/**
|
|
666
669
|
* PATCH /{type}/{id}/ -- partial update. DESTRUCTIVE on sent fields: arrays
|
|
@@ -675,7 +678,7 @@ var OwV2Client = class {
|
|
|
675
678
|
async patch(type, id, partial, opts = {}) {
|
|
676
679
|
only("patch", opts, ["ifMatch"]);
|
|
677
680
|
refuseKnownOf(partial, "patch");
|
|
678
|
-
return this.request("PATCH", `/${type}/${id}/`, { write: true, body: sanitizePayload(partial), ifMatch: opts.ifMatch });
|
|
681
|
+
return this.request("PATCH", `/${type}/${id}/`, { write: true, elementWrite: true, body: sanitizePayload(partial), ifMatch: opts.ifMatch });
|
|
679
682
|
}
|
|
680
683
|
/**
|
|
681
684
|
* DELETE /{type}/{id}/ -- idempotent (204 on absent). Server writes a
|
|
@@ -683,7 +686,7 @@ var OwV2Client = class {
|
|
|
683
686
|
* transaction -- no client-side unlink pass needed, ever.
|
|
684
687
|
*/
|
|
685
688
|
async delete(type, id) {
|
|
686
|
-
await this.request("DELETE", `/${type}/${id}/`, { write: true, allowEmpty: true });
|
|
689
|
+
await this.request("DELETE", `/${type}/${id}/`, { write: true, elementWrite: true, allowEmpty: true });
|
|
687
690
|
}
|
|
688
691
|
/**
|
|
689
692
|
* POST /{type}/{id}/links/{field} with {add, remove} -- atomic link merge.
|
|
@@ -695,7 +698,7 @@ var OwV2Client = class {
|
|
|
695
698
|
async editLinks(type, id, field, edit, opts = {}) {
|
|
696
699
|
only("editLinks", opts, ["ifMatch"]);
|
|
697
700
|
only("editLinks", edit, ["add", "remove"], "The edit is { add?: string[], remove?: string[] }.");
|
|
698
|
-
return this.request("POST", `/${type}/${id}/links/${field}`, { write: true, body: edit, ifMatch: opts.ifMatch });
|
|
701
|
+
return this.request("POST", `/${type}/${id}/links/${field}`, { write: true, elementWrite: true, body: edit, ifMatch: opts.ifMatch });
|
|
699
702
|
}
|
|
700
703
|
/**
|
|
701
704
|
* POST /{type}/{id}/adopt with {member} -- change who made an element (keel #427, D141).
|
|
@@ -711,7 +714,7 @@ var OwV2Client = class {
|
|
|
711
714
|
*/
|
|
712
715
|
async adopt(type, id, member) {
|
|
713
716
|
if (typeof member !== "string" || member === "") throw new TypeError('adopt: member must be a membership id or "owner"');
|
|
714
|
-
return this.request("POST", `/${type}/${id}/adopt`, { write: true, body: { member } });
|
|
717
|
+
return this.request("POST", `/${type}/${id}/adopt`, { write: true, elementWrite: true, body: { member } });
|
|
715
718
|
}
|
|
716
719
|
// -- Bulk ----------------------------------------------------------------
|
|
717
720
|
/**
|
|
@@ -745,6 +748,7 @@ var OwV2Client = class {
|
|
|
745
748
|
};
|
|
746
749
|
return this.request("POST", "/bulk/", {
|
|
747
750
|
write: true,
|
|
751
|
+
elementWrite: true,
|
|
748
752
|
body,
|
|
749
753
|
idempotencyKey: opts.idempotencyKey,
|
|
750
754
|
replayAware: true
|
|
@@ -1511,6 +1515,7 @@ var OwV2Client = class {
|
|
|
1511
1515
|
if (opts.idempotencyKey) headers["Idempotency-Key"] = opts.idempotencyKey;
|
|
1512
1516
|
if (opts.ifMatch !== void 0) headers["If-Match"] = `"${opts.ifMatch}"`;
|
|
1513
1517
|
if (this.agent && opts.write) headers["X-OW-Agent"] = "1";
|
|
1518
|
+
if (opts.elementWrite) headers["X-OW-Client"] = this.clientName;
|
|
1514
1519
|
let res;
|
|
1515
1520
|
try {
|
|
1516
1521
|
res = await this.fetchImpl(url, {
|
|
@@ -1670,6 +1675,16 @@ function only(method, obj, keys, hint = "") {
|
|
|
1670
1675
|
}
|
|
1671
1676
|
}
|
|
1672
1677
|
}
|
|
1678
|
+
var CLIENT_CONFIG_KEYS = ["apiKey", "apiPin", "baseUrl", "pageSize", "changesPageSize", "fetch", "agent", "client"];
|
|
1679
|
+
var CLIENT_NAME_RULE = /^[a-z0-9-]{1,32}$/;
|
|
1680
|
+
var DEFAULT_CLIENT_NAME = "sdk";
|
|
1681
|
+
function clientNameOf(value) {
|
|
1682
|
+
if (value === void 0) return DEFAULT_CLIENT_NAME;
|
|
1683
|
+
if (typeof value !== "string" || !CLIENT_NAME_RULE.test(value)) {
|
|
1684
|
+
throw new TypeError(`OwV2Client: client must be lower case letters, digits and hyphens, 1 to 32 characters ([a-z0-9-]{1,32}), such as 'atlas'; got ${JSON.stringify(value) ?? String(value)}. It is sent as X-OW-Client on writes; leave it out for '${DEFAULT_CLIENT_NAME}'.`);
|
|
1685
|
+
}
|
|
1686
|
+
return value;
|
|
1687
|
+
}
|
|
1673
1688
|
function buildQuery(params) {
|
|
1674
1689
|
const q = new URLSearchParams();
|
|
1675
1690
|
for (const [k, v] of Object.entries(params)) {
|