Skip to content

Commit 2013347

Browse files
committed
fix: make inspector working again
1 parent 725df55 commit 2013347

File tree

17 files changed

+298
-1402
lines changed

17 files changed

+298
-1402
lines changed

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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";
3+
import { fetcher } from "@rivetkit/engine-api-full/core";
44
import { infiniteQueryOptions, queryOptions } from "@tanstack/react-query";
55
import { cloudEnv } from "@/lib/env";
66
import { queryClient } from "@/queries/global";
@@ -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
@@ -308,6 +308,7 @@ const defaultContext = {
308308
destroyedAt: data.destroyedAt
309309
? new Date(data.destroyedAt)
310310
: null,
311+
runner: data.runner ?? undefined,
311312
sleepingAt: data.sleepingAt ? new Date(data.sleepingAt) : null,
312313
startedAt: data.startedAt ? new Date(data.startedAt) : null,
313314
}),

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,14 @@ export function createClient(
5656
}
5757

5858
export const createGlobalContext = (opts: {
59-
engineToken: (() => string) | string;
59+
engineToken: (() => string) | string | (() => Promise<string>);
6060
}) => {
6161
const client = createClient(engineEnv().VITE_APP_API_URL, {
6262
token: opts.engineToken,
6363
});
6464
return {
6565
client,
66+
...opts,
6667
namespacesQueryOptions() {
6768
return infiniteQueryOptions({
6869
queryKey: ["namespaces"] as any,
@@ -129,12 +130,14 @@ export const createNamespaceContext = ({
129130
namespace,
130131
namespaceId,
131132
client,
133+
...parent
132134
}: { namespace: string; namespaceId: string } & ReturnType<
133135
typeof createGlobalContext
134136
>) => {
135137
const def = createDefaultGlobalContext();
136138
const dataProvider = {
137139
...def,
140+
endpoint: engineEnv().VITE_APP_API_URL,
138141
features: {
139142
canCreateActors: true,
140143
canDeleteActors: true,
@@ -423,6 +426,7 @@ export const createNamespaceContext = ({
423426

424427
return {
425428
engineNamespace: namespace,
429+
engineToken: parent.engineToken,
426430
...dataProvider,
427431
runnersQueryOptions() {
428432
return infiniteQueryOptions({

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: 8 additions & 5 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

88
export const useActorClearEventsMutation = (
@@ -31,7 +31,7 @@ export const useActorStatePatchMutation = (
3131
const queries = useActor();
3232
return useMutation({
3333
mutationFn: async (data: any) => {
34-
const client = queries.createActorInspector(actorId);
34+
const client = await queries.createActorInspector(actorId);
3535

3636
const oldStateQuery = queryClient.getQueryData(
3737
queries.actorStateQueryOptions(actorId).queryKey,
@@ -58,12 +58,15 @@ export const useActorStatePatchMutation = (
5858
if (!response.ok) {
5959
throw response;
6060
}
61-
return await response.json();
61+
return (await response.json()) as {
62+
state: unknown;
63+
enabled: boolean;
64+
};
6265
},
6366
onSuccess: (data) => {
6467
queryClient.setQueryData(
6568
queries.actorStateQueryOptions(actorId).queryKey,
66-
() => ({ enabled: true, state: data }),
69+
() => ({ enabled: true, state: data.state }),
6770
);
6871
},
6972
...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)