forked from bai/curriculum-project-hub
chore: drop superseded admin-panel agent-config prototype after rebase onto main
main now ships the canonical org-scoped agent-config implementation (OrganizationAgentRole/OrganizationAgentSkill + hub/src/agent/configuration.ts + hub/src/agent/skillStore.ts per ADR-0018, and envelope-encrypted OrganizationProviderConnection per ADR-0024). The earlier admin-panel prototype (OrgModel/OrgRole/simple ProviderConnection baseUrl+authToken, modelRoutes.ts, agentConfig.ts, migration 20260710120000, admin-web models/roles pages) is superseded and clashes with main's schema; drop it. Follow-up still needed: rewire admin-web SPA to the new config APIs (+layout.svelte nav still lists models/roles, RoleCard.svelte unused).
This commit is contained in:
@@ -1,252 +0,0 @@
|
||||
/**
|
||||
* Org-admin routes for agent config: provider connection, enabled models, and
|
||||
* role presets (ADR-0017 / ADR-0021). Mounted under `/api/org/:orgSlug`.
|
||||
*/
|
||||
import type { PrismaClient } from "@prisma/client";
|
||||
import type { FastifyInstance } from "fastify";
|
||||
import {
|
||||
createOrgModel,
|
||||
createOrgRole,
|
||||
deleteOrgModel,
|
||||
deleteOrgRole,
|
||||
getProviderConnection,
|
||||
listOrgModels,
|
||||
listOrgRoles,
|
||||
updateOrgModel,
|
||||
updateOrgRole,
|
||||
upsertProviderConnection,
|
||||
} from "../../org/agentConfig.js";
|
||||
import { requireOrgRole, type GuardDeps } from "../auth/guards.js";
|
||||
import { handleRouteError } from "../errors.js";
|
||||
|
||||
const PROVIDER_MODES = ["BYOK", "PLATFORM_MANAGED"] as const;
|
||||
type ProviderMode = (typeof PROVIDER_MODES)[number];
|
||||
|
||||
export async function registerModelRoutes(
|
||||
app: FastifyInstance,
|
||||
config: { readonly prisma: PrismaClient; readonly sessionSecret: string },
|
||||
): Promise<void> {
|
||||
const guardDeps: GuardDeps = { prisma: config.prisma, sessionSecret: config.sessionSecret };
|
||||
|
||||
// --- Provider connection ---------------------------------------------
|
||||
|
||||
app.get("/api/org/:orgSlug/provider-connection", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug } = request.params as { orgSlug: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
return await getProviderConnection(config.prisma, auth.organization.id);
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
app.put("/api/org/:orgSlug/provider-connection", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug } = request.params as { orgSlug: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
const body = request.body as {
|
||||
providerId?: unknown;
|
||||
mode?: unknown;
|
||||
baseUrl?: unknown;
|
||||
authToken?: unknown;
|
||||
};
|
||||
const mode = parseProviderMode(body.mode);
|
||||
if (mode === null) {
|
||||
return reply.status(400).send({
|
||||
error: { code: "bad_request", message: "mode must be BYOK or PLATFORM_MANAGED" },
|
||||
});
|
||||
}
|
||||
const connection = await upsertProviderConnection(config.prisma, {
|
||||
organizationId: auth.organization.id,
|
||||
mode,
|
||||
...(typeof body.providerId === "string" ? { providerId: body.providerId } : {}),
|
||||
...(body.baseUrl === null || typeof body.baseUrl === "string"
|
||||
? { baseUrl: body.baseUrl as string | null }
|
||||
: {}),
|
||||
...(body.authToken === null || typeof body.authToken === "string"
|
||||
? { authToken: body.authToken as string | null }
|
||||
: {}),
|
||||
});
|
||||
return connection;
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
// --- Models ----------------------------------------------------------
|
||||
|
||||
app.get("/api/org/:orgSlug/models", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug } = request.params as { orgSlug: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
return { models: await listOrgModels(config.prisma, auth.organization.id) };
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/org/:orgSlug/models", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug } = request.params as { orgSlug: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
const body = request.body as {
|
||||
modelId?: unknown;
|
||||
label?: unknown;
|
||||
toolCapable?: unknown;
|
||||
sortKey?: unknown;
|
||||
};
|
||||
if (typeof body.modelId !== "string" || typeof body.label !== "string") {
|
||||
return reply.status(400).send({
|
||||
error: { code: "bad_request", message: "modelId and label are required" },
|
||||
});
|
||||
}
|
||||
const model = await createOrgModel(config.prisma, {
|
||||
organizationId: auth.organization.id,
|
||||
modelId: body.modelId,
|
||||
label: body.label,
|
||||
...(typeof body.toolCapable === "boolean" ? { toolCapable: body.toolCapable } : {}),
|
||||
...(typeof body.sortKey === "string" ? { sortKey: body.sortKey } : {}),
|
||||
});
|
||||
return reply.status(201).send(model);
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
app.patch("/api/org/:orgSlug/models/:modelId", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug, modelId } = request.params as { orgSlug: string; modelId: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
const body = request.body as {
|
||||
label?: unknown;
|
||||
toolCapable?: unknown;
|
||||
sortKey?: unknown;
|
||||
modelId?: unknown;
|
||||
};
|
||||
return await updateOrgModel(config.prisma, {
|
||||
organizationId: auth.organization.id,
|
||||
id: modelId,
|
||||
...(typeof body.label === "string" ? { label: body.label } : {}),
|
||||
...(typeof body.toolCapable === "boolean" ? { toolCapable: body.toolCapable } : {}),
|
||||
...(typeof body.sortKey === "string" ? { sortKey: body.sortKey } : {}),
|
||||
...(typeof body.modelId === "string" ? { modelId: body.modelId } : {}),
|
||||
});
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/org/:orgSlug/models/:modelId", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug, modelId } = request.params as { orgSlug: string; modelId: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
return await deleteOrgModel(config.prisma, {
|
||||
organizationId: auth.organization.id,
|
||||
id: modelId,
|
||||
});
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
// --- Roles -----------------------------------------------------------
|
||||
|
||||
app.get("/api/org/:orgSlug/roles", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug } = request.params as { orgSlug: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
return { roles: await listOrgRoles(config.prisma, auth.organization.id) };
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/api/org/:orgSlug/roles", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug } = request.params as { orgSlug: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
const body = request.body as {
|
||||
roleId?: unknown;
|
||||
label?: unknown;
|
||||
defaultModelId?: unknown;
|
||||
systemPrompt?: unknown;
|
||||
tools?: unknown;
|
||||
};
|
||||
if (typeof body.roleId !== "string" || typeof body.label !== "string") {
|
||||
return reply.status(400).send({
|
||||
error: { code: "bad_request", message: "roleId and label are required" },
|
||||
});
|
||||
}
|
||||
const role = await createOrgRole(config.prisma, {
|
||||
organizationId: auth.organization.id,
|
||||
roleId: body.roleId,
|
||||
label: body.label,
|
||||
...(typeof body.defaultModelId === "string" ? { defaultModelId: body.defaultModelId } : {}),
|
||||
...(body.defaultModelId === null ? { defaultModelId: null } : {}),
|
||||
...(typeof body.systemPrompt === "string" ? { systemPrompt: body.systemPrompt } : {}),
|
||||
...(body.systemPrompt === null ? { systemPrompt: null } : {}),
|
||||
...(Array.isArray(body.tools) ? { tools: body.tools as readonly string[] } : {}),
|
||||
...(body.tools === null ? { tools: null } : {}),
|
||||
});
|
||||
return reply.status(201).send(role);
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
app.patch("/api/org/:orgSlug/roles/:roleId", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug, roleId } = request.params as { orgSlug: string; roleId: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
const body = request.body as {
|
||||
label?: unknown;
|
||||
defaultModelId?: unknown;
|
||||
systemPrompt?: unknown;
|
||||
tools?: unknown;
|
||||
roleId?: unknown;
|
||||
};
|
||||
return await updateOrgRole(config.prisma, {
|
||||
organizationId: auth.organization.id,
|
||||
id: roleId,
|
||||
...(typeof body.label === "string" ? { label: body.label } : {}),
|
||||
...(typeof body.defaultModelId === "string" ? { defaultModelId: body.defaultModelId } : {}),
|
||||
...(body.defaultModelId === null ? { defaultModelId: null } : {}),
|
||||
...(typeof body.systemPrompt === "string" ? { systemPrompt: body.systemPrompt } : {}),
|
||||
...(body.systemPrompt === null ? { systemPrompt: null } : {}),
|
||||
...(Array.isArray(body.tools) ? { tools: body.tools as readonly string[] } : {}),
|
||||
...(body.tools === null ? { tools: null } : {}),
|
||||
...(typeof body.roleId === "string" ? { roleId: body.roleId } : {}),
|
||||
});
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
|
||||
app.delete("/api/org/:orgSlug/roles/:roleId", async (request, reply) => {
|
||||
try {
|
||||
const { orgSlug, roleId } = request.params as { orgSlug: string; roleId: string };
|
||||
const auth = await requireOrgRole(request, reply, guardDeps, { orgSlug });
|
||||
if (auth === null) return;
|
||||
return await deleteOrgRole(config.prisma, {
|
||||
organizationId: auth.organization.id,
|
||||
id: roleId,
|
||||
});
|
||||
} catch (err) {
|
||||
return handleRouteError(reply, err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function parseProviderMode(value: unknown): ProviderMode | null {
|
||||
if (typeof value !== "string") return null;
|
||||
return (PROVIDER_MODES as readonly string[]).includes(value) ? (value as ProviderMode) : null;
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
import { registerAccessRoutes } from "./accessRoutes.js";
|
||||
import { registerExplorerRoutes } from "./explorerRoutes.js";
|
||||
import { registerMembersRoutes } from "./membersRoutes.js";
|
||||
import { registerModelRoutes } from "./modelRoutes.js";
|
||||
import { registerSessionsAndUsageRoutes } from "./sessionsRoutes.js";
|
||||
import { registerTeamsRoutes } from "./teamsRoutes.js";
|
||||
import { registerProviderConnectionRoutes } from "./providerConnectionRoutes.js";
|
||||
@@ -106,10 +105,6 @@ export async function registerOrgRoutes(app: FastifyInstance, config: OrgRouteCo
|
||||
prisma: config.prisma,
|
||||
sessionSecret: config.sessionSecret,
|
||||
});
|
||||
await registerModelRoutes(app, {
|
||||
prisma: config.prisma,
|
||||
sessionSecret: config.sessionSecret,
|
||||
});
|
||||
await registerSessionsAndUsageRoutes(app, {
|
||||
prisma: config.prisma,
|
||||
sessionSecret: config.sessionSecret,
|
||||
|
||||
Reference in New Issue
Block a user