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.
| Name |
Last commit
|
Last Update |
|---|---|---|
| .. | ||
| audit.go | Loading commit data... | |
| auth_flow_test.go | Loading commit data... | |
| auth_session.go | Loading commit data... | |
| auth_session_test.go | Loading commit data... | |
| authz.go | Loading commit data... | |
| billing.go | Loading commit data... | |
| billing_option_test.go | Loading commit data... | |
| channel-billing.go | Loading commit data... | |
| channel-test.go | Loading commit data... | |
| channel.go | Loading commit data... | |
| channel_affinity_cache.go | Loading commit data... | |
| channel_authz.go | Loading commit data... | |
| channel_authz_test.go | Loading commit data... | |
| channel_pin_retry_test.go | Loading commit data... | |
| channel_task_plugin_bind_test.go | Loading commit data... | |
| channel_task_plugin_validation_test.go | Loading commit data... | |
| channel_test_internal_test.go | Loading commit data... | |
| channel_upstream_update.go | Loading commit data... | |
| channel_upstream_update_test.go | Loading commit data... | |
| checkin.go | Loading commit data... | |
| codex_usage.go | Loading commit data... | |
| custom_oauth.go | Loading commit data... | |
| deployment.go | Loading commit data... | |
| group.go | Loading commit data... | |
| image.go | Loading commit data... | |
| log.go | Loading commit data... | |
| midjourney.go | Loading commit data... | |
| misc.go | Loading commit data... | |
| misc_oidc_test.go | Loading commit data... | |
| missing_models.go | Loading commit data... | |
| model.go | Loading commit data... | |
| model_list_test.go | Loading commit data... | |
| model_meta.go | Loading commit data... | |
| model_owned_by_test.go | Loading commit data... | |
| model_sync.go | Loading commit data... | |
| oauth.go | Loading commit data... | |
| option.go | Loading commit data... | |
| option_claude_test.go | Loading commit data... | |
| option_gemini_test.go | Loading commit data... | |
| passkey.go | Loading commit data... | |
| passkey_test.go | Loading commit data... | |
| payment_compliance.go | Loading commit data... | |
| payment_webhook_availability.go | Loading commit data... | |
| payment_webhook_availability_test.go | Loading commit data... | |
| perf_metrics.go | Loading commit data... | |
| performance.go | Loading commit data... | |
| playground.go | Loading commit data... | |
| plugin_endpoint_test.go | Loading commit data... | |
| plugin_native_e2e_test.go | Loading commit data... | |
| plugin_protocol.go | Loading commit data... | |
| plugin_protocol_limiter.go | Loading commit data... | |
| plugin_protocol_limiter_test.go | Loading commit data... | |
| plugin_protocol_sdk_test.go | Loading commit data... | |
| plugin_protocol_test.go | Loading commit data... | |
| prefill_group.go | Loading commit data... | |
| pricing.go | Loading commit data... | |
| rankings.go | Loading commit data... | |
| ratio_config.go | Loading commit data... | |
| ratio_sync.go | Loading commit data... | |
| redemption.go | Loading commit data... | |
| relay.go | Loading commit data... | |
| relay_count_tokens_test.go | Loading commit data... | |
| relay_error_log_test.go | Loading commit data... | |
| relay_task_plugin_test.go | Loading commit data... | |
| return_path.go | Loading commit data... | |
| return_path_test.go | Loading commit data... | |
| revalidated_response.go | Loading commit data... | |
| secure_verification.go | Loading commit data... | |
| setup.go | Loading commit data... | |
| subscription.go | Loading commit data... | |
| subscription_payment_creem.go | Loading commit data... | |
| subscription_payment_epay.go | Loading commit data... | |
| subscription_payment_stripe.go | Loading commit data... | |
| subscription_payment_waffo_pancake.go | Loading commit data... | |
| system_info.go | Loading commit data... | |
| system_task.go | Loading commit data... | |
| system_task_handlers.go | Loading commit data... | |
| task.go | Loading commit data... | |
| task_generic_test.go | Loading commit data... | |
| task_log_view_test.go | Loading commit data... | |
| task_plugin.go | Loading commit data... | |
| task_plugin_debug.go | Loading commit data... | |
| task_plugin_debug_test.go | Loading commit data... | |
| task_plugin_test.go | Loading commit data... | |
| telegram.go | Loading commit data... | |
| telegram_test.go | Loading commit data... | |
| theme_compat_test.go | Loading commit data... | |
| token.go | Loading commit data... | |
| token_auto_groups_test.go | Loading commit data... | |
| token_test.go | Loading commit data... | |
| topup.go | Loading commit data... | |
| topup_creem.go | Loading commit data... | |
| topup_quota_limit_test.go | Loading commit data... | |
| topup_stripe.go | Loading commit data... | |
| topup_waffo.go | Loading commit data... | |
| topup_waffo_pancake.go | Loading commit data... | |
| topup_waffo_pancake_test.go | Loading commit data... | |
| twofa.go | Loading commit data... | |
| uptime_kuma.go | Loading commit data... | |
| usedata.go | Loading commit data... | |
| usedata_flow_test.go | Loading commit data... | |
| user.go | Loading commit data... | |
| user_manage_test.go | Loading commit data... | |
| vendor_meta.go | Loading commit data... | |
| video_proxy.go | Loading commit data... | |
| wechat.go | Loading commit data... |