* fix(extensions): make indexed access explicit across channel plugins
Transport-payload-safe burn-down: malformed Telegram/Discord/QQ/LINE
and sibling channel input keeps existing skip paths; no synthesized
fields, no new throws in delivery loops. Zalo escape sentinels preserve
literal matches instead of undefined replacements.
* fix(extensions): make indexed access explicit across provider and memory plugins
Stream and model iteration, tool-block guards, capture guards, and
sparse accumulators; singleton model reads carry named invariants.
* fix(extensions): make indexed access explicit across tooling plugins, flip the extensions lane
Remaining plugins (oc-path, qa-lab, browser, logbook, and siblings) plus
the tsconfig.extensions.json flag flip. Cleanup: logbook sampleFrames
NaN index at max=1, QA retry clamp at non-positive attempts, dead Canvas
probe and OpenShell no-op slice removed, twitch test setup leak excluded
from the prod lane.
* refactor(plugin-sdk): expose expectDefined via a focused SDK subpath
Extensions imported @openclaw/normalization-core directly, crossing the
external-plugin packaging boundary (it only worked because the runtime
builder bundles undeclared workspace helpers). expect-runtime joins the
canonical entrypoints JSON, generated exports, API baseline, docs, and
subpath contract test; all 78 extension imports now use the SDK seam.
Two scanner-shaped locals renamed for review-bundle hygiene.
* chore(plugin-sdk): raise surface budgets for the expect-runtime subpath
One new entrypoint with one callable export, added intentionally as the
packaging-honest seam for extension invariant helpers.
* fix(opencode-go): remove deprecated mimo-v2-omni and mimo-v2-pro model aliases
These deprecated aliases reject agent requests from the OpenCode Go gateway.
Remove them from the provider catalog and clean up all references in probe
skip lists, CI workflows, and tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(opencode-go): complete deprecated MiMo cleanup
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(opencode-go): re-arm idle timer on block-boundary events to prevent false stalled-stream abort
When the opencode-go model finalizes a tool call and deliberates before
the next one, the provider emits real block-boundary SSE events
(text_end, thinking_end, toolcall_start, toolcall_end) that prove the
socket is alive, but the watchdog's isProviderProgressEvent only
returned true for token deltas (text_delta, thinking_delta,
toolcall_delta). This caused the idle timer to fire and falsely abort a
live stream, replacing a completed answer with a stalled error and
dropping the provider's real done event.
Fix: include block-boundary events in isProviderProgressEvent so the
idle timer is re-armed on any forward-progress provider event.
text_start and thinking_start are intentionally excluded because they
are synthetic preamble events that should not shorten the first-event
window.
Closes#96518
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* test(opencode-go): satisfy lint in stream regression
* test(opencode-go): satisfy lint in stream regression
* test(opencode-go): satisfy lint in stream regression
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* chore(release): close out 2026.6.10 on main
* chore(release): align native app metadata for 2026.6.10
* chore(release): sync Android 2026.6.10 notes
* docs(changelog): preserve 2026.6.9 history
* docs(changelog): preserve 2026.6.9 history
* fix(opencode-go): abort stalled SSE streams at provider-owned raw boundary
opencode-go routes through the shared OpenAI-compatible completions provider,
where a stalled SSE socket (provider emits tokens then never closes the stream)
hangs the gateway until stuckSessionAbortMs (~622s) and surfaces as
'LLM request failed' / 'Request was aborted'. Issue #93610 reports ~90% of
opencode-go cron jobs failing intermittently this way.
Add a provider-owned stream wrapper at the opencode-go raw SSE boundary that
injects an AbortController into the underlying OpenAI SDK request and aborts
it after a configurable idle window (default 30s, far below 622s) elapses
without any forward-progress event. The wrapper is:
- Provider-scoped: only applies when model.provider === 'opencode-go'; the
shared openai-completions.ts path is untouched.
- Abortable: calls controller.abort() on the injected AbortSignal, which
propagates through OpenAI SDK requestOptions.signal and genuinely
interrupts the underlying fetch/stream (not just iterator return()).
- Idle-based: every event (text/tool/thinking delta, including delayed
usage-only chunks) refreshes the timer; natural completion (done/error)
cancels it. Normal delayed usage-only completion is preserved.
- Boundary-terminal: pushes a terminal { type: 'error', reason: 'aborted' }
event downstream so consumers do not hang.
TDD: stream-termination.test.ts covers (a) stalled stream after first
progress is aborted within the idle window with a downstream 'aborted'
terminal event, and (b) normal delayed completion within the idle window
is not aborted and the done event is forwarded unchanged.
* fix(opencode-go): align stalled-stream idle default with runtime (120s)
Match the runtime's shared `DEFAULT_LLM_IDLE_TIMEOUT_MS` (120s) so
non-cron interactive opencode-go runs see no behavior change versus the
existing watchdog. Cron runs — for which the runtime disables its idle
watchdog entirely (`resolveLlmIdleTimeoutMs` returns 0 when trigger is
cron and no explicit timeout is set) — still get provider-owned
termination well before the ~622s stuck-session recovery.
Refs #93610
* fix(opencode-go): satisfy CI lint and test type checks
- Remove unnecessary `?? {}` fallback in spread (oxlint
no-useless-fallback-in-spread).
- Drop non-narrowing `!` on the wrapper return type; use
`await Promise.resolve(...)` to collapse the
`StreamLike | Promise<StreamLike>` union before `for await`.
Refs #93610
* fix(opencode-go): arm stalled-stream idle timer only after first event
The wrapper armed the idle timer before the first upstream event, which
would mis-abort slow time-to-first-byte requests — including the
opencode-go cron runs that the runtime deliberately leaves uncapped via
resolveLlmIdleTimeoutMs. Arm only after the first forwarded event, and
add regression coverage for the slow-first-event path.
* fix(opencode-go): cover stalled stream first event
* fix(opencode-go): respect explicit stream timeout
* fix(opencode-go): preserve first-event timer after synthetic start
* fix(opencode-go): satisfy stream termination test lint
* fix(opencode-go): distinguish synthetic stream preambles
* fix(opencode-go): route stalled streams through failover
Register OpenCode Go's provider-owned static catalog so lifecycle cache warmup supplies the correct context window to memory flush and compaction without persisting catalog rows in user config.
Fixes#92912.
Co-authored-by: kumaxs <45620232+kumaxs@users.noreply.github.com>
Bumps OpenClaw release metadata to 2026.5.31 across package manifests, app version files, plugin metadata, changelog headings, and generated shrinkwraps.
Verification:
- pnpm plugins:sync:check
- pnpm ios:version:check
- pnpm deps:shrinkwrap:check
- git diff --check
- stale 2026.5.30/build-code scan across changed files
- autoreview clean: no accepted/actionable findings
- PR CI green for real gates: Checks, security scans, dependency guard, app lanes, real behavior proof
Known non-code workflow issue:
- label workflow failed because this PR hits GitHub's 100-label issue cap before the size-label step.