Skip to content
34 linesCodeBlameRaw
1import { data } from "react-router";
2
3import type { Result, User } from "@g1t/contracts";
4
5import { assertSameOrigin, requireUser, roleIn } from "../../lib/session.server";
6import type { ActionResult } from "./dialogs";
7
8/** What an Agents action knows first: who is asking, in which workspace, whether they own it, and the form. */
9export async function agentsAction(
10 request: Request,
11 context: Parameters<typeof requireUser>[0],
12 owner: string,
13): Promise<{ viewer: User; slug: string; isOwner: boolean; form: FormData }> {
14 assertSameOrigin(request);
15 const viewer = requireUser(context, request);
16 const slug = owner.toLowerCase();
17 const role = roleIn(viewer, slug);
18 if (!role) throw data(null, { status: 404 });
19 return { viewer, slug, isOwner: role === "owner", form: await request.formData() };
20}
21
22/** An agents-service call as an action's answer: worked, or why not. */
23export async function answer<T>(intent: string, call: Promise<Result<T>>): Promise<ActionResult> {
24 const result = await call.catch(() => null);
25 if (!result) return { ok: false, intent, error: "The agents service didn't answer. Try again in a moment." };
26 if (!result.ok) return { ok: false, intent, error: result.error.message };
27 return { ok: true, intent };
28}
29
30/** A loader's agents-service read: its value, or null when it failed (the page says so). */
31export async function readOrNull<T>(call: Promise<Result<T>>): Promise<T | null> {
32 const result = await call.catch(() => null);
33 return result?.ok ? result.value : null;
34}