fix(agent): record ended_early when a clean exit leaves the skeleton behind - #668
Open
yzxcj797 wants to merge 2 commits into
Open
fix(agent): record ended_early when a clean exit leaves the skeleton behind#668yzxcj797 wants to merge 2 commits into
yzxcj797 wants to merge 2 commits into
Conversation
OpenRouter's platform-side 429s (free-models-per-min) carry no Retry-After, which the LangChain AsyncCaller classifies as non-retryable capacity and turns into an immediate abort, so OPENWIKI_PROVIDER_RETRY_ATTEMPTS never applied and ~50s of agent work was discarded on the first 429 (langchain-ai#664). langchain-ai#461's createProviderRetryFetch only reaches ChatOpenAI-backed transports -- ChatOpenRouter has no configuration option -- and its flat 1s fallback cannot ride out a per-minute window anyway. Retry in installOpenRouterDebugFetch, which already wraps every OpenRouter chat-completions fetch: - honour Retry-After (seconds or HTTP-date), then OpenRouter's X-RateLimit-Reset epoch (unix-ms, seconds-magnitude detection, small margin), then exponential backoff (1s doubling, 30s cap); header- derived waits are defensively capped at 5 min; - spend the existing OPENWIKI_PROVIDER_RETRY_ATTEMPTS budget; - only retry when the request is re-sendable (string/absent body, not a Request carrying a body) and propagate abort signals through the wait; - keep the diagnostics contract: the final non-ok response is captured for attachOpenRouterDebugInfo, retries emit debug lines.
…behind .last-update.json recorded status=complete whenever the agent's final turn ended without an error, including runs that ended on a plan or a question with most of the wiki unwritten. Consumers keying on the status (resume logic, CI docs jobs, batch scripts, the update no-op check) treated those as finished wikis and skipped them (langchain-ai#653). Gate complete on the one verifiable state the run controls: the agent is instructed to delete _skeleton.md once every wiki file is written, so a leftover skeleton on a clean exit now records ended_early (new UpdateRunStatus value; interrupted keeps its stream/owner-failure meaning). The no-op check never skips after ended_early, old metadata without a status field still reads as complete, and the gate emits a visible warning naming the leftover file.
|
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.
Summary
Fixes #653.
.last-update.jsonrecordedstatus: "complete"whenever the agent's final turn ended without an error — including runs that ended on a plan, a "would you like me to continue?", or an announced-but-not-performed cleanup. Anything keying on the status (resume logic, CI docs jobs, batch scripts, the--updateno-op check) then treated a mostly-unwritten wiki as finished and skipped it.What this does
Gates
completeon the one piece of verifiable state the run controls. The agent is instructed to delete_skeleton.mdonce every wiki file has been written, so on a clean exit a leftover skeleton means the run ended before finishing:UpdateRunStatusvalue"ended_early"(distinct frominterrupted, which keeps its stream/owner-failure meaning).hasLeftoverSkeletonFile(cwd, outputMode)and recordsended_earlyinstead ofcompletewhen it's present — catching the "announced deleting_skeleton.mdwithout doing it" case regardless of what the final message claimed.getUpdateNoopStatustreatsended_earlylikeinterrupted: never skip, with its own reason ("previous run ended before finishing the wiki").readLastUpdatepreserves the new value; metadata written before the status field existed still reads ascomplete, so upgrades don't force spurious re-runs.Tests
test/agent/skeleton-status.test.ts: skeleton detection in both output modes (repositoryopenwiki/_skeleton.md,local-wikiroot), negative case, and a metadata write/read round-trip forended_early.test/agent/update-noop.test.ts: the no-op check does not skip after anended_earlyrun.