Commit Graph

67697 Commits

Author SHA1 Message Date
Peter Steinberger
8aab4ff94d refactor(state): split migration modules (#106356)
* refactor(state): split migration modules

* fix(state): relocate migration guard baselines
2026-07-13 05:13:42 -07:00
Peter Steinberger
3e21c2f256 feat(ui): dismissible sidebar attention chips (#106223)
* feat(ui): dismissible sidebar attention chips

* fix(ui): use toSorted for attention signatures

* refactor(ui): move attention dismissal store to its own module

* fix(ui): make attention dismissals safe across tabs

* style(ui): drop redundant String() in storage mock

* fix(ui): prune dismissals only after fresh data and key overdue snoozes by incident
2026-07-13 05:11:59 -07:00
Peter Steinberger
200103a72b fix(ci): remove chat test export debt 2026-07-13 13:11:35 +01:00
Peter Steinberger
a627a77eab refactor(cli): split update command orchestration (#106322)
* refactor(cli): split update command orchestration

* fix(ci): refresh update command export baseline
2026-07-13 05:11:22 -07:00
Peter Steinberger
644bc79ed1 perf(ui): enforce build performance budgets (#106367) 2026-07-13 05:07:18 -07:00
Peter Steinberger
aa98780675 fix(docs-i18n): protect Markdown syntax before translation 2026-07-13 08:05:53 -04:00
Peter Steinberger
801ec63f92 refactor(cli): rely on Commander contracts (#106366) 2026-07-13 05:05:31 -07:00
Peter Steinberger
a03df5fd58 fix(ci): stamp event envelope type in chat-state test 2026-07-13 05:01:04 -07:00
Peter Steinberger
bfdfd35e5d fix(mac): allow slow node worker startup (#106281)
* fix(mac): allow slow node worker startup

* chore: leave release notes to release flow
2026-07-13 05:00:48 -07:00
Peter Steinberger
bbd6f79b3b fix(ci): baseline test-only chat-state export
#106353 exports requestChatPageUpdate for its test only; production
knip flags it as an unused export and check-dependencies fails on main.
2026-07-13 04:58:23 -07:00
Peter Steinberger
bd2be839ce fix(ci): update route and agents page tests for agent selection scope 2026-07-13 04:52:11 -07:00
Peter Steinberger
497662f0fc perf(ui): batch streaming chat renders (#106353) 2026-07-13 04:44:39 -07:00
qingminlong
c5aa7397b4 fix(nodes): reject malformed camera content lengths (#105954) 2026-07-13 04:42:21 -07:00
Peter Steinberger
8f7df1b94b fix(ci): stub agent selection in gateway source replacement test context 2026-07-13 04:41:45 -07:00
Peter Steinberger
d262cad41f refactor: burn down Matrix, Telegram, and outbound dead exports (#106153)
* refactor(matrix): remove unused internal exports

* refactor(telegram): remove unused internal exports

* refactor(matrix): remove stale thread binding imports

* refactor(outbound): remove unused internal exports

* style(outbound): format dead export cleanup
2026-07-13 04:39:58 -07:00
Peter Steinberger
418dd85e66 improve: speed up focused test execution (#106307)
* test: speed up focused test execution

* style: format vitest config test

* test: preserve targeted watch routing
2026-07-13 04:38:05 -07:00
Peter Steinberger
cad6df0a7c fix(ui): trim unused export surface 2026-07-13 12:35:26 +01:00
Peter Steinberger
88fccc6735 fix(ci): refresh generated Swift protocol 2026-07-13 12:35:26 +01:00
Peter Steinberger
279f21e02b chore(deps): remove redundant Commander declarations (#106345) 2026-07-13 04:34:19 -07:00
Peter Steinberger
b0ebb81e89 refactor(macos): use swift-log contracts (#106270) 2026-07-13 04:18:32 -07:00
Peter Steinberger
faef57e138 fix(ci): repair suspension lane lint errors and stale deadcode entry 2026-07-13 04:18:07 -07:00
Peter Steinberger
4b6575636f fix(ci): finalize control UI locale artifacts 2026-07-13 12:12:51 +01:00
Peter Steinberger
a487d6b41d improve(ui): lazy-load MCP Apps chat bridge (#106288)
* perf(ui): lazy-load MCP Apps bridge

* test(ui): align lazy MCP Apps checks
2026-07-13 04:05:57 -07:00
Peter Steinberger
9086389527 feat(control-ui): agent identity editor, Settings-homed Agents page, scalable chip switcher (#106058)
* feat(control-ui): agent identity editor, settings-homed agents page, chip switcher pinning

* test(control-ui): pinned-agent persistence coverage; persist pins only when set

* refactor(control-ui): split agent menu, identity actions, model staging out of oversized files

* chore(i18n): sync control-ui locale bundles for agent identity/switcher keys

* fix(control-ui): stabilize new sidebar switcher tests; ratchet LOC + export baselines

* chore(review): document identity clear limitation; drop unused export

* feat(control-ui): scope pages to selected agent

* fix(control-ui): keep scoped page state consistent

* docs(control-ui): explain shared agent scope

* fix(control-ui): reconcile agent scope with current ui

* fix(control-ui): preserve complete agent filtering

* fix(control-ui): bound uploaded agent avatars

* test(control-ui): keep pinned-route fixture valid

* test(control-ui): keep pinned-route fixture valid

* chore(i18n): sync locale bundles for agent scoping keys
2026-07-13 04:03:26 -07:00
Peter Steinberger
4dd839c462 refactor(release): split cross-os checks (#106309) 2026-07-13 04:01:40 -07:00
Peter Steinberger
fa963eee06 refactor(copilot): use SDK contracts (#106208) 2026-07-13 04:00:17 -07:00
Peter Steinberger
bd9bedb201 fix(docs): refresh gateway lock map (#106312) 2026-07-13 03:58:49 -07:00
Peter Steinberger
e0e0394d05 refactor(ui): remove dead export seams (#106220) 2026-07-13 03:54:00 -07:00
Ho Lim
b00ff778b8 fix(gateway): clear session suspension timers on shutdown (#103211)
Improve gateway session suspension shutdown handling.

Co-authored-by: Ho Lim <subhoya@gmail.com>
2026-07-13 03:53:24 -07:00
Ayaan Zaidi
745ab05e6f fix(gateway): drain parked restart emit hooks on hooked emissions
A gateway-tool restart parks sentinel/continuation hooks in
pendingRestartEmitHooks, but emitPreparedGatewayRestartUnderAdmission only
drained them when emitting hookless. When the config-reload deferral won the
emission race with its own emitHooks, the restart sentinel was never written:
no post-restart notice, no continuation turn, stale pendingRestartSessionKey
surviving in-process restarts, and orphaned hooks never rejected.

Run the caller preflight first, then drain parked hooks with the original
replace/reject loop whose tail re-read also captures hooks accepted while the
caller's beforeEmit awaited; release session ownership only once the slot is
settled and no awaits remain before emission. Reject every prepared hook set
on non-emitted outcomes and error-isolate afterEmitFailed callbacks. The
empty-slot path stays await-free so mid-flight intent/deferral timing is
unchanged, and emission attempts remain single-flight behind the restart-signal
admission fence (now documented).

Fixes #106138
2026-07-13 16:23:04 +05:30
Peter Steinberger
624977ec90 fix(ci): await async doctor compaction in the sqlite reliability runner
runDoctorStateSqliteCompact became async in #106210 but this caller
still read fields off the Promise, breaking check-test-types and the
bench-sqlite-reliability tooling test on main.
2026-07-13 03:51:25 -07:00
Vincent Koc
572b4c7146 fix(msteams): remove orphaned attachment helper (#106301) 2026-07-13 18:51:13 +08:00
openclaw-mantis[bot]
801252c66e chore(i18n): refresh native locales (#106260)
* chore(i18n): refresh native locales

* chore(i18n): sync generated app resources

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 03:49:36 -07:00
Peter Steinberger
d87d78f667 fix(ci): refresh plugin SDK API baseline hash (#106289) 2026-07-13 03:49:14 -07:00
Peter Steinberger
eb1120feee test(worker): deterministically gate the lost-window replay scenario
Post-merge review of #105921 flagged a synchronization race: the restart
fault fired before the pre-restart tail live event was guaranteed to
reach the gateway, making the replay trace assertion timing-dependent.
Pin the pre-restart prefix with vi.waitFor and assert the lost-window
invariants (resync replay renumbered from the fresh ack state) instead
of the exact retry trace, which legitimately varies with the ack/teardown
race. 5x stable locally.
2026-07-13 03:47:31 -07:00
Joshua West
392a02a396 fix(workboard): resolve parent dependency status via targeted lookups, not a full-corpus scan (#104668)
* fix(workboard): resolve parent dependency status via targeted lookups, not a full-corpus scan

dependencyTargetStatus() called the fully unscoped store.list() (every card,
every board, fully materialized via entries()+readCard()) just to look up the
status of a card's own parent id(s) -- almost always exactly one. dispatch()
calls promoteDependencyReady() once per card in its board-scoped pass, so
every parented card in that pass re-paid for a full-corpus re-scan.

Confirmed via a live CDP CPU profile of a real "openclaw workboard dispatch"
call (--inspect attached to a running gateway, Profiler.start/stop scoped to
the repro, elapsed 161.8s matching a known 160s+ stall): 93.3% of the time
(142s + 8.7s of 162s) was inside native SQLite all()/prepare() bindings, all
funneling through dispatch -> promoteDependencyReady -> dependencyTargetStatus
-> list -> entries -> readCard (readCard issues 4 separate synchronous SQL
statements per card). On a corpus of ~5770 cards, this is O(parented_cards_in_pass
x corpus_size x 4_queries) -- a genuine algorithmic defect, not event-loop
starvation from a concurrent session as originally suspected for this symptom.

Replace the unscoped list()+Map lookup with targeted get(parentId) calls
(already a single indexed-row lookup used everywhere else in this file) --
O(parents.length), normally O(1), instead of O(corpus size). Behavior is
unchanged: parent?.status === "done" on the get() result is exactly what
cards.get(parentId)?.status === "done" computed from the unscoped list().

Adds a regression test asserting the underlying store's entries() is called
at most once while promoting 8 parented cards together in one dispatch pass
(would have been 9 calls before this fix -- 1 outer scoped list() + 1 inner
unscoped list() per parented card).

* fix(workboard): address review feedback on dependency-target-status fastpath

Two findings from the automated PR review, both confirmed real:

- Remove an incomplete, unrelated active-owner fast-path (listActiveOwnerIds()
  in store.ts + its cross-board test in store.test.ts) that leaked into this
  commit from separate, still-in-progress local work. It imported
  WorkboardActiveOwnerQueryable, a type that isn't defined anywhere in this
  PR's tree, breaking typecheck and the bundled-extension lint check. Not
  part of the dependencyTargetStatus fix this PR is scoped to.
- Replace the comparator-free, mutating .sort() calls in the new dependency
  regression test with .toSorted() plus an explicit localeCompare comparator,
  per the repo's lint rules.

Re-ran locally against just these two files (the actual PR diff, review WIP
set aside): pnpm lint --threads=8, pnpm format:check, pnpm tsgo:prod, pnpm
check:test-types, pnpm run lint:extensions:bundled all pass; full workboard
extension suite 111/111 (two removed tests belonged to the unrelated
active-owner code, not this fix).

---------

Co-authored-by: ClawBox <clawbox@cayk.ca>
2026-07-13 03:46:05 -07:00
Peter Steinberger
8ba5cd3070 refactor(agents): trim exec approval exports (#106292) 2026-07-13 03:43:45 -07:00
Peter Steinberger
88e0bbc86f fix(ci): drop unused msteams media placeholder test constants
Companion to 4bb4ffc55c: check-lint (no-unused-vars) still fails on
attachments.helpers.test.ts after #106279 trimmed their usages.
2026-07-13 03:43:17 -07:00
Peter Steinberger
4bb4ffc55c fix(ci): drop dangling msteams attachment placeholder helper 2026-07-13 03:42:39 -07:00
Peter Steinberger
0e520d68e7 fix(ci): stabilize runtime test retries 2026-07-13 11:41:15 +01:00
Peter Steinberger
e2ed58efec fix(ci): publish native generated locales 2026-07-13 11:41:15 +01:00
Peter Steinberger
3a9e750939 fix(pr): fail closed on paginated file errors (#106254) 2026-07-13 03:40:53 -07:00
Peter Steinberger
a17058d191 feat(usage): show the account email with plan windows in the chat context popover (#106200)
* feat(usage): surface plan windows and account email in the chat context popover

The context-window popover now shows which account a session runs on:
provider usage snapshots carry an accountEmail resolved from the auth
profile when stored, the ChatGPT access-token JWT claims (openai/codex),
or the Claude CLI config file (~/.claude.json oauthAccount) for
keychain-synced logins. models.authStatus embeds it, quota groups keep
distinct accounts separate, and the popover renders the email under the
plan header for local CLI sessions and OpenClaw-configured subscriptions
alike.

* test(openai): assemble the fake usage JWT from parts

* test(usage): keep fixture tokens and identity plumbing scanner-safe

* fix(usage): verify the Claude CLI login before labeling usage with its email

Review findings: the CLI-config email fallback now requires the usage token
to match the cached CLI credential (and honors CLAUDE_CONFIG_DIR), so an
ambient login for another account never labels a snapshot; token-type
credentials propagate their stored email alongside oauth ones.

* style(anthropic): scanner-safe local for the CLI login read

* fix(usage): capture the Claude CLI account email on the credential

Review findings: reading ambient CLI config at usage-fetch time could not
verify keychain-only logins and could go stale across account switches.
The credential reader now captures oauthAccount.emailAddress next to the
credential it belongs to, the synced claude-cli profile carries it, and
the anthropic fetcher uses only the credential-borne identity.

* style(usage): scanner-safe credential fixtures and helper naming

* fix(auth): backfill the CLI account email onto existing synced profiles

Profiles synced before identity capture stay usable and skip CLI reads,
so upgraded installs would never gain the email until token rotation.
While the stored token material matches the CLI login, merge the
non-secret email onto the stored profile.

* style(test): scanner-safe email assertion

* test(auth): pin the no-reread invariant to identity-complete profiles
2026-07-13 03:39:16 -07:00
Peter Steinberger
b9411fda36 test(plugins): restore removed regression coverage (#106269) 2026-07-13 03:34:46 -07:00
Peter Steinberger
9857f05b74 fix(ci): drop stale gateway-lock deadcode entries 2026-07-13 03:28:56 -07:00
Peter Steinberger
1577c28500 refactor(deadcode): trim msteams private exports (#106279)
* refactor(deadcode): trim msteams private exports

* chore(deadcode): refresh unused export baseline
2026-07-13 03:26:24 -07:00
Arca
0e5ed900b0 fix(discord): retry stale preview cleanup after final delivery (#104893)
* fix(discord): retry stale preview cleanup

* test(channels): use compatible deferred helper

* test(channels): satisfy deferred lint

* chore: prepare Discord preview cleanup

* fix(channels): retain failed draft cleanup targets

* fix(channels): separate draft cleanup callbacks

* fix(channels): claim standalone draft cleanup ids

---------

Co-authored-by: Cad from Arca <cad@arcabot.ai>
Co-authored-by: Colin <colin@solvely.net>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 03:23:27 -07:00
Peter Steinberger
ca0fe7f691 refactor(agents): trim subagent spawn exports (#106275) 2026-07-13 03:22:12 -07:00
Peter Steinberger
2aa4ff0825 refactor: consolidate duplicate helper exports (#106016)
* refactor(normalization): consolidate string helpers

* refactor(normalization): consolidate agent ids

* refactor(paths): consolidate user path resolution

* refactor(gateway): preserve transcript helper facade

* fix(normalization): align helper build aliases

* fix(memory): keep helper import line neutral

* chore(plugin-sdk): align consolidated helper surface

* refactor(normalization): reuse lowercase string helper

* refactor(normalization): reuse record guard

* refactor(normalization): share surrogate boundary helper

* refactor(agents): share token estimate constant

* refactor(memory): distinguish standalone helper contracts

* refactor(normalization): share error cause formatter

* refactor(config): distinguish eligibility predicates

* refactor(plugins): share registry state symbol

* refactor(cli): reuse outbound dependency adapter

* refactor(cron): distinguish positive duration parser

* fix(gateway): keep transcript helper private

* fix(paths): preserve public helper status

* refactor(channels): reuse registry normalizer

* refactor(agents): reuse agent core runtime facade

* refactor(auth): reuse locked profile upsert

* refactor(records): distinguish trap-safe guard

* refactor(migrations): distinguish sync directory helper

* test(plugins): drop stale duration alias expectations

* fix(channels): remove stale registry import

* chore(plugin-sdk): refresh helper API baseline

* fix(memory): keep renamed helpers private

* fix(plugins): keep registry state key private

* fix(plugin-sdk): tighten wildcard surface budget

* chore(plugin-sdk): refresh rebased helper API baseline
2026-07-13 03:22:00 -07:00
Peter Steinberger
62e53919fd improve(ui): move Devices into Settings and redesign the device inventory (#106055)
* feat(ui): move Devices page into settings and redesign device inventory

- Devices now lives at /settings/devices (System group); /nodes stays as alias
- per-device form-factor icons (phone/browser/terminal/machine) with status dot
- equal-height header actions; stale cleanup and pairing only
- drop manual Refresh button; page already auto-refreshes via presence events + 30s poll
- dynamic connected/pending summary replaces static card subtitle

* style(ui): oxfmt pass + loading empty state for devices inventory

* chore(ui): sync locale bundles for devices settings copy; docs point at Settings → Devices

* refactor(ui): split device tile + pending rows out of view-inventory; drop unused icons

Keeps the TypeScript LOC ratchet green: view-inventory.ts returns below its
baseline and icons.ts sheds unused folderOpen/micOff/volumeOff glyphs.

* fix(ui): ratchet LOC baseline, drop unused DeviceIconSource export, settle devices settings copy

- baseline: icons.ts 693, view-inventory.ts back under the 500 ceiling
- subtitles.nodes now describes the settings page; nav tests updated
- locale bundles resynced (fallbacks=0)

* refactor(ui): rename token row param for reviewer-tool clarity

* fix(ui): collapse device rows in narrow containers and classify the TUI as a terminal client

Review findings: the nodes-entry grid override beat the shared 560px
list-item collapse, overflowing phone-width rows; openclaw-tui connects
with mode ui so only its client id marks it as a terminal.

* chore(ui): translate pending locale keys after rebase (fallbacks=0)
2026-07-13 03:18:17 -07:00