Commit Graph

9696 Commits

Author SHA1 Message Date
Peter Steinberger
4b7d6fa3bf docs: align interactive client behavior (#111047) 2026-07-18 17:00:14 -07:00
Ted Li
10f5a7ac58 fix(groq): keep default Llama agent turns within TPM limit (#104904)
* fix(groq): recover oversized requests safely

* fix(groq): clear parallel tool aliases on fallback

* fix(groq): require provenance-aware host

* fix(groq): preserve configured request budgets

---------
authored-by: @MonkeyLeeT
Co-authored-by: Colin <colin@solvely.net>
2026-07-18 20:00:12 -04:00
Peter Steinberger
56eef79989 fix(channels): recover dead-lettered inbound events (#111029)
* feat(channels): add ingress dead-letter recovery

* fix(channels): preserve dead-letter compatibility

* docs: refresh CLI map for channel dead letters
2026-07-19 00:44:23 +01:00
Peter Steinberger
7562b79465 refactor(channels): share durable ingress monitor (#111017)
* refactor(channels): share durable ingress monitor

* fix(channels): harden ingress monitor shutdown

* docs: refresh SDK documentation map
2026-07-19 00:42:08 +01:00
Peter Steinberger
ec998a0f3f feat(canvas): export widgets as PNG — copy or download from the card menu (#110992)
* feat(canvas): export widgets as PNG — copy to clipboard or download from the card menu

* fix(ui): widget-export lint, knip, and lines-budget cleanup
2026-07-19 00:39:59 +01:00
Peter Steinberger
9275837f41 docs: explain managed Gateway heap sizing (#111027) 2026-07-19 00:36:03 +01:00
Peter Steinberger
5590d7c280 docs: align SecretRef degradation semantics (#111021) 2026-07-19 00:18:01 +01:00
Peter Steinberger
14a714901b docs(imessage): align recovery with durable ingress (#111002) 2026-07-19 00:09:44 +01:00
Peter Steinberger
556a2ee276 feat(cron): add per-job dynamic cadence (#110978)
Add optional per-job pacing bounds across the cron API, CLI, tool schema, public output, and SQLite job envelope, requiring at least one bound. Allow only the currently running paced job to record a one-shot next_check proposal and carry it through isolated-run completion.

After successful runs, clamp the proposal to the job bounds and persist an exact one-shot slot marker so maintenance preserves only that timestamp. Clear the marker on runs, edits, and schedule normalization; preserve existing no-proposal, skip, timeout, and error scheduling behavior.
2026-07-18 23:43:39 +01:00
Peter Steinberger
d343216510 fix(ios): keep unified voice controls recoverable (#110906)
* docs(ios): align unified chat voice copy

* fix(ios): keep active dictation control available

* fix(ios): keep active talk control available

* fix(ios): restore unified voice recovery

* fix(ios): keep pending dictation cancel visible

* chore(ios): refresh native i18n inventory

* chore(ios): sync unified voice locale memory

* fix(ios): return unified mic label view

* test(ios): lock dictation cancellation ordering
2026-07-18 23:41:00 +01:00
Peter Steinberger
333a3297af refactor(plugin-sdk): consolidate persistent dedupe claim loop (#110984) 2026-07-18 23:36:59 +01:00
cxbAsDev
2295fae731 fix: bound miscellaneous unbounded file reads across 5 modules (#110516)
* fix: bound misc unbounded fs.readFile calls; remove unused fs import

* fix: decode buffer to string before passing to string consumers

readRegularFile and readRegularFileSync return { buffer, stat },
not a string. All 4 new call sites passed the raw object to functions
expecting a string (JSON.parse, RegExp.test, template literals, etc.),
causing TS2345 type errors and runtime failures.

Fix each call by extracting .buffer and calling .toString('utf8')
before passing the result to string consumers.

* style: fix oxfmt formatting in config-set-input.ts

* fix: bound config and trajectory metadata reads

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

* refactor: isolate bounded read ownership

Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 23:27:26 +01:00
Peter Steinberger
a5ec26fa3c fix: prevent LINE channel reloads from hanging on stalled deliveries (#110971)
* fix(channels): bound ingress shutdown and document retention

* docs(channels): note ingress shutdown behavior

* chore: keep release notes in pull request

* docs: refresh documentation map

* fix(line): preserve deferred claims during shutdown

* fix(line): handle late abandonment failures
2026-07-18 23:25:33 +01:00
Peter Steinberger
264a7b0d12 refactor(channels): consolidate manifest descriptors (#110985) 2026-07-18 23:18:28 +01:00
Peter Steinberger
bb7b2bca68 feat(ui): finish the chat session → thread rename across the Control UI (#110973)
* feat(ui): finish the chat session → thread rename across the Control UI

Completes the #110933 creation-surface rename mechanically: Threads page
(title, filters, archive/delete/rename/pin menus, transcript search),
sidebar labels and menus, welcome suggestion, palette category, tools
availability copy, workboard lifecycle/card strings, dreaming history,
board/diff/workspace-rail chrome, and the untitled main/channel fallback
names. Technical identifiers stay: Session ID, session keys, terminal
sessions, protocol wording. Living docs updated (control-ui.md);
historical release notes left as shipped.

* style(ui): format session-management e2e

* fix(ui): finish thread rename in navigation labels and stale test literals

Codex review caught the palette Threads entry and the Worktrees owner
column still saying Session; CI caught test literals asserting the old
copy (Threads page overview tile, filter tooltips, group counts, catalog
terminal notice, create-rejection error, workboard lifecycle hint). Also
completes the usage-stat cluster (Threads + hints) and the tool-catalog
group label. Native app strings (iOS/Android/macOS) keep session wording
and reconcile through their own i18n pipelines as a follow-up.
2026-07-18 23:15:13 +01:00
Peter Steinberger
f3f6eb2321 fix(codex): stop fallback for superseded sessions (#110980) 2026-07-18 23:02:03 +01:00
Peter Steinberger
460e3e669c fix(canvas): restore shipped policy/host-disable contracts; harden workspaces doctor cleanup (#110927)
* fix(dashboard): harden canvas and workspace compatibility

* docs(web): add dashboard architecture

* chore: remove release-owned changelog entry

* docs: update dashboard architecture map
2026-07-18 23:00:00 +01:00
clawsweeper[bot]
b88646cf78 feat(webchat): reply-to a message with hydrated reply context (#110791)
* feat(webchat): reply-to a message with hydrated reply context

Control UI replies now carry the target transcript id as replyToId on
chat.send. The Gateway resolves the replied-to message from session
history and hydrates the channel-agnostic ReplyToId/ReplyToBody/
ReplyToSender envelope fields, so agents receive reply_to_id,
has_reply_context, and the untrusted reply-target block exactly like
Discord replies (mirrors #90263). Reply targets without a persisted
transcript id keep the inline-quote fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(webchat): keep non-reply chat.send dispatch ordering and satisfy CI gates

* docs(webchat): match reply-context doc to webchat conversation-info policy

* fix(webchat): hydrate reply bodies from display-visible content only

---------

Co-authored-by: openclaw-clawsweeper[bot] <openclaw-clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
2026-07-18 15:57:59 -06:00
Peter Steinberger
4d683904df fix(agents): restore ask_user roundtrip in Gateway chats (#110961)
* fix(agents): restore ask_user channel roundtrip

* test(qa): derive ask_user proof from answers

* test(qa): isolate mock reply directives

* test(qa): wait for complete ask_user reply

* fix(agents): fail closed on stale ask_user prompts

* chore: remove release-owned changelog entry

* fix(agents): satisfy ask_user CI contracts
2026-07-18 22:55:46 +01:00
Peter Steinberger
7a551bff0c fix(vault): aggregate provider outage diagnostics (#110908)
* fix(vault): aggregate provider outage diagnostics

* fix(vault): classify revoked token outages

* fix(vault): preserve scoped ACL failures

* fix(vault): keep token probes advisory

* test(vault): satisfy gateway proof gates

* fix(secrets): attribute web provider outages

* test(secrets): prove web outage fan-out in owner suite

* fix(vault): scope malformed responses per secret

* test(secrets): harden exec fanout fixtures
2026-07-18 22:44:06 +01:00
Peter Steinberger
5fe8d6a852 fix(gateway): clients can identify authorization failures (#110925)
* fix(gateway): structure authorization errors

* test(gateway): align authorization contracts

* fix(gateway): regenerate protocol bindings

* fix(gateway): preserve optional scope errors

* fix(gateway): report complete pairing scopes

* style(gateway): format protocol exports
2026-07-18 22:02:28 +01:00
sheyanmin
ff3ed99cde fix(usage-bar): validate meter width with strict integer parsing (#110410)
* fix(usage-bar): validate meter width with strict integer parsing

* fix(usage-bar): restore canonical meter width range [0, 100]

* fix(usage-bar): preserve bounded meter defaults

Co-authored-by: sheyanmin <she.yanmin@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 21:57:11 +01:00
Peter Steinberger
242093fb00 fix(ui): dark theme AA contrast for coral fills — deepen primary/destructive, add widget accent-fill token (#110957) 2026-07-18 21:56:24 +01:00
Peter Steinberger
81362bf643 feat(apps,ui): question surface parity and composer takeover (#110681)
* feat(apple): question parity — persistent summaries, skip, reconnect fallback, macOS keyboard

* feat(android): question parity — persistent summaries, skip, reconnect fallback

* feat(ui): question panel replaces composer while expanded

* fix(apps): regenerate question parity contracts

* fix(apps): preserve question reconciliation state

* fix(apps): keep question terminal state monotonic

* test(android): satisfy question test formatting

* fix(security): restore skill audit file reads

* fix(apps): harden question parity edge cases

* fix(apps): preserve expired question summaries

* fix(apps): keep question recovery retries current

* fix(apps): retry stale question recovery snapshots

* fix(android): reset stale question retry budgets

* docs(tools): clarify question composer takeover

* fix(apps): satisfy question recovery release gates

* fix(apps): preserve unknown question outcomes

* fix(apps): harden question action state

* fix(apps): keep unavailable questions terminal

* fix(apps): finalize local question outcomes

* fix(apps): preserve question card API

* fix(apps): reconcile external question answers

* fix(apps): reset question backoff budget

* chore(apps): refresh native i18n inventory

* fix(android): distinguish question skip progress

* fix(android): reconcile locally expired questions

* fix(apps): keep question recovery state fresh

* docs: note question surface parity

* fix(ui): reconcile IME draft before question takeover

* docs: leave question parity notes to release workflow
2026-07-18 21:42:15 +01:00
Peter Steinberger
09a64f7ab0 feat(models): make per-agent allowlists explicit (#110888) 2026-07-18 21:42:05 +01:00
Peter Steinberger
2bcbe3a612 feat(reef): follow up on unconfirmed deliveries instead of staying silent (#110938)
* feat(reef): follow up on unconfirmed deliveries instead of staying silent

* test(reef): satisfy lint and test-type gates for delivery notices

* test(reef): keep rejection notifier mock signature untyped
2026-07-18 21:08:10 +01:00
Peter Steinberger
1cacb12c4d feat(canvas): give show_widget a design system — theme tokens, base styles, live host theme bridge (#110832) 2026-07-18 21:05:16 +01:00
Peter Steinberger
1d492f5c53 fix(gateway): honor scopes for WebChat session mutations (#110931)
* fix(gateway): authorize webchat session mutations by scope

* chore: keep gateway release note in PR body
2026-07-18 20:48:39 +01:00
Omar Shahine
bbad877aed fix: deliver Codex-generated images on message-tool routes (#110893)
* fix: deliver Codex-generated images on message-tool routes

* test(codex): cover native image delivery path

Document trusted harness artifact provenance and cover the runner-to-dispatch bridge.\n\nRelease note: Codex-generated images now reach message-tool-only routes while normal source suppression remains intact.\n\nCo-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-18 20:45:57 +01:00
Peter Steinberger
be80cc747c feat(zalouser): recover accepted messages after local crashes (#110916)
* feat(zalouser): add durable ingress recovery

* fix(zalouser): settle aborted ingress claims

* fix(zalouser): preserve concurrent ingress lanes

* docs: refresh generated channel map

* refactor(zalouser): simplify ingress abort listener
2026-07-18 20:32:30 +01:00
Peter Steinberger
6589788c02 docs: The main session concept page and shipped-sidebar updates (#110905)
* docs: add The main session concept page and cross-links

* docs: precise memory-priming wording on the main-session page

* docs: update Control UI sidebar description to the Home and zones model
2026-07-18 20:23:09 +01:00
Peter Steinberger
04a9552a1f chore(codex): update app-server to 0.144.6 [AI] (#110821)
* build(codex): bump app-server to 0.144.6

* build(codex): align ACP runtime to 0.144.6

* test(codex): harden live image probe

* test(codex): accept alphanumeric image tokens

* test(codex): stabilize image probe glyphs

* test(gateway): disable cron probe delivery

* test(codex): enlarge live image token

* test(codex): tie compaction proof to native output

* test(codex): accept wrapped native stress commands

* test(codex): stabilize compaction acknowledgements

* docs(changelog): note Codex 0.144.6 update

* docs(changelog): defer Codex note to release
2026-07-18 19:19:17 +00:00
Peter Steinberger
5fdb0cd24e feat(chat): switch between session transcript branches from the chat header (#110857)
* feat(chat): switch between session transcript branches from the chat header

* fix(chat): type fixes and protocol regen for branch switcher CI
2026-07-18 20:06:36 +01:00
Josh Lehman
453444636c feat: bound transcript reads across replacements (#110374) 2026-07-18 11:41:39 -07:00
Peter Steinberger
3572fba7f9 feat(plugin-sdk): guard ingress effects once per event (#110846)
* feat(plugin-sdk): add ingress effect guard

* docs: refresh docs map

* fix(plugin-sdk): propagate effect commit failures

* fix(plugin-sdk): isolate ingress effect namespaces
2026-07-18 19:23:39 +01:00
Peter Steinberger
8a5c8690e1 fix(secrets): keep unaffected owners live during reload failures (#110779)
* fix(secrets): isolate reload failures per owner

* refactor(secrets): split runtime activation helpers

* fix(secrets): export web warning type

* fix(secrets): reject unsafe degraded config writes

* fix(secrets): derive reload defaults type

* fix(secrets): defer reload state publication

* fix(secrets): preserve partial refresh state

* fix(secrets): retry superseded reload preflight

* fix(secrets): bind stale credentials to owner contracts

* fix(secrets): scope degraded credential contracts

* fix(secrets): restore source ownership guards

* fix(secrets): recover provider-only degradation

* fix(secrets): enforce degraded reload contracts

* fix(secrets): preserve scoped reload state

* fix(secrets): reconcile deferred descendant state

* fix(secrets): commit reload state atomically

* fix(secrets): preserve source transaction lineage

* test(secrets): use non-secret lineage marker

* chore(plugin-sdk): refresh API baseline

* fix(secrets): canonicalize web owner contracts

* fix(plugin-sdk): preserve legacy secret owner contracts

* fix(secrets): satisfy startup activation types

* test(secrets): align reload fixtures with owner contracts

* refactor(secrets): move source recovery scope helper

* fix(secrets): preserve owner contracts on web failures

* fix(secrets): bind legacy web resolution contract

* fix(secrets): retry stale auth publication
2026-07-18 18:29:24 +01:00
Peter Steinberger
4d27b5b67e refactor(macos): move PortGuardian state to SQLite (#110527)
* refactor: compose native SQLite bootstrap tables

* refactor: share native SQLite state bootstrap

* refactor(macos): move PortGuardian state to SQLite

* test: align PortGuardian future-schema fixture

* fix(macos): reserve PortGuardian ledger across tunnel spawn

* fix(ci): align PortGuardian migration gates

* fix(macos): tolerate vanished SQLite sidecars

* fix(macos): revalidate PortGuardian writes

* test(macos): use sqlite identity bootstrap
2026-07-18 18:15:17 +01:00
Peter Steinberger
c8fe8f102f feat(macos): Quick Chat area capture and focused-app text context (#110635)
* feat(macos): add Quick Chat capture context

* docs(macos): describe Quick Chat capture context

* fix(macos): bound the AX text walk with deadline, cancellation, and per-message timeout; keep distinct repeated text

* fix(macos): ancestry-scoped echo suppression and adapter-wide AX timeouts

* fix(macos): hard outer timeout abandons a hung AX walk

* fix(macos): truly abandon hung AX walks; hide the bar synchronously before area selection

* chore(i18n): refresh native locale artifacts for Quick Chat capture strings
2026-07-18 17:45:52 +01:00
Peter Steinberger
98410d986e refactor(state): move device identity into canonical SQLite state (#110392)
* refactor: store device identities in SQLite

* style: satisfy Swift identity lint limits

* test: harden device identity migration fixtures

* fix: harden SQLite device identity recovery

* chore: remove stale identity helper

* refactor: isolate device identity repair

* chore: remove stale migration import

* test: validate migrated identity key types

* fix: harden device identity repair

* style: format device identity assertion

* fix: derive repaired identity key from PEM

* style: remove redundant PEM conversions

* fix: align native identity store with schema v4

* fix(state): satisfy SQLite identity CI gates

* fix(state): coordinate native identity migration

* test(doctor): include native identity claim path

* fix(infra): preserve coordinator release error

* fix(state): clear identity validation gates

* refactor(apple): remove identity test-only APIs

* refactor(apple): remove dead identity error type

* test(apple): use canonical identity test seam

* test(macos): isolate gateway readiness identity
2026-07-18 17:43:56 +01:00
Peter Steinberger
33f9c47e3c fix(ui): label the local-only chat message delete honestly as hide (#110801) 2026-07-18 17:27:51 +01:00
Peter Steinberger
9177601e7e fix(plugin-sdk): refresh merged API baseline (#110751) 2026-07-18 16:05:55 +01:00
Peter Steinberger
5143d909b9 feat(macos): Quick Chat streamed replies and continue-recent targeting (#110631)
* feat(macos): stream Quick Chat conversations

* docs(macos): explain Quick Chat recents

* fix(macos): bind the Quick Chat reply consumer before dispatching the send

* fix(macos): pre-bind reply consumer for all send paths; gate rebind on visible route

* fix(macos): revalidate recents eligibility after the async fetch

* fix(macos): invalidate in-flight recents fetches on competing interactions

* fix(macos): single-owner recents invalidation; fresh presentations clear prepared replies

* docs(macos): name the accepted scheduler-scale pre-bind tradeoff

* chore(i18n): refresh native locale artifacts for new Quick Chat strings

* fix(macos): keep Quick Chat placeholder and recents titles localizable
2026-07-18 15:58:49 +01:00
Peter Steinberger
d7b0bacf10 fix(teams-meetings): join and transcribe live meetings reliably (#110615)
* fix(teams-meetings): validate live web flows

* chore(plugin-sdk): update meeting runtime baseline

* test(teams-meetings): align live validation fixtures

* fix(teams-meetings): harden live browser validation

* fix(teams-meetings): preserve live transition lifecycles

* fix(meeting-bot): pass wait budget during recovery

* test(teams-meetings): satisfy extension lint

* fix(teams-meetings): preserve browser session ownership

* fix(teams-meetings): retire audio bridges after leave

* fix(teams-meetings): harden leave and audio ownership

* fix(teams-meetings): preserve leave transition ownership

* fix(teams-meetings): serialize leave cleanup safely

* fix(teams-meetings): guard live transition cleanup

* fix(teams-meetings): preserve adapter boundaries

* fix(teams-meetings): await caption readiness

* fix(teams-meetings): surface caption blockers

* fix(teams-meetings): retry transient media playback

* chore(teams-meetings): defer release notes

* refactor(meeting-bot): isolate navigation error helper

* test(teams-meetings): keep page control helper private

* fix(meeting-bot): bound caption lifecycle cleanup

* chore(plugin-sdk): refresh API baseline

* test(teams-meetings): split caption ownership coverage

* fix(teams-meetings): retry pending audio routing

* fix(teams-meetings): retain leave transition ownership

* fix(teams-meetings): refresh transcript target

* fix(teams-meetings): bound audio routing retries

* fix(teams-meetings): retry pending remote audio

* fix(teams-meetings): harden media source ownership
2026-07-18 15:57:22 +01:00
Peter Steinberger
a115af2774 feat(ui): add reactive OpenClaw health nudges (#110708)
* feat(ui): add reactive custodian health nudges

* fix(ui): distinguish stopped channels from startup failures

* test(ui): update custodian route gateway fixture

* fix(ui): preserve current channel health failures

* fix(ui): ignore recovered channel errors
2026-07-18 15:44:29 +01:00
Peter Steinberger
0acece4591 feat(chat): rewind and fork a session from a message bubble (#110660)
* feat(chat): rewind and fork a session from a message bubble

* docs(web): document chat rewind and fork bubble actions

* fix(chat): lint cleanups, protocol regen, and test splits for rewind/fork CI

* fix(ui): fit chat rewind disabled styles inside the startup CSS budget
2026-07-18 14:46:34 +01: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
42133d0c3c feat(mac): show native notification permission in dashboard Notifications settings (#110646)
* feat(mac): show native notification permission in dashboard Notifications settings

The Mac app's embedded Control UI showed the web-push section as
Unsupported/Not subscribed even though the app delivers notifications
natively. The dashboard now installs an openclawNotifications WebKit
bridge (status / request-permission / send-test) and the Notifications
settings page renders native permission state with Enable, Open System
Settings, and Send test actions when hosted in the Mac app. Browsers
keep the existing web-push UI. The notifications section renderer moved
out of the oversized config view module.

* fix(ui): break config view import cycle and satisfy lint/deadcode/i18n gates

Move the notifications section props to a leaf contract (no view.ts
type import), unexport the status-event constant, use bracket access
for the injected dunder global, default-case the status switch, and
refresh the native i18n inventory line offset.
2026-07-18 14:13:06 +01:00
Peter Steinberger
1cddec35f4 feat(clients): session groups, batch actions, inspector, and worktree-aware creation for native chat (#110347)
* feat(clients): gateway session groups, batch operations, session inspector, and new-session options

* chore(i18n): translate session management strings and regenerate catalogs

* chore(i18n): complete translation artifacts for session management strings

* fix(clients): fail closed when a transport cannot honor agent or base-ref session options

* fix(clients): authoritative agent identity for new-session parents and revision-keyed sidebar group refresh

* fix(clients): refetch session groups on remote catalog events and correct Swedish repository-root translation

* fix(clients): resilient new-session popover, revision-keyed group manager, and popover string translations

* fix(clients): scope reset fallback to plain new-session requests and revision-key the inspector groups

* fix(clients): reject empty agent catalogs and refresh sessions on remote group events

* refactor(clients): drop unused agents fetch wrapper and runtime memberwise init flagged by periphery

* chore(i18n): realign locale artifacts after rebase onto model-controls main

* chore(clients): split session creation into the session-actions extension and realign i18n after ask-user main rebase

* chore(i18n): resync derived artifacts after question-card main rebase
2026-07-18 14:09:42 +01:00
Peter Steinberger
40793e6f8b fix: bound pasted input and provider response bodies (#110627)
* refactor(runtime): centralize bounded I/O handling

* fix(runtime): finalize bounded I/O contracts

* chore(security): drop stale audit import

* docs(changelog): credit bounded I/O fixes

Co-authored-by: Pick-cat <huang.ting3@xydigit.com>

* fix(agents): keep provider HTTP options private

* fix(ai): traverse OpenAI schema maps by value

* fix(runtime): preserve absolute download deadlines

* ci(ui): stabilize compressed CSS budget

* fix(ai): traverse legacy schema applicators

---------

Co-authored-by: Pick-cat <huang.ting3@xydigit.com>
2026-07-18 13:54:56 +01:00
Peter Steinberger
28069db63a feat(macos): render system chat option cards (#110584)
* feat(macos): render system chat option cards

* fix(macos): localize question card controls

* test(macos): stabilize main actor attachment tests
2026-07-18 13:23:59 +01:00