Commit Graph

66940 Commits

Author SHA1 Message Date
zhang-guiping
bbf494955d fix(outbound): preserve configured directory entries before reserved-literal rejection in resolveMessagingTarget
Move the reserved-literal check from before directory lookup to after directory
miss, so configured Telegram groups/channels whose directory key is a reserved
word (current, self, this, me) still resolve through the directory before
failing closed. The reserved check now runs only after the directory returns no
match and before plugin fallback resolution.

Update the regression test to verify directory-first ordering: a configured
directory entry named current resolves successfully, and a directory miss with
a reserved literal fails with the descriptive error.
2026-06-25 08:37:00 -07:00
zhang-guiping
f12ade0082 fix(outbound): skip sync reserved-literal rejection for heartbeat mode
The sync reserved-literal check in resolveOutboundTargetWithPlugin was
suppressing heartbeat routes to directory entries whose names match
reserved literals (e.g., a Telegram group named "current"). Skip the
check for heartbeat mode so the async resolveChannelTarget →
resolveMessagingTarget path can do directory-first lookup before
deciding.
2026-06-25 08:37:00 -07:00
张贵萍
56baf9d079 fix(outbound): reject reserved Telegram targets 2026-06-25 08:37:00 -07:00
Ayaan Zaidi
dc12b998da fix(media): scope UUID filename restore to media store 2026-06-25 08:35:41 -07:00
Narahari Raghava
cf512f639b fix(media): strip internal UUID suffix from outbound media filenames
Closes #96538
2026-06-25 08:35:41 -07:00
Ayaan Zaidi
29670c13f6 refactor(status): reuse runtime authority decision 2026-06-25 08:31:54 -07:00
zhang-guiping
bead84f0ee fix(status): route usage to session-selected model 2026-06-25 08:31:54 -07:00
Vincent Koc
497d53d821 fix(sdk): tighten wildcard surface budget 2026-06-25 23:30:17 +08:00
yetval
446d98d601 fix(trajectory): export legacy v1 sessions without entry timestamps
readSessionBranch filtered out every entry lacking a string or number
timestamp. Sessions written before entry timestamps existed (version 1)
have ids and parentIds synthesized by the legacy migration but no entry
timestamp, so all entries were dropped and the exported bundle reported
transcriptEventCount 0. The transcript event builder already defaults a
missing timestamp via normalizeTimestamp, so the filter clause was both
wrong and redundant. Drop it; entry identity plus the canonical-entry
check is what the branch walk needs.
2026-06-25 08:29:25 -07:00
Gio Della-Libera
82a6a57330 Doctor: expose session artifact findings (#95976)
* feat(doctor): expose session artifact findings

* fix(doctor): make session artifact findings advisory
2026-06-25 08:27:25 -07:00
Ayaan Zaidi
01ce03c5b1 fix(gateway): preserve webchat send guard 2026-06-25 08:26:12 -07:00
黑承亮0668000844
5881dc8ac3 fix(gateway): use normalizeMessageChannel for send validation to support plugin channels
Fixes #92094
2026-06-25 08:26:12 -07:00
openclaw-clownfish[bot]
31a0f97dd9 fix(clownfish): repair validation for repair-94016-live-pr-inventory-20260617t082059-003-20260617a (2) 2026-06-25 08:25:09 -07:00
openclaw-clownfish[bot]
ace22feb3f fix(clownfish): address review for repair-94016-live-pr-inventory-20260617t082059-003-20260617a (1) 2026-06-25 08:25:09 -07:00
openclaw-clownfish[bot]
ecd29fe572 fix(gateway): resume channel after pending task recovery 2026-06-25 08:25:09 -07:00
openclaw-clownfish[bot]
6039da3ed6 fix(gateway): resume channel after pending task recovery 2026-06-25 08:25:09 -07:00
sheyanmin
8b4be2fdd4 fix: recover channel after stop timeout in health monitor
When a channel stop times out (e.g. during a Telegram API outage),
the channel enters recoveryStopTimedOut state. The health monitor's
subsequent start call would set restartPending and return without
actually starting the channel.

If the stuck stop never completes, the channel stays in limbo forever
with the health monitor retrying every cycle but never recovering.

Fix: when the health monitor retries recovery (recoveryStartRequested
already set), clean up the stuck task state and allow the channel to
start normally.

Closes #94008
2026-06-25 08:25:09 -07:00
Ayaan Zaidi
210ea659f7 fix(outbound): prevent partial-send recovery replay 2026-06-25 08:16:56 -07:00
rosenlo
c0a61f5351 test(outbound): add drain no-replay guard for unknown_after_send; clarify fallback intent
- Add integration test: after mid-batch failure with send evidence the
  resulting unknown_after_send entry is NOT replayed by reconnect drain
  when no adapter reconciliation is available ('refusing blind replay').
  Pins the drain contract so any regression that re-enables blind replay
  is caught end-to-end against a real SQLite queue.
- Add comment in deliver.ts fallback branch: failDelivery inside the
  markQueuedPlatformOutcomeUnknown catch is a last-resort DB-write-error
  path, not an indication that failDelivery is correct with send evidence.
2026-06-25 08:16:56 -07:00
rosenlo
7f2c04ce11 fix(test): remove unused import and unnecessary type assertions in queue integration test 2026-06-25 08:16:56 -07:00
rosenlo
f9e0dce731 test(outbound): add real-queue integration test for unknown_after_send on mid-batch failure
Complement the unit test (which mocks delivery-queue) with an integration
test that uses the real SQLite delivery queue (no mock of ./delivery-queue.js)
and the real deliverOutboundPayloads code path.

Verifies at the queue layer:
- mid-batch failure with send evidence (first payload succeeds, second
  throws, queuePolicy=required) -> queue entry recovery_state advances to
  unknown_after_send, retryCount stays 0, no lastError. This is the patch
  path: drain will route the entry through reconcileUnknownQueuedDelivery
  instead of leaving it in send_attempt_started for blind replay.
- no send evidence (sole payload fails immediately) -> failDelivery path:
  retryCount bumped, recovery_state stays send_attempt_started. Patch does
  not affect this path.

Negative control confirmed: with deliver.ts reverted to v2026.6.8 original
(no patch), the mid-batch test fails with recovery_state=send_attempt_started
(the root-cause state), while the no-evidence test still passes. This
reproduces the patch's code path and proves the fix at the real-queue layer.
2026-06-25 08:16:56 -07:00
rosenlo
71422a9a5a fix(outbound): advance queue entry to unknown_after_send on mid-batch failure with send evidence
When a required-mode batch send fails mid-batch after an earlier payload
already succeeded, the wrapper catch in deliverOutboundPayloadsWithQueueCleanup
called failDelivery. failDelivery only bumps retryCount/lastError; it does
not advance recoveryState, so the entry stayed in send_attempt_started (set
earlier by markDeliveryPlatformSendAttemptStarted via onPlatformSendStart).

On the next Telegram reconnect, drainQueuedEntry sees send_attempt_started
and calls reconcileUnknownQueuedDelivery. When adapter reconciliation
misreports not_sent (the message was actually sent, per the outbound send
ok / messageId evidence), the entry is replayed and the user receives a
duplicate.

Fix: when the error carries send evidence (OutboundDeliveryError with
sentBeforeError === true and platformSendStarted === true), call
markQueuedPlatformOutcomeUnknown instead of failDelivery. This advances the
entry to unknown_after_send, which drain already routes through
reconcileUnknownQueuedDelivery, preserving the entry for adapter
reconciliation rather than leaving it in send_attempt_started for replay.

When there is no send evidence (sentBeforeError === false), failDelivery
remains correct: nothing reached the channel, so retrying is safe.

This is a third duplicate path distinct from #89812 (mirror best-effort)
and #92274 (subagent-announce-delivery retry); it is the outbound/deliver
wrapper catch, which neither prior fix covers.

Tests:
- regression: two payloads, first succeeds, second throws; asserts
  markDeliveryPlatformOutcomeUnknown called, failDelivery/ackDelivery not.
- guard: no send evidence; failDelivery still called.
2026-06-25 08:16:56 -07:00
linhongkuan
2e6e17f7c5 fix(media-generation): preserve trimmed default model flag (#96430) 2026-06-25 20:46:47 +08:00
linhongkuan
1ba1fecaa6 fix(acp-core): clear stale active run lookups (#96427) 2026-06-25 20:44:07 +08:00
Shakker
4ecb45bf77 fix: narrow test config path 2026-06-25 10:40:38 +01:00
Shakker
0757cad597 fix: narrow cron path env cleanup 2026-06-25 10:07:09 +01:00
Shakker
21b21583cc test: isolate reply media state env 2026-06-25 10:02:41 +01:00
Shakker
c8c4490b17 fix: scope embedded image state env 2026-06-25 09:59:32 +01:00
Shakker
d693b70bfc test: preserve daemon coverage env scope 2026-06-25 09:56:16 +01:00
Shakker
2b8c089b76 fix: guard current turn state env 2026-06-25 09:53:17 +01:00
Shakker
1d1c2f4f72 test: stabilize allowlist config env 2026-06-25 09:50:50 +01:00
Shakker
3ce398712a fix: preserve exec env test cleanup 2026-06-25 09:48:15 +01:00
Shakker
3c2a3d9d2b test: centralize tool manager agent env 2026-06-25 09:45:37 +01:00
Shakker
33d7a2a3f7 fix: route session history config env 2026-06-25 09:42:46 +01:00
Vincent Koc
94ae918d8f perf(plugins): reuse installed manifest realpaths (#96710)
Co-authored-by: sheyanmin <she.yanmin@xydigit.com>
2026-06-25 16:41:26 +08:00
David
af906225fa fix(git-hooks): skip sequencer pre-commit formatting (#95842)
* fix(git-hooks): skip sequencer pre-commit formatting

* chore: rerun CI

* fix(git-hooks): skip revert sequencer formatting

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-25 16:40:12 +08:00
Shakker
08b7fddf80 test: centralize shell snapshot env 2026-06-25 09:37:55 +01:00
Wynne668
d7dff3cbf4 fix(document-extract): render PDF image fallback per page so multi-page scans don't starve later pages (#96390)
* fix(document-extract): render PDF image fallback per page so multi-page scans don't starve later pages

clawpdf's mode:"images" extract applies a single maxPixels budget across
every page, so the first page consumes it and later pages collapse to ~1x1
PNGs that vision OCR models reject. Render each selected page in its own
extract() call so the pixel budget resets per page and every page yields a
usable image.

* fix(document-extract): preserve aggregate PDF render budget

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-06-25 16:37:47 +08:00
Vincent Koc
42d0a1267e perf(gateway): cache transcript field regexes (#96707)
Co-authored-by: Yongan Zhang <374456248@qq.com>
2026-06-25 16:36:44 +08:00
David
99f56cd548 fix(discord): keep audio voice replies threaded (#95978)
* fix(discord): keep audio voice replies threaded

* chore: retrigger CI after base recovery
2026-06-25 16:36:23 +08:00
Shakker
e6a2f61e94 fix: route persisted result config env 2026-06-25 09:29:46 +01:00
linhongkuan
c030b305a4 fix(agent-core): preserve empty prompt arguments (#96405) 2026-06-25 16:25:52 +08:00
ly-wang19
770b19f496 fix(imessage): only strip standalone role-turn markers, not prose ending in a role word (#96392)
ROLE_TURN_MARKER_RE anchored only the end of the line (\b...:\s*$), so any
outbound line that merely ended with 'user:'/'system:'/'assistant:' was
truncated — e.g. 'Please send this reply to the user:' lost its last word.
Anchor the marker to the whole line so only a standalone leaked turn marker
(its own line) is stripped; standalone-marker behavior is unchanged.

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-25 16:05:36 +08:00
linhongkuan
793b604b23 fix(media-understanding): parse nested Gemini output JSON (#96432) 2026-06-25 15:50:39 +08:00
linhongkuan
31e941c3fc fix(context): count fullwidth chars in token estimates (#96442) 2026-06-25 14:36:04 +08:00
Vincent Koc
56d95b18f4 fix(sdk): refresh plugin sdk api baseline 2026-06-25 06:51:02 +02:00
Vincent Koc
e7f2b125f6 fix(test): isolate upgrade survivor artifacts 2026-06-25 05:49:46 +02:00
Vincent Koc
643410c1f3 test(qa): scope fanout marker proof to channel runtime 2026-06-25 10:20:51 +08:00
Vincent Koc
8d4e40d293 test(qa): extend fanout marker wait 2026-06-25 10:20:51 +08:00
Vincent Koc
068ae4eb4b test(qa): allow Codex fanout completion window 2026-06-25 10:20:51 +08:00