Commit Graph

16336 Commits

Author SHA1 Message Date
Peter Steinberger
c11d112b63 refactor(codex): deduplicate sandbox HTTP test setup (#109229) 2026-07-16 10:12:31 -07:00
Peter Steinberger
a726bd7340 fix(qa): retry transient FTS settle races 2026-07-16 18:11:50 +01:00
Peter Steinberger
e71ef76e8e feat(onboarding): offer detected Claude Code/Codex/Hermes memory imports across CLI, macOS, and Linux onboarding (#108977)
* feat(migrate): add Hermes memory-only import and a shared memory-import core

* feat(onboarding): offer detected memory imports during CLI setup and guided onboarding

* feat(ui): show a first-run memory-import offer in Control UI onboarding mode

* feat(linux-app): open the first-run dashboard in onboarding mode

* feat(macos): add the onboarding memory-import page

* docs: document the onboarding memory-import page across surfaces

* chore(i18n): translate onboarding memory-import strings for control-ui and native locales

* refactor: keep memory-import internals unexported for deadcode gates

* fix(ci): resolve lint findings in onboarding memory import

* chore(i18n): refresh native inventory after lint refactor

* fix(ci): skip updater artifacts in the unsigned Linux companion PR lane

* chore(i18n): reconcile locale artifacts after rebase
2026-07-16 10:10:01 -07:00
Alix-007
7da3bc9872 fix(acpx): prevent process cleanup from hanging (#109146)
* fix(acpx): bound process inspection

* docs(changelog): note ACPX cleanup deadline

Co-authored-by: Alix-007 <li.long15@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 10:08:56 -07:00
Peter Steinberger
4dc67161ee fix(qa): harden gateway process cleanup 2026-07-16 17:51:26 +01:00
Monkey-wusky
f193c50577 fix(codex): preserve sandbox HTTP UTF-8 diagnostics (#108618)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 09:47:07 -07:00
Peter Steinberger
d4d7b80431 refactor(feishu): remove comment retry test seam (#109192) 2026-07-16 09:46:29 -07:00
Dallin Romney
303be5e0e4 fix(qa): label static scorecard data as inventory (#108784) 2026-07-16 09:43:51 -07:00
wahaha1223
0903ebe4fa fix(xai): release realtime reconnect delay on close (#108252)
* fix(xai): cancel realtime reconnect backoff on close

* test(xai): cover reconnect after bridge close

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 09:40:49 -07:00
Peter Steinberger
8bf4d388b0 fix(onepassword): disable desktop-app integration on broker op calls (#109157)
Without OP_LOAD_DESKTOP_APP_SETTINGS=false and OP_BIOMETRIC_UNLOCK_ENABLED=false,
op 2.35 on macOS reads the 1Password desktop app's settings even on the
service-account path and can block on a per-PID App Data Protection dialog,
hanging the broker until timeoutMs on Mac gateway hosts.
2026-07-16 09:15:03 -07:00
Peter Steinberger
8c676623b7 fix(discord): open newest activity widget when launch ID is missing (#108817)
* fix(discord): open latest activity widget on fallback

* chore: remove release-owned changelog entry

* fix(discord): order activity fallback by delivery

* fix(discord): require atomic widget delivery updates

* test(discord): type activity delivery fixtures

* test(discord): model missing atomic state support

* fix(discord): order activity fallback by message snowflake

* docs(discord): clarify activity fallback order
2026-07-16 09:11:55 -07:00
Peter Steinberger
14bb0b4e52 refactor(discord): deprecate abort signal helper (#109166) 2026-07-16 09:08:00 -07:00
wangmiao0668000666
813021fa79 fix(feishu): honor abortSignal in drive comment reply retry loop (#108408)
* fix(feishu): honor abortSignal in drive comment reply retry loop

The inter-attempt delay in monitor.comment.ts used a bare setTimeout and
never received the owning monitor account's AbortSignal, so an account
teardown (ws disconnect, webhook stop, config reload) left the in-flight
comment reply retry running for up to ~6s after the rest of the lifecycle
settled. delayMs now wraps waitForAbortableDelay from async.ts and the
abortSignal is threaded through fetchDriveCommentContext →
resolveDriveCommentEventTurn → handleFeishuCommentEvent →
createFeishuDriveCommentNoticeHandler, sourced from
monitorSingleAccount.

The retry loop checks the waitMs return value and the abortSignal flag,
breaking out of the next 1s tick instead of running the full 6×1s poll
budget. Sibling surface monitor.bot-identity.ts already uses the same
pattern; #104431 explicitly skipped the comment-monitor retry because
it is a result-predicate poll, not an error retry, and this fix is
orthogonal to that decision.

Not tested: live Feishu tenant, real bot identity, real drive comment,
and account restart. requestFeishuOpenApi itself does not accept
AbortSignal — that is a separate, larger refactor and is out of scope.

* test(feishu): prove comment retry abort

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 09:05:23 -07:00
Peter Steinberger
cd96603f9a fix(codex): show Atlas and ChatGPT sessions in catalog (#109142)
* fix(codex): include all interactive session sources

* chore: remove release-owned changelog entry
2026-07-16 08:55:40 -07:00
Peter Steinberger
0fa77124e9 fix(acpx): migrate codex adapter to maintained @agentclientprotocol/codex-acp (#109075)
* fix(acpx): migrate codex adapter to maintained @agentclientprotocol/codex-acp

The bundled codex ACP adapter pinned the npm-deprecated
@zed-industries/codex-acp@0.16.0, which embeds codex crates from the
rust-v0.137.0 era: GPT-5.6-era models are unknown to it and sessions fail
with 'requires a newer version of Codex'. Migrate to the maintained
@agentclientprotocol/codex-acp@1.1.4 (Node CLI, depends on @openai/codex
^0.144.4 matching the codex plugin pin):

- Wrapper generation resolves the adapter bin from its package manifest and
  delivers startup config via CODEX_CONFIG; OpenClaw-owned wrapper args are
  stripped before launch. Explicit new-adapter commands keep their own
  -c/--config args untouched; only retired Zed commands migrate, with their
  -c TOML overrides (dotted/quoted keys, attached forms, MCP config)
  faithfully converted.
- Model overrides emit the bare model id plus a separate
  model_reasoning_effort; composite model/effort ids are accepted as parse
  input but never emitted.
- Process reaper recognizes the maintained adapter tree and packaged codex
  app-server children without claiming native codex plugin processes.

Live proof: direct adapter smoke with local subscription auth initialized
1.1.4, advertised model gpt-5.6-sol with separate medium effort, and
completed a turn. Fixes #108664

* fix(acpx): pin codex-acp 1.1.2 to satisfy the lockfile release-age gate

1.1.4 is under the 48-hour minimumReleaseAge and fails lockfile
verification repo-wide. 1.1.2 (2026-07-09) passes the gate, carries the
same CODEX_CONFIG startup contract, and its ^0.144.0 codex dependency
resolves to the same 0.144.4 the codex plugin pins. Lockfile re-resolved
from main without any release-age bypass; shrinkwrap regenerated.

* chore(acpx): split oversized auth-bridge test file, register adapter as CLI-resolved dep

codex-auth-bridge.test.ts crossed the max-lines gate after the migration
regressions; the command-migration cluster moves to
codex-auth-bridge.migration.test.ts. knip's CLI-resolved dependency list
swaps the retired zed adapter for @agentclientprotocol/codex-acp (invoked
via generated wrapper/npx, never imported).
2026-07-16 08:51:30 -07:00
Peter Steinberger
c46cc1e2d4 refactor(channels): unify inbound replay protection (#109117)
* refactor(channels): unify inbound replay-guard orchestration on shared factory

* fix(plugin-sdk): bind replay-guard settlement to claim handles

* fix(plugin-sdk): claim-handle settlement (rest)

* fix(discord): align skipped queue cleanup

* style(feishu): simplify bot menu claim settlement

* refactor(plugin-sdk): extract replay dedupe contracts
2026-07-16 08:46:34 -07:00
xingzhou
d15e84610a fix(discord): keep voice allowlists from granting owner authority (#108813)
* fix(discord): keep voice allowlists from granting owner authority

* fix(discord): normalize wildcard voice admission

* refactor(discord): separate voice admission from ownership

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 08:44:42 -07:00
sunlit-deng
9c08675852 fix(voice-call): ignore blank provider environment values (#108816)
* fix(voice-call): ignore blank provider environment values

* refactor(voice-call): reuse shared credential resolver

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 08:39:39 -07:00
qingminlong
ac3635b50c fix(qa-lab): keep child output UTF-8 safe when capped (#108156)
* fix(qa-lab): keep child output UTF-8 safe when capped

* fix(qa-lab): preserve uncapped malformed output

Co-authored-by: qingminlong <34085845+qingminglong@users.noreply.github.com>

* refactor(qa-lab): keep utf8 repair plugin-local

Co-authored-by: qingminlong <34085845+qingminglong@users.noreply.github.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 08:35:42 -07:00
Wynne668
38448750eb fix(openai): stop realtime voice reconnects promptly on close (#108209)
* fix(openai): cancel realtime reconnect backoff on close

* test(openai): cover reconnect after bridge close

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 08:27:36 -07:00
wahaha1223
aaa37a0c26 fix(googlechat): ignore blank service account env during setup (#108948) 2026-07-16 08:11:11 -07:00
wahaha1223
77f9da5461 fix(synology-chat): ignore blank token accounts (#108922) 2026-07-16 07:51:16 -07:00
Peter Steinberger
12786fe07d test: speed up timeout and pairing suites (#108863) 2026-07-16 07:47:32 -07:00
Peter Steinberger
2bd1a63075 feat: add Baseten Model API provider (#108708)
* feat: add Baseten model provider

* test: satisfy Baseten provider lint

* fix: align Baseten thinking controls

* docs: refresh Baseten documentation metadata

* fix: preserve Baseten DeepSeek replay metadata

* docs: remove release-owned Baseten changelog entry
2026-07-16 07:41:33 -07:00
Peter Steinberger
44314c9451 refactor(channels): table-drive setup and control-plane helpers (#109028)
* refactor(channels): table-drive setup credentials, config schemas, doctor detectors, status issues

* refactor(channels): control-plane tables (rest)

* fix(plugin-sdk): refresh surface budgets after rebase

* style(plugin-sdk): format credential helpers

* fix(channels): preserve generic schema refinement types

* fix(channels): preserve schema input and output inference

* fix(clickclack): forward credential patch fields

* test(plugin-sdk): use redacted credential fixtures

* fix(plugin-sdk): refresh API baseline after inference fix

* fix(channels): keep multi-account envelope optional

* fix(channels): preserve policy validation invariants

* fix(extensions): remove stale awaits from file checks

* style(qqbot): format synchronous file check

* fix(config): refresh bundled channel metadata

* fix(qqbot): reject unsupported pairing policy
2026-07-16 07:17:01 -07:00
Peter Steinberger
0340d7c0c1 fix(tts): normalize sibling provider credentials (#109051) 2026-07-16 07:08:42 -07:00
Erick Kinnee
a1ed5e7b3c fix(acp): skip unsupported automatic thinking config in manager gate (#108392)
* fix(acp): skip unsupported automatic thinking config in manager gate

When an ACP backend does not advertise thinking-related config options
(e.g. OpenCode advertising only mode/model), the manager's automatic
startup-control path would reject the session with
ACP_BACKEND_UNSUPPORTED_CONTROL.

Fix:
- Add THINKING_CONFIG_KEYS set and isThinkingConfigKey helper to
  manager.runtime-controls.ts, following the existing OPTIONAL_TIMEOUT_CONFIG_KEYS pattern
- Skip thinking keys in the advertised-keys validation gate (auto-derived
  options are best-effort)
- Skip unsupported-control rejection for thinking keys at the
  setConfigOption catch level
- Extract isUnsupportedControlRejection helper to avoid duplicating the
  error code check
- Forward getCapabilities input handle in ACPX runtime so session-scoped
  capability queries work
- Inject thinking/thought_level aliases for Codex ACP sessions when
  reasoning_effort is advertised

Closes #103802

* fix(acp): honor thinking control capabilities

---------

Co-authored-by: Erick Kinnee <erick@ekinnee.dev>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 07:03:15 -07:00
LavyaT
a24cf632c7 fix(anthropic): align exact Claude 1M model limits (#108751)
* fix(anthropic): declare GA 1M context window for opus-4-7/sonnet-4-6/opus-4-6 (issue #108152)

* test(anthropic): cover corrected context resolution

* fix(anthropic): align exact Claude model limits

* fix(anthropic): scope Claude CLI output limits

* fix(anthropic): preserve plan-safe Claude CLI context

* test(anthropic): align status context expectations

* test(anthropic): align gateway context expectations

* test(anthropic): align lookup context expectations

* test(anthropic): align CLI status context

* test(anthropic): align CLI reseed context cap

---------

Co-authored-by: Lavya Tandel <lavya@loom.local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 06:48:56 -07:00
Peter Steinberger
a50dd6276b refactor(test): complete channel activity runtime mock (#109022) 2026-07-16 06:45:28 -07:00
lsr911
d2e9fa22bc fix(gradium): treat blank env API key as unconfigured in synthesis paths (#108800)
* fix(gradium): treat blank env API key as unconfigured in synthesis paths

The isGradiumProviderConfigured helper already uses trimToUndefined on
GRADIUM_API_KEY, but synthesize and synthesizeTelephony still used the
bare env var. This made whitespace-only credentials pass the
missing-key guard and send unusable bearer tokens.

- Wrap process.env.GRADIUM_API_KEY with trimToUndefined in synthesize
- Wrap process.env.GRADIUM_API_KEY with trimToUndefined in
  synthesizeTelephony
- Add test for whitespace-only env key rejection in synthesize

This completes the blank-credential guard for the Gradium provider,
matching the pattern from OpenAI (#108212), Xiaomi (#108558),
Deepgram (#108565), and Inworld (#108783).

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

* fix(gradium): centralize speech API key resolution

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 06:29:47 -07:00
Peter Steinberger
e3f343bd53 fix(codex): preserve Unicode in stderr tails (#109013) 2026-07-16 06:04:03 -07:00
lsr911
7a81f29980 fix(inworld): treat blank env API key as unconfigured in speech provider (#108783)
* fix(inworld): treat blank env API key as unconfigured in speech provider

A whitespace-only INWORLD_API_KEY made the Inworld speech provider
report configured, then sent an unusable bearer credential from
synthesis, telephony synthesis, and voice listing.

- Wrap process.env.INWORLD_API_KEY with trimToUndefined in isConfigured
  so blank values are treated as not configured
- Wrap process.env.INWORLD_API_KEY with trimToUndefined in synthesize,
  synthesizeTelephony, and listVoices so blank values are rejected
  locally before any network request
- Add test coverage for whitespace-only env key in isConfigured and
  synthesize paths

This matches the blank-credential guard pattern applied in the OpenAI
(#108212), Xiaomi (#108558), and Deepgram (#108565) providers.

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

* fix(inworld): centralize speech API key resolution

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 05:55:55 -07:00
Alix-007
ee70f20fed fix(qa): stop Docker startup hangs on stalled health checks (#108992)
* fix(qa): bound Docker health probe deadlines

* fix(qa): race Matrix health candidates

Co-authored-by: Alix-007 <li.long15@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 05:51:38 -07:00
Andrey Gruzdev
878f55c4c2 fix: text-only Mattermost replies fail with blank attachment fields (#108281)
* fix(mattermost): ignore blank attachment payload fields

* test(mattermost): prove blank placeholder send path

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 05:46:48 -07:00
mushuiyu886
576a222da2 fix(codex): preserve split UTF-8 in app-server stderr (#108335) 2026-07-16 05:41:56 -07:00
Yehonal
175181f42f fix(discord): suppress typing when hooks silently handle a turn (#108449)
* fix(discord): defer typing until reply dispatch is accepted

* fix(discord): preserve typing for accepted fast replies

* refactor(discord): create typing feedback after admission

* refactor(discord): keep queue key resolver internal

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 05:30:42 -07:00
sunlit-deng
f643fc3c97 fix(minimax): ignore blank environment API key (#108777)
* fix(minimax): ignore blank environment API key

* fix(minimax): centralize TTS API key resolution

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 05:26:33 -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
lsr911
df7fcef4b5 fix(xiaomi): treat blank env API key as unconfigured in speech provider (#108558)
* fix(xiaomi): treat blank env API key as unconfigured in speech provider

A whitespace-only XIAOMI_API_KEY made the Xiaomi MiMo speech provider
report configured, then sent an unusable bearer credential from synthesis.

- Wrap process.env.XIAOMI_API_KEY with trimToUndefined in isConfigured
  so blank values are treated as not configured
- Wrap process.env.XIAOMI_API_KEY with trimToUndefined in synthesize
  so blank values are rejected locally before any network request
- Add test coverage for whitespace-only and blank env key in both paths

This matches the blank-credential guard applied in the OpenAI speech
provider (PR #108212).

* refactor(xiaomi): centralize speech key resolution

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 05:05:03 -07:00
qingminlong
552fd224cf fix(opencode): reject output stream failures in session catalog (#108218)
* fix(opencode): reject output stream failures in session catalog

* test(opencode): format stream failure regression

* test(opencode): prove output pipe failure cleanup

Co-authored-by: qingminlong <qing.minlong@xydigit.com>

* test(opencode): satisfy pipe proof lint

Co-authored-by: qingminlong <qing.minlong@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 04:57:28 -07:00
Peter Steinberger
e1fda44ecc fix(onepassword): preserve oversized token diagnostics (#108964) 2026-07-16 04:52:36 -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
48866bbc40 fix(memory): preserve linked MEMORY.md during promotion (#108921)
* fix(memory): preserve promotion symlink targets

Follow-up to #108397.

* fix(memory): retain writable-target compatibility

* fix(memory): prove atomic rename stage
2026-07-16 04:46:29 -07:00
Peter Steinberger
3f25f4b5fc fix(doctor): stop duplicating state schema migration labels (#108947)
* fix(doctor): distinguish state schema migrations

* fix(doctor): enforce migration formatter exhaustiveness

* docs(changelog): note state schema reporting fix

* docs(changelog): keep release note in PR body
2026-07-16 04:37:36 -07:00
Peter Steinberger
990e8d24b0 feat(presentation): hosted-widget launch via typed web-app actions (#108927)
* feat(presentation): support hosted widget actions

* refactor(discord): route widget launches through presentation

* chore: keep changelog release-owned

* test(interactive): type the invalid web-app boundary case explicitly

* test: type web-app action fixtures against the split union

The two-member web-app union no longer accepts a distributed
type: "url" | "web-app" literal or an empty receipt in typed
callbacks; use explicit action casts and the Discord receipt factory.
2026-07-16 04:35:31 -07:00
sunlit-deng
c4e696d1ba fix(vydra): ignore blank environment API key (#108757)
* fix(vydra): ignore blank environment API key

* refactor(tts): centralize speech API key resolution

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

* chore(plugin-sdk): pin speech resolver surface

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 04:33:25 -07:00
wahaha1223
549322a5f2 fix(nextcloud-talk): bound API password file reads (#108321) 2026-07-16 04:33:05 -07:00
Peter Steinberger
f7a665aaa1 refactor(clickclack): deduplicate gateway event fixtures (#108942) 2026-07-16 04:28:10 -07:00
Wynne668
f1f4b8ae8d fix: keep image attachments when steering active runs (#107657)
* fix: preserve images during active-run steering

* fix(codex): preserve steering fallback order

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>

* test(codex): satisfy strict steering assertions

Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 04:23:03 -07:00
zhanxingxin1998
5810de21b9 fix(clickclack): prevent reconnect from skipping in-flight events (#108577)
* fix(clickclack): commit websocket cursors after processing

Serialize realtime events and wait for queued handlers before reconnecting so only successfully processed cursors advance.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* fix(clickclack): replay failed websocket events

Keep the last successful cursor when realtime handling fails, then reconnect through durable backlog recovery before reopening the stream.

Co-authored-by: 詹幸心0668001037 <zhan.xingxin@xydigit.com>

---------

Co-authored-by: OpenAI Codex <noreply@openai.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-16 04:12:54 -07:00