rivetkit 2.3.0-rc.12 → 2.3.0-rc.13

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 +50 -0
  2. package/dist/browser/client.js +98 -84
  3. package/dist/browser/client.js.map +1 -1
  4. package/dist/browser/inspector/client.js +12 -2
  5. package/dist/browser/inspector/client.js.map +1 -1
  6. package/dist/tsup/actor/errors.d.cts +1 -1
  7. package/dist/tsup/actor/errors.d.ts +1 -1
  8. package/dist/tsup/agent-os/index.cjs +66 -3
  9. package/dist/tsup/agent-os/index.cjs.map +1 -1
  10. package/dist/tsup/agent-os/index.d.cts +50 -0
  11. package/dist/tsup/agent-os/index.d.ts +50 -0
  12. package/dist/tsup/agent-os/index.js +66 -3
  13. package/dist/tsup/agent-os/index.js.map +1 -1
  14. package/dist/tsup/{chunk-EWVOWEMD.js → chunk-33YE6XCI.js} +4 -4
  15. package/dist/tsup/{chunk-2ZTBRZRS.cjs → chunk-7OR3CHD5.cjs} +10 -10
  16. package/dist/tsup/{chunk-2ZTBRZRS.cjs.map → chunk-7OR3CHD5.cjs.map} +1 -1
  17. package/dist/tsup/{chunk-UETC5RF7.cjs → chunk-7XQCARVY.cjs} +3 -3
  18. package/dist/tsup/{chunk-UETC5RF7.cjs.map → chunk-7XQCARVY.cjs.map} +1 -1
  19. package/dist/tsup/{chunk-SS56HFM2.cjs → chunk-BSPS6NSN.cjs} +5 -5
  20. package/dist/tsup/{chunk-SS56HFM2.cjs.map → chunk-BSPS6NSN.cjs.map} +1 -1
  21. package/dist/tsup/{chunk-WIMUFZVJ.js → chunk-DPIMKYNB.js} +61 -2
  22. package/dist/tsup/chunk-DPIMKYNB.js.map +1 -0
  23. package/dist/tsup/{chunk-2U6RLFKX.cjs → chunk-E5CLYAUZ.cjs} +144 -142
  24. package/dist/tsup/chunk-E5CLYAUZ.cjs.map +1 -0
  25. package/dist/tsup/{chunk-VNMIAPPF.cjs → chunk-EBWOJRCC.cjs} +21 -4
  26. package/dist/tsup/chunk-EBWOJRCC.cjs.map +1 -0
  27. package/dist/tsup/{chunk-OLIJHKLL.js → chunk-HHNYEQD3.js} +6 -6
  28. package/dist/tsup/chunk-HHNYEQD3.js.map +1 -0
  29. package/dist/tsup/{chunk-3EVVOYFD.js → chunk-IOUSQVXI.js} +20 -3
  30. package/dist/tsup/chunk-IOUSQVXI.js.map +1 -0
  31. package/dist/tsup/{chunk-C7AAIILH.cjs → chunk-ISDKSSYR.cjs} +4 -4
  32. package/dist/tsup/{chunk-C7AAIILH.cjs.map → chunk-ISDKSSYR.cjs.map} +1 -1
  33. package/dist/tsup/{chunk-7UZF56RS.js → chunk-J72WHUBC.js} +10 -8
  34. package/dist/tsup/{chunk-7UZF56RS.js.map → chunk-J72WHUBC.js.map} +1 -1
  35. package/dist/tsup/{chunk-6KTMKPNU.cjs → chunk-KWABEUUA.cjs} +10 -10
  36. package/dist/tsup/chunk-KWABEUUA.cjs.map +1 -0
  37. package/dist/tsup/{chunk-WHYBAEWG.cjs → chunk-NIY3RSPX.cjs} +62 -3
  38. package/dist/tsup/chunk-NIY3RSPX.cjs.map +1 -0
  39. package/dist/tsup/{chunk-VLXRFJ7P.js → chunk-T44AVAGW.js} +2 -2
  40. package/dist/tsup/{chunk-QKSGGKGQ.js → chunk-TCXEM6PA.js} +2 -2
  41. package/dist/tsup/{chunk-OOB32JVG.js → chunk-ZI5CNA2Z.js} +2 -2
  42. package/dist/tsup/client/mod.cjs +7 -7
  43. package/dist/tsup/client/mod.cjs.map +1 -1
  44. package/dist/tsup/client/mod.d.cts +3 -3
  45. package/dist/tsup/client/mod.d.ts +3 -3
  46. package/dist/tsup/client/mod.js +6 -6
  47. package/dist/tsup/common/log.cjs +2 -2
  48. package/dist/tsup/common/log.js +1 -1
  49. package/dist/tsup/common/websocket.cjs +3 -3
  50. package/dist/tsup/common/websocket.js +2 -2
  51. package/dist/tsup/{config-DKgPGC0f.d.ts → config-BxWAw3iH.d.ts} +121 -2
  52. package/dist/tsup/{config-BtAh7oBu.d.cts → config-CZQQ-mso.d.cts} +121 -2
  53. package/dist/tsup/{context-Cfjl5pgz.d.cts → context-Bw7xq8w3.d.cts} +1 -1
  54. package/dist/tsup/{context-C-6dGebY.d.ts → context-D8QA76sV.d.ts} +1 -1
  55. package/dist/tsup/dynamic/mod.cjs +2 -2
  56. package/dist/tsup/dynamic/mod.d.cts +2 -2
  57. package/dist/tsup/dynamic/mod.d.ts +2 -2
  58. package/dist/tsup/dynamic/mod.js +1 -1
  59. package/dist/tsup/inspector/mod.cjs +5 -5
  60. package/dist/tsup/inspector/mod.js +4 -4
  61. package/dist/tsup/inspector-tab/mod.cjs +173 -0
  62. package/dist/tsup/inspector-tab/mod.cjs.map +1 -0
  63. package/dist/tsup/inspector-tab/mod.d.cts +250 -0
  64. package/dist/tsup/inspector-tab/mod.d.ts +250 -0
  65. package/dist/tsup/inspector-tab/mod.js +173 -0
  66. package/dist/tsup/inspector-tab/mod.js.map +1 -0
  67. package/dist/tsup/mod.cjs +189 -81
  68. package/dist/tsup/mod.cjs.map +1 -1
  69. package/dist/tsup/mod.d.cts +4 -4
  70. package/dist/tsup/mod.d.ts +4 -4
  71. package/dist/tsup/mod.js +124 -16
  72. package/dist/tsup/mod.js.map +1 -1
  73. package/dist/tsup/test/mod.cjs +10 -10
  74. package/dist/tsup/test/mod.d.cts +2 -2
  75. package/dist/tsup/test/mod.d.ts +2 -2
  76. package/dist/tsup/test/mod.js +6 -6
  77. package/dist/tsup/{utils-DVekpm4I.d.cts → utils-DQosb24I.d.cts} +1 -1
  78. package/dist/tsup/{utils-DVekpm4I.d.ts → utils-DQosb24I.d.ts} +1 -1
  79. package/dist/tsup/utils.cjs +2 -2
  80. package/dist/tsup/utils.d.cts +1 -1
  81. package/dist/tsup/utils.d.ts +1 -1
  82. package/dist/tsup/utils.js +1 -1
  83. package/dist/tsup/workflow/mod.cjs +11 -11
  84. package/dist/tsup/workflow/mod.cjs.map +1 -1
  85. package/dist/tsup/workflow/mod.d.cts +4 -4
  86. package/dist/tsup/workflow/mod.d.ts +4 -4
  87. package/dist/tsup/workflow/mod.js +5 -5
  88. package/package.json +19 -9
  89. package/src/actor/config.ts +91 -0
  90. package/src/actor/instance/mod.ts +4 -4
  91. package/src/actor/mod.ts +2 -0
  92. package/src/common/engine.ts +28 -1
  93. package/src/devtools-loader/index.ts +4 -7
  94. package/src/devtools-loader/serve-devtools.ts +26 -0
  95. package/src/engine-client/actor-http-client.ts +2 -2
  96. package/src/engine-client/ws-proxy.ts +5 -0
  97. package/src/inspector-tab/mod.ts +315 -0
  98. package/src/registry/config/index.ts +37 -7
  99. package/src/registry/index.ts +4 -2
  100. package/src/registry/native.ts +118 -7
  101. package/src/registry/runtime.ts +20 -0
  102. package/src/utils/env-vars.ts +6 -0
  103. package/dist/tsup/chunk-2U6RLFKX.cjs.map +0 -1
  104. package/dist/tsup/chunk-3EVVOYFD.js.map +0 -1
  105. package/dist/tsup/chunk-6KTMKPNU.cjs.map +0 -1
  106. package/dist/tsup/chunk-OLIJHKLL.js.map +0 -1
  107. package/dist/tsup/chunk-VNMIAPPF.cjs.map +0 -1
  108. package/dist/tsup/chunk-WHYBAEWG.cjs.map +0 -1
  109. package/dist/tsup/chunk-WIMUFZVJ.js.map +0 -1
  110. /package/dist/tsup/{chunk-EWVOWEMD.js.map → chunk-33YE6XCI.js.map} +0 -0
  111. /package/dist/tsup/{chunk-VLXRFJ7P.js.map → chunk-T44AVAGW.js.map} +0 -0
  112. /package/dist/tsup/{chunk-QKSGGKGQ.js.map → chunk-TCXEM6PA.js.map} +0 -0
  113. /package/dist/tsup/{chunk-OOB32JVG.js.map → chunk-ZI5CNA2Z.js.map} +0 -0
