Clean up old stuff & fix ui errors
Build and Push Spoon Images / quality (push) Successful in 2m22s
Build and Push Spoon Images / build-images (push) Successful in 23m10s

This commit is contained in:
Gabriel Brown
2026-06-23 14:57:05 -04:00
parent d207b8b0b8
commit a6f7ea7f78
34 changed files with 1565 additions and 551 deletions
+84
View File
@@ -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'),