Commit Graph

61720 Commits

Author SHA1 Message Date
Vincent Koc 0a338147a5 refactor(numbers): share non-negative finite guard 2026-06-23 03:46:22 +08:00
Vincent Koc 013e33c6d3 fix(telegram): avoid duplicate progress headings 2026-06-22 21:43:47 +02:00
Hoi Hin Adrian Ip dbd4c98b02 Handle Codex toolResult blocks in truncation (#87912)
Co-authored-by: Hoi Hin Adrian Ip <255652477+AdrianIp0204@users.noreply.github.com>
2026-06-22 19:41:30 +00:00
Vincent Koc 0529281430 refactor(sqlite): share numeric column decoding 2026-06-23 03:38:18 +08:00
Vincent Koc 284e514e19 refactor(logging): share log file path primitives 2026-06-23 03:34:43 +08:00
Vincent Koc 066700bdd0 refactor(anthropic): share Foundry bearer auth policy 2026-06-23 03:31:32 +08:00
Vincent Koc 470a0f80b6 refactor(plugins): reuse optional string normalization 2026-06-23 03:28:01 +08:00
Vincent Koc b31bf811cb refactor(providers): share bounded error body reader 2026-06-23 03:24:54 +08:00
Yzx 1662b07810 fix(cron): expose per-job fallbacks in CLI (#93369) 2026-06-22 19:22:20 +00:00
pick-cat cf31689a03 fix(control-ui): restore provider usage quota pill in sidebar session switcher (fixes #93041) (#94219)
* fix(control-ui): restore provider usage quota pill in sidebar session switcher

* ci: re-trigger flaky cron-service shard

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

---------

Co-authored-by: Pick-cat <266665499+Pick-cat@users.noreply.github.com>
Co-authored-by: Pick-cat <Pick-cat@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 19:21:38 +00:00
Vincent Koc a07d92ff4f refactor(net): share FormData shape guard 2026-06-23 03:20:18 +08:00
Vincent Koc 858fd2c5a2 refactor(sqlite): share user version probe 2026-06-23 03:19:45 +08:00
Vincent Koc 7c4ab782cb refactor(providers): reuse capability provider registry maps 2026-06-23 03:17:22 +08:00
Moeed Ahmed 5cafe4b0cf fix(telegram): keep bot reply answers anchored to current message (#90475)
Co-authored-by: Moeed Ahmed <moeedahmed@Moeed-Mac-mini.local>
2026-06-22 19:17:07 +00:00
Darren2030 c4cac33af6 fix(openrouter): expand short canonical model IDs to upstream API slugs (fixes #95198) (#95268)
- Add OPENROUTER_SHORT_TO_API_MODEL_ID map for short model refs like
  openrouter/deepseek-v4-flash that OpenClaw surfaces but OpenRouter API
  expects as deepseek/deepseek-v4-flash.
- In normalizeOpenRouterApiModelId, expand short refs before falling back
  to the existing namespaced strip logic.
- Add unit tests covering short refs, long refs, native routes, and
  pass-through cases.
- Add standalone reproduction script that verifies all normalization cases.
2026-06-22 19:15:25 +00:00
Masato Hoshino 965d1fff3f fix(providers): strip cache-boundary marker from non-Anthropic prompts (#89716) 2026-06-22 19:14:31 +00:00
snowzlmbot 23f94bfa78 fix(reply): normalize persisted model overrides before reset (#94752)
Co-authored-by: snowzlm <snowzlm@noreply.codeberg.org>
2026-06-22 19:14:25 +00:00
Yzx a0ed4273ee fix(agents): resolve bound route agent for inbound sessions (#95118) 2026-06-22 19:14:17 +00:00
areslp bfbf25e234 fix(feishu): show voice message duration via upload duration (#89172)
Voice/audio messages sent to Feishu (opus) play fine but show no duration
on the bubble. Feishu derives the voice-bubble duration from the `duration`
parameter of the file upload API (`im/v1/files`); the audio message content
only carries `{file_key}` and has no duration field, so the duration was
never set.

`sendMediaFeishu` now probes the outgoing audio with `ffprobe` and passes the
result as the upload `duration` (ms). It probes the buffer that is actually
sent (after the existing voice transcode, which caps length via
`MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS`), so the reported length matches what
is played. Probing is best-effort: on failure it logs and omits the duration,
and the message still sends. The audio message content is unchanged.

Fixes #53798

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 19:13:14 +00:00
Gavin Lee 8c366bfefd test(cli): add banner emission reset helper (#87121) 2026-06-22 19:12:07 +00:00
Vincent Koc b4bc1f20c9 fix(agents): repair OpenAI responses replay pairing 2026-06-23 03:11:33 +08:00
Vincent Koc c782fa98aa refactor(delivery): share recovery primitives 2026-06-23 03:10:30 +08:00
ly-wang19 81e1ec467c fix(imessage): strip leading echo corruption markers in the persisted echo cache (#94442)
The persisted iMessage echo-dedupe cache normalized text with CRLF->LF + trim only, not the leading attributedBody corruption-marker stripping the in-memory echo cache applies (#93511). The persisted 12h cache is the only matcher once the 4s in-memory text TTL expires, so a delayed reflected own-message echo whose text decoded with a leading NUL/replacement/BOM marker did not match the clean stored send -- the agent's own message was re-ingested as fresh inbound, causing a self-reply loop.

Extract the marker-stripping into a leaf module shared by both echo caches (the in-memory cache already imports the persisted one, so importing back would be a cycle) and apply it in the persisted normalizeText, so both caches strip identically.

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 19:07:45 +00:00
snowzlm 10113b2c9f fix(daemon): keep systemd gateway running after child OOM (#93585)
Co-authored-by: snowzlm <snowzlm@noreply.codeberg.org>
2026-06-22 18:54:21 +00:00
jase-283 f8df80646b chore: sync yuanbao plugin catalog to 2.15.0 (#94470) 2026-06-22 18:50:07 +00:00
Vincent Koc 541f7ffc65 fix(doctor): handle unknown tool profiles in preview warnings 2026-06-22 20:41:02 +02:00
Vincent Koc 43f134ff55 refactor(security): share tool policy layering 2026-06-23 02:40:29 +08:00
Ayaan Zaidi 780f83bcfb test(agents): distill media lifecycle fixture 2026-06-23 00:09:20 +05:30
Peter Steinberger 37714f185f fix(media): pin canonical requester route 2026-06-23 00:09:20 +05:30
Peter Steinberger 9d1ba36f6b test(media): allow partial session fixtures 2026-06-23 00:09:20 +05:30
Peter Steinberger 908a71ab57 fix(media): reject account-only route conflicts 2026-06-23 00:09:20 +05:30
Peter Steinberger 253180a265 fix(media): keep pinned routes account-bound 2026-06-23 00:09:20 +05:30
Peter Steinberger 3dce88e2b3 test(media): update requester route mocks 2026-06-23 00:09:20 +05:30
Peter Steinberger 025db6cf9e fix(agents): pin media requester route at task start 2026-06-23 00:09:20 +05:30
Peter Steinberger 1ed8592467 fix(agents): keep fallback routes account-bound 2026-06-23 00:09:20 +05:30
Peter Steinberger dc9ad35bda test(agents): prove requester account fallback 2026-06-23 00:09:20 +05:30
wanglu241 d6d7a4c4b8 test(announce-delivery): satisfy curly rule for cross-channel guard test
oxlint(curly) rejected the bare `if (!params) continue;` continue inside
the regression test added for #86034. Wrap the body in braces. No logic
change.
2026-06-23 00:09:20 +05:30
wanglu241 4e24dcf396 test(announce-delivery): cross-channel lastTo must not leak into telegram delivery (#86034)
Locks the mergeDeliveryContext channelsConflict guard so a stale lastChannel that differs from the completion origin's channel cannot import its lastTo. Addresses ClawSweeper's contract question on PR #89949.

node_modules not available in this worktree; vitest was not run locally. CI is the gate.
2026-06-23 00:09:20 +05:30
wanglu241 ab3d2b44ac test(announce-delivery): clean up temp session store on assertion failure 2026-06-23 00:09:20 +05:30
wanglu241 e5f3df6538 fix(announce-delivery): backfill effectiveDirectOrigin.to from requester session entry
When a media-generation task is created off the direct-reply path (heartbeat,
cron, subagent spawn), `agentTo` is undefined and the persisted
`requesterOrigin` lacks `to`. Every downstream `Boolean(channel && to)` gate
then short-circuits, so the generated artifact is never delivered even though
the artifact exists on disk and `task_runs.status` is later marked failed with
`completion delivery failed after successful generation`.

The requester session entry already carries `lastTo`/`lastChannel`/
`lastAccountId` and is loaded in the same function further down. Merge that
context back into `effectiveDirectOrigin` before the deliverability decision,
as the existing comment at the same site already promises.

Fixes #86034 (Hypothesis A). Hypothesis B (wake-false skips direct fallback)
remains a separate follow-up - see issue thread for details.
2026-06-23 00:09:20 +05:30
Vincent Koc 5d48a2ec54 refactor(auth): dedupe blocked profile stats construction 2026-06-23 02:34:24 +08:00
Vincent Koc b49395ddb1 refactor(gateway): dedupe MCP loopback auth gate 2026-06-23 02:29:48 +08:00
ruomuxydt 105a30b5a5 fix(config): fail closed when configure runs without an interactive TTY (#93953) (#94238)
Both `openclaw configure` and the no-subcommand `openclaw config` route through `configureCommandFromSectionsArg`, so a single guard there fail-closes both entry points when stdin/stdout are not TTYs instead of partially entering the wizard and exiting dirty (exit 13) on a piped stdin.

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-22 18:28:55 +00:00
Zechen Wang 4d636335db fix(google): add gemini-3.5-flash model catalog entry (#94726)
* fix(google): add gemini-3.5-flash model catalog entry

gemini-3.5-flash was missing from the bundled Google model catalog,
causing it to silently fall back to DEFAULT_CONTEXT_TOKENS (200k)
instead of its documented 1,048,576-token input window.

Add the catalog entry and forward-compat routing so the model
resolves with the correct context window.

Closes: openclaw/openclaw#94723
Co-Authored-By: Claude <noreply@anthropic.com>

* chore: retry CI (flaky test)

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-22 18:28:01 +00:00
ml12580 1585ec54f1 perf(plugins): cache existence probes within bundle manifest scan [AI-assisted] (#93919)
* perf(plugins): cache existence probes within bundle manifest scan

Bundle plugin discovery re-probes the same marker paths (skills/, commands/,
agents/, .mcp.json, .lsp.json, settings.json, hooks/hooks.json) once in
detectBundleManifestFormat and again in loadBundleManifest's capability
builders. Across the bundled plugin tree this is thousands of redundant
synchronous fs.existsSync calls; #76209 reports 25.4s of self-time on a
Windows cold start.

Add a scan-scoped existence cache (plugin-scan-existence-cache.ts) entered
only around discoverBundleInRoot. pluginScanExistsSync memoizes inside the
active scan and falls back to plain fs.existsSync outside it, so install,
hooks, and doctor flows stay uncached. The cache is push/pop per
discoverBundleInRoot call (try/finally), so a later install/repair pass
re-reads the filesystem — no process-global staleness.

Measured on Windows over a 25-plugin fixture: 550 -> 325 fs.existsSync
calls (41% fewer), 294.75ms -> 208.49ms. Discovery results unchanged.

Closes #76209

* fix(plugins): drop unused test reset helper and satisfy oxlint

Remove __resetPluginScanExistenceCacheForTest: the scan cache is push/pop
balanced by try/finally in withPluginScanExistenceCache, so the stack never
leaks between tests and the helper was dead code. It also tripped oxlint
no-underscore-dangle. Refactor the integration test to count existsSync calls
via a const-returning helper so there is no useless assignment.
2026-06-22 18:27:36 +00:00
Yuval Dinodia f257c0609d fix(sessions): keep bound channel identity across non-delivery turns (#95467)
* fix(sessions): keep bound channel identity across non-delivery turns

mergeOrigin reset channel-keyed origin fields (nativeChannelId,
nativeDirectUserId, accountId, threadId) whenever the new turn's
provider/surface/account differed, intended for a real Slack -> Telegram
switch. A non-delivery turn (gateway webchat send, heartbeat/cron/webhook
tick) derives origin.provider as the internal channel, so it was treated
as a channel switch and wiped the session's live channel/thread identity
even though the session never left that channel.

Gate the reset on the new turn being a real, deliverable channel so
internal non-delivery turns preserve the bound channel identity while a
genuine cross-channel switch still resets it.

* fix(sessions): also exclude system-event providers from the channel-switch reset

cron-event and exec-event turns (and heartbeat) carry no channel of their
own. They can reach mergeOrigin through the non-skip callers
(recordSessionMetaFromInbound / updateLastRoute) that derive an origin
without skipSystemEventOrigin, so the channel-switch reset would wipe a
bound session's native channel/thread identity. Add isSystemEventProvider
to the non-deliverable gate (reusing it to de-dupe the same check already
inlined in deriveSessionOrigin).
2026-06-22 18:27:23 +00:00
ly-wang19 d63389ccf6 fix(qqbot): recognize GFM table separators with one or two dashes (#95637)
`isTableSeparatorLine` required 3+ dashes per cell (`/^:?-{3,}:?$/`), but a
GFM delimiter cell needs only one or more dashes. So a valid table whose
separator used 1 or 2 dashes (e.g. `|--|--|`) was not recognized: the header
stayed pending and was silently overwritten by each following row, so the
table's header, separator, and every row but the last vanished from the sent
message.

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

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 18:27:01 +00:00
Vincent Koc 420a0e6fce fix(doctor): ignore unknown profile preview grants 2026-06-23 02:24:29 +08:00
Vincent Koc 96c6f8022c fix(auto-reply): suppress quoted silent replies 2026-06-23 02:24:29 +08:00
Peter Steinberger 03ba09bfa8 fix(doctor): accept missing profile policies 2026-06-22 14:20:09 -04:00