The provider stream path interpolated the rejected SSE frame and its raw lines into the thrown error, so text the model had generated reached logs and the operator's error surface. The transport path already answers this exact condition with the shared MALFORMED_STREAMING_FRAGMENT_ERROR_MESSAGE and keeps the SyntaxError on cause, and the user-facing substitution in formatRawAssistantErrorForUi matches that constant exactly. Align the provider path with it so the same failure reads the same way on both paths. The error-event branch is left as is: its payload is parsed downstream to build a meaningful operator message, so redacting it would be a regression. Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
@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.