@rynx-ai/remote-runtime-client 0.1.9
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/browser-surface-client.d.ts +31 -0
- package/dist/browser-surface-client.js +785 -0
- package/dist/client.d.ts +86 -0
- package/dist/client.js +1915 -0
- package/dist/credential.d.ts +35 -0
- package/dist/credential.js +163 -0
- package/dist/errors.d.ts +55 -0
- package/dist/errors.js +112 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/package.json +32 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type KeyObject } from "node:crypto";
|
|
2
|
+
import { type DirectRuntimeClientErrorCode } from "./errors.js";
|
|
3
|
+
export interface DirectRuntimeClientIdentity {
|
|
4
|
+
clientId: string;
|
|
5
|
+
/** Canonical Ed25519 SubjectPublicKeyInfo DER, unpadded base64url. */
|
|
6
|
+
clientPublicKey: string;
|
|
7
|
+
/** Ed25519 PKCS#8 private key. Keep this value secret. */
|
|
8
|
+
clientPrivateKeyPem: string;
|
|
9
|
+
}
|
|
10
|
+
export interface GenerateDirectRuntimeClientIdentityOptions {
|
|
11
|
+
clientId?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface DirectRuntimeCredential extends DirectRuntimeClientIdentity {
|
|
14
|
+
version: 2;
|
|
15
|
+
daemonId: string;
|
|
16
|
+
/** Pinned daemon Ed25519 SubjectPublicKeyInfo DER, unpadded base64url. */
|
|
17
|
+
identityPublicKey: string;
|
|
18
|
+
/** Pinned daemon X25519 SubjectPublicKeyInfo DER, unpadded base64url. */
|
|
19
|
+
serverEncryptionPublicKey: string;
|
|
20
|
+
directEndpoint: string;
|
|
21
|
+
grantId: string;
|
|
22
|
+
}
|
|
23
|
+
export interface ParsedDirectRuntimeClientIdentity {
|
|
24
|
+
value: DirectRuntimeClientIdentity;
|
|
25
|
+
privateKey: KeyObject;
|
|
26
|
+
}
|
|
27
|
+
/** Generate a durable client identity for one or more Direct Runtime grants. */
|
|
28
|
+
export declare function generateDirectRuntimeClientIdentity(options?: GenerateDirectRuntimeClientIdentityOptions): DirectRuntimeClientIdentity;
|
|
29
|
+
/** Validate persisted, untrusted credential JSON and return only known fields. */
|
|
30
|
+
export declare function parseDirectRuntimeCredential(value: unknown): DirectRuntimeCredential;
|
|
31
|
+
export declare function parseDirectRuntimeClientIdentity(value: unknown, code?: DirectRuntimeClientErrorCode): ParsedDirectRuntimeClientIdentity;
|
|
32
|
+
export declare function parseEd25519PublicKey(value: unknown, field: string, code: DirectRuntimeClientErrorCode): string;
|
|
33
|
+
export declare function parseDirectEndpoint(value: unknown, code: DirectRuntimeClientErrorCode): string;
|
|
34
|
+
export declare function parseX25519PublicKey(value: unknown, field: string, code: DirectRuntimeClientErrorCode): string;
|
|
35
|
+
export declare function opaqueId(value: unknown, field: string, code: DirectRuntimeClientErrorCode): string;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { createPrivateKey, createPublicKey, generateKeyPairSync, randomBytes, } from "node:crypto";
|
|
2
|
+
import { DIRECT_RUNTIME_CONTROL_PATH } from "@rynx-ai/protocol/direct-runtime";
|
|
3
|
+
import { clientError, } from "./errors.js";
|
|
4
|
+
const MAX_ID_CHARS = 256;
|
|
5
|
+
const MAX_ENDPOINT_CHARS = 2_048;
|
|
6
|
+
const MAX_PRIVATE_KEY_BYTES = 4 * 1024;
|
|
7
|
+
const OPAQUE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._~-]*$/;
|
|
8
|
+
const BASE64URL_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
9
|
+
/** Generate a durable client identity for one or more Direct Runtime grants. */
|
|
10
|
+
export function generateDirectRuntimeClientIdentity(options = {}) {
|
|
11
|
+
const clientId = options.clientId === undefined
|
|
12
|
+
? `client_${randomBytes(18).toString("base64url")}`
|
|
13
|
+
: opaqueId(options.clientId, "clientId", "authentication_failed");
|
|
14
|
+
const pair = generateKeyPairSync("ed25519");
|
|
15
|
+
return {
|
|
16
|
+
clientId,
|
|
17
|
+
clientPublicKey: exportPublicKey(pair.publicKey),
|
|
18
|
+
clientPrivateKeyPem: pair.privateKey
|
|
19
|
+
.export({ type: "pkcs8", format: "pem" })
|
|
20
|
+
.toString(),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Validate persisted, untrusted credential JSON and return only known fields. */
|
|
24
|
+
export function parseDirectRuntimeCredential(value) {
|
|
25
|
+
const record = requireRecord(value, "Direct Runtime credential", "authentication_failed");
|
|
26
|
+
if (record.version !== 2) {
|
|
27
|
+
throw clientError("authentication_failed", "Direct Runtime credential version must be 2");
|
|
28
|
+
}
|
|
29
|
+
const daemonId = opaqueId(record.daemonId, "daemonId", "authentication_failed");
|
|
30
|
+
const identityPublicKey = parseEd25519PublicKey(record.identityPublicKey, "identityPublicKey", "authentication_failed");
|
|
31
|
+
const serverEncryptionPublicKey = parseX25519PublicKey(record.serverEncryptionPublicKey, "serverEncryptionPublicKey", "authentication_failed");
|
|
32
|
+
const directEndpoint = parseDirectEndpoint(record.directEndpoint, "authentication_failed");
|
|
33
|
+
const identity = parseDirectRuntimeClientIdentity(record, "authentication_failed");
|
|
34
|
+
const grantId = opaqueId(record.grantId, "grantId", "authentication_failed");
|
|
35
|
+
return {
|
|
36
|
+
version: 2,
|
|
37
|
+
daemonId,
|
|
38
|
+
identityPublicKey,
|
|
39
|
+
serverEncryptionPublicKey,
|
|
40
|
+
directEndpoint,
|
|
41
|
+
...identity.value,
|
|
42
|
+
grantId,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export function parseDirectRuntimeClientIdentity(value, code = "authentication_failed") {
|
|
46
|
+
const record = requireRecord(value, "Direct Runtime client identity", code);
|
|
47
|
+
const clientId = opaqueId(record.clientId, "clientId", code);
|
|
48
|
+
const clientPublicKey = parseEd25519PublicKey(record.clientPublicKey, "clientPublicKey", code);
|
|
49
|
+
const clientPrivateKeyPem = parsePrivateKeyPem(record.clientPrivateKeyPem, code);
|
|
50
|
+
let privateKey;
|
|
51
|
+
try {
|
|
52
|
+
privateKey = createPrivateKey({ key: clientPrivateKeyPem, format: "pem" });
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
throw clientError(code, "clientPrivateKeyPem is not a valid private key", error);
|
|
56
|
+
}
|
|
57
|
+
if (privateKey.asymmetricKeyType !== "ed25519") {
|
|
58
|
+
throw clientError(code, "clientPrivateKeyPem must contain an Ed25519 key");
|
|
59
|
+
}
|
|
60
|
+
const derivedPublicKey = exportPublicKey(createPublicKey(privateKey));
|
|
61
|
+
if (derivedPublicKey !== clientPublicKey) {
|
|
62
|
+
throw clientError(code, "client private and public keys do not match");
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
value: { clientId, clientPublicKey, clientPrivateKeyPem },
|
|
66
|
+
privateKey,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
export function parseEd25519PublicKey(value, field, code) {
|
|
70
|
+
if (typeof value !== "string" ||
|
|
71
|
+
value.length === 0 ||
|
|
72
|
+
value.length > 512 ||
|
|
73
|
+
!BASE64URL_PATTERN.test(value)) {
|
|
74
|
+
throw clientError(code, `${field} must be an Ed25519 SPKI DER base64url key`);
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const bytes = Buffer.from(value, "base64url");
|
|
78
|
+
if (bytes.toString("base64url") !== value)
|
|
79
|
+
throw new Error("non-canonical base64url");
|
|
80
|
+
const key = createPublicKey({ key: bytes, format: "der", type: "spki" });
|
|
81
|
+
if (key.asymmetricKeyType !== "ed25519")
|
|
82
|
+
throw new Error("not Ed25519");
|
|
83
|
+
const canonical = exportPublicKey(key);
|
|
84
|
+
if (canonical !== value)
|
|
85
|
+
throw new Error("non-canonical SPKI DER");
|
|
86
|
+
return canonical;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw clientError(code, `${field} must be an Ed25519 SPKI DER base64url key`, error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
export function parseDirectEndpoint(value, code) {
|
|
93
|
+
if (typeof value !== "string" ||
|
|
94
|
+
value.length === 0 ||
|
|
95
|
+
value.length > MAX_ENDPOINT_CHARS ||
|
|
96
|
+
!/^wss?:\/\/[^\s]+$/.test(value)) {
|
|
97
|
+
throw clientError(code, "directEndpoint must be a bounded ws: or wss: URL");
|
|
98
|
+
}
|
|
99
|
+
let endpoint;
|
|
100
|
+
try {
|
|
101
|
+
endpoint = new URL(value);
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
throw clientError(code, "directEndpoint must be a valid ws: or wss: URL", error);
|
|
105
|
+
}
|
|
106
|
+
if ((endpoint.protocol !== "ws:" && endpoint.protocol !== "wss:") ||
|
|
107
|
+
endpoint.hostname.length === 0 ||
|
|
108
|
+
endpoint.username.length > 0 ||
|
|
109
|
+
endpoint.password.length > 0 ||
|
|
110
|
+
endpoint.hash.length > 0 ||
|
|
111
|
+
endpoint.search.length > 0 ||
|
|
112
|
+
endpoint.pathname !== DIRECT_RUNTIME_CONTROL_PATH) {
|
|
113
|
+
throw clientError(code, `directEndpoint must be a credential-free ws: or wss: URL at ${DIRECT_RUNTIME_CONTROL_PATH} without query or fragment`);
|
|
114
|
+
}
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
export function parseX25519PublicKey(value, field, code) {
|
|
118
|
+
if (typeof value !== "string" || !BASE64URL_PATTERN.test(value)) {
|
|
119
|
+
throw clientError(code, `${field} must be an X25519 SPKI DER base64url key`);
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
const bytes = Buffer.from(value, "base64url");
|
|
123
|
+
if (bytes.byteLength !== 44 || bytes.toString("base64url") !== value) {
|
|
124
|
+
throw new Error("non-canonical base64url");
|
|
125
|
+
}
|
|
126
|
+
const key = createPublicKey({ key: bytes, format: "der", type: "spki" });
|
|
127
|
+
if (key.asymmetricKeyType !== "x25519")
|
|
128
|
+
throw new Error("not X25519");
|
|
129
|
+
return key.export({ type: "spki", format: "der" }).toString("base64url");
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
throw clientError(code, `${field} must be an X25519 SPKI DER base64url key`, error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export function opaqueId(value, field, code) {
|
|
136
|
+
if (typeof value !== "string" ||
|
|
137
|
+
value.length === 0 ||
|
|
138
|
+
value.length > MAX_ID_CHARS ||
|
|
139
|
+
!OPAQUE_ID_PATTERN.test(value)) {
|
|
140
|
+
throw clientError(code, `${field} must be an opaque ASCII token`);
|
|
141
|
+
}
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
function parsePrivateKeyPem(value, code) {
|
|
145
|
+
if (typeof value !== "string" ||
|
|
146
|
+
value.length === 0 ||
|
|
147
|
+
Buffer.byteLength(value, "utf8") > MAX_PRIVATE_KEY_BYTES ||
|
|
148
|
+
value.includes("\0") ||
|
|
149
|
+
!value.includes("-----BEGIN PRIVATE KEY-----") ||
|
|
150
|
+
!value.includes("-----END PRIVATE KEY-----")) {
|
|
151
|
+
throw clientError(code, "clientPrivateKeyPem must be a bounded PKCS#8 PEM key");
|
|
152
|
+
}
|
|
153
|
+
return value;
|
|
154
|
+
}
|
|
155
|
+
function exportPublicKey(key) {
|
|
156
|
+
return key.export({ type: "spki", format: "der" }).toString("base64url");
|
|
157
|
+
}
|
|
158
|
+
function requireRecord(value, field, code) {
|
|
159
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
160
|
+
throw clientError(code, `${field} must be an object`);
|
|
161
|
+
}
|
|
162
|
+
return value;
|
|
163
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { RemoteRuntimeRpcErrorCode, RemoteRuntimeRpcMethod, RemoteRuntimeSessionEventsCloseReason, RemoteRuntimeSessionTerminalCloseReason } from "@rynx-ai/protocol/remote-runtime-rpc";
|
|
2
|
+
export type DirectRuntimeClientErrorCode = "invalid_offer" | "tls_error" | "identity_mismatch" | "incompatible" | "authentication_failed" | "protocol_error" | "deadline_exceeded" | "unreachable" | "closed";
|
|
3
|
+
export type DirectRuntimeCallOutcome = "not_started" | "unknown";
|
|
4
|
+
export declare class DirectRuntimeClientError extends Error {
|
|
5
|
+
readonly code: DirectRuntimeClientErrorCode;
|
|
6
|
+
readonly outcome?: DirectRuntimeCallOutcome;
|
|
7
|
+
/** Original application WebSocket close code, when the peer supplied one. */
|
|
8
|
+
readonly webSocketCloseCode?: number;
|
|
9
|
+
constructor(code: DirectRuntimeClientErrorCode, message: string, options?: ErrorOptions & {
|
|
10
|
+
webSocketCloseCode?: number;
|
|
11
|
+
outcome?: DirectRuntimeCallOutcome;
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
export { DirectRuntimeClientError as RemoteRuntimeClientError };
|
|
15
|
+
export type DirectRuntimeClientCapacity = "pending_rpc" | "session_subscription" | "session_terminal" | "emulator_surface" | "outbound_frames" | "outbound_bytes";
|
|
16
|
+
/** Local admission failure. The rejected operation was not written to the wire. */
|
|
17
|
+
export declare class DirectRuntimeClientCapacityError extends DirectRuntimeClientError {
|
|
18
|
+
readonly capacity: DirectRuntimeClientCapacity;
|
|
19
|
+
readonly limit: number;
|
|
20
|
+
readonly outcome: "not_started";
|
|
21
|
+
constructor(capacity: DirectRuntimeClientCapacity, limit: number, message: string);
|
|
22
|
+
}
|
|
23
|
+
/** A valid application-level `rpc.error` returned by the authenticated daemon. */
|
|
24
|
+
export declare class DirectRuntimeRpcError extends Error {
|
|
25
|
+
readonly code: RemoteRuntimeRpcErrorCode;
|
|
26
|
+
readonly method: RemoteRuntimeRpcMethod;
|
|
27
|
+
readonly requestId: string;
|
|
28
|
+
readonly outcome: "unknown" | undefined;
|
|
29
|
+
constructor(code: RemoteRuntimeRpcErrorCode, method: RemoteRuntimeRpcMethod, requestId: string, message: string);
|
|
30
|
+
}
|
|
31
|
+
export { DirectRuntimeRpcError as RemoteRuntimeRpcCallError };
|
|
32
|
+
/** Transport failure correlated to one call, including delivery ambiguity. */
|
|
33
|
+
export declare class DirectRuntimeCallTransportError extends DirectRuntimeClientError {
|
|
34
|
+
readonly method: RemoteRuntimeRpcMethod;
|
|
35
|
+
readonly requestId: string;
|
|
36
|
+
readonly outcome: DirectRuntimeCallOutcome;
|
|
37
|
+
constructor(code: DirectRuntimeClientErrorCode, method: RemoteRuntimeRpcMethod, requestId: string, outcome: DirectRuntimeCallOutcome, message: string, options?: ErrorOptions & {
|
|
38
|
+
webSocketCloseCode?: number;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** A terminal error scoped to one accepted Remote Session event stream. */
|
|
42
|
+
export declare class DirectRuntimeSessionEventsError extends DirectRuntimeClientError {
|
|
43
|
+
readonly reason: RemoteRuntimeSessionEventsCloseReason;
|
|
44
|
+
readonly subscriptionId: string;
|
|
45
|
+
readonly sessionId: string;
|
|
46
|
+
constructor(reason: RemoteRuntimeSessionEventsCloseReason, subscriptionId: string, sessionId: string, message: string, options?: ErrorOptions);
|
|
47
|
+
}
|
|
48
|
+
/** A terminal error scoped to one Remote Session terminal attachment. */
|
|
49
|
+
export declare class DirectRuntimeSessionTerminalError extends DirectRuntimeClientError {
|
|
50
|
+
readonly reason: RemoteRuntimeSessionTerminalCloseReason;
|
|
51
|
+
readonly attachmentId: string;
|
|
52
|
+
readonly sessionId: string;
|
|
53
|
+
constructor(reason: RemoteRuntimeSessionTerminalCloseReason, attachmentId: string, sessionId: string, message: string, options?: ErrorOptions);
|
|
54
|
+
}
|
|
55
|
+
export declare function clientError(code: DirectRuntimeClientErrorCode, message: string, cause?: unknown, webSocketCloseCode?: number): DirectRuntimeClientError;
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
export class DirectRuntimeClientError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
outcome;
|
|
4
|
+
/** Original application WebSocket close code, when the peer supplied one. */
|
|
5
|
+
webSocketCloseCode;
|
|
6
|
+
constructor(code, message, options) {
|
|
7
|
+
super(message, options);
|
|
8
|
+
this.name = "DirectRuntimeClientError";
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.outcome = options?.outcome;
|
|
11
|
+
if (options?.webSocketCloseCode !== undefined) {
|
|
12
|
+
this.webSocketCloseCode = options.webSocketCloseCode;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export { DirectRuntimeClientError as RemoteRuntimeClientError };
|
|
17
|
+
/** Local admission failure. The rejected operation was not written to the wire. */
|
|
18
|
+
export class DirectRuntimeClientCapacityError extends DirectRuntimeClientError {
|
|
19
|
+
capacity;
|
|
20
|
+
limit;
|
|
21
|
+
outcome = "not_started";
|
|
22
|
+
constructor(capacity, limit, message) {
|
|
23
|
+
// Keep the stable public error-code surface aligned with peer-side capacity
|
|
24
|
+
// rejection while exposing a distinct class for local admission decisions.
|
|
25
|
+
super("unreachable", message);
|
|
26
|
+
this.capacity = capacity;
|
|
27
|
+
this.limit = limit;
|
|
28
|
+
this.name = "DirectRuntimeClientCapacityError";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** A valid application-level `rpc.error` returned by the authenticated daemon. */
|
|
32
|
+
export class DirectRuntimeRpcError extends Error {
|
|
33
|
+
code;
|
|
34
|
+
method;
|
|
35
|
+
requestId;
|
|
36
|
+
outcome;
|
|
37
|
+
constructor(code, method, requestId, message) {
|
|
38
|
+
super(message);
|
|
39
|
+
this.code = code;
|
|
40
|
+
this.method = method;
|
|
41
|
+
this.requestId = requestId;
|
|
42
|
+
this.name = "DirectRuntimeRpcError";
|
|
43
|
+
this.outcome = code === "outcome_unknown" ? "unknown" : undefined;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export { DirectRuntimeRpcError as RemoteRuntimeRpcCallError };
|
|
47
|
+
/** Transport failure correlated to one call, including delivery ambiguity. */
|
|
48
|
+
export class DirectRuntimeCallTransportError extends DirectRuntimeClientError {
|
|
49
|
+
method;
|
|
50
|
+
requestId;
|
|
51
|
+
outcome;
|
|
52
|
+
constructor(code, method, requestId, outcome, message, options) {
|
|
53
|
+
super(code, message, options);
|
|
54
|
+
this.method = method;
|
|
55
|
+
this.requestId = requestId;
|
|
56
|
+
this.outcome = outcome;
|
|
57
|
+
this.name = "DirectRuntimeCallTransportError";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** A terminal error scoped to one accepted Remote Session event stream. */
|
|
61
|
+
export class DirectRuntimeSessionEventsError extends DirectRuntimeClientError {
|
|
62
|
+
reason;
|
|
63
|
+
subscriptionId;
|
|
64
|
+
sessionId;
|
|
65
|
+
constructor(reason, subscriptionId, sessionId, message, options) {
|
|
66
|
+
super(sessionEventsErrorCode(reason), message, options);
|
|
67
|
+
this.reason = reason;
|
|
68
|
+
this.subscriptionId = subscriptionId;
|
|
69
|
+
this.sessionId = sessionId;
|
|
70
|
+
this.name = "DirectRuntimeSessionEventsError";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/** A terminal error scoped to one Remote Session terminal attachment. */
|
|
74
|
+
export class DirectRuntimeSessionTerminalError extends DirectRuntimeClientError {
|
|
75
|
+
reason;
|
|
76
|
+
attachmentId;
|
|
77
|
+
sessionId;
|
|
78
|
+
constructor(reason, attachmentId, sessionId, message, options) {
|
|
79
|
+
super(sessionTerminalErrorCode(reason), message, options);
|
|
80
|
+
this.reason = reason;
|
|
81
|
+
this.attachmentId = attachmentId;
|
|
82
|
+
this.sessionId = sessionId;
|
|
83
|
+
this.name = "DirectRuntimeSessionTerminalError";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function sessionEventsErrorCode(reason) {
|
|
87
|
+
if (reason === "unauthorized")
|
|
88
|
+
return "authentication_failed";
|
|
89
|
+
if (reason === "capacity")
|
|
90
|
+
return "unreachable";
|
|
91
|
+
return "closed";
|
|
92
|
+
}
|
|
93
|
+
function sessionTerminalErrorCode(reason) {
|
|
94
|
+
if (reason === "unauthorized")
|
|
95
|
+
return "authentication_failed";
|
|
96
|
+
if (reason === "capacity" || reason === "backpressure")
|
|
97
|
+
return "unreachable";
|
|
98
|
+
return "closed";
|
|
99
|
+
}
|
|
100
|
+
export function clientError(code, message, cause, webSocketCloseCode) {
|
|
101
|
+
if (cause instanceof DirectRuntimeClientError &&
|
|
102
|
+
cause.code === code &&
|
|
103
|
+
webSocketCloseCode === undefined) {
|
|
104
|
+
return cause;
|
|
105
|
+
}
|
|
106
|
+
return new DirectRuntimeClientError(code, message, cause === undefined && webSocketCloseCode === undefined
|
|
107
|
+
? undefined
|
|
108
|
+
: {
|
|
109
|
+
...(cause === undefined ? {} : { cause }),
|
|
110
|
+
...(webSocketCloseCode === undefined ? {} : { webSocketCloseCode }),
|
|
111
|
+
});
|
|
112
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { connectDirectRuntime, pairDirectRuntime, type DirectRuntimeCallOptions, type DirectRuntimeClientOptions, type DirectRuntimeConnection, type DirectRuntimeSessionEventsOptions, type DirectRuntimeSessionEventsSubscription, type DirectRuntimeSessionTerminal, type DirectRuntimeSessionTerminalOptions, type DirectRuntimeEmulatorSurface, type DirectRuntimeEmulatorSurfaceOptions, type PairDirectRuntimeOptions, type PairDirectRuntimeResult, } from "./client.js";
|
|
2
|
+
export { DirectRuntimeBrowserSurfaceError, openDirectRuntimeBrowserSurface, type DirectRuntimeBrowserSurfaceClientOptions, type DirectRuntimeBrowserSurfaceConnection, type DirectRuntimeBrowserSurfaceEvent, } from "./browser-surface-client.js";
|
|
3
|
+
export { generateDirectRuntimeClientIdentity, parseDirectRuntimeCredential, type DirectRuntimeClientIdentity, type DirectRuntimeCredential, type GenerateDirectRuntimeClientIdentityOptions, } from "./credential.js";
|
|
4
|
+
export { DirectRuntimeCallTransportError, DirectRuntimeClientCapacityError, DirectRuntimeClientError, DirectRuntimeRpcError, DirectRuntimeSessionEventsError, DirectRuntimeSessionTerminalError, RemoteRuntimeClientError, RemoteRuntimeRpcCallError, type DirectRuntimeCallOutcome, type DirectRuntimeClientCapacity, type DirectRuntimeClientErrorCode, } from "./errors.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { connectDirectRuntime, pairDirectRuntime, } from "./client.js";
|
|
2
|
+
export { DirectRuntimeBrowserSurfaceError, openDirectRuntimeBrowserSurface, } from "./browser-surface-client.js";
|
|
3
|
+
export { generateDirectRuntimeClientIdentity, parseDirectRuntimeCredential, } from "./credential.js";
|
|
4
|
+
export { DirectRuntimeCallTransportError, DirectRuntimeClientCapacityError, DirectRuntimeClientError, DirectRuntimeRpcError, DirectRuntimeSessionEventsError, DirectRuntimeSessionTerminalError, RemoteRuntimeClientError, RemoteRuntimeRpcCallError, } from "./errors.js";
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rynx-ai/remote-runtime-client",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"description": "Authenticated Node.js client for a Rynx Direct Remote Runtime.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"registry": "https://registry.npmjs.org/",
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"ws": "^8.21.0",
|
|
23
|
+
"@rynx-ai/protocol": "0.1.9",
|
|
24
|
+
"@rynx-ai/remote-runtime-e2ee": "0.1.9"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/ws": "^8.18.1"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "rm -rf dist && tsc -p tsconfig.json"
|
|
31
|
+
}
|
|
32
|
+
}
|