Stop severing plugin artifact pulls at fixed timeouts - #6228
Merged
Conversation
thv ai-plugin had both ceilings that #6212 fixed for skills, for the same reason: its client is a near-copy of the skills client and its router sat among the standard routers. The client gave up after 30s and blamed server availability, when the server was healthy and mid-pull. Past that, the plugins router inherited the flat 60s cap that the workload and skills routers are both exempt from, on the grounds that artifact pulls take minutes. - classify timeouts as ErrRequestTimeout, separate from unreachability, and leave caller cancellation as neither - raise the client default and allow TOOLHIVE_API_TIMEOUT to override it - give the plugins router per-route timeouts, long ones on install, build, and push Follows #6212.
samuv
requested review from
ChrisJBurns,
JAORMX,
amirejaz,
aponcedeleonch,
jhrozek,
rdimitrov and
reyortiz3
as code owners
August 6, 2026 09:17
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #6228 +/- ##
==========================================
- Coverage 72.47% 72.47% -0.01%
==========================================
Files 739 739
Lines 76767 76790 +23
==========================================
+ Hits 55639 55650 +11
- Misses 17163 17171 +8
- Partials 3965 3969 +4 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
JAORMX
approved these changes
Aug 6, 2026
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
#6224 fixed two independent timeout ceilings for
thv skill. I noted there thatPluginsRouterlooked like it had the same problem. It has both of them, for a structural reason: the plugins client is a near-copy of the skills client, and the plugins router sat in the samestandardRoutersmap.1. The client gave up at 30s and reported the server as unreachable, when the server was healthy and pulling. Abandoning the request cancels its context server-side, so the work is discarded rather than continuing — retrying restarts from nothing.
2. The plugins router inherited the flat 60s cap.
WorkloadRouterand nowSkillsRouterare both mounted outsidestandardRoutersprecisely because artifact pulls take minutes.install,build, andpushmove OCI artifacts the same way; the router just never got the same treatment. The route docs already anticipate this — several carry504 Gateway Timeout (upstream pull timed out).Changes, mirroring #6224 exactly:
ErrRequestTimeout, distinct fromErrServerUnreachable; caller cancellation (Ctrl-C) is classified as neither and surfaces ascontext.Canceled.TOOLHIVE_API_TIMEOUTas an override. An explicitWithTimeoutstill outranks the env var; an unparsable or non-positive value is ignored with a warning rather than disabling the timeout.PluginsRoutergains per-route timeouts — long oninstall,build,push; short on the read routes — and is mounted outsidestandardRouters.formatAIPluginErrorgives the hint that matches the failure and names the override.Follows #6212 / #6224.
Type of change
Test plan
task test)task lint-fix)Same coverage as the skills PR:
TestTimeoutFromEnv(table over unset / durations / whitespace / bare number / garbage / zero / negative),TestNewDefaultClientTimeoutPrecedence, and three classification tests over real sockets — slow server yieldsErrRequestTimeoutand notErrServerUnreachable, closed port yields the reverse, cancelled caller context yields neither.Because remounting a router is the kind of change that silently breaks routing, I checked the live surface rather than trusting the diff:
/plugins/buildsresolving to the builds route and/plugins/nopeto 404 confirms the sub-route ordering survived the move.Does this introduce a user-facing change?
Yes.
thv ai-pluginoperations that pull OCI artifacts no longer fail on slow or large pulls. Timeout failures say the request timed out instead of claiming the server is unreachable, andTOOLHIVE_API_TIMEOUToverrides the client limit — the same variable that already works forthv skill.Special notes for reviewers
pkg/plugins/clientandpkg/skills/clientare now carrying a third and fourth copy of the same logic (timeoutFromEnv,classifyTransportError, the two sentinels, and the resolution ladder). I mirrored rather than extracted, because the two packages deliberately parallel each other and extracting mid-fix would have made this diff hard to review against #6224. But the duplication is real and getting harder to keep in sync —pkg/plugins/project_root.goalready re-exports fromskills, so there is precedent for consolidating. Worth a follow-up if you agree.Generated with Claude Code