Repository navigation
Fix #2494: [Bug] DSH adapter: a transient gateway 502 on the host-LLM path is never retried - #2496
Open
Memtensor-AI wants to merge 3 commits into
Open
Memtensor-AI wants to merge 3 commits into
Memtensor-AI wants to merge 3 commits into
Conversation
…2494) complete() dispatched a single prepared.stream() call with no retry, so a transient 5xx from the gateway in front of the host Messages API failed the auxiliary call outright. Recall filtering and capture summarization then degraded silently (safeCutoff / heuristic) — 25 of 96 host calls failed on the reporter's installation. Add a bounded retry in the bridge: at most 3 attempts, 250ms x attempt backoff, bounded by the existing per-call deadline. Retry only LLM_UNAVAILABLE with no status or status >= 500; never retry 401/402/403, rate limits, timeouts, malformed output, or deadline/caller aborts. Each attempt re-prepares via the cached capability path because a prepared DSH call is single-use. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ensor#2494) A provider `aborted` finish maps to LLM_UNAVAILABLE with no status, which the status gate would treat as a retryable transport failure. A cancellation is not transient, so exclude dshCode "ABORTED" explicitly and cover it with a regression test. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 of 5 tasks
Collaborator
Author
🤖 Open Code ReviewTarget: PR #2496 ✅ OpenCodeReview: Review complete: 0 finding(s) across 1 selected item(s). Generated by cloud-assistant via Open Code Review. |
Collaborator
Author
🔧 Open Code Review requested Agent fixOpen Code Review found 2 issue(s). I have resumed the development Agent to fix them.
The Agent will push a new commit to this PR branch. OCR will recheck after the commit is pushed. |
Replace the adapter-local waitForRetryBackoff with the shared core/util/retry-after.js waitForRetry so the abort-listener contract has a single implementation, and fail fast when HOST_LLM_MAX_ATTEMPTS is misconfigured to a non-positive value instead of throwing `undefined`. Refs MemTensor#2494
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixed the DSH host-LLM adapter so a transient gateway 5xx is retried instead of silently degrading the auxiliary stage (issue #2494).
Root cause:
createDeepSeekHarnessHostLlmBridge().complete()inapps/memos-local-plugin/adapters/deepseek-harness/host-llm.tsdispatched oneprepared.stream()call and never retried. A transient 502 from the gateway in front of the host Messages API surfaced as a terminalfinish→MemosError(LLM_UNAVAILABLE, status:502), which propagated straight out. The two host-LLM stages (retrieval.retrieval.filter.v5,capture.summarize) then degraded silently — recall filtering fell back tosafeCutoffand capture summarization to the heuristic — matching the reporter's 25/96 failed calls.config.maxRetriesnever applied because it is consumed by the direct-provider fetcher, not the host-bridge path.Fix: dispatch now runs through a bounded retry loop (
completeAuxiliaryWithRetry): at most 3 attempts,250 ms × attemptbackoff, bounded by the existing per-calldeadline(). The classifier (isRetryableAuxiliaryError) retries onlyLLM_UNAVAILABLEwith no status (transport failure) or status ≥ 500, and never401/402/403, provider aborts (dshCode "ABORTED"),LLM_RATE_LIMITED,LLM_TIMEOUT, malformed output, or deadline/caller aborts. Because a prepared DSH call is single-use, each attempt re-prepares viaprepareAuxiliaryCall; the model-capability lookup is cached per route, so re-preparation is a cache hit and adds no round trip. Success-path behavior and the returnedHostLlmCompletionshape are unchanged.Tests/verification: added 13 regression tests to
tests/unit/adapters/deepseek-harness-host-llm.test.tscovering the acceptance matrix ([502,502,ok]→3 ok; [502,ok]→2 ok; [502,502,502]→3 thrown; [ok]→1; [401/402/403]→1 thrown; statusless transport→2 ok; provider abort→1 thrown; RATE_LIMIT→1 thrown; malformed→1 thrown; deadline abort→1 thrown; caller abort during backoff→1).npx tsc -p tsconfig.json --noEmitis clean andnpx vitest run tests/unit/adapters/deepseek-harness-host-llm.test.ts tests/unit/llmreports 121/121 passing. Broader suites that fail (better_sqlite3.nodemissing native binding) were confirmed pre-existing on a clean stash and are unrelated. An independent code review flagged the provider-abort retry gap, which is fixed and covered.Deliverables: 2 commits on
bugfix/autodev-2494-20261014045802002(892ab4c initial fix, 7bcf73a abort exclusion), pushed to origin. opsp artifacts written under.ai-tasks/andopenspec/changes/2026-10-14-2494-.../(proposal/spec/design/verification-report) and archived to thememos-autodev-specsrepo (commit 682db96). No PR created — left to the scheduler.Related Issue (Required): Fixes #2494
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Not run; documentation-only change.
Checklist
@whipser030, @hijzy please review this PR.
Reviewer Checklist