Commit Graph

81244 Commits

Author SHA1 Message Date
Amp 5053cb1252 fix(node-host): share skill-bin refreshes 2026-08-21 08:30:51 +00:00
parthjayaram a049fe8c9b fix(cron): count isolated setup as execution progress (#93914)
Amp-Thread-ID: https://ampcode.com/threads/T-01a0220e-0046-742a-bdd8-2883b9305619

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: Cadbury <cadbury@localclaw.local>
2026-08-21 00:58:30 -07:00
Peter Steinberger c7b216edef fix(cron): use selected account for CLI announce delivery (#126995)
* fix(cron): preserve CLI delivery account

Amp-Thread-ID: https://ampcode.com/threads/T-01a02218-35bb-715b-b40d-f918b943bbb7

* test(cron): prove CLI account-bound message sends

Amp-Thread-ID: https://ampcode.com/threads/T-01a02218-35bb-715b-b40d-f918b943bbb7

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-21 00:46:18 -07:00
Peter Steinberger 76af07b735 fix(onboard): redact gateway health failures (#127071)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-21 00:43:16 -07:00
Peter Steinberger 8ac7dd254c perf(test): speed up model provider page observation polling (#127085) 2026-08-21 00:40:36 -07:00
Peter Steinberger 58127fa73e fix(agents): remove a deleted agent's cron jobs on the offline delete path (#127075)
* fix(agents): remove a deleted agent's cron jobs on the offline delete path

Follow-up to #127037, which fixed the exec-approvals half of the same gap and
named this one explicitly.

`agents delete` tries the Gateway first and falls back to a local path. The
Gateway handler nests two transactional cleanups around the roster commit --
cron wrapping approvals wrapping the config write. After #127037 the offline
path did the inner one; it still skipped cron. So deleting an agent without a
Gateway left its scheduled jobs enabled:

    $ openclaw agents delete cronprobe --force
    Deleted agent: cronprobe            <- no mention of cron
    $ sqlite3 <state>/state/openclaw.sqlite "select job_id, name, agent_id, enabled from cron_jobs"
    975cb750-... | cronprobe-job | cronprobe | 1
    $ openclaw cron list
    cronprobe-job   every 1h   Next: in 59m   idle

To be accurate about severity: this is not silent. Each firing records
`error: "cron job agent is unavailable: cronprobe"` and `cron list` flips to
`error`. The defect is that the job keeps its schedule forever, and that
recreating an agent with the same id points it at the new agent.

The fallback had collapsed two different reasons into one `null` return, which
is what made the fix look unsafe at first: credential failures happen *before*
transport, so a live scheduler may still own the cron store, while an
unreachable Gateway means nothing else is holding it. `maybeDeleteAgentThroughGateway`
now returns a discriminated union, and only the unreachable branch mutates the
store directly. The credentials branch commits the roster, warns, and sets
`cronCleanupSkipped: true` in JSON.

The local `CronService` construction already existed inside
`local-request-context.ts`; it moves to `src/cron/local-service.ts` and both
callers share it rather than growing a second cron mutation path. That
extraction also switches the default-owner resolver from
`tryResolveLegacyCompatibilityAgentId` to `tryResolveAmbientOwnerAgentId`, which
is a superset -- it honors an explicitly configured
`agents.defaults.systemAgent.agentId` and otherwise falls back to exactly the
previous function. Live testing showed agentless memory-dreaming jobs need it to
load under explicit agent ownership.

Production +89/-62.

* test(agents): split the delete suite so the new cron coverage stays under the cap

The 40-line cron regression test added in the previous commit pushed
`src/commands/agents.delete.test.ts` to 1018 code lines, over the 1000 cap, and
`check-lint-core-3` went red. Repo policy forbids a `max-lines` suppression.

Unlike the earlier `cron/view.test.ts` split there was no describe-level seam --
23 flat tests in a single describe -- so the split follows subject instead. The
seven workspace-lifecycle tests (trashing, sharing, overlap, symlink reachability,
workspace-state cleanup) move to `agents.delete.workspace.test.ts`.

`vi.mock` and `vi.hoisted` are per-file and cannot be imported, so the mock
preamble and the shared `beforeEach` are declared in both files; the helper block
above them is unchanged in each. Each file then imports only what it uses, which
is why the import lists differ.

Trimming to a hair under the cap by moving only the new test was possible and
rejected: it would have left the file at ~978 code lines, back at the cap within
a couple of changes. This leaves 749 and 603 physical lines.

No test content changed: 27 passed before, 27 after.
2026-08-21 00:31:17 -07:00
Vincent Koc fa86caf94f fix(release): keep protected tooling trusted after main moves (#126881)
* fix(release): keep protected tooling trusted after main moves

* fix(release): cover protected tooling recovery paths

* fix(release): honor live tooling contracts

* fix(release): revalidate tooling at npm publish

* fix(release): bind npm publishers to live tooling

* fix(release): preserve trusted dispatch identity

* fix(release): revalidate parent authorization

* fix(release): bind ClawHub to release parent

* docs(release): define frozen tooling identity

* test(release): align ClawHub protected dispatch ref

* fix(release): trust protected plugin npm preflight tooling

* docs(release): scope protected writer guarantees

* fix(release): keep protected tooling foundation npm-only

* test(release): cover trusted npm preflight tooling
2026-08-21 07:24:31 +00:00
Vishal Doshi b470422371 fix(cron): surface Code Mode MCP resolution failures (#121796)
Amp-Thread-ID: https://ampcode.com/threads/T-01a0220e-1365-736f-b0f8-bfe122e23a8f

Co-authored-by: Grynn <grynn@users.noreply.github.com>
2026-08-21 00:15:35 -07:00
Peter Steinberger fc019c52b8 fix(gateway): return runtime-owned task results (#127045)
Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-b547-7788-a916-d4a94cbd3e3b

Co-authored-by: Amp <amp@ampcode.com>
2026-08-21 00:13:46 -07:00
Peter Steinberger e7e1c53250 fix(auto-reply): surface missing final replies after progress updates (#127070)
* fix(auto-reply): distinguish follow-up progress from final delivery

* test(auto-reply): compact follow-up delivery evidence cases
2026-08-21 00:07:45 -07:00
Ayaan Zaidi 190f2edd7f fix(qa): stop Mantis skipping visible Telegram changes (#127032)
Remove the premature visibility classifier and let one proof agent configure and exercise the disposable Telegram gateway. Align mock response timing with the 15-minute lane budget while preserving credential isolation through the alias-token proxy.
2026-08-21 12:33:38 +05:30
Peter Steinberger c83d212c7f perf(plugins): narrow installed index normalization imports (#127067)
Amp-Thread-ID: https://ampcode.com/threads/T-01a021f5-984a-7628-a30c-491c166ff247

Co-authored-by: Amp <amp@ampcode.com>
2026-08-21 00:03:27 -07:00
Peter Steinberger c021295233 fix(clawhub): clean failed archive staging (#127065) 2026-08-20 23:57:35 -07:00
Peter Steinberger 46d09d1a28 perf(test): speed up Agents page observation polling (#127063) 2026-08-20 23:55:44 -07:00
Vincent Koc 2405b98b05 fix(android): explicitly target notification intents (#127055) 2026-08-20 23:48:16 -07:00
Yuval Dinodia 8ec5ae0693 fix(agents): preserve literal Unicode-space paths (#126797)
Preserve model-supplied filename identity for mutations while keeping existence-checked Unicode-equivalent fallback for reads.

Co-authored-by: yetval <yetvald@gmail.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-21 12:18:11 +05:30
Vincent Koc 73ff2d2f45 fix(agents): distinguish review routing from enforcement (#126216) 2026-08-20 23:47:14 -07:00
Shakker faa1cfc598 fix(ui): associate steering work by target run (#126997) 2026-08-21 07:45:40 +01:00
Shakker b2d49afd8e fix(ui): collapse completed pre-steer work 2026-08-21 07:45:40 +01:00
Shakker 69fa1a8eab fix(codex): preserve steering transcript order 2026-08-21 07:45:40 +01:00
Peter Steinberger 72c8bf9946 fix(gateway): retain Bonjour cleanup on startup failure (#127062) 2026-08-20 23:39:12 -07:00
Vincent Koc 750f2f3762 fix(release): require concrete validation retry groups (#127012)
* fix(release): require concrete validation retry groups

* fix(release): reject mismatched retry filters

* fix(release): align retry controller vocabulary

* fix(release): preserve historical validation evidence

* fix(release): validate retry filters before scheduling

* test(release): follow shared filter validator

* docs(testing): clarify release QA retry groups
2026-08-20 23:35:16 -07:00
Peter Steinberger 5570c5ffac fix(file-transfer): expose directory page tokens (#127051) 2026-08-20 23:28:31 -07:00
Peter Steinberger 3b295b374c perf: trim setup detection worker imports (#127053)
Amp-Thread-ID: https://ampcode.com/threads/T-01a021f4-76a1-76f1-8758-25d0466913af

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 23:24:52 -07:00
Peter Steinberger ac724b1e41 fix(onboard): make --auth-choice help match the accepted set (#127030)
`openclaw onboard --help` advertised `claude-cli`, which the command
rejects, and hid `token`, which it accepts and its own error text
recommends. Three surfaces each rebuilt the accepted set independently:
Commander help asked for legacy aliases, the reset preflight added a
hardcoded `BUILT_IN_AUTH_CHOICES`, and the non-interactive dispatcher
added a hardcoded `GENERIC_NON_INTERACTIVE_AUTH_CHOICES`.

`formatAuthChoiceChoicesForCli` is now the single owner of that set. It
emits the generic token-provider choices (`setup-token`, `token`,
`apiKey`) that `AuthChoice` has always declared built-in, so every
surface renders and validates the same list.

Deprecated aliases stay out of it. `includeLegacyAliases: true` arrived
with a mechanical help-text refactor, never as a product decision: the
pre-refactor hardcoded help string listed no legacy alias, the reset
preflight's copy was unreachable because normalization runs first, and
the deprecation error already names the replacement. `oauth` is likewise
normalized to `setup-token` before any validator sees it, so the
dispatcher's `oauth` arm and its slot in the accepted list were dead.

Production LOC: -26.
2026-08-20 23:19:11 -07:00
Peter Steinberger 872048000b fix(gateway): await cron exit watcher drain (#126963)
* fix(gateway): await cron exit watcher drain

Amp-Thread-ID: https://ampcode.com/threads/T-01a0220d-d77f-73fb-a791-cbfb09be7d07

* fix(gateway): drain exit watchers before cron restart

Amp-Thread-ID: https://ampcode.com/threads/T-01a0220d-d77f-73fb-a791-cbfb09be7d07

* fix(gateway): fence cron restart after later stop

Amp-Thread-ID: https://ampcode.com/threads/T-01a0220d-d77f-73fb-a791-cbfb09be7d07

---------

Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 23:18:36 -07:00
Peter Steinberger f1723c757b fix(telegram): preserve direct-topic self-history (#127050) 2026-08-20 23:18:05 -07:00
Shakker d15f570742 fix: dismiss sidebar session menu tooltip (#127044)
Dismiss the sidebar session tooltip whenever its overflow menu opens, preserving unobstructed menu actions and stable row semantics.

Refs #127039.
2026-08-21 07:14:13 +01:00
Peter Steinberger f14cf6b910 perf(test): speed up pairing access polling (#127047) 2026-08-20 23:02:46 -07:00
Peter Steinberger c60a26695d perf(cli): remove ineffective dynamic imports (#127046)
Co-authored-by: Amp <amp@ampcode.com>
2026-08-20 23:01:49 -07:00
Peter Steinberger 2ecd342fbb fix(gateway): recover credential-file accounts after secrets reload (#126999)
* fix(gateway): recover credential-file accounts on secrets reload

Preserve independently discovered credential-file degradation across runtime snapshot refreshes, and re-inspect only the affected account when secrets are reloaded. Healthy sibling accounts remain running while status and doctor retain exact-owner diagnostics until recovery or teardown.

* test(gateway): prove credential-file reload recovery

* test(gateway): assert redacted reload error code
2026-08-20 23:00:49 -07:00
Marvinthebored 9feb1db00d fix(gateway): restore scheduler-owned Gateway context (#126640)
Bind scheduler-owned cron, hook, and heartbeat runs to lifecycle-fenced Gateway context so trusted built-in tools resolve after startup or reload without inheriting request client state.

Co-authored-by: Marvinthebored <marvin.assistant@lindsey.jp>
Co-authored-by: Marvinthebored <peter@lindsey.jp>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-08-21 11:29:09 +05:30
Peter Steinberger 0e75204f05 fix(macos): keep first-run onboarding visible after Gateway changes (#127038) 2026-08-20 22:45:44 -07:00
sinner dbf791bb1b fix(cron): reject blank --command-cwd before kind forge (#121535)
* fix(cron): reject blank --command-cwd/--command-input before kind forge

Presence-only typeof checks counted blank cwd/input as command-specific
edits, forging {kind:"command"} patches that could convert agentTurn or
script jobs into empty command payloads. Require non-blank values first.

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

* fix(cron): allow empty --command-input while rejecting blank cwd

ClawSweeper: Gateway command stdin is an unrestricted string, so empty
or whitespace --command-input must still patch through. Keep the blank
--command-cwd reject that prevents forging a command payload with no cwd.

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

* test(cron): focus command blank option coverage

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

* fix(cron): reject blank cwd before edit reads

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 22:44:52 -07:00
Peter Steinberger 0f642d2ac1 fix(agents): clean exec approvals on offline delete, and stop deleting main from taking the wildcard with it (#127037)
Two defects in one lifecycle, found by following one thread.

`agents delete` tries the Gateway first and falls back to a local path when the
Gateway is unreachable -- its own header calls this "gateway delegation and local
cleanup fallback". The Gateway path wraps deletion in
`withAgentExecApprovalsRemoved`; the local fallback did not. So deleting an agent
with no Gateway running left its exec approvals allowlist behind, silently.

That residue is not inert. Verified end to end: approve a pattern for an agent,
delete it through the offline path, recreate an agent with the same id, and
`approvals get` shows the old allowlist live under the new agent. The operator
never granted it. The offline path now uses the same journal-fenced,
rollback-capable helper as the Gateway path.

Removal rather than a warning: an exec approval is a latent authority grant, and
leaving one behind contradicts the deletion contract the Gateway already
enforces. `agents delete` already trashes the workspace and agent dir, so
removing a policy entry is not out of character for it.

The second defect is in the shared helper and affects the Gateway path too, which
means it is shipped today. It matched policy keys with

    normalizeAgentId(policyKey) === key

and `normalizeAgentId` falls back to `"main"` for anything it cannot represent.
`"*"` normalizes to `""` and therefore returns `"main"`, so deleting the `main`
agent also matched -- and removed -- the `"*"` wildcard allowlist. Strict
normalization now skips unrepresentable keys, so valid aliases are still removed
while the wildcard and unrelated agents survive.

Sibling sweep of `pruneAgentConfig`, which already handled bindings, subagent
allowlists, heartbeat/system-agent ownership, and Talk ownership: broadcast
targets, hook mappings, and hook agent allowlists also retained the deleted id.
Fixed, preserving `"*"` in the hook allowlist.

Follow-ups deliberately not taken here, each needing its own owner or design:
offline deletion still lacks the Gateway's transactional cron-job cleanup;
plugin-owned routing and thread bindings need an agent-deletion lifecycle hook;
remote node approvals need distributed cleanup or explicit warning semantics;
approval `agentFilter` cleanup needs a disabled-state design, since removing its
last entry would widen policy rather than narrow it.

Production +45/-18.
2026-08-20 22:44:41 -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