mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-29 00:46:40 +08:00
* refactor(server): share the host hook registration checks Move the misspelled-hook detection, the "did you mean" hint and the bound-once hook reads out of the persistence hooks registry into lib/server/host-hook-registration.ts, so another host hook registry can validate its registrations the same way. No behavior change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(generation): host hooks for server-side generation runs Add configureGenerationRunHooks, registered once from instrumentation.ts register() like the persistence hooks, for a host that meters usage, enforces a quota or keeps an audit trail around course generation: - authorizeStart: admits or refuses a start on POST /api/generation-runs and POST /api/generate-classroom, after every built-in check, inside the create transaction; a refusal answers with the host's status, code, message and headers, and no run is created. Attributes it returns are stored on the run (generation-runs migration 5, host_attributes JSONB). - wrapExecution: runs every claimed execution of a run (first claim, takeover, the claim after a Retry or an outline confirmation, media-only executions) and each background material extraction inside the host's context, with the run's stored attributes. A wrapper that refuses pauses the run at its step (Retry resumes it) or fails the extraction. - classifyFailure: maps a host error to a stable code and says whether an automatic retry is worthwhile; consulted before the step retries, the outline stream's retries, the model fallback, media failures and extraction failures. A non-retryable host failure pauses the run at the step; the AI SDK's own retries of a retryable provider status stop at it too (callLLM and streamLLM put every model they hand the SDK, v2 or v3, and any model a prepareStep picks, behind a gate that raises it again as not retryable; frozen models included), callLLM's own retries stop at it and throw it rather than an earlier invalid result, and an outline stream that fails with it is not accepted on its partial outlines. - onRunEvent: best-effort notifications after committed transitions (started, outline-ready, scene-appended, paused, completed, ended), in commit order within a process, each with the stored ownerId and the currentOwnerId the run was claimed into since (looked up for at most 5 s; at most 1000 notifications queue per process, newer ones dropped with a counted warning); never awaited, and a failing listener never affects the run. With nothing registered every path behaves as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>