rivetkit 2.3.0-rc.5 → 2.3.0-rc.7

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 (142) hide show
  1. package/dist/browser/client.d.ts +35 -3
  2. package/dist/browser/client.js +795 -200
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +4 -3
  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 +7 -5
  12. package/dist/tsup/agent-os/index.cjs.map +1 -1
  13. package/dist/tsup/agent-os/index.d.cts +35 -3
  14. package/dist/tsup/agent-os/index.d.ts +35 -3
  15. package/dist/tsup/agent-os/index.js +7 -5
  16. package/dist/tsup/agent-os/index.js.map +1 -1
  17. package/dist/tsup/{chunk-2GANBXVP.cjs → chunk-2H4ISA4Y.cjs} +10 -10
  18. package/dist/tsup/chunk-2H4ISA4Y.cjs.map +1 -0
  19. package/dist/tsup/{chunk-UXTP4EBU.js → chunk-4DJMFOSU.js} +2 -2
  20. package/dist/tsup/{chunk-LDTT6WKJ.js → chunk-4LTY5TOO.js} +132 -4
  21. package/dist/tsup/chunk-4LTY5TOO.js.map +1 -0
  22. package/dist/tsup/{chunk-PGYEMIOE.js → chunk-52TPEKEC.js} +2 -2
  23. package/dist/tsup/{chunk-OVJX4IFY.cjs → chunk-55E7IR6D.cjs} +4 -4
  24. package/dist/tsup/{chunk-OVJX4IFY.cjs.map → chunk-55E7IR6D.cjs.map} +1 -1
  25. package/dist/tsup/{chunk-V3QNBJ7N.cjs → chunk-63WNTDRC.cjs} +31 -10
  26. package/dist/tsup/chunk-63WNTDRC.cjs.map +1 -0
  27. package/dist/tsup/{chunk-SULB574D.js → chunk-CMV6N5OX.js} +3 -3
  28. package/dist/tsup/{chunk-T6YVRM4K.js → chunk-D5G75T7J.js} +3 -1
  29. package/dist/tsup/chunk-D5G75T7J.js.map +1 -0
  30. package/dist/tsup/{chunk-NW2J4SOL.cjs → chunk-FEOG44WH.cjs} +137 -9
  31. package/dist/tsup/chunk-FEOG44WH.cjs.map +1 -0
  32. package/dist/tsup/{chunk-HR547GVH.cjs → chunk-G5HUSWP4.cjs} +8 -8
  33. package/dist/tsup/{chunk-HR547GVH.cjs.map → chunk-G5HUSWP4.cjs.map} +1 -1
  34. package/dist/tsup/{chunk-N2DQSJIW.js → chunk-HERL2VQ2.js} +17 -48
  35. package/dist/tsup/chunk-HERL2VQ2.js.map +1 -0
  36. package/dist/tsup/{chunk-LELRJK66.cjs → chunk-SJLPZEA3.cjs} +3 -3
  37. package/dist/tsup/{chunk-LELRJK66.cjs.map → chunk-SJLPZEA3.cjs.map} +1 -1
  38. package/dist/tsup/{chunk-WQ4HNA4W.cjs → chunk-SRNOPUC6.cjs} +4 -2
  39. package/dist/tsup/chunk-SRNOPUC6.cjs.map +1 -0
  40. package/dist/tsup/{chunk-K34B3OVG.js → chunk-TMLOKTRB.js} +30 -9
  41. package/dist/tsup/chunk-TMLOKTRB.js.map +1 -0
  42. package/dist/tsup/{chunk-NATOT3ET.js → chunk-VFIY6GWO.js} +4 -4
  43. package/dist/tsup/chunk-VFIY6GWO.js.map +1 -0
  44. package/dist/tsup/{chunk-JY73X7VU.js → chunk-VJ4Y4WBT.js} +692 -114
  45. package/dist/tsup/chunk-VJ4Y4WBT.js.map +1 -0
  46. package/dist/tsup/{chunk-JRCZDHXT.cjs → chunk-X6HIFXNK.cjs} +23 -54
  47. package/dist/tsup/chunk-X6HIFXNK.cjs.map +1 -0
  48. package/dist/tsup/{chunk-FTZIZ3JG.cjs → chunk-ZGPX6KAH.cjs} +838 -260
  49. package/dist/tsup/chunk-ZGPX6KAH.cjs.map +1 -0
  50. package/dist/tsup/client/mod.cjs +7 -7
  51. package/dist/tsup/client/mod.d.cts +3 -4
  52. package/dist/tsup/client/mod.d.ts +3 -4
  53. package/dist/tsup/client/mod.js +6 -6
  54. package/dist/tsup/common/log.cjs +3 -3
  55. package/dist/tsup/common/log.js +2 -2
  56. package/dist/tsup/common/websocket.cjs +4 -4
  57. package/dist/tsup/common/websocket.js +3 -3
  58. package/dist/tsup/{config-CvQUtDp9.d.ts → config-Ak1lv4gF.d.ts} +27 -5
  59. package/dist/tsup/{config-C-a9vrke.d.cts → config-DU_xj4qZ.d.cts} +27 -5
  60. package/dist/tsup/{context-A7R0bsZL.d.ts → context-DAAp4Lpg.d.ts} +1 -1
  61. package/dist/tsup/{context-CA3r-pf2.d.cts → context-Dt_L55q8.d.cts} +1 -1
  62. package/dist/tsup/inspector/mod.cjs +6 -6
  63. package/dist/tsup/inspector/mod.js +5 -5
  64. package/dist/tsup/mod.cjs +507 -308
  65. package/dist/tsup/mod.cjs.map +1 -1
  66. package/dist/tsup/mod.d.cts +4 -5
  67. package/dist/tsup/mod.d.ts +4 -5
  68. package/dist/tsup/mod.js +432 -233
  69. package/dist/tsup/mod.js.map +1 -1
  70. package/dist/tsup/process-metrics-NW754INA.js +118 -0
  71. package/dist/tsup/process-metrics-NW754INA.js.map +1 -0
  72. package/dist/tsup/process-metrics-TYAGKCEJ.cjs +118 -0
  73. package/dist/tsup/process-metrics-TYAGKCEJ.cjs.map +1 -0
  74. package/dist/tsup/test/mod.cjs +10 -10
  75. package/dist/tsup/test/mod.d.cts +2 -3
  76. package/dist/tsup/test/mod.d.ts +2 -3
  77. package/dist/tsup/test/mod.js +6 -6
  78. package/dist/tsup/utils-DVekpm4I.d.cts +103 -0
  79. package/dist/tsup/utils-DVekpm4I.d.ts +103 -0
  80. package/dist/tsup/utils.cjs +3 -3
  81. package/dist/tsup/utils.d.cts +1 -1
  82. package/dist/tsup/utils.d.ts +1 -1
  83. package/dist/tsup/utils.js +2 -2
  84. package/dist/tsup/workflow/mod.cjs +41 -16
  85. package/dist/tsup/workflow/mod.cjs.map +1 -1
  86. package/dist/tsup/workflow/mod.d.cts +4 -5
  87. package/dist/tsup/workflow/mod.d.ts +4 -5
  88. package/dist/tsup/workflow/mod.js +35 -10
  89. package/dist/tsup/workflow/mod.js.map +1 -1
  90. package/package.json +11 -10
  91. package/src/actor/config.ts +3 -0
  92. package/src/actor/errors.ts +53 -7
  93. package/src/agent-os/actor/session.ts +2 -2
  94. package/src/client/actor-conn.ts +55 -60
  95. package/src/client/actor-handle.ts +59 -24
  96. package/src/client/errors.ts +2 -1
  97. package/src/client/queue.ts +2 -1
  98. package/src/client/raw-utils.ts +2 -4
  99. package/src/client/utils.ts +32 -4
  100. package/src/common/actor-router-consts.ts +4 -0
  101. package/src/common/bare/generated/client-protocol/v4.ts +599 -0
  102. package/src/common/client-protocol-versioned.ts +125 -18
  103. package/src/common/client-protocol-zod.ts +7 -0
  104. package/src/common/client-protocol.ts +1 -1
  105. package/src/common/database/native-database.test.ts +35 -0
  106. package/src/common/database/native-database.ts +8 -4
  107. package/src/common/encoding.ts +243 -5
  108. package/src/common/inline-websocket-adapter.ts +12 -12
  109. package/src/common/log.ts +1 -0
  110. package/src/common/router.ts +40 -10
  111. package/src/common/utils.ts +9 -200
  112. package/src/drivers/engine/actor-driver.ts +29 -28
  113. package/src/engine-client/actor-websocket-client.ts +2 -1
  114. package/src/engine-client/mod.ts +3 -2
  115. package/src/registry/config/index.ts +3 -5
  116. package/src/registry/index.ts +90 -16
  117. package/src/registry/napi-runtime.ts +15 -0
  118. package/src/registry/native.ts +197 -255
  119. package/src/registry/process-metrics.ts +183 -0
  120. package/src/registry/runtime.ts +4 -0
  121. package/src/registry/wasm-runtime.ts +9 -0
  122. package/src/registry/write-through-proxy.ts +40 -0
  123. package/src/serde.ts +2 -2
  124. package/src/workflow/context.ts +32 -5
  125. package/src/workflow/inspector.ts +2 -1
  126. package/dist/tsup/chunk-2GANBXVP.cjs.map +0 -1
  127. package/dist/tsup/chunk-FTZIZ3JG.cjs.map +0 -1
  128. package/dist/tsup/chunk-JRCZDHXT.cjs.map +0 -1
  129. package/dist/tsup/chunk-JY73X7VU.js.map +0 -1
  130. package/dist/tsup/chunk-K34B3OVG.js.map +0 -1
  131. package/dist/tsup/chunk-LDTT6WKJ.js.map +0 -1
  132. package/dist/tsup/chunk-N2DQSJIW.js.map +0 -1
  133. package/dist/tsup/chunk-NATOT3ET.js.map +0 -1
  134. package/dist/tsup/chunk-NW2J4SOL.cjs.map +0 -1
  135. package/dist/tsup/chunk-T6YVRM4K.js.map +0 -1
  136. package/dist/tsup/chunk-V3QNBJ7N.cjs.map +0 -1
  137. package/dist/tsup/chunk-WQ4HNA4W.cjs.map +0 -1
  138. package/dist/tsup/utils-fwx3o3K9.d.cts +0 -18
  139. package/dist/tsup/utils-fwx3o3K9.d.ts +0 -18
  140. /package/dist/tsup/{chunk-UXTP4EBU.js.map → chunk-4DJMFOSU.js.map} +0 -0
  141. /package/dist/tsup/{chunk-PGYEMIOE.js.map → chunk-52TPEKEC.js.map} +0 -0
  142. /package/dist/tsup/{chunk-SULB574D.js.map → chunk-CMV6N5OX.js.map} +0 -0
