* fix(xurl): use install kind "node" instead of invalid "npm" [AI]
The xurl skill's second installer declares kind "npm", which is not a
valid install kind. The installer switches on spec.kind with cases for
brew/node/go/uv/download and a default of "unsupported installer", so the
entry is dropped -- `openclaw skills info xurl` only offers the brew
option, leaving no install path on machines without Homebrew.
npm-backed installs use kind "node" (which honors
skills.install.nodeManager, default npm). Only kind is changed;
id/package/bins are left as-is.
Verified against openclaw 2026.6.11 in a container:
before (kind: npm): Install options: → Install xurl (brew)
after (kind: node): Install options: → Install @xdevplatform/xurl (npm)
* fix(github): drop non-functional "apt" install entry [AI]
The github skill's second installer declares kind "apt", which is not a
supported install kind (installer switch handles brew/node/go/uv/download
+ default "unsupported installer"). openclaw silently drops it -- `skills
info github` only ever surfaces the brew option -- so the entry is dead,
misleading metadata rather than a working Linux path.
The remaining brew installer is cross-platform (Homebrew runs on Linux),
so removing the dead entry loses no working path. Improving install paths
for Linux users without Homebrew is tracked separately in #57555
(needs-product-decision).
* fix: harden web fetch html conversion
* fix: consume malformed html tag tails
* fix: consume invalid html tag spans
* fix: preserve html scanner edge cases
* fix: preserve title-only html fallback
* fix: harden html scanner malformed tokens
* fix: close html scanner review gaps
* fix: keep malformed html raw text hidden
* fix: keep html scanner comment content hidden
* fix: skip unsupported html attribute values
* fix: skip raw text from opener end
* fix: drop malformed html tag tails
* fix: preserve trailing slash href links
* fix: close html scanner review gaps
* fix: preserve literal less-than text
* fix: bound html render context nesting
* fix: drop bogus html closing tags
* fix: handle abrupt html comments
* fix: remove dead html scanner branches
* fix: close quoted self-closing html tags
* fix: track anchor text incrementally
* fix: ignore quoted raw text markers
* fix: close title contexts through literal markup
* fix: close anchors through nested contexts
* fix: close nested HTML contexts consistently
* feat(secrets): resolve SecretRef model credentials at egress via process-local sentinels
SecretRef-managed model-provider credentials now travel as opaque
oc-sent-v1 sentinels through auth storage, stream options, and SDK
config; the guarded model fetch injects real values into headers and
URLs immediately before the SSRF-guarded send and fails closed on
unknown sentinels. packages/ai adapters converge on the host guarded
fetch where the SDK supports custom fetch and unwrap at construction
where it does not. Resolved values (and their percent-encoded forms)
register for exact-value log redaction. Kill switch:
OPENCLAW_SECRET_SENTINELS=off. Also fixes a pre-existing unhandled
rejection race in capNonOkResponseBodyLazily (pipeThrough writer leak).
* test(plugin-sdk): update public surface budget
The wrapper probes `crabbox --version` and `crabbox run --help` once each with a
snappy 5s timeout to enumerate providers before delegating. A cold Crabbox — the
first call right after a version bump, or one on a loaded machine — can exceed
that timeout while rendering `run --help` (52KB, emitted on stderr in 0.36) or
doing first-run init, and can emit nothing on that first call. When that happens
both guards fire and hard-exit the wrapper ("selected binary failed basic
--version/--help sanity checks" or "could not parse provider list from --help;
refusing to run"), which blocks ALL remote validation (`pnpm check:changed`,
remote `pnpm test` lanes) even though the binary is fine.
Retry each metadata probe once with a generous 20s timeout when the first attempt
is killed or returns empty. The warm path is unchanged (one ~instant probe); only
a slow/empty first probe pays for the retry, after which the sanity/provider-list
guards judge the recovered result. Add a regression test: a fake Crabbox whose
`run --help` is slower than the default probe timeout (and, like 0.36, writes help
to stderr) is now recovered by the retry instead of hard-failing.
* fix(state): close cached SQLite state and agent databases on process exit
* refactor(state): pair SQLite exit-close with cache lifecycle and rebind stale proxy-capture stores
* fix(cli): register debug-proxy finalize before the state DB exit hook
* refactor(state): narrow to agent-db and proxy-capture exit lifecycle after #100691 landed shared-state close
---------
Co-authored-by: Alex Knight <15041791+amknight@users.noreply.github.com>