Skip to content

Commit fe4da15

Browse files
jog1tNathanFlurry
authored andcommitted
fix: make inspector working again
1 parent 0d55d94 commit fe4da15

File tree

16 files changed

+283
-1379
lines changed

16 files changed

+283
-1379
lines changed

frontend/src/app/data-providers/cloud-data-provider.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Clerk } from "@clerk/clerk-js";
22
import { type Rivet, RivetClient } from "@rivet-gg/cloud";
3-
import { type FetchFunction, fetcher } from "@rivetkit/engine-api-full/core";
4-
import { infiniteQueryOptions, QueryKey, QueryOptions, queryOptions, UseQueryOptions } from "@tanstack/react-query";
3+
import { fetcher } from "@rivetkit/engine-api-full/core";
4+
import { infiniteQueryOptions, queryOptions } from "@tanstack/react-query";
55
import { cloudEnv } from "@/lib/env";
66
import { queryClient } from "@/queries/global";
77
import { RECORDS_PER_PAGE } from "./default-data-provider";
@@ -339,19 +339,21 @@ export const createNamespaceContext = ({
339339
} & ReturnType<typeof createProjectContext> &
340340
ReturnType<typeof createOrganizationContext> &
341341
ReturnType<typeof createGlobalContext>) => {
342+
const token = async () => {
343+
const response = await queryClient.fetchQuery(
344+
parent.accessTokenQueryOptions({ namespace }),
345+
);
346+
347+
return response.token;
348+
};
342349
return {
343350
...createEngineNamespaceContext({
344351
...parent,
345352
namespace: engineNamespaceName,
346353
namespaceId: engineNamespaceId,
354+
engineToken: token,
347355
client: createEngineClient(cloudEnv().VITE_APP_API_URL, {
348-
token: async () => {
349-
const response = await queryClient.fetchQuery(
350-
parent.accessTokenQueryOptions({ namespace }),
351-
);
352-
353-
return response.token;
354-
},
356+
token,
355357
}),
356358
}),
357359
namespaceQueryOptions() {

frontend/src/app/data-providers/default-data-provider.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ const defaultContext = {
311311
destroyedAt: data.destroyedAt
312312
? new Date(data.destroyedAt)
313313
: null,
314+
runner: data.runner ?? undefined,
314315
sleepingAt: data.sleepingAt ? new Date(data.sleepingAt) : null,
315316
startedAt: data.startedAt ? new Date(data.startedAt) : null,
316317
}),

frontend/src/app/data-providers/engine-data-provider.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ export function createClient(
4949
environment: "",
5050
...opts,
5151
fetcher: async (args) => {
52-
Object.keys(args.headers).forEach((key) => {
52+
Object.keys(args.headers || {}).forEach((key) => {
5353
if (key.toLowerCase().startsWith("x-fern-")) {
54-
delete args.headers[key];
54+
delete args.headers?.[key];
5555
}
5656
});
5757
return await fetcher(args);
@@ -60,13 +60,14 @@ export function createClient(
6060
}
6161

6262
export const createGlobalContext = (opts: {
63-
engineToken: (() => string) | string;
63+
engineToken: (() => string) | string | (() => Promise<string>);
6464
}) => {
6565
const client = createClient(engineEnv().VITE_APP_API_URL, {
6666
token: opts.engineToken,
6767
});
6868
return {
6969
client,
70+
...opts,
7071
namespacesQueryOptions() {
7172
return infiniteQueryOptions({
7273
queryKey: ["namespaces"] as any,
@@ -138,6 +139,7 @@ export const createNamespaceContext = ({
138139
const def = createDefaultGlobalContext();
139140
const dataProvider = {
140141
...def,
142+
endpoint: engineEnv().VITE_APP_API_URL,
141143
features: {
142144
canCreateActors: true,
143145
canDeleteActors: true,
@@ -190,7 +192,7 @@ export const createNamespaceContext = ({
190192
return queryOptions({
191193
...def.regionQueryOptions(regionId),
192194
queryKey: [
193-
{ namespace, namespaceId },
195+
{ namespace },
194196
...def.regionQueryOptions(regionId).queryKey,
195197
],
196198
queryFn: async ({ client }) => {
@@ -426,6 +428,7 @@ export const createNamespaceContext = ({
426428

427429
return {
428430
engineNamespace: namespace,
431+
engineToken: parent.engineToken,
429432
...dataProvider,
430433
runnersQueryOptions() {
431434
return infiniteQueryOptions({

frontend/src/app/dialogs/connect-railway-frame.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ export function EnvVariablesStep() {
177177
<p>Value</p>
178178
</Label>
179179
<RivetEndpointEnv />
180-
<RivetNamespaceEnv />
181180
<RivetTokenEnv />
181+
<RivetNamespaceEnv />
182182
<RivetRunnerEnv />
183183
</div>
184184
<div className="mt-2 flex justify-end">

frontend/src/components/actors/actor-editable-state.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@ import {
1414
JsonCode,
1515
} from "@/components/code-mirror";
1616
import { ActorStateChangeIndicator } from "./actor-state-change-indicator";
17-
import {
18-
type ActorId,
19-
useActorStatePatchMutation,
20-
useActorStateStream,
21-
} from "./queries";
17+
import { type ActorId, useActorStatePatchMutation } from "./queries";
2218

2319
const isValidJson = (json: string | null): json is string => {
2420
if (!json) return false;
@@ -50,7 +46,7 @@ export function ActorEditableState({
5046

5147
const isValid = isValidJson(value) ? JSON.parse(value) : false;
5248

53-
const { mutate, isPending } = useActorStatePatchMutation(actorId);
49+
const { mutateAsync, isPending } = useActorStatePatchMutation(actorId);
5450

5551
// useActorStateStream(actorId);
5652

@@ -88,8 +84,8 @@ export function ActorEditableState({
8884
variant="outline"
8985
isLoading={isPending}
9086
disabled={!isValid || !isEditing}
91-
onClick={() => {
92-
mutate(JSON.parse(value || ""));
87+
onClick={async () => {
88+
await mutateAsync(JSON.parse(value || ""));
9389
setIsEditing(false);
9490
setValue(null);
9591
}}

frontend/src/components/actors/queries/actor.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { fetchEventSource } from "@microsoft/fetch-event-source";
22
import { useMutation, useQueryClient } from "@tanstack/react-query";
3-
import { applyPatch, compare } from "fast-json-patch";
3+
import { compare } from "fast-json-patch";
44
import { useCallback, useEffect, useMemo } from "react";
5-
import type { ActorId, Patch, RecordedRealtimeEvent } from "rivetkit/inspector";
5+
import type { ActorId, RecordedRealtimeEvent } from "rivetkit/inspector";
66
import { useActor } from "../actor-queries-context";
77
import { useAsyncMemo } from "@/components/hooks/use-async-memo";
88

@@ -59,12 +59,15 @@ export const useActorStatePatchMutation = (
5959
if (!response.ok) {
6060
throw response;
6161
}
62-
return await response.json();
62+
return (await response.json()) as {
63+
state: unknown;
64+
enabled: boolean;
65+
};
6366
},
6467
onSuccess: (data) => {
6568
queryClient.setQueryData(
6669
queries.actorStateQueryOptions(actorId).queryKey,
67-
() => ({ enabled: true, state: data }),
70+
() => ({ enabled: true, state: data.state }),
6871
);
6972
},
7073
...options,

frontend/src/components/actors/worker/actor-repl.worker.ts

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { fromJs } from "esast-util-from-js";
22
import { toJs } from "estree-util-to-js";
3-
import { createClient } from "rivetkit/client";
3+
import { createActorInspectorClient } from "rivetkit/inspector";
44
import {
55
createHighlighterCore,
66
createOnigurumaEngine,
77
type HighlighterCore,
88
} from "shiki";
9+
import { match } from "ts-pattern";
910
import {
1011
type InitMessage,
1112
MessageSchema,
@@ -113,12 +114,7 @@ addEventListener("message", async (event) => {
113114
}
114115

115116
if (data.type === "init") {
116-
init = {
117-
rpcs: data.rpcs ?? [],
118-
endpoint: data.endpoint,
119-
name: data.name,
120-
id: data.id,
121-
};
117+
init = structuredClone(data);
122118
respond({
123119
type: "ready",
124120
});
@@ -181,9 +177,43 @@ function respond(msg: Response) {
181177
async function callAction({ name, args }: { name: string; args: unknown[] }) {
182178
if (!init) throw new Error("Actor not initialized");
183179

184-
const client = createClient({
185-
endpoint: init.endpoint,
186-
token: init.engineToken,
187-
}).getForId(init.name, init.id);
188-
return await client.action({ name, args });
180+
const url = new URL(`inspect`, init.endpoint).href;
181+
182+
// we need to build this from scratch because we don't have access to
183+
// createInspectorActorContext in the worker
184+
// and we want to avoid bundling the entire RivetKit here, issues with @react-refresh
185+
const client = createActorInspectorClient(url, {
186+
headers: {
187+
Authorization: init.inspectorToken
188+
? `Bearer ${init.inspectorToken}`
189+
: "",
190+
"x-rivet-target": "actor",
191+
"x-rivet-actor": init.id,
192+
"X-RivetKit-Query": JSON.stringify({
193+
getForId: { actorId: init.id },
194+
}),
195+
196+
...match(__APP_TYPE__)
197+
.with("engine", () => {
198+
return init?.engineToken
199+
? { "X-Rivet-Token": init.engineToken }
200+
: {};
201+
})
202+
.otherwise(() => ({})),
203+
},
204+
});
205+
206+
const response = await client.action.$post({
207+
json: { name, params: args },
208+
});
209+
210+
if (!response.ok) {
211+
try {
212+
return await response.json();
213+
} catch {
214+
return await response.text();
215+
}
216+
}
217+
218+
return (await response.json()).result;
189219
}

frontend/src/components/actors/worker/actor-worker-container.ts

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -33,42 +33,38 @@ export type ContainerState = {
3333
commands: ReplCommand[];
3434
};
3535

36+
interface Meta {
37+
actorId: string;
38+
rpcs: string[];
39+
endpoint?: string;
40+
name?: string;
41+
engineToken?: string | (() => Promise<string>) | (() => string);
42+
runnerName?: string;
43+
namespace?: string;
44+
inspectorToken?: string;
45+
}
46+
3647
export class ActorWorkerContainer {
3748
#state: ContainerState = {
3849
status: { type: "unknown" },
3950
commands: [],
4051
};
4152

42-
#meta: {
43-
actorId: string;
44-
rpcs: string[];
45-
endpoint?: string;
46-
name?: string;
47-
engineToken?: string;
48-
} | null = null;
53+
#meta: Meta | null = null;
4954

5055
#listeners: (() => void)[] = [];
5156
#worker: Worker | undefined;
5257

5358
//
5459
async init({
55-
actorId,
5660
signal,
57-
rpcs = [],
58-
endpoint,
59-
name,
60-
engineToken,
61+
...meta
6162
}: {
62-
actorId: string;
6363
signal: AbortSignal;
64-
rpcs?: string[];
65-
endpoint?: string;
66-
name?: string;
67-
engineToken?: string;
68-
}) {
64+
} & Meta) {
6965
this.terminate();
7066

71-
this.#meta = { actorId, rpcs, endpoint, name, engineToken };
67+
this.#meta = { ...meta };
7268
this.#state.status = { type: "pending" };
7369
this.#update();
7470
try {
@@ -81,12 +77,12 @@ export class ActorWorkerContainer {
8177

8278
// If we reached this point, the actor is supported
8379
// check if we still operate on the same actor
84-
if (this.#meta.actorId !== actorId) {
80+
if (this.#meta.actorId !== meta.actorId) {
8581
// if not, we don't need to do anything
8682
return null;
8783
}
8884

89-
const worker = new ActorWorker({ name: `actor-${actorId}` });
85+
const worker = new ActorWorker({ name: `actor-${meta.actorId}` });
9086
signal.throwIfAborted();
9187
// now worker needs to check if the actor is supported
9288
this.#setupWorker(worker);
@@ -123,7 +119,7 @@ export class ActorWorkerContainer {
123119
this.#update();
124120
}
125121

126-
#setupWorker(worker: Worker) {
122+
async #setupWorker(worker: Worker) {
127123
this.#worker = worker;
128124
this.#worker.addEventListener("message", (event) => {
129125
try {
@@ -145,7 +141,13 @@ export class ActorWorkerContainer {
145141
id: this.#meta?.actorId ?? "",
146142
endpoint: this.#meta?.endpoint ?? "",
147143
name: this.#meta?.name ?? "",
148-
engineToken: this.#meta?.engineToken ?? "",
144+
engineToken:
145+
typeof this.#meta?.engineToken === "function"
146+
? await this.#meta?.engineToken()
147+
: this.#meta?.engineToken,
148+
namespace: this.#meta?.namespace,
149+
runnerName: this.#meta?.runnerName,
150+
inspectorToken: this.#meta?.inspectorToken,
149151
} satisfies InitMessage);
150152
}
151153

@@ -238,9 +240,9 @@ export class ActorWorkerContainer {
238240
}
239241

240242
if (msg.type === "error") {
243+
console.error("Actor Worker Error", msg);
241244
if (!msg.id) {
242245
this.#state.status = { type: "error", error: msg.data };
243-
console.error("Actor Worker Error", msg.data);
244246
this.#update();
245247
return;
246248
}

0 commit comments

Comments
 (0)