Files
openclaw/packages/ai
Peter Steinberger 5ebbc3c003 fix(agents): keep stalled turns visible after Responses streams settle (#120426)
* fix(agents): keep stalled turns visible after Responses streams settle

A bare-continue turn in live QA (goal-followthrough-live, gpt-5.4 via
openai-responses) completed its SSE requests and then produced no terminal
result, delivery, timeout, or error for 6+ minutes until SIGTERM. Root cause:
turn liveness is enforced only while awaiting provider stream events (llm-idle
watchdog); queued subscription handlers are fire-and-forget during the turn and
finalize joined them unbounded and un-abortable, backed only by the 48h default
run budget. One hung delivery handler silently dead-ended the whole turn.

- Bound the pending-events join in attempt-stream-finalize with a 120s liveness
  deadline plus the run-abort signal; on expiry, warn with the runId and proceed
  to settlement so the run always yields a visible terminal outcome.
- Responses transports now report every SSE event via notifyLlmRequestActivity
  (parity with completions/anthropic), so bookkeeping-only events keep the idle
  watchdog quiet instead of counting as network silence.

* fix(agents): bound the settlement block-reply flush with the shared liveness join

ClawSweeper P1 on #120426: after the finalize-phase join times out, settlement
still awaited onBlockReplyFlush on the same wedged delivery chain (unbounded on
the supported blockReplyTimeoutMs: 0 path). Generalize the bounded join into
joinWithRunLivenessDeadline in run/abortable.ts (owner of abort/liveness
racing) and use it for both the pending-events join and the settle flush;
timeout and abort resolve with a recorded warning so the turn always reaches a
visible terminal outcome. New coverage: helper tests (hang, abort, rejection)
and a real-settle-path regression holding the flush past the deadline.
2026-08-08 12:34:23 -07:00
..

@openclaw/ai

Reusable model API contracts, provider adapters, and streaming primitives from OpenClaw. The package supports isolated runtime instances; importing it does not register providers globally.

import { createLlmRuntime } from "@openclaw/ai";
import { registerBuiltInApiProviders } from "@openclaw/ai/providers";

const runtime = createLlmRuntime();
registerBuiltInApiProviders(runtime.registry);

Provider-neutral contracts, validation, diagnostics, and event streams are available from the package root and focused subpaths such as @openclaw/ai/event-stream, @openclaw/ai/transports, and @openclaw/ai/validation. No second OpenClaw runtime package is required.

Provider ids, credentials, model catalogs, retries, and failover remain application concerns. OpenClaw supplies those policies around this package. Host policy (request fetch guarding, secret redaction, strict-tool defaults, provider plugin hooks, and diagnostics logging) can be injected with configureAiTransportHost; the defaults are inert.

The explicit @openclaw/ai/internal/anthropic, openai, retry-after, runtime, and shared subpaths exist for the OpenClaw application itself. They carry no semver guarantee and can change or disappear in any release; do not depend on them outside OpenClaw.