rivetkit 2.3.20 → 2.3.21
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/client.d.ts +43 -5
- package/dist/browser/client.js +302 -60
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +2 -1
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/tsup/actor/errors.cjs.map +1 -1
- package/dist/tsup/agent-os/index.cjs +2 -1
- package/dist/tsup/agent-os/index.cjs.map +1 -1
- package/dist/tsup/agent-os/index.d.cts +32 -4
- package/dist/tsup/agent-os/index.d.ts +32 -4
- package/dist/tsup/agent-os/index.js +2 -1
- package/dist/tsup/agent-os/index.js.map +1 -1
- package/dist/tsup/{chunk-553CIQJY.js → chunk-2CI2IEVN.js} +2 -2
- package/dist/tsup/{chunk-W2PXGWMR.js → chunk-5EGLHQJJ.js} +2 -2
- package/dist/tsup/{chunk-DMQUERRN.js → chunk-5IBUZFLP.js} +2 -2
- package/dist/tsup/{chunk-76YTS32R.cjs → chunk-6LRPYB4Q.cjs} +4 -4
- package/dist/tsup/chunk-6LRPYB4Q.cjs.map +1 -0
- package/dist/tsup/{chunk-WAISW7KR.cjs → chunk-APOANSDG.cjs} +10 -10
- package/dist/tsup/chunk-APOANSDG.cjs.map +1 -0
- package/dist/tsup/{chunk-IHKDFKM4.cjs → chunk-ARGNQGYG.cjs} +3 -3
- package/dist/tsup/chunk-ARGNQGYG.cjs.map +1 -0
- package/dist/tsup/{chunk-A36FMKOV.cjs → chunk-B5SNXPSS.cjs} +448 -199
- package/dist/tsup/chunk-B5SNXPSS.cjs.map +1 -0
- package/dist/tsup/{chunk-SNNVRHLX.js → chunk-CJXBGTVT.js} +2 -2
- package/dist/tsup/{chunk-CVLNRT7O.cjs → chunk-GHKQC4PD.cjs} +3 -3
- package/dist/tsup/chunk-GHKQC4PD.cjs.map +1 -0
- package/dist/tsup/chunk-JX2ITWAV.cjs.map +1 -1
- package/dist/tsup/chunk-KVFIONKQ.cjs.map +1 -1
- package/dist/tsup/{chunk-2CE5UNWK.cjs → chunk-KWGN2ZBJ.cjs} +3 -2
- package/dist/tsup/chunk-KWGN2ZBJ.cjs.map +1 -0
- package/dist/tsup/{chunk-3WS7Z64U.cjs → chunk-LWSLKKZ5.cjs} +3 -3
- package/dist/tsup/chunk-LWSLKKZ5.cjs.map +1 -0
- package/dist/tsup/chunk-MYWZCDML.cjs.map +1 -1
- package/dist/tsup/{chunk-RSIOGT2U.cjs → chunk-NL2EIKK6.cjs} +7 -7
- package/dist/tsup/chunk-NL2EIKK6.cjs.map +1 -0
- package/dist/tsup/chunk-NWCAIWHL.cjs.map +1 -1
- package/dist/tsup/{chunk-5G2J26VM.js → chunk-PYRI75DL.js} +314 -65
- package/dist/tsup/chunk-PYRI75DL.js.map +1 -0
- package/dist/tsup/{chunk-2NXLTFWI.js → chunk-RFN3BG6D.js} +3 -3
- package/dist/tsup/chunk-RFN3BG6D.js.map +1 -0
- package/dist/tsup/{chunk-DHWZTUKA.js → chunk-RGIZNZYO.js} +3 -2
- package/dist/tsup/chunk-RGIZNZYO.js.map +1 -0
- package/dist/tsup/{chunk-TZVAVPGJ.js → chunk-VMMXXVDO.js} +4 -4
- package/dist/tsup/client/mod.cjs +5 -5
- package/dist/tsup/client/mod.cjs.map +1 -1
- package/dist/tsup/client/mod.d.cts +12 -3
- package/dist/tsup/client/mod.d.ts +12 -3
- package/dist/tsup/client/mod.js +4 -4
- package/dist/tsup/common/log.cjs +2 -2
- package/dist/tsup/common/log.cjs.map +1 -1
- package/dist/tsup/common/log.js +1 -1
- package/dist/tsup/common/websocket.cjs +3 -3
- package/dist/tsup/common/websocket.cjs.map +1 -1
- package/dist/tsup/common/websocket.js +2 -2
- package/dist/tsup/{config-Be-VOHaX.d.ts → config-Bc1nnvUl.d.ts} +35 -5
- package/dist/tsup/{config-Ct5uXxXk.d.cts → config-Do_0guSS.d.cts} +35 -5
- package/dist/tsup/{context-Cw-11Q-B.d.cts → context-CgNkhjdY.d.cts} +1 -1
- package/dist/tsup/{context-CXLa0BIM.d.ts → context-oGQxZDPz.d.ts} +1 -1
- package/dist/tsup/db/drizzle.cjs +2 -2
- package/dist/tsup/db/drizzle.cjs.map +1 -1
- package/dist/tsup/db/drizzle.js +1 -1
- package/dist/tsup/db/mod.cjs +3 -3
- package/dist/tsup/db/mod.cjs.map +1 -1
- package/dist/tsup/db/mod.js +2 -2
- package/dist/tsup/dynamic/mod.cjs.map +1 -1
- package/dist/tsup/dynamic/mod.d.cts +2 -1
- package/dist/tsup/dynamic/mod.d.ts +2 -1
- package/dist/tsup/inspector/mod.cjs +5 -5
- package/dist/tsup/inspector/mod.cjs.map +1 -1
- package/dist/tsup/inspector/mod.js +4 -4
- package/dist/tsup/inspector/workflow.cjs +4 -4
- package/dist/tsup/inspector/workflow.cjs.map +1 -1
- package/dist/tsup/inspector/workflow.js +3 -3
- package/dist/tsup/inspector-tab/mod.cjs.map +1 -1
- package/dist/tsup/inspector-tab/mod.d.cts +3 -2
- package/dist/tsup/inspector-tab/mod.d.ts +3 -2
- package/dist/tsup/mod.cjs +105 -115
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +4 -3
- package/dist/tsup/mod.d.ts +4 -3
- package/dist/tsup/mod.js +29 -39
- package/dist/tsup/mod.js.map +1 -1
- package/dist/tsup/test/mod.cjs +6 -6
- package/dist/tsup/test/mod.cjs.map +1 -1
- package/dist/tsup/test/mod.d.cts +2 -1
- package/dist/tsup/test/mod.d.ts +2 -1
- package/dist/tsup/test/mod.js +4 -4
- package/dist/tsup/unstable/migrations.cjs.map +1 -1
- package/dist/tsup/utils.cjs +2 -2
- package/dist/tsup/utils.cjs.map +1 -1
- package/dist/tsup/utils.js +1 -1
- package/dist/tsup/workflow/mod.cjs +7 -7
- package/dist/tsup/workflow/mod.cjs.map +1 -1
- package/dist/tsup/workflow/mod.d.cts +4 -3
- package/dist/tsup/workflow/mod.d.ts +4 -3
- package/dist/tsup/workflow/mod.js +4 -4
- package/package.json +10 -9
- package/src/client/actor-conn.ts +34 -1
- package/src/client/actor-handle.ts +29 -1
- package/src/client/auth.ts +37 -0
- package/src/client/client.ts +10 -2
- package/src/client/config.ts +12 -1
- package/src/client/mod.ts +9 -0
- package/src/client/token-provider.test.ts +86 -0
- package/src/client/token-provider.ts +93 -0
- package/src/client/utils.ts +1 -0
- package/src/engine-client/actor-websocket-client.ts +2 -1
- package/src/engine-client/api-endpoints.ts +28 -0
- package/src/engine-client/driver.ts +4 -0
- package/src/engine-client/mod.ts +201 -64
- package/src/registry/config/envoy.ts +1 -17
- package/src/registry/config/index.test.ts +2 -2
- package/src/registry/config/index.ts +7 -2
- package/src/registry/index.ts +28 -0
- package/dist/tsup/chunk-2CE5UNWK.cjs.map +0 -1
- package/dist/tsup/chunk-2NXLTFWI.js.map +0 -1
- package/dist/tsup/chunk-3WS7Z64U.cjs.map +0 -1
- package/dist/tsup/chunk-5G2J26VM.js.map +0 -1
- package/dist/tsup/chunk-76YTS32R.cjs.map +0 -1
- package/dist/tsup/chunk-A36FMKOV.cjs.map +0 -1
- package/dist/tsup/chunk-CVLNRT7O.cjs.map +0 -1
- package/dist/tsup/chunk-DHWZTUKA.js.map +0 -1
- package/dist/tsup/chunk-IHKDFKM4.cjs.map +0 -1
- package/dist/tsup/chunk-RSIOGT2U.cjs.map +0 -1
- package/dist/tsup/chunk-WAISW7KR.cjs.map +0 -1
- /package/dist/tsup/{chunk-553CIQJY.js.map → chunk-2CI2IEVN.js.map} +0 -0
- /package/dist/tsup/{chunk-W2PXGWMR.js.map → chunk-5EGLHQJJ.js.map} +0 -0
- /package/dist/tsup/{chunk-DMQUERRN.js.map → chunk-5IBUZFLP.js.map} +0 -0
- /package/dist/tsup/{chunk-SNNVRHLX.js.map → chunk-CJXBGTVT.js.map} +0 -0
- /package/dist/tsup/{chunk-TZVAVPGJ.js.map → chunk-VMMXXVDO.js.map} +0 -0
package/dist/browser/client.js
CHANGED
|
@@ -220,7 +220,7 @@ function noopNext() {
|
|
|
220
220
|
// package.json
|
|
221
221
|
var package_default = {
|
|
222
222
|
name: "rivetkit",
|
|
223
|
-
version: "2.3.
|
|
223
|
+
version: "2.3.21",
|
|
224
224
|
description: "Lightweight libraries for building stateful actors on edge platforms",
|
|
225
225
|
license: "Apache-2.0",
|
|
226
226
|
keywords: [
|
|
@@ -433,6 +433,7 @@ var package_default = {
|
|
|
433
433
|
"@rivet-dev/agent-os-core": "^0.1.1",
|
|
434
434
|
"@rivet-dev/services": "^0.1.5",
|
|
435
435
|
"@rivetkit/bare-ts": "^0.6.2",
|
|
436
|
+
"@rivetkit/engine-api-full": "workspace:*",
|
|
436
437
|
"@rivetkit/engine-cli": "workspace:*",
|
|
437
438
|
"@rivetkit/engine-envoy-protocol": "workspace:*",
|
|
438
439
|
"@rivetkit/on-change": "6.0.1",
|
|
@@ -1145,6 +1146,73 @@ function deserializeActorKey(keyString) {
|
|
|
1145
1146
|
return parts;
|
|
1146
1147
|
}
|
|
1147
1148
|
|
|
1149
|
+
// src/client/token-provider.ts
|
|
1150
|
+
function isInvalidToken(group, code) {
|
|
1151
|
+
return group === "auth" && (code === "invalid_token" || code === "token_expired");
|
|
1152
|
+
}
|
|
1153
|
+
function isInvalidTokenResponse(response) {
|
|
1154
|
+
if (response.status !== 401) return false;
|
|
1155
|
+
const error = response.headers.get("x-rivet-error");
|
|
1156
|
+
if (!error) return false;
|
|
1157
|
+
const separator = error.indexOf(".");
|
|
1158
|
+
return separator > 0 && isInvalidToken(error.slice(0, separator), error.slice(separator + 1));
|
|
1159
|
+
}
|
|
1160
|
+
var TokenProvider = class {
|
|
1161
|
+
constructor(getToken) {
|
|
1162
|
+
this.getToken = getToken;
|
|
1163
|
+
}
|
|
1164
|
+
#cached;
|
|
1165
|
+
#pending;
|
|
1166
|
+
#pendingForce = false;
|
|
1167
|
+
async current() {
|
|
1168
|
+
if (this.#cached && (this.#cached.expiresAt === void 0 || Date.now() < this.#cached.expiresAt - 5e3)) {
|
|
1169
|
+
return this.#cached.token;
|
|
1170
|
+
}
|
|
1171
|
+
return this.#load(false);
|
|
1172
|
+
}
|
|
1173
|
+
/** A late rejection for an older token must never erase a newer credential. */
|
|
1174
|
+
async refreshIfCurrent(failedToken) {
|
|
1175
|
+
if (this.#pending !== void 0) {
|
|
1176
|
+
const wasForced = this.#pendingForce;
|
|
1177
|
+
const refreshed = await this.#pending;
|
|
1178
|
+
if (wasForced || refreshed !== failedToken) return refreshed;
|
|
1179
|
+
}
|
|
1180
|
+
if (this.#cached?.token !== failedToken) {
|
|
1181
|
+
return this.current();
|
|
1182
|
+
}
|
|
1183
|
+
return this.#load(true);
|
|
1184
|
+
}
|
|
1185
|
+
#load(forceRefresh) {
|
|
1186
|
+
if (this.#pending !== void 0) return this.#pending;
|
|
1187
|
+
const pending = Promise.resolve().then(() => this.getToken({ forceRefresh })).then((token) => {
|
|
1188
|
+
if (typeof token !== "string" || token.length === 0) {
|
|
1189
|
+
throw new Error(
|
|
1190
|
+
"getToken must resolve to a nonempty string"
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
this.#cached = { token, expiresAt: jwtExpiration(token) };
|
|
1194
|
+
return token;
|
|
1195
|
+
}).finally(() => {
|
|
1196
|
+
if (this.#pending === pending) this.#pending = void 0;
|
|
1197
|
+
});
|
|
1198
|
+
this.#pending = pending;
|
|
1199
|
+
this.#pendingForce = forceRefresh;
|
|
1200
|
+
return pending;
|
|
1201
|
+
}
|
|
1202
|
+
};
|
|
1203
|
+
function jwtExpiration(token) {
|
|
1204
|
+
try {
|
|
1205
|
+
const payload = token.split(".")[1];
|
|
1206
|
+
if (!payload) return void 0;
|
|
1207
|
+
const claims = JSON.parse(
|
|
1208
|
+
atob(payload.replace(/-/g, "+").replace(/_/g, "/"))
|
|
1209
|
+
);
|
|
1210
|
+
return typeof claims.exp === "number" && Number.isSafeInteger(claims.exp) ? claims.exp * 1e3 : void 0;
|
|
1211
|
+
} catch {
|
|
1212
|
+
return void 0;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1148
1216
|
// src/common/actor-router-consts.ts
|
|
1149
1217
|
var PATH_CONNECT = "/connect";
|
|
1150
1218
|
var PATH_WEBSOCKET_BASE = "/websocket";
|
|
@@ -1230,6 +1298,25 @@ function buildGuardHeaders(runConfig, actorRequest, options) {
|
|
|
1230
1298
|
// src/client/config.ts
|
|
1231
1299
|
import z3 from "zod/v4";
|
|
1232
1300
|
|
|
1301
|
+
// src/common/engine.ts
|
|
1302
|
+
var ENGINE_HOST = "127.0.0.1";
|
|
1303
|
+
var ENGINE_PORT = 6420;
|
|
1304
|
+
var ENGINE_ENDPOINT = buildEngineEndpoint(ENGINE_HOST, ENGINE_PORT);
|
|
1305
|
+
function buildEngineEndpoint(host, port) {
|
|
1306
|
+
const urlHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
1307
|
+
return `http://${urlHost}:${port}`;
|
|
1308
|
+
}
|
|
1309
|
+
function isLocalEngineEndpoint(endpoint) {
|
|
1310
|
+
let url;
|
|
1311
|
+
try {
|
|
1312
|
+
url = new URL(endpoint);
|
|
1313
|
+
} catch {
|
|
1314
|
+
return false;
|
|
1315
|
+
}
|
|
1316
|
+
const hostname = url.hostname.toLowerCase();
|
|
1317
|
+
return hostname === "localhost" || hostname === "0.0.0.0" || hostname === "::" || hostname === "[::]" || hostname === "::1" || hostname === "[::1]" || /^127(?:\.\d{1,3}){0,3}$/.test(hostname);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1233
1320
|
// src/utils/endpoint-parser.ts
|
|
1234
1321
|
function tryParseEndpoint(ctx, options) {
|
|
1235
1322
|
const {
|
|
@@ -1327,6 +1414,8 @@ var ClientConfigSchemaBase = z3.object({
|
|
|
1327
1414
|
}),
|
|
1328
1415
|
/** Token to use to authenticate with the API. */
|
|
1329
1416
|
token: z3.string().optional().transform((val) => val ?? getRivetToken()),
|
|
1417
|
+
/** Issue and renew a client token on demand. Overrides the static token when provided. */
|
|
1418
|
+
getToken: z3.custom().optional(),
|
|
1330
1419
|
/** Namespace to connect to. */
|
|
1331
1420
|
namespace: z3.string().optional().transform((val) => val ?? getRivetNamespace()),
|
|
1332
1421
|
/** Name of the envoy pool. This is used to group together envoys in to different pools. */
|
|
@@ -1368,7 +1457,7 @@ function transformClientConfig(config, ctx) {
|
|
|
1368
1457
|
...config,
|
|
1369
1458
|
endpoint: parsedEndpoint?.endpoint,
|
|
1370
1459
|
namespace: parsedEndpoint?.namespace ?? config.namespace ?? "default",
|
|
1371
|
-
token: parsedEndpoint?.token ?? config.token
|
|
1460
|
+
token: parsedEndpoint?.token ?? config.token ?? (config.endpoint && isLocalEngineEndpoint(config.endpoint) ? "default" : void 0)
|
|
1372
1461
|
};
|
|
1373
1462
|
}
|
|
1374
1463
|
|
|
@@ -1679,7 +1768,8 @@ async function openWebSocketToGateway(runConfig, gatewayUrl, encoding, params, o
|
|
|
1679
1768
|
const ackHookToken = typeof process !== "undefined" && process.env.VITEST ? crypto.randomUUID() : void 0;
|
|
1680
1769
|
logger3().debug({
|
|
1681
1770
|
msg: "opening websocket to actor via guard",
|
|
1682
|
-
|
|
1771
|
+
// Gateway URLs can embed credentials; never include the path or query in logs.
|
|
1772
|
+
origin: new URL(gatewayUrl).origin
|
|
1683
1773
|
});
|
|
1684
1774
|
const ws = new WebSocket2(
|
|
1685
1775
|
gatewayUrl,
|
|
@@ -3865,7 +3955,8 @@ async function sendHttpRequest(opts) {
|
|
|
3865
3955
|
{
|
|
3866
3956
|
metadata: responseData.metadata,
|
|
3867
3957
|
rayId: rayId ?? void 0,
|
|
3868
|
-
actor: responseData.actor
|
|
3958
|
+
actor: responseData.actor,
|
|
3959
|
+
statusCode: response.status
|
|
3869
3960
|
}
|
|
3870
3961
|
);
|
|
3871
3962
|
} catch (error) {
|
|
@@ -3946,6 +4037,14 @@ async function apiCall(config, method, path, body) {
|
|
|
3946
4037
|
}
|
|
3947
4038
|
|
|
3948
4039
|
// src/engine-client/api-endpoints.ts
|
|
4040
|
+
async function issueToken(config, options) {
|
|
4041
|
+
return apiCall(config, "POST", "/auth/tokens", {
|
|
4042
|
+
namespace: config.namespace,
|
|
4043
|
+
subject: options.subject,
|
|
4044
|
+
duration: options.expiresIn,
|
|
4045
|
+
grants: options.grants
|
|
4046
|
+
});
|
|
4047
|
+
}
|
|
3949
4048
|
async function getActor(config, _, actorId) {
|
|
3950
4049
|
return apiCall(
|
|
3951
4050
|
config,
|
|
@@ -4183,6 +4282,8 @@ function closeWebSocketIfOpen(ws, code, reason) {
|
|
|
4183
4282
|
var RemoteEngineControlClient = class {
|
|
4184
4283
|
#config;
|
|
4185
4284
|
#metadataPromise;
|
|
4285
|
+
#tokenProvider;
|
|
4286
|
+
#webSocketTokens = /* @__PURE__ */ new WeakMap();
|
|
4186
4287
|
constructor(runConfig) {
|
|
4187
4288
|
if (getNextPhase() === "phase-production-build") {
|
|
4188
4289
|
logger3().info(
|
|
@@ -4191,6 +4292,8 @@ var RemoteEngineControlClient = class {
|
|
|
4191
4292
|
runConfig.disableMetadataLookup = true;
|
|
4192
4293
|
}
|
|
4193
4294
|
this.#config = { ...runConfig };
|
|
4295
|
+
if (runConfig.getToken)
|
|
4296
|
+
this.#tokenProvider = new TokenProvider(runConfig.getToken);
|
|
4194
4297
|
if (!runConfig.disableMetadataLookup) {
|
|
4195
4298
|
this.#metadataPromise = lookupMetadataCached(this.#config).then(
|
|
4196
4299
|
(metadataData) => {
|
|
@@ -4199,14 +4302,13 @@ var RemoteEngineControlClient = class {
|
|
|
4199
4302
|
if (metadataData.clientNamespace) {
|
|
4200
4303
|
this.#config.namespace = metadataData.clientNamespace;
|
|
4201
4304
|
}
|
|
4202
|
-
if (metadataData.clientToken) {
|
|
4305
|
+
if (metadataData.clientToken && !this.#tokenProvider) {
|
|
4203
4306
|
this.#config.token = metadataData.clientToken;
|
|
4204
4307
|
}
|
|
4205
4308
|
logger3().info({
|
|
4206
4309
|
msg: "overriding client endpoint",
|
|
4207
4310
|
endpoint: metadataData.clientEndpoint,
|
|
4208
|
-
namespace: metadataData.clientNamespace
|
|
4209
|
-
token: metadataData.clientToken
|
|
4311
|
+
namespace: metadataData.clientNamespace
|
|
4210
4312
|
});
|
|
4211
4313
|
}
|
|
4212
4314
|
logger3().info({
|
|
@@ -4219,12 +4321,47 @@ var RemoteEngineControlClient = class {
|
|
|
4219
4321
|
);
|
|
4220
4322
|
}
|
|
4221
4323
|
}
|
|
4324
|
+
async #authorizedConfig() {
|
|
4325
|
+
if (!this.#tokenProvider) return this.#config;
|
|
4326
|
+
return { ...this.#config, token: await this.#tokenProvider.current() };
|
|
4327
|
+
}
|
|
4328
|
+
async #withCredential(request, readOnly = false) {
|
|
4329
|
+
const config = await this.#authorizedConfig();
|
|
4330
|
+
try {
|
|
4331
|
+
return await request(config);
|
|
4332
|
+
} catch (error) {
|
|
4333
|
+
if (this.#tokenProvider && config.token && error instanceof RivetError && error.statusCode === 401 && isInvalidToken(error.group, error.code)) {
|
|
4334
|
+
if (readOnly) {
|
|
4335
|
+
const token = await this.#tokenProvider.refreshIfCurrent(
|
|
4336
|
+
config.token
|
|
4337
|
+
);
|
|
4338
|
+
return request({ ...this.#config, token });
|
|
4339
|
+
}
|
|
4340
|
+
await this.#tokenProvider.refreshIfCurrent(config.token);
|
|
4341
|
+
}
|
|
4342
|
+
throw error;
|
|
4343
|
+
}
|
|
4344
|
+
}
|
|
4345
|
+
async issueToken(options) {
|
|
4346
|
+
await this.#metadataPromise;
|
|
4347
|
+
const response = await this.#withCredential(
|
|
4348
|
+
(config) => issueToken(config, options)
|
|
4349
|
+
);
|
|
4350
|
+
return {
|
|
4351
|
+
token: response.token,
|
|
4352
|
+
issuedAt: response.issued_ts,
|
|
4353
|
+
expiresAt: response.expires_ts
|
|
4354
|
+
};
|
|
4355
|
+
}
|
|
4222
4356
|
async getForId({
|
|
4223
4357
|
name,
|
|
4224
4358
|
actorId
|
|
4225
4359
|
}) {
|
|
4226
4360
|
await this.#metadataPromise;
|
|
4227
|
-
const response = await
|
|
4361
|
+
const response = await this.#withCredential(
|
|
4362
|
+
(config) => getActor(config, name, actorId),
|
|
4363
|
+
true
|
|
4364
|
+
);
|
|
4228
4365
|
const actor = response.actors[0];
|
|
4229
4366
|
if (!actor) return void 0;
|
|
4230
4367
|
if (actor.name !== name) {
|
|
@@ -4245,7 +4382,10 @@ var RemoteEngineControlClient = class {
|
|
|
4245
4382
|
await this.#metadataPromise;
|
|
4246
4383
|
logger3().debug({ msg: "getWithKey: searching for actor", name, key });
|
|
4247
4384
|
try {
|
|
4248
|
-
const response = await
|
|
4385
|
+
const response = await this.#withCredential(
|
|
4386
|
+
(config) => getActorByKey(config, name, key),
|
|
4387
|
+
true
|
|
4388
|
+
);
|
|
4249
4389
|
const actor = response.actors[0];
|
|
4250
4390
|
if (!actor) return void 0;
|
|
4251
4391
|
logger3().debug({
|
|
@@ -4278,16 +4418,18 @@ var RemoteEngineControlClient = class {
|
|
|
4278
4418
|
key
|
|
4279
4419
|
});
|
|
4280
4420
|
try {
|
|
4281
|
-
const { actor, created } = await
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4421
|
+
const { actor, created } = await this.#withCredential(
|
|
4422
|
+
(config) => getOrCreateActor(config, {
|
|
4423
|
+
datacenter: region,
|
|
4424
|
+
name,
|
|
4425
|
+
key: serializeActorKey(key),
|
|
4426
|
+
runner_name_selector: poolName ?? this.#config.poolName,
|
|
4427
|
+
input: actorInput ? uint8ArrayToBase64(
|
|
4428
|
+
encodeCborCompat(actorInput)
|
|
4429
|
+
) : void 0,
|
|
4430
|
+
crash_policy: crashPolicy ?? "sleep"
|
|
4431
|
+
})
|
|
4432
|
+
);
|
|
4291
4433
|
logger3().info({
|
|
4292
4434
|
msg: "getOrCreateWithKey: actor ready",
|
|
4293
4435
|
actorId: actor.actor_id,
|
|
@@ -4303,7 +4445,10 @@ var RemoteEngineControlClient = class {
|
|
|
4303
4445
|
name,
|
|
4304
4446
|
key
|
|
4305
4447
|
});
|
|
4306
|
-
const response = await
|
|
4448
|
+
const response = await this.#withCredential(
|
|
4449
|
+
(config) => getActorByKey(config, name, key),
|
|
4450
|
+
true
|
|
4451
|
+
);
|
|
4307
4452
|
const existing = response.actors[0];
|
|
4308
4453
|
if (!existing) throw error;
|
|
4309
4454
|
logger3().info({
|
|
@@ -4327,14 +4472,18 @@ var RemoteEngineControlClient = class {
|
|
|
4327
4472
|
}) {
|
|
4328
4473
|
await this.#metadataPromise;
|
|
4329
4474
|
logger3().info({ msg: "creating actor via engine api", name, key });
|
|
4330
|
-
const result = await
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4475
|
+
const result = await this.#withCredential(
|
|
4476
|
+
(config) => createActor(config, {
|
|
4477
|
+
datacenter: region,
|
|
4478
|
+
name,
|
|
4479
|
+
runner_name_selector: poolName ?? this.#config.poolName,
|
|
4480
|
+
key: serializeActorKey(key),
|
|
4481
|
+
input: input ? uint8ArrayToBase64(
|
|
4482
|
+
encodeCborCompat(input)
|
|
4483
|
+
) : void 0,
|
|
4484
|
+
crash_policy: crashPolicy ?? "sleep"
|
|
4485
|
+
})
|
|
4486
|
+
);
|
|
4338
4487
|
logger3().info({
|
|
4339
4488
|
msg: "actor created",
|
|
4340
4489
|
actorId: result.actor.actor_id,
|
|
@@ -4346,43 +4495,60 @@ var RemoteEngineControlClient = class {
|
|
|
4346
4495
|
async listActors({ name }) {
|
|
4347
4496
|
await this.#metadataPromise;
|
|
4348
4497
|
logger3().debug({ msg: "listing actors via engine api", name });
|
|
4349
|
-
const response = await
|
|
4498
|
+
const response = await this.#withCredential(
|
|
4499
|
+
(config) => listActorsByName(config, name),
|
|
4500
|
+
true
|
|
4501
|
+
);
|
|
4350
4502
|
return response.actors.map(apiActorToOutput);
|
|
4351
4503
|
}
|
|
4352
4504
|
async destroyActor(actorId) {
|
|
4353
4505
|
await this.#metadataPromise;
|
|
4354
4506
|
logger3().info({ msg: "destroying actor via engine api", actorId });
|
|
4355
|
-
await
|
|
4507
|
+
await this.#withCredential((config) => destroyActor(config, actorId));
|
|
4356
4508
|
logger3().info({ msg: "actor destroyed", actorId });
|
|
4357
4509
|
}
|
|
4358
4510
|
async sendRequest(target, actorRequest, options = {}) {
|
|
4359
4511
|
await this.#metadataPromise;
|
|
4360
|
-
const
|
|
4361
|
-
const gatewayUrl = this.#buildGatewayUrlForTarget(
|
|
4362
|
-
target,
|
|
4363
|
-
path,
|
|
4364
|
-
options
|
|
4365
|
-
);
|
|
4512
|
+
const config = await this.#authorizedConfig();
|
|
4366
4513
|
const httpOptions = {
|
|
4367
4514
|
...options,
|
|
4368
4515
|
directActorId: shouldSkipReadyWait(options) ? directActorIdFromTarget(target) : void 0
|
|
4369
4516
|
};
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4517
|
+
const send = (current) => sendHttpRequestToGateway(
|
|
4518
|
+
current,
|
|
4519
|
+
this.#buildGatewayUrlForTarget(
|
|
4520
|
+
current,
|
|
4521
|
+
target,
|
|
4522
|
+
requestPath(actorRequest),
|
|
4523
|
+
options
|
|
4524
|
+
),
|
|
4373
4525
|
actorRequest,
|
|
4374
4526
|
httpOptions
|
|
4375
4527
|
);
|
|
4528
|
+
const response = await send(config);
|
|
4529
|
+
if (!this.#tokenProvider || !config.token || !isInvalidTokenResponse(response))
|
|
4530
|
+
return response;
|
|
4531
|
+
if ((actorRequest.method === "GET" || actorRequest.method === "HEAD") && !("getOrCreateForKey" in target)) {
|
|
4532
|
+
const token = await this.#tokenProvider.refreshIfCurrent(
|
|
4533
|
+
config.token
|
|
4534
|
+
);
|
|
4535
|
+
await response.body?.cancel();
|
|
4536
|
+
return send({ ...this.#config, token });
|
|
4537
|
+
}
|
|
4538
|
+
await this.#tokenProvider.refreshIfCurrent(config.token);
|
|
4539
|
+
return response;
|
|
4376
4540
|
}
|
|
4377
4541
|
async openWebSocket(path, target, encoding, params, options = {}) {
|
|
4378
4542
|
await this.#metadataPromise;
|
|
4543
|
+
const config = await this.#authorizedConfig();
|
|
4379
4544
|
const gatewayUrl = this.#buildGatewayUrlForTarget(
|
|
4545
|
+
config,
|
|
4380
4546
|
target,
|
|
4381
4547
|
path,
|
|
4382
4548
|
options
|
|
4383
4549
|
);
|
|
4384
|
-
|
|
4385
|
-
|
|
4550
|
+
const ws = await openWebSocketToGateway(
|
|
4551
|
+
config,
|
|
4386
4552
|
gatewayUrl,
|
|
4387
4553
|
encoding,
|
|
4388
4554
|
params,
|
|
@@ -4391,24 +4557,58 @@ var RemoteEngineControlClient = class {
|
|
|
4391
4557
|
directActorId: shouldSkipReadyWait(options) ? directActorIdFromTarget(target) : void 0
|
|
4392
4558
|
}
|
|
4393
4559
|
);
|
|
4560
|
+
this.#watchWebSocketAuth(ws, config.token);
|
|
4561
|
+
return ws;
|
|
4562
|
+
}
|
|
4563
|
+
async refreshAuthToken(ws) {
|
|
4564
|
+
const context2 = this.#webSocketTokens.get(ws);
|
|
4565
|
+
if (!context2?.refresh) return false;
|
|
4566
|
+
await context2.refresh;
|
|
4567
|
+
return true;
|
|
4568
|
+
}
|
|
4569
|
+
#watchWebSocketAuth(ws, token) {
|
|
4570
|
+
const tokenProvider = this.#tokenProvider;
|
|
4571
|
+
if (!tokenProvider || !token) return;
|
|
4572
|
+
const context2 = {};
|
|
4573
|
+
this.#webSocketTokens.set(ws, context2);
|
|
4574
|
+
ws.addEventListener(
|
|
4575
|
+
"close",
|
|
4576
|
+
(event) => {
|
|
4577
|
+
if (event.code !== 1008 || !event.reason) return;
|
|
4578
|
+
const separator = event.reason.indexOf(".");
|
|
4579
|
+
if (separator < 0) return;
|
|
4580
|
+
const code = event.reason.slice(separator + 1).split(/[\s:#]/, 1)[0];
|
|
4581
|
+
if (isInvalidToken(event.reason.slice(0, separator), code)) {
|
|
4582
|
+
context2.refresh = tokenProvider.refreshIfCurrent(token).catch((error) => {
|
|
4583
|
+
logger3().warn(
|
|
4584
|
+
"failed to renew authentication token"
|
|
4585
|
+
);
|
|
4586
|
+
throw error;
|
|
4587
|
+
});
|
|
4588
|
+
context2.refresh.catch(() => {
|
|
4589
|
+
});
|
|
4590
|
+
}
|
|
4591
|
+
}
|
|
4592
|
+
);
|
|
4394
4593
|
}
|
|
4395
4594
|
async buildGatewayUrl(target, options = {}) {
|
|
4396
4595
|
await this.#metadataPromise;
|
|
4397
|
-
return this.#buildGatewayUrlForTarget(
|
|
4596
|
+
return this.#buildGatewayUrlForTarget(
|
|
4597
|
+
await this.#authorizedConfig(),
|
|
4598
|
+
target,
|
|
4599
|
+
"",
|
|
4600
|
+
options
|
|
4601
|
+
);
|
|
4398
4602
|
}
|
|
4399
4603
|
async proxyRequest(_c, actorRequest, actorId) {
|
|
4400
|
-
|
|
4401
|
-
const gatewayUrl = this.#buildGatewayUrlForTarget(
|
|
4402
|
-
{ directId: actorId },
|
|
4403
|
-
requestPath(actorRequest)
|
|
4404
|
-
);
|
|
4405
|
-
return sendHttpRequestToGateway(this.#config, gatewayUrl, actorRequest);
|
|
4604
|
+
return this.sendRequest({ directId: actorId }, actorRequest);
|
|
4406
4605
|
}
|
|
4407
4606
|
async proxyWebSocket(c, path, actorId, encoding, params) {
|
|
4408
4607
|
await this.#metadataPromise;
|
|
4409
|
-
const
|
|
4608
|
+
const config = await this.#authorizedConfig();
|
|
4609
|
+
const upgradeWebSocket = config.getUpgradeWebSocket?.();
|
|
4410
4610
|
invariant3(upgradeWebSocket, "missing getUpgradeWebSocket");
|
|
4411
|
-
const endpoint = getEndpoint(
|
|
4611
|
+
const endpoint = getEndpoint(config);
|
|
4412
4612
|
const guardUrl = combineUrlPath(endpoint, path);
|
|
4413
4613
|
const wsGuardUrl = guardUrl.replace("http://", "ws://");
|
|
4414
4614
|
logger3().debug({
|
|
@@ -4418,7 +4618,7 @@ var RemoteEngineControlClient = class {
|
|
|
4418
4618
|
guardUrl
|
|
4419
4619
|
});
|
|
4420
4620
|
const protocols = buildWebSocketProtocols(
|
|
4421
|
-
|
|
4621
|
+
config,
|
|
4422
4622
|
encoding,
|
|
4423
4623
|
params,
|
|
4424
4624
|
void 0,
|
|
@@ -4436,8 +4636,8 @@ var RemoteEngineControlClient = class {
|
|
|
4436
4636
|
setGetUpgradeWebSocket(getUpgradeWebSocket) {
|
|
4437
4637
|
this.#config.getUpgradeWebSocket = getUpgradeWebSocket;
|
|
4438
4638
|
}
|
|
4439
|
-
#buildGatewayUrlForTarget(target, path, options = {}) {
|
|
4440
|
-
const endpoint = getEndpoint(
|
|
4639
|
+
#buildGatewayUrlForTarget(config, target, path, options = {}) {
|
|
4640
|
+
const endpoint = getEndpoint(config);
|
|
4441
4641
|
if (shouldSkipReadyWait(options) && directActorIdFromTarget(target) && canUseDirectSkipReadyWaitPath(path)) {
|
|
4442
4642
|
return combineUrlPath(endpoint, path);
|
|
4443
4643
|
}
|
|
@@ -4445,7 +4645,7 @@ var RemoteEngineControlClient = class {
|
|
|
4445
4645
|
return buildActorGatewayUrl(
|
|
4446
4646
|
endpoint,
|
|
4447
4647
|
target.directId,
|
|
4448
|
-
|
|
4648
|
+
config.token,
|
|
4449
4649
|
path
|
|
4450
4650
|
);
|
|
4451
4651
|
}
|
|
@@ -4453,20 +4653,20 @@ var RemoteEngineControlClient = class {
|
|
|
4453
4653
|
return buildActorGatewayUrl(
|
|
4454
4654
|
endpoint,
|
|
4455
4655
|
target.getForId.actorId,
|
|
4456
|
-
|
|
4656
|
+
config.token,
|
|
4457
4657
|
path
|
|
4458
4658
|
);
|
|
4459
4659
|
}
|
|
4460
4660
|
if ("getForKey" in target || "getOrCreateForKey" in target) {
|
|
4461
4661
|
return buildActorQueryGatewayUrl(
|
|
4462
4662
|
endpoint,
|
|
4463
|
-
|
|
4663
|
+
config.namespace,
|
|
4464
4664
|
target,
|
|
4465
|
-
|
|
4665
|
+
config.token,
|
|
4466
4666
|
path,
|
|
4467
|
-
|
|
4667
|
+
config.maxInputSize,
|
|
4468
4668
|
void 0,
|
|
4469
|
-
"getOrCreateForKey" in target ? target.getOrCreateForKey.poolName ??
|
|
4669
|
+
"getOrCreateForKey" in target ? target.getOrCreateForKey.poolName ?? config.poolName : void 0,
|
|
4470
4670
|
options
|
|
4471
4671
|
);
|
|
4472
4672
|
}
|
|
@@ -4949,6 +5149,7 @@ var ActorConnRaw = class {
|
|
|
4949
5149
|
/** Promise used to indicate the socket has connected successfully. This will be rejected if the connection fails. */
|
|
4950
5150
|
#onOpenPromise;
|
|
4951
5151
|
#websocket;
|
|
5152
|
+
#authRetryAvailable = true;
|
|
4952
5153
|
#client;
|
|
4953
5154
|
#driver;
|
|
4954
5155
|
#currentActorInvocation;
|
|
@@ -5191,6 +5392,10 @@ var ActorConnRaw = class {
|
|
|
5191
5392
|
if (error instanceof ActorConnDisposed) {
|
|
5192
5393
|
return false;
|
|
5193
5394
|
}
|
|
5395
|
+
if (error instanceof RivetError && isInvalidToken(error.group, error.code) && this.#driver.refreshAuthToken && this.#authRetryAvailable) {
|
|
5396
|
+
this.#authRetryAvailable = false;
|
|
5397
|
+
return true;
|
|
5398
|
+
}
|
|
5194
5399
|
if (error instanceof RivetError && this.#shouldReconnectForStaleActor(error.group, error.code)) {
|
|
5195
5400
|
return true;
|
|
5196
5401
|
}
|
|
@@ -5315,6 +5520,7 @@ var ActorConnRaw = class {
|
|
|
5315
5520
|
messageQueueLength: this.#messageQueue.length,
|
|
5316
5521
|
connId: this.#connId
|
|
5317
5522
|
});
|
|
5523
|
+
this.#authRetryAvailable = true;
|
|
5318
5524
|
this.#setConnStatus("connected");
|
|
5319
5525
|
if (this.#onOpenPromise) {
|
|
5320
5526
|
this.#onOpenPromise.resolve(void 0);
|
|
@@ -5456,6 +5662,7 @@ var ActorConnRaw = class {
|
|
|
5456
5662
|
}
|
|
5457
5663
|
/** Called by the onclose event from drivers. */
|
|
5458
5664
|
async #handleOnClose(event) {
|
|
5665
|
+
const failedSocket = this.#websocket;
|
|
5459
5666
|
const closeEvent = event;
|
|
5460
5667
|
const wasClean = closeEvent.wasClean;
|
|
5461
5668
|
const wasConnected = this.#connStatus === "connected";
|
|
@@ -5477,6 +5684,20 @@ var ActorConnRaw = class {
|
|
|
5477
5684
|
const parsed = parseWebSocketCloseReason(reason);
|
|
5478
5685
|
if (parsed) {
|
|
5479
5686
|
const { group, code, rayId } = parsed;
|
|
5687
|
+
if (isInvalidToken(group, code) && closeEvent.code === 1008 && failedSocket) {
|
|
5688
|
+
try {
|
|
5689
|
+
if (!await this.#driver.refreshAuthToken?.(
|
|
5690
|
+
failedSocket
|
|
5691
|
+
)) {
|
|
5692
|
+
this.#authRetryAvailable = false;
|
|
5693
|
+
}
|
|
5694
|
+
} catch {
|
|
5695
|
+
logger2().warn("token renewal failed");
|
|
5696
|
+
this.#authRetryAvailable = false;
|
|
5697
|
+
}
|
|
5698
|
+
} else if (isInvalidToken(group, code)) {
|
|
5699
|
+
this.#authRetryAvailable = false;
|
|
5700
|
+
}
|
|
5480
5701
|
if (this.#shouldReconnectForStaleActor(group, code)) {
|
|
5481
5702
|
this.#clearResolvedActorIdentity();
|
|
5482
5703
|
this.#onOpenPromise?.reject(
|
|
@@ -5526,7 +5747,7 @@ var ActorConnRaw = class {
|
|
|
5526
5747
|
if (error instanceof RivetError) {
|
|
5527
5748
|
this.#dispatchActorError(error);
|
|
5528
5749
|
}
|
|
5529
|
-
if (wasConnected) {
|
|
5750
|
+
if (wasConnected && this.#authRetryAvailable) {
|
|
5530
5751
|
logger2().debug({
|
|
5531
5752
|
msg: "triggering reconnect",
|
|
5532
5753
|
connId: this.#connId
|
|
@@ -6832,6 +7053,22 @@ var ActorHandleRaw = class {
|
|
|
6832
7053
|
"dynamic actor resolution did not produce a direct actor id"
|
|
6833
7054
|
);
|
|
6834
7055
|
}
|
|
7056
|
+
/** Issue a token scoped to this actor. Defaults to actor gateway read access. */
|
|
7057
|
+
async issueToken(options = {}) {
|
|
7058
|
+
const actorId = await this.resolve();
|
|
7059
|
+
const permissions = options.permissions ?? {
|
|
7060
|
+
actor_gateway: ["read"]
|
|
7061
|
+
};
|
|
7062
|
+
const grants = Object.keys(permissions).flatMap((resource) => {
|
|
7063
|
+
const operations = permissions[resource];
|
|
7064
|
+
return operations ? [{ resource, target: { id: actorId }, operations }] : [];
|
|
7065
|
+
});
|
|
7066
|
+
return this.#driver.issueToken({
|
|
7067
|
+
subject: options.subject,
|
|
7068
|
+
expiresIn: options.expiresIn,
|
|
7069
|
+
grants
|
|
7070
|
+
});
|
|
7071
|
+
}
|
|
6835
7072
|
/**
|
|
6836
7073
|
* Returns the raw URL for routing traffic to the actor.
|
|
6837
7074
|
*/
|
|
@@ -6866,6 +7103,8 @@ var ACTOR_CONNS_SYMBOL = /* @__PURE__ */ Symbol("actorConns");
|
|
|
6866
7103
|
var CREATE_ACTOR_CONN_PROXY = /* @__PURE__ */ Symbol("createActorConnProxy");
|
|
6867
7104
|
var ClientRaw = class {
|
|
6868
7105
|
#disposed = false;
|
|
7106
|
+
/** Issue namespace-scoped tokens with an explicit grant list. */
|
|
7107
|
+
auth;
|
|
6869
7108
|
[ACTOR_CONNS_SYMBOL] = /* @__PURE__ */ new Set();
|
|
6870
7109
|
#driver;
|
|
6871
7110
|
#encodingKind;
|
|
@@ -6877,6 +7116,9 @@ var ClientRaw = class {
|
|
|
6877
7116
|
*/
|
|
6878
7117
|
constructor(driver, options = {}) {
|
|
6879
7118
|
this.#driver = driver;
|
|
7119
|
+
this.auth = {
|
|
7120
|
+
issueToken: (issueOptions) => this.#driver.issueToken(issueOptions)
|
|
7121
|
+
};
|
|
6880
7122
|
this.#encodingKind = options.encoding ?? "bare";
|
|
6881
7123
|
this.#gatewayOptions = options.gateway ?? {};
|
|
6882
7124
|
this.#currentActorInvocation = options.currentActorInvocation;
|