Clean up old stuff & fix ui errors
This commit is contained in:
@@ -48,6 +48,7 @@ const createAgentJob = async (
|
||||
spoonId: Id<'spoons'>;
|
||||
status: 'running' | 'failed' | 'cancelled';
|
||||
workspaceStatus?: 'active' | 'stopped' | 'failed' | 'expired';
|
||||
threadId?: Id<'threads'>;
|
||||
},
|
||||
) =>
|
||||
await t.mutation(async (ctx) => {
|
||||
@@ -64,6 +65,7 @@ const createAgentJob = async (
|
||||
spoonId: args.spoonId,
|
||||
ownerId: args.ownerId,
|
||||
agentRequestId: requestId,
|
||||
threadId: args.threadId,
|
||||
status: args.status,
|
||||
prompt: 'Clean this workspace',
|
||||
runtime: 'opencode',
|
||||
@@ -299,6 +301,126 @@ describe('convex-test harness', () => {
|
||||
).rejects.toThrow('Agent job not found.');
|
||||
});
|
||||
|
||||
test('persists and clamps workspace agent thread width', async () => {
|
||||
const t = convexTest(schema, modules);
|
||||
const ownerId = (await createUser(t, 'owner@example.com')) as Id<'users'>;
|
||||
const spoonId = await authed(t, ownerId).mutation(
|
||||
api.spoons.createManual,
|
||||
spoonInput,
|
||||
);
|
||||
const jobId = await createAgentJob(t, {
|
||||
ownerId,
|
||||
spoonId,
|
||||
status: 'running',
|
||||
workspaceStatus: 'active',
|
||||
});
|
||||
|
||||
const defaults = await authed(t, ownerId).query(
|
||||
api.agentJobs.getWorkspaceUiState,
|
||||
{ jobId },
|
||||
);
|
||||
expect(defaults.agentThreadWidth).toBe(420);
|
||||
|
||||
await authed(t, ownerId).mutation(api.agentJobs.patchWorkspaceUiState, {
|
||||
jobId,
|
||||
agentThreadWidth: 999,
|
||||
});
|
||||
const wide = await authed(t, ownerId).query(
|
||||
api.agentJobs.getWorkspaceUiState,
|
||||
{ jobId },
|
||||
);
|
||||
expect(wide.agentThreadWidth).toBe(720);
|
||||
|
||||
await authed(t, ownerId).mutation(api.agentJobs.patchWorkspaceUiState, {
|
||||
jobId,
|
||||
agentThreadWidth: 100,
|
||||
});
|
||||
const narrow = await authed(t, ownerId).query(
|
||||
api.agentJobs.getWorkspaceUiState,
|
||||
{ jobId },
|
||||
);
|
||||
expect(narrow.agentThreadWidth).toBe(320);
|
||||
});
|
||||
|
||||
test('deletes terminal threads and attached terminal workspace rows', async () => {
|
||||
const t = convexTest(schema, modules);
|
||||
const ownerId = (await createUser(t, 'owner@example.com')) as Id<'users'>;
|
||||
const spoonId = await authed(t, ownerId).mutation(
|
||||
api.spoons.createManual,
|
||||
spoonInput,
|
||||
);
|
||||
const threadId = await t.mutation(async (ctx) => {
|
||||
return await ctx.db.insert('threads', {
|
||||
ownerId,
|
||||
spoonId,
|
||||
title: 'Failed attempt',
|
||||
source: 'user_request',
|
||||
status: 'failed',
|
||||
priority: 'normal',
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
});
|
||||
const jobId = await createAgentJob(t, {
|
||||
ownerId,
|
||||
spoonId,
|
||||
threadId,
|
||||
status: 'failed',
|
||||
workspaceStatus: 'failed',
|
||||
});
|
||||
await t.mutation(async (ctx) => {
|
||||
await ctx.db.patch(threadId, { latestAgentJobId: jobId });
|
||||
});
|
||||
|
||||
await authed(t, ownerId).mutation(api.threads.deleteThread, { threadId });
|
||||
|
||||
const [thread, job, messages] = await t.run(async (ctx) => {
|
||||
const rows = await ctx.db
|
||||
.query('agentJobMessages')
|
||||
.withIndex('by_job', (q) => q.eq('jobId', jobId))
|
||||
.collect();
|
||||
return [await ctx.db.get(threadId), await ctx.db.get(jobId), rows];
|
||||
});
|
||||
expect(thread).toBeNull();
|
||||
expect(job).toBeNull();
|
||||
expect(messages).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('does not delete threads with active workspace runs', async () => {
|
||||
const t = convexTest(schema, modules);
|
||||
const ownerId = (await createUser(t, 'owner@example.com')) as Id<'users'>;
|
||||
const spoonId = await authed(t, ownerId).mutation(
|
||||
api.spoons.createManual,
|
||||
spoonInput,
|
||||
);
|
||||
const threadId = await t.mutation(async (ctx) => {
|
||||
return await ctx.db.insert('threads', {
|
||||
ownerId,
|
||||
spoonId,
|
||||
title: 'Active attempt',
|
||||
source: 'user_request',
|
||||
status: 'running',
|
||||
priority: 'normal',
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now(),
|
||||
});
|
||||
});
|
||||
const jobId = await createAgentJob(t, {
|
||||
ownerId,
|
||||
spoonId,
|
||||
threadId,
|
||||
status: 'running',
|
||||
workspaceStatus: 'active',
|
||||
});
|
||||
await t.mutation(async (ctx) => {
|
||||
await ctx.db.patch(threadId, { latestAgentJobId: jobId });
|
||||
});
|
||||
|
||||
await expect(
|
||||
authed(t, ownerId).mutation(api.threads.deleteThread, { threadId }),
|
||||
).rejects.toThrow('Stop or cancel active workspace runs');
|
||||
});
|
||||
|
||||
test('queues a new thread job after the previous job is terminal', async () => {
|
||||
const t = convexTest(schema, modules);
|
||||
const ownerId = (await createUser(t, 'owner@example.com')) as Id<'users'>;
|
||||
|
||||
Reference in New Issue
Block a user