76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
import { denFetch } from "@openwork/behaviors";
|
|
import type { DenSession } from "@openwork/behaviors";
|
|
import { resolvePlace } from "@openwork/testkit/stack";
|
|
import type { Den, Place } from "@openwork/testkit/stack";
|
|
import {
|
|
ACME_DOCS_APP,
|
|
ACME_DOCS_MEMBER,
|
|
ACME_DOCS_ORGANIZATION_NAME,
|
|
ACME_DOCS_PROMPT_CARDS,
|
|
bootAcmeDocs,
|
|
} from "../../worlds/acme-docs.ts";
|
|
import type { AcmeDocsWorld } from "../../worlds/acme-docs.ts";
|
|
import { provider } from "./ctx.ts";
|
|
|
|
export const DOCS_ORGANIZATION_NAME = ACME_DOCS_ORGANIZATION_NAME;
|
|
export const DOCS_PROMPT_CARDS = ACME_DOCS_PROMPT_CARDS;
|
|
export const DOCS_MEMBER = ACME_DOCS_MEMBER;
|
|
export const DOCS_APP = ACME_DOCS_APP;
|
|
|
|
export interface SeededOrg {
|
|
world: AcmeDocsWorld;
|
|
den: Den;
|
|
place: Place;
|
|
orgId: string;
|
|
/** Plugin ids in the order of the fixture's plugins. */
|
|
pluginIds: string[];
|
|
mcpToken: string;
|
|
}
|
|
|
|
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
}
|
|
|
|
async function readOrganizationId(admin: DenSession): Promise<string> {
|
|
const { response, body, text } = await denFetch(admin, "/v1/me/orgs", {
|
|
headers: { authorization: `Bearer ${admin.token}` },
|
|
});
|
|
const orgs = isRecord(body) && Array.isArray(body.orgs) ? body.orgs.filter(isRecord) : [];
|
|
const organization = orgs.find((entry) => entry.name === DOCS_ORGANIZATION_NAME);
|
|
const id = organization && typeof organization.id === "string" ? organization.id : "";
|
|
if (!response.ok || !id) throw new Error(`Resolving the organization failed: HTTP ${response.status} ${text.slice(0, 300)}`);
|
|
return id;
|
|
}
|
|
|
|
async function mintMcpToken(admin: DenSession, orgId: string): Promise<string> {
|
|
const { response, body, text } = await denFetch(admin, "/v1/mcp/token", {
|
|
method: "POST",
|
|
headers: { authorization: `Bearer ${admin.token}`, "x-openwork-org-id": orgId },
|
|
body: JSON.stringify({ scopes: ["mcp:read", "mcp:write"] }),
|
|
});
|
|
const token = isRecord(body) && typeof body.token === "string" ? body.token : "";
|
|
if (!response.ok || !token) throw new Error(`Minting an MCP token failed: HTTP ${response.status} ${text.slice(0, 300)}`);
|
|
return token;
|
|
}
|
|
|
|
export const org = provider(async (ctx) => {
|
|
const place = resolvePlace(process.env);
|
|
const stack = new AsyncDisposableStack();
|
|
try {
|
|
const world = await bootAcmeDocs(stack, place);
|
|
ctx.onDispose(() => stack.disposeAsync());
|
|
const orgId = await readOrganizationId(world.den.admin);
|
|
return {
|
|
world,
|
|
den: world.den,
|
|
place,
|
|
orgId,
|
|
pluginIds: world.pluginIds,
|
|
mcpToken: await mintMcpToken(world.den.admin, orgId),
|
|
};
|
|
} catch (error) {
|
|
await stack.disposeAsync();
|
|
throw error;
|
|
}
|
|
});
|