Commit Graph

277 Commits

Author SHA1 Message Date
Peter Steinberger
24d94a54a5 fix: migrate QQBot credential backups to SQLite KV (#89597)
* fix: migrate qqbot credential backups to sqlite kv

* fix: complete qqbot sqlite migration cleanup

* fix: harden qqbot doctor state migration
2026-07-01 20:03:59 +01:00
Patrick Erichsen
56c2d637d9 fix(qqbot): tighten bundled skill guardrails (#98032) 2026-06-29 22:48:52 -07:00
Vincent Koc
c0ee7a1d20 test: gate symlink assertions on file symlink capability (#95531)
Co-authored-by: ANIRUDDHA ADAK <127435065+aniruddhaadak80@users.noreply.github.com>
2026-06-28 22:50:37 -07:00
ly-wang19
3e64d84712 fix(qqbot): treat escaped pipes as literal content when splitting table cells (#97429)
splitTableCells/splitPartialTableCells split on every '|', including a GFM
backslash-escaped pipe ('\|'), which is literal cell content rather than a
column delimiter. A cell containing '\|' was therefore mis-counted as multiple
columns, so the oversized-row fallback (renderTableRowAsFields) rendered the
trailing content under the wrong header.

Split via an escape-aware scan that treats '\|' as a literal '|' (and '\\' as
a literal backslash so a following '|' still delimits). Behavior is byte-for-byte
unchanged for any row without an escaped pipe, so existing chunking is preserved.

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 12:03:52 -07:00
llagy009
d693ed4af3 fix(qqbot): truncate reminder job name on code-point boundary (#96575)
generateJobName truncated reminder content with String.slice(0, 20) on
a UTF-16 code-unit index, so an astral character (e.g. an emoji) landing
on the boundary was cut into a lone surrogate, producing a malformed
cron job name.

Truncate with the shared truncateUtf16Safe helper so a surrogate pair is
never split, keeping the existing 20-unit budget and ellipsis suffix.

Adds a test asserting the truncated job name contains no lone surrogate.
2026-06-27 09:30:52 -07:00
mushuiyu886
6e8f30c0e2 fix(qqbot): bound STT transcription JSON response (#96968) 2026-06-27 07:25:29 -07:00
joshavant
0a14444924 Bound successful provider response reads 2026-06-24 19:08:22 -05:00
Sliverp
9535b102d3 Gate private QQBot group commands (#92154)
* fix: gate private qqbot group commands

* fix(qqbot): keep authorized stop urgent in groups

* fix(qqbot): preserve omitted group command level

* fix(qqbot): preserve ignore-other-mentions gate

* test(qqbot): avoid unbound mention gate mock

* fix(qqbot): close strict command visibility gaps

* fix(qqbot): gate private group commands and close strict command visibility gaps (#92154) (thanks @sliverp)
2026-06-23 17:20:50 +08:00
ANIRUDDHA ADAK
82316c2f45 test: make qqbot symlinked media helper test robust on Windows
Gate the QQ Bot symlink-media helper regression test on actual file-symlink capability, so environments that cannot create file symlinks skip that specific test while capable hosts still run it.

Validation:
- Windows Vitest proof in the PR body: `extensions/qqbot/src/engine/utils/file-utils.test.ts` passed with 4 tests passed and 1 symlink test skipped when file symlinks were unavailable.
- Current CI is clean at `cb7d5a162e24f7ec5be6985e97b2b74ae45b20f9`, including the refreshed Real behavior proof run `27992101343`.

Co-authored-by: Aniruddha Adak <aniruddhaadak80@users.noreply.github.com>
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
2026-06-23 07:54:53 +08:00
ly-wang19
d63389ccf6 fix(qqbot): recognize GFM table separators with one or two dashes (#95637)
`isTableSeparatorLine` required 3+ dashes per cell (`/^:?-{3,}:?$/`), but a
GFM delimiter cell needs only one or more dashes. So a valid table whose
separator used 1 or 2 dashes (e.g. `|--|--|`) was not recognized: the header
stayed pending and was silently overwritten by each following row, so the
table's header, separator, and every row but the last vanished from the sent
message.

Accept `-+` so valid GFM separators are recognized, matching the spec and the
sibling LINE channel. Every existing test separator already uses 3+ dashes, so
they are byte-identical.

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 18:27:01 +00:00
Vincent Koc
5c19699cb2 chore(deadcode): remove qqbot duplicate wrappers 2026-06-20 16:41:41 +08:00
Vincent Koc
9e5ac0cea4 refactor(extensions): drop stale internal declarations 2026-06-20 02:52:05 +08:00
Vincent Koc
37962aac95 test(qqbot): keep stt temp helper on sdk surface 2026-06-19 17:03:16 +02:00
Vincent Koc
a876f8d073 fix(qqbot): bound chunked upload error bodies 2026-06-19 17:03:16 +02:00
Vincent Koc
e0d58d994d fix(qqbot): bound stt error bodies 2026-06-19 16:44:51 +02:00
Vincent Koc
b16fd6bee7 test(qqbot): fix channel api bounded body assertion 2026-06-19 16:35:55 +02:00
Vincent Koc
51ebe87a09 fix(qqbot): guard channel api fetches 2026-06-19 16:30:53 +02:00
Vincent Koc
ed8ab712dc fix(qqbot): guard api client fetches 2026-06-19 16:14:19 +02:00
Vincent Koc
8594af21e9 fix(qqbot): bound token response bodies 2026-06-19 16:14:19 +02:00
Vincent Koc
772158c716 fix(qqbot): bound api error bodies 2026-06-19 15:30:29 +02:00
Vincent Koc
350aa7c3be refactor(extensions): remove unused helper facades 2026-06-19 01:05:26 +08:00
Vincent Koc
58b77e787d refactor(extensions): remove unused helper exports 2026-06-18 15:05:35 +08:00
Vincent Koc
0aa6b8ca0d refactor(qqbot): dedupe approval capability state 2026-06-18 13:03:55 +08:00
Vincent Koc
4681a559c0 refactor(qqbot): hide response timeout default 2026-06-17 10:47:01 +08:00
Vincent Koc
ff5d6571f2 test(qqbot): avoid bare temp dirs in media path coverage 2026-06-16 20:44:48 +02:00
ZengWen-DT
cfdcd5cdfd fix(qqbot): deliver cron auto-TTS voice by trusting OpenClaw temp root (#92947)
QQBot is the only channel that root-sandboxes outbound local files. Its three
gate sites (resolveOutboundMediaPath, the voice send re-check, and
structured-payload validation) only trusted the QQ Bot media storage roots, so
framework-generated scratch media written under OpenClaw's hardened temp root
(e.g. cron auto-TTS voice files from speech-core) was rejected. The send then
returned a no-identity error, the message was silently lost, yet cron still
recorded it as delivered.

Add one shared resolver (resolveTrustedOutboundMediaPath) that also trusts the
preferred OpenClaw temp root — already a sanctioned media root in core
(buildMediaLocalRoots) — and route all three gates through it so the trust set
agrees everywhere. Fixes #92816.

Co-authored-by: zengwen <zeng_wen@foxmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 02:11:52 +08:00
Sliverp
e7ee1c55b4 fix(qqbot): keep markdown table chunks valid (#92428)
* fix(qqbot): keep markdown table chunks valid

* fix(qqbot): keep markdown table chunks valid across message boundaries (#92428) (thanks @sliverp)

Co-authored-by: sliverp <870080352@qq.com>
2026-06-15 18:32:25 +08:00
zhang-guiping
650c5cac33 fix(qqbot): surface failed media sends (#92823)
* fix(qqbot): surface media send failures

* test(qqbot): cover text send failures

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-14 11:13:56 +08:00
Vincent Koc
3883d7365e fix(qqbot): guard silent-final tool flushing 2026-06-11 20:09:55 +09:00
Sliverp
7e88c287a1 fix(qqbot): flush tool output before silent non-streaming final (#92074)
* fix(qqbot): flush tool output before silent non-streaming final

* fix qqbot silent final delivery

* chore: drop local plugin runtime helper

* fix: suppress stale qqbot tool flush

* fix(qqbot): flush tool output before silent non-streaming final (#92074) (thanks @sliverp)

---------

Co-authored-by: Ubuntu <ubuntu@localhost.localdomain>
2026-06-11 18:28:32 +08:00
Vincent Koc
7f1d82ab25 revert(sessions): defer session metadata sqlite
Reverts 538d36eaaa while preserving subsequent main changes. The beta-only SQLite downgrade rescue and reverse migration remain excluded.
2026-06-10 16:34:06 +09:00
Vincent Koc
cd0bca0823 test(qqbot): reduce group allways command scaffolding 2026-06-09 17:34:23 +09:00
cxy
d12b7b0551 feat(qqbot): add /bot-group-allways command to toggle mention requirement (#91423)
* feat(qqbot): add /bot-group-allways command to toggle group mention requirement

Add slash command to configure defaultRequireMention for qqbot accounts.
Clear runtime config snapshot cache after config write to ensure
getRuntimeConfig() reads fresh values on next message.

- Add register-group-allways command (on/off/status)
- Support named accounts and default account
- Clear runtime config cache after write for immediate effect
- Add unit tests for group config resolution

* test(qqbot): fix group allways test imports

* feat(qqbot): add /bot-group-allways command to toggle group mention requirement (#91423) (thanks @cxyhhhhh)

---------

Co-authored-by: sliverp <870080352@qq.com>
2026-06-09 15:43:12 +08:00
Peter Steinberger
538d36eaaa refactor: move session metadata to SQLite (#91322)
* refactor: move session metadata to sqlite

* test: seed session stores with sqlite fixtures

* test: seed remaining session stores with sqlite fixtures

* fix: stabilize sqlite session cache freshness

* test: seed cli transcript metadata in sqlite
2026-06-07 23:17:35 -07:00
Peter Steinberger
6f2b3830f1 fix(qqbot): migrate group tool policy config (#91128)
* fix(qqbot): migrate group tool policy config

* test: stabilize changed check lanes

* style: format changed main files

* test: align CI matrix expectations
2026-06-07 02:33:06 -07:00
Dallin Romney
ebabf5022f perf(qqbot): narrow tool discovery cold load (#90780)
* perf: narrow qqbot tool discovery load

* fix(qqbot): load bridge entries through sidecars
2026-06-07 00:41:11 -07:00
Chunyue Wang
1a3ce7c2a8 fix(qqbot): sanitize outbound text to strip reasoning/thinking content (#90132)
Summary:
- Adds QQBot outbound `sanitizeText` wired to `sanitizeAssistantVisibleText` plus a regression test for stripping `<thinking>` and `<think>` blocks.
- PR surface: Source +2, Tests +19. Total +21 across 2 files.
- Reproducibility: yes. source-reproducible: current main QQBot outbound lacks `sanitizeText`, and shared deli ... nnel text sanitization when that hook exists. I did not run a live Tencent QQBot plus MiniMax reproduction.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(qqbot): add curly braces for eslint(curly) compliance

Validation:
- ClawSweeper review passed for head 17cf140183.
- Required merge gates passed before the squash merge.

Prepared head SHA: 17cf140183
Review: https://github.com/openclaw/openclaw/pull/90132#issuecomment-4618527026

Co-authored-by: openperf <16864032@qq.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-06-05 06:57:16 +00:00
Peter Steinberger
6868cde4d4 docs: document large extension sources 2026-06-04 21:40:44 -04:00
Shakker
f3128f92d0 test: scope qqbot path env 2026-06-04 23:06:33 +01:00
Peter Steinberger
6467ddd7ed fix(qqbot): migrate state stores to sqlite kv
Move QQBot credential backups, gateway sessions, known-user records, and ref-index rows into plugin SQLite KV stores. Import shipped JSON/JSONL state files on first use and keep auxiliary known-user/ref-index state best-effort so message delivery is not blocked by cache persistence failures.
2026-06-02 08:15:19 -04:00
Coy Geek
a14be505ff fix(qqbot): isolate credential backups by state root
QQBot credential backups now resolve under the active OpenClaw state directory instead of the old home-global QQBot data path. This keeps isolated gateway profiles from restoring each other's QQBot appId/clientSecret backups while preserving per-state-root recovery.

Proof: focused QQBot path/storage-laziness Vitest suite passed on Node 24.15.0, focused oxlint passed, source-runtime two-root backup proof passed, exact-head CI run 26814565282 passed, and ClawSweeper re-review run 26815054980 marked proof sufficient.

Closes #84313.

Co-authored-by: Coy Geek <65363919+coygeek@users.noreply.github.com>
2026-06-02 07:11:01 -04:00
Sliverp
0552ec899f fix(qqbot): allow RFC2544 benchmark range for token fetch (#88984) (#89015)
* fix(qqbot): allow RFC2544 benchmark range for token fetch (#88984)

QQ Bot `bots.qq.com` token-fetch path was failing for users whose DNS resolver maps the hostname into the RFC 2544 benchmark range `198.18.0.0/15` (commonly seen with fake-IP proxy stacks: sing-box, Clash, Surge, WSL2 DNS). The default SSRF guard treats that range as private and blocks the request, surfacing as "Network error getting access_token: Blocked: resolves to private/internal/special-use IP address".

Pass a host-scoped `SsrFPolicy` (`allowRfc2544BenchmarkRange: true`) to the single hard-coded `TOKEN_URL` request, mirroring the existing `QQBOT_MEDIA_SSRF_POLICY` pattern used by the media path. Because `TOKEN_URL` is a const and not user-controlled, the relaxation cannot widen attack surface to other hosts.

Adds a regression test asserting `policy: { allowRfc2544BenchmarkRange: true }` is forwarded into `fetchWithSsrFGuard`, and updates the existing equality assertion accordingly.

Fixes #88984

* fix(qqbot): scope token ssrf policy
2026-06-02 15:00:39 +08:00
Peter Steinberger
27dde7a4d6 chore(lint): enable stricter error rules 2026-06-01 01:12:21 +01:00
Peter Steinberger
22cb7fb6b7 chore(lint): enable no-promise-executor-return 2026-05-31 23:06:13 +01:00
Peter Steinberger
b653d94918 chore(lint): enable no-useless-assignment 2026-05-31 22:40:48 +01:00
Peter Steinberger
2df95c0b10 chore(lint): enable no-misused-promises 2026-05-31 20:42:13 +01:00
Peter Steinberger
304e2c83c0 chore(lint): enable stricter oxlint rules 2026-05-31 18:59:02 +01:00
Peter Steinberger
f5eca3f84c chore(lint): enable object and reassignment rules 2026-05-31 09:32:52 +01:00
Peter Steinberger
b9fe0894a6 chore(lint): enable additional cleanup rules 2026-05-31 08:16:11 +01:00
Peter Steinberger
d4d7fdbc59 fix(ci): satisfy strict nullish guards 2026-05-31 02:50:24 -04:00