Skip to content

feat(selfhost): support per-repo model overrides for ollama/openai/anthropic providers - #3965

Merged
JSONbored merged 1 commit into
mainfrom
feat/per-repo-model-override-all-providers
Jul 7, 2026
Merged

feat(selfhost): support per-repo model overrides for ollama/openai/anthropic providers#3965
JSONbored merged 1 commit into
mainfrom
feat/per-repo-model-override-all-providers

Conversation

@JSONbored

Copy link
Copy Markdown
Owner

Summary

  • The per-repo reviewer model override (review.ai_model in .gittensory.yml) was wired end-to-end only for the two CLI-subscription providers (claude-code/codex). createOpenAiCompatibleAi (ollama/openai/openai-compatible) and createAnthropicAi bound their model ONCE at buildProvider() construction time from a global env var, with no per-call override parameter at all.
  • Concretely: an operator running Ollama (or a BYOK OpenAI-compatible/Anthropic HTTP provider) across multiple repos had no way to set a stronger/cheaper model per repo the way claude-code/codex operators already could — a review.ai_model.ollama_model (etc.) config entry was silently ignored, with no warning, whenever the active provider wasn't claude-code/codex.
  • Extended SelfHostAiModelConfig (packages/gittensory-engine/src/focus-manifest.ts — this type was extracted into the shared engine package; the miner package doesn't consume it, so this is gittensory-review-only) and AiRunOptions (src/selfhost/ai.ts) with ollamaModel/openaiModel/openaiCompatibleModel/anthropicModel, threaded through the full chain: focus-manifest parser → processors.tsGittensoryAiReviewInputAiRunCorrelationrunWorkersOpinion's ai.run() call → read per-call inside createOpenAiCompatibleAi/createAnthropicAi's own .run() — mirroring exactly how claudeModel/codexModel already work, at the same repo-override > global-env-var > hardcoded-default priority.
  • Also extended the AI-review cache fingerprint (src/review/ai-review-cache-input.ts, version bumped v3→v4 following the file's own established precedent for adding a hashed field) so changing one of these new per-repo overrides correctly invalidates a previously-cached review instead of replaying a decision made under a different model.
  • Scoped effort out: the CLI providers' claudeEffort/codexEffort have no equivalent for these HTTP-API providers (no existing effort-shaping mechanism to override — inventing one is a separate, larger feature).
  • Left config/examples/gittensory.full.yml's commented ai_model: example block un-updated: that file sits at 65,478/65,536 bytes against MAX_FOCUS_MANIFEST_BYTES, ~58 bytes of margin — nowhere near enough room for 4 new documented keys without trimming unrelated comment text elsewhere in a 65KB shared file. Noting this explicitly rather than silently leaving the example incomplete (a known, pre-existing byte-budget fragility, also flagged in feat(regate-sweep): add opt-in oldest-first ordering mode to selectRegateCandidates #3867 earlier).

Found via a fresh performance/scalability/accuracy hardening audit of the self-host ORB stack. Tracked under #1667.

Scope

  • packages/gittensory-engine/src/focus-manifest.ts — type, empty-config, parser, presence-check, serialization
  • src/selfhost/ai.tsAiRunOptions, createOpenAiCompatibleAi (+ new providerName field), createAnthropicAi, buildProvider
  • src/services/ai-review.tsGittensoryAiReviewInput, AiRunCorrelation, construction + spread sites
  • src/queue/processors.ts — forward the 4 new fields from the resolved manifest
  • src/review/ai-review-cache-input.ts — fingerprint fields + version bump v3→v4
  • Tests: focus-manifest.test.ts (parser, all 8 knobs + each new one individually with round-trip), selfhost-ai.test.ts (per-provider override priority + buildProvider end-to-end wiring), ai-review-cache-input.test.ts (fingerprint changes per new field); fixed 2 pre-existing test files whose fixtures/assertions needed updating for the stricter type / bumped cache version

Validation

  • npm run typecheck
  • npm run test:coverage (full unsharded) — 561 files / 11120 tests passed; changed lines in every touched src/** file fully covered per lcov.info (cross-checked against diff hunks — zero overlap with pre-existing uncovered lines)
  • git diff --check clean

Safety

  • Absent/null override fields (the default — no .gittensory.yml ai_model.* set) are byte-identical to today: same global-env-var-then-hardcoded-default resolution as before this existed. No secrets; no new credential paths (only the model NAME can be redirected, never the API key/base URL, matching the existing claude/codex override's own scope).

Closes #3902

…thropic providers

review.ai_model's per-repo reviewer model override only worked for the
claude-code/codex CLI subscription providers. createOpenAiCompatibleAi
and createAnthropicAi bound their model ONCE at buildProvider()
construction time from a global env var, with no per-call override
parameter at all -- so an operator running ollama/openai/openai-
compatible/anthropic across multiple repos had no way to set a
stronger/cheaper model per repo the way claude-code/codex operators
already could; the config field was silently ignored.

Extend SelfHostAiModelConfig (packages/gittensory-engine) and
AiRunOptions with ollamaModel/openaiModel/openaiCompatibleModel/
anthropicModel, thread them through the full chain (focus-manifest
parser -> processors.ts -> GittensoryAiReviewInput -> AiRunCorrelation
-> runWorkersOpinion's ai.run() call), and read them per-call inside
createOpenAiCompatibleAi/createAnthropicAi's own run() -- mirroring
exactly how claudeModel/codexModel already work, at the same repo-
override > global-env-var > hardcoded-default priority. Also extends
the AI-review cache fingerprint (bumped v3->v4) so changing one of
these repo overrides correctly invalidates a previously-cached review.

Closes #3902
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
gittensory-ui 1e2f0b8 Commit Preview URL

Branch Preview URL
Jul 07 2026, 08:02 AM

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 7, 2026
@loopover-orb

loopover-orb Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-07 08:06:06 UTC

10 files · 1 AI reviewer · no blockers · readiness 100/100 · CI pending · blocked

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review: This PR changes guardrail-protected path(s): src/selfhost/ai.ts (matched src/selfhost/**).

Review summary
This PR extends the existing per-repo `review.ai_model` override mechanism (already working for claude-code/codex) to the HTTP-API self-host providers (ollama/openai/openai-compatible/anthropic), threading the four new fields through focus-manifest parsing, `GittensoryAiReviewInput`/`AiRunCorrelation`, `runWorkersOpinion`, and into `createOpenAiCompatibleAi`/`createAnthropicAi`'s per-call model resolution, with a matching v3→v4 cache-fingerprint bump so a changed override invalidates stale cached reviews. The `resolveOpenAiCompatibleRepoOverride` dispatch correctly maps `providerName` to its own override key with no cross-variant leakage (verified by the added test), and the priority order (repo override > construction-time/env model > hardcoded default) mirrors the established claude/codex pattern exactly. Test coverage is thorough across all four new fields at the unit, buildProvider-wiring, cache-fingerprint, and focus-manifest-parse levels.

Nits — 7 non-blocking
  • src/selfhost/ai.ts: `resolveOpenAiCompatibleRepoOverride`'s final `else return options.openaiCompatibleModel` implicitly treats any non-ollama/non-openai providerName as openai-compatible — currently safe because the `providerName` param type is a closed union, but worth a comment noting the assumption if that union ever grows.
  • src/services/ai-review.ts:286 and similar: the `feat(selfhost): support per-repo model overrides for ollama/openai/anthropic providers #3902` issue-number references in comments are fine as historical breadcrumbs but add no runtime value — not an issue, just flagging per the external brief's magic-number note as a non-concern.
  • Effort-shaping (`claudeEffort`/`codexEffort` equivalent) is explicitly scoped out for the HTTP-API providers with a documented rationale — reasonable, but worth confirming operators are told (e.g. in README/config docs) that effort override isn't available for ollama/openai/anthropic to avoid a support question.
  • Consider a small lookup object (`{ollama: 'ollamaModel', openai: 'openaiModel', 'openai-compatible': 'openaiCompatibleModel'}`) in `resolveOpenAiCompatibleRepoOverride` instead of the if/else chain for readability parity with similar maps elsewhere in ai.ts.
  • The `.gittensory.yml` example/docs (if any exist alongside `review.ai_model.claude_model` etc.) should be updated to list the four new `ollama_model`/`openai_model`/`openai_compatible_model`/`anthropic_model` keys so operators discover them.
  • PR author also opened the linked issue — Link an issue that was opened by a different contributor, or provide a rationale for why this self-authored issue represents genuine discovery work.
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ Linked #3902
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 51 registered-repo PR(s), 43 merged, 343 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 51 PR(s), 343 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 51 PR(s), 343 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.18519% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.67%. Comparing base (b8a1186) to head (1e2f0b8).
⚠️ Report is 16 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/services/ai-review.ts 50.00% 0 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3965      +/-   ##
==========================================
- Coverage   93.68%   93.67%   -0.01%     
==========================================
  Files         373      373              
  Lines       34895    34919      +24     
  Branches    12768    12791      +23     
==========================================
+ Hits        32692    32712      +20     
  Misses       1584     1584              
- Partials      619      623       +4     
Files with missing lines Coverage Δ
packages/gittensory-engine/src/focus-manifest.ts 100.00% <100.00%> (ø)
src/queue/processors.ts 94.55% <100.00%> (+<0.01%) ⬆️
src/review/ai-review-cache-input.ts 100.00% <100.00%> (ø)
src/selfhost/ai.ts 98.61% <100.00%> (+0.01%) ⬆️
src/services/ai-review.ts 96.42% <50.00%> (-0.65%) ⬇️
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored
JSONbored merged commit 583e7b2 into main Jul 7, 2026
12 of 13 checks passed
@JSONbored
JSONbored deleted the feat/per-repo-model-override-all-providers branch July 7, 2026 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Development

Successfully merging this pull request may close these issues.

feat(selfhost): support per-repo model overrides for ollama/openai/anthropic providers

1 participant