rivetkit 2.3.0-rc.5 → 2.3.0-rc.6

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.
Files changed (113) hide show
  1. package/dist/browser/client.d.ts +21 -18
  2. package/dist/browser/client.js +735 -170
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +1 -1
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/actor/errors.cjs +4 -2
  7. package/dist/tsup/actor/errors.cjs.map +1 -1
  8. package/dist/tsup/actor/errors.d.cts +1 -74
  9. package/dist/tsup/actor/errors.d.ts +1 -74
  10. package/dist/tsup/actor/errors.js +3 -1
  11. package/dist/tsup/agent-os/index.cjs +1 -1
  12. package/dist/tsup/agent-os/index.cjs.map +1 -1
  13. package/dist/tsup/agent-os/index.d.cts +18 -7
  14. package/dist/tsup/agent-os/index.d.ts +18 -7
  15. package/dist/tsup/agent-os/index.js +1 -1
  16. package/dist/tsup/agent-os/index.js.map +1 -1
  17. package/dist/tsup/{chunk-2GANBXVP.cjs → chunk-2G64KSZQ.cjs} +10 -10
  18. package/dist/tsup/{chunk-2GANBXVP.cjs.map → chunk-2G64KSZQ.cjs.map} +1 -1
  19. package/dist/tsup/{chunk-N2DQSJIW.js → chunk-6S25NVAP.js} +13 -46
  20. package/dist/tsup/chunk-6S25NVAP.js.map +1 -0
  21. package/dist/tsup/{chunk-NATOT3ET.js → chunk-CAF6JDJE.js} +4 -4
  22. package/dist/tsup/{chunk-PGYEMIOE.js → chunk-DEO7MMWQ.js} +2 -2
  23. package/dist/tsup/{chunk-SULB574D.js → chunk-EMO6E3PJ.js} +3 -3
  24. package/dist/tsup/{chunk-FTZIZ3JG.cjs → chunk-ENK7C66G.cjs} +838 -236
  25. package/dist/tsup/chunk-ENK7C66G.cjs.map +1 -0
  26. package/dist/tsup/{chunk-JY73X7VU.js → chunk-FLODVLYW.js} +690 -88
  27. package/dist/tsup/chunk-FLODVLYW.js.map +1 -0
  28. package/dist/tsup/{chunk-OVJX4IFY.cjs → chunk-HTR4YLNT.cjs} +4 -4
  29. package/dist/tsup/{chunk-OVJX4IFY.cjs.map → chunk-HTR4YLNT.cjs.map} +1 -1
  30. package/dist/tsup/{chunk-LELRJK66.cjs → chunk-JALSAX7Z.cjs} +3 -3
  31. package/dist/tsup/{chunk-LELRJK66.cjs.map → chunk-JALSAX7Z.cjs.map} +1 -1
  32. package/dist/tsup/{chunk-JRCZDHXT.cjs → chunk-K5BA2LEO.cjs} +19 -52
  33. package/dist/tsup/chunk-K5BA2LEO.cjs.map +1 -0
  34. package/dist/tsup/{chunk-K34B3OVG.js → chunk-KIWH5H3K.js} +30 -9
  35. package/dist/tsup/chunk-KIWH5H3K.js.map +1 -0
  36. package/dist/tsup/{chunk-NW2J4SOL.cjs → chunk-LIXXFXVR.cjs} +5 -5
  37. package/dist/tsup/{chunk-NW2J4SOL.cjs.map → chunk-LIXXFXVR.cjs.map} +1 -1
  38. package/dist/tsup/{chunk-HR547GVH.cjs → chunk-M5C7YNI5.cjs} +8 -8
  39. package/dist/tsup/{chunk-HR547GVH.cjs.map → chunk-M5C7YNI5.cjs.map} +1 -1
  40. package/dist/tsup/{chunk-V3QNBJ7N.cjs → chunk-QAZLM4WT.cjs} +31 -10
  41. package/dist/tsup/chunk-QAZLM4WT.cjs.map +1 -0
  42. package/dist/tsup/{chunk-LDTT6WKJ.js → chunk-RTC2AZGB.js} +2 -2
  43. package/dist/tsup/{chunk-UXTP4EBU.js → chunk-ZI5QJMKO.js} +2 -2
  44. package/dist/tsup/client/mod.cjs +7 -7
  45. package/dist/tsup/client/mod.d.cts +3 -4
  46. package/dist/tsup/client/mod.d.ts +3 -4
  47. package/dist/tsup/client/mod.js +6 -6
  48. package/dist/tsup/common/log.cjs +3 -3
  49. package/dist/tsup/common/log.js +2 -2
  50. package/dist/tsup/common/websocket.cjs +4 -4
  51. package/dist/tsup/common/websocket.js +3 -3
  52. package/dist/tsup/{config-CvQUtDp9.d.ts → config-0Ta55UV0.d.ts} +10 -9
  53. package/dist/tsup/{config-C-a9vrke.d.cts → config-Ca8dN4cS.d.cts} +10 -9
  54. package/dist/tsup/{context-A7R0bsZL.d.ts → context-B_IWbWne.d.ts} +1 -1
  55. package/dist/tsup/{context-CA3r-pf2.d.cts → context-CUrQ9MHc.d.cts} +1 -1
  56. package/dist/tsup/inspector/mod.cjs +6 -6
  57. package/dist/tsup/inspector/mod.js +5 -5
  58. package/dist/tsup/mod.cjs +252 -207
  59. package/dist/tsup/mod.cjs.map +1 -1
  60. package/dist/tsup/mod.d.cts +4 -5
  61. package/dist/tsup/mod.d.ts +4 -5
  62. package/dist/tsup/mod.js +183 -138
  63. package/dist/tsup/mod.js.map +1 -1
  64. package/dist/tsup/test/mod.cjs +10 -10
  65. package/dist/tsup/test/mod.d.cts +2 -3
  66. package/dist/tsup/test/mod.d.ts +2 -3
  67. package/dist/tsup/test/mod.js +6 -6
  68. package/dist/tsup/utils-DVekpm4I.d.cts +103 -0
  69. package/dist/tsup/utils-DVekpm4I.d.ts +103 -0
  70. package/dist/tsup/utils.cjs +3 -3
  71. package/dist/tsup/utils.d.cts +1 -1
  72. package/dist/tsup/utils.d.ts +1 -1
  73. package/dist/tsup/utils.js +2 -2
  74. package/dist/tsup/workflow/mod.cjs +9 -9
  75. package/dist/tsup/workflow/mod.d.cts +4 -5
  76. package/dist/tsup/workflow/mod.d.ts +4 -5
  77. package/dist/tsup/workflow/mod.js +5 -5
  78. package/package.json +8 -8
  79. package/src/actor/errors.ts +53 -7
  80. package/src/client/actor-conn.ts +52 -29
  81. package/src/client/actor-handle.ts +57 -23
  82. package/src/client/errors.ts +2 -1
  83. package/src/client/raw-utils.ts +2 -4
  84. package/src/client/utils.ts +32 -3
  85. package/src/common/actor-router-consts.ts +4 -0
  86. package/src/common/bare/generated/client-protocol/v4.ts +599 -0
  87. package/src/common/client-protocol-versioned.ts +125 -18
  88. package/src/common/client-protocol-zod.ts +7 -0
  89. package/src/common/client-protocol.ts +1 -1
  90. package/src/common/database/native-database.test.ts +35 -0
  91. package/src/common/database/native-database.ts +8 -4
  92. package/src/common/router.ts +38 -8
  93. package/src/common/utils.ts +9 -52
  94. package/src/drivers/engine/actor-driver.ts +18 -17
  95. package/src/registry/config/index.ts +3 -5
  96. package/src/registry/index.ts +156 -19
  97. package/src/registry/napi-runtime.ts +44 -6
  98. package/src/registry/native.ts +5 -152
  99. package/src/registry/runtime.ts +16 -5
  100. package/src/registry/wasm-runtime.ts +22 -2
  101. package/dist/tsup/chunk-FTZIZ3JG.cjs.map +0 -1
  102. package/dist/tsup/chunk-JRCZDHXT.cjs.map +0 -1
  103. package/dist/tsup/chunk-JY73X7VU.js.map +0 -1
  104. package/dist/tsup/chunk-K34B3OVG.js.map +0 -1
  105. package/dist/tsup/chunk-N2DQSJIW.js.map +0 -1
  106. package/dist/tsup/chunk-V3QNBJ7N.cjs.map +0 -1
  107. package/dist/tsup/utils-fwx3o3K9.d.cts +0 -18
  108. package/dist/tsup/utils-fwx3o3K9.d.ts +0 -18
  109. /package/dist/tsup/{chunk-NATOT3ET.js.map → chunk-CAF6JDJE.js.map} +0 -0
  110. /package/dist/tsup/{chunk-PGYEMIOE.js.map → chunk-DEO7MMWQ.js.map} +0 -0
  111. /package/dist/tsup/{chunk-SULB574D.js.map → chunk-EMO6E3PJ.js.map} +0 -0
  112. /package/dist/tsup/{chunk-LDTT6WKJ.js.map → chunk-RTC2AZGB.js.map} +0 -0
  113. /package/dist/tsup/{chunk-UXTP4EBU.js.map → chunk-ZI5QJMKO.js.map} +0 -0
