(ctx: RunContext, finalWaitStates?: Record<string, WaitState>)
| 346 | } |
| 347 | |
| 348 | const finalize = (ctx: RunContext, finalWaitStates?: Record<string, WaitState>): void => { |
| 349 | // Prefer the mesh of the last branch the user actually ran — it's already in the |
| 350 | // viewer, and topo order must not override the user's last action. |
| 351 | let outputUrl: string | undefined = ctx.lastSceneMesh |
| 352 | let outputPath: string | undefined |
| 353 | |
| 354 | const lastOutputNode = outputUrl ? undefined : [...ctx.ordered].reverse().find((n) => isSceneOutput(n.type)) |
| 355 | if (lastOutputNode) { |
| 356 | for (const edge of ctx.workflow.edges.filter((e) => e.target === lastOutputNode.id)) { |
| 357 | const src = ctx.nodeOutputs.get(edge.source) |
| 358 | if (src?.filePath) { |
| 359 | const norm = src.filePath.replace(/\\/g, '/') |
| 360 | if (norm.startsWith(ctx.workspaceDir)) { |
| 361 | outputUrl = `/workspace/${norm.slice(ctx.workspaceDir.length).replace(/^\//, '')}` |
| 362 | } |
| 363 | } |
| 364 | } |
| 365 | } |
| 366 | if (!outputUrl) { |
| 367 | for (const [, o] of ctx.nodeOutputs) { |
| 368 | if (o.filePath) { |
| 369 | const norm = o.filePath.replace(/\\/g, '/') |
| 370 | if (norm.startsWith(ctx.workspaceDir)) { |
| 371 | outputUrl = `/workspace/${norm.slice(ctx.workspaceDir.length).replace(/^\//, '')}` |
| 372 | } else { |
| 373 | outputPath = o.filePath |
| 374 | } |
| 375 | } |
| 376 | } |
| 377 | } |
| 378 | |
| 379 | set((s) => ({ |
| 380 | activeNodeId: null, |
| 381 | runningBranchId: null, |
| 382 | waitStates: finalWaitStates ?? s.waitStates, |
| 383 | nodeImageOutputs: collectImageOutputs(ctx), |
| 384 | runState: { |
| 385 | status: 'done', |
| 386 | blockIndex: 0, |
| 387 | blockTotal: 0, |
| 388 | blockProgress: 100, |
| 389 | blockStep: 'Done', |
| 390 | outputUrl, |
| 391 | outputPath, |
| 392 | }, |
| 393 | })) |
| 394 | useAppStore.getState().updateCurrentJob({ status: 'done', progress: 100, outputUrl }) |
| 395 | } |
| 396 | |
| 397 | return { |
| 398 | runState: IDLE, |
no test coverage detected