Commit Graph

15788 Commits

Author SHA1 Message Date
Peter Steinberger
d185f9a0b4 fix(infra): preserve characters in truncated response snippets (#103136)
* fix(infra): preserve bounded response text characters

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

* ci(plugin-sdk): refresh API baseline

---------

Co-authored-by: qingminlong <34085845+qingminglong@users.noreply.github.com>
2026-07-09 23:43:26 +01:00
Alix-007
2f057e1be7 fix(tlon): remove auth retry abort listener after delay (#101661)
* fix(tlon): remove auth retry abort listener after delay

* fix(tlon): reuse abort-aware retry sleep

Co-authored-by: Alix <267018309+Alix-007@users.noreply.github.com>

* test(tlon): complete runtime fixture

* test(infra): cover abortable sleep cleanup

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 23:04:19 +01:00
clawsweeper[bot]
90b68536c4 fix(twitch): strip internal tool-trace banners from outbound text (#103109)
* fix(twitch): strip internal tool-trace banners from outbound text

Co-authored-by: Masato Hoshino <246810661+masatohoshino@users.noreply.github.com>

* fix(twitch): strip internal tool-trace banners from outbound text

---------

Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: Masato Hoshino <246810661+masatohoshino@users.noreply.github.com>
2026-07-09 22:39:03 +01:00
Peter Steinberger
676cf03f7d ci(release): retry transient MiniMax image failures (#103114) 2026-07-09 22:33:33 +01:00
Alix-007
a4ae95c1c6 fix(device-pair): resolve QR senders by own key (#101652)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 22:31:07 +01:00
Alix-007
f8efe14639 fix(discord): add timeouts to voice upload requests (#102863)
* fix(discord): add timeouts to voice upload requests

* fix(discord): refine voice upload timeouts

Use the normalized REST timeout for upload negotiation and the existing attachment transfer budget for the signed audio upload. Reuse the shared loopback test harness and verify both hanging sockets close.

Thanks @Alix-007 for the original timeout fix.

Co-authored-by: llagy009 <0668001470@xydigit.com>

---------

Co-authored-by: llagy009 <0668001470@xydigit.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 22:15:13 +01:00
VACInc
740e7687e8 fix(anthropic): don't crash models list when a configured Sonnet 5 model has no cost (#102186)
* fix(anthropic): don't crash models list when a configured Sonnet 5 model has no cost

applyAnthropicSonnet5Cost read params.model.cost.input unconditionally, so
'openclaw models list' aborted with 'Cannot read properties of undefined
(reading input)' whenever config supplied an anthropic Sonnet 5 model row
without cost metadata (e.g. an agents.defaults.models runtime binding).
Guard with optional chaining — a costless model now falls through and gets
the canonical Sonnet 5 cost applied.

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

* fix(models): normalize missing Sonnet 5 costs

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>

* chore(plugin-sdk): refresh API baseline

* ci(plugin-sdk): update surface budgets

---------

Co-authored-by: VACInc <3279061+VACInc@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 22:13:56 +01:00
mikasa
ce6cb3b250 fix(openrouter): bound music SSE buffering (#101488)
* fix(openrouter): bound music SSE buffering

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

* fix(openrouter): align music stream bounds with media config

Co-authored-by: mikasa0818 <0668001030@xydigit.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 22:10:44 +01:00
Oliver Mee
ae11ea5ba9 feat(qwen): add Token Plan (Team Edition) provider (#94419)
* feat(qwen): add Token Plan provider

Co-authored-by: Oliver Mee <102673257+Omee11@users.noreply.github.com>

* docs: regenerate documentation map

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Oliver Mee <102673257+Omee11@users.noreply.github.com>
2026-07-09 22:07:01 +01:00
Agustin Rivera
47ec6237ff fix(nvidia): sync recommended models with featured catalog (#99242)
* fix(nvidia): refresh bundled featured models

* fix(nvidia): match featured model feed exactly

* fix(nvidia): remove transient feed detail

* fix(nvidia): correct super context window

* fix(nvidia): align auth choice expectation

* fix(nvidia): hide deprecated models from selection

Refresh the bundled featured catalog while retaining deprecated model metadata for exact-reference compatibility. Route NVIDIA onboarding and catalog picker surfaces through selectable-only provider builders.

* fix(nvidia): simplify featured model table

* fix(nvidia): restore shipped compatibility rows
2026-07-09 13:09:38 -07:00
Bartok
1b03e51e18 fix(qqbot): render safe exec approval previews (#102119)
Render pending approvals from shared typed views, add marked grapheme-safe display wraps for QQ Desktop, preserve the 300 UTF-16-unit cap, fence command and metadata safely, and report plugin expiry from the runtime clock.

Fixes #101979
2026-07-09 20:31:57 +01:00
Vincent Koc
266ca5b3a2 fix(providers): publish Meta provider (#103070) 2026-07-09 12:11:56 -07:00
Peter Steinberger
745b8c315e fix(codex-supervisor): ship CLI metadata entry (#102803)
* fix(codex-supervisor): ship CLI metadata entry

* chore: keep release notes in PR body

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-09 10:31:47 -07:00
Hamid Shojanazeri
08a957e0ae feat(providers): add Meta Model API - muse-spark-1.1 (#102873)
* feat(providers): add Meta Model API - muse-spark-1.1

Adds meta-model-api provider via bundled extension:
- extensions/meta-model-api/ (provider, catalog, stream, thinking, onboarding)
- docs/providers/meta-model-api.md
- core wiring: env-api-keys, zod-schema, provider-display-names, dotenv, provider-env-vars

Model: meta-model-api/muse-spark-1.1 (Responses API at https://api.ai.meta.com/v1)
Auth: MODEL_API_KEY (Bearer)
Default reasoning: high, maps --thinking off -> minimal (model rejects none)

Fix: bump live test maxTokens 200->4000 (high reasoning uses ~300 tokens for reasoning alone)

Co-authored-by: Meta

* fix(meta-model-api): clean reasoning lint

* test(meta-model-api): align live proof checks

* chore(meta-model-api): bundle provider metadata

* docs: fix Meta Model API setup wording

* docs: format Meta Model API provider page

---------

Co-authored-by: Dave Morin <dave@morin.com>
Co-authored-by: Colin <colin@solvely.net>
Co-authored-by: Josh Lehman <josh@martian.engineering>
2026-07-09 10:27:09 -07:00
mushuiyu886
88acda11b8 fix(nextcloud-talk): keep error snippets UTF-16 safe (#102949)
* fix(nextcloud-talk): keep error snippets UTF-16 safe

* test(nextcloud-talk): assert exact safe error

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 18:21:26 +01:00
xingzhou
f1e7081b4d fix(active-memory): recall context breaks when recent turns contain emoji (#102877)
* fix(active-memory): keep recall query snippets utf16-safe

* test(active-memory): exercise recall hook for utf16 bounds

* test(active-memory): detect only unpaired surrogates

* fix(active-memory): bound timeout partials safely

Co-authored-by: 张贵萍0668001030 <zhang.guiping@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 18:03:34 +01:00
Peter Steinberger
3c048ef052 fix(browser): preserve no-display launch diagnostics (#102946)
* fix(browser): preserve no-display launch diagnostics

* chore: keep changelog release-owned
2026-07-09 16:26:18 +01:00
Peter Steinberger
d5fb4903f1 fix(browser): reject credentialed page URLs safely (#102952)
Co-authored-by: bitkyc08 <bitkyc08@gmail.com>
2026-07-09 16:23:17 +01:00
Wynne668
baa009e26f fix(imessage): cap per-chat group-allowlist warn-once cache (#102658)
* fix(imessage): cap per-chat group-allowlist warn-once cache

Replace unbounded perChatWarned Set with createDedupeCache(maxSize=512)
to keep long-running iMessage monitor memory stable. The cache grows
with every distinct group chat the gateway sees; without a cap it can
accumulate entries indefinitely.

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

* fix(imessage): prove warning cache eviction

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 16:16:03 +01:00
Peter Steinberger
8245ae4278 test(whatsapp): freeze reconnect boundary clock (#102942) 2026-07-09 16:11:27 +01:00
Peter Steinberger
36227737c5 fix(slack): preserve standalone reply anchors (#102905)
Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>
2026-07-09 15:56:52 +01:00
Peter Steinberger
743422217e fix(qa): normalize malformed JSON errors (#102830)
Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com>
2026-07-09 15:40:27 +01:00
Peter Steinberger
428c68a3c7 feat: show provider plan usage (5h/weekly/credits) in the chat context popover, keep API cost for API billing (#102784)
* feat(usage): route claude-cli to Anthropic plan usage with plan label and billing

* feat(webchat): redesign context popover with plan-usage bars and API-cost gating

* fix(usage): match plan usage across CLI provider aliases and source plan label from synced auth profile

* docs(plugins): document plan metadata on usage auth token

* chore(usage): document provider-level billing attribution limits, fix overview test types

* fix(webchat): avoid map-spread in quota group collection

* test(webchat): deflake subscription popover reset fixture
2026-07-09 15:36:13 +01:00
Peter Steinberger
f8dbd34ab8 feat(nodes): add computer use (computer.act) on macOS nodes via Peekaboo (#102776)
* feat(nodes): add computer use (computer.act) on macOS nodes via Peekaboo

* fix(nodes): release held computer.act input on node disconnect/stop/disable

* fix(nodes): release held computer.act input armed after a lifecycle release

* fix(nodes): scope computer.act lifecycle catch-up release to the arming action

* chore(nodes): register computer tool display metadata, sync native i18n, doc-comment constants

* fix(nodes): preserve caught-error cause in computer tool resolver; regen docs map
2026-07-09 15:28:09 +01:00
Peter Steinberger
5ef269c2bb fix: keep bounded Unicode text valid across UTF-16 boundaries (#102823)
* fix(text): keep bounded output UTF-16 safe

Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>
Co-authored-by: 0668000539 <shu.zongyu@xydigit.com>
Co-authored-by: 张鹊平0668001085 <zhang.queping@xydigit.com>
Co-authored-by: 赵旺0668001248 <zhao.wang1@xydigit.com>
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: lizeyu-xydt <li.zeyu@xydigit.com>

* chore(changelog): defer release note to automation

* refactor(qa-lab): keep text helper behind SDK

---------

Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>
Co-authored-by: 0668000539 <shu.zongyu@xydigit.com>
Co-authored-by: 张鹊平0668001085 <zhang.queping@xydigit.com>
Co-authored-by: 赵旺0668001248 <zhao.wang1@xydigit.com>
Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com>
Co-authored-by: lizeyu-xydt <li.zeyu@xydigit.com>
2026-07-09 15:21:23 +01:00
LiLan0125
db0f6f09dc fix(google): restore image tool results for prefixed Gemini 2 models (#102382)
* fix(google): handle prefixed Gemini 2 image fallback

* test(google): cover prefixed Gemini 3 image responses

* docs(changelog): note prefixed Gemini fallback

Co-authored-by: 李兰 0668001394 <li.lan3@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 15:09:05 +01:00
wings1029
4c55d46254 fix(imessage): keep CLI stderr tails UTF-16 safe (#102626)
* fix(imessage): keep CLI stderr tail truncation UTF-16 safe

* test(imessage): hit stderr surrogate boundary

* fix(imessage): use plugin sdk text helper

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 15:04:07 +01:00
NIO
2d5dd6c035 fix(googlechat): bound control and media requests (#102227)
* fix(googlechat): add 30 s request timeout to withGoogleChatResponse

* fix(googlechat): satisfy ResolvedGoogleChatAccount in api.test.ts

* fix(googlechat): bound control and media requests

Co-authored-by: NIO <nocodet@mail.com>

---------

Co-authored-by: NIO <nocodet@mail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 14:49:14 +01:00
Peter Steinberger
47cc6c9667 fix(qqbot): propagate canonical image MIME types (#102795) 2026-07-09 14:48:11 +01:00
huangjianxiong
0e626690cd fix(qa-matrix): keep shared reply previews UTF-16 safe (#102656)
* fix(qa-matrix): keep reply body preview truncation UTF-16 safe

Replace `.slice(0, 200)` with `truncateUtf16Safe(replyBody, 200)` in
buildMatrixReplyArtifact to prevent surrogate pair corruption.

Ref. lsr911 pattern — mechanical substitution, no behavior change.

* test(qa-matrix): preserve reply preview semantics

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 14:41:54 +01:00
Peter Steinberger
f6b9901243 fix(msteams): bound team group lookup cache (#102814)
Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com>
2026-07-09 14:31:45 +01:00
Ayaan Zaidi
474d660137 fix(infra): converge legacy state migrations on archive collisions 2026-07-09 18:57:58 +05:30
Peter Steinberger
124119a898 test(plugins): sync release contracts (#102777)
* test(plugins): sync release contracts

* test(codex): isolate dynamic tool capability test
2026-07-09 13:57:35 +01:00
Alix-007
e5259fa8bb fix(google): add timeout to Vertex ADC token refresh (#102050)
* fix(google): add timeout to Vertex ADC token refresh

* test(google): consolidate ADC timeout proof

* fix(google): bound all ADC token refreshes

* test(google): observe ADC timeout before advancing time

* fix(google): keep dependency timeout claims exact

* fix(google): bound library-managed ADC refreshes

* fix(google): recover after ADC refresh timeout

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 13:46:33 +01:00
Peter Steinberger
07a7d596ff feat(providers): add Qwen 3.6 Flash and Gemini 3.1 Live (#102791)
* feat(providers): add current Qwen and Gemini Live models

* fix(google): align live thinking enum type

* fix(google): align live thinking enum type
2026-07-09 13:37:16 +01:00
Alix-007
64e80888d4 fix(qqbot): bound speech transcription requests (#102028)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 13:25:29 +01:00
Masato Hoshino
a49567cdfd fix(qqbot): treat inbound attachment content types case-insensitively (#102753)
* fix(qqbot): treat inbound attachment content types case-insensitively

* test(qqbot): use distinct download paths per image; note voice sentinel in comment
2026-07-09 05:05:34 -07:00
Vincent Koc
d6cb18736a refactor(xai): localize internal declarations (#102778) 2026-07-09 05:00:37 -07:00
lzyyzznl
e99b5deb7a fix(codex): keep dynamic tool output UTF-16 safe (#102622)
* fix(codex-dynamic-tools): use truncateUtf16Safe for notice text truncation

* fix(codex): keep dynamic tool text UTF-16 safe

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:44:34 +01:00
mikasa
18fd6ee9e6 fix(tts-local-cli): cap local CLI speech outputs (#101510)
* fix(tts-local-cli): bound local speech output

Co-authored-by: mikasa0818 <0668001030@xydigit.com>

* chore(tts-local-cli): keep changelog release-owned

* docs(tts-local-cli): format output-limit note

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:42:41 +01:00
lzyyzznl
5497662408 fix(active-memory): keep search queries UTF-16 safe (#102621)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:41:38 +01:00
lzyyzznl
57c468ca1b fix(google-meet): use truncateUtf16Safe for log value truncation (#102617)
* fix(google-meet): use truncateUtf16Safe for log value truncation

One .slice(0, 180) truncation site in the Google Meet extension
may cut UTF-16 surrogate pairs in half when the log value contains
multi-byte characters such as emoji. Replace it with
truncateUtf16Safe to keep the truncated output valid Unicode.

* test(google-meet): cover UTF-16 model log boundary

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:40:26 +01:00
lzyyzznl
d750477d43 fix(migrate-claude): use truncateUtf16Safe for skill description truncation (#102616)
* fix(migrate-claude): use truncateUtf16Safe for skill description truncation

One .slice(0, 180) truncation site in the migrate-claude extension
may cut UTF-16 surrogate pairs in half when the skill description
contains multi-byte characters such as emoji. Replace it with
truncateUtf16Safe to keep the truncated output valid Unicode.

* test(migrate-claude): cover UTF-16 skill description

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:38:20 +01:00
lzyyzznl
0aae1ea816 fix(slack): use truncateUtf16Safe for message body preview truncation (#102612)
* fix(slack): use truncateUtf16Safe for message body preview truncation

One .slice(0, 160) truncation site in the Slack message handler may
cut UTF-16 surrogate pairs in half when the message body preview
contains multi-byte characters such as emoji. Replace it with
truncateUtf16Safe to keep the truncated output valid Unicode.

* test(slack): cover UTF-16 preview boundary

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:37:49 +01:00
wings1029
0bdd646fc2 fix(text): keep context tails UTF-16 safe (#102599)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:37:07 +01:00
Gary
981d67a703 fix(browser): remove hardcoded profile="user" suggestion from tool description (#102582)
* fix(browser): remove hardcoded profile="user" suggestion from browser tool description

The browser tool description hardcoded a suggestion to use profile="user"
for logged-in sessions, even when the operator has configured a different
default profile (e.g. browser.defaultProfile: "openclaw").

Replace with profile-agnostic guidance that references the configured
browser.defaultProfile setting instead of prescribing a specific value.

Fixes #102566

* test: update browser tool description assertion for profile-agnostic wording

* refactor(browser): unify tool profile guidance

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:32:56 +01:00
Peter Steinberger
3ccf2a0739 feat: render inline web chat widgets via capability-gated show_widget tool (#101840)
Adds client-capability-gated tool availability: gateway clients declare
capabilities at connect (new inline-widgets cap), chat.send stamps them into
the run context, and every tool assembly path (embedded runner, queued
followups, Codex app-server harness, plugin-only construction plans) drops
tools whose requiredClientCaps the originating client did not declare. The
Canvas plugin ships the first such tool, show_widget: agents pass SVG or an
HTML fragment plus a title; the plugin hosts it as a bounded, retention-scoped
Canvas document and returns the existing canvas preview handle, which web chat
renders as a sandboxed iframe fitted to the widget's reported content height.
Widget frames never get allow-same-origin (per-preview sandbox ceiling,
including the sidebar path) and the Canvas host serves widget documents with a
CSP sandbox header so direct navigation runs in an opaque origin. Verified
live end-to-end on a Testbox with gpt-5.5 (screenshots on the PR). CLI-backed
model backends do not carry client caps yet and stay fail-closed (#102577).

Closes #101790
2026-07-09 12:29:50 +01:00
lzyyzznl
6c3a46fb41 fix(openai): use truncateUtf16Safe for image gen log value truncation (#102611)
* fix(openai): use truncateUtf16Safe for image gen log value truncation

One .slice(0, N) truncation site in the OpenAI image generation
provider may cut UTF-16 surrogate pairs in half when the log value
contains multi-byte characters such as emoji. Replace it with
truncateUtf16Safe to keep the truncated output valid Unicode.

* fix(openai): keep image auth logs UTF-16 safe

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:21:24 +01:00
velanir-ai-manager
e84a0dde17 fix(msteams): surface quoted message body in Teams quote replies (#101856)
* fix(msteams): surface quoted message body in Teams quote replies

Teams sends the quoted text of a 1:1 DM quote-reply in <p itemprop="preview">
(a truncated snippet), not <p itemprop="copy"> which the parser matched. The
match failed, so quoteInfo was undefined and nothing was surfaced to the agent.

Fix 1 (primary): extractMSTeamsQuoteInfo now accepts copy OR preview (prefers
copy, falls back to preview) and captures the blockquote itemid as the quoted
message id.

Fix 2 (enhancement): when the quoted message id is known, fetch the full text
via the app-only Graph endpoint GET /chats/{chatId}/messages/{id} (permitted
with Chat.Read.All, unlike the delegated /me/chats listing) and use it as the
quote body. Restricted to chats (DM + group) whose Graph chat id is a 19: id;
any failure degrades to the truncated preview so message handling never breaks.

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

* fix(msteams): address review — DM-only full-text fetch, drop unsupported $select, fix mocks

Addresses ClawSweeper review on the quote-reply PR:

- Security (P1): restrict the app-only Graph full-text quote fetch to 1:1 DMs.
  Previously it ran for any non-channel chat, so in a group an allowlisted
  sender could quote a non-allowlisted member and the fetched full body would
  bypass the supplemental-quote visibility allowlist. Group/channel quotes keep
  the (now-surfaced) truncated preview from fix 1.
- Graph contract (P2): the get-chatMessage endpoint does not support OData
  query params; drop the ?$select=id,body that tenants enforcing the contract
  would reject (which would silently fall back to the preview).
- Tests (P1): add fetchChatMessageText to the two vi.mock(../graph-thread.js)
  factories prod now touches, and add a group-chat regression test proving the
  Graph full-text fetch does not fire for group quotes.

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

* docs(msteams): add redacted real Teams quote-reply proof screenshots

Real-behavior evidence for the quote-reply fix (personal names + avatars
redacted): a 1:1 DM where the bot now reads back the full quoted message.

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

* docs(msteams): remove committed proof screenshots from branch

Proof media should live as external PR artifacts, not in the product tree.

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

* test(msteams): bound and prove quote enrichment

* test(msteams): use valid open DM fixture

---------

Co-authored-by: Yash Inani <yashinani@Yashs-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:20:54 +01:00
huangjianxiong
ac71074807 fix(mattermost): keep slash command error truncation UTF-16 safe (#102607)
* fix(mattermost): keep slash command error truncation UTF-16 safe

Replace `.slice(0, 300)` and `.slice(0, 200)` with `truncateUtf16Safe`
in sanitizeCommandLookupError and sanitizeMattermostLogValue to prevent
surrogate pair corruption.

Ref. lsr911 pattern — mechanical substitution, no behavior change.

* test(mattermost): cover UTF-16-safe slash logs

Co-authored-by: 黄剑雄0668001315 <huang.jianxiong@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 12:20:38 +01:00