fix(custom-widgets): address final v2 review feedback (#6451)

This commit is contained in:
Thomas authored and GitHub committed 2026-07-23 02:11:32 +02:00
1 parent df967751f6
commit 4f6e335f72
20 files changed
+186 -92

No files matched your search

@@ -47,21 +47,30 @@ export const managementQueryProcedures = {
return [...current, ...legacy].toSorted((left, right) => left.name.localeCompare(right.name));
}),
legacyMigrationPrompt: manageProcedure.input(z.object({ id: z.string() })).query(async ({ ctx, input }) => {
const definition = await ctx.db.query.legacyCustomWidgetDefinitions.findFirst({
where: eq(legacyCustomWidgetDefinitions.id, input.id),
with: { secrets: true },
});
if (!definition) throw new TRPCError({ code: "NOT_FOUND", message: "Legacy custom widget not found" });
return {
id: definition.id,
version: 1 as const,
prompt: buildLegacyCustomWidgetMigrationPrompt(
definition,
definition.secrets.map(({ kind }) => kind),
),
};
}),
legacyMigrationPrompt: manageProcedure
.meta({
mcp: {
enabled: true,
description:
"Get a redacted AI migration prompt for one preserved legacy Custom Widget. Credentials must be configured separately.",
},
})
.input(z.object({ id: z.string() }))
.query(async ({ ctx, input }) => {
const definition = await ctx.db.query.legacyCustomWidgetDefinitions.findFirst({
where: eq(legacyCustomWidgetDefinitions.id, input.id),
with: { secrets: true },
});
if (!definition) throw new TRPCError({ code: "NOT_FOUND", message: "Legacy custom widget not found" });
return {
id: definition.id,
version: 1 as const,
prompt: buildLegacyCustomWidgetMigrationPrompt(
definition,
definition.secrets.map(({ kind }) => kind),
),
};
}),
get: manageProcedure
.meta({ mcp: { enabled: true, description: "Get one Custom JSX widget without secret values." } })
@@ -40,6 +40,13 @@ export const transferProcedures = {
}),
migrateLegacy: manageProcedure
.meta({
mcp: {
enabled: true,
description:
"Replace one preserved legacy Custom Widget with a validated v2 definition while retaining compatible encrypted credentials.",
},
})
.input(
z.object({
id: z.string(),
@@ -124,10 +131,18 @@ export const transferProcedures = {
return { id: legacy.id, preservedSecretCount: preservedSecrets.length };
}),
deleteLegacy: manageProcedure.input(z.object({ id: z.string() })).mutation(async ({ ctx, input }) => {
await ctx.db.delete(legacyCustomWidgetDefinitions).where(eq(legacyCustomWidgetDefinitions.id, input.id));
logger.info("Deleted legacy custom widget definition", { id: input.id });
}),
deleteLegacy: manageProcedure
.meta({
mcp: {
enabled: true,
description: "Permanently delete one preserved legacy Custom Widget that will not be migrated.",
},
})
.input(z.object({ id: z.string() }))
.mutation(async ({ ctx, input }) => {
await ctx.db.delete(legacyCustomWidgetDefinitions).where(eq(legacyCustomWidgetDefinitions.id, input.id));
logger.info("Deleted legacy custom widget definition", { id: input.id });
}),
};
function canPreserveLegacySecrets(
+3
View File
@@ -22,6 +22,7 @@ const MCP_TOOL_ALLOWLIST = {
"customWidget_get",
"customWidget_getAuthoringPrompt",
"customWidget_getSkill",
"customWidget_legacyMigrationPrompt",
"customWidget_list",
"customWidget_previewJournal",
"customWidget_previewQuery",
@@ -69,6 +70,7 @@ const MCP_TOOL_ALLOWLIST = {
"board_setHomeBoard",
"board_setMobileHomeBoard",
"customWidget_delete",
"customWidget_deleteLegacy",
"customWidget_previewAction",
"customWidget_templatePatch",
"dnsHole_disable",
@@ -94,6 +96,7 @@ const MCP_TOOL_ALLOWLIST = {
"apiKeys_delete",
"customWidget_configurationRequestUser",
"customWidget_create",
"customWidget_migrateLegacy",
"customWidget_previewCreate",
"customWidget_secretSet",
"customWidget_sourceConfigure",