Commit Graph

78807 Commits

Author SHA1 Message Date
Peter Steinberger c5a52f10bb style(gateway): format portal method-order assertions
Rebase union-merge left the portal.list assertion wrapped; oxfmt fits it
on one line.
2026-08-12 20:44:12 -07:00
Peter Steinberger aaba4e2e45 chore(protocol): regenerate portal models 2026-08-12 20:44:12 -07:00
Peter Steinberger d762bdefb4 docs(gateway): clarify portals PORT/PUBLIC_URL are agent-set
Opening a portal creates only the proxy listener; the agent sets PORT
and PUBLIC_URL in its own exec command, matching the portal tool
contract. Removes the implication of an automatic env handoff.
2026-08-12 20:44:12 -07:00
Peter Steinberger 283b58cbc8 fix(gateway): type portal open credentials 2026-08-12 20:44:12 -07:00
Peter Steinberger 1efa308d0b docs(web): list the portals route 2026-08-12 20:44:12 -07:00
Peter Steinberger cb77c5424c fix(gateway): scope portal token URLs to write-capable clients
The portal bearer token rides in the summary url/tokenQuery; portal.list
is operator.read and portal.changed fans out to read subscribers, so a
read-only client could harvest an openable URL. Make those fields
optional, redact them from read-scope list responses, and drop them from
every portal.changed broadcast; write/admin clients still receive them
and the UI refetches the list on change.
2026-08-12 20:44:12 -07:00
Peter Steinberger 5b5bbeda5d fix(gateway): namespace portal auth cookies by listener 2026-08-12 20:44:12 -07:00
Peter Steinberger 0fbf31915f chore(protocol): regenerate after rebase 2026-08-12 20:44:12 -07:00
Peter Steinberger 4d7514c60b test(gateway): provide control UI request hosts 2026-08-12 20:44:11 -07:00
Peter Steinberger 1b18bd7f5b test(ui): satisfy portal reachability lint 2026-08-12 20:44:11 -07:00
Peter Steinberger 82db963623 fix(ui): detect unreachable portals behind proxied gateways
Probe the portal origin from the browser (no-cors, 4s timeout) and show
a recovery notice with the gateway-host URL instead of a dead iframe
when only the gateway port is exposed (Serve/Funnel/reverse proxy).
Docs: cookie isolation + reachability; zh-CN glossary entry.
2026-08-12 20:44:11 -07:00
Peter Steinberger 069a8466a4 fix(gateway): isolate portal cookie jars per target
Cookies are hostname-scoped, not port-scoped, so the per-port origin
split alone let Gateway plugin-auth cookies reach agent-run targets.
Forward only cookies carrying this portal's own name prefix (stripped),
rewrite target Set-Cookie names to the prefixed form incl. the WS 101
handshake, and drop Domain attributes.
2026-08-12 20:44:11 -07:00
Peter Steinberger a4a50f973a fix: satisfy portal integration gates 2026-08-12 20:44:11 -07:00
Peter Steinberger eeb41d2b47 fix(gateway): type portal dual-stack connection 2026-08-12 20:44:11 -07:00
Peter Steinberger 5343d8ec56 fix(gateway): dial portal targets via localhost dual-stack
Vite and other Node >=17 dev servers bind ::1 only for localhost, so a
fixed 127.0.0.1 dial 502s on the default path. Use hostname localhost
with family autoselection and rewrite Host to match.
2026-08-12 20:44:11 -07:00
Peter Steinberger e54be90291 docs(gateway): add portals guide 2026-08-12 20:44:11 -07:00
Peter Steinberger 1e63928ad0 feat(ui): add portals page 2026-08-12 20:44:11 -07:00
Peter Steinberger 2a1839f4c5 fix(gateway): export portal protocol types 2026-08-12 20:44:11 -07:00
Peter Steinberger ad0c06790d refactor(protocol): compact portal schema exports 2026-08-12 20:44:11 -07:00
Peter Steinberger d802bc8d6e test(gateway): narrow websocket payload types 2026-08-12 20:44:11 -07:00
Peter Steinberger d82b712ba0 test(gateway): satisfy portal proxy lint 2026-08-12 20:44:11 -07:00
Peter Steinberger 191bffc5c1 fix(gateway): declare portal transport service 2026-08-12 20:44:11 -07:00
Peter Steinberger 753e17aebb refactor(gateway): keep portal helper types private 2026-08-12 20:44:11 -07:00
Peter Steinberger b7a0d957fa fix(gateway): refine portal URL and proxy auth 2026-08-12 20:44:11 -07:00
Peter Steinberger e388364430 feat(agents): add portal tool 2026-08-12 20:44:11 -07:00
Peter Steinberger d306ef65a4 feat(gateway): add portal service and reverse proxy 2026-08-12 20:44:11 -07:00
Peter Steinberger fa00d1fd0b feat(protocol): add portal methods and event
Bump the reviewed protocol owner-module count from 55 to 56.
2026-08-12 20:44:11 -07:00
Peter Steinberger c61ee511ab fix(onboard): allow imports after runtime scaffolding (#122967) 2026-08-12 20:41:36 -07:00
Peter Steinberger d2628e430c fix(cli): avoid restart hint for unchanged config (#122953)
* fix(cli): avoid restart hint for unchanged config

* docs(cli): clarify no-op restart guidance
2026-08-12 20:40:30 -07:00
PIYUSH RATHORE 6cfc05ae2f fix(projects): avoid stale GitHub results after token rotation (#122613)
* fix(projects): avoid stale GitHub results after token rotation

* fix(gateway): scope GitHub caches by credential

* style(gateway): format GitHub credential scope

---------

Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-12 20:39:30 -07:00
Peter Steinberger 4d54c3f1a1 refactor(config): retire dead streaming.progress.render key (#122927)
* refactor(config): retire dead streaming.progress.render key

The key had zero runtime consumers after #122552. Core doctor now strips it via stripRetiredTuningKnobs, and production LOC is net -13.

* fix(tooling): pin plugin SDK surface counts to the reduced export set

The retired progress-draft render reader counted twice via channel-outbound and channel-message's wildcard re-export.
2026-08-12 20:36:40 -07:00
Peter Steinberger 5db09954c7 fix(wizard): honor gateway overrides in manual flow (#122961) 2026-08-12 20:34:00 -07:00
Josh Avant 705f043e04 fix(qa): isolate staged auth state (#122958) 2026-08-12 22:30:46 -05:00
Peter Steinberger ffb2ed9e89 refactor: remove residual normalization aliases (#122956)
* refactor: remove residual normalization aliases

* test(gateway): isolate approval authority handshake
2026-08-12 20:26:30 -07:00
Peter Steinberger 061c9c2f7f fix(ai): honor embedded transport policy (#122946) 2026-08-12 20:20:18 -07:00
Feng 7dbe21b9cf fix(agents): hydrate CLI images from agent workspaces (#122684)
* fix(agents): hydrate CLI images from agent workspace

* fix(agents): preserve resolved CLI workspace owner

* fix(agents): keep workspace owner in prepared params

* fix(agents): resolve CLI owner before preparation

* fix(agents): preserve CLI runtime policy owner

---------

Co-authored-by: Adkid-Zephyr <169631528+Adkid-Zephyr@users.noreply.github.com>
Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-12 20:18:15 -07:00
Josh Lehman edb941a508 oc-e35: restore explicit multi-agent UI ownership (#122889) 2026-08-13 03:17:13 +00:00
Vyctor H. Brzezowski aba94bbe0b fix: install or review the publisher you picked when ClawHub skills share a slug (#121697)
* fix(skills): keep ClawHub publisher identity from search through install

ClawHub search returns one entry per publisher, so several results can share a
slug. Every client collapsed the selection to that bare slug before calling
skills.detail and skills.install, and ClawHub answered 409 AMBIGUOUS_SKILL_SLUG
with no in-product way forward.

searchClawHubSkills now records the publisher-qualified reference once, on the
result that carries it, and the Gateway protocol documents it. skills.detail
parses the same reference grammar skills.install already accepted, so review and
install cannot resolve to different publishers. Control UI carries that one
reference through row actions, detail, busy state, and acknowledgement retries,
and shows it so otherwise identical rows are distinguishable.

Fixes #117633

* fix(apps): send the ClawHub publisher reference from native skill browsers

macOS, iOS, and Android read the qualified reference from search results and use
it for skills.detail, install, busy state, installed matching, and list identity,
so two publishers sharing a slug stay distinct instead of collapsing into one
ambiguous request.

* fix(skills): refuse external-source skill detail instead of reading a same-slug skill

ClawHub has no source-qualified read endpoint, so a skills-sh reference parsed
down to its bare slug would have returned a registry skill's card while install
resolved the external artifact. Review and install could name different skills.

skills.detail now fails closed on any reference that carries a source, and the
macOS and AgentPro rows show the publisher reference next to the summary instead
of only when a summary is missing, so same-slug rows stay distinguishable.

* chore(apps): refresh native i18n source baseline for the skill row references

* refactor(skills): drop the unread search-result ownerHandle field

installRef is the one reference clients send back, and no client reads the
publisher handle separately, so the protocol and Control UI carry one field
instead of two.

* fix(skills): name the next step when external skill detail is refused

Clients that gate install behind a successful review would otherwise see only a
refusal, so the error names the direct install path and the CLI equivalent.

* fix(macos): use a doc comment on the ClawHub row subtitle

swift-format's docComments rule requires doc comments on declarations; the
subtitle property carried a regular comment and failed macos-swift.

* fix(skills): carry ClawHub trust state to clients that can install

Forwarding installRef let clients install the exact publisher the operator
picked, including external skills-sh sources. It did not forward the trust
state that says ClawHub never scanned that source, so iOS AgentPro — the one
surface that installs in a single tap with no review step — could install an
unscanned artifact with nothing on screen saying so. The CLI already labels
these (docs/clawhub/cli.md, docs/cli/skills.md); native clients could not,
because trustState was never on the wire.

trustState becomes an optional field on SkillsSearchResultSchema. It is purely
additive: older clients ignore an unknown key and the field is absent for
registry results, so downgraded readers are unaffected and no protocol version
moves.

Every client that renders a search row now shows "Not scanned by ClawHub",
matching the CLI wording exactly: iOS AgentPro in the row above the install
button, macOS and Android beside the review action, and Control UI on the row
that explains why review is refused for these sources.

Covered by a wire assertion that the state reaches clients for an external
source and stays absent for registry rows, plus decode-and-label tests on the
shared Swift kit and the Android parser, and a Control UI render assertion.

* fix(ui): size the ClawHub detail dialog to a refusal message

Refusing detail for an external source made an error-only dialog reachable.
The shared preview panel reserves a tall reader height for skill documents, so
a two-line refusal rendered in a mostly empty dialog and read as broken rather
than deliberate. Found by inspecting the review captures.

* revert(ui,apps): drop the ClawHub trust label layer

Maintainer product decision: skills.sh runs its own scanners, so OpenClaw does
not add a second alert layer in the apps. Removes the label from Control UI,
iOS, macOS and Android, and drops the trustState wire field that nothing would
render. The CLI keeps its existing label; changing that is a separate call.

Publisher identity, the fail-closed detail refusal, and the message-only dialog
are unchanged. Splits the oversized skills view test file to satisfy max-lines
without a suppression.

* test(ui): fix ClawHub skill fixture checks

* chore(plugin-sdk): refresh API baseline

---------

Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-12 20:13:15 -07:00
Peter Steinberger f5ad8735d1 feat(ui): open subagent details in chat sidebar (#122941)
* feat(ui): open subagent details in chat sidebar

* chore: drop changelog edit (release generation owns it)

* refactor(ui): drop duplicate close in subagent detail panel

The sidebar region header already owns a Close Details control in both
wide and narrow layouts; the panel-local X duplicated it 40px away.

* fix(ui): stop subagent transcript loader when pane presentation retires

Pane retention wipes sidebarContent directly, so the detail slot's
render-time reset can never run again; a pending refresh timer plus
incoming task events kept refetching chat.history for a hidden panel.

* docs(ui): note close-control ownership in subagent detail header

* fix(ui): break transcript renderer import cycle

* fix(ui): use shared action cursor for subagent rows
2026-08-12 20:11:13 -07:00
Peter Steinberger 132299bcfa fix(gateway): allow downloading zero-byte artifacts (#122928)
* fix(gateway): preserve zero-byte artifacts

* fix(gateway): keep non-string data out of artifact lists

* test(gateway): compact zero-byte artifact coverage
2026-08-12 20:09:32 -07:00
Peter Steinberger 495f295f25 feat(ui): split new session place picker (#122938)
* feat(ui): split new session place picker

* test(ui): cover three-chip session picker
2026-08-12 20:09:27 -07:00
Colin Johnson ae20e2c163 fix(ui): model picker shifts when another user starts typing (#122809)
* fix(ui): keep composer model picker stable while typing

* test(ui): prove typing keeps model picker stable

Co-authored-by: Colin Johnson <colin@solvely.net>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-08-12 20:08:45 -07:00
Masato Hoshino 4c12c973ed fix(sessions): highWaterBytes 0 no longer deletes all session history (#119909)
* fix(sessions): zero highWaterBytes no longer clears all session history

resolveHighWaterBytes passed an explicit non-positive highWaterBytes through
verbatim. The resolved value is the disk-budget cleanup loop's stop condition,
so a zero target made enforce mode evict every unprotected session and prune
its extracted archives instead of trimming to the documented 80% default.

Route the non-positive case to the function's existing unusable-value branch
(computeDefault). Not null: that disables the budget and permits unbounded
growth, which is right for a cap but wrong for a target.

Sibling of #119422, which fixed the same harm for maxDiskBytes and guarded
only resolveMaxDiskBytes.

* test(infra): isolate worktree migration discovery

Keep worktree migration coverage focused on its real filesystem, Git, and SQLite owner while avoiding unrelated channel and plugin doctor cold starts on fork CI.

Co-authored-by: masatohoshino <g515hoshino@gmail.com>

* test(ci): carry owner-approved SDK and doctor gate repairs

Carry the already-approved plugin SDK contract manifest and focused doctor-flow test isolation from the maintainer-owned CI repair. Preserve real config migration, persistence, snapshot, and SQLite cleanup coverage; no production behavior changes.

Co-authored-by: masatohoshino <g515hoshino@gmail.com>

* fix(sessions): use the renamed withTestDir helper in the new budget test

* fix(sessions): align high-water zero contract

* style(sessions): format high-water changes

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-12 20:05:46 -07:00
Chinmay Rawat 1e19f22dbd fix: prompt caching breaks on Claude Opus 5 and Sonnet 5 (#121283)
* fix: prompt caching breaks on Claude Opus 5 and Sonnet 5

shouldPreserveThinkingBlocks() matched modern Claude ids with a hardcoded
family list plus /claude-[5-9]/ future-proofing. That regex assumes the
generation follows the prefix (claude-5-x), but shipped generation-5 ids
place the family in between (claude-opus-5, claude-sonnet-5, claude-mythos-5),
so none matched and dropThinkingBlocks flipped to true. Signed thinking blocks
were stripped from replayed history, diverging every request and invalidating
the Anthropic prompt cache on the default opus/sonnet aliases.

Read the generation from the id instead, preserving blocks for generation 4
and newer. This handles both id shapes and matches the idiom already used in
audit-extra.sync.ts and live-model-filter.ts.

Closes #121251

* fix: correct Claude thinking replay contract

Use the canonical Claude model identity and exact Anthropic preservation contract when deciding whether replay may retain prior thinking blocks. Carry deployment metadata through provider-family and fallback paths, and include canonicalModelId in the transcript policy cache key.

Release note: Restore prompt-cache reuse for Claude Opus 5 and Sonnet 5 while continuing to strip unsupported Sonnet and Haiku 4.5 thinking history.

* refactor: remove unused replay compatibility helper

Use the canonical Claude drop predicate at the remaining test call sites and remove the unconsumed preservation export so the dependency/dead-code gate stays clean.

* fix: keep Claude replay contract internal

Use canonical llm-core identity resolution without exporting a new llm-core capability, avoiding unintended Plugin SDK API drift.

---------

Co-authored-by: FullerStackDev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-08-12 20:05:16 -07:00
Peter Steinberger 812bbd8884 docs(deploy): add verification, cost, observability, and troubleshooting to the Cloudflare guide (#122932)
The template shipped without the operator-facing half: no way to prove the
restore path works before depending on it, no cost signal for the always-on
versus webhook-only choice, no log surfaces, and no failure-mode index.

Adds an architecture diagram, a restore rehearsal, measured recovery numbers
from the real-R2 proof, provisioned-resource cost guidance, wrangler tail
observability, and a troubleshooting index covering image architecture,
Litestream S3 credentials, the startupz/readyz split, and ephemeral-disk
config loss.
2026-08-12 20:00:09 -07:00
Peter Steinberger c401f8a1a9 fix(ui): fence stale recovery scope work (#122944) 2026-08-12 19:59:30 -07:00
Peter Steinberger 08f9c3a5cb test(extensions): remove duplicate runtime replays (#122949) 2026-08-12 19:58:04 -07:00
Peter Steinberger 93d93d1d14 perf(test): cut workflow guard import overhead (#122940)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-12 19:55:45 -07:00
Peter Steinberger a1c091fb1b test(gateway): stabilize sender avatar fixture (#122942) 2026-08-12 19:54:40 -07:00
Peter Steinberger cad7e7f9e1 fix: session model selection replaced by response aliases and fallback wins (#122910)
* fix(agents): keep session model selection canonical

Preserve configured session model identity across response aliases and turn-local fallbacks.

* fix(gateway): align session model projection consumers

* test(gateway): mark session event model selection
2026-08-12 19:46:56 -07:00