refactor: cleanup auto-rename code

This commit is contained in:
Zoe
2026-02-25 20:38:55 +00:00
parent e4536cbb8c
commit c3370c27a7
6 changed files with 71 additions and 40 deletions
+142
View File
@@ -0,0 +1,142 @@
import * as z from 'zod';
import { httpClient } from '~~/server/lib/triplit';
import { renamePrompt } from '~~/prompts';
import { schema } from '~~/triplit/schema';
import { type Entity } from '@triplit/client';
import { generateText } from 'ai';
import { GatewayFetchError, getProviderDetails, type ModelGateway } from '~~/server/utils/ai-provider';
import { addPendingRename } from '~~/server/utils/renames';
import { assert } from '~~/utils/assert';
export default defineEventHandler(async (event) => {
await protectRoute(event);
const userId = event.context.user!.id;
const topicId = getRouterParam(event, 'topicId')!;
const result = await readValidatedBody(event, (body) =>
z
.object({
modelId: z.string(),
prompt: z.string(),
providerApiKey: z.string().optional(),
})
.safeParse(body),
);
if (!result.success) {
throw createError({
statusCode: 400,
message: result.error.issues[0]!.message,
data: {
code: 'INVALID_BODY',
ok: false,
}
});
}
const { modelId, prompt, providerApiKey } = result.data;
const model = await httpClient.fetchOne(httpClient.query('models').Where('id', '=', modelId).Include('provider'));
if (model === null || model.providerId !== model.providerId || model.userId !== userId || model.provider === null) {
throw createError({
statusCode: 400,
statusMessage: 'Invalid model',
data: {
code: 'INVALID_MODEL',
ok: false,
}
});
}
const providerDetails = await getProviderDetails(model.provider, providerApiKey, model);
if (!providerDetails.ok) {
switch (providerDetails.error) {
case GatewayFetchError.NoProviderApiKey: {
setResponseStatus(event, 400, "No provider API key");
throw createError({
statusCode: 400,
statusMessage: `${model.provider.type} provider requires an API key`,
data: {
code: 'NO_PROVIDER_API_KEY',
ok: false,
}
});
}
case GatewayFetchError.NoProviderBaseUrl: {
throw createError({
statusCode: 400,
statusMessage: 'Invalid provider URL',
data: {
code: 'BAD_PROVIDER_URL',
ok: false,
}
});
}
}
}
const { gateway } = providerDetails.data;
if (gateway === null) {
throw createError({
statusCode: 500,
statusMessage: 'Invalid gateway',
data: {
code: 'INVALID_GATEWAY',
ok: false,
}
});
}
const [renameId, pendingRename] = addPendingRename(topicId);
event.waitUntil(autoRename(topicId, renameId, pendingRename.abortController, { gateway: gateway.gateway, model }, gateway.textTransformer, prompt));
return {
renameId,
ok: true,
};
});
const autoRename = async (
topicId: string,
renameId: string,
abortController: AbortController,
model: {
gateway: ModelGateway,
model: Entity<typeof schema, 'models'>,
},
textTransformer: ((text: string) => string) | ((text: string) => string)[] | undefined,
prompt: string,
) => {
try {
const response = await generateText({
model: model.gateway(model.model.externalId),
system: renamePrompt,
prompt,
timeout: 90 * 1000,
abortSignal: abortController.signal,
})
let text = response.text;
if (textTransformer !== undefined) {
if (Array.isArray(textTransformer)) {
for (const transformer of textTransformer) {
text = transformer(text);
}
} else {
text = textTransformer(text);
}
}
await httpClient.update('topics', topicId, {
name: text,
});
} catch (error) {
console.error('Failed to auto-rename:', error);
} finally {
completeRename(renameId);
await httpClient.update('topics', topicId, {
renaming: false
});
}
}