@@ -13,6 +13,171 @@ const JSON_COMPAT_BIGINT = "$BigInt";
13
13
  const JSON_COMPAT_ARRAY_BUFFER = "$ArrayBuffer";
14
14
  const JSON_COMPAT_UINT8_ARRAY = "$Uint8Array";
15
15
  const JSON_COMPAT_UNDEFINED = "$Undefined";
16
+ const JSON_COMPAT_SET = "$Set";
17
+
18
+ /**
19
+ * Types that cbor-x encodes natively without any compat transforms.
20
+ */
21
+ export type CborSerializable =
22
+ | string
23
+ | number
24
+ | boolean
25
+ | null
26
+ | undefined
27
+ | bigint
28
+ | Date
29
+ | RegExp
30
+ | Error
31
+ | ArrayBuffer
32
+ | Uint8Array
33
+ | Uint8ClampedArray
34
+ | Uint16Array
35
+ | Uint32Array
36
+ | BigUint64Array
37
+ | Int8Array
38
+ | Int16Array
39
+ | Int32Array
40
+ | BigInt64Array
41
+ | Float32Array
42
+ | Float64Array
43
+ | CborSerializable[]
44
+ | Map<CborSerializable, CborSerializable>
45
+ | { [key: string]: CborSerializable };
46
+
47
+ /**
48
+ * User-facing serializable type. Extends CborSerializable with Set (encoded
49
+ * as a `$Set` tagged array by the JSON compat layer).
50
+ */
51
+ export type JsonCompatValue =
52
+ | CborSerializable
53
+ | Set<JsonCompatValue>
54
+ | JsonCompatValue[]
55
+ | Map<JsonCompatValue, JsonCompatValue>
56
+ | { [key: string]: JsonCompatValue };
57
+
58
+ function isTypedArray(value: unknown): boolean {
59
+ return (
60
+ value instanceof Uint8ClampedArray ||
61
+ value instanceof Uint16Array ||
62
+ value instanceof Uint32Array ||
63
+ value instanceof BigUint64Array ||
64
+ value instanceof Int8Array ||
65
+ value instanceof Int16Array ||
66
+ value instanceof Int32Array ||
67
+ value instanceof BigInt64Array ||
68
+ value instanceof Float32Array ||
69
+ value instanceof Float64Array
70
+ );
71
+ }
72
+
73
+ /**
74
+ * Recursively validates that a value is CBOR serializable. Throws TypeError
75
+ * with a descriptive message for non-serializable values.
76
+ */
77
+ export function assertJsonCompatValue(
78
+ value: unknown,
79
+ path = "",
80
+ ): asserts value is JsonCompatValue {
81
+ if (
82
+ value === null ||
83
+ value === undefined ||
84
+ typeof value === "string" ||
85
+ typeof value === "number" ||
86
+ typeof value === "boolean" ||
87
+ typeof value === "bigint"
88
+ ) {
89
+ return;
90
+ }
91
+
92
+ if (typeof value === "function") {
93
+ throw new TypeError(
94
+ `Value at ${path || "root"} is a function and is not CBOR serializable`,
95
+ );
96
+ }
97
+
98
+ if (typeof value === "symbol") {
99
+ throw new TypeError(
100
+ `Value at ${path || "root"} is a symbol and is not CBOR serializable`,
101
+ );
102
+ }
103
+
104
+ if (
105
+ value instanceof Date ||
106
+ value instanceof RegExp ||
107
+ value instanceof Error ||
108
+ value instanceof ArrayBuffer ||
109
+ value instanceof Uint8Array ||
110
+ isTypedArray(value)
111
+ ) {
112
+ return;
113
+ }
114
+
115
+ if (value instanceof WeakMap) {
116
+ throw new TypeError(
117
+ `Value at ${path || "root"} is a WeakMap and is not CBOR serializable`,
118
+ );
119
+ }
120
+
121
+ if (value instanceof WeakSet) {
122
+ throw new TypeError(
123
+ `Value at ${path || "root"} is a WeakSet and is not CBOR serializable`,
124
+ );
125
+ }
126
+
127
+ if (value instanceof WeakRef) {
128
+ throw new TypeError(
129
+ `Value at ${path || "root"} is a WeakRef and is not CBOR serializable`,
130
+ );
131
+ }
132
+
133
+ if (value instanceof Promise) {
134
+ throw new TypeError(
135
+ `Value at ${path || "root"} is a Promise and is not CBOR serializable`,
136
+ );
137
+ }
138
+
139
+ if (value instanceof Map) {
140
+ for (const [k, v] of value.entries()) {
141
+ assertJsonCompatValue(k, `${path || "root"}.key(${String(k)})`);
142
+ assertJsonCompatValue(v, `${path || "root"}.value(${String(k)})`);
143
+ }
144
+ return;
145
+ }
146
+
147
+ if (value instanceof Set) {
148
+ let index = 0;
149
+ for (const item of value.values()) {
150
+ assertJsonCompatValue(item, `${path || "root"}.set[${index}]`);
151
+ index++;
152
+ }
153
+ return;
154
+ }
155
+
156
+ if (Array.isArray(value)) {
157
+ for (let i = 0; i < value.length; i++) {
158
+ assertJsonCompatValue(value[i], `${path || "root"}[${i}]`);
159
+ }
160
+ return;
161
+ }
162
+
163
+ if (isPlainObject(value)) {
164
+ for (const key in value) {
165
+ assertJsonCompatValue(
166
+ value[key as keyof typeof value],
167
+ path ? `${path}.${key}` : key,
168
+ );
169
+ }
170
+ return;
171
+ }
172
+
173
+ const typeName =
174
+ typeof value === "object" && value !== null
175
+ ? value.constructor?.name ?? typeof value
176
+ : typeof value;
177
+ throw new TypeError(
178
+ `Value at ${path || "root"} of type "${typeName}" is not CBOR serializable`,
179
+ );
180
+ }
16
181
 
17
182
  export const EncodingSchema = z.enum(["json", "cbor", "bare"]);
18
183
 
@@ -112,38 +277,95 @@ function isPlainObject(value: unknown): value is Record<string, unknown> {
112
277
  return proto === Object.prototype || proto === null;
113
278
  }
114
279
 
115
- export function encodeJsonCompatValue(input: any): any {
280
+ export function encodeJsonCompatValue(input: JsonCompatValue): unknown {
281
+ // Primitives
282
+ if (input === null) {
283
+ return input;
284
+ }
116
285
  if (input === undefined) {
117
286
  return [JSON_COMPAT_UNDEFINED, 0];
118
287
  }
288
+ if (
289
+ typeof input === "string" ||
290
+ typeof input === "number" ||
291
+ typeof input === "boolean"
292
+ ) {
293
+ return input;
294
+ }
119
295
  if (typeof input === "bigint") {
120
296
  return [JSON_COMPAT_BIGINT, input.toString()];
121
297
  }
298
+
299
+ // Binary types with custom encoding
122
300
  if (input instanceof ArrayBuffer) {
123
301
  return [JSON_COMPAT_ARRAY_BUFFER, base64EncodeArrayBuffer(input)];
124
302
  }
125
303
  if (input instanceof Uint8Array) {
126
304
  return [JSON_COMPAT_UINT8_ARRAY, base64EncodeUint8Array(input)];
127
305
  }
306
+
307
+ // TypedArrays pass through for cbor-x native handling
308
+ if (isTypedArray(input)) {
309
+ return input;
310
+ }
311
+
312
+ // Date, RegExp, and Error pass through for cbor-x native handling
313
+ if (input instanceof Date || input instanceof RegExp || input instanceof Error) {
314
+ return input;
315
+ }
316
+
317
+ // Set uses custom tag encoding
318
+ if (input instanceof Set) {
319
+ const encoded = [...input.values()].map((v) =>
320
+ encodeJsonCompatValue(v as JsonCompatValue),
321
+ );
322
+ return [JSON_COMPAT_SET, encoded];
323
+ }
324
+
325
+ // Map recurses into keys and values
326
+ if (input instanceof Map) {
327
+ const encoded = new Map<unknown, unknown>();
328
+ for (const [k, v] of input.entries()) {
329
+ encoded.set(
330
+ encodeJsonCompatValue(k as JsonCompatValue),
331
+ encodeJsonCompatValue(v as JsonCompatValue),
332
+ );
333
+ }
334
+ return encoded;
335
+ }
336
+
337
+ // Arrays
128
338
  if (Array.isArray(input)) {
129
- const encoded = input.map((value) => encodeJsonCompatValue(value));
339
+ const encoded = input.map((value) =>
340
+ encodeJsonCompatValue(value as JsonCompatValue),
341
+ );
130
342
  if (
131
343
  encoded.length === 2 &&
132
344
  typeof encoded[0] === "string" &&
133
- encoded[0].startsWith("$")
345
+ (encoded[0] as string).startsWith("$")
134
346
  ) {
135
347
  return ["$" + encoded[0], encoded[1]];
136
348
  }
137
349
  return encoded;
138
350
  }
351
+
352
+ // Plain objects
139
353
  if (isPlainObject(input)) {
140
354
  const encoded: Record<string, unknown> = {};
141
355
  for (const [key, value] of Object.entries(input)) {
142
- encoded[key] = encodeJsonCompatValue(value);
356
+ encoded[key] = encodeJsonCompatValue(value as JsonCompatValue);
143
357
  }
144
358
  return encoded;
145
359
  }
146
- return input;
360
+
361
+ // Not serializable
362
+ const typeName =
363
+ typeof input === "object" && input !== null
364
+ ? (input as object).constructor?.name ?? typeof input
365
+ : typeof input;
366
+ throw new TypeError(
367
+ `Value of type "${typeName}" is not CBOR serializable`,
368
+ );
147
369
  }
148
370
 
149
371
  export interface JsonCompatReviveOptions {
@@ -164,6 +386,16 @@ export function reviveJsonCompatValue(
164
386
  }
165
387
  return input;
166
388
  }
389
+ if (input instanceof Map) {
390
+ const revived = new Map();
391
+ for (const [k, v] of input.entries()) {
392
+ revived.set(
393
+ reviveJsonCompatValue(k, options),
394
+ reviveJsonCompatValue(v, options),
395
+ );
396
+ }
397
+ return revived;
398
+ }
167
399
  if (Array.isArray(input)) {
168
400
  if (
169
401
  input.length === 2 &&
@@ -182,6 +414,12 @@ export function reviveJsonCompatValue(
182
414
  if (input[0] === JSON_COMPAT_UNDEFINED) {
183
415
  return undefined;
184
416
  }
417
+ if (input[0] === JSON_COMPAT_SET) {
418
+ const items = (input[1] as unknown[]).map((v) =>
419
+ reviveJsonCompatValue(v, options),
420
+ );
421
+ return new Set(items);
422
+ }
185
423
  if (input[0].startsWith("$$")) {
186
424
  return [
187
425
  input[0].substring(1),
@@ -161,28 +161,28 @@ export class InlineWebSocketAdapter {
161
161
  }
162
162
  }
163
163
 
164
- #handleError(err: unknown): void {
165
- console.error("INLINE_WEBSOCKET_ADAPTER_ERROR", err);
164
+ #handleError(error: unknown): void {
165
+ console.error("INLINE_WEBSOCKET_ADAPTER_ERROR", error);
166
166
  logger().error({
167
167
  msg: "error in websocket",
168
- error: err,
169
- errorMessage: err instanceof Error ? err.message : String(err),
170
- stack: err instanceof Error ? err.stack : undefined,
168
+ error,
169
+ errorMessage: error instanceof Error ? error.message : String(error),
170
+ stack: error instanceof Error ? error.stack : undefined,
171
171
  });
172
172
 
173
173
  // Call handler.onError
174
174
  try {
175
- this.#handler.onError(err, this.#wsContext);
176
- } catch (handlerErr) {
175
+ this.#handler.onError(error, this.#wsContext);
176
+ } catch (error) {
177
177
  logger().error({
178
178
  msg: "error in onError handler",
179
- error: handlerErr,
179
+ error,
180
180
  });
181
181
  }
182
182
 
183
183
  // Fire error event to both sides
184
- this.#clientWs.triggerError(err);
185
- this.#actorWs.triggerError(err);
184
+ this.#clientWs.triggerError(error);
185
+ this.#actorWs.triggerError(error);
186
186
  }
187
187
 
188
188
  #close(code: number, reason: string): void {
@@ -199,8 +199,8 @@ export class InlineWebSocketAdapter {
199
199
  { code, reason, wasClean: true },
200
200
  this.#wsContext,
201
201
  );
202
- } catch (err) {
203
- logger().error({ msg: "error closing websocket", error: err });
202
+ } catch (error) {
203
+ logger().error({ msg: "error closing websocket", error });
204
204
  } finally {
205
205
  this.#readyState = 3; // CLOSED
206
206
 
package/src/common/log.ts CHANGED
@@ -76,6 +76,7 @@ export function configureDefaultLogger(logLevel?: LogLevel) {
76
76
  messageKey: "msg",
77
77
  // Do not include pid/hostname in output
78
78
  base: {},
79
+ errorKey: "error",
79
80
  // Keep the numeric level so the logfmt sink can match Pino's levels.
80
81
  formatters: {
81
82
  level(_label: string, number: number) {
@@ -1,6 +1,12 @@
1
1
  import type { Context as HonoContext, Next } from "hono";
2
2
  import * as envoyProtocol from "@rivetkit/engine-envoy-protocol";
3
- import type { Encoding } from "@/common/encoding";
3
+ import type { ActorSpecifier } from "@/actor/errors";
4
+ import {
5
+ HEADER_ACTOR_GENERATION,
6
+ HEADER_ACTOR_ID,
7
+ HEADER_ACTOR_KEY,
8
+ } from "@/common/actor-router-consts";
9
+ import type { JsonCompatValue, Encoding } from "@/common/encoding";
4
10
  import {
5
11
  getRequestEncoding,
6
12
  getRequestExposeInternalError,
@@ -61,16 +67,22 @@ export function handleRouteNotFound(c: HonoContext) {
61
67
  export function handleRouteError(error: unknown, c: HonoContext) {
62
68
  const exposeInternalError = getRequestExposeInternalError(c.req.raw);
63
69
 
64
- const { statusCode, group, code, message, metadata } = deconstructError(
70
+ const { statusCode, group, code, message, metadata, actor } = deconstructError(
65
71
  error,
66
- logger(),
67
- {
68
- method: c.req.method,
69
- path: c.req.path,
70
- },
71
72
  exposeInternalError,
72
73
  );
73
74
 
75
+ if (actor) {
76
+ logger().warn({
77
+ msg: "actor http error response",
78
+ actorId: actor.actorId,
79
+ generation: actor.generation,
80
+ actorKey: actor.key,
81
+ group,
82
+ code,
83
+ });
84
+ }
85
+
74
86
  let encoding: Encoding;
75
87
  try {
76
88
  encoding = getRequestEncoding(c.req);
@@ -78,7 +90,7 @@ export function handleRouteError(error: unknown, c: HonoContext) {
78
90
  encoding = "json";
79
91
  }
80
92
 
81
- const errorData = { group, code, message, metadata };
93
+ const errorData = { group, code, message, metadata, actor };
82
94
  const output = serializeWithEncoding(
83
95
  encoding,
84
96
  errorData,
@@ -91,6 +103,7 @@ export function handleRouteError(error: unknown, c: HonoContext) {
91
103
  code: value.code,
92
104
  message: value.message,
93
105
  metadata: value.metadata,
106
+ actor: value.actor,
94
107
  }),
95
108
  // BARE/CBOR: metadata needs to be CBOR-encoded to ArrayBuffer
96
109
  (value): protocol.HttpResponseError => ({
@@ -98,13 +111,30 @@ export function handleRouteError(error: unknown, c: HonoContext) {
98
111
  code: value.code,
99
112
  message: value.message,
100
113
  metadata: value.metadata
101
- ? bufferToArrayBuffer(encodeCborCompat(value.metadata))
114
+ ? bufferToArrayBuffer(encodeCborCompat(value.metadata as JsonCompatValue))
115
+ : null,
116
+ actor: value.actor
117
+ ? {
118
+ actorId: value.actor.actorId,
119
+ generation: BigInt(value.actor.generation),
120
+ key: value.actor.key ?? null,
121
+ }
102
122
  : null,
103
123
  }),
104
124
  );
105
125
 
126
+ const headers = actor ? actorResponseHeaders(actor) : undefined;
127
+
106
128
  // TODO: Remove any
107
- return c.body(output as any, { status: statusCode });
129
+ return c.body(output as any, { status: statusCode, headers });
130
+ }
131
+
132
+ function actorResponseHeaders(actor: ActorSpecifier): Record<string, string> {
133
+ return {
134
+ [HEADER_ACTOR_ID]: actor.actorId,
135
+ [HEADER_ACTOR_GENERATION]: String(actor.generation),
136
+ ...(actor.key ? { [HEADER_ACTOR_KEY]: actor.key } : {}),
137
+ };
108
138
  }
109
139
 
110
140
  export type MetadataEnvoyKind =