@space3-npm/cybersoul-client 1.4.9 → 1.4.11
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/dist/client.js +48 -10
- package/dist/errors.d.ts +82 -0
- package/dist/errors.js +110 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { InteractRequestType, } from "./types.js";
|
|
2
2
|
import { robustJsonParse } from "./utils/json.utils.js";
|
|
3
3
|
import { GenericLLMProvider } from "./llm.provider.js";
|
|
4
|
+
import { CyberSoulApiError, CyberSoulAuthError, CyberSoulInsufficientPointsError, CyberSoulNetworkError, CyberSoulTimeoutError, CyberSoulWalletError, } from "./errors.js";
|
|
4
5
|
export class CyberSoulClient {
|
|
5
6
|
config;
|
|
6
7
|
llm;
|
|
@@ -47,10 +48,12 @@ export class CyberSoulClient {
|
|
|
47
48
|
}
|
|
48
49
|
catch (error) {
|
|
49
50
|
if (error instanceof Error && error.name === "AbortError") {
|
|
50
|
-
lastError = new
|
|
51
|
+
lastError = new CyberSoulTimeoutError(endpoint, method, this.requestTimeoutMs);
|
|
51
52
|
}
|
|
52
53
|
else {
|
|
53
|
-
lastError = error
|
|
54
|
+
lastError = new CyberSoulNetworkError(endpoint, method, error instanceof Error
|
|
55
|
+
? `Network request failed: ${method} ${endpoint}: ${error.message}`
|
|
56
|
+
: `Network request failed: ${method} ${endpoint}`, { cause: error });
|
|
54
57
|
}
|
|
55
58
|
if (attempt >= retryLimit) {
|
|
56
59
|
throw lastError;
|
|
@@ -60,14 +63,34 @@ export class CyberSoulClient {
|
|
|
60
63
|
clearTimeout(timeout);
|
|
61
64
|
}
|
|
62
65
|
}
|
|
66
|
+
// Defensive: the loop above either returns a Response, throws the
|
|
67
|
+
// wrapped network error, or continues to the next attempt. Reaching
|
|
68
|
+
// this point means the retry budget was exhausted without ever
|
|
69
|
+
// populating `lastError` (logically unreachable, but TypeScript
|
|
70
|
+
// cannot prove that).
|
|
63
71
|
throw lastError instanceof Error
|
|
64
72
|
? lastError
|
|
65
|
-
: new
|
|
73
|
+
: new CyberSoulNetworkError(endpoint, method, `Request failed unexpectedly: ${method} ${endpoint}`);
|
|
66
74
|
}
|
|
67
75
|
async fetchRemoteState() {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
const endpoint = "/api/v1/cyber-soul/state";
|
|
77
|
+
const res = await this.apiFetch(endpoint);
|
|
78
|
+
if (!res.ok) {
|
|
79
|
+
let body;
|
|
80
|
+
try {
|
|
81
|
+
body = await res.json();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
body = undefined;
|
|
85
|
+
}
|
|
86
|
+
const detail = (body && typeof body === "object" && "error" in body
|
|
87
|
+
? String(body.error)
|
|
88
|
+
: undefined) ?? `HTTP ${res.status}`;
|
|
89
|
+
if (res.status === 401 || res.status === 403) {
|
|
90
|
+
throw new CyberSoulAuthError(endpoint, "GET", res.status, `Character credential rejected by backend (${detail}). The character may have been deleted.`, body);
|
|
91
|
+
}
|
|
92
|
+
throw new CyberSoulApiError(endpoint, "GET", res.status, `Failed to fetch character state: ${detail}`, body);
|
|
93
|
+
}
|
|
71
94
|
const json = await res.json();
|
|
72
95
|
return json.data;
|
|
73
96
|
}
|
|
@@ -99,7 +122,8 @@ export class CyberSoulClient {
|
|
|
99
122
|
return availableOutfits;
|
|
100
123
|
}
|
|
101
124
|
async generatePrimitive(type, payload) {
|
|
102
|
-
const
|
|
125
|
+
const endpoint = `/api/v1/cyber-soul/${type}/generate`;
|
|
126
|
+
const res = await this.apiFetch(endpoint, {
|
|
103
127
|
method: "POST",
|
|
104
128
|
body: JSON.stringify(payload),
|
|
105
129
|
});
|
|
@@ -110,9 +134,23 @@ export class CyberSoulClient {
|
|
|
110
134
|
}
|
|
111
135
|
catch (e) { }
|
|
112
136
|
const msg = errData?.message || errData?.error || `Status ${res.status}`;
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
137
|
+
const code = errData?.code || "UNKNOWN_ERROR";
|
|
138
|
+
const detailedMessage = `Failed to generate ${type}: ${msg}`;
|
|
139
|
+
if (res.status === 402 || code === "INSUFFICIENT_POINTS") {
|
|
140
|
+
throw new CyberSoulInsufficientPointsError(endpoint, "POST", res.status, detailedMessage, errData, code);
|
|
141
|
+
}
|
|
142
|
+
if (code === "WALLET_DEDUCTION_ERROR") {
|
|
143
|
+
throw new CyberSoulWalletError(endpoint, "POST", res.status, detailedMessage, errData, code);
|
|
144
|
+
}
|
|
145
|
+
if (res.status === 401 || res.status === 403) {
|
|
146
|
+
throw new CyberSoulAuthError(endpoint, "POST", res.status, detailedMessage, errData);
|
|
147
|
+
}
|
|
148
|
+
const apiErr = new CyberSoulApiError(endpoint, "POST", res.status, detailedMessage, errData);
|
|
149
|
+
// Preserve the legacy duck-typed `code` field so existing callers
|
|
150
|
+
// that branch on `e.code` (including this SDK's own `interact()`
|
|
151
|
+
// mediaTasks catch block) keep working unchanged.
|
|
152
|
+
apiErr.code = code;
|
|
153
|
+
throw apiErr;
|
|
116
154
|
}
|
|
117
155
|
return res.json();
|
|
118
156
|
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error hierarchy thrown by the CyberSoul SDK.
|
|
3
|
+
*
|
|
4
|
+
* Consumers should branch on `instanceof` rather than parsing error
|
|
5
|
+
* messages — message strings are not a stable API.
|
|
6
|
+
*/
|
|
7
|
+
export declare class CyberSoulError extends Error {
|
|
8
|
+
/** Stable discriminator usable in serialized logs / event payloads. */
|
|
9
|
+
readonly kind: string;
|
|
10
|
+
constructor(kind: string, message: string, options?: {
|
|
11
|
+
cause?: unknown;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The underlying fetch call never produced a response (DNS failure,
|
|
16
|
+
* connection refused, TLS error, offline, etc.). The remote service may
|
|
17
|
+
* or may not have processed the request; callers should treat this as a
|
|
18
|
+
* transient failure and retry later when connectivity is restored.
|
|
19
|
+
*/
|
|
20
|
+
export declare class CyberSoulNetworkError extends CyberSoulError {
|
|
21
|
+
readonly endpoint: string;
|
|
22
|
+
readonly method: string;
|
|
23
|
+
constructor(endpoint: string, method: string, message: string, options?: {
|
|
24
|
+
cause?: unknown;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The request was aborted because it exceeded the configured
|
|
29
|
+
* `requestTimeoutMs`. A specialization of network error — callers that
|
|
30
|
+
* want to distinguish "no connection" from "slow connection" can use
|
|
31
|
+
* `instanceof CyberSoulTimeoutError`.
|
|
32
|
+
*/
|
|
33
|
+
export declare class CyberSoulTimeoutError extends CyberSoulNetworkError {
|
|
34
|
+
readonly timeoutMs: number;
|
|
35
|
+
constructor(endpoint: string, method: string, timeoutMs: number);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The backend returned a non-2xx HTTP response. Callers can inspect
|
|
39
|
+
* `status` to decide how to react (e.g. surface a user-facing message
|
|
40
|
+
* for 4xx vs. retry on 5xx).
|
|
41
|
+
*/
|
|
42
|
+
export declare class CyberSoulApiError extends CyberSoulError {
|
|
43
|
+
readonly status: number;
|
|
44
|
+
readonly endpoint: string;
|
|
45
|
+
readonly method: string;
|
|
46
|
+
/** Parsed JSON body when available, otherwise `undefined`. */
|
|
47
|
+
readonly body?: unknown;
|
|
48
|
+
constructor(endpoint: string, method: string, status: number, message: string, body?: unknown, kind?: string);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The backend rejected the SDK's character credential (HTTP 401/403 on
|
|
52
|
+
* a character-scoped endpoint). The most common cause is that the
|
|
53
|
+
* character profile bound to this `characterKey` has been deleted on
|
|
54
|
+
* the backend; the binding is effectively terminal for this client.
|
|
55
|
+
*/
|
|
56
|
+
export declare class CyberSoulAuthError extends CyberSoulApiError {
|
|
57
|
+
constructor(endpoint: string, method: string, status: number, message: string, body?: unknown);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The backend rejected a paid action because the user's wallet does
|
|
61
|
+
* not have enough points to cover it (HTTP 402 / `INSUFFICIENT_POINTS`).
|
|
62
|
+
* Callers should surface a top-up prompt rather than retrying.
|
|
63
|
+
*/
|
|
64
|
+
export declare class CyberSoulInsufficientPointsError extends CyberSoulApiError {
|
|
65
|
+
/**
|
|
66
|
+
* Backend-supplied machine code. Always `"INSUFFICIENT_POINTS"` today;
|
|
67
|
+
* kept as a field so future variants (e.g. per-feature paywalls) can
|
|
68
|
+
* piggy-back on the same class.
|
|
69
|
+
*/
|
|
70
|
+
readonly code: string;
|
|
71
|
+
constructor(endpoint: string, method: string, status: number, message: string, body?: unknown, code?: string);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The wallet-deduction call failed for a reason *other than* insufficient
|
|
75
|
+
* balance (e.g. wallet service unavailable, accounting bug). Distinct from
|
|
76
|
+
* `CyberSoulInsufficientPointsError` because the user can't fix this by
|
|
77
|
+
* topping up — it's an upstream infrastructure issue.
|
|
78
|
+
*/
|
|
79
|
+
export declare class CyberSoulWalletError extends CyberSoulApiError {
|
|
80
|
+
readonly code: string;
|
|
81
|
+
constructor(endpoint: string, method: string, status: number, message: string, body?: unknown, code?: string);
|
|
82
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed error hierarchy thrown by the CyberSoul SDK.
|
|
3
|
+
*
|
|
4
|
+
* Consumers should branch on `instanceof` rather than parsing error
|
|
5
|
+
* messages — message strings are not a stable API.
|
|
6
|
+
*/
|
|
7
|
+
export class CyberSoulError extends Error {
|
|
8
|
+
/** Stable discriminator usable in serialized logs / event payloads. */
|
|
9
|
+
kind;
|
|
10
|
+
constructor(kind, message, options) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = new.target.name;
|
|
13
|
+
this.kind = kind;
|
|
14
|
+
if (options?.cause !== undefined) {
|
|
15
|
+
// ES2022 `cause` field. We assign defensively so older targets
|
|
16
|
+
// don't drop it on the floor.
|
|
17
|
+
this.cause = options.cause;
|
|
18
|
+
}
|
|
19
|
+
// Preserve prototype chain for downlevel-transpiled `extends`.
|
|
20
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The underlying fetch call never produced a response (DNS failure,
|
|
25
|
+
* connection refused, TLS error, offline, etc.). The remote service may
|
|
26
|
+
* or may not have processed the request; callers should treat this as a
|
|
27
|
+
* transient failure and retry later when connectivity is restored.
|
|
28
|
+
*/
|
|
29
|
+
export class CyberSoulNetworkError extends CyberSoulError {
|
|
30
|
+
endpoint;
|
|
31
|
+
method;
|
|
32
|
+
constructor(endpoint, method, message, options) {
|
|
33
|
+
super("network", message, options);
|
|
34
|
+
this.endpoint = endpoint;
|
|
35
|
+
this.method = method;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The request was aborted because it exceeded the configured
|
|
40
|
+
* `requestTimeoutMs`. A specialization of network error — callers that
|
|
41
|
+
* want to distinguish "no connection" from "slow connection" can use
|
|
42
|
+
* `instanceof CyberSoulTimeoutError`.
|
|
43
|
+
*/
|
|
44
|
+
export class CyberSoulTimeoutError extends CyberSoulNetworkError {
|
|
45
|
+
timeoutMs;
|
|
46
|
+
constructor(endpoint, method, timeoutMs) {
|
|
47
|
+
super(endpoint, method, `Request timed out after ${timeoutMs}ms: ${method} ${endpoint}`);
|
|
48
|
+
this.timeoutMs = timeoutMs;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The backend returned a non-2xx HTTP response. Callers can inspect
|
|
53
|
+
* `status` to decide how to react (e.g. surface a user-facing message
|
|
54
|
+
* for 4xx vs. retry on 5xx).
|
|
55
|
+
*/
|
|
56
|
+
export class CyberSoulApiError extends CyberSoulError {
|
|
57
|
+
status;
|
|
58
|
+
endpoint;
|
|
59
|
+
method;
|
|
60
|
+
/** Parsed JSON body when available, otherwise `undefined`. */
|
|
61
|
+
body;
|
|
62
|
+
constructor(endpoint, method, status, message, body, kind = "api") {
|
|
63
|
+
super(kind, message);
|
|
64
|
+
this.status = status;
|
|
65
|
+
this.endpoint = endpoint;
|
|
66
|
+
this.method = method;
|
|
67
|
+
this.body = body;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The backend rejected the SDK's character credential (HTTP 401/403 on
|
|
72
|
+
* a character-scoped endpoint). The most common cause is that the
|
|
73
|
+
* character profile bound to this `characterKey` has been deleted on
|
|
74
|
+
* the backend; the binding is effectively terminal for this client.
|
|
75
|
+
*/
|
|
76
|
+
export class CyberSoulAuthError extends CyberSoulApiError {
|
|
77
|
+
constructor(endpoint, method, status, message, body) {
|
|
78
|
+
super(endpoint, method, status, message, body, "auth");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The backend rejected a paid action because the user's wallet does
|
|
83
|
+
* not have enough points to cover it (HTTP 402 / `INSUFFICIENT_POINTS`).
|
|
84
|
+
* Callers should surface a top-up prompt rather than retrying.
|
|
85
|
+
*/
|
|
86
|
+
export class CyberSoulInsufficientPointsError extends CyberSoulApiError {
|
|
87
|
+
/**
|
|
88
|
+
* Backend-supplied machine code. Always `"INSUFFICIENT_POINTS"` today;
|
|
89
|
+
* kept as a field so future variants (e.g. per-feature paywalls) can
|
|
90
|
+
* piggy-back on the same class.
|
|
91
|
+
*/
|
|
92
|
+
code;
|
|
93
|
+
constructor(endpoint, method, status, message, body, code = "INSUFFICIENT_POINTS") {
|
|
94
|
+
super(endpoint, method, status, message, body, "insufficient-points");
|
|
95
|
+
this.code = code;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The wallet-deduction call failed for a reason *other than* insufficient
|
|
100
|
+
* balance (e.g. wallet service unavailable, accounting bug). Distinct from
|
|
101
|
+
* `CyberSoulInsufficientPointsError` because the user can't fix this by
|
|
102
|
+
* topping up — it's an upstream infrastructure issue.
|
|
103
|
+
*/
|
|
104
|
+
export class CyberSoulWalletError extends CyberSoulApiError {
|
|
105
|
+
code;
|
|
106
|
+
constructor(endpoint, method, status, message, body, code = "WALLET_DEDUCTION_ERROR") {
|
|
107
|
+
super(endpoint, method, status, message, body, "wallet");
|
|
108
|
+
this.code = code;
|
|
109
|
+
}
|
|
110
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED