Commit Graph

101 Commits

Author SHA1 Message Date
Peter Steinberger d17bbfc31a feat(nodes): expose plugin duplex channels (#126961)
* feat(nodes): expose plugin duplex channels

* fix(nodes): enforce duplex declarations
2026-08-21 01:52:06 -07:00
Peter Steinberger 015913306f fix(nodes): preserve node inventory failures (#126609) 2026-08-20 02:06:09 -07:00
Peter Steinberger 341551937e fix(agents): preserve empty CLI subagent completions (#126379)
* fix(agents): preserve empty CLI subagent completions

* chore(qa): remove retired Matrix coverage leaf

* refactor: consolidate shared runtime ownership

* fix(scripts): keep runtime build coercion dependency-light

* chore: remove release-owned changelog entry
2026-08-19 11:30:43 -07:00
Peter Steinberger 6267703b30 refactor(canvas): share eligible node selection (#126374) 2026-08-19 10:51:02 -07:00
Peter Steinberger ae55a4090c refactor(canvas): make the panel a widget presenter (#126030)
* refactor(canvas): retire legacy host and commands

* refactor(apple): narrow shared Canvas contracts

* refactor(macos): keep Canvas as widget presenter

* refactor(ios): remove Canvas client

* refactor(android): remove Canvas client

* refactor(linux): remove Canvas client

* fix(ci): isolate native locale artifacts

* fix(linux): regenerate companion lockfile

* fix(canvas): refresh native tool display metadata

* test(canvas): align coverage with presenter surface

* test(canvas): remove obsolete asset root seam

* test(canvas): stabilize retirement CI coverage

* refactor(swift): remove orphaned resource wrapper

* test(ios): remove retired canvas layout assertion

* fix(macos): reserve retired canvas command namespace

* refactor(macos): isolate canvas command policy

* fix(canvas): select only eligible macOS panels

* fix(canvas): keep panel selection plugin-owned
2026-08-19 08:21:07 -07:00
Peter Steinberger 97557ec3f5 fix(widgets): route show_widget through Discord Activities (#126294)
* refactor(widgets): unify Discord presentation

* fix(discord): keep incomplete Activity routes private

* fix(discord): require usable Activity accounts

* docs(discord): clarify hidden Activity routes
2026-08-19 05:41:37 -07:00
Peter Steinberger 3378e07d50 refactor(plugin-sdk): promote shared runtime primitives (#126193)
* refactor(plugin-sdk): promote shared runtime primitives

* test(codex): keep one attempt tools owner
2026-08-19 01:10:18 -07:00
Peter Steinberger 6b68ffd3ab fix(canvas): present widgets atomically (#126039) 2026-08-18 15:08:17 -07:00
Peter Steinberger 3a96fbd64d feat(canvas): present widgets on native device panels (#125818)
* feat(canvas): present widgets on native panels

* refactor(agents): inline gateway caller selection

* fix(canvas): restrict widget panels to macOS

* refactor(agents): reuse resolved spawn workspace
2026-08-18 11:05:41 -07:00
Peter Steinberger 5f65ef8138 feat: add A2UI widgets to session boards (#125803)
* feat: add A2UI board widgets

* fix: harden A2UI board widget integration

* fix: repair A2UI CI contracts

* fix(canvas): keep native A2UI pushes on v0.8

* fix(canvas): support board-only widgets without file host
2026-08-18 09:08:45 -07:00
Peter Steinberger 5e964265fd fix(canvas): omit deleted snapshot paths (#125216)
* fix(canvas): omit deleted snapshot paths

* refactor(canvas): return pathless snapshot details
2026-08-17 04:18:01 -07:00
Peter Steinberger 90969ff41e fix: keep browser and Canvas tool results bounded and actionable (#125126)
* fix: bound browser and Canvas tool results

* fix: type host profile availability result

* fix: reuse Canvas snapshot format normalizer

* fix: preserve large Canvas snapshots

* fix(browser): bound captured network text

* fix: close tool result limit gaps

* fix: finalize tool result lifecycle bounds

* fix(canvas): narrow snapshot cleanup errors

* fix(canvas): bound final eval output

* fix: cap sanitized tool results
2026-08-17 03:43:45 -07:00
Peter Steinberger 620fcd0e27 refactor(plugins): make manifests own config ui hints (#121329) 2026-08-09 18:48:49 -07:00
zengLingbiao a466958d33 fix(canvas): serve Content-Length on A2UI HEAD responses (#117961)
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-08-06 18:58:09 -07:00
Peter Steinberger 2b3351a743 fix(browser): protect private observation media and Canvas trust boundaries (#118775)
* fix(browser): protect observation screenshots and Canvas trust boundaries

* test(canvas): preserve actual image helper result types
2026-08-03 11:33:27 -07:00
Peter Steinberger deb682abfe refactor(plugins): consolidate extension runtime helpers (#118509)
* refactor(plugins): consolidate extension runtime helpers

* fix(ci): satisfy extension type and lint checks

* chore(plugin-sdk): regenerate API baseline for #118509
2026-08-03 02:56:43 -07:00
Peter Steinberger 3edbe19fbd fix(canvas): remove unsupported snapshot delay hint (#117326)
Co-authored-by: Peter Steinberger <steipete@macos.shared>
2026-08-01 02:44:22 -07:00
Peter Steinberger 060a541c92 fix(canvas): honor paired-node invocation deadlines (#117316)
Co-authored-by: Peter Steinberger <steipete@macos.shared>
2026-08-01 02:40:19 -07:00
Peter Steinberger b0b708d919 fix(canvas): emit successful control results in JSON mode (#117297)
Co-authored-by: Peter Steinberger <steipete@macos.shared>
2026-08-01 01:28:41 -07:00
Peter Steinberger b0603cb443 refactor(fs): adopt shared safe filesystem primitives (#113596)
* refactor(fs): adopt fs-safe helpers

* fix(zalouser): keep stable per-profile QR temp path

* fix(fs): route adoption through owned facades
2026-07-25 03:24:19 -07:00
Peter Steinberger 756b6f7009 fix(release): repair plugin prerelease regressions (#113373) 2026-07-24 10:20:32 -07:00
sunlit-deng b73600b0cb fix(canvas): reject malformed snapshot base64 (#108987)
* fix(canvas): reject malformed snapshot base64

* refactor(canvas): reuse base64 canonicalizer

* fix(canvas): avoid control regex lint

* fix(canvas): allow base64 spaces

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-20 19:32:25 -07:00
Peter Steinberger 9710a1339e refactor(canvas): promote inline-widget hosting and show_widget to core (#110475)
* refactor(canvas): promote inline widgets to core

* docs(agents): note discord show_widget ownership at core registration

* ci: retrigger after GitHub scheduling outage

* fix(canvas): satisfy dead-code and test type checks
2026-07-18 14:40:45 +01:00
Peter Steinberger 241143262a fix(ci): script-only changes cold-start every Node job (#110158)
* fix(ci): keep sticky deps warm across script edits

* fix(ci): register dependency fingerprint entrypoint

* fix(ci): distinguish missing fingerprint inputs

* fix(ci): invalidate delegated workspace scripts

* fix(ci): harden cold install recovery

* fix(docs): escape release gate placeholder

* fix(ci): reject unaudited dependency hooks
2026-07-17 23:05:16 +01:00
Peter Steinberger 28a3540f32 feat: add native inline widget support (#109212)
* feat: add native inline widget support

* refactor: simplify plugin surface refresh

* fix: preserve plugin surface refresh API

* fix: reload widgets after WebKit termination

* fix: harden native widget refresh

* fix: bound native widget recovery

* docs: defer native widget release note

* chore: refresh native i18n inventory

* fix: harden native widget delivery

* refactor: simplify native widget API surface

* fix: serialize native widget capability refresh

* fix: harden native widget recovery

* fix: recover native widget capabilities

* style: format widget refresh role selection

* fix: correct widget refresh formatting

* fix: harden cross-platform widget recovery

* fix: bind widget trust and recovery to routes

* chore: refresh native i18n inventory

* chore: regenerate Android gateway protocol

* test: remove unused release workflow read
2026-07-16 19:24:41 -07:00
Peter Steinberger 093b8859c4 perf(test): fix env-dependent failures, stop verifier lazy-fetch, balance CI stripes (#109332)
* test: fix environment-dependent failures on built and partial-clone checkouts

Canvas A2UI fixtures now pin the resolved root through a new canvas
test-api hook: dev checkouts with a locally built a2ui.bundle.js won
candidate resolution and shadowed the fixture root. Speech-core prefs
tests resolve the canonical tmpdir (macOS /tmp symlink breaks fs-safe
store roots), and the bundled plugin install test asks discovery for
the canonical bundled path instead of hardcoding the source tree.

* fix(release): keep evidence verifier blob reads local-deterministic

git show against a forged or missing SHA lazily fetched from the
promisor remote on partial clones, hanging a security check on network
state (266s observed). GIT_NO_LAZY_FETCH pins verification to local
objects; missing blobs fail closed as before.

* perf(test): pay the command-handler barrel once and merge subagent command tests

commands-name and commands-login imported the full handler barrel
(~1,700 modules) for registration assertions; those now live in a
dedicated registration test, dropping the two files from 12.6s/4.6s to
1.4s/1.0s locally. Five subagent command test files merged into one so
the auto-reply module graph evaluates once instead of five times.

* perf(ci): stripe node test bins by measured file cost

Round-robin striping packed the whale files together, leaving
auto-reply-commands-1 at ~220s while sibling stripes idled at ~30s.
Greedy LPT over advisory per-file seconds hints balances the commands,
cli-runner, and tooling stripes deterministically; group hints for the
restriped bins are equalized at the old totals.
2026-07-16 13:38:56 -07:00
Peter Steinberger 16d1f487fe feat(widgets): unify show_widget across surfaces (#108983)
* feat(widgets): unify show_widget across surfaces

* docs(canvas): keep lazy show_widget descriptor in sync with the loaded tool
2026-07-16 05:24:11 -07:00
Peter Steinberger 2d9584ccda feat(canvas): interactive widgets can send follow-up prompts in web chat (#108889)
* feat(canvas): let widget buttons send prompts into web chat

Inline show_widget documents get a sendPrompt(text) bridge: a private
MessageChannel offered to the Control UI before widget code runs. The chat
adopts only the first offer per frame, requires transient user activation,
a visible focused frame, plain text (no slash commands), and rate limits
10 prompts/minute per widget. Accepted prompts run the normal user send
path of the owning chat pane.

* fix(canvas): appease lint/knip/docs gates for widget prompts

Split widget prompt tests into their own file, drive validation and rate
limits through the real port path instead of exported internals, use
addEventListener on the adopted port, and regenerate docs_map.

* fix(canvas): install widget listeners per window for non-isolated tests

Module-boolean listener flags broke in shared vitest workers where each test
file gets a fresh jsdom window; key installation by window instead and give
port flushing more headroom.
2026-07-16 04:52:26 -07:00
Peter Steinberger 05c2701e3d refactor(plugin-sdk): share widget HTML validation helpers (#108807)
* refactor(plugin-sdk): add widget HTML helpers

* refactor(plugins): share widget HTML validation
2026-07-16 03:13:29 -07:00
Peter Steinberger 5bbf30b852 refactor(canvas): remove internal A2UI handler factory (#108038)
* refactor(canvas): remove internal A2UI handler factory

* chore(deadcode): refresh export baseline
2026-07-14 22:41:27 -07:00
Peter Steinberger b363d5a293 feat(linux): canvas UI via CLI-node + Tauri app IPC bridge (#107633)
* feat(linux): canvas via CLI-node + Tauri app IPC bridge

* refactor: extract gateway helper modules

* build(linux-canvas): register plugin package in lockfile

* fix(linux-canvas): move canvas advertise test out of core, regen docs/protocol/deadcode

* fix(gateway): break node-catalog/registry import cycle via leaf normalize module; add canvas glossary term

* style: oxfmt invoke.ts and runtime.ts after buildNodeEventParams extraction

* fix(linux): load Canvas WebView via dedicated data_directory context

Wry's Linux/WebKitGTK incognito mode discards Tauri's registered
WebContext (wry webkitgtk/mod.rs), so the Canvas window got a fresh
ephemeral context without the openclaw-canvas:// scheme handler — the
bundled A2UI page never committed (stayed about:blank) and every A2UI
command timed out. Use an isolated cache-backed data_directory instead,
which keeps the protocol handler while still isolating Canvas storage
from the dashboard window.

* fix(linux): keep Canvas WebView ephemeral via incognito + data_directory

Autoreview flagged that a dedicated data_directory alone persists Canvas
browser state (cookies, localStorage, IndexedDB, service workers) across
restarts, so an agent that navigates Canvas to a site could leak an
authenticated session into a later session. iOS uses a non-persistent
store; Linux should match.

Add .incognito(true) alongside .data_directory(): the distinct directory
gives Tauri a fresh WebContext key so it still attaches the
openclaw-canvas:// protocol closure, and incognito makes Wry swap in a
fresh *ephemeral* context carrying those protocols. Live-verified on a
Wayland/WebKitGTK box: the bundled page still loads
(location.href=openclaw-canvas://localhost/index.html, openclawA2UI
present, A2UI renders) and the canvas-webview dir holds no persistent
cookie/storage files.
2026-07-14 16:05:14 -07:00
Peter Steinberger 7b9a72fc4f refactor(extensions): trim small plugin exports (#107784)
* refactor(workspaces): privatize internal plugin surfaces

* refactor(canvas): trim internal host exports

* refactor(qa-channel): privatize media URL validation

* refactor(google): remove web search test facade

* refactor(xai): remove response helper test facades

* chore(deadcode): shrink extension export baseline
2026-07-14 14:38:08 -07:00
Peter Steinberger 433656286d refactor(ws): use native socket contracts 2026-07-14 10:35:38 -07:00
Peter Steinberger b4128978cd refactor(canvas): use native websocket clients 2026-07-14 05:24:27 -07:00
Peter Steinberger eb169a3c87 refactor(canvas): use chokidar watch directly 2026-07-13 14:04:39 -07:00
Peter Steinberger b9f0246765 feat(plugin-sdk): add shared HTML escaping seam (#105975) 2026-07-12 22:33:53 -07:00
Peter Steinberger c6dc5bc764 fix(canvas): hosted pages fail on macOS with scoped Gateway auth (#105336)
* fix(canvas): harden hosted Canvas on macOS

Resolve Gateway-hosted Canvas and A2UI targets through refreshed node capabilities, keep bridge and live-reload behavior correct, and restrict native action dispatch to the exact trusted main-frame document.

Preserve scalar evaluation results, secure action IDs, and hidden state-directory watching.

Co-authored-by: GuoJiaming <804436395@qq.com>
Co-authored-by: Lucenx9 <185146821+Lucenx9@users.noreply.github.com>
Co-authored-by: zeng-weihan <ceng.weihan@xydigit.com>

* chore(canvas): defer release note

* chore(canvas): refresh native i18n inventory

* refactor(canvas): isolate hosted surface resolution

---------

Co-authored-by: GuoJiaming <804436395@qq.com>
Co-authored-by: Lucenx9 <185146821+Lucenx9@users.noreply.github.com>
Co-authored-by: zeng-weihan <ceng.weihan@xydigit.com>
2026-07-12 13:02:27 +01:00
Coy Geek 3ac83ddfca fix: Canvas WebSocket creation in browser context silently swallows... (#82505)
* fix(canvas): report live reload websocket errors

Surface WebSocket initialization failures from the injected canvas live reload client through console diagnostics, DOM attributes, and a browser event instead of silently swallowing them.

* refactor(canvas): keep reload diagnostics console-only

* fix(canvas): distinguish page teardown from socket failure

* style(canvas): brace pagehide listener

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-12 10:13:04 +01:00
Peter Steinberger 218dcd815a feat(tooling): enforce noUncheckedIndexedAccess in the extensions lane (NUIA phase 4) (#105132)
* 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.
2026-07-12 09:17:31 +01:00
qingminlong 5c77724ff8 fix(canvas): validate A2UI JSONL centrally (#103713) 2026-07-11 01:48:37 +01:00
Peter Steinberger 3ccf2a0739 feat: render inline web chat widgets via capability-gated show_widget tool (#101840)
Adds client-capability-gated tool availability: gateway clients declare
capabilities at connect (new inline-widgets cap), chat.send stamps them into
the run context, and every tool assembly path (embedded runner, queued
followups, Codex app-server harness, plugin-only construction plans) drops
tools whose requiredClientCaps the originating client did not declare. The
Canvas plugin ships the first such tool, show_widget: agents pass SVG or an
HTML fragment plus a title; the plugin hosts it as a bounded, retention-scoped
Canvas document and returns the existing canvas preview handle, which web chat
renders as a sandboxed iframe fitted to the widget's reported content height.
Widget frames never get allow-same-origin (per-preview sandbox ceiling,
including the sidebar path) and the Canvas host serves widget documents with a
CSP sandbox header so direct navigation runs in an opaque origin. Verified
live end-to-end on a Testbox with gpt-5.5 (screenshots on the PR). CLI-backed
model backends do not carry client caps yet and stay fail-closed (#102577).

Closes #101790
2026-07-09 12:29:50 +01:00
Vincent Koc 0c6bb026b2 refactor(deadcode): localize canvas declarations (#101915) 2026-07-07 16:49:22 -07:00
Vincent Koc 775ef966c3 refactor(deadcode): localize internal type aliases (#101243) 2026-07-06 17:57:32 -07:00
Vincent Koc 28a5b0a212 fix(canvas): guard native A2UI resources 2026-06-23 13:44:14 +08:00
Vincent Koc 493e418fa5 test(canvas): isolate A2UI host fixtures 2026-06-22 17:15:40 +08:00
Vincent Koc a89e65c167 fix(canvas): remove stale A2UI compatibility assets 2026-06-22 16:38:54 +08:00
Rohit e55cebf4c2 fix(canvas): validate CLI numeric options
Validate Canvas CLI numeric arguments before node invocation.

- Reject malformed `--invoke-timeout` values through the shared Canvas invoke path before resolving a node.
- Keep snapshot `--quality` bounded to the existing Canvas tool schema range of 0..1.
- Add focused CLI regressions for timeout validation, quality bounds, and accepted boundary values.

Verification:
- `node scripts/run-vitest.mjs extensions/canvas/src/cli.test.ts --maxWorkers=1`
- `.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/main ...`
- AWS Crabbox `cbx_b7838c58daba`, run `run_bbb58ca536f4`: `check:changed`
- Exact PR head `a970ce594ea6e7284ace519352fc258b1b81cb80`: GitHub checks green
2026-06-14 07:39:17 +08:00
Peter Steinberger 68222ba5e3 fix: harden websocket payload handling 2026-06-12 21:03:10 -07:00
Peter Steinberger 4fa5092cdc docs: document small extension sources 2026-06-04 21:02:07 -04:00
Peter Steinberger 4726aaa08c docs: document canvas plugin 2026-06-04 08:07:38 -04:00