Commit Graph

81223 Commits

Author SHA1 Message Date
Vincent Koc 4b400b1f30 fix(release): keep plugin scanner fail-slow 2026-08-20 23:41:42 -07:00
Vincent Koc a9d0e6d230 fix(release): bound plugin artifact downloads 2026-08-20 22:42:32 -07:00
Vincent Koc 18152738ce chore(release): leave changelog to release prep 2026-08-20 22:42:32 -07:00
Vincent Koc a313476fa2 fix(release): keep prerelease scanner supplemental 2026-08-20 22:42:31 -07:00
Vincent Koc 60ab3c666e docs(testing): define plugin scanner trust boundary 2026-08-20 22:42:31 -07:00
Vincent Koc dd9677012a fix(release): scan publication-equivalent plugin artifacts 2026-08-20 22:42:31 -07:00
Vincent Koc dc15c4f660 fix(release): keep plugin security packing inert 2026-08-20 22:42:31 -07:00
Vincent Koc bf65391b7e test(release): make scanner timeout fixture portable 2026-08-20 22:42:31 -07:00
Vincent Koc 0fecd2ec46 fix(release): scan immutable plugin artifacts 2026-08-20 22:42:31 -07:00
Vincent Koc f33ee89256 fix(release): isolate plugin pack enumeration 2026-08-20 22:42:31 -07:00
Vincent Koc 60c029367f fix(release): fail slow in plugin security scan 2026-08-20 22:42:31 -07:00
Vincent Koc ddd2bfc39c fix(release): bound plugin security scanning 2026-08-20 22:42:31 -07:00
Vincent Koc e88d3410eb fix(release): harden trusted plugin scan 2026-08-20 22:42:31 -07:00
Vincent Koc 412ee3b783 fix(release): isolate plugin security scanner 2026-08-20 22:42:31 -07:00
Peter Steinberger bed80ee645 fix(cron): reject malformed condition scripts before saving (#127004)
* fix(cron): reject malformed condition triggers

Validate newly authored cron condition scripts before persistence, return actionable Gateway errors, and preserve maintenance of malformed triggers shipped in existing releases.

* fix(cron): reject blank condition triggers
2026-08-20 22:42:06 -07:00
Vyctor H. Brzezowski 6c667989a8 fix(ui): soften active split-pane indication (#126714)
* fix(ui): soften active split-pane indication

* fix(ui): scope split-pane attenuation to split layout

* fix(ui): refine split-pane visual hierarchy

* test(ui): establish active split pane in visual proof

* test(ui): activate split pane through its header

* style(ui): format split-pane selectors

* fix(ui): preserve inactive split-pane controls

* fix(ui): finalize inactive split-pane styling

* fix(ui): preserve inactive split-pane actions

* Revert "fix(ui): preserve inactive split-pane actions"

This reverts commit 2cadd21346.

* fix(ui): keep inactive split-pane status visible

* fix(ui): restore approved split-pane treatment

* fix(ui): keep inactive placement status visible
2026-08-21 02:41:32 -03:00
Peter Steinberger 2753351abe fix(cli): reject onboarding flags on recommendation leaves (#126973)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 22:37:21 -07:00
Peter Steinberger 95b2cd77e8 fix(agents): point a missing API key at an auth command, not at agent creation (#127011)
The generic provider-missing-auth error told operators to create a new agent:

    No API key found for provider "openai". Auth store: <path> (agentDir: <path>).
    Configure auth for this agent (openclaw agents add <id>) or copy only portable
    static auth profiles from the main agentDir.

`openclaw agents add <id>` creates an agent. It does nothing about a missing
provider credential, so following it leaves you with a second agent that also
has no key.

Reproduced on a real build: a fresh install with only an Anthropic key, then
`openclaw memory index`. There is exactly one configured agent, `main`, and it is
correctly configured -- nothing about `agents add` applies. Doctor, diagnosing the
identical condition on the same install, gets it right, listing how to supply the
key and how to disable memory search. The command that actually failed gave worse
advice than the advisory check.

`models auth paste-api-key --provider <id>` is the suggestion rather than
`models auth login`, because `login` requires an owning provider plugin while this
generic fallback is also reached for pluginless, inline, and custom providers, and
for a plugin-owned provider that returns no specialized message. Pasting a key
resolves every "No API key found" case the fallback can produce. The `--agent`
hint is folded in for non-default agents, and `formatCliCommand` keeps the command
correct under a profile or container.

One message rather than two: distinguishing "no credential anywhere" from "this
agent lacks a profile another agent has" would need cross-agent store reads the
resolver does not do today, and the combined sentence is correct for both.

Production +1/-1.
2026-08-20 22:35:51 -07:00
Peter Steinberger 9a64770ea6 fix(macos): unblock remote onboarding after local Gateway failure (#127033) 2026-08-20 22:32:36 -07:00
Peter Steinberger 0a377a5b53 fix(tui): clear stale session display names (#127029) 2026-08-20 22:32:01 -07:00
Peter Steinberger 7efc077abe test(onboard): follow canonical secret-ref storage (#126965)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 22:31:14 -07:00
Peter Steinberger e7cfff2167 feat(control-ui): stream live draft previews in the typing indicator (#126994)
* feat(control-ui): stream live draft previews in the typing indicator

Multi-identity sessions now show what a teammate is typing, not just that
they are typing: the composer's per-keystroke session.typing sends carry a
bounded tail of the draft (optional preview field, 400 code points max),
the gateway throttle re-emits on changed payloads at 250ms (boolean-only
stays at 1s, trailing edge keeps the latest draft), and the transcript
renders a per-actor bubble with the live text plus a blinking caret.
Actors without preview data keep the three-dot bubble.

Previews are ephemeral presence: never persisted, never part of the
session transcript or model context, excluded from aria-live regions, and
gated by the existing >=2-live-viewers, sharing-role, and incognito
checks. No new config surface.

* chore(protocol): regenerate Swift gateway models for typing preview

* fix(gateway): aggregate typing previews across same-actor connections

A boolean-only session.typing update from a second connection of the same
actor (another tab or device) erased their live draft preview, because
typing liveness aggregated per actor while the broadcast preview came only
from the latest request. Preview aggregation now lives with the connection
aggregation owner: updateTypingConnections tracks per-connection previews
and returns the newest non-empty preview among live connections, so the
broadcast keeps the active draft until its connection stops or expires.

Regression fails pre-fix (event lost its preview field).
2026-08-20 22:30:41 -07:00
Peter Steinberger 5c9b734ac2 perf(channels): coalesce typing starts (#127006)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 22:30:20 -07:00
Peter Steinberger 6f52e9fc2f fix(telegram): preserve direct-message topics in config and cron writeback (#127010)
* fix(telegram): preserve direct message topics in target writeback

* test(ui): consolidate cron scheduler status coverage
2026-08-20 22:27:10 -07:00
Peter Steinberger 57a2677c3c fix(cli): render skills JSON failures (#127016) 2026-08-20 22:23:52 -07:00
Peter Steinberger 3cf33583db perf(test): speed up lazy UI lifecycle polling (#127025) 2026-08-20 22:22:58 -07:00
Peter Steinberger b6c5d84e5e fix(onboard): reject local gateway credentials in remote mode (#127015) 2026-08-20 22:22:16 -07:00
Peter Steinberger cfc93e1738 fix: reject stale session replacements after ownership changes (#127027) 2026-08-20 22:21:30 -07:00
Peter Steinberger 5de08664ac improve(ui): skip discarded workspace loading during first-run setup (#126967)
* perf(ui): defer workspace loading during first-run setup

Wait for the initial model-setup decision before starting the default Chat router, and load workspace chrome only when a workspace route is visible.

Keep the existing loading mascot visible while the Gateway decides the first-run destination.

Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-76a1-76f1-8758-25d0466913af

* fix(ui): release first-run gate on terminal connect failure

Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-76a1-76f1-8758-25d0466913af

* fix(ui): dedupe sidebar lazy preload

Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-76a1-76f1-8758-25d0466913af

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 22:20:12 -07:00
Bek 76bb7ff2b6 fix(skills): omit content hashes from prompts (#126951) 2026-08-21 01:13:42 -04:00
Peter Steinberger df8fedcc00 fix(macos): isolate profiles and report direct Gateway failures (#127007)
* fix(macos): isolate named-profile development project roots

* fix(macos): report actual direct gateway connection failures

* fix(macos): satisfy SwiftLint remote recovery line limit

* fix(macos): sync native IPv6 endpoint localization inventory

* fix(macos): keep IPv6 endpoint formatting out of localization inventory
2026-08-20 22:08:01 -07:00
Peter Steinberger da18d2f335 test(ui): split the oversized cron view suite to unbreak main (#127018)
`main` is red: `check-lint-core-5` fails with

    ui/src/pages/cron/view.test.ts
      1124:4  error  File has too many lines (1004).  eslint(max-lines)

The file has been growing for a while (1104 lines at fa75cdd01c, 1116 at
2acfc47b7f) and crossed the 1000 code-line cap at a4b3f63a87 (#126945). Every
PR opened since inherits the failure, so this is not any one PR's fault to fix
in passing -- it blocks the merge gate for everyone.

Repo policy forbids a `max-lines` suppression, so the file is split along the
seam it already had: three top-level describes, one of which was two thirds of
the file. `cron view editor` moves to `view.editor.test.ts`; `cron view list
pane` and `cron view selects` stay in `view.test.ts`. The four DOM helpers the
blocks shared move into the existing `view.test-support.ts` sibling rather than
being duplicated, and each file imports only what it uses.

No test content changed: 42 tests before, 42 after, same 41 `it(` declarations.
Sizes drop to 373 / 721 / 143 lines, all well under the cap.
2026-08-20 22:06:18 -07:00
sinner 1fb4857e3c fix(cron): reject blank/invalid --webhook before delivery.mode flip (#121533)
* fix(cron): reject blank/invalid --webhook before delivery.mode flip

Presence-only typeof checks treated empty or non-http --webhook as a
delivery edit, forging mode=webhook with no URL and clearing the prior
chat destination on merge. Validate with normalizeHttpWebhookUrl first.

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* test(cron): cover webhook validation boundaries

Amp-Thread-ID: https://ampcode.com/threads/T-01a0220d-eaa0-76b4-adb9-68841f015b75

---------

Co-authored-by: zyw02 <zyw02@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:52:30 -07:00
Peter Steinberger 4ba2c46cc4 fix(qa): own container first-run onboarding journey (#126981)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:47:44 -07:00
Goutam Adwant 2b190b2122 fix(doctor): migrate markerless multi-agent rosters (#126595) 2026-08-20 21:44:05 -07:00
Peter Steinberger 2e1b882845 fix(doctor): report degraded gateway secret owners (#126998) 2026-08-20 21:43:45 -07:00
sinner 9bc772ba50 fix(cron): mutex blank --model/--thinking with matching clear flags (#119894)
* fix(cron): reject blank --model/--thinking on cron edit

Empty Commander values skipped the clear-* mutex after normalize, so
--model '' --clear-model still cleared the override. Align with fallbacks
and delivery clear presence checks.

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* test(cron): align empty model/thinking edit expectation with blank reject

The legacy cron-cli suite still expected blank --model/--thinking to be omitted; that contradicts the fail-closed blank validation and broke CI.

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* fix(cron): mutex blank --model/--thinking with matching clear flags

Standalone blank overrides stay omitted. Flag presence now conflicts with
--clear-model/--clear-thinking instead of silently applying the clear.

Co-authored-by: Peter Steinberger <steipete@gmail.com>

* test(cron): focus blank clear mutex coverage

Amp-Thread-ID: https://ampcode.com/threads/T-01a0220d-eaa0-76b4-adb9-68841f015b75

---------

Co-authored-by: zyw02 <zyw02@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:41:30 -07:00
Peter Steinberger 371f8ce80f fix(skills): point a ClawHub miss at search, not at the local skill list (#126987)
`openclaw skills install <slug>` and `skills verify <slug>` both answered a
ClawHub 404 with:

    Skill "nonexistent-skill-xyz" not found. Run `openclaw skills list` to see available skills.

ClawHub is saying the slug is not in the registry. `skills list` lists the skills
already installed locally, so it cannot resolve a registry miss -- the operator
is sent to look at what they already have when they were trying to acquire
something new. `skills search` exists for exactly this and is one line away in
`skills --help`.

The sibling gets this right, which is what makes it a defect rather than a
preference: `plugins install <unknown>` answers with "Run `openclaw plugins
list` to see installed plugins, or `openclaw plugins search <name>` to look for
installable plugins."

The 404 branch now names ClawHub as the source of the miss and suggests
`skills search <slug>`. It also routes through `formatCliCommand` like the rest
of the file's sibling messages, so the suggestion stays correct under `--profile`
or `--container`; the hardcoded string did not.

The local-lookup message in `skills-cli.format.ts` is unchanged: there
`skills list` is the right answer, because that path is looking for a skill the
operator should already have.

Production +4/-1.
2026-08-20 21:40:59 -07:00
Peter Steinberger 9737026237 improve(agents): avoid repeated model suppression planning (#126982)
* perf(agents): cache model suppression by generation

* test(agents): narrow model suppression spies

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:40:44 -07:00
Peter Steinberger 3186e22382 fix(doctor): name the unreadable state database instead of dying on a SQLite string (#126985)
Doctor is the designated repair owner and nearly every CLI failure footer in this
product ends with `Try: openclaw doctor`. With a corrupt shared state database it
produced this, and nothing else:

    ┌  OpenClaw doctor
    database disk image is malformed

No path. No indication of which database. No next step. `doctor --fix` printed
the identical two lines and repaired nothing, `OPENCLAW_DEBUG=1` added nothing,
and the standard `Reason:`/`Debug:`/`Try:` envelope never appeared. The operator
was in a closed loop: every command told them to run doctor, and doctor told
them a SQLite string with no object attached to it.

Corrupt the agent database instead and doctor already does the right thing --
names the file, names the reason, warns visibly, completes the full run, exits 0.
Same corruption class, two databases, opposite treatment.

The mechanism: `assertDoctorDatabaseSchemasCompatible` read
`preflightOpenClawDatabaseSchemas` and inspected only `incompatible`, silently
discarding `indeterminate`, which is exactly where an unreadable shared database
is recorded with its path and reason already populated. Doctor then proceeded and
died deeper with the context stripped, at
`src/infra/sqlite-readonly-location.ts:428` by way of state ownership inspection
and the config preflight.

Doctor now consumes that dropped signal and stops with a diagnosis that names the
file, the reason, what it deliberately did not do, and how to recover. It stops
rather than continuing like the agent-database path because shared state owns
write admission and holds the persisted plugin index the health context is built
from; disabling migrations still fails on that index, so continuing would mean a
bespoke degraded doctor. It does not recreate the database: that file holds auth
profiles among other things, so silent rebuild is data loss.

Also fixes an adjacent leak found in the same investigation: `io.load.ts` passed
a raw `Error` to the logger, so `doctor --session-sqlite inspect` printed a stack
trace with absolute `dist/*.js` frames without `OPENCLAW_DEBUG=1`, contradicting
the CLI's own debug-gating convention. It now logs formatted message text.

`doctor --lint` exiting 1 while bare `doctor --json` exits 0 was investigated and
left alone: commit 6e5bf3ec55 established that advisory JSON exit behavior
deliberately, and register.maintenance.test.ts covers it.

Production +11/-1.
2026-08-20 21:38:28 -07:00
Ayaan Zaidi 1aa211be4a fix(qa): make Mantis backfills reliable (#126980)
Preserve honest blocked proof outcomes and publish visible stop-reports without marking them passed. Serialize burst runs through the authoritative Telegram-user lease while reserving time for proof and cleanup.
2026-08-21 10:01:58 +05:30
Peter Steinberger a4b3f63a87 fix(ui): use active scheduler trigger capability (#126945)
Control UI automation trigger authoring now reflects the running scheduler across unsaved and saved-but-unapplied config edits and reconnects.
2026-08-20 21:28:44 -07:00
EricCai aea1ca60e6 fix(doctor): fail closed on newer cron schema (#115447)
Amp-Thread-ID: https://ampcode.com/threads/T-01a0220e-399b-73e8-8e77-a1d872a68848

Co-authored-by: EricCai <287630876+ericcaiwx-star@users.noreply.github.com>
2026-08-20 21:21:28 -07:00
Dallin Romney 997af9c02d fix(release): keep packed SDK smoke on public types (#126992) 2026-08-20 21:21:20 -07:00
Peter Steinberger 747a49e7a7 fix(cli): reject invalid gateway status timeouts (#126977)
Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:13:48 -07:00
Peter Steinberger 9be871245b fix(channels): answer the channel question, and stop calling ECONNREFUSED an auth failure (#126984)
Two defects in one command, both on the path a brand-new operator is on
immediately after `openclaw onboard`.

`channels status` never mentioned channels when none were configured. With the
gateway up it printed `Gateway reachable.` and a tip about `status --deep`;
without it, two blank lines where the channel list belongs. The operator asked
for the status of their channels and got gateway reachability. Its siblings
already handle this -- `channels list` prints `- no configured chat channels
(run \`openclaw channels list --all\` to see installable channels)` and
`openclaw status` prints `No channels configured` -- so `channels status` was
the lone holdout. Both renderers now emit that same line, moved to a shared
constant so the three surfaces cannot drift apart again.

The second is worse because it sends the operator somewhere wrong. The fallback
computed `gatewayAuthUnavailable = expectedError || isGatewaySecretRefUnavailableError(err)`,
and `isExpectedCliError` returns true for `isGatewayTransportError` -- a plain
ECONNREFUSED. So a gateway that simply was not running reported `Gateway auth
unavailable; showing config-only status.`, contradicting the `Gateway not
reachable at ws://... (ECONNREFUSED)` line printed three lines above it. Someone
who runs `channels status` before starting the gateway went hunting for a token
problem that did not exist. The flag now consults only the two genuinely
auth-related predicates; `expectedError` keeps its separate job of selecting the
canonical CLI failure output.

`isGatewayCredentialsCliError` becomes exported for that check. The JSON shape is
unchanged; only the truth of `gatewayAuthUnavailable` changes, and no test or
documented contract depended on transport errors setting it.

Production +27/-9.
2026-08-20 21:12:33 -07:00
Peter Steinberger 2acfc47b7f fix(ui): expose all automation schedule filters (#126962)
* fix(ui): expose all automation schedule filters

Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b

* refactor(ui): derive cron filters from protocol

Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 21:10:49 -07:00
Bek e2a48d4b70 fix(cron): prune terminal task history after seven days (#126095) 2026-08-21 00:10:11 -04:00
Peter Steinberger 46dcc57c54 fix(cli): reject an unconfigured --agent across every operator selector (#126983)
`skills` (#126954) turned out to be one instance of a class. Two more surfaces
accepted an agent id that names nothing, and one of them wrote it to disk:

- `sandbox explain --agent nope-agent` exited 0 and printed a complete policy
  report, including `Elevated: enabled: true` and a workspace root that does
  not exist, for an agent `openclaw agents list` does not know.
- `approvals allowlist add "<pattern>" --agent nope-agent` exited 0, printed
  `Writing local approvals.`, and persisted the entry under a key nothing will
  ever read. The operator believes they approved an exec pattern; nothing was
  approved. This is the severe one: a false record of an approval.

Sweeping `option("--agent"` across the CLI found the rest. Each hit was
classified as a selector (names the thing operated on, must validate) or a
filter (narrows a list, may legitimately return empty). Selectors now route the
explicit value through `resolveConfiguredAgentId`, the helper that already backs
`models`, `memory`, `sessions list`, `hooks`, and every capability surface:
`channels resolve`, `sessions export-trajectory`, `sessions archive/delete`,
`backup enable`, `backup git create`, `backup sqlite create`. Blank-only guards
close the empty-shell-variable hole in `hooks`, `sessions` list/cleanup/tail/
compact, `migrate`, and agent turns.

Filters are deliberately unchanged: `audit`, `usage-cost`, agent bindings,
`backup verify/restore`, and `sandbox recreate` all match existing records and
correctly report no matches. Cron is gateway-owned and already rejects an
unavailable agent server-side; it is untouched.

`sessions archive/delete` was not silent -- it failed with `Session not found.
Run openclaw sessions list --agent ghost --json to choose a valid key.` But that
suggested command itself exits 1 with `Unknown agent id "ghost"`, so the
remediation handed to the operator could not run. Validating locally, exactly as
`sessions list` already does, keeps the hint runnable without adding a roster
round-trip to the gateway.

Production +140/-38.
2026-08-20 21:08:38 -07:00
Peter Steinberger 514d148519 fix(qa): reject skipped-only confidence lanes (#126975) 2026-08-20 21:01:38 -07:00