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
+4 -1
View File
@@ -66,7 +66,10 @@ const cancelAutoRename = async (topicId: string) => {
const renameId = activeAutoRenames.get(topicId); const renameId = activeAutoRenames.get(topicId);
if (!renameId) return; if (!renameId) return;
await $fetch(`/api/topic/auto-rename/cancel/${renameId}`, { await $fetch(`/api/auto-rename/cancel`, {
body: {
renameId,
},
method: 'POST', method: 'POST',
}); });
+14 -7
View File
@@ -412,10 +412,6 @@ export const useChat = (agentId: string) => {
return Err(AutoRenameError.NoModelSelected); return Err(AutoRenameError.NoModelSelected);
} }
await triplit.update('topics', topicId, {
renaming: true
});
const modelResult = await attempt(triplit.fetchOne(triplit.query('models').Where('id', '=', settings.value.systemAssistants.rename.modelId).Include('provider'))); const modelResult = await attempt(triplit.fetchOne(triplit.query('models').Where('id', '=', settings.value.systemAssistants.rename.modelId).Include('provider')));
if (modelResult.ok === false) { if (modelResult.ok === false) {
@@ -453,19 +449,30 @@ export const useChat = (agentId: string) => {
} }
} }
await triplit.update('topics', topicId, {
renaming: true
});
try { try {
const res = await $fetch(`/api/topic/auto-rename`, { const res = await $fetch(`/api/auto-rename/${topicId}`, {
method: 'POST', method: 'POST',
body: JSON.stringify({ body: JSON.stringify({
modelId: model.id, modelId: model.id,
topicId,
prompt, prompt,
providerApiKey, providerApiKey,
}), }),
}); }) as { ok: true, renameId: string } | { ok: false, code: string };
if (!res.ok) {
console.error('Failed to auto-rename:', res.code);
return Err(AutoRenameError.FailedToGenerate);
}
return Ok(res.renameId); return Ok(res.renameId);
} catch (error) { } catch (error) {
triplit.update('topics', topicId, {
renaming: false,
});
console.error('Failed to auto-rename:', error); console.error('Failed to auto-rename:', error);
return Err(AutoRenameError.FailedToGenerate); return Err(AutoRenameError.FailedToGenerate);
} }
+1 -10
View File
@@ -49,16 +49,7 @@ const handleSubmit = async (message: string, model: ModelWithProvider | null) =>
const topic = await createTopic(); const topic = await createTopic();
if (!topic) throw new Error('Failed to create topic'); if (!topic) throw new Error('Failed to create topic');
autoRename(topic.id, message).then(async res => { autoRename(topic.id, message);
if (res.ok === false) {
console.error('Failed to auto-rename:', res.error);
await triplit.update('topics', topic.id, {
renaming: false,
});
return;
}
});
await navigateTo(`/agent/${route.params.id}/topic/${topic.id}`); await navigateTo(`/agent/${route.params.id}/topic/${topic.id}`);
+1 -10
View File
@@ -110,16 +110,7 @@ const handleChatSubmit = async (message: string, model: ModelWithProvider | null
await navigateTo(`/agent/${agent.id}/topic/${topic.id}`); await navigateTo(`/agent/${agent.id}/topic/${topic.id}`);
autoRename(topic.id, message).then(async res => { autoRename(topic.id, message);
if (res.ok === false) {
console.error('Failed to auto-rename:', res.error);
await triplit.update('topics', topic.id, {
renaming: false,
});
return;
}
});
return sendMessage(message, topic, [], agent, model.provider, model).then(async res => { return sendMessage(message, topic, [], agent, model.provider, model).then(async res => {
if (res.ok === false) { if (res.ok === false) {
@@ -12,12 +12,12 @@ export default defineEventHandler(async (event) => {
await protectRoute(event); await protectRoute(event);
const userId = event.context.user!.id; const userId = event.context.user!.id;
const topicId = getRouterParam(event, 'topicId')!;
const result = await readValidatedBody(event, (body) => const result = await readValidatedBody(event, (body) =>
z z
.object({ .object({
modelId: z.string(), modelId: z.string(),
topicId: z.string(),
prompt: z.string(), prompt: z.string(),
providerApiKey: z.string().optional(), providerApiKey: z.string().optional(),
}) })
@@ -27,47 +27,72 @@ export default defineEventHandler(async (event) => {
throw createError({ throw createError({
statusCode: 400, statusCode: 400,
message: result.error.issues[0]!.message, message: result.error.issues[0]!.message,
data: {
code: 'INVALID_BODY',
ok: false,
}
}); });
} }
const { modelId, topicId, prompt, providerApiKey } = result.data; const { modelId, prompt, providerApiKey } = result.data;
const model = await httpClient.fetchOne(httpClient.query('models').Where('id', '=', modelId).Include('provider')); const model = await httpClient.fetchOne(httpClient.query('models').Where('id', '=', modelId).Include('provider'));
if (model === null || model.providerId !== model.providerId || model.userId !== userId) { if (model === null || model.providerId !== model.providerId || model.userId !== userId || model.provider === null) {
throw createError({ throw createError({
statusCode: 400, statusCode: 400,
message: 'Invalid model', statusMessage: 'Invalid model',
data: {
code: 'INVALID_MODEL',
ok: false,
}
}); });
} }
assert(model.provider !== null, 'Invalid model provider');
const providerDetails = await getProviderDetails(model.provider, providerApiKey, model); const providerDetails = await getProviderDetails(model.provider, providerApiKey, model);
if (!providerDetails.ok) { if (!providerDetails.ok) {
switch (providerDetails.error) { switch (providerDetails.error) {
case GatewayFetchError.NoProviderApiKey: { case GatewayFetchError.NoProviderApiKey: {
setResponseStatus(event, 400, "No provider API key");
throw createError({ throw createError({
statusCode: 400, statusCode: 400,
message: `${model.provider.type} provider requires an API key`, statusMessage: `${model.provider.type} provider requires an API key`,
data: {
code: 'NO_PROVIDER_API_KEY',
ok: false,
}
}); });
} }
case GatewayFetchError.NoProviderBaseUrl: { case GatewayFetchError.NoProviderBaseUrl: {
throw createError({ throw createError({
statusCode: 400, statusCode: 400,
message: 'Invalid provider URL', statusMessage: 'Invalid provider URL',
data: {
code: 'BAD_PROVIDER_URL',
ok: false,
}
}); });
} }
} }
} }
const { gateway } = providerDetails.data; const { gateway } = providerDetails.data;
assert(gateway !== null, 'Invalid gateway'); if (gateway === null) {
throw createError({
statusCode: 500,
statusMessage: 'Invalid gateway',
data: {
code: 'INVALID_GATEWAY',
ok: false,
}
});
}
const [renameId, pendingRename] = addPendingRename(topicId); const [renameId, pendingRename] = addPendingRename(topicId);
event.waitUntil(autoRename(topicId, renameId, pendingRename.abortController, { gateway: gateway.gateway, model }, gateway.textTransformer, prompt)); event.waitUntil(autoRename(topicId, renameId, pendingRename.abortController, { gateway: gateway.gateway, model }, gateway.textTransformer, prompt));
return { return {
success: true,
renameId, renameId,
ok: true,
}; };
}); });
@@ -1,3 +1,4 @@
import * as z from 'zod';
import { httpClient } from '~~/server/lib/triplit'; import { httpClient } from '~~/server/lib/triplit';
import { cancelPendingRename } from '~~/server/utils/renames'; import { cancelPendingRename } from '~~/server/utils/renames';
import { assert } from '~~/utils/assert'; import { assert } from '~~/utils/assert';
@@ -5,7 +6,20 @@ import { assert } from '~~/utils/assert';
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
await protectRoute(event); await protectRoute(event);
const { renameId } = event.context.params!; const body = await readValidatedBody(event, (body) =>
z
.object({
renameId: z.string(),
})
.safeParse(body),
);
if (!body.success) {
throw createError({
statusCode: 400,
message: 'Invalid rename ID',
});
}
const { renameId } = body.data;
assert(renameId); assert(renameId);
const [success, pendingRename] = cancelPendingRename(renameId); const [success, pendingRename] = cancelPendingRename(renameId);
@@ -18,11 +32,11 @@ export default defineEventHandler(async (event) => {
} }
return { return {
success: true, ok: true,
}; };
} }
return { return {
success: false, ok: false,
}; };
}); });