@pouchy_ai/world-sdk 0.27.0 → 0.28.1
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/CHANGELOG.md +27 -0
- package/README.md +5 -3
- package/dist/index.d.ts +21 -1
- package/dist/index.js +36 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @pouchy_ai/world-sdk
|
|
2
2
|
|
|
3
|
+
## 0.28.1
|
|
4
|
+
|
|
5
|
+
- **`WorldApiError.errorId`** — the server's lookup reference (`err_…`) for a
|
|
6
|
+
persisted 5xx, when the envelope carried one. An uncaught world-plane fault is
|
|
7
|
+
sanitized to "An unexpected error occurred." before it leaves the server; the
|
|
8
|
+
`errorId` on that envelope is the one thing an operator can resolve to the
|
|
9
|
+
real cause, and the client read `error` / `code` / `retryAfterSec` and dropped
|
|
10
|
+
it — so a 5xx gave you `500 server_error` and nothing to quote. Additive;
|
|
11
|
+
absent on every 4xx and on a 5xx that was not persisted; string-only, like
|
|
12
|
+
`serverCode`. Quote it in a support request.
|
|
13
|
+
|
|
14
|
+
## 0.28.0
|
|
15
|
+
|
|
16
|
+
- **`WorldApiError.serverCode`** — the server's own machine-readable `code`
|
|
17
|
+
on a refusal, when it sent one. `code` maps the STATUS (every 409 is
|
|
18
|
+
`conflict`), and the world answers 409 for several different reasons whose
|
|
19
|
+
right response differs: `stale_deliberation` (re-run `deliberate`),
|
|
20
|
+
`episode_ended` (start the next episode), `has_instances`,
|
|
21
|
+
`episode_history_incomplete`, `story_contract_v{2,3,4}_write_disabled`. The
|
|
22
|
+
server has carried that field since those refusals were written; the client
|
|
23
|
+
read `error` into `detail` and dropped `code`, so the only thing an
|
|
24
|
+
integrator could branch on was a prose sentence that varies per site — and
|
|
25
|
+
the JSDoc on `deliberate` named a code the error never surfaced.
|
|
26
|
+
- Absent when the body carries no string `code` — "the server did not say"
|
|
27
|
+
stays distinct from a conflict with no sub-reason. Additive; nothing else
|
|
28
|
+
moves.
|
|
29
|
+
|
|
3
30
|
## 0.27.0
|
|
4
31
|
|
|
5
32
|
- **`WorldProgressCheckpointV1.publicFlags` / `publicFlagsTruncated`** — Story
|
package/README.md
CHANGED
|
@@ -249,9 +249,11 @@ an `approved` editorial can be exported.
|
|
|
249
249
|
|
|
250
250
|
**Helpers** — `signSourceRequest` (the exact canonical the server verifies),
|
|
251
251
|
`newTurnId` / `isReservedTurnId` (idempotency), `describeTurn` (read a result
|
|
252
|
-
without guessing), `WorldApiError` with typed codes, `.retryable`,
|
|
253
|
-
`
|
|
254
|
-
|
|
252
|
+
without guessing), `WorldApiError` with typed codes, `.retryable`,
|
|
253
|
+
`serverCode` (the server's own `code` on a refusal — which 409, since `code`
|
|
254
|
+
maps the status), `errorId` (the server's `err_…` lookup reference on a
|
|
255
|
+
persisted 5xx — quote it in a support request), and `rejectedEffects` (which of YOUR proposed ops the world
|
|
256
|
+
refused, and why — validation is all-or-nothing, so one bad op moves nothing).
|
|
255
257
|
|
|
256
258
|
## When a signed door refuses you
|
|
257
259
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* a project is running — which is exactly the field you reach for when a
|
|
5
5
|
* customer's integration behaves like an older SDK than they say they have.
|
|
6
6
|
* It sat at '0.1.0' for eight releases before anything compared the two. */
|
|
7
|
-
export declare const WORLD_SDK_VERSION = "0.
|
|
7
|
+
export declare const WORLD_SDK_VERSION = "0.28.1";
|
|
8
8
|
export declare const DEFAULT_BASE_URL = "https://pouchy.ai/v1";
|
|
9
9
|
/** One direction a beat could take. The WHOLE of what a deliberation shows a
|
|
10
10
|
* player: no reasoning, no role secrets, no simulated effects, no scores. */
|
|
@@ -50,6 +50,24 @@ export declare class WorldApiError extends Error {
|
|
|
50
50
|
readonly status: number;
|
|
51
51
|
/** The server's own message, when it sent one. */
|
|
52
52
|
readonly detail?: string;
|
|
53
|
+
/** The server's own machine-readable `code`, when the refusal carried one —
|
|
54
|
+
* the field a 409 uses to say WHICH conflict, since `code` above maps a
|
|
55
|
+
* status and every 409 is `conflict` there. `stale_deliberation` (re-run
|
|
56
|
+
* `deliberate`), `episode_ended` (start the next episode), `has_instances`,
|
|
57
|
+
* `episode_history_incomplete`, `story_contract_v{2,3,4}_write_disabled`
|
|
58
|
+
* are the server's vocabulary today; a refusal that carries only prose
|
|
59
|
+
* leaves this undefined — absent means "the server did not say", never
|
|
60
|
+
* "no conflict". Until 0.28.0 the client read `error` into `detail` and
|
|
61
|
+
* dropped `code` on the floor, so the one carrier an integrator could
|
|
62
|
+
* branch on never arrived. */
|
|
63
|
+
readonly serverCode?: string;
|
|
64
|
+
/** The server's lookup reference for a persisted 5xx (`err_…`), when the
|
|
65
|
+
* envelope carried one. A world-plane fault is sanitized to "An unexpected
|
|
66
|
+
* error occurred." before it leaves the server; the `errorId` is the ONE
|
|
67
|
+
* greppable thing the operator can resolve to the real cause — quote it in
|
|
68
|
+
* a support request. Absent on every 4xx and on a 5xx that was not
|
|
69
|
+
* persisted (0.28.1; until then the client dropped it). */
|
|
70
|
+
readonly errorId?: string;
|
|
53
71
|
readonly retryAfterSec?: number;
|
|
54
72
|
/** Why the world refused the effects you proposed — per op, with the
|
|
55
73
|
* server's own reason and code.
|
|
@@ -78,6 +96,8 @@ export declare class WorldApiError extends Error {
|
|
|
78
96
|
status: number;
|
|
79
97
|
message: string;
|
|
80
98
|
detail?: string;
|
|
99
|
+
serverCode?: string;
|
|
100
|
+
errorId?: string;
|
|
81
101
|
retryAfterSec?: number;
|
|
82
102
|
rejectedEffects?: readonly {
|
|
83
103
|
readonly index: number;
|
package/dist/index.js
CHANGED
|
@@ -23,7 +23,7 @@ import { createHash, createHmac, randomUUID } from 'node:crypto';
|
|
|
23
23
|
* a project is running — which is exactly the field you reach for when a
|
|
24
24
|
* customer's integration behaves like an older SDK than they say they have.
|
|
25
25
|
* It sat at '0.1.0' for eight releases before anything compared the two. */
|
|
26
|
-
export const WORLD_SDK_VERSION = '0.
|
|
26
|
+
export const WORLD_SDK_VERSION = '0.28.1';
|
|
27
27
|
export const DEFAULT_BASE_URL = 'https://pouchy.ai/v1';
|
|
28
28
|
/** Read the commit turn id out of an envelope, so the signature covers the id
|
|
29
29
|
* the server will commit under. The payload half is base64url JSON; the
|
|
@@ -60,6 +60,24 @@ export class WorldApiError extends Error {
|
|
|
60
60
|
status;
|
|
61
61
|
/** The server's own message, when it sent one. */
|
|
62
62
|
detail;
|
|
63
|
+
/** The server's own machine-readable `code`, when the refusal carried one —
|
|
64
|
+
* the field a 409 uses to say WHICH conflict, since `code` above maps a
|
|
65
|
+
* status and every 409 is `conflict` there. `stale_deliberation` (re-run
|
|
66
|
+
* `deliberate`), `episode_ended` (start the next episode), `has_instances`,
|
|
67
|
+
* `episode_history_incomplete`, `story_contract_v{2,3,4}_write_disabled`
|
|
68
|
+
* are the server's vocabulary today; a refusal that carries only prose
|
|
69
|
+
* leaves this undefined — absent means "the server did not say", never
|
|
70
|
+
* "no conflict". Until 0.28.0 the client read `error` into `detail` and
|
|
71
|
+
* dropped `code` on the floor, so the one carrier an integrator could
|
|
72
|
+
* branch on never arrived. */
|
|
73
|
+
serverCode;
|
|
74
|
+
/** The server's lookup reference for a persisted 5xx (`err_…`), when the
|
|
75
|
+
* envelope carried one. A world-plane fault is sanitized to "An unexpected
|
|
76
|
+
* error occurred." before it leaves the server; the `errorId` is the ONE
|
|
77
|
+
* greppable thing the operator can resolve to the real cause — quote it in
|
|
78
|
+
* a support request. Absent on every 4xx and on a 5xx that was not
|
|
79
|
+
* persisted (0.28.1; until then the client dropped it). */
|
|
80
|
+
errorId;
|
|
63
81
|
retryAfterSec;
|
|
64
82
|
/** Why the world refused the effects you proposed — per op, with the
|
|
65
83
|
* server's own reason and code.
|
|
@@ -84,6 +102,10 @@ export class WorldApiError extends Error {
|
|
|
84
102
|
this.status = input.status;
|
|
85
103
|
if (input.detail !== undefined)
|
|
86
104
|
this.detail = input.detail;
|
|
105
|
+
if (input.serverCode !== undefined)
|
|
106
|
+
this.serverCode = input.serverCode;
|
|
107
|
+
if (input.errorId !== undefined)
|
|
108
|
+
this.errorId = input.errorId;
|
|
87
109
|
if (input.retryAfterSec !== undefined)
|
|
88
110
|
this.retryAfterSec = input.retryAfterSec;
|
|
89
111
|
if (input.rejectedEffects !== undefined)
|
|
@@ -921,11 +943,24 @@ export class PouchyWorldClient {
|
|
|
921
943
|
: undefined;
|
|
922
944
|
const retryAfterSec = retryAfterFrom(response, parsed && typeof parsed === 'object' ? parsed : null);
|
|
923
945
|
const rejectedEffects = rejectedEffectsFrom(parsed);
|
|
946
|
+
// A string only: a body whose `code` is not text (a number, an
|
|
947
|
+
// object) would hand the integrator a value the type does not
|
|
948
|
+
// promise, so it stays absent rather than coerced.
|
|
949
|
+
const serverCode = parsed && typeof parsed === 'object' && typeof parsed.code === 'string'
|
|
950
|
+
? parsed.code
|
|
951
|
+
: undefined;
|
|
952
|
+
// Same string-only rule as `serverCode`: the envelope's lookup ref, or
|
|
953
|
+
// nothing — never a coerced non-string.
|
|
954
|
+
const errorId = parsed && typeof parsed === 'object' && typeof parsed.errorId === 'string'
|
|
955
|
+
? parsed.errorId || undefined
|
|
956
|
+
: undefined;
|
|
924
957
|
throw new WorldApiError({
|
|
925
958
|
code: codeForStatus(response.status),
|
|
926
959
|
status: response.status,
|
|
927
960
|
message: `${method} ${path} → ${response.status}`,
|
|
928
961
|
...(detail !== undefined ? { detail } : {}),
|
|
962
|
+
...(serverCode !== undefined ? { serverCode } : {}),
|
|
963
|
+
...(errorId !== undefined ? { errorId } : {}),
|
|
929
964
|
...(retryAfterSec !== undefined ? { retryAfterSec } : {}),
|
|
930
965
|
...(rejectedEffects !== undefined ? { rejectedEffects } : {})
|
|
931
966
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pouchy_ai/world-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.1",
|
|
4
4
|
"description": "Server-side TypeScript client for Pouchy World \u2014 story packages, world definitions, world sessions, coordinated turns, trusted events, replay verification and script drafts. Node only: it holds a project Secret Key and a source signing key, which never belong in a browser or a mobile app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|