check_batch_progress
Check progress of a batch transcription job. Returns overall progress, current file, failed files, and elapsed time. Call repeatedly until complete.
Instructions
Check the status of a batch started with start_batch. Automatically advances to the next file when the current one finishes. Returns overall progress, current file, failed files, and elapsed time. Call repeatedly until the batch shows as complete.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| batch_id | Yes | Batch ID returned by start_batch. |
Implementation Reference
- src/index.ts:1722-1731 (handler)The CallToolRequestSchema handler that routes 'check_batch_progress' requests to the readBatchProgress helper function.
if (name === "check_batch_progress") { const batchId = args?.batch_id as string; if (!batchId) return { content: [{ type: "text", text: "batch_id is required." }], isError: true }; try { const result = await readBatchProgress(batchId); return { content: [{ type: "text", text: result }] }; } catch (err: any) { return { content: [{ type: "text", text: `Error reading batch progress:\n\n${err?.message || String(err)}` }], isError: true }; } } - src/index.ts:393-499 (helper)The readBatchProgress helper function that reads the batch state JSON, checks the current running job, validates completed/failed jobs, advances to the next file, and builds a human-readable progress report. This is the core logic behind check_batch_progress.
async function readBatchProgress(batchId: string): Promise<string> { const batchPath = join(JOBS_DIR, `${batchId}.batch.json`); if (!existsSync(batchPath)) { return `❌ Batch not found: ${batchId}\n\nThe batch file may have been deleted or the ID is incorrect.`; } const state: BatchState = JSON.parse(readFileSync(batchPath, "utf8")); // Check current running job const running = state.files.find(f => f.status === "running"); if (running && running.jobId) { const jobPath = join(JOBS_DIR, `${running.jobId}.json`); if (existsSync(jobPath)) { const job = JSON.parse(readFileSync(jobPath, "utf8")); const isRunning = await isPidRunning(job.pid); const outputExists = existsSync(job.outputPath); if (!isRunning) { // Move temp output to final destination if needed. // spawnDetached writes to a sanitized JOBS_DIR temp path to avoid Unicode // filename issues. readJobProgress normally handles this move, but // readBatchProgress must do it too since it never calls readJobProgress. const ext = job.outputFormat === "srt" ? ".srt" : ".txt"; const tmpOutput = `${job.tmpOutputBase}${ext}`; if (existsSync(tmpOutput) && tmpOutput !== job.outputPath) { try { writeFileSync(job.outputPath, readFileSync(tmpOutput, "utf8"), "utf8"); unlinkSync(tmpOutput); } catch { /* ignore — validateTranscript will catch missing output */ } } // Clean up temp WAV if present if (job.isTmp && existsSync(job.transcribeFrom)) { try { unlinkSync(job.transcribeFrom); } catch { } } // Job finished — validate and advance const finalOutputExists = existsSync(job.outputPath); const validation = validateTranscript(job.outputPath, running.durationSec); if (finalOutputExists && validation.valid) { running.status = "complete"; } else { running.status = "failed"; running.failReason = validation.reason ?? "no output file"; } // Advance to next state.currentIndex = state.files.indexOf(running) + 1; if (state.files.some(f => f.status === "pending")) { await spawnNextBatchJob(state); } else { state.status = "complete"; writeFileSync(batchPath, JSON.stringify(state, null, 2), "utf8"); } } else { // Still running — update state file without advancing writeFileSync(batchPath, JSON.stringify(state, null, 2), "utf8"); } } } else if (state.status !== "complete" && state.files.some(f => f.status === "pending")) { // No running job but pending files exist — advance await spawnNextBatchJob(state); } // Build status report const done = state.files.filter(f => f.status === "complete").length; const failed = state.files.filter(f => f.status === "failed"); const pending = state.files.filter(f => f.status === "pending").length; const currentRunning = state.files.find(f => f.status === "running"); const total = state.files.length; const elapsed = Math.round((Date.now() - new Date(state.startTime).getTime()) / 1000); let report = `Batch: ${batchId}\n`; report += `Folder: ${state.folder}\n`; report += `${"─".repeat(50)}\n`; report += `Progress: ${done}/${total} complete`; if (failed.length > 0) report += ` | ${failed.length} failed`; if (pending > 0) report += ` | ${pending} remaining`; report += `\nElapsed: ${formatDuration(elapsed)}\n`; if (currentRunning) { report += `\nCurrently processing: ${currentRunning.fileName}`; if (currentRunning.jobId) { const jobPath = join(JOBS_DIR, `${currentRunning.jobId}.json`); if (existsSync(jobPath)) { const job = JSON.parse(readFileSync(jobPath, "utf8")); const logContent = existsSync(job.logPath) ? readFileSync(job.logPath, "utf8") : ""; const lastSec = parseLastTimestamp(logContent); if (lastSec > 0) report += ` (${formatDuration(lastSec)} / ${formatDuration(currentRunning.durationSec)})`; } } } if (failed.length > 0) { report += `\n\n⚠️ Failed files:\n`; for (const f of failed) { report += ` ❌ ${f.fileName} — ${f.failReason ?? "unknown reason"}\n`; } report += `\nRe-run failed files with transcribe_audio individually.`; } if (state.status === "complete") { report = `✅ Batch complete!\n\n` + report; } else { report += `\n\nCall check_batch_progress again to update.`; } return report; } - src/index.ts:1032-1046 (registration)Registration of the 'check_batch_progress' tool in the ListToolsRequestSchema handler, including its description and input schema (requires batch_id string).
{ name: "check_batch_progress", description: "Check the status of a batch started with start_batch. " + "Automatically advances to the next file when the current one finishes. " + "Returns overall progress, current file, failed files, and elapsed time. " + "Call repeatedly until the batch shows as complete.", inputSchema: { type: "object", properties: { batch_id: { type: "string", description: "Batch ID returned by start_batch." }, }, required: ["batch_id"], }, }, - src/index.ts:351-362 (schema)BatchState interface — the data structure used by readBatchProgress (and hence check_batch_progress) to represent batch state.
interface BatchState { batchId: string; batchPath: string; folder: string; startTime: string; files: BatchFile[]; currentIndex: number; status: "running" | "complete"; model: string; language: string; threads: number; }