integrate assistant custom widget workflow
This commit is contained in:
1 parent
d40e6852e6
commit
87a42f09be
8 files changed
+550
-351
No files matched your search
@@ -4,6 +4,7 @@ import { createTRPCRouter } from "./trpc";
|
||||
import { appRouter as appRouterForApps } from "./router/app";
|
||||
import { apiKeysRouter } from "./router/apiKeys";
|
||||
import { boardRouter } from "./router/board";
|
||||
import { customWidgetRouter } from "./router/custom-widget/custom-widget-router";
|
||||
import { dockerRouter } from "./router/docker/docker-router";
|
||||
import { iconsRouter } from "./router/icons";
|
||||
import { infoRouter } from "./router/info";
|
||||
@@ -27,6 +28,7 @@ export const mcpRouter = createTRPCRouter({
|
||||
app: appRouterForApps,
|
||||
apiKeys: apiKeysRouter,
|
||||
board: boardRouter,
|
||||
customWidget: customWidgetRouter,
|
||||
docker: dockerRouter,
|
||||
icon: iconsRouter,
|
||||
info: infoRouter,
|
||||
|
||||
@@ -7,13 +7,14 @@ import { createLogger } from "@homarr/core/infrastructure/logs";
|
||||
import { and, eq, handleTransactionsAsync, notInArray } from "@homarr/db";
|
||||
import { customWidgetDefinitions, customWidgetSecrets } from "@homarr/db/schema";
|
||||
import {
|
||||
customWidgetCreateSchema,
|
||||
customWidgetDefinitionSchema,
|
||||
customWidgetUpdateSchema,
|
||||
normalizeCustomWidgetAuthoringUpdate,
|
||||
} from "@homarr/custom-widgets/core";
|
||||
|
||||
import { createTRPCRouter, permissionRequiredProcedure } from "../../trpc";
|
||||
import { insertCustomWidgetDefinition } from "./definition-insert";
|
||||
import { parseCustomWidgetAuthoringInput } from "./authoring-validation";
|
||||
import { creationProcedures } from "./creation-procedures";
|
||||
import { managementQueryProcedures } from "./management-queries";
|
||||
import { metadataProcedures } from "./metadata-procedures";
|
||||
import { previewActionProcedures } from "./preview-action-procedures";
|
||||
@@ -35,23 +36,17 @@ const logger = createLogger({ module: "custom-widget" });
|
||||
export const customWidgetRouter = createTRPCRouter({
|
||||
...metadataProcedures,
|
||||
...managementQueryProcedures,
|
||||
|
||||
create: permissionRequiredProcedure
|
||||
.requiresPermission("admin")
|
||||
.meta({ mcp: { enabled: true, description: "Create one validated Custom JSX widget." } })
|
||||
.input(customWidgetCreateSchema)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const { secrets, ...candidate } = input;
|
||||
const definition = customWidgetDefinitionSchema.parse(candidate);
|
||||
assertSecretSources(definition.sources, secrets);
|
||||
const id = await insertCustomWidgetDefinition(ctx.db, definition, ctx.session.user.id, secrets);
|
||||
logger.info("Created custom widget definition", { id, name: definition.name });
|
||||
return { id };
|
||||
}),
|
||||
...creationProcedures,
|
||||
|
||||
update: permissionRequiredProcedure
|
||||
.requiresPermission("admin")
|
||||
.meta({ mcp: { enabled: true, description: "Update one Custom JSX widget." } })
|
||||
.meta({
|
||||
mcp: {
|
||||
enabled: true,
|
||||
description:
|
||||
"Update one Custom JSX widget. Prefer templateLines for multiline JSX changes. Returns a client-navigable edit link.",
|
||||
},
|
||||
})
|
||||
.input(customWidgetUpdateSchema)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const existing = await ctx.db.query.customWidgetDefinitions.findFirst({
|
||||
@@ -60,8 +55,11 @@ export const customWidgetRouter = createTRPCRouter({
|
||||
if (!existing) throw new TRPCError({ code: "NOT_FOUND" });
|
||||
|
||||
const current = parseStoredCustomWidgetDefinition(existing);
|
||||
const { id, secrets, ...changes } = input;
|
||||
const definition = customWidgetDefinitionSchema.parse({ ...current, ...changes });
|
||||
const { id, secrets, ...authoringChanges } = input;
|
||||
const definition = parseCustomWidgetAuthoringInput(() => {
|
||||
const changes = normalizeCustomWidgetAuthoringUpdate(authoringChanges);
|
||||
return customWidgetDefinitionSchema.parse({ ...current, ...changes });
|
||||
});
|
||||
if (secrets) assertSecretSources(definition.sources, secrets);
|
||||
const definitionChanges = { ...serializeCustomWidgetDefinition(definition), updatedAt: new Date() };
|
||||
const secretRows = secrets?.map((secret) => ({
|
||||
@@ -178,6 +176,7 @@ export const customWidgetRouter = createTRPCRouter({
|
||||
},
|
||||
});
|
||||
logger.info("Updated custom widget definition", { id });
|
||||
return { id, managementPath: `/manage/custom-widgets/edit/${id}` };
|
||||
}),
|
||||
|
||||
...secretProcedures,
|
||||
|
||||
Reference in new issue
Block a user