Clean up old stuff & fix ui errors
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { ConvexError, v } from 'convex/values';
|
||||
|
||||
import type { Doc } from './_generated/dataModel';
|
||||
import type { MutationCtx } from './_generated/server';
|
||||
import { internal } from './_generated/api';
|
||||
import {
|
||||
internalMutation,
|
||||
@@ -68,6 +69,53 @@ const titleFromPrompt = (prompt: string) => {
|
||||
|
||||
const publicThread = (thread: Doc<'threads'>) => thread;
|
||||
|
||||
const isDeletableThreadJob = (job: Doc<'agentJobs'>) =>
|
||||
['failed', 'cancelled', 'timed_out', 'draft_pr_opened'].includes(
|
||||
job.status,
|
||||
) || ['stopped', 'expired', 'failed'].includes(job.workspaceStatus ?? '');
|
||||
|
||||
const deleteThreadJobRows = async (ctx: MutationCtx, job: Doc<'agentJobs'>) => {
|
||||
const [messages, events, artifacts, changes, uiStates, interactions] =
|
||||
await Promise.all([
|
||||
ctx.db
|
||||
.query('agentJobMessages')
|
||||
.withIndex('by_job', (q) => q.eq('jobId', job._id))
|
||||
.collect(),
|
||||
ctx.db
|
||||
.query('agentJobEvents')
|
||||
.withIndex('by_job', (q) => q.eq('jobId', job._id))
|
||||
.collect(),
|
||||
ctx.db
|
||||
.query('agentJobArtifacts')
|
||||
.withIndex('by_job', (q) => q.eq('jobId', job._id))
|
||||
.collect(),
|
||||
ctx.db
|
||||
.query('agentWorkspaceChanges')
|
||||
.withIndex('by_job', (q) => q.eq('jobId', job._id))
|
||||
.collect(),
|
||||
ctx.db
|
||||
.query('agentWorkspaceUiStates')
|
||||
.withIndex('by_job', (q) => q.eq('jobId', job._id))
|
||||
.collect(),
|
||||
ctx.db
|
||||
.query('agentInteractionRequests')
|
||||
.withIndex('by_job', (q) => q.eq('jobId', job._id))
|
||||
.collect(),
|
||||
]);
|
||||
|
||||
for (const row of [
|
||||
...messages,
|
||||
...events,
|
||||
...artifacts,
|
||||
...changes,
|
||||
...uiStates,
|
||||
...interactions,
|
||||
]) {
|
||||
await ctx.db.delete(row._id);
|
||||
}
|
||||
await ctx.db.delete(job._id);
|
||||
};
|
||||
|
||||
export const listMine = query({
|
||||
args: {
|
||||
status: v.optional(v.union(threadStatus, v.literal('all'))),
|
||||
@@ -275,6 +323,42 @@ export const markResolved = mutation({
|
||||
},
|
||||
});
|
||||
|
||||
export const deleteThread = mutation({
|
||||
args: { threadId: v.id('threads') },
|
||||
handler: async (ctx, { threadId }) => {
|
||||
const ownerId = await getRequiredUserId(ctx);
|
||||
const thread = await ctx.db.get(threadId);
|
||||
if (thread?.ownerId !== ownerId) throw new ConvexError('Thread not found.');
|
||||
|
||||
const jobs = (
|
||||
await ctx.db
|
||||
.query('agentJobs')
|
||||
.withIndex('by_owner', (q) => q.eq('ownerId', ownerId))
|
||||
.collect()
|
||||
).filter((job) => job.threadId === threadId);
|
||||
|
||||
const activeJob = jobs.find((job) => !isDeletableThreadJob(job));
|
||||
if (activeJob) {
|
||||
throw new ConvexError(
|
||||
'Stop or cancel active workspace runs before deleting this thread.',
|
||||
);
|
||||
}
|
||||
|
||||
const messages = await ctx.db
|
||||
.query('threadMessages')
|
||||
.withIndex('by_thread', (q) => q.eq('threadId', threadId))
|
||||
.collect();
|
||||
for (const job of jobs) {
|
||||
await deleteThreadJobRows(ctx, job);
|
||||
}
|
||||
for (const message of messages) {
|
||||
await ctx.db.delete(message._id);
|
||||
}
|
||||
await ctx.db.delete(threadId);
|
||||
return { deletedJobs: jobs.length, deletedMessages: messages.length };
|
||||
},
|
||||
});
|
||||
|
||||
export const findOpenMaintenanceThread = internalQuery({
|
||||
args: {
|
||||
spoonId: v.id('spoons'),
|
||||
|
||||
Reference in New Issue
Block a user