Show results whose plan item stopped as failed
The engine can stop a plan item without updating its drafts: a run paused on material_quote_changed leaves the draft "preparing" for good, so the result showed Preparing forever. A draft still at work now counts as failed once its plan item is failed, blocked, cancelled or skipped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
import { request } from '../api/client'
|
||||
import { t } from '../i18n'
|
||||
import { kindLabel, type ContentKind, type Rule } from './parse'
|
||||
import { expressAgents, PLAN_ACTIVE, productionStatus, type Schedule } from './schedules'
|
||||
import { expressAgents, PLAN_ACTIVE, productionStatus, type PlanItem, type Schedule } from './schedules'
|
||||
|
||||
const AGENTS = '/organizations/current/agents'
|
||||
|
||||
@@ -79,6 +79,12 @@ interface RawSource {
|
||||
const ORDER: MaterialStatus[] = ['failed', 'rejected', 'preparing', 'generating', 'ready', 'accepted']
|
||||
const combined = (parts: Part[]) => ORDER.find(s => parts.some(p => p.status === s)) ?? 'preparing'
|
||||
|
||||
// The engine can stop a plan item without updating its drafts (e.g. a run paused on a changed
|
||||
// quote leaves the draft "preparing" for good), so a stopped item overrides a draft still at work.
|
||||
const STOPPED = new Set<PlanItem['status']>(['failed', 'blocked', 'cancelled', 'skipped'])
|
||||
export const withPlanItem = (status: MaterialStatus, item: PlanItem['status'] | undefined): MaterialStatus =>
|
||||
item && STOPPED.has(item) && (status === 'preparing' || status === 'generating') ? 'failed' : status
|
||||
|
||||
async function materialsOf(schedule: Schedule): Promise<Material[]> {
|
||||
if (schedule.rule.type === 'content' && schedule.rule.kind === 'video') return videosOf(schedule)
|
||||
const { agent, rule } = schedule
|
||||
@@ -87,9 +93,9 @@ async function materialsOf(schedule: Schedule): Promise<Material[]> {
|
||||
request<RawMaterial[]>(`${AGENTS}/${agent.id}/material-drafts`),
|
||||
productionStatus(agent.id).catch(() => null),
|
||||
])
|
||||
const titles = new Map<number, string>()
|
||||
const items = new Map<number, PlanItem>()
|
||||
for (const plan of status?.plans ?? []) {
|
||||
for (const item of plan.items ?? []) if (item.run_id) titles.set(item.run_id, item.title)
|
||||
for (const item of plan.items ?? []) if (item.run_id) items.set(item.run_id, item)
|
||||
}
|
||||
// One run makes one result; its drafts are its parts (one, or the lesson + quiz of a SCORM module).
|
||||
const byRun = new Map<number, RawMaterial[]>()
|
||||
@@ -101,8 +107,8 @@ async function materialsOf(schedule: Schedule): Promise<Material[]> {
|
||||
const parts = group.map(g => ({ id: g.id, revision: g.revision, kind: g.output_kind, status: g.status }))
|
||||
return {
|
||||
id: d.id, agentId: agent.id, kind: kind === 'audio' || kind === 'scorm' ? kind : d.output_kind,
|
||||
status: combined(parts), revision: d.revision, parts,
|
||||
planTitle: titles.get(d.run_id) ?? null,
|
||||
status: withPlanItem(combined(parts), items.get(d.run_id)?.status), revision: d.revision, parts,
|
||||
planTitle: items.get(d.run_id)?.title ?? null,
|
||||
composeSetId: d.compose_set_id, sources: d.sources.map(s => s.title), createdAt: d.created_at, rule,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user