feat: add next_action field to update_job_status response

This commit is contained in:
Janpeter Visser 2026-05-01 14:13:22 +02:00
parent 994f28f103
commit ca0883a837
2 changed files with 41 additions and 1 deletions

View file

@ -0,0 +1,25 @@
import { describe, it, expect } from 'vitest'
import { resolveNextAction } from '../src/tools/update-job-status.js'
describe('resolveNextAction', () => {
it('returns wait_for_job_again when queue has jobs after done', () => {
expect(resolveNextAction(3, 'done')).toBe('wait_for_job_again')
})
it('returns queue_empty when queue is empty after done', () => {
expect(resolveNextAction(0, 'done')).toBe('queue_empty')
})
it('returns wait_for_job_again when queue has jobs after failed', () => {
expect(resolveNextAction(1, 'failed')).toBe('wait_for_job_again')
})
it('returns queue_empty when queue is empty after failed', () => {
expect(resolveNextAction(0, 'failed')).toBe('queue_empty')
})
it('returns idle for running status regardless of queue count', () => {
expect(resolveNextAction(5, 'running')).toBe('idle')
expect(resolveNextAction(0, 'running')).toBe('idle')
})
})

View file

@ -97,6 +97,14 @@ const DB_STATUS_MAP = {
failed: 'FAILED',
} as const
export function resolveNextAction(
queueCount: number,
status: 'running' | 'done' | 'failed',
): 'wait_for_job_again' | 'queue_empty' | 'idle' {
if (status === 'running') return 'idle'
return queueCount > 0 ? 'wait_for_job_again' : 'queue_empty'
}
export async function maybeCreateAutoPr(opts: {
jobId: string
productId: string
@ -140,7 +148,8 @@ export function registerUpdateJobStatusTool(server: McpServer) {
'Report progress on a claimed ClaudeJob. Allowed transitions from CLAIMED/RUNNING: ' +
'running (start), done (finished), failed (error). ' +
'The Bearer token must match the token that claimed the job. ' +
'Automatically emits an SSE event so the Scrum4Me UI updates in real time.',
'Automatically emits an SSE event so the Scrum4Me UI updates in real time. ' +
'Response includes next_action: when wait_for_job_again, immediately call wait_for_job again. When queue_empty, the agent batch is done.',
inputSchema,
},
async ({ job_id, status, branch, summary, error }) =>
@ -262,6 +271,11 @@ export function registerUpdateJobStatusTool(server: McpServer) {
await cleanupWorktreeForTerminalStatus(job.product_id, job_id, actualStatus, branchToWrite)
}
const queueCount = await prisma.claudeJob.count({
where: { user_id: userId, status: 'QUEUED' },
})
const nextAction = resolveNextAction(queueCount, actualStatus)
return toolJson({
job_id: updated.id,
status: actualStatus,
@ -272,6 +286,7 @@ export function registerUpdateJobStatusTool(server: McpServer) {
error: updated.error,
started_at: updated.started_at?.toISOString() ?? null,
finished_at: updated.finished_at?.toISOString() ?? null,
next_action: nextAction,
})
}),
)