Skip to content

fix(embedding): retry transient API failures (#927) - #942

Draft
YOMXXX wants to merge 5 commits into
TencentCloud:feat/server_teamfrom
YOMXXX:fix/927-l0-embedding-retry
Draft

fix(embedding): retry transient API failures (#927)#942
YOMXXX wants to merge 5 commits into
TencentCloud:feat/server_teamfrom
YOMXXX:fix/927-l0-embedding-retry

Conversation

@YOMXXX

@YOMXXX YOMXXX commented Aug 11, 2026

Copy link
Copy Markdown

Summary

Fixes #927 by enabling the existing bounded retry path for transient embedding API failures.

When the embedding provider returns a 5xx response or a request timeout occurs, the service now retries up to two times with the existing exponential backoff before failing. This reduces silent metadata-only L0 writes caused by transient embedding failures.

Root cause

OpenAIEmbeddingService had MAX_RETRIES = 0, so the retry loop executed only once even though timeout and 5xx errors were classified as retryable.

Validation

  • npm test — 5 test files, 17 tests passed for this PR scope
  • npm run build:plugin — passed
  • git diff --check — passed

Scope

This PR intentionally covers the bounded retry portion of #927. It does not change the existing response contract or add a background reconciliation workflow.

YOMXXX added 5 commits August 9, 2026 18:13
Issue TencentCloud#851: the plugin used to monkey-patch OpenClaw's compiled dist files
to inject event.messages into after_tool_call. The patch is removed in v2,
but the hook still gated L3 compression on classifyPatchEffectiveness() and
relied on the injected messages — on current OpenClaw versions (where
event.messages is absent) L3/MMD never ran.

- after_tool_call now fetches session messages through the official
  api.runtime.subagent.getSessionMessages({ sessionKey, limit }) when the
  event carries none
- removed the classifyPatchEffectiveness() patch check (the patch no longer
  exists)
- the handler takes an optional getSessionMessages callback, wired from the
  plugin api at registration

Fixes TencentCloud#851 (replaces the fragile dist-patch approach with the supported API)

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
drain() invoked entry.task() directly; when a queued task threw
synchronously the call escaped before .finally() was registered,
leaving running=true forever. The queue stayed stuck, so every later
add() hung and onIdle() never resolved — silently stalling L1/L2/L3
flushes in the pipeline.

Wrap the task call in Promise.resolve().then() so the error is caught,
bookkeeping is finalized, and the next queued task runs normally.

Fixes TencentCloud#518

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
…essionKey

OpenClaw's afterTurn/assemble path passes sessionId (or
sessionTarget.sessionKey) but not always a top-level sessionKey. The
stateManager fallback only guarded on params.sessionKey, so assemble()
returned early every turn: L1.5 never settled, MMD injection never ran,
and L2/L3 never fired (TencentCloud#878, TencentCloud#880).

Extend the fallback to sessionKey -> sessionId -> sessionTarget.sessionKey
in both assemble() and afterTurn(), mirroring the compact() fix (TencentCloud#862).

Adds a vitest suite covering: assemble resolving from sessionId only,
afterTurn resolving from sessionId only, and clean skip when no session
is resolvable.

Fixes TencentCloud#878

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
Hermes' memory_tencentdb provider stubbed on_memory_write(), so explicit
memory(action="add", ...) writes were accepted locally but never became
searchable via memory search — only conversation search surfaced them
(TencentCloud#417).

Implement the full mirror path:
- on_memory_write() calls client.write_explicit_memory() (non-add /
  empty content / gateway-down are no-ops)
- client posts to /v3/memories/explicit (v3 data plane, tenancy isolated)
- v2-router dispatches the route and handleExplicitMemoryWrite ingests
  via explicit-memory.ts -> writeMemory() with requireVectorStoreWrite
- l1-writer gains requireVectorStoreWrite: the write must reach the
  searchable VectorStore index (embedding + upsert), otherwise it is
  rejected — a JSONL-only write would never surface in recall
- target classification: user/profile -> persona, else instruction

Tests: explicit-memory.test.ts (5) + explicit-memory-route.test.ts (4)
covering classify, vector-store-required semantics, route dispatch.

Fixes TencentCloud#417

Signed-off-by: 李冠辰 <liguanchen@xiaomi.com>
@Maxwell-Code07

Copy link
Copy Markdown
Collaborator

Thank you for your attention and contribution! We will schedule an internal review of this PR, and we will share any feedback right here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] L0 embedding timeout silently degrades to metadata-only write with code:0 — MAX_RETRIES=0 leaves retry scaffold disabled

2 participants