-
feat(task): give polling hooks a real query context, host HTTP classification,… · 9df450fe
feat(task): give polling hooks a real query context, host HTTP classification, and bounded poll failures Plugin polling hooks previously ran against a hollow context: parseTaskResult and parseBatchResult received {} / nil, buildQueryRequest received a {task_id, action} map under the misleading name requestBody, and batch hooks saw only bare task ids. The per-task poller also never looked at the upstream HTTP status, and every built-in plugin papered over unrecognized bodies with `|| "IN_PROGRESS"`, so a 404, a revoked key, or a shape the plugin did not know would sit in IN_PROGRESS for the full 24h TASK_TIMEOUT_MINUTES while holding the user's pre-charged quota. Contract (docs/plugin-api v1.d.ts, v1.md, v1.schema.json): - TaskQueryContext is declared separately from DriverContext and rebuilt from the persisted Task row: taskId, publicTaskId, action, model, upstreamModel, baseUrl, apiKey, authHeader, auth, data, state. Query-side requestBody is removed; the original request is not persisted and hooks that need a request-derived value must save it into state at submit time. - parseTaskResult / parseBatchResult receive a third {status, headers} argument. Batch hooks receive tasks[] with one TaskQueryContext per task. - NormalizedTaskResult accepts status "UNKNOWN" meaning "I do not recognize this body". Falling back to IN_PROGRESS for unknown shapes is forbidden; `plugin lint` warns on the literal. - parseSubmitResponse / parseTaskResult / parseBatchResult may return `state`. Task.Data remains a per-round snapshot overwritten on every valid parse; state is plugin-owned, persisted in TaskPrivateData.PluginState, preserved when a hook omits it, byte-capped like taskData, and never exposed through presenter views. Host (service/task_polling.go, relay/channel/task/jsplugin/adaptor.go): - TaskPollingAdaptor / BatchTaskPollingAdaptor take *model.Task and the *http.Response so the adaptor can build the full context; jsplugin is the only implementation. - HTTP classification before the plugin sees the body: 2xx -> plugin; 404/410 -> FAILURE and refund; 401/403 -> poll failure plus a channel-scoped warning, no auto-disable; 429/5xx/transport -> poll failure; other 4xx -> plugin with the status visible, counted as unrecognized if the plugin still reports a non-terminal state. - TaskPrivateData.PollFailures counts consecutive poll failures (transient HTTP, auth, transport, hook error, UNKNOWN). It is persisted through the existing UpdateWithStatus CAS so a concurrent terminal transition on another instance is never clobbered, and reset on any valid 2xx non-terminal parse. Reaching TASK_POLL_MAX_FAILURES (default 20, <= 0 disables) fails the task with the last classification and HTTP code in fail_reason and runs the existing settle/refund chain exactly once. sweepTimedOutTasks and its 1440-minute default are unchanged as the outer backstop. - Unrecognized bodies are logged at WARN with a bounded redacted copy since Task.Data is intentionally not overwritten on that path. Plugins (all ten bumped one patch version): - jimeng persists the outbound req_key in state and reads it back in buildQueryRequest, replacing dead reads of ctx.data / ctx.requestBody that never resolved. - sunoapi batch hooks read tasks[] instead of the removed requestBody. - hailuo treats base_resp.status_code != 0 as FAILURE before the status table. - kling, vidu, sora, alibaba, doubao, hailuo, jimeng return UNKNOWN with the raw upstream status in reason on table miss. - google and vertex-ai treat a missing `done` as in-progress: Google long-running operations omit proto3 default fields, so a running Veo operation has no `done` key at all. Only a body without an operation name is UNKNOWN. plugins/veo_poll_test.go locks this so the poll-failure cutoff can never fail a rendering Veo task. Tests cover the classification table end to end against a real DB (404 immediate refund, 429xN refund, 401 increments without status change, 2xx reset, UNKNOWN increments, state preserved vs replaced, PollFailures survives the CAS write), the query-context shape, UNKNOWN on unrecognized bodies, and the absence of PluginState/PollFailures from TaskView. Controller tests derive the kling factory version from the embedded manifest instead of hardcoding it.CaIon committed
| Name |
Last commit
|
Last Update |
|---|---|---|
| .. | ||
| tasks | Loading commit data... | |
| .oxfmtrc.json | Loading commit data... | |
| .oxlintrc.json | Loading commit data... | |
| alibaba_responses_test.go | Loading commit data... | |
| builtin_plugins_test.go | Loading commit data... | |
| doubao_responses_test.go | Loading commit data... | |
| embed.go | Loading commit data... | |
| google_responses_test.go | Loading commit data... | |
| hailuo_responses_test.go | Loading commit data... | |
| jimeng_responses_test.go | Loading commit data... | |
| kling_responses_test.go | Loading commit data... | |
| sora_responses_test.go | Loading commit data... | |
| sunoapi_responses_test.go | Loading commit data... | |
| veo_poll_test.go | Loading commit data... | |
| vertex_ai_responses_test.go | Loading commit data... | |
| video_responses_test_helpers_test.go | Loading commit data... | |
| vidu_responses_test.go | Loading commit data... |