mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-17 16:12:21 -06:00
8506e32748
* fix(wiki): wiki_get and wiki compile miss nested source files (#96022) * fix(wiki): discover nested source files in QUERY_DIRS Two functions in the memory-wiki extension — listWikiMarkdownFiles (wiki_get runtime lookup) and collectMarkdownFiles (wiki compile indexing) — used fs.readdir without { recursive: true }. Nested source files (e.g. sources/audi/car.md) were silently invisible to both wiki_get and wiki compile. Add recursive: true and adjust path construction using entry.parentPath so nested .md files in all QUERY_DIRS are discovered while preserving the index.md exclusion and backward compatibility with flat vaults. * fix(wiki): remove entry.path fallback, only parentPath is typed on Dirent * fix(wiki): add recursive scan to status.ts and add nested-file regression tests * fix(wiki): use toSorted instead of sort to pass lint * style(memory-wiki): format recursive discovery fix --------- Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com> (cherry picked from commit63ee4cd240) * fix(tools-manager): require clean exit in commandExists (#96361) Summary: - The PR changes the agent tools manager to treat spawned-but-nonzero fd/rg probes as missing and adds regression tests for non-zero and zero spawn status. - PR surface: Source +3, Tests +27. Total +30 across 2 files. - Reproducibility: yes. Current main ignores non-zero `spawnSync.status`, and a live Node probe confirms a spawned child can exit non-zero while leaving `error` unset. Automerge notes: - No ClawSweeper repair was needed after automerge opt-in. Validation: - ClawSweeper review passed for head377d560eff. - Required merge gates passed before the squash merge. Prepared head SHA:377d560effReview: https://github.com/openclaw/openclaw/pull/96361#issuecomment-4788071605 Co-authored-by: liyuanbin <li.yuanbin1@xydigit.com> Co-authored-by: Claude <noreply@anthropic.com> Approved-by: takhoffman (cherry picked from commit380f2749be) * fix(lmstudio): bound model load success response body to prevent OOM (#96042) The /api/v1/models/load success path read the response with an unbounded await response.json(), so a misbehaving or compromised LM Studio server could stream an arbitrarily large JSON body that is fully buffered into memory before any size check. Read it through the shared byte-capped readProviderJsonResponse helper instead (16 MiB provider-JSON cap, cancels the stream on overflow, wraps malformed JSON), matching the discovery path and the already-bounded error body. Migrate the model fetch/load test mocks to real Response objects (the bounded readers need a real body stream) and add a regression test that streams an oversized success body and asserts a bounded error plus stream cancellation. Label: security (cherry picked from commit7844b08445) * fix(parallel): bound successful web-search JSON response reads (#96035) * fix(parallel): bound successful web-search JSON response reads The Parallel web_search provider parsed its /v1/search success body with an unbounded await res.json(). The body comes from an external web-search upstream, so a hostile or malfunctioning endpoint streaming an unbounded JSON payload could force the runtime to buffer the whole response before parsing, creating memory pressure or a hang on the provider path. Read the success body through the shared readProviderJsonResponse helper with a 16 MiB cap (matching the provider JSON cap from #95218); on overflow the stream is cancelled and a bounded error is thrown. The error-body path was already bounded (readResponseTextLimited, 8 KiB). Symmetric follow-up to the #95103/#95108 response-limit campaign. * docs(parallel): drop upstream PR ref from response-cap comment Replace the PR-specific '#95218' annotation with a neutral description of the shared provider JSON cap so the comment stays accurate independent of upstream PR numbering. (cherry picked from commit6163b1977b) * fix(exa): bound untrusted search JSON response reads (#96038) Exa search success responses were read via an unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing. Read the success body through the shared bounded reader (16 MiB cap, the same limit other bundled providers use) and cancel the stream on overflow. This mirrors the error-body bound already in place and the #95103/#95108 response -limit campaign on the success-JSON side. AI-assisted. (cherry picked from commit605aede38c) * fix(ollama): bound model-discovery JSON response reads (#96027) * fix(ollama): bound model-discovery JSON response reads The /api/tags and /api/show discovery reads in extensions/ollama/src/provider-models.ts parsed their HTTP responses with an unbounded await response.json(). Ollama base URLs are user-supplied and can point at remote/cloud endpoints, so a hostile or buggy server (or one reachable via SSRF) could stream an unbounded or never-ending JSON body and drive model discovery into OOM. Route both reads through the shared @openclaw/media-core byte-bounded reader (readResponseWithLimit, re-exported via openclaw/plugin-sdk/response-limit-runtime) under a single 16 MiB cap before JSON.parse, cancelling the stream on overflow. Overflow throws a bounded error that the existing fail-soft handlers swallow, so a capped endpoint degrades gracefully: /api/tags returns { reachable: false, models: [] } and /api/show returns {}. Symmetric counterpart to the #95103/#95108 response-limit campaign. AI-assisted. * fix(ollama): reuse shared bounded JSON reader for model discovery Replace the local readOllamaDiscoveryJson helper with the shared readProviderJsonResponse (from openclaw/plugin-sdk/provider-http), which already enforces the 16 MiB cap, cancels the stream on overflow, and wraps malformed JSON with the caller label. The /api/tags and /api/show discovery reads now go through it directly while keeping the existing fail-soft handlers ({ reachable: false, models: [] } and {}). Add a focused regression test: when a discovery stream exceeds the JSON byte cap, fetchOllamaModels returns { reachable: false, models: [] }, queryOllamaModelShowInfo returns {}, and the bounded reader cancels the body mid-flight so less than the full advertised stream is read. (cherry picked from commitd1c2934d0d) * fix(providers): bound self-hosted provider discovery JSON reads (#95244) * fix(providers): bound self-hosted discovery JSON reads discoverLlamaCppRuntimeContextTokens and discoverOpenAICompatibleLocalModels parsed their HTTP responses via an unbounded await response.json(). Self-hosted provider base URLs are user-supplied and untrusted (an endpoint reachable via SSRF could stream an unbounded JSON body), so a hostile or buggy endpoint could drive the setup wizard into OOM. Route both reads through the shared byte-bounded reader (readResponseWithLimit from @openclaw/media-core) under a single 4 MiB cap before JSON.parse, mirroring the bound-stream hardening landed for Anthropic error bodies. Overflow cancels the stream and is swallowed by the existing discovery error handling, so a capped endpoint degrades gracefully (returns [] / skips the runtime context probe) instead of buffering the whole body. * tune self-hosted discovery cap Signed-off-by: sallyom <somalley@redhat.com> --------- Signed-off-by: sallyom <somalley@redhat.com> Co-authored-by: sallyom <somalley@redhat.com> (cherry picked from commitdad5ce64d4) * fix(providers): bound successful response reads Backport of 0a14444924e34e031133c997b00d30573353c5a0; retains the target's existing provider-reader SDK baseline. * fix(outbound): prevent partial-send recovery replay (cherry picked from commit210ea659f7) * fix(qwen): bound video success response (#96604) (cherry picked from commitcc124d2921) * fix(byteplus): bound video-generation success response (#96606) (cherry picked from commit7b5ee739eb) * fix(voyage): bound embedding-batch status, error, and non-OK responses (#96608) The batch status read (fetchVoyageBatchStatus) parsed its response with an unbounded await res.json(), and the batch error-file read (readVoyageBatchError) buffered the whole body via await res.text(). On top of that, the non-OK (4xx/5xx) diagnostic body was still read unbounded: assertVoyageResponseOk did await res.text() before throwing, and the non-OK output-file branch in runVoyageEmbeddingBatches did the same. Voyage base URLs are user-supplied and reachable via SSRF, so a misbehaving or hostile endpoint could stream an unbounded body into memory on any of these paths before parsing. Route the status JSON through the shared readProviderJsonResponse, the error file through readResponseWithLimit, and now the non-OK diagnostic body through readResponseWithLimit as well, all under a single 16 MiB cap, cancelling the stream on overflow before decode/parse. assertVoyageResponseOk preserves its original "${context}: ${status} ${text}" diagnostic shape for under-cap bodies and throws a bounded "(error body exceeds <N> bytes)" on overflow; the non-OK output-file branch now reuses it instead of a duplicate unbounded read. The existing error-file fail-soft handling (formatUnavailableBatchError) is preserved, so a capped endpoint degrades gracefully. The submit path already bounds its body via postJsonWithRetry/maxResponseBytes and is left untouched. Symmetric counterpart to the #96027/#96038 response-limit campaign. (cherry picked from commitd3620da3e0) * fix(github-copilot): bound usage response (#96607) The Copilot usage read in extensions/github-copilot/usage.ts parsed its HTTP response with an unbounded await res.json(). A hostile or buggy api.github.com proxy (the proxy endpoint is derived from a user-supplied token) could stream an unbounded JSON body and drive the usage snapshot into OOM. Route the read through the shared readProviderJsonResponse (from openclaw/plugin-sdk/provider-http), which enforces the 16 MiB byte cap, cancels the stream on overflow, and wraps malformed JSON with the caller label. Same no-helper-import-to-bounded-reader shape as the #96027 / #96038 response-limit work. Add a focused regression test: when the usage stream exceeds the JSON byte cap, fetchCopilotUsage rejects with a bounded-overflow error and the reader cancels the body mid-flight instead of buffering the full advertised stream. Existing parse/HTTP-error cases keep passing. (cherry picked from commit646e54ae35) * fix(openrouter): bound video catalog JSON reads (#96505) (cherry picked from commit5715b55000) * fix(speech): bound TTS/STT voice-list and transcription JSON response reads (#96496) Route success JSON reads through readProviderJsonResponse (16 MiB cap) in azure-speech, elevenlabs, microsoft, minimax/tts, xai/stt, and openrouter/media-understanding to prevent OOM from oversized or hostile endpoint responses. Mirrors the response-limit campaign already applied to other provider paths. AI-assisted. Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit66e2fcc6f8) * fix(github-copilot): bound model discovery and embeddings JSON response (#96499) * fix(github-copilot): bound model discovery and embeddings JSON response reads The GitHub Copilot embeddings plugin already bounds its error response bodies via readResponseTextLimited, but the success JSON reads for both model discovery and the embeddings call used unbounded response.json(). Route both through readProviderJsonResponse (16 MiB cap). Update isCopilotSetupError to recognise the new error label prefix so auto-selection still falls through on malformed discovery responses. Update tests to use proper Response objects and the new error messages. AI-assisted. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(github-copilot): use memory embedding response cap Signed-off-by: sallyom <somalley@redhat.com> --------- Signed-off-by: sallyom <somalley@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: sallyom <somalley@redhat.com> (cherry picked from commit1aa7cafc35) * fix(image-gen): bound image generation provider JSON response reads (#96495) * fix(image-gen): bound image generation provider JSON response reads Route success JSON reads through readProviderJsonResponse (16 MiB cap) in openrouter, google, fal, minimax, openai, and vydra image generation providers to prevent OOM from oversized or hostile endpoint responses. Mirrors the response-limit campaign already applied to other provider paths. AI-assisted. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(image-gen): size bounded JSON caps for inline image payloads Signed-off-by: sallyom <somalley@redhat.com> --------- Signed-off-by: sallyom <somalley@redhat.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: sallyom <somalley@redhat.com> (cherry picked from commit527f8f0cbb) * fix(google-media): bound JSON response reads (#96920) * fix(google-media): bound JSON response reads * test(google): relax media response cap assertion --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org> (cherry picked from commita7bfc06f45) * fix(google): bound TTS success JSON response reads (#96984) (cherry picked from commit5ccfc97b31) * fix(clickclack): bound REST success JSON response reads (#96970) * fix(clickclack): bound REST success JSON response reads * test(clickclack): harden response cap proof --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org> (cherry picked from commitf4fa10c2c5) * Fix/discord bound probe getme json reads (#97278) * fix(discord): bound probe getMe JSON response reads * test(discord): add oversized probe getMe JSON regression * test(discord): add loopback proof for bounded probe getMe reads * fix(scripts): satisfy oxlint in discord probe proof script * test(discord): keep probe proof in focused coverage --------- Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: Peter Steinberger <steipete@golden-gate.local> (cherry picked from commit7ba9212665) * Fix/zalo bound api json response reads (#97277) * fix(zalo): bound Bot API JSON response reads via readProviderJsonResponse * test(zalo): keep API proof in focused coverage --------- Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: Peter Steinberger <steipete@golden-gate.local> (cherry picked from commit38ddcef78f) * fix(embedding): bound OpenAI-compatible embedding response reads (#96868) * fix(embedding): bound OpenAI-compatible embedding response reads * test(embedding): avoid loop-condition lint in stream proof (cherry picked from commitf1e4980a97) * fix(mattermost): bound successful REST JSON/text response reads (#96033) * fix(mattermost): bound successful REST JSON/text response reads The Mattermost REST client already bounds error bodies (readResponseTextLimited) and streams guarded responses without buffering, but the success path still called `await res.json()` / `await res.text()`, reading the whole body into memory before parsing. A self-hosted or compromised Mattermost server can return an arbitrarily large (or never-terminating, content-length-less) JSON/text body and force the plugin to buffer it unbounded. Read successful JSON through the shared readProviderJsonResponse (16 MiB cap, cancels the stream and throws a bounded error on overflow, same as the provider HTTP path) and cap non-JSON success bodies with readResponseTextLimited. uploadMattermostFile's file-info JSON is bounded the same way. Symmetric follow-up to the #95103 / #95108 response-limit campaign. AI-assisted. * fix(mattermost): bound probe success JSON reads * fix(mattermost): reject oversized success text bodies (cherry picked from commit9241b9701d) * fix(minimax): bound video control response reads (#96889) * fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads * fix(minimax): leave image response sizing to image hardening * fix(minimax): bound image/video success response reads MiniMax image generation and video generation (task submit + status poll) read their success responses through unbounded `await response.json()`, so a misbehaving or hostile endpoint could stream an arbitrarily large body into memory before parsing and exhaust the process. Read those success bodies through the shared bounded reader (16 MiB cap, the same limit other bundled providers and the sibling MiniMax web-search provider already use) and cancel the stream on overflow. The error-body path is already bounded via assertOkOrThrowHttpError; this closes the matching success-JSON gap. MiniMax TTS is already bounded and is left unchanged. AI-assisted. * fix(minimax): bound video metadata response reads (cherry picked from commit25e184aeab) * fix(speech): bound TTS response reads (#96874) (cherry picked from commit2f851ecfe9) * fix(deepinfra): bound video generation JSON response reads (#97486) (cherry picked from commit0d59280131) * fix(openrouter): bound generation-cost JSON response reads (#97490) (cherry picked from commitc0883a531d) * fix(openrouter): bound video response reads Route OpenRouter video submit and poll success JSON through the shared bounded provider JSON reader, preserving malformed-response mapping and SSRF request policy coverage. (cherry picked from commit48f34b1d4d) * fix(signal): bound GitHub release info JSON response with readProviderJsonResponse (#97536) Replace bare `await response.json()` in `installSignalCliFromRelease` with `readProviderJsonResponse` (16 MiB cap, stream cancel on overflow). The external GitHub Releases endpoint can include a large `body` changelog field; the error path was already guarded but the success path was unbounded. The existing inner catch continues to convert overflow errors into the graceful `{ ok: false, error: "Failed to parse signal-cli release info." }` path. Adds a regression test verifying the stream is cancelled before all chunks are read on an oversized 20 MiB streaming response. Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit51064bda4d) * fix(openai): bound embedding-batch and realtime session JSON response reads (#97533) (cherry picked from commit4c477ee632) * fix(telegram): bound getChat Bot API response reads (#97274) * fix(telegram): bound getChat Bot API response reads * fix(telegram): repair getChat bound-read type and proof script lint --------- Co-authored-by: NIO <nocodet@mail.com> (cherry picked from commitb948c86b2a) * fix(google): bound embedding-batch JSON response reads (#97535) * fix(google): bound embedding-batch JSON response reads * fix(google): repair embedding-batch test types and lint --------- Co-authored-by: NIO <nocodet@mail.com> (cherry picked from commit91297bf420) * fix(ollama): bound cloud-auth 401 JSON response reads (cherry picked from commita82cff8892) * fix(xai): bound OAuth response reads to prevent OOM (#97615) Replace unbounded response.text() in readResponseBody and response.json() in the device-code polling loop with readResponseWithLimit (16 MiB cap). (cherry picked from commitd5aca1d6d2) * fix: bound APNs relay response body so an oversized relay reply can't exhaust gateway memory Reviewed and accepted after live preflight: mergeable clean, checks passing, no unresolved review threads. (cherry picked from commit89b5a87909) * fix(runway): bound video create/poll response reads Reviewed and accepted after live preflight: mergeable clean, checks passing, no unresolved review threads. (cherry picked from commit63b089383a) * fix(openai): bound video create-submit response reads Reviewed and accepted after live preflight: mergeable clean, checks passing, no unresolved review threads. (cherry picked from commitf0e2f7b4f5) * fix(together, pixverse): bound video response reads Reviewed and accepted after live preflight: mergeable clean, checks passing, no unresolved review threads. (cherry picked from commitca1bc58759) * fix(fal): bound music/video generation response reads Reviewed and accepted after live preflight: mergeable clean, checks passing, no unresolved review threads. (cherry picked from commitce1217a49c) * fix(vydra): bound control response reads Reviewed and accepted after live preflight: mergeable clean, checks passing, no unresolved review threads. (cherry picked from commit74a9beb83f) * fix(video-generation): bound DashScope JSON response reads (cherry picked from commit238398e331) * fix(comfy): bound JSON response reads via readProviderJsonResponse (cherry picked from commitbf66b4e1ea) * fix(github-copilot): bound login JSON response reads (cherry picked from commit748bea3434) * fix(xai): bound video response body reads (cherry picked from commit46e119074e) * fix(provider-usage): bound usage response body reads (cherry picked from commitdb2786bde1) * fix(agents): bound WHAM usage probe JSON response reads (cherry picked from commit0ce10d7793) * fix(discord): bound PluralKit and voice-message JSON reads (cherry picked from commit597a0ba43c) * fix(nextcloud-talk): bound bot preflight error reads (#97811) Co-authored-by: Pick-cat <266665499+Pick-cat@users.noreply.github.com> (cherry picked from commit09167523bf) * fix(pdf): guard native provider requests (#97872) * fix(pdf): guard native provider requests * fix(pdf): preserve configured origin trust * fix(pdf): preserve resolver compatibility (cherry picked from commitb7b2e1f77e) * fix(cli): bound docs search API response reads with committed test (#98188) (cherry picked from commitf284ce3b4d) * fix(moonshot): bound video description JSON response reads (#96502) * fix(moonshot): bound video description JSON response reads The Moonshot video description endpoint used an unbounded await res.json() to parse the media understanding response. Route through readProviderJsonResponse (16 MiB cap) to match the bound already in place for other media understanding providers (xai, openrouter). AI-assisted. Co-authored-by: Cursor <cursoragent@cursor.com> * test(moonshot): add bounds and malformed-JSON coverage for video description --------- Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit765d05c2e4) * fix(minimax): bound OAuth JSON response via shared provider reader (#96322) Use readProviderJsonResponse (shared 16 MiB default cap) instead of unbounded response.json() for MiniMax OAuth authorization code endpoint. Signed-off-by: lsr911 <liao.shirong@xydigit.com> Co-authored-by: Claude <noreply@anthropic.com> (cherry picked from commit4a96c06615) * fix(openai): bound embedding batch file downloads (#98554) * fix(openai): bound embedding batch file downloads * fix(openai): bound batch output records --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org> (cherry picked from commitce4a259485) * fix(memory): preserve UTF-8 when qmd output splits across pipe chunks (#107263) * fix(memory): preserve UTF-8 across fragmented qmd output chunks * fix(memory): decode qmd streams at UTF-8 boundary Co-authored-by: wahaha1223 <0668001153@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit7f36f49052) * fix(synology-chat): bound outbound NAS response bodies to prevent Gateway OOM (#105089) * fix(synology-chat): settle user_list overflow without hanging Cap reads at 1 MiB with Buffer concat. On overflow, finish the promise before destroy() — bare destroy often skips end/error and hung the test. * fix(synology-chat): share bounded user-list reader Co-authored-by: zw-xysk <zhao.wang1@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit30c257f6b4) * fix(extensions): prevent corrupted UTF-8 in api.exec output (#108365) * fix(extensions): preserve split UTF-8 in api.exec * test(agents): cover incomplete exec UTF-8 at EOF Co-authored-by: zhang-guiping <zhang.guiping@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit3b51889c3b) * fix(sessions): stop leaking file path as prompt content on read failure (#108546) * fix(sessions): stop leaking file path as prompt content on read failure When readFileSync fails for a valid file path, resolvePromptInput returns the raw path string as prompt content instead of undefined. This injects filesystem paths into the LLM context. The existing console.error warning still fires; the caller already handles undefined returns correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: cover unreadable prompt paths * test: use tracked resource loader temp dirs --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Peter Steinberger <peter@steipete.me> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitc924819292) * fix(clickclack): bound websocket handshake waits at 30s (#106485) * fix(clickclack): bound websocket handshake waits at 30s * test(clickclack): prove WebSocket handshake deadline --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit3eec404aab) * fix(memory-core): write MEMORY.md atomically during short-term promotion (#108397) * fix(memory-core): write MEMORY.md atomically during short-term promotion applyShortTermPromotions rewrote MEMORY.md with a single non-atomic fs.writeFile, which truncates the file before streaming the new content. An OS write failure part way through (for example EFBIG on a size-limited or full volume) left MEMORY.md truncated to the bytes written before the failure, permanently dropping user long-term memory. The dreaming cron path invokes this writer automatically, and the recall store is only updated after the write, so the promotion stays eligible and the next run reads the already-truncated file. Route the write through replaceFileAtomic (temp file, fsync, atomic rename), the same durable-write helper the sibling DREAMS.md writer in this extension already uses. On failure the temp file is discarded and the existing MEMORY.md is left untouched; on success the content and the existing file mode are preserved. * fix(memory-core): harden atomic promotion durability --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit0317d7e628) * fix(agents): bound base64 image input before decode in tool-image sanitizer (#105086) * fix(agents): bound base64 image input before decode in tool-image sanitizer * fix(agents): lower input-size cap to 10MB for OOM headroom * fix(agents): align tool-image input-cap comment with 10 MiB ceiling * fix(agents): typecheck-safe access in tool-image input-cap test * test(agents): exercise real tool image input cap --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitb85531c62f) * fix(qqbot): bound tail log reads to actual bytes returned by fs.readSync (#108955) * fix(qqbot): bound tail log reads to actual bytes returned by fs.readSync * fix(qqbot): satisfy knip deadcode check for testing export Add __testing re-export and test-api.ts barrel so knip traces the testing export through a recognized entry point. * fix(qqbot): restore testing export alongside __testing re-export Both exports are needed: testing for proof scripts, __testing for knip tracing. * fix(qqbot): remove unused __testing re-export from log-helpers test-api.ts already imports testing and re-exports as __testing. The extra re-export in log-helpers.ts was unused by production code. * fix(qqbot): retry short log tail reads * test(qqbot): keep short-read seam private Co-authored-by: RileyJJY <100176083+RileyJJY@users.noreply.github.com> * test(qqbot): exercise short reads through log export Co-authored-by: RileyJJY <0668000974@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: RileyJJY <100176083+RileyJJY@users.noreply.github.com> (cherry picked from commit3f89aae98d) * fix(proxy-capture): guard body-less arrayBuffer reads against oversized responses (#101268) * fix(proxy-capture): guard body-less arrayBuffer reads against oversized responses * fix(proxy-capture): exercise body-less fallback in bounded read tests New tests use mock clones with body: null plus arrayBuffer spies to prove the content-length precheck guards the !body path. A real Response clone exposes body.getReader in Node 24, so the prior test only exercised the streaming branch and would stay green even if the precheck were deleted. * chore: retrigger CI * fix(proxy-capture): reject non-safe content-length before arrayBuffer (#101268) ClawSweeper P2: the body-less fallback used Number(content-length), so a huge digit-only Content-Length value could overflow to Infinity, bypass the Number.isFinite guard, and still call arrayBuffer() — leaving an OOM path in the hardening PR. Add declaredContentLengthExceedsCap, which accepts only plain digit strings, treats any value longer than Number.MAX_SAFE_INTEGER as oversized, and compares safe-integer parsed values against the cap. Non-numeric or malformed values fall through to the post-read length check. Adds a regression test for a 100-digit Content-Length that would previously have bypassed the guard. * fix(proxy-capture): normalize zero-padded Content-Length before digit-count guard * fix(proxy-capture): fail closed without response streams --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit7cde0ac8c0) * fix(lmstudio): cancel model discovery response body on non-ok (#109718) * fix(lmstudio): cancel model discovery response body on non-ok Wire the direct-fetch release hook to cancel unread bodies so failed model discovery releases the TCP connection instead of leaving it open. Co-authored-by: Cursor <cursoragent@cursor.com> * refactor(lmstudio): unify response cleanup Co-authored-by: Zeng Wen <27948732+ZengWen-DT@users.noreply.github.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Zeng Wen <27948732+ZengWen-DT@users.noreply.github.com> (cherry picked from commit1573c78f5b) * fix(msteams): cancel non-OK consent upload response body before throwing (#109701) * fix(msteams): cancel non-OK consent upload response body before throwing * fix(msteams): release all consent upload responses Cancel unread response bodies after successful uploads as well as failed uploads, and fold the lifecycle assertions into the existing status-path tests. Co-authored-by: Monkey-wusky <66244686+Monkey-wusky@users.noreply.github.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit9b238a7927) * fix(discord): honor caller abortSignal during 429 retry backoff (#109913) * fix(discord): honor caller abortSignal during 429 retry backoff * test(discord): prove 429 backoff abort through a real loopback server * test(discord): make retry abort proof deterministic --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit40acbb05c9) * fix(auto-reply): treat U+2028/U+2029 as paragraph boundaries when chunking (#103518) * fix(auto-reply): treat U+2028/U+2029 as paragraph boundaries when chunking chunkByParagraph normalized only CR/CRLF before blank-line paragraph detection, so model output using Unicode LINE/PARAGRAPH SEPARATOR (U+2028/U+2029) instead of a blank line was not split at those boundaries and fell back to length-based splitting. Normalize U+2028/U+2029 to \n alongside CR/CRLF, matching how the Control UI markdown renderer handles them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(auto-reply): normalize U+2028 as line break, U+2029 as blank-line paragraph boundary Distinguish U+2028 (LINE SEPARATOR) from U+2029 (PARAGRAPH SEPARATOR): U+2029 becomes \n\n (blank line — paragraph boundary) while U+2028 becomes \n (single newline — intra-paragraph line break). The original fix mapped both to \n, so standalone U+2029 still produced single-line text without a blank-line gap — paragraph detection failed. The combined U+2028 input accidentally produced the right blank-line sequence, which masked the bug. Adds individual tests for lone U+2029 (splits at paragraph boundary), lone U+2028 (stays within paragraph), and consecutive U+2028 (combined blank line — matches \n\n behavior). * test(auto-reply): simplify Unicode separator cases --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit3a4e2ef65f) * fix(synology-chat): bound user_list fetches with a wall-clock deadline (#109111) * fix(synology-chat): bound user_list fetches with a wall-clock deadline * refactor(synology-chat): keep deadline internal * style(synology-chat): format deadline proof --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitf7cc0ef838) * fix(security): bound plugin manifest reads in audit deep scan (#101773) (cherry picked from commitaa0c92186b) * fix(heartbeat): bound HEARTBEAT.md file read size (#101775) * fix(heartbeat): bound HEARTBEAT.md file read size * fix(heartbeat): follow symlinked HEARTBEAT.md while bounding reads * fix(heartbeat): warn operators when oversized HEARTBEAT.md is skipped (cherry picked from commit993c975f57) * fix(plugins): bound marketplace manifest file reads (#101774) * fix(plugins): bound marketplace manifest file reads * fix(plugins): distinguish oversized marketplace manifest from other read failures * fix(plugins): follow symlinked marketplace manifests while bounding reads * test(plugins): cover oversized symlinked marketplace manifest target (cherry picked from commit35754a63cc) * fix(plugins): bound plugin manifest metadata file reads (#110036) * fix(plugins): bound plugin manifest metadata file reads * fix(plugins): use correct Error type check in oversized manifest catch readRegularFileSync throws a plain Error (not RangeError) when the file exceeds maxBytes. Change the catch-block type check from RangeError to Error to properly detect oversized plugin manifests and emit the subsystem warning. * test(plugins): exercise valid oversized manifests Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit2e21d53c84) * fix(gateway): bound BOOT.md file read size (#101776) * fix(gateway): bound BOOT.md file read size * fix(gateway): treat non-regular BOOT.md as empty/missing and add coverage * fix(gateway): preserve non-size BOOT.md failures while bounding oversized reads * fix(gateway): preserve readable BOOT.md symlink behavior * fix(gateway): treat dangling BOOT.md symlink as missing * fix(gateway): report oversized BOOT files * fix(gateway): preserve missing BOOT race behavior Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commite22c2dfaaa) * fix(agents): bound IDENTITY.md reads to prevent OOM (#101447) * fix(agents): bound IDENTITY.md reads to prevent OOM * fix(agents): reuse shared workspace bootstrap file size limit for IDENTITY.md * chore: retrigger CI after cancelled gate run * chore: retrigger CI after runner tooling flake * chore: retrigger CI after main typecheck fix and runner brew flake * fix(identity): bound explicit --identity-file imports through shared loader * fix(agents): unexport parseIdentityMarkdown to satisfy production deadcode scan * chore: retrigger CI after stuck previous run * chore: retrigger CI after stuck checks-node-compact-large-4 run * chore: retrigger CI after stuck checks-node-compact-large-4 and flaky small-9 * fix(agents): report oversized identity file size to the user When `--identity-file` points at a file exceeding the size limit, the `no identity data found` error is misleading. Re-throw the fs-safe `exceeds` error with a human-readable message so the CLI surfaces the actual cause. * fix(agents): update test assertion for oversized identity diagnostic * fix(agents): attach caught error as cause in oversized identity diagnostic * fix(agents): preserve symlinked identity files * fix(agents): classify identity size errors exactly Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com> * fix(agents): preserve supported identity avatars Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com> * fix(agents): keep identity limit private Co-authored-by: 陈宪彪0668000387 <chen.xianbiao@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Peter Steinberger <peter@steipete.me> (cherry picked from commit80f6acc8de) * fix(config): bound state-directory .env file reads with size limit (#109487) * fix(config): bound state-directory .env file reads with size limit Replace unbounded fs.readFileSync with readRegularFileSync capped at 1 MiB (MAX_STATE_DIR_DOTENV_BYTES) so an oversized .env file is rejected before loading the entire file into memory. Resolve symlinks via fs.realpathSync before the bounded read so symlinked .env files keep working — matching the marketplace.ts pattern for bounded manifest reads. * fix(config): add diagnostic when oversized state .env is skipped Log a warning when the state-directory .env file exceeds the 1 MiB limit so operators know a configured file was skipped — matching the pattern from #108200 (plugin catalog bounded read diagnostic). * fix(config): bound global runtime dotenv file reads with size limit Replace unbounded fs.readFileSync in readDotEnvFile with readRegularFileSync capped at 1 MiB so CLI/Gateway startup dotenv loading also gets the bounded read protection — not just the state-dir service-env path. This addresses the P1 review finding that the original fix only capped the helper-level reader while the shared readDotEnvFile used by loadGlobalRuntimeDotEnvFiles was still unbounded. (cherry picked from commit0c221d2b4f) * fix(nostr): profile imports no longer crash on invalid fields (#110684) * fix(nostr): profile imports no longer crash on invalid fields * test(nostr): define invalid profile import policy * test(nostr): cover invalid imported URL types --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit9fe92cf5ce) * fix(tlon): preserve shutdown when body cancellation fails (#111106) * fix(tlon): observe shutdown body cancellation failures * test(tlon): streamline shutdown cleanup proof * test(tlon): narrow shutdown fixtures --------- Co-authored-by: ZengWen-DT <290981215+ZengWen-DT@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit5bb969f7de) * fix(qqbot): cancel non-OK direct-upload response body before throwing (#110008) (cherry picked from commit17643f3850) * fix(tui): prevent memory growth during repeated selector searches (#109451) * fix(tui): bound searchable select regex cache * fix(tui): discard stale selector regexes Co-authored-by: wahaha1223 <0668001153@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit80c16ecc80) * fix(tlon): bound Urbit auth response body drain to prevent OOM (#109697) * fix(tlon): bound Urbit auth response body drain to prevent OOM Replace the unbounded response.text() body drain (discarded after reading to finalize set-cookie headers) with a streaming reader capped at 64 KiB. When no body stream is available, fall back to text() for compatibility. A hostile or misconfigured Urbit endpoint could previously stream an arbitrarily large body into memory during login. Co-Authored-By: Claude <noreply@anthropic.com> * fix(tlon): add curly braces to drain loop for lint compliance * fix(tlon): remove unbounded text() fallback, cancel reader in finally Remove the unbounded response.text() body-less fallback path. When no body stream is available, there is nothing to drain — cookie headers are already finalised. Move reader.cancel() into a finally block so the reader is released even when read() throws. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> (cherry picked from commit4e9b1f4775) * fix(tlon): cancel failed auth response bodies (#112059) (cherry picked from commite024aa38b9) * fix(memory-core): guard invalid timestamps in dreaming rankings (#110537) (cherry picked from commit1e4e588142) * fix(security): restore filesystem API after bounded manifest read Source:95d632e644Target adaptation: this release line does not yet have the skill-file audit path, so only restore the fs/promises import still required by its other deep audit helpers afterd5b0218b7eremoved it. * test(proxy-capture): adapt bounded capture coverage to release test harness Source:7cde0ac8c0Target adaptation: import vi explicitly and model Buffer payload persistence so the null-body assertion exercises the shipped store contract. * style: format backported provider response bounds * fix: correct release-line backport adaptations Retain the existing Synology client export and remove source-context imports/constants that have no caller on the .34 release line. * fix(retry): support abortable operation backoff Target adaptation for source40acbb05c9: the .34 retry utility predates the per-operation sleeper hook required by Discord's abortable 429 backoff. * fix(clickclack): cap inbound WebSocket frames Target adaptation for source3eec404aab: retain the source's 16 MiB ws cap alongside the handshake deadline; this release line predates its shared inbound JSON limit constant. * fix(openai): bound blank streamed batch records Target hardening for sourcece4a259485: count blank JSONL records so newline-only responses cannot bypass the existing output record cap. * fix(openai): complete blank batch record backport * fix(browser): run mutation guard before JSON parsing (#104677) * fix(browser): run mutation guard before JSON parsing * test(browser): cover auth in mutation guard ordering --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit85a8f4ba8d) (cherry picked from commit 36ef64341bf8355c3832e56b8fb7ece3b4a0c26f) * fix(tts-local-cli): handle stdout/stderr stream errors in speech provider (#102347) * fix(tts-local-cli): handle stdout/stderr stream errors in speech provider CLI TTS speech provider spawns a child process to generate audio and registers stdout/stderr data listeners but omits stream error handlers. stdout carries synthesized audio data. A pipe error mid-generation must reject the promise so the caller does not silently receive truncated audio when the child later exits zero. stderr carries diagnostic logs only — errors there are benign and should not crash the provider. Apply separate strategies matching vincentkoc's requirement: - stdout (audio): error → reject(Promise) — surface the failure - stderr (diagnostic): error → ignore — does not affect audio output * fix lint: remove unused signal param from mock kill() * fix(tts-local-cli): contain child stream failures Co-authored-by: 赵旺0668001248 <zhao.wang1@xydigit.com> * chore(tts-local-cli): keep release notes in PR body --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit9fa913740d) (cherry picked from commit 66099c79c0e1d82b424c63af60d3060c08787db1) * fix(tts-local-cli): preserve file output on stream errors Co-authored-by: 赵旺0668001248 <zhao.wang1@xydigit.com> (cherry picked from commit45d15aabf9) (cherry picked from commit 0d836bb58024cae18b7fc46df40806950e27e63b) * fix(azure-speech): add timeout to voices list request (#102984) * fix(azure-speech): add timeout to voices list request * test(azure-speech): simplify voice timeout proof * test(azure-speech): mark voice keys as placeholders --------- Co-authored-by: chengzhichao-xydt <chengzhichao-xydt@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit1ed04910e2) (cherry picked from commit fa440cf51c95ad2ef4608f38c846e4c425f0ceee) * fix(minimax): add timeouts to OAuth HTTP requests (#102862) * fix(minimax): add timeouts to OAuth HTTP requests * fix(minimax): remove duplicate OAuth abort signals * refactor(minimax): keep OAuth timeout internal * test(minimax): make OAuth timeout proof deterministic --------- Co-authored-by: llagy009 <0668001470@xydigit.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit8f8aad9ae6) (cherry picked from commit 3cc03752fd349668c418580389afcc0caaababca) * fix(google-meet): handle stdout/stderr stream errors in local audio bridge (#101596) * fix(google-meet): handle stdout/stderr stream errors in local audio bridge * test(google-meet): prove command bridge stream errors (cherry picked from commit5fd5bf2aee) (cherry picked from commit e61d2f9d37044d463e22691ee87bc5cb39bdfbf0) * fix(google-meet): bound Calendar event lookups (#102157) Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit28bbbe4f60) (cherry picked from commit fe03932992ab65ca9d7d0f598aa31c0c8679e49c) * fix(matrix): handle stdout/stderr stream errors in dependency commands (#101597) * fix(matrix): handle stdout/stderr stream errors in dependency commands * fix(matrix): type stream-error test process kill * fix(matrix): harden dependency stream errors * test(matrix): fix dependency stream test typings (cherry picked from commit35d5ea069a) (cherry picked from commit 141a2e76420dd593b2f3efdd7c9cb8aac2a89ef5) * fix(matrix): handle event decryption errors during sync (#94416) Co-authored-by: mushuiyu886 <mushuiyu886@users.noreply.github.com> (cherry picked from commit4200745a98) (cherry picked from commit 663134e30c8b265f89ffd692f6f10f795c2b3735) * fix(zalouser): clear probe timeout after auth resolves (#101649) (cherry picked from commitca8f6e1efd) (cherry picked from commit b66d2abccd5ffe0a75f04bf8e51cdb99d89c4456) * fix(msteams): lowercase content type so attachment classification is case-insensitive (#102431) * fix(msteams): lowercase content type so attachment classification is case-insensitive normalizeContentType only trimmed its input. MIME types are case-insensitive (RFC 2045), and MS Teams relay payloads (SharePoint, OneDrive, Bot Framework CDN) routinely emit mixed-case values such as "Image/PNG" or "Application/Vnd.Microsoft.Teams.File.Download.Info". Every downstream comparison in the attachments module assumes a lowercased value (startsWith("image/"), === "application/vnd.microsoft.teams.file.download.info", startsWith("text/html")), so a mixed-case attachment was silently misclassified: images became documents, HTML bodies were skipped, and file-download candidates were not resolved. Lowercase in normalizeContentType so all six call sites match. The sibling inferPlaceholder in the same file already lowercases via normalizeLowercaseStringOrEmpty, so this aligns the two paths. Co-Authored-By: Claude <noreply@anthropic.com> * fix(msteams): route HTML text extraction through normalizeContentType extractTextFromHtmlAttachments guarded its loop with an exact `attachment.contentType !== "text/html"` check, which is the same case-sensitivity gap the rest of the PR closes via normalizeContentType. A mixed-case "TEXT/HTML" attachment (common from Teams relays; MIME types are case-insensitive per RFC 2045) was skipped, so a message whose only body text lived in such an HTML attachment entered the agent path with empty text. Route the guard through normalizeContentType so mixed-case HTML attachments reach the body extractor. Export the function and add regression coverage for mixed-case / whitespace-padded / object-content / non-HTML cases. Co-Authored-By: Claude <noreply@anthropic.com> * fix(msteams): preserve MIME parameter case --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commite6a2136c3a) (cherry picked from commit bdaf9d91415815ec870236bd1261f5ad44759e10) * fix(msteams): bound team group lookup cache (#102814) Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com> (cherry picked from commitf6b9901243) (cherry picked from commit 1af683390d2502256eea35d157ea62015d8d2f28) * fix(tlon): cap SSE payload JSON.parse at 16 MiB to prevent OOM (#101274) * fix(tlon): cap SSE payload JSON.parse at 16 MiB to prevent OOM * fix(tlon): cap SSE stream buffer and JSON.parse at 16 MiB to prevent OOM * chore(tlon): add production-style SSE bounded proof script (#101274) Adds extensions/tlon/proof-sse-bounded.mts which drives the real UrbitSSEClient.processStream and processEvent against Node Readable streams (not unit-test mocks) to demonstrate: - normal SSE events are still delivered through the stream path; - an unterminated stream that would grow beyond 16 MiB is rejected before unbounded accumulation; - a single SSE payload above 16 MiB is rejected before JSON.parse. The script passes on this branch and fails 2/3 assertions when run against origin/main's sse-client.ts, providing the before/after proof ClawSweeper requested. * chore(tlon): fix oxlint catch type in proof script (#101274) * fix(tlon): reject oversized SSE chunk before buffer concatenation Move the stream byte-limit check before buffer += chunkStr so a single oversized chunk never lands in the pending buffer. The old guard ran after concatenation, which still allowed the memory spike this hardening is meant to prevent. Add a single-oversized-chunk test to prove the guard fires before the chunk is concatenated into the pending buffer. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(tlon): remove PR-specific SSE bounded proof script The proof script was review-only validation for #101274. Durable behavior coverage lives in sse-client.test.ts (stream buffer bounding, oversized chunk rejection before concatenation, 16 MiB boundary, normal delivery, 1000 small events). Per ClawSweeper P3 finding, drop the one-off script from the plugin tree. * fix(tlon): bound SSE event buffering safely * test(tlon): avoid unsafe optional chaining * fix(tlon): count split Unicode at SSE limit * fix(tlon): parse split SSE delimiters at limit --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit1710ccad29) (cherry picked from commit 938ba5d7fa21057b5be935b8a38a69b4ea0882cf) * fix(inworld): add timeout to voices list request (#102965) * fix(inworld): add timeout to voices list request * refactor(inworld): reuse guarded timeout test helpers * test(inworld): rely on harness timeout --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commita11449211a) (cherry picked from commit 42e1ab25c9dab2151440d0afb2d985a365086e70) * fix(voice-call): add timeout to guardedJsonApiRequest (#102884) * fix(voice-call): add timeout to guardedJsonApiRequest * fix(voice-call): bound provider JSON requests --------- Co-authored-by: chengzhichao-xydt <chengzhichao-xydt@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit5b916cb319) (cherry picked from commit 2de4b2d0708c46e451ca90bdcfeda329f9a3a318) * fix(file-transfer): reject oversized inline file writes before node dispatch (#104556) * fix(file-transfer): cap inline file write payloads * fix(file-transfer): validate inline base64 before decoding --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitfdf5812817) (cherry picked from commit 7fc1041e2737d43c38d18a7313678db774333e2d) * fix(imessage): apply authoritative projection in anchorless recovery (#104218) * fix(imessage): apply authoritative projection in anchorless recovery Rebuild on latest main with imessage-only changes: authoritative history projection (optional destination_caller_id), whole-path inbound proof tests, and no unrelated restart.ts diff. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(imessage): restore recovery cursor API and format tests Co-authored-by: Cursor <cursoragent@cursor.com> * test(imessage): add monitor whole-path L3 proof for #104136 recovery Exercise issue synthetic payloads through monitorIMessageProvider for authoritative remote reply routing and from-me suppression before dispatch. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(imessage): clear stale destination_caller_id when history omits it Exact-GUID history is authoritative for destination_caller_id. When the history row omits that outgoing-only field, clear any stale notification value instead of inheriting it into the recovered inbound projection. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: sm <sm@zwdeMacBook-Pro.local> Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit6ef3e87583) (cherry picked from commit 184deb936f55f8137d0842067893f4fe7d57e18d) * fix(imessage): narrow recovered projection before use (#106022) (cherry picked from commit8a2da4b1bf) (cherry picked from commit fa55df678fffa3cd716eb29e71be2cd516c54b96) * 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> (cherry picked from commit90b68536c4) (cherry picked from commit afbd2caff18677c15564b51cce0a6b57d0ae6804) * fix(synology-chat): strip internal tool-trace banners from outbound text (#102925) * fix(synology-chat): strip internal tool-trace banners from outbound text * fix(synology-chat): satisfy eslint curly rule * fix(synology-chat): add sanitizeText to outbound type contract * fix(synology-chat): use canonical outbound sanitizer type --------- Co-authored-by: Pick-cat <266665499+Pick-cat@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit7eb163d905) (cherry picked from commit bdc4440e2f48147a6dca84ae5a4a275a8aa7cdbe) * fix(tlon): strip internal tool-trace banners from outbound text (#103450) Route assistant-visible Tlon output through the shared sanitizer and prove the rendered Urbit poke payload for DMs, groups, and media captions. Co-authored-by: masatohoshino <g515hoshino@gmail.com> (cherry picked from commit1d20542449) (cherry picked from commit b8b5e9d72b30aadedfd591067d8918ccde6ef951) * fix(nextcloud-talk): strip internal tool-trace banners from outbound text (#101712) * fix(nextcloud-talk): strip internal tool-trace banners from outbound text * fix(nextcloud-talk): sanitize inbound replies Co-authored-by: liyuanbin <li.yuanbin1@xydigit.com> * test(nextcloud-talk): prove low-level send text preservation * test(nextcloud-talk): focus inbound sanitizer coverage * fix(nextcloud-talk): report stripped replies as non-visible * docs(changelog): note Nextcloud Talk reply sanitization * chore: keep PR changelog-neutral --------- Co-authored-by: Pick-cat <266665499+Pick-cat@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: liyuanbin <li.yuanbin1@xydigit.com> (cherry picked from commit8a93d288e2) (cherry picked from commit 3f1774653aefa225eea770b0491008a83e6a142c) * fix(microsoft-foundry): reject malformed endpoints (#104796) (cherry picked from commitf5a50db569) (cherry picked from commit 1bc1ec21b49ee1a1350ad5688fd2420f270acfb9) * fix(google): bound realtime browser token requests (#106034) * fix(google): bound realtime browser token requests * fix(google): satisfy realtime timeout checks * test(google): use placeholder browser key --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit d33254b72efc4a46824f218c9a43ff830804c96f) (cherry picked from commit ac8e45955d567dd78e5cf0e02599cb58e008da07) * fix(github-copilot): bound device flow requests (#103255) * fix(github-copilot): bound device flow requests * docs(changelog): note Copilot login timeout * fix(github-copilot): bound device flow requests * fix(github-copilot): bound device flow requests * fix(github-copilot): bound device flow requests --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Peter Steinberger <peter@steipete.me> (cherry picked from commit 1e3dea75d5690e36f135c39eb4f792815b87c19d) (cherry picked from commit faa4cf7321ce62b48a5f2c03f198e1691030acf0) * fix(openai): add timeout to realtime client-secret requests (#102860) * fix(openai): add timeout to realtime client-secret requests * test(openai): prove realtime timeout through real guard * test(openai): route realtime timeout proof through guard * fix(openai): bound realtime client-secret requests Co-authored-by: llagy009 <0668001470@xydigit.com> * fix(openai): align realtime secret timeout --------- Co-authored-by: llagy009 <0668001470@xydigit.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit 1836275810cb9cb3f7487cf66a8f7c2f0b16d853) (cherry picked from commit f2e18c4250592d8dcfc8a7bad17531fb83c3db63) * fix(memory-core): guard supplement lookup in resolveMemoryReadFailureResult with try-catch (fixes #101809) (#101902) * fix(memory-core): guard supplement lookup in resolveMemoryReadFailureResult with try-catch (fixes #101809) * fix(memory-core): preserve primary read errors --------- Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com> (cherry picked from commit1aee742d23) (cherry picked from commit 7427f3ef171139edb693dec56aec6141222d293d) * fix(browser): guard act hooks on current tab URL (#104095) * fix(browser): guard act hooks on current tab URL * test(browser): align navigation policy hook mock * test(browser): exercise real hook navigation guard --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit4bf4cacb37) (cherry picked from commit 72e4a8b21cee6cb848e50b6a211f1380bd293c6c) * fix(google-meet): bound Google API requests (#102149) Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit51b4e78c33) (cherry picked from commit 2bc883a7a23812ca9a610ae6c75119b63100fcf7) * fix(browser): reject non-page json new targets (#104129) * fix(browser): reject non-page json new targets * fix(browser): adopt only validated raw CDP targets --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit7027d2c227) (cherry picked from commit 7dea1a3cd7ac5643ec9e5c32f19fc041c5a7fc55) * fix(agents): skip wham probe when oauth access token is locally expired (cherry picked from commite975d49238) (cherry picked from commit f5b234db3fc58b4275f4e6b0e65393f3631da659) * fix(media): accept matching repeated content lengths (#102939) Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit3f68e1b5e3) (cherry picked from commit 7693544cccc64ac359597555185fdc8f530556d0) * fix: 429 errors without rate-limit wording skip the same-model retry (#99097) * fix: 429 errors without rate-limit wording skip the same-model retry Aggregated providers such as OpenRouter provider pools surface transient upstream throttles as a bare "429 <generic text>" with no RPM/TPM wording and no Retry-After header. resolveShortWindowRateLimitRetry required one of those hints, so these errors bypassed the same-model retry ladder and failed the turn on the first attempt. Treat a status-prefixed 429 as short-window once the long-window guard (quota, usage, billing wording) has filtered its phrasings, and let the existing backoff ladder pace the retry. * test(agents): streamline bare 429 coverage --------- Co-authored-by: Altay <altay@hey.com> (cherry picked from commit9330ad86ff) (cherry picked from commit f6db641108cd139f211cabeb6834f57916a4f2bf) * fix(sdk): add prototype-pollution guard to migration config merge (#103059) (#106116) * fix(sdk): add prototype-pollution guard to migration config merge mergeMigrationConfigValue and writeMigrationConfigPath had no isBlockedObjectKey guard, allowing __proto__/constructor/prototype keys from imported config files to trigger prototype pollution. Add the same guard used by the sibling config-path writer (setConfigValueAtPath/parseConfigPath) to reject blocked object keys before they reach a bracket assignment. Fixes #103059 * fix(sdk): harden migration config patches --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitb6330edbe4) (cherry picked from commit 4fe0cf4ddb1686fe0e824536d281fb4295150468) * fix(session): swallow onRecordError throw to avoid unhandled rejection (#106951) * fix(session): swallow onRecordError throw to avoid unhandled rejection * fix(session): settle async record error handlers * fix(session): assimilate record handler results --------- Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit8419675fa1) (cherry picked from commit 0f9bd196538d51d1808753da4566270df5682fe0) * fix(cron): reject non-string values in delivery target validation (#106952) * fix(cron): reject non-string values in delivery target validation assertNonBlankStringField had inverted logic — non-string values (number, boolean, object) were silently accepted because typeof !== 'string' was grouped with the undefined/null early return. The function name says 'assert non-blank string field' but it was bypassing validation for any non-string type, defeating the purpose of input validation. * test(cron): cover invalid delivery fields at entrypoints --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit692cb8dd9b) (cherry picked from commit c1e72de24d0469a7aedc98312f5d0338ac3a8f9f) * fix(extra-params): preserve resolved cacheRetention against undefined own-property clobber (#106069) * fix(extra-params): preserve resolved cacheRetention when options carries undefined own-property When the proxy transport emits cacheRetention as an own property set to undefined, JS spread semantics clobber the resolved cacheRetention value from per-model params. Re-assert the resolved value after the spread so it takes precedence over an undefined own-property in the caller's options. Fixes #106014 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(agents): strengthen cache retention precedence proof * refactor(agents): keep cache retention merge compact * style(agents): format cache retention matrix --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commite588f2c0ce) (cherry picked from commit 5b9f5f78af6b6314703ade574decfed7414c258d) * fix(gateway): guard thinkingLevel re-validation against only relevant patch fields (#102866) * fix(gateway): guard thinkingLevel re-validation against only relevant patch fields The second thinkingLevel validation block used `if (next.thinkingLevel)`, which enters on ANY patch when the session already has a thinkingLevel inherited from the existing entry. This caused unnecessary model catalog loading and could silently delete or modify the existing value. Fix: change guard to also check that the patch explicitly touches thinkingLevel or changes the model (which may alter the effective provider/model that thinkingLevel is validated against). Ref: BUG-002 (local finding) Co-Authored-By: Claude <claude@anthropic.com> * test(gateway): prove session patch catalog isolation --------- Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit9526224f42) (cherry picked from commit d47e7cf04ac09f2b5b65bd06021aa72ed37c0092) * fix(gateway): cap history when numeric limit is huge (#104263) * fix(gateway): cap oversized history limits * refactor(gateway): simplify oversized history limits --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit3ed8143495) (cherry picked from commit 856de05abd18f556a481cde78a4fa874828f5d01) * fix(agents): xAI/Grok requests fail after a stale reasoning replay ("could not decrypt encrypted_content") (#97926) * fix(agents): recover xAI/Grok "could not decrypt encrypted_content" 400 instead of tripping the circuit breaker openclaw already strips a stale reasoning replay and retries the Responses call, but the recovery is gated on isInvalidEncryptedContentError(), which only recognizes the `invalid_encrypted_content` / `thinking_signature_invalid` codes/messages. xAI/Grok returns a prose 400 with no error code — "Could not decrypt the provided encrypted_content. Ensure the value is the unmodified encrypted_content from a previous response." — so the matcher returns false, the call fails, and the per-model circuit breaker trips, blocking ALL grok-4.3 traffic through the gateway until manual intervention. Match that message (contains `encrypted_content` and a decrypt-failure phrase) so the existing strip-and-retry path handles it too. Narrow enough to avoid unrelated "could not decrypt" messages (e.g. the OAuth sidecar warning), which do not mention `encrypted_content`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(agents): narrow xAI decrypt retry detection Co-authored-by: rvdlaar <rvdlaar@gmail.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitfc507c70c5) (cherry picked from commit eda2574e4acaa7b146e12c8a9a2d0c2e6127906c) * fix(memory-host): reject queued worker requests on shutdown (#102451) * fix(memory-host): reject queued worker requests on shutdown * fix(memory-host): settle queued requests on shutdown --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitd5a31888ed) (cherry picked from commit 7de709b0cf25155a4cd9c7ac719c9ed2cf9f801f) * fix(memory): accept leading-zero Content-Length on JSON responses (#105916) * fix(memory): accept leading-zero content lengths * test(memory): keep leading-zero size caps --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit8ffe428bd8) (cherry picked from commit 57318da2ced13809d8fbff77640d415c81afebd6) * fix(fal): image generation hangs on slow generated-image downloads (#103071) * fix(fal): timeout generated image downloads * fix(fal): honor image operation timeout budget --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit87a652bc37) (cherry picked from commit 113072a74725143ee33c219550a6b4910a06f23b) * fix(media): accept matching repeated content lengths (#102939) Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit3f68e1b5e3) (cherry picked from commit 7693544cccc64ac359597555185fdc8f530556d0) * fix: 429 errors without rate-limit wording skip the same-model retry (#99097) * fix: 429 errors without rate-limit wording skip the same-model retry Aggregated providers such as OpenRouter provider pools surface transient upstream throttles as a bare "429 <generic text>" with no RPM/TPM wording and no Retry-After header. resolveShortWindowRateLimitRetry required one of those hints, so these errors bypassed the same-model retry ladder and failed the turn on the first attempt. Treat a status-prefixed 429 as short-window once the long-window guard (quota, usage, billing wording) has filtered its phrasings, and let the existing backoff ladder pace the retry. * test(agents): streamline bare 429 coverage --------- Co-authored-by: Altay <altay@hey.com> (cherry picked from commit9330ad86ff) (cherry picked from commit f6db641108cd139f211cabeb6834f57916a4f2bf) * fix(sdk): add prototype-pollution guard to migration config merge (#103059) (#106116) * fix(sdk): add prototype-pollution guard to migration config merge mergeMigrationConfigValue and writeMigrationConfigPath had no isBlockedObjectKey guard, allowing __proto__/constructor/prototype keys from imported config files to trigger prototype pollution. Add the same guard used by the sibling config-path writer (setConfigValueAtPath/parseConfigPath) to reject blocked object keys before they reach a bracket assignment. Fixes #103059 * fix(sdk): harden migration config patches --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitb6330edbe4) (cherry picked from commit 4fe0cf4ddb1686fe0e824536d281fb4295150468) * fix(session): swallow onRecordError throw to avoid unhandled rejection (#106951) * fix(session): swallow onRecordError throw to avoid unhandled rejection * fix(session): settle async record error handlers * fix(session): assimilate record handler results --------- Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit8419675fa1) (cherry picked from commit 0f9bd196538d51d1808753da4566270df5682fe0) * fix(cron): reject non-string values in delivery target validation (#106952) * fix(cron): reject non-string values in delivery target validation assertNonBlankStringField had inverted logic — non-string values (number, boolean, object) were silently accepted because typeof !== 'string' was grouped with the undefined/null early return. The function name says 'assert non-blank string field' but it was bypassing validation for any non-string type, defeating the purpose of input validation. * test(cron): cover invalid delivery fields at entrypoints --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit692cb8dd9b) (cherry picked from commit c1e72de24d0469a7aedc98312f5d0338ac3a8f9f) * fix(extra-params): preserve resolved cacheRetention against undefined own-property clobber (#106069) * fix(extra-params): preserve resolved cacheRetention when options carries undefined own-property When the proxy transport emits cacheRetention as an own property set to undefined, JS spread semantics clobber the resolved cacheRetention value from per-model params. Re-assert the resolved value after the spread so it takes precedence over an undefined own-property in the caller's options. Fixes #106014 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test(agents): strengthen cache retention precedence proof * refactor(agents): keep cache retention merge compact * style(agents): format cache retention matrix --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commite588f2c0ce) (cherry picked from commit 5b9f5f78af6b6314703ade574decfed7414c258d) * fix(gateway): guard thinkingLevel re-validation against only relevant patch fields (#102866) * fix(gateway): guard thinkingLevel re-validation against only relevant patch fields The second thinkingLevel validation block used `if (next.thinkingLevel)`, which enters on ANY patch when the session already has a thinkingLevel inherited from the existing entry. This caused unnecessary model catalog loading and could silently delete or modify the existing value. Fix: change guard to also check that the patch explicitly touches thinkingLevel or changes the model (which may alter the effective provider/model that thinkingLevel is validated against). Ref: BUG-002 (local finding) Co-Authored-By: Claude <claude@anthropic.com> * test(gateway): prove session patch catalog isolation --------- Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit9526224f42) (cherry picked from commit d47e7cf04ac09f2b5b65bd06021aa72ed37c0092) * fix(gateway): cap history when numeric limit is huge (#104263) * fix(gateway): cap oversized history limits * refactor(gateway): simplify oversized history limits --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit3ed8143495) (cherry picked from commit 856de05abd18f556a481cde78a4fa874828f5d01) * fix(agents): xAI/Grok requests fail after a stale reasoning replay ("could not decrypt encrypted_content") (#97926) * fix(agents): recover xAI/Grok "could not decrypt encrypted_content" 400 instead of tripping the circuit breaker openclaw already strips a stale reasoning replay and retries the Responses call, but the recovery is gated on isInvalidEncryptedContentError(), which only recognizes the `invalid_encrypted_content` / `thinking_signature_invalid` codes/messages. xAI/Grok returns a prose 400 with no error code — "Could not decrypt the provided encrypted_content. Ensure the value is the unmodified encrypted_content from a previous response." — so the matcher returns false, the call fails, and the per-model circuit breaker trips, blocking ALL grok-4.3 traffic through the gateway until manual intervention. Match that message (contains `encrypted_content` and a decrypt-failure phrase) so the existing strip-and-retry path handles it too. Narrow enough to avoid unrelated "could not decrypt" messages (e.g. the OAuth sidecar warning), which do not mention `encrypted_content`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(agents): narrow xAI decrypt retry detection Co-authored-by: rvdlaar <rvdlaar@gmail.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitfc507c70c5) (cherry picked from commit eda2574e4acaa7b146e12c8a9a2d0c2e6127906c) * fix(memory-host): reject queued worker requests on shutdown (#102451) * fix(memory-host): reject queued worker requests on shutdown * fix(memory-host): settle queued requests on shutdown --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitd5a31888ed) (cherry picked from commit 7de709b0cf25155a4cd9c7ac719c9ed2cf9f801f) * fix(memory): accept leading-zero Content-Length on JSON responses (#105916) * fix(memory): accept leading-zero content lengths * test(memory): keep leading-zero size caps --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit8ffe428bd8) (cherry picked from commit 57318da2ced13809d8fbff77640d415c81afebd6) * fix(agent-core): stop canceled parallel tools from starting (#102276) * fix(agent-core): skip prepared tools after abort * docs(agent-core): explain parallel abort guard * docs(changelog): note parallel cancellation fix * docs(changelog): leave release notes release-owned --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit85aa26d34f) (cherry picked from commit ae2087834ff36591015e55e25f038bffc6243c8d) * fix: ignore invalid Retry-After HTTP dates (#102987) * fix: ignore invalid Retry-After HTTP dates * fix(ai): centralize strict Retry-After dates --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Peter Steinberger <peter@steipete.me> (cherry picked from commit 2fd0f88f62e8b0ac696559777b6208955b217a8f) (cherry picked from commit 888fd2b93875b2e121efc03a0167fdabec840f3d) * fix(read): reject non-positive offsets (#102481) * fix(read): reject non-positive offsets * fix(read): validate offsets before filesystem access Co-authored-by: qingminlong <qing.minlong@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit 2f8f8ae1ae14c6365491b796430c90dcc0cd7f22) (cherry picked from commit ae6ffc68d9e9f1a35d3f6ebf23f3949d74db975e) * fix(plugins): fall back to os.homedir() when HOME/OPENCLAW_HOME is empty (#102413) * fix(plugins): fall back to os.homedir() when HOME/OPENCLAW_HOME is empty manifest-metadata-scan resolved the home directory with `env.OPENCLAW_HOME ?? env.HOME ?? env.USERPROFILE ?? os.homedir()`. The nullish coalescing operator only catches null/undefined, so an empty or whitespace home variable (e.g. HOME="" in a stripped-down container/sandbox env) was kept as "" and path.join("", ".openclaw") resolved to a RELATIVE ".openclaw" under the cwd. Plugin discovery then read global extensions from the wrong directory. Normalize each candidate with the already-imported normalizeOptionalString (which returns undefined for empty/whitespace) so an empty value falls through to os.homedir(), matching the canonical home resolver in src/infra/home-dir.ts. Co-Authored-By: Claude <noreply@anthropic.com> * refactor(plugins): reuse canonical manifest paths Co-authored-by: liyuanbin <li.yuanbin1@xydigit.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit 61a7fc5da6af27803a46d1efa4e1536998d84eb9) (cherry picked from commit de3d9ecf7325adbe5dd5b9e72d60955361d59530) * fix(infra): cap session-maintenance-warning dedupe cache with LRU eviction (#101643) * fix(infra): cap session-maintenance-warning dedupe cache with LRU eviction The warnedContexts Map accumulated every warned session key forever with no eviction, TTL, or size cap. A long-running gateway would grow this unboundedly. Add a 4 096-entry LRU cache with touch-on-read so frequently re-warned sessions survive and old entries are evicted on overflow. * fix(test): restore original unicode escapes and add LRU eviction tests * fix(test): seed eviction entries with real warning context keys ClawSweeper P3: the eviction test seeded but the production buildWarningContext computes . The mismatch meant params1 could redeliver because the context changed, not because LRU eviction actually worked. Seed the exact context pattern so the test fails when eviction breaks. * fix(infra): bound maintenance warning cache Co-authored-by: sunlit-deng <sunlit-deng@users.noreply.github.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: sunlit-deng <sunlit-deng@users.noreply.github.com> (cherry picked from commit 8dedb0ebcae07ea027ed7b57e21d1e80010ca1ce) (cherry picked from commit 55d681644185d361119398dcae43a43602114c75) * fix(usage-bar): cap warnedTemplateOverrides warn-once dedupe cache (#102659) * fix(usage-bar): cap warnedTemplateOverrides warn-once dedupe cache Replace unbounded warnedTemplateOverrides Set with createDedupeCache(maxSize=256) for consistency with the bounded fileCache Map (MAX_CACHED_TEMPLATE_FILES=64) already present in the same file. Co-Authored-By: Claude <noreply@anthropic.com> * fix(usage-bar): bound invalid-template warnings Co-authored-by: ZengWen-DT <ceng.wen@xydigit.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit a1c16f0a3dc3d94316f36c57b7e7c70cb9567fa4) (cherry picked from commit 3cec4603bc75d66bb6a6a9c05dafd5b87a4ed062) * fix(agents): prevent local provider sidecars surviving canceled startup (#104070) * fix(agents): prevent local provider sidecars surviving canceled startup * test(agents): harden local service abort regression --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit ad7f84949019e6ea12ee4db102c833b31d2310bf) (cherry picked from commit 3a20b4e17341769ad7b7dfe43a9c804fc522528e) * fix(agents): reject invalid goal token budgets (#104534) * fix(agents): reject invalid goal token budgets * test(agents): update goal assertion for session accessor --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit c59e24647c35c7533695bc39f5eff7a664709558) (cherry picked from commit e9e3f651893cbe001ef14555c69c8902104fd76c) * fix(infra): bound ed25519 base64url decode input length (#104921) (cherry picked from commit 4dfffeb4d1f983cbbf1e4e1bd2cb5d54a007ee95) (cherry picked from commit baec292246e1a6793e9563ad36de7b7aa009a7c6) * fix(update): prevent build workers surviving timeouts (#103406) * fix(update): terminate timed-out process trees * chore: leave changelog to release generation (cherry picked from commit c7909ead75b553e0d6f751cad6a9b781712b9c0f) (cherry picked from commit 176942a821709cbf5eab3d36d1b37743591c23aa) * fix(pdf): reject unsafe page numbers before analysis (#105315) * fix(pdf): reject unsafe page numbers before analysis * test(pdf): bound unsafe page range regression (cherry picked from commit0e15a5d994) (cherry picked from commit 9b13bb3f9347025cad38bcd2ff9c3d8dd0e49269) * fix(tool-call-repair): preserve stream content order after repair (#103585) Keep byte-over-cap visible suffixes at their streamed content indexes when terminal message snapshots are normalized. Co-authored-by: ZOOWH <ZOOWH@users.noreply.github.com> (cherry picked from commit2c909212f1) (cherry picked from commit 338b33fd071ee89861bfb1e8873c1991fb35eeaa) * fix(cron): channel failure alerts drop when global webhook failure destination is set (#102445) * fix(cron): keep channel-shaped failure destinations from inheriting webhook mode * test(cron): prove channel failure destination announces under global webhook * test(gateway): prove cron channel failure destination under global webhook * fix(cron): harden failure destination mode inference Tighten the resolver invariant, reuse focused test fixtures, and keep the Gateway proof at the real finished-event boundary. Co-authored-by: wuqingxuan <wu.qingxuan@xydigit.com> Co-authored-by: Hakan Baysal <hakan.baysal@trmix.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Hakan Baysal <hakan.baysal@trmix.com> (cherry picked from commite99af07369) (cherry picked from commit 57219910d9f5d5235b98792bb721638eaaf99147) * fix(mcp): bound short-lived OAuth requests (#103704) * fix(mcp): bound CLI OAuth login through guarded fetch timeout * fix(mcp): bound OAuth request lifecycles Co-authored-by: NIO <nocodet@mail.com> * fix(mcp): preserve caller cancellation * test(mcp): centralize timeout rejection capture --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: NIO <nocodet@mail.com> (cherry picked from commit9c0c932c33) (cherry picked from commit a308fbaf77cc0def11d1d5a65ae7325ecde883b9) * fix(ai): reject non-finite tool schema numbers (#104470) * fix(ai): reject non-finite tool schema numbers Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(ai): catch non-finite values from tool schema serializers Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com> * test(ai): cover nested tool schema serializers Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(ai): satisfy schema projection lint Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(ai): satisfy schema projection lint Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(ai): preserve empty-key schema diagnostic paths * fix(ai): reject boxed non-finite schema numbers * fix(ai): ignore spoofed boxed-number tags * fix(ai): isolate boxed-number brand probes * refactor(ai): use intrinsic boxed-number detection --------- Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitf8c7f67bde) (cherry picked from commit e551be1ea4032177ffa5c897ad32a5d50b02e73e) * fix: require full frontmatter delimiter lines (#101795) Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com> (cherry picked from commitdbbab1044e) (cherry picked from commit bc332f5007a8e1482912d2c0ef2dde21524234a5) * fix(browser): normalize geolocation permission origins (#105092) Co-authored-by: llagy007 <0668001470@xydigit.com> (cherry picked from commit89f740651d) (cherry picked from commit 8b61386a8fc9121f3c5894c98df420d73098ed08) * fix(zalo): bound stalled inbound media header waits (#104578) * fix(zalo): bound stalled inbound media header waits * test(zalo): type inbound media mock to runtime contract * test(zalo): return complete saved media metadata --------- Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit9b430fd6f6) (cherry picked from commit 398b7044ea91e2edcb9fb2c57c4c6983e1388e2c) * fix(browser): bound Chrome launch stderr diagnostics (#101506) * fix(browser): bound Chrome launch stderr diagnostics * fix(browser): preserve chrome launch recovery diagnostics * refactor(browser): share bounded UTF-8 stderr tails * fix(browser): own bounded stderr storage --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commita522e4309c) (cherry picked from commit 1d61a4947984675c3ec6ad428378c97ff91f5b20) * fix(twilio): redact webhook turnToken diagnostics (#102089) * fix(twilio): redact webhook turnToken diagnostics * chore(twilio): rerun ci * fix(twilio): contain webhook URL diagnostics Co-authored-by: Alix-007 <li.long15@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitb37476ab0b) (cherry picked from commit 408ffdf6fd7f9a299ea0b4760e4ff7ed8fa4e7f9) * 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> (cherry picked from commitbaa009e26f) (cherry picked from commit 6bbb9cdf887d21e990c25232fc3e96e9dd25d1d3) * fix(nextcloud-talk): add timeout to room info lookup (#102859) * fix(nextcloud-talk): add timeout to room info lookup * test(nextcloud-talk): assert room lookup deadline Co-authored-by: llagy009 <0668001470@xydigit.com> --------- Co-authored-by: llagy009 <0668001470@xydigit.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitc4f46baec3) (cherry picked from commit 87576b04a606157fa7da30dd46a92a387b3f4ed1) * fix(tlon): bound stalled inbound and outbound media header waits (#104132) * fix(tlon): bound stalled inbound and outbound media header waits * refactor(tlon): share media fetch timeout policy --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitcacd435632) (cherry picked from commit 4a24faa8d2795adabf0ee84359933cb7289063b8) * fix(googlechat): bound webhook cert fetch during token verification (#102924) * fix(googlechat): bound webhook cert fetch during token verification * refactor(googlechat): consolidate cert timeout proof --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitce990a3ad9) (cherry picked from commit dd6804316194156b4d53c6712f28e445b52da215) * test(release): keep middle backport core-only * fix(google): stream Gemini batch JSONL output instead of res.text() (#102974) * fix(google): stream Gemini batch JSONL output instead of res.text() * fix(google): avoid Promise executor return in batch stream test --------- Co-authored-by: NIO <nocodet@mail.com> (cherry picked from commit18e8713b99) (cherry picked from commit 1a9f10c895f2649cb2d658ea406232ccd62ae2eb) * fix(queue): prevent applyQueueDropPolicy from selecting in-flight items as overflow victims (#103284) * fix(queue): prevent applyQueueDropPolicy from selecting in-flight items as overflow victims When a burst of inbound messages hits the followup queue cap while the head item is mid-delivery, applyQueueDropPolicy can select that same in-flight item as an overflow victim. With the default dropPolicy: "summarize", the in-flight item ends up recorded in the overflow summary as dropped even though it is still being delivered, producing a contradictory record where the same message is both answered and reported as unanswered-due-to-overflow. The fix introduces an optional `inFlight` Set parameter to applyQueueDropPolicy and drainNextQueueItem. The followup queue state now owns a shared inFlight set that is: - Populated by drainNextQueueItem during the await run(next) window - Populated by the collect-merge drain path for activeGroupItems - Passed to applyQueueDropPolicy in enqueueFollowupRun The drop policy now computes an effective queue length that excludes in-flight items, and skips them when selecting splice victims. Fixes #103246 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(queue): align pending depth with active deliveries --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit2f7e2aee15) (cherry picked from commit fea4530d9c75046dd3b8ed116268291a480e5417) * fix: Microsoft Teams streaming keeps chunk after whitespace collapse (#102357) * fix(msteams): preserve streaming delta after whitespace collapse * fix(msteams): clear stale stream text on rewrite fallback * test(msteams): update delivery trace stream mock --------- Co-authored-by: Peter Steinberger <steipete@openai.com> (cherry picked from commit787ed383f5) (cherry picked from commit 14837e7d6a0a3cc05ca98ac0e4061d9fc61cf8e8) * fix(gateway): bound sessions.usage all-agent session discovery concurrency (#102013) * fix(gateway): bound sessions.usage all-agent session discovery concurrency * refactor(gateway): centralize usage agent tasks --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit34248e101f) (cherry picked from commit da2bb3c6c0f0824cbe922d2d5d469ac5e975b17d) * fix(google-meet): validate calendar Meet URLs (#104863) * fix(google-meet): validate calendar meet urls * fix(google-meet): share meet url normalization * fix(google-meet): normalize Calendar Meet URLs * fix(google-meet): keep calendar text fallback stable * fix(google-meet): validate calendar text candidates --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Peter Steinberger <peter@steipete.me> (cherry picked from commit7ed7840c94) (cherry picked from commit 6b1d47a41f0905405cba1d8e7bff133a3fa3da95) * fix(node): approved local commands no longer fail identity validation (#103886) * fix(node): preserve approval replay identity * docs(node): explain replay identity boundary * fix(node): reuse persisted replay identity * chore(release): leave changelog to release automation (cherry picked from commit7a38f140a2) (cherry picked from commit 825dbccbd4dafa4bfec8f29764d61aeedf5c6c46) * fix(google-meet): guard node-host meet URLs (#104687) (cherry picked from commitf6d11d0e29) (cherry picked from commit 16d2f0e01e115c1c7624c954231f7d57d9a9c15d) * fix(plugins): bound hosted catalog feed reads on non-streaming responses (#101000) Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit8cf88bfa12) (cherry picked from commit 4297f51be999679d4fdbef99b5389cfe3cc38c27) * fix(sessions): reject malformed history offsets (#103594) * fix(sessions): reject malformed history offsets * test(sessions): prove invalid offsets stop before reads --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitbf02b611eb) (cherry picked from commit f7528ecfc97dab6d25b607da38a5330c033c367b) * 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> (cherry picked from commit2f057e1be7) (cherry picked from commit 5c4fe1c0c7a5d9b2f486877eacec0fb040e4b2e6) * test(github-copilot): cover token exchange timeout fallback The provider adapter already classifies Copilot token exchange failures as setup errors. Preserve the timeout fallback assertion from the source backport while the owned deadline lives in the plugin SDK. (cherry picked from commit e41e421ec1b2a4673b11803be274597be2b5b7a5) * fix(searxng): report incomplete response bodies Preserve the extension-side diagnostic and regression coverage from the stream-failure backport; the shared reader adaptation is owned by the core slice. (cherry picked from commit d499f201a66017c1d60b55f69388c8512214ec05) * fix: complete browser and Google Meet backport adaptations Require a page only for the raw /json/new result while retaining compatibility for legacy list entries with no target type. Use the release-line profile state and tab-limit API. Restore the bounded Google OAuth success-body reader that owns the existing 256 KiB limit. (cherry picked from commit 7dea1a3cd7ac5643ec9e5c32f19fc041c5a7fc55) (cherry picked from commit783c0aec50) * revert: exclude incomplete middle backports * fix(web): mark partial response reads when streams fail (#102550) (cherry picked from commit6cd94f6049) * fix(github-copilot): bound Copilot token exchange fetch timeout (#104488) (cherry picked from commit92db88e36b) * test(google-meet): cover bounded OAuth token reads (cherry picked from commit783c0aec50) * revert: exclude incomplete tool-call repair backport * fix(retry): complete release-line adaptation * perf(slack): bound thread history pagination (cherry picked from commite3b43a0001) * fix(mattermost): cap opaque target cache (#103258) * fix(mattermost): cap opaque target cache * refactor(mattermost): clarify bounded target cache * chore: keep release notes in PR * chore: keep release notes in PR * refactor(mattermost): clarify bounded target cache --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: Peter Steinberger <peter@steipete.me> (cherry picked from commit20e1368787) * fix(discord): recover from failed gateway resumes (#103596) * fix(discord): recover from failed gateway resumes * chore: leave release notes to release workflow (cherry picked from commitabbd5ae3ea) * 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 (cherry picked from commita49567cdfd) * fix(qqbot): bound stalled token acquisition (#102897) (cherry picked from commit6b460e50a4) * fix(qqbot): reject unsafe mention patterns (#102976) Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitc93f87756a) * fix(feishu): configure websocket ping timeout (#103763) (cherry picked from commita0c4c31a17) * fix(signal): surface daemon errors split across output chunks (#104152) * fix(signal): preserve daemon log lines across chunks * test(signal): cover split utf-8 daemon output --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitbf642ef287) * fix(discord): keep slash commands deployed at the application limit (#105280) * fix(discord): reconcile commands at the application cap * docs(changelog): note Discord command cap fix * chore: keep release changelog unchanged * fix(discord): narrow command deployment errors (cherry picked from commit4249cdb8fe) * fix(discord): bound ffmpeg stderr by bytes (#104230) (cherry picked from commit47751c117c) * fix(mattermost): add timeout to REST client requests (#102027) * fix(mattermost): add timeout to REST client requests * fixup: preserve Mattermost DM retry timeout * test(mattermost): reuse hanging server helper * test(mattermost): satisfy timeout lint --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit65b2e7a4e3) * fix(discord): add timeouts to PluralKit lookup requests (#104121) * fix(discord): add timeouts to PluralKit lookup requests * fix(discord): bound PluralKit preflight cancellation * docs(changelog): note PluralKit lookup deadline * chore: keep changelog release-owned * test(discord): reject PluralKit aborts with errors --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commite7c3f7be6c) * fix(telegram): add timeouts to getChat lookup requests (#104289) * fix(telegram): add timeouts to getChat lookup requests * fix(telegram): reuse shared timeout abort helper (cherry picked from commit 78a98a7ed8f93cbd9fb3cb7f0511871a37076da4) * fix(feishu): prevent duplicate content in streaming cards (#103915) * fix(feishu): keep streaming card snapshots authoritative Co-authored-by: Jun Ma <hpumajunhappy@163.com> * refactor(feishu): use current snapshot as retry source * fix(feishu): validate CardKit response bodies * fix(feishu): keep close summaries accepted * test(feishu): simplify close rejection state proof * test(feishu): match normalized close summary --------- Co-authored-by: Jun Ma <hpumajunhappy@163.com> * fix(feishu): bound streaming CardKit JSON responses * fix(feishu): add 30 s request timeout to streaming-card API calls (#102948) * fix(feishu): bound streaming-card API requests with a 30s timeout * fix(feishu): honor configured streaming timeout Signed-off-by: sallyom <somalley@redhat.com> * test(feishu): declare streaming mock credentials Signed-off-by: sallyom <somalley@redhat.com> --------- Signed-off-by: sallyom <somalley@redhat.com> Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: sallyom <somalley@redhat.com> (cherry picked from commit473df17bd7) * revert: exclude incomplete node identity backport * fix(utils): fetchWithTimeout ignores caller-provided AbortSignal in RequestInit (#102951) * fix(utils): fetchWithTimeout ignores caller-provided AbortSignal in RequestInit * fix(fetch): preserve caller abort through response body * test(fetch): satisfy abort rejection lint * test(mattermost): satisfy promise executor lint --------- Co-authored-by: Aniruddha Adak <aniruddhaadak80@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commit991262e2e7) * fix(release): complete bounded backport adaptations * fix(mattermost): bound stalled inbound media header waits (#104575) * fix(mattermost): bound stalled inbound media header waits * test(mattermost): always close stalled media server * test(mattermost): satisfy server cleanup lint --------- Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> (cherry picked from commitc04c85b6f3) * fix(web): complete bounded response adaptation * fix: complete release-line plugin adaptations Restore Browser route and diagnostic contracts, complete the Tlon media-runtime migration, and align Google Meet, iMessage, and Zalo changes with the release-line SDK types. Source provenance: 1d61a4947984675c3ec6ad428378c97ff91f5b20, 8b61386a8fc9121f3c5894c98df420d73098ed08, 4a24faa8d2795adabf0ee84359933cb7289063b8, 398b7044ea91e2edcb9fb2c57c4c6983e1388e2c, 6bbb9cdf887d21e990c25232fc3e96e9dd25d1d3, 16d2f0e01e115c1c7624c954231f7d57d9a9c15d. * test(web): model bounded response stream failures * fix(clickclack): sanitize outbound assistant text Adapted for the release-line ClickClack client: retain quote replies, omit unreleased provenance/correlation APIs. (cherry picked from commit2a69149566) * fix(discord): add timeouts to directory lookup requests (#104290) (cherry picked from commitbfb4557c83) * fix(release): adapt browser and oauth backport contracts * fix: adapt plugin media timeout contracts * fix(nextcloud-talk): complete bounded room cache backport * chore(release): prepare 2026.6.35 * fix(release): repair provider mocks and ACPX shrinkwrap * fix(release): align SDK and cron test baselines * fix(release): complete web and PDF backport contracts * test(web): use bounded response fixtures * chore(release): regenerate npm shrinkwraps for 2026.6.35 * fix(telegram): stalled getChat errors retain connections (#109007) * fix(telegram): abort stalled getChat errors * test(telegram): satisfy promise executor lint * fix(telegram): close getChat lookup transports --------- Co-authored-by: Peter Steinberger <steipete@gmail.com> * chore(release): complete npm shrinkwrap metadata * fix(release): complete bounded web response test fixtures * fix(release): repair extension lint backports * fix(release): align extension backport fixtures * test(qqbot): preserve mocked warning typing * fix(codex): isolate native hook relay startup * fix(release): resolve CI lint failures --------- Signed-off-by: sallyom <somalley@redhat.com> Signed-off-by: lsr911 <liao.shirong@xydigit.com> Co-authored-by: machine3at <vivekbehani@me.com> Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com> Co-authored-by: miorbnli <li.yuanbin1@xydigit.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Alix-007 <li.long15@xydigit.com> Co-authored-by: sallyom <somalley@redhat.com> Co-authored-by: Ayaan Zaidi <hi@obviy.us> Co-authored-by: mushuiyu886 <yang.haoyu@xydigit.com> Co-authored-by: NIO <hu.genshen@xydigit.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org> Co-authored-by: NIO <nocodet@mail.com> Co-authored-by: Peter Steinberger <steipete@golden-gate.local> Co-authored-by: cxbAsDev <chen.xianbiao@xydigit.com> Co-authored-by: wangmiao0668000666 <wang.miao86@xydigit.com> Co-authored-by: pick-cat <huang.ting3@xydigit.com> Co-authored-by: Pick-cat <266665499+Pick-cat@users.noreply.github.com> Co-authored-by: Agustin Rivera <31522568+eleqtrizit@users.noreply.github.com> Co-authored-by: lsr911 <liao.shirong@xydigit.com> Co-authored-by: sunlit-deng <yang.jiajun1@xydigit.com> Co-authored-by: wahaha1223 <0668001153@xydigit.com> Co-authored-by: Peter Steinberger <steipete@gmail.com> Co-authored-by: zw-xysk <zhao.wang1@xydigit.com> Co-authored-by: xingzhou <zhang.guiping@xydigit.com> Co-authored-by: krissding <ding.yuting@xydigit.com> Co-authored-by: Peter Steinberger <peter@steipete.me> Co-authored-by: Yuval Dinodia <102706514+yetval@users.noreply.github.com> Co-authored-by: thomas.szbay <zheng.tao@xydigit.com> Co-authored-by: RileyJJY <0668000974@xydigit.com> Co-authored-by: RileyJJY <100176083+RileyJJY@users.noreply.github.com> Co-authored-by: Wynne668 <ceng.wen@xydigit.com> Co-authored-by: Zeng Wen <27948732+ZengWen-DT@users.noreply.github.com> Co-authored-by: Monkey-wusky <mao.yuhao@xydigit.com> Co-authored-by: chengzhichao-xydt <cheng.zhichao@xydigit.com> Co-authored-by: maweibin <ma.weibin@xydigit.com> Co-authored-by: zengLingbiao <zeng.lingbiao@xydigit.com> Co-authored-by: ZengWen-DT <290981215+ZengWen-DT@users.noreply.github.com> Co-authored-by: LZY3538 <liu.zhenye@xydigit.com> Co-authored-by: llagy007 <0668001470@xydigit.com> Co-authored-by: chengzhichao-xydt <chengzhichao-xydt@users.noreply.github.com> Co-authored-by: mushuiyu886 <mushuiyu886@users.noreply.github.com> Co-authored-by: qingminlong <qing.minlong@xydigit.com> Co-authored-by: sm <sm@zwdeMacBook-Pro.local> Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com> Co-authored-by: Masato Hoshino <246810661+masatohoshino@users.noreply.github.com> Co-authored-by: masatohoshino <g515hoshino@gmail.com> Co-authored-by: mikasa <0668001030@xydigit.com> Co-authored-by: Gorkem Erdogan <gorkem.erdogan@outlook.com> Co-authored-by: Altay <altay@hey.com> Co-authored-by: ruel225 <liu.rui25@xydigit.com> Co-authored-by: moguangyu5-design <mo.guangyu@xydigit.com> Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com> Co-authored-by: SunnyShu <shu.zongyu@xydigit.com> Co-authored-by: Claude <claude@anthropic.com> Co-authored-by: rvdlaar <rvdlaar@users.noreply.github.com> Co-authored-by: QiuYuang <chou.yuang@xydigit.com> Co-authored-by: qingminlong <0668001063@xydigit.com> Co-authored-by: Harjoth Khara <harjoth.khara@gmail.com> Co-authored-by: ZOOWH <ZOOWH@users.noreply.github.com> Co-authored-by: wuqxuan <wu.qingxuan@xydigit.com> Co-authored-by: Hakan Baysal <hakan.baysal@trmix.com> Co-authored-by: VectorPeak <garrufariw@gmail.com> Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> Co-authored-by: NianJiu <3235467914@qq.com> Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com> Co-authored-by: tzy-17 <tang.ziyi@xydigit.com> Co-authored-by: Galin Iliev <iliev@galcho.com> Co-authored-by: Peter Steinberger <steipete@openai.com> Co-authored-by: litang9 <141409885+litang9@users.noreply.github.com> Co-authored-by: Jun Ma <hpumajunhappy@163.com> Co-authored-by: ANIRUDDHA ADAK <aniruddhaadak80@gmail.com> Co-authored-by: Aniruddha Adak <aniruddhaadak80@users.noreply.github.com>