@@ -14,6 +14,15 @@ export interface RivetErrorOptions extends ErrorOptions {
14
14
  metadata?: unknown;
15
15
  /** Explicit HTTP status override for router responses. */
16
16
  statusCode?: number;
17
+ /** Actor context associated with this error. */
18
+ actor?: ActorSpecifier;
19
+ }
20
+
21
+ /** Identifies the actor that was handling work when an error was produced. */
22
+ export interface ActorSpecifier {
23
+ actorId: string;
24
+ generation: number;
25
+ key?: string;
17
26
  }
18
27
 
19
28
  export interface RivetErrorLike {
@@ -24,8 +33,11 @@ export interface RivetErrorLike {
24
33
  metadata?: unknown;
25
34
  public?: boolean;
26
35
  statusCode?: number;
36
+ actor?: ActorSpecifier;
27
37
  }
28
38
 
39
+ export interface BridgeRivetErrorPayload extends RivetErrorLike {}
40
+
29
41
  export interface UserErrorOptions extends ErrorOptions {
30
42
  /**
31
43
  * Machine readable code for this error. Useful for catching different types of
@@ -48,6 +60,7 @@ function looksLikeRivetErrorOptions(
48
60
  ("public" in value ||
49
61
  "metadata" in value ||
50
62
  "statusCode" in value ||
63
+ "actor" in value ||
51
64
  "cause" in value)
52
65
  );
53
66
  }
@@ -85,12 +98,25 @@ export function isRivetErrorLike(
85
98
  );
86
99
  }
87
100
 
101
+ function isActorSpecifier(value: unknown): value is ActorSpecifier {
102
+ return (
103
+ typeof value === "object" &&
104
+ value !== null &&
105
+ "actorId" in value &&
106
+ typeof value.actorId === "string" &&
107
+ "generation" in value &&
108
+ typeof value.generation === "number" &&
109
+ (!("key" in value) || value.key === undefined || typeof value.key === "string")
110
+ );
111
+ }
112
+
88
113
  export class RivetError extends Error {
89
114
  __type = "RivetError" as const;
90
115
 
91
116
  public public: boolean;
92
117
  public metadata?: unknown;
93
118
  public statusCode: number;
119
+ public actor?: ActorSpecifier;
94
120
  public readonly group: string;
95
121
  public readonly code: string;
96
122
 
@@ -123,6 +149,7 @@ export class RivetError extends Error {
123
149
  this.public = normalized.public ?? false;
124
150
  this.metadata = normalized.metadata;
125
151
  this.statusCode = normalized.statusCode ?? (this.public ? 400 : 500);
152
+ this.actor = normalized.actor;
126
153
  }
127
154
 
128
155
  toString() {
@@ -165,6 +192,7 @@ export function toRivetError(
165
192
  public: error.public,
166
193
  statusCode: error.statusCode,
167
194
  metadata: error.metadata,
195
+ actor: error.actor,
168
196
  cause: error instanceof Error ? error.cause : undefined,
169
197
  });
170
198
  }
@@ -177,6 +205,7 @@ export function toRivetError(
177
205
  public: fallback?.public,
178
206
  statusCode: fallback?.statusCode,
179
207
  metadata: fallback?.metadata,
208
+ actor: fallback?.actor,
180
209
  cause: error instanceof Error ? error : undefined,
181
210
  },
182
211
  );
@@ -190,10 +219,13 @@ export function encodeBridgeRivetError(error: RivetErrorLike): string {
190
219
  metadata: error.metadata,
191
220
  public: error.public,
192
221
  statusCode: error.statusCode,
222
+ actor: error.actor,
193
223
  })}`;
194
224
  }
195
225
 
196
- export function decodeBridgeRivetError(value: string): RivetError | undefined {
226
+ export function decodeBridgeRivetErrorPayload(
227
+ value: string,
228
+ ): BridgeRivetErrorPayload | undefined {
197
229
  if (!value.startsWith(BRIDGE_RIVET_ERROR_PREFIX)) {
198
230
  return undefined;
199
231
  }
@@ -201,21 +233,34 @@ export function decodeBridgeRivetError(value: string): RivetError | undefined {
201
233
  try {
202
234
  const payload = JSON.parse(
203
235
  value.slice(BRIDGE_RIVET_ERROR_PREFIX.length),
204
- ) as RivetErrorLike;
236
+ ) as BridgeRivetErrorPayload;
205
237
  if (!isRivetErrorLike(payload)) {
206
238
  return undefined;
207
239
  }
240
+ if (payload.actor !== undefined && !isActorSpecifier(payload.actor)) {
241
+ return undefined;
242
+ }
208
243
 
209
- return new RivetError(payload.group, payload.code, payload.message, {
210
- metadata: payload.metadata,
211
- public: payload.public,
212
- statusCode: payload.statusCode,
213
- });
244
+ return payload;
214
245
  } catch {
215
246
  return undefined;
216
247
  }
217
248
  }
218
249
 
250
+ export function decodeBridgeRivetError(value: string): RivetError | undefined {
251
+ const payload = decodeBridgeRivetErrorPayload(value);
252
+ if (!payload) {
253
+ return undefined;
254
+ }
255
+
256
+ return new RivetError(payload.group, payload.code, payload.message, {
257
+ metadata: payload.metadata,
258
+ public: payload.public,
259
+ statusCode: payload.statusCode,
260
+ actor: payload.actor,
261
+ });
262
+ }
263
+
219
264
  export function isRivetErrorCode(
220
265
  error: unknown,
221
266
  group: string,
@@ -241,6 +286,7 @@ export function internalError(
241
286
  public: options?.public,
242
287
  statusCode: options?.statusCode,
243
288
  metadata: options?.metadata,
289
+ actor: options?.actor,
244
290
  cause: options?.cause,
245
291
  },
246
292
  );
@@ -56,7 +56,6 @@ import {
56
56
  type QueueSendResult,
57
57
  type QueueSendWaitOptions,
58
58
  } from "./queue";
59
- import { resolveGatewayTarget } from "./resolve-gateway-target";
60
59
  import {
61
60
  type WebSocketMessage as ConnMessage,
62
61
  messageLength,
@@ -217,6 +216,9 @@ export class ActorConnRaw {
217
216
  this.#encoding = encoding;
218
217
  this.#actorResolutionState = actorResolutionState;
219
218
  this.#gatewayOptions = resolveActorGatewayOptions(gatewayOptions);
219
+ if ("getForId" in actorResolutionState) {
220
+ this.#actorId = actorResolutionState.getForId.actorId;
221
+ }
220
222
  this.#readyPromise = promiseWithResolvers((reason) =>
221
223
  logger().warn({
222
224
  msg: "unhandled ready promise rejection",
@@ -578,9 +580,7 @@ export class ActorConnRaw {
578
580
 
579
581
  async #connectWebSocket() {
580
582
  const params = await this.#resolveConnectionParams();
581
- const target = this.#gatewayOptions.skipReadyWait
582
- ? await this.#resolveGatewayTargetForSkipReadyWait()
583
- : getGatewayTarget(this.#actorResolutionState);
583
+ const target = getGatewayTarget(this.#actorResolutionState);
584
584
  const ws = await this.#driver.openWebSocket(
585
585
  PATH_CONNECT,
586
586
  target,
@@ -634,25 +634,6 @@ export class ActorConnRaw {
634
634
  });
635
635
  }
636
636
 
637
- async #resolveGatewayTargetForSkipReadyWait() {
638
- if ("getForId" in this.#actorResolutionState) {
639
- return {
640
- directId: this.#actorResolutionState.getForId.actorId,
641
- } as const;
642
- }
643
-
644
- if (this.#actorId) {
645
- return { directId: this.#actorId } as const;
646
- }
647
-
648
- return {
649
- directId: await resolveGatewayTarget(
650
- this.#driver,
651
- this.#actorResolutionState,
652
- ),
653
- } as const;
654
- }
655
-
656
637
  /** Called by the onopen event from drivers. */
657
638
  #handleOnOpen() {
658
639
  // Connection was disposed before Init message arrived - close the websocket to avoid leak
@@ -754,7 +735,7 @@ export class ActorConnRaw {
754
735
  this.#handleOnOpen();
755
736
  } else if (response.body.tag === "Error") {
756
737
  // Connection error
757
- const { group, code, message, metadata, actionId } =
738
+ const { group, code, message, metadata, actionId, actor } =
758
739
  response.body.val;
759
740
 
760
741
  if (actionId !== null) {
@@ -769,10 +750,16 @@ export class ActorConnRaw {
769
750
  code,
770
751
  message,
771
752
  metadata,
753
+ actorId: actor?.actorId,
754
+ generation: actor?.generation,
755
+ actorKey: actor?.key,
772
756
  });
773
757
 
774
758
  inFlight.reject(
775
- new errors.ActorError(group, code, message, metadata),
759
+ new errors.ActorError(group, code, message, {
760
+ metadata,
761
+ actor,
762
+ }),
776
763
  );
777
764
  } else {
778
765
  logger().warn({
@@ -781,12 +768,18 @@ export class ActorConnRaw {
781
768
  code,
782
769
  message,
783
770
  metadata,
771
+ actorId: actor?.actorId,
772
+ generation: actor?.generation,
773
+ actorKey: actor?.key,
784
774
  });
785
775
 
786
776
  if (this.#shouldReconnectForStaleActor(group, code)) {
787
777
  this.#clearResolvedActorIdentity();
788
778
  this.#onOpenPromise?.reject(
789
- new errors.ActorError(group, code, message, metadata),
779
+ new errors.ActorError(group, code, message, {
780
+ metadata,
781
+ actor,
782
+ }),
790
783
  );
791
784
  return;
792
785
  }
@@ -796,7 +789,7 @@ export class ActorConnRaw {
796
789
  group,
797
790
  code,
798
791
  message,
799
- metadata,
792
+ { metadata, actor },
800
793
  );
801
794
  if (errors.isSchedulingError(group, code) && this.#actorId) {
802
795
  const schedulingError = await checkForSchedulingError(
@@ -1368,6 +1361,7 @@ export class ActorConnRaw {
1368
1361
  message: string;
1369
1362
  metadata: unknown;
1370
1363
  actionId: bigint | null;
1364
+ actor?: errors.ActorSpecifier;
1371
1365
  };
1372
1366
  }
1373
1367
  | { tag: "ActionResponse"; val: { id: bigint; output: unknown } }
@@ -1382,8 +1376,26 @@ export class ActorConnRaw {
1382
1376
  buffer,
1383
1377
  CLIENT_PROTOCOL_TO_CLIENT,
1384
1378
  ToClientSchema,
1385
- // JSON: values are already the correct type
1386
- (msg): ToClientJson => msg as ToClientJson,
1379
+ // JSON/CBOR: normalize actor generation to the public number shape.
1380
+ (msg): any => {
1381
+ if (msg.body.tag !== "Error" || !msg.body.val.actor) {
1382
+ return msg as ToClientJson;
1383
+ }
1384
+ return {
1385
+ body: {
1386
+ tag: "Error",
1387
+ val: {
1388
+ ...msg.body.val,
1389
+ actor: {
1390
+ ...msg.body.val.actor,
1391
+ generation: Number(
1392
+ msg.body.val.actor.generation,
1393
+ ),
1394
+ },
1395
+ },
1396
+ },
1397
+ };
1398
+ },
1387
1399
  // BARE: need to decode ArrayBuffer fields back to unknown
1388
1400
  (msg): any => {
1389
1401
  if (msg.body.tag === "Error") {
@@ -1402,6 +1414,17 @@ export class ActorConnRaw {
1402
1414
  )
1403
1415
  : null,
1404
1416
  actionId: msg.body.val.actionId,
1417
+ actor: msg.body.val.actor
1418
+ ? {
1419
+ actorId: msg.body.val.actor.actorId,
1420
+ generation: Number(
1421
+ msg.body.val.actor.generation,
1422
+ ),
1423
+ key:
1424
+ msg.body.val.actor.key ??
1425
+ undefined,
1426
+ }
1427
+ : undefined,
1405
1428
  },
1406
1429
  },
1407
1430
  };
@@ -1,4 +1,5 @@
1
1
  import type { AnyActorDefinition } from "@/actor/definition";
2
+ import type { ActorSpecifier } from "@/actor/errors";
2
3
  import type { Encoding } from "@/common/encoding";
3
4
  import {
4
5
  HEADER_CONN_PARAMS,
@@ -139,7 +140,13 @@ export class ActorHandleRaw {
139
140
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
140
141
  let actorId: string | undefined;
141
142
  try {
142
- const target = await this.#resolveActionTarget(useQueryTarget);
143
+ const gatewayOptions = resolveActorGatewayOptions(
144
+ this.#gatewayOptions,
145
+ );
146
+ const target = await this.#resolveGatewayRequestTarget(
147
+ useQueryTarget,
148
+ gatewayOptions,
149
+ );
143
150
  actorId = "directId" in target ? target.directId : undefined;
144
151
 
145
152
  return await createQueueSender({
@@ -149,17 +156,13 @@ export class ActorHandleRaw {
149
156
  return await this.#driver.sendRequest(
150
157
  target,
151
158
  request,
152
- resolveActorGatewayOptions(
153
- this.#gatewayOptions,
154
- ),
159
+ gatewayOptions,
155
160
  );
156
161
  },
157
162
  }).send(name, body, options as any);
158
163
  } catch (err) {
159
- const { group, code, message, metadata } = deconstructError(
164
+ const { group, code, message, metadata, actor } = deconstructError(
160
165
  err,
161
- logger(),
162
- {},
163
166
  true,
164
167
  );
165
168
 
@@ -216,7 +219,7 @@ export class ActorHandleRaw {
216
219
  continue;
217
220
  }
218
221
 
219
- throw new ActorError(group, code, message, metadata);
222
+ throw new ActorError(group, code, message, { metadata, actor });
220
223
  }
221
224
  }
222
225
 
@@ -270,7 +273,10 @@ export class ActorHandleRaw {
270
273
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
271
274
  let actorId: string | undefined;
272
275
  try {
273
- const target = await this.#resolveActionTarget(useQueryTarget);
276
+ const target = await this.#resolveGatewayRequestTarget(
277
+ useQueryTarget,
278
+ gatewayOptions,
279
+ );
274
280
  actorId = "directId" in target ? target.directId : undefined;
275
281
 
276
282
  logger().debug(
@@ -337,10 +343,8 @@ export class ActorHandleRaw {
337
343
  }
338
344
  return output;
339
345
  } catch (err) {
340
- const { group, code, message, metadata } = deconstructError(
346
+ const { group, code, message, metadata, actor } = deconstructError(
341
347
  err,
342
- logger(),
343
- {},
344
348
  true,
345
349
  );
346
350
 
@@ -382,7 +386,7 @@ export class ActorHandleRaw {
382
386
  "actor",
383
387
  "not_found",
384
388
  "The actor does not exist or was destroyed.",
385
- metadata,
389
+ { metadata, actor },
386
390
  );
387
391
  }
388
392
 
@@ -398,7 +402,7 @@ export class ActorHandleRaw {
398
402
  continue;
399
403
  }
400
404
 
401
- throw new ActorError(group, code, message, metadata);
405
+ throw new ActorError(group, code, message, { metadata, actor });
402
406
  }
403
407
  }
404
408
 
@@ -561,6 +565,17 @@ export class ActorHandleRaw {
561
565
  }
562
566
  }
563
567
 
568
+ async #resolveGatewayRequestTarget(
569
+ useQueryTarget: boolean,
570
+ gatewayOptions: ActorGatewayOptions,
571
+ ) {
572
+ if (gatewayOptions.skipReadyWait) {
573
+ return getGatewayTarget(this.#actorResolutionState);
574
+ }
575
+
576
+ return await this.#resolveActionTarget(useQueryTarget);
577
+ }
578
+
564
579
  /**
565
580
  * Establishes a persistent connection to the actor.
566
581
  *
@@ -619,7 +634,10 @@ export class ActorHandleRaw {
619
634
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
620
635
  let actorId: string | undefined;
621
636
  try {
622
- const target = await this.#resolveActionTarget(useQueryTarget);
637
+ const target = await this.#resolveGatewayRequestTarget(
638
+ useQueryTarget,
639
+ gatewayOptions,
640
+ );
623
641
  actorId = "directId" in target ? target.directId : undefined;
624
642
  const response = await rawHttpFetch(
625
643
  this.#driver,
@@ -644,10 +662,8 @@ export class ActorHandleRaw {
644
662
  }
645
663
  return response;
646
664
  } catch (err) {
647
- const { group, code, message, metadata } = deconstructError(
665
+ const { group, code, message, metadata, actor } = deconstructError(
648
666
  err,
649
- logger(),
650
- {},
651
667
  true,
652
668
  );
653
669
 
@@ -691,7 +707,7 @@ export class ActorHandleRaw {
691
707
  continue;
692
708
  }
693
709
 
694
- throw new ActorError(group, code, message, metadata);
710
+ throw new ActorError(group, code, message, { metadata, actor });
695
711
  }
696
712
  }
697
713
 
@@ -771,6 +787,7 @@ export class ActorHandleRaw {
771
787
  code: string;
772
788
  message: string;
773
789
  metadata?: unknown;
790
+ actor?: ActorSpecifier;
774
791
  } | null> {
775
792
  if (response.ok) {
776
793
  return null;
@@ -790,13 +807,22 @@ export class ActorHandleRaw {
790
807
  code: string;
791
808
  message: string;
792
809
  metadata?: unknown;
810
+ actor?: ActorSpecifier;
793
811
  }
794
812
  >(
795
813
  encoding,
796
814
  new Uint8Array(await response.clone().arrayBuffer()),
797
815
  HTTP_RESPONSE_ERROR_VERSIONED,
798
816
  HttpResponseErrorSchema,
799
- (json) => json as HttpResponseErrorJson,
817
+ (json) => ({
818
+ ...json,
819
+ actor: json.actor
820
+ ? {
821
+ ...json.actor,
822
+ generation: Number(json.actor.generation),
823
+ }
824
+ : undefined,
825
+ }),
800
826
  (bare) => ({
801
827
  group: bare.group,
802
828
  code: bare.code,
@@ -804,6 +830,13 @@ export class ActorHandleRaw {
804
830
  metadata: bare.metadata
805
831
  ? decodeCborCompat(new Uint8Array(bare.metadata))
806
832
  : undefined,
833
+ actor: bare.actor
834
+ ? {
835
+ actorId: bare.actor.actorId,
836
+ generation: Number(bare.actor.generation),
837
+ key: bare.actor.key ?? undefined,
838
+ }
839
+ : undefined,
807
840
  }),
808
841
  );
809
842
  } catch {
@@ -824,9 +857,10 @@ export class ActorHandleRaw {
824
857
  this.#gatewayOptions,
825
858
  options,
826
859
  );
827
- const target = gatewayOptions.skipReadyWait
828
- ? await this.#resolveActionTarget(false)
829
- : getGatewayTarget(this.#actorResolutionState);
860
+ const target = await this.#resolveGatewayRequestTarget(
861
+ false,
862
+ gatewayOptions,
863
+ );
830
864
  return await rawWebSocket(
831
865
  this.#driver,
832
866
  target,
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  INTERNAL_ERROR_CODE,
3
3
  RivetError,
4
+ type ActorSpecifier,
4
5
  type RivetErrorLike,
5
6
  UserError,
6
7
  } from "@/actor/errors";
@@ -21,7 +22,7 @@ export class MalformedResponseMessage extends ActorClientError {
21
22
 
22
23
  export { RivetError, RivetError as ActorError, UserError };
23
24
  export type ActorSchedulingError = RivetError;
24
- export type { RivetErrorLike };
25
+ export type { ActorSpecifier, RivetErrorLike };
25
26
 
26
27
  export class HttpRequestError extends ActorClientError {
27
28
  constructor(message: string, opts?: { cause?: unknown }) {
@@ -96,13 +96,11 @@ export async function rawHttpFetch(
96
96
  return driver.sendRequest(target, proxyRequest, options);
97
97
  } catch (err) {
98
98
  // Standardize to ClientActorError instead of the native backend error
99
- const { group, code, message, metadata } = deconstructError(
99
+ const { group, code, message, metadata, actor } = deconstructError(
100
100
  err,
101
- logger(),
102
- {},
103
101
  true,
104
102
  );
105
- throw new ActorError(group, code, message, metadata);
103
+ throw new ActorError(group, code, message, { metadata, actor });
106
104
  }
107
105
  }
108
106
 
@@ -186,8 +186,16 @@ export async function sendHttpRequest<
186
186
  new Uint8Array(bufferResponse),
187
187
  HTTP_RESPONSE_ERROR_VERSIONED,
188
188
  HttpResponseErrorSchema,
189
- // JSON: metadata is already unknown
190
- (json): HttpResponseErrorJson => json as HttpResponseErrorJson,
189
+ // JSON/CBOR: normalize actor generation to the public number shape.
190
+ (json): any => ({
191
+ ...json,
192
+ actor: json.actor
193
+ ? {
194
+ ...json.actor,
195
+ generation: Number(json.actor.generation),
196
+ }
197
+ : undefined,
198
+ }),
191
199
  // BARE: decode ArrayBuffer metadata to unknown
192
200
  (bare): any => ({
193
201
  group: bare.group,
@@ -196,14 +204,35 @@ export async function sendHttpRequest<
196
204
  metadata: bare.metadata
197
205
  ? decodeCborCompat(new Uint8Array(bare.metadata))
198
206
  : undefined,
207
+ actor: bare.actor
208
+ ? {
209
+ actorId: bare.actor.actorId,
210
+ generation: Number(bare.actor.generation),
211
+ key: bare.actor.key ?? undefined,
212
+ }
213
+ : undefined,
199
214
  }),
200
215
  );
201
216
 
217
+ logger().warn({
218
+ msg: "http error response",
219
+ group: responseData.group,
220
+ code: responseData.code,
221
+ message: responseData.message,
222
+ metadata: responseData.metadata,
223
+ actorId: responseData.actor?.actorId,
224
+ generation: responseData.actor?.generation,
225
+ actorKey: responseData.actor?.key,
226
+ });
227
+
202
228
  throw new ActorError(
203
229
  responseData.group,
204
230
  responseData.code,
205
231
  responseData.message,
206
- responseData.metadata,
232
+ {
233
+ metadata: responseData.metadata,
234
+ actor: responseData.actor,
235
+ },
207
236
  );
208
237
  } catch (error) {
209
238
  // If it's already an ActorError, re-throw it
@@ -14,6 +14,8 @@ export const HEADER_ENCODING = "x-rivet-encoding";
14
14
  export const HEADER_CONN_PARAMS = "x-rivet-conn-params";
15
15
 
16
16
  export const HEADER_ACTOR_ID = "x-rivet-actor";
17
+ export const HEADER_ACTOR_GENERATION = "x-rivet-actor-generation";
18
+ export const HEADER_ACTOR_KEY = "x-rivet-actor-key";
17
19
 
18
20
  export const HEADER_RIVET_TOKEN = "x-rivet-token";
19
21
 
@@ -49,6 +51,8 @@ export const ALLOWED_PUBLIC_HEADERS = [
49
51
  HEADER_ENCODING,
50
52
  HEADER_CONN_PARAMS,
51
53
  HEADER_ACTOR_ID,
54
+ HEADER_ACTOR_GENERATION,
55
+ HEADER_ACTOR_KEY,
52
56
  HEADER_RIVET_TARGET,
53
57
  HEADER_RIVET_ACTOR,
54
58
  HEADER_RIVET_NAMESPACE,