@@ -10,7 +10,7 @@ import {
10
10
  queueMetadataKey,
11
11
  workflowStoragePrefix,
12
12
  } from "@/actor/keys";
13
- import { ENGINE_ENDPOINT } from "@/common/engine";
13
+ import { buildEngineEndpoint, ENGINE_HOST, ENGINE_PORT } from "@/common/engine";
14
14
  import { type Logger, LogLevelSchema } from "@/common/log";
15
15
  import { VERSION } from "@/utils";
16
16
  import { tryParseEndpoint } from "@/utils/endpoint-parser";
@@ -20,6 +20,8 @@ import {
20
20
  getRivetkitRuntime,
21
21
  getRivetNamespace,
22
22
  getRivetRunEngine,
23
+ getRivetRunEngineHost,
24
+ getRivetRunEnginePort,
23
25
  getRivetRunEngineVersion,
24
26
  getRivetToken,
25
27
  isDev,
@@ -224,6 +226,27 @@ export const RegistryConfigSchema = z
224
226
  * Starts the full Rust engine process locally.
225
227
  */
226
228
  startEngine: z.boolean().default(() => getRivetRunEngine()),
229
+ /**
230
+ * @experimental
231
+ *
232
+ * Host to bind the spawned local engine process to.
233
+ */
234
+ engineHost: z
235
+ .string()
236
+ .optional()
237
+ .default(() => getRivetRunEngineHost() ?? ENGINE_HOST),
238
+ /**
239
+ * @experimental
240
+ *
241
+ * Port to bind the spawned local engine process to.
242
+ */
243
+ enginePort: z
244
+ .number()
245
+ .int()
246
+ .min(1)
247
+ .max(65_535)
248
+ .optional()
249
+ .default(() => getRivetRunEnginePort() ?? ENGINE_PORT),
227
250
  /** @experimental */
228
251
  engineVersion: z
229
252
  .string()
@@ -312,7 +335,9 @@ export const RegistryConfigSchema = z
312
335
  })
313
336
  : undefined;
314
337
 
315
- // Can't start a local engine and connect to a remote endpoint.
338
+ // RIVET_ENDPOINT configures what RivetKit connects to. Use
339
+ // engineHost/enginePort (or RIVET_RUN_ENGINE_HOST/PORT) to control the
340
+ // spawned local engine bind address.
316
341
  if (config.startEngine && parsedEndpoint) {
317
342
  ctx.addIssue({
318
343
  code: "custom",
@@ -329,12 +354,17 @@ export const RegistryConfigSchema = z
329
354
  });
330
355
  }
331
356
 
332
- // Flatten the endpoint and apply defaults for namespace/token
333
- // If startEngine is enabled, set endpoint to the engine endpoint.
357
+ // Flatten the endpoint and apply defaults for namespace/token.
358
+ const localEngineEndpoint = buildEngineEndpoint(
359
+ config.engineHost,
360
+ config.enginePort,
361
+ );
334
362
  const endpoint = config.startEngine
335
- ? ENGINE_ENDPOINT
363
+ ? localEngineEndpoint
336
364
  : (parsedEndpoint?.endpoint ??
337
- (isDevEnv ? ENGINE_ENDPOINT : undefined));
365
+ (isDevEnv
366
+ ? buildEngineEndpoint(ENGINE_HOST, ENGINE_PORT)
367
+ : undefined));
338
368
  const validateServerlessEndpoint = Boolean(
339
369
  config.startEngine || parsedEndpoint,
340
370
  );
@@ -367,7 +397,7 @@ export const RegistryConfigSchema = z
367
397
  // In dev mode, clients connect directly to the local Rivet Engine.
368
398
  const publicEndpoint =
369
399
  parsedPublicEndpoint?.endpoint ??
370
- (isDevEnv && config.startEngine ? ENGINE_ENDPOINT : undefined);
400
+ (isDevEnv && config.startEngine ? endpoint : undefined);
371
401
  // We extract publicNamespace to validate that it matches the backend
372
402
  // namespace (see validation above), not for functional use.
373
403
  const publicNamespace = parsedPublicEndpoint?.namespace;
@@ -1,5 +1,5 @@
1
1
  import { Hono } from "hono";
2
- import { ENGINE_ENDPOINT } from "@/common/engine";
2
+ import { isLocalEngineEndpoint } from "@/common/engine";
3
3
  import { configureServerlessPool } from "@/serverless/configure";
4
4
  import { detectRuntime, VERSION } from "@/utils";
5
5
  import { crossPlatformServe, loadRuntimeServeStatic } from "@/utils/serve";
@@ -700,7 +700,9 @@ export class Registry<A extends RegistryActors> {
700
700
 
701
701
  if (config.endpoint) {
702
702
  const endpointType =
703
- config.endpoint === ENGINE_ENDPOINT ? "local native" : "remote";
703
+ config.startEngine || isLocalEngineEndpoint(config.endpoint)
704
+ ? "local native"
705
+ : "remote";
704
706
  logLine("Endpoint", `${config.endpoint} (${endpointType})`);
705
707
  }
706
708
 
@@ -71,12 +71,15 @@ import type {
71
71
  RuntimeActorConfig,
72
72
  RuntimeBytes,
73
73
  RuntimeHttpResponse,
74
+ RuntimeInspectorTabEntry,
74
75
  RuntimeQueueMessage,
75
76
  RuntimeServeConfig,
76
77
  RuntimeStateDeltaPayload,
77
78
  WebSocketHandle,
78
79
  } from "./runtime";
79
80
  import { loadWasmRuntime } from "./wasm-runtime";
81
+ import nodeFs from "node:fs";
82
+ import nodePath from "node:path";
80
83
  import { createWriteThroughProxy } from "./write-through-proxy";
81
84
 
82
85
  const textEncoder = new TextEncoder();
@@ -627,6 +630,14 @@ function encodeValue(value: unknown): RuntimeBytes {
627
630
  return encodeCborCompat(value as JsonCompatValue);
628
631
  }
629
632
 
633
+ function normalizeArgs(value: unknown): unknown[] {
634
+ return Array.isArray(value)
635
+ ? value
636
+ : value === undefined || value === null
637
+ ? []
638
+ : [value];
639
+ }
640
+
630
641
  function unwrapTsfnPayload<T>(error: unknown, payload: T): T {
631
642
  if (error !== null && error !== undefined) {
632
643
  throw error;
@@ -1093,11 +1104,7 @@ function wrapNativeCallback<Args extends Array<unknown>, Result>(
1093
1104
 
1094
1105
  function decodeArgs(value?: RuntimeBytes | null): unknown[] {
1095
1106
  const decoded = decodeValue<unknown>(value);
1096
- return Array.isArray(decoded)
1097
- ? decoded
1098
- : decoded === undefined
1099
- ? []
1100
- : [decoded];
1107
+ return normalizeArgs(decoded);
1101
1108
  }
1102
1109
 
1103
1110
  function buildRequest(init: {
@@ -3323,9 +3330,87 @@ function buildActorConfig(
3323
3330
  actions: Object.keys((config.actions ?? {}) as Record<string, unknown>)
3324
3331
  .sort()
3325
3332
  .map((name) => ({ name })),
3333
+ inspectorTabs: buildInspectorTabs(config.inspector),
3326
3334
  };
3327
3335
  }
3328
3336
 
3337
+ function buildInspectorTabs(
3338
+ inspector: unknown,
3339
+ ): Array<RuntimeInspectorTabEntry> | undefined {
3340
+ if (!inspector || typeof inspector !== "object") return undefined;
3341
+ const tabs = (inspector as { tabs?: unknown }).tabs;
3342
+ if (!Array.isArray(tabs) || tabs.length === 0) return undefined;
3343
+ return tabs.map((raw) => {
3344
+ const entry = raw as {
3345
+ id: string;
3346
+ label?: string;
3347
+ source?: string;
3348
+ icon?: string;
3349
+ hidden?: boolean;
3350
+ };
3351
+ if (entry.hidden === true) {
3352
+ return { id: entry.id, hidden: true };
3353
+ }
3354
+ // Resolve the author's source path against the current working
3355
+ // directory so the Rust runtime gets an absolute path. The author
3356
+ // runs the actor process from their project root by convention.
3357
+ const resolved =
3358
+ entry.source !== undefined
3359
+ ? nodePath.resolve(entry.source)
3360
+ : undefined;
3361
+ if (resolved !== undefined) {
3362
+ validateInspectorTabSource(entry.id, resolved);
3363
+ }
3364
+ return {
3365
+ id: entry.id,
3366
+ label: entry.label,
3367
+ icon: entry.icon,
3368
+ source: resolved,
3369
+ };
3370
+ });
3371
+ }
3372
+
3373
+ function validateInspectorTabSource(tabId: string, resolved: string): void {
3374
+ // Catch obviously dangerous misconfigurations at registry construction
3375
+ // rather than silently exposing the wrong subtree over the unauthenticated
3376
+ // `/inspector/custom-tabs/<id>/*` route. Fail loudly so misconfigured
3377
+ // actors never start.
3378
+ if (resolved === nodePath.parse(resolved).root) {
3379
+ throw new Error(
3380
+ `inspector.tabs[id="${tabId}"].source resolves to the filesystem root (${resolved}). ` +
3381
+ "Point it at the tab's own static-asset directory instead.",
3382
+ );
3383
+ }
3384
+ let stat: import("node:fs").Stats;
3385
+ try {
3386
+ stat = nodeFs.statSync(resolved);
3387
+ } catch (err) {
3388
+ const code = (err as NodeJS.ErrnoException)?.code;
3389
+ if (code === "ENOENT") {
3390
+ throw new Error(
3391
+ `inspector.tabs[id="${tabId}"].source (${resolved}) does not exist.`,
3392
+ );
3393
+ }
3394
+ if (code === "EACCES") {
3395
+ throw new Error(
3396
+ `inspector.tabs[id="${tabId}"].source (${resolved}) is not readable (EACCES).`,
3397
+ );
3398
+ }
3399
+ throw new Error(
3400
+ `inspector.tabs[id="${tabId}"].source (${resolved}) could not be stat'd: ${
3401
+ (err as Error)?.message ?? err
3402
+ }`,
3403
+ );
3404
+ }
3405
+ if (!stat.isDirectory()) {
3406
+ throw new Error(
3407
+ `inspector.tabs[id="${tabId}"].source (${resolved}) must be a directory, got ${
3408
+ stat.isFile() ? "file" : "non-directory"
3409
+ }.`,
3410
+ );
3411
+ }
3412
+ }
3413
+
3329
3414
  export function buildNativeFactory(
3330
3415
  runtime: CoreRuntime,
3331
3416
  registryConfig: RegistryConfig,
@@ -3756,14 +3841,38 @@ export function buildNativeFactory(
3756
3841
  404,
3757
3842
  );
3758
3843
  }
3759
- const body = (await jsRequest.json()) as { args?: unknown[] };
3844
+ const body = (await jsRequest.json()) as {
3845
+ args?: unknown;
3846
+ properties?: unknown;
3847
+ };
3848
+ if (body.args !== undefined && body.properties !== undefined) {
3849
+ return jsonResponse(
3850
+ { error: "use either args or properties, not both" },
3851
+ { status: 400 },
3852
+ );
3853
+ }
3854
+ if (
3855
+ body.properties !== undefined &&
3856
+ (body.properties === null ||
3857
+ typeof body.properties !== "object" ||
3858
+ Array.isArray(body.properties))
3859
+ ) {
3860
+ return jsonResponse(
3861
+ { error: "properties must be an object" },
3862
+ { status: 400 },
3863
+ );
3864
+ }
3865
+ const args =
3866
+ body.properties !== undefined
3867
+ ? [body.properties]
3868
+ : normalizeArgs(body.args);
3760
3869
  try {
3761
3870
  const output = await action(
3762
3871
  actorCtx,
3763
3872
  ...validateActionArgs(
3764
3873
  schemaConfig.actionInputSchemas,
3765
3874
  actionName,
3766
- body.args ?? [],
3875
+ args,
3767
3876
  ),
3768
3877
  );
3769
3878
  return jsonResponse({ output });
@@ -4650,6 +4759,8 @@ export async function buildServeConfig(
4650
4759
  if (config.startEngine) {
4651
4760
  const { getEnginePath } = await loadEngineCli();
4652
4761
  serveConfig.engineBinaryPath = getEnginePath();
4762
+ serveConfig.engineHost = config.engineHost;
4763
+ serveConfig.enginePort = config.enginePort;
4653
4764
  }
4654
4765
  if (config.test?.enabled) {
4655
4766
  serveConfig.inspectorTestToken =
@@ -225,6 +225,22 @@ export interface RuntimeActorConfig {
225
225
  preloadMaxWorkflowBytes?: number;
226
226
  preloadMaxConnectionsBytes?: number;
227
227
  actions?: Array<{ name: string }>;
228
+ inspectorTabs?: Array<RuntimeInspectorTabEntry>;
229
+ }
230
+
231
+ export interface RuntimeInspectorTabEntry {
232
+ id: string;
233
+ /** Required for custom entries; omitted for built-in hides. */
234
+ label?: string;
235
+ /**
236
+ * Required for custom entries — absolute path to the source directory.
237
+ * Resolved on the TS side before being handed to the runtime.
238
+ */
239
+ source?: string;
240
+ /** Optional icon id for custom entries. */
241
+ icon?: string;
242
+ /** Set to true for built-in hide entries. */
243
+ hidden?: boolean;
228
244
  }
229
245
 
230
246
  export interface RuntimeServeConfig {
@@ -234,6 +250,8 @@ export interface RuntimeServeConfig {
234
250
  namespace: string;
235
251
  poolName: string;
236
252
  engineBinaryPath?: string;
253
+ engineHost?: string;
254
+ enginePort?: number;
237
255
  handleInspectorHttpInRuntime?: boolean;
238
256
  inspectorTestToken?: string;
239
257
  serverlessBasePath?: string;
@@ -583,6 +601,8 @@ export async function buildServeConfig(
583
601
 
584
602
  if (config.startEngine) {
585
603
  serveConfig.engineBinaryPath = await loadEnginePath();
604
+ serveConfig.engineHost = config.engineHost;
605
+ serveConfig.enginePort = config.enginePort;
586
606
  }
587
607
  if (config.test?.enabled) {
588
608
  serveConfig.inspectorTestToken =
@@ -22,6 +22,12 @@ export const getRivetTotalSlots = (): number | undefined => {
22
22
  };
23
23
  export const getRivetRunEngine = (): boolean =>
24
24
  getEnvUniversal("RIVET_RUN_ENGINE") === "1";
25
+ export const getRivetRunEngineHost = (): string | undefined =>
26
+ getEnvUniversal("RIVET_RUN_ENGINE_HOST");
27
+ export const getRivetRunEnginePort = (): number | undefined => {
28
+ const value = getEnvUniversal("RIVET_RUN_ENGINE_PORT");
29
+ return value !== undefined ? parseInt(value, 10) : undefined;
30
+ };
25
31
  export const getRivetRunEngineVersion = (): string | undefined =>
26
32
  getEnvUniversal("RIVET_RUN_ENGINE_VERSION");
27
33
  export const getRivetEnvoyKind = (): string | undefined =>