Repository navigation
fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint - #3631
Conversation
…xpansion (cheaper-inference#3624) v3.8.21 broadened package.json files to include open-sse/ and src/*/* directories for TypeScript-first imports, but pack-artifact-policy.ts was not updated. Add the new directories to PACK_ARTIFACT_ROOT_ALLOWED_PATH_PREFIXES. Also increase execFileSync maxBuffer to 64 MB to fix ENOBUFS on large packs.
…ional endpoint
Kiro/CodeWhisperer access tokens and Q Developer profile ARNs are region-bound,
but the executor and usage service hardcoded codewhisperer.us-east-1.amazonaws.com.
Enterprise IAM Identity Center accounts whose profile lives in another region
(e.g. eu-central-1) always failed with 403 "User is not authorized to make this
call": a regional token is rejected by us-east-1 ("bearer token is invalid"), a
regional profileArn sent to us-east-1 fails with "Improperly formed request", and
codewhisperer.{region}.amazonaws.com does not resolve - the regional host is
q.{region}.amazonaws.com.
- open-sse/executors/kiro.ts: resolve the region from providerSpecificData.region
(or the profileArn) and POST generateAssistantResponse to the regional host.
us-east-1 keeps the legacy codewhisperer.us-east-1 host (no Builder ID regression).
- open-sse/services/usage.ts: GetUsageLimits now targets the same regional host.
- src/lib/oauth/providers/kiro.ts: the device-code login (Builder ID / IDC) now
discovers the Q Developer profileArn via ListAvailableProfiles against the
regional endpoint and stores it, since enterprise accounts require it on every call.
There was a problem hiding this comment.
Code Review
This pull request introduces region-specific routing and profile discovery for AWS Kiro/CodeWhisperer connections to support region-bound enterprise AWS IAM Identity Center accounts. The review feedback highlights critical issues, including a missing timeout on the profile discovery fetch call that could block the login flow, and a lack of lowercase normalization for region strings across multiple files, which may cause comparison and host resolution failures. Additionally, the reviewer notes that unit tests must be added for the new production code changes in open-sse/ and src/ to comply with the repository style guide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| try { | ||
| const runtimeHost = | ||
| tokenRegion === "us-east-1" | ||
| ? "https://codewhisperer.us-east-1.amazonaws.com" | ||
| : `https://q.${tokenRegion}.amazonaws.com`; | ||
| const profRes = await fetch(`${runtimeHost}/`, { | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/x-amz-json-1.0", | ||
| Accept: "application/json", | ||
| "x-amz-target": "AmazonCodeWhispererService.ListAvailableProfiles", | ||
| Authorization: `Bearer ${data.accessToken}`, | ||
| }, | ||
| body: JSON.stringify({ maxResults: 10 }), | ||
| }); | ||
| if (profRes.ok) { | ||
| const profData = await profRes.json(); | ||
| const profiles = Array.isArray(profData?.profiles) ? profData.profiles : []; | ||
| const matched = | ||
| profiles.find( | ||
| (p: { arn?: string }) => | ||
| typeof p?.arn === "string" && p.arn.includes(`:${tokenRegion}:`) | ||
| ) || profiles[0]; | ||
| if (matched && typeof matched.arn === "string") profileArn = matched.arn; | ||
| } |
There was a problem hiding this comment.
There are two issues here:
- The
fetchcall toListAvailableProfilesdoes not have a timeout. If the network hangs or AWS is slow, this fetch will block the device-code polling/login flow indefinitely. Adding a timeout (e.g., 10 seconds) ensures the login flow remains responsive. tokenRegionis not normalized to lowercase. If it contains uppercase characters, the comparisontokenRegion === "us-east-1"will fail, and the profile ARN lookupp.arn.includes(":${tokenRegion}:")might also fail since ARNs typically use lowercase regions. Normalize the region to lowercase before using it.
try {
const normalizedRegion = tokenRegion.toLowerCase();
const runtimeHost =
normalizedRegion === "us-east-1"
? "https://codewhisperer.us-east-1.amazonaws.com"
: `https://q.${normalizedRegion}.amazonaws.com`;
const profRes = await fetch(`${runtimeHost}/`, {
method: "POST",
headers: {
"Content-Type": "application/x-amz-json-1.0",
Accept: "application/json",
"x-amz-target": "AmazonCodeWhispererService.ListAvailableProfiles",
Authorization: `Bearer ${data.accessToken}`
},
body: JSON.stringify({ maxResults: 10 }),
signal: AbortSignal.timeout(10000)
});
if (profRes.ok) {
const profData = await profRes.json();
const profiles = Array.isArray(profData?.profiles) ? profData.profiles : [];
const matched =
profiles.find(
(p: { arn?: string }) =>
typeof p?.arn === "string" && p.arn.includes(`:${normalizedRegion}:`)
) || profiles[0];
if (matched && typeof matched.arn === "string") profileArn = matched.arn;
}| credentials: { providerSpecificData?: unknown } | null | undefined | ||
| ): string { | ||
| const psd = (credentials?.providerSpecificData || {}) as Record<string, unknown>; | ||
| const region = typeof psd.region === "string" ? psd.region.trim() : ""; |
There was a problem hiding this comment.
The region string retrieved from providerSpecificData is trimmed but not normalized to lowercase. If the region is stored in uppercase or mixed case (e.g., EU-CENTRAL-1), comparison checks like region === "us-east-1" will fail, and the regional host will be constructed with uppercase letters (e.g., https://q.EU-CENTRAL-1.amazonaws.com), which can cause issues with host resolution or signature verification. Normalize the region to lowercase.
| const region = typeof psd.region === "string" ? psd.region.trim() : ""; | |
| const region = typeof psd.region === "string" ? psd.region.trim().toLowerCase() : ""; |
| * regional profileArn sent to us-east-1 fails with "Improperly formed request". Falls back to | ||
| * the region embedded in the profileArn, then us-east-1 (the AWS Builder ID default). | ||
| */ | ||
| export function resolveKiroRegion( |
There was a problem hiding this comment.
According to the Repository Style Guide (Rule 9), tests must be included when changing production code in open-sse/ or src/. Please add unit tests (e.g., in tests/) to cover the new resolveKiroRegion and kiroRuntimeHost functions, verifying correct region resolution and host mapping.
References
- Always include tests when changing production code (src/, open-sse/, electron/, bin/). (link)
| const region = | ||
| (typeof providerSpecificData?.region === "string" && providerSpecificData.region.trim()) || | ||
| regionFromArn || | ||
| "us-east-1"; |
There was a problem hiding this comment.
Similar to the executor, the region retrieved from providerSpecificData here is not normalized to lowercase. If it contains uppercase characters, the comparison region === "us-east-1" will fail, routing us-east-1 requests to https://q.US-EAST-1.amazonaws.com instead of CODEWHISPERER_BASE_URL. Normalize the region to lowercase.
| const region = | |
| (typeof providerSpecificData?.region === "string" && providerSpecificData.region.trim()) || | |
| regionFromArn || | |
| "us-east-1"; | |
| const region = | |
| (typeof providerSpecificData?.region === "string" && providerSpecificData.region.trim().toLowerCase()) || | |
| regionFromArn || | |
| "us-east-1"; |
…discovery, add tests - Lowercase-normalize the resolved region in the executor and usage service (and the device-code token region) so mixed-case values like "EU-CENTRAL-1" still match us-east-1 and produce a valid lowercase regional host. - Move enterprise profileArn discovery (ListAvailableProfiles) out of pollToken into the provider's postExchange hook so the device-code polling path stays responsive and existing pollToken contract is unchanged; add a 10s AbortSignal.timeout so a slow/hung AWS call can never block login. - Add tests/unit/kiro-iam-region.test.ts covering resolveKiroRegion, kiroRuntimeHost and the kiro postExchange/mapTokens profileArn behavior.
8ecfe75
into
cheaper-inference:release/v3.8.22
|
Merged into |
* chore(release): open v3.8.22 development cycle * refactor(dashboard): extract ProviderDetailPageClient — #3501 Phase 0 (#3633) #3501 Phase 0: extract ProviderDetailPageClient + smoke test. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract auth-import modals — #3501 Phase 1a (#3634) #3501 Phase 1a: extract 3 auth-import modal clusters. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(db): reclassify localDb unexported modules as intentionally-internal (#3499) (#3635) Closes #3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing). * refactor(db): move call_logs aggregations into callLogStats db module (#3500) (#3636) #3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule #5). Byte-identical queries; TDD 6/6. * refactor(dashboard): extract EditCompatibleNodeModal — #3501 Phase 1b (#3638) #3501 Phase 1b: extract EditCompatibleNodeModal (cycle-safe via leaf constants module). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(db): move community_servers SQL into gamification db module (#3500 slice 3) (#3639) #3500 slice 3: community_servers SQL → gamification db module. * refactor(db): move usage_history SQL into usageAnalytics module (#3500 slice 2) (#3644) #3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module. * refactor(db): move skills UPDATE + db-backups SQL into db modules (#3500 slice 5) (#3647) #3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules. * refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (#3500 slice 4) (#3648) #3500 slice 4: usage_logs/semantic_cache/proxy_logs SQL → db modules. All internal routes done (2 external by-design remain). * chore(db-gate): reclassify external-DB reads, fully close #3500 (#3649) Closes #3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules. * refactor(dashboard): extract pure helpers to providerPageHelpers — #3501 Phase 2 (#3653) #3501 Phase 2: extract pure helpers to providerPageHelpers (leaf, cycle-safe). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract remaining shared helpers to providerPageHelpers — #3501 Phase 2b (#3658) #3501 Phase 2b: extract remaining shared helpers to providerPageHelpers (leaf, cycle-safe). Heavy modals unblocked. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(reasoning): replay reasoning_content on plain DeepSeek turns (#1682) (#3632) Integrated into release/v3.8.22 * fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (#3631) Integrated into release/v3.8.22 * refactor: small code cleanup (#3523) Integrated into release/v3.8.22 * fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (#3637) Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2) * feat(providers): add MiMoCode free-tier provider with bootstrap JWT auth (#3659) Integrated into release/v3.8.22 — page.tsx conflict resolved + NoAuthAccountCard re-applied to ProviderDetailPageClient in review. MiMoCode endpoint validated live. * Log Responses WebSocket calls in history (#3616) Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging. * Add Claude Code routing preference for unprefixed Claude models (#3540) Integrated into release/v3.8.22 — page.tsx conflict resolved (re-applied toggle to ProviderDetailPageClient) + disable-test updated for catalog drift in review. * docs(changelog): credit #3632/#3631/#3637/#3659/#3540/#3616/#3523 (v3.8.22 targeted review round) * fix(mimocode): add required authHeader:"none" to registry entry (#3659 follow-up) The mimocode RegistryEntry omitted the required authHeader field, which broke typecheck:core (TS2741). Match the no-auth convention (authType:"none" + authHeader:"none") used by veoaifree-web and other free providers. Follow-up to #3659 (@pizzav-xyz). * fix(responses): detect stream readiness for tool-call-only and object-less chunks (#3612) (#3661) Closes #3612 * fix(mitm): remove duplicated 'Command failed:' error prefix (#3641) (#3662) Closes #3641 * fix(cli): honor HERMES_HOME for Hermes Agent config path (#3628) (#3663) Closes #3628 * fix(api): fetch live OpenCode model catalog for no-auth model picker (#3611) (#3664) Closes #3611 * fix(api): flag provider topology error state by current status, not stale history (#3619) (#3666) Closes #3619 * fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (#3386) (#3665) Closes #3386 * fix(dashboard): restore home topology live in-flight pulse (#3507) (#3667) Closes #3507 * fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (#3615) (#3671) Closes #3615 * fix(resilience): clear stale transient connection cooldowns on startup (#3625) (#3672) Closes #3625 * fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL #3541) (#3670) Closes #3541 * fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (#3610) (#3669) Closes #3610 * refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — #3501 Phase 1c (#3674) #3501 Phase 1c: extract AddApiKeyModal, EditConnectionModal, WebSessionCredentialGuide into components/; god-component 10,166->8,092 LOC. Reconciles the v3.8.22 file-size drift for this file. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * docs(changelog): reconcile v3.8.22 — credit #3621/#3622 + MiMoCode follow-up roll-up * refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — #3501 Phase 1d (#3676) #3501 Phase 1d: god-component 8,092->6,838 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * feat(obsidian): add WebDAV config route + encrypt creds at rest (#3485 part 1) (#3677) Part 1 of #3485. Adds /api/settings/obsidian/webdav (GET/POST/DELETE) wiring the ready obsidianSync lib, encrypts webdav password + obsidian token at rest, removes the duplicate UI block, drops the KNOWN_MISSING entry. WebDAV file server is part 2. * feat(obsidian): add /api/v1/webdav file server for Obsidian vault sync (#3485 part 2) (#3678) Part 2 of #3485. WebDAV server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE/OPTIONS) handled in the custom server layer (standalone-server-ws.mjs) since the App Router cannot export WebDAV methods. Basic-Auth (constant-time), path-traversal hardened, password decrypt ported from encryption.ts (parity-tested), DATA_DIR resolution parity-tested against dataPaths.ts. End-to-end Obsidian-over-Tailscale validation is a live VPS step (Rule #18). * fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (#3680) Integrated into release/v3.8.22 * feat(dashboard): deactivate/activate accounts from the quota overview (#3675) Integrated into release/v3.8.22 * fix(dashboard): close review gaps in bulk provider connection actions (#3271 follow-up) (#3673) Integrated into release/v3.8.22 — page.tsx conflict (god-component split #3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx * refactor(dashboard): extract useModelCompatState hook + model sections — #3501 Phase 1e (#3683) #3501 Phase 1e: extract useModelCompatState hook (unblocks the model sections) + ModelRow/PassthroughModelsSection/PassthroughModelRow/CustomModelsSection/CompatibleModelsSection. god-component 6,838->4,921 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract useProviderConnections/Settings/Models hooks — #3501 Phase 1f (#3684) #3501 Phase 1f: god-component 4,948->4,062 LOC. Connection state+handlers, settings, and model metadata moved into hooks/. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * chore(release): v3.8.22 CHANGELOG + env-doc sync - Set release date in CHANGELOG [3.8.22] to 2026-06-11 - Add HERMES_HOME to .env.example (from #3628/#3663) - Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (#3628/#3540) * docs(changelog): credit #3673 + #3675 — leninejunior bulk-actions + quota-toggle --------- Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: Abhishek Divekar <adivekar@utexas.edu> Co-authored-by: NOXX - Commiter <artur1992123@mail.ru> Co-authored-by: Nicolas Lorin <androw95220@gmail.com> Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com> Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com> Co-authored-by: kkkayye <98376609+kkkayye@users.noreply.github.com> Co-authored-by: Witroch4 <witalo_rocha@hotmail.com> Co-authored-by: Lenine Júnior <lenine@engrene.com.br>
…ional endpoint (cheaper-inference#3631) Integrated into release/v3.8.22
…ional endpoint (cheaper-inference#3631) Integrated into release/v3.8.22
* chore(release): open v3.8.22 development cycle * refactor(dashboard): extract ProviderDetailPageClient — cheaper-inference#3501 Phase 0 (cheaper-inference#3633) cheaper-inference#3501 Phase 0: extract ProviderDetailPageClient + smoke test. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract auth-import modals — cheaper-inference#3501 Phase 1a (cheaper-inference#3634) cheaper-inference#3501 Phase 1a: extract 3 auth-import modal clusters. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(db): reclassify localDb unexported modules as intentionally-internal (cheaper-inference#3499) (cheaper-inference#3635) Closes cheaper-inference#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing). * refactor(db): move call_logs aggregations into callLogStats db module (cheaper-inference#3500) (cheaper-inference#3636) cheaper-inference#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule cheaper-inference#5). Byte-identical queries; TDD 6/6. * refactor(dashboard): extract EditCompatibleNodeModal — cheaper-inference#3501 Phase 1b (cheaper-inference#3638) cheaper-inference#3501 Phase 1b: extract EditCompatibleNodeModal (cycle-safe via leaf constants module). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(db): move community_servers SQL into gamification db module (cheaper-inference#3500 slice 3) (cheaper-inference#3639) cheaper-inference#3500 slice 3: community_servers SQL → gamification db module. * refactor(db): move usage_history SQL into usageAnalytics module (cheaper-inference#3500 slice 2) (cheaper-inference#3644) cheaper-inference#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module. * refactor(db): move skills UPDATE + db-backups SQL into db modules (cheaper-inference#3500 slice 5) (cheaper-inference#3647) cheaper-inference#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules. * refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (cheaper-inference#3500 slice 4) (cheaper-inference#3648) cheaper-inference#3500 slice 4: usage_logs/semantic_cache/proxy_logs SQL → db modules. All internal routes done (2 external by-design remain). * chore(db-gate): reclassify external-DB reads, fully close cheaper-inference#3500 (cheaper-inference#3649) Closes cheaper-inference#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules. * refactor(dashboard): extract pure helpers to providerPageHelpers — cheaper-inference#3501 Phase 2 (cheaper-inference#3653) cheaper-inference#3501 Phase 2: extract pure helpers to providerPageHelpers (leaf, cycle-safe). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract remaining shared helpers to providerPageHelpers — cheaper-inference#3501 Phase 2b (cheaper-inference#3658) cheaper-inference#3501 Phase 2b: extract remaining shared helpers to providerPageHelpers (leaf, cycle-safe). Heavy modals unblocked. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(reasoning): replay reasoning_content on plain DeepSeek turns (cheaper-inference#1682) (cheaper-inference#3632) Integrated into release/v3.8.22 * fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (cheaper-inference#3631) Integrated into release/v3.8.22 * refactor: small code cleanup (cheaper-inference#3523) Integrated into release/v3.8.22 * fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (cheaper-inference#3637) Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2) * feat(providers): add MiMoCode free-tier provider with bootstrap JWT auth (cheaper-inference#3659) Integrated into release/v3.8.22 — page.tsx conflict resolved + NoAuthAccountCard re-applied to ProviderDetailPageClient in review. MiMoCode endpoint validated live. * Log Responses WebSocket calls in history (cheaper-inference#3616) Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging. * Add Claude Code routing preference for unprefixed Claude models (cheaper-inference#3540) Integrated into release/v3.8.22 — page.tsx conflict resolved (re-applied toggle to ProviderDetailPageClient) + disable-test updated for catalog drift in review. * docs(changelog): credit cheaper-inference#3632/cheaper-inference#3631/cheaper-inference#3637/cheaper-inference#3659/cheaper-inference#3540/cheaper-inference#3616/cheaper-inference#3523 (v3.8.22 targeted review round) * fix(mimocode): add required authHeader:"none" to registry entry (cheaper-inference#3659 follow-up) The mimocode RegistryEntry omitted the required authHeader field, which broke typecheck:core (TS2741). Match the no-auth convention (authType:"none" + authHeader:"none") used by veoaifree-web and other free providers. Follow-up to cheaper-inference#3659 (@pizzav-xyz). * fix(responses): detect stream readiness for tool-call-only and object-less chunks (cheaper-inference#3612) (cheaper-inference#3661) Closes cheaper-inference#3612 * fix(mitm): remove duplicated 'Command failed:' error prefix (cheaper-inference#3641) (cheaper-inference#3662) Closes cheaper-inference#3641 * fix(cli): honor HERMES_HOME for Hermes Agent config path (cheaper-inference#3628) (cheaper-inference#3663) Closes cheaper-inference#3628 * fix(api): fetch live OpenCode model catalog for no-auth model picker (cheaper-inference#3611) (cheaper-inference#3664) Closes cheaper-inference#3611 * fix(api): flag provider topology error state by current status, not stale history (cheaper-inference#3619) (cheaper-inference#3666) Closes cheaper-inference#3619 * fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (cheaper-inference#3386) (cheaper-inference#3665) Closes cheaper-inference#3386 * fix(dashboard): restore home topology live in-flight pulse (cheaper-inference#3507) (cheaper-inference#3667) Closes cheaper-inference#3507 * fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (cheaper-inference#3615) (cheaper-inference#3671) Closes cheaper-inference#3615 * fix(resilience): clear stale transient connection cooldowns on startup (cheaper-inference#3625) (cheaper-inference#3672) Closes cheaper-inference#3625 * fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL cheaper-inference#3541) (cheaper-inference#3670) Closes cheaper-inference#3541 * fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (cheaper-inference#3610) (cheaper-inference#3669) Closes cheaper-inference#3610 * refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — cheaper-inference#3501 Phase 1c (cheaper-inference#3674) cheaper-inference#3501 Phase 1c: extract AddApiKeyModal, EditConnectionModal, WebSessionCredentialGuide into components/; god-component 10,166->8,092 LOC. Reconciles the v3.8.22 file-size drift for this file. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * docs(changelog): reconcile v3.8.22 — credit cheaper-inference#3621/cheaper-inference#3622 + MiMoCode follow-up roll-up * refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — cheaper-inference#3501 Phase 1d (cheaper-inference#3676) cheaper-inference#3501 Phase 1d: god-component 8,092->6,838 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * feat(obsidian): add WebDAV config route + encrypt creds at rest (cheaper-inference#3485 part 1) (cheaper-inference#3677) Part 1 of cheaper-inference#3485. Adds /api/settings/obsidian/webdav (GET/POST/DELETE) wiring the ready obsidianSync lib, encrypts webdav password + obsidian token at rest, removes the duplicate UI block, drops the KNOWN_MISSING entry. WebDAV file server is part 2. * feat(obsidian): add /api/v1/webdav file server for Obsidian vault sync (cheaper-inference#3485 part 2) (cheaper-inference#3678) Part 2 of cheaper-inference#3485. WebDAV server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE/OPTIONS) handled in the custom server layer (standalone-server-ws.mjs) since the App Router cannot export WebDAV methods. Basic-Auth (constant-time), path-traversal hardened, password decrypt ported from encryption.ts (parity-tested), DATA_DIR resolution parity-tested against dataPaths.ts. End-to-end Obsidian-over-Tailscale validation is a live VPS step (Rule cheaper-inference#18). * fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (cheaper-inference#3680) Integrated into release/v3.8.22 * feat(dashboard): deactivate/activate accounts from the quota overview (cheaper-inference#3675) Integrated into release/v3.8.22 * fix(dashboard): close review gaps in bulk provider connection actions (cheaper-inference#3271 follow-up) (cheaper-inference#3673) Integrated into release/v3.8.22 — page.tsx conflict (god-component split cheaper-inference#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx * refactor(dashboard): extract useModelCompatState hook + model sections — cheaper-inference#3501 Phase 1e (cheaper-inference#3683) cheaper-inference#3501 Phase 1e: extract useModelCompatState hook (unblocks the model sections) + ModelRow/PassthroughModelsSection/PassthroughModelRow/CustomModelsSection/CompatibleModelsSection. god-component 6,838->4,921 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract useProviderConnections/Settings/Models hooks — cheaper-inference#3501 Phase 1f (cheaper-inference#3684) cheaper-inference#3501 Phase 1f: god-component 4,948->4,062 LOC. Connection state+handlers, settings, and model metadata moved into hooks/. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * chore(release): v3.8.22 CHANGELOG + env-doc sync - Set release date in CHANGELOG [3.8.22] to 2026-06-11 - Add HERMES_HOME to .env.example (from cheaper-inference#3628/cheaper-inference#3663) - Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (cheaper-inference#3628/cheaper-inference#3540) * docs(changelog): credit cheaper-inference#3673 + cheaper-inference#3675 — leninejunior bulk-actions + quota-toggle --------- Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: Abhishek Divekar <adivekar@utexas.edu> Co-authored-by: NOXX - Commiter <artur1992123@mail.ru> Co-authored-by: Nicolas Lorin <androw95220@gmail.com> Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com> Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com> Co-authored-by: kkkayye <98376609+kkkayye@users.noreply.github.com> Co-authored-by: Witroch4 <witalo_rocha@hotmail.com> Co-authored-by: Lenine Júnior <lenine@engrene.com.br>
* chore(release): open v3.8.22 development cycle * refactor(dashboard): extract ProviderDetailPageClient — cheaper-inference#3501 Phase 0 (cheaper-inference#3633) cheaper-inference#3501 Phase 0: extract ProviderDetailPageClient + smoke test. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract auth-import modals — cheaper-inference#3501 Phase 1a (cheaper-inference#3634) cheaper-inference#3501 Phase 1a: extract 3 auth-import modal clusters. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(db): reclassify localDb unexported modules as intentionally-internal (cheaper-inference#3499) (cheaper-inference#3635) Closes cheaper-inference#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing). * refactor(db): move call_logs aggregations into callLogStats db module (cheaper-inference#3500) (cheaper-inference#3636) cheaper-inference#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule cheaper-inference#5). Byte-identical queries; TDD 6/6. * refactor(dashboard): extract EditCompatibleNodeModal — cheaper-inference#3501 Phase 1b (cheaper-inference#3638) cheaper-inference#3501 Phase 1b: extract EditCompatibleNodeModal (cycle-safe via leaf constants module). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(db): move community_servers SQL into gamification db module (cheaper-inference#3500 slice 3) (cheaper-inference#3639) cheaper-inference#3500 slice 3: community_servers SQL → gamification db module. * refactor(db): move usage_history SQL into usageAnalytics module (cheaper-inference#3500 slice 2) (cheaper-inference#3644) cheaper-inference#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module. * refactor(db): move skills UPDATE + db-backups SQL into db modules (cheaper-inference#3500 slice 5) (cheaper-inference#3647) cheaper-inference#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules. * refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (cheaper-inference#3500 slice 4) (cheaper-inference#3648) cheaper-inference#3500 slice 4: usage_logs/semantic_cache/proxy_logs SQL → db modules. All internal routes done (2 external by-design remain). * chore(db-gate): reclassify external-DB reads, fully close cheaper-inference#3500 (cheaper-inference#3649) Closes cheaper-inference#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules. * refactor(dashboard): extract pure helpers to providerPageHelpers — cheaper-inference#3501 Phase 2 (cheaper-inference#3653) cheaper-inference#3501 Phase 2: extract pure helpers to providerPageHelpers (leaf, cycle-safe). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract remaining shared helpers to providerPageHelpers — cheaper-inference#3501 Phase 2b (cheaper-inference#3658) cheaper-inference#3501 Phase 2b: extract remaining shared helpers to providerPageHelpers (leaf, cycle-safe). Heavy modals unblocked. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(reasoning): replay reasoning_content on plain DeepSeek turns (cheaper-inference#1682) (cheaper-inference#3632) Integrated into release/v3.8.22 * fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (cheaper-inference#3631) Integrated into release/v3.8.22 * refactor: small code cleanup (cheaper-inference#3523) Integrated into release/v3.8.22 * fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (cheaper-inference#3637) Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2) * feat(providers): add MiMoCode free-tier provider with bootstrap JWT auth (cheaper-inference#3659) Integrated into release/v3.8.22 — page.tsx conflict resolved + NoAuthAccountCard re-applied to ProviderDetailPageClient in review. MiMoCode endpoint validated live. * Log Responses WebSocket calls in history (cheaper-inference#3616) Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging. * Add Claude Code routing preference for unprefixed Claude models (cheaper-inference#3540) Integrated into release/v3.8.22 — page.tsx conflict resolved (re-applied toggle to ProviderDetailPageClient) + disable-test updated for catalog drift in review. * docs(changelog): credit cheaper-inference#3632/cheaper-inference#3631/cheaper-inference#3637/cheaper-inference#3659/cheaper-inference#3540/cheaper-inference#3616/cheaper-inference#3523 (v3.8.22 targeted review round) * fix(mimocode): add required authHeader:"none" to registry entry (cheaper-inference#3659 follow-up) The mimocode RegistryEntry omitted the required authHeader field, which broke typecheck:core (TS2741). Match the no-auth convention (authType:"none" + authHeader:"none") used by veoaifree-web and other free providers. Follow-up to cheaper-inference#3659 (@pizzav-xyz). * fix(responses): detect stream readiness for tool-call-only and object-less chunks (cheaper-inference#3612) (cheaper-inference#3661) Closes cheaper-inference#3612 * fix(mitm): remove duplicated 'Command failed:' error prefix (cheaper-inference#3641) (cheaper-inference#3662) Closes cheaper-inference#3641 * fix(cli): honor HERMES_HOME for Hermes Agent config path (cheaper-inference#3628) (cheaper-inference#3663) Closes cheaper-inference#3628 * fix(api): fetch live OpenCode model catalog for no-auth model picker (cheaper-inference#3611) (cheaper-inference#3664) Closes cheaper-inference#3611 * fix(api): flag provider topology error state by current status, not stale history (cheaper-inference#3619) (cheaper-inference#3666) Closes cheaper-inference#3619 * fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (cheaper-inference#3386) (cheaper-inference#3665) Closes cheaper-inference#3386 * fix(dashboard): restore home topology live in-flight pulse (cheaper-inference#3507) (cheaper-inference#3667) Closes cheaper-inference#3507 * fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (cheaper-inference#3615) (cheaper-inference#3671) Closes cheaper-inference#3615 * fix(resilience): clear stale transient connection cooldowns on startup (cheaper-inference#3625) (cheaper-inference#3672) Closes cheaper-inference#3625 * fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL cheaper-inference#3541) (cheaper-inference#3670) Closes cheaper-inference#3541 * fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (cheaper-inference#3610) (cheaper-inference#3669) Closes cheaper-inference#3610 * refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — cheaper-inference#3501 Phase 1c (cheaper-inference#3674) cheaper-inference#3501 Phase 1c: extract AddApiKeyModal, EditConnectionModal, WebSessionCredentialGuide into components/; god-component 10,166->8,092 LOC. Reconciles the v3.8.22 file-size drift for this file. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * docs(changelog): reconcile v3.8.22 — credit cheaper-inference#3621/cheaper-inference#3622 + MiMoCode follow-up roll-up * refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — cheaper-inference#3501 Phase 1d (cheaper-inference#3676) cheaper-inference#3501 Phase 1d: god-component 8,092->6,838 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * feat(obsidian): add WebDAV config route + encrypt creds at rest (cheaper-inference#3485 part 1) (cheaper-inference#3677) Part 1 of cheaper-inference#3485. Adds /api/settings/obsidian/webdav (GET/POST/DELETE) wiring the ready obsidianSync lib, encrypts webdav password + obsidian token at rest, removes the duplicate UI block, drops the KNOWN_MISSING entry. WebDAV file server is part 2. * feat(obsidian): add /api/v1/webdav file server for Obsidian vault sync (cheaper-inference#3485 part 2) (cheaper-inference#3678) Part 2 of cheaper-inference#3485. WebDAV server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE/OPTIONS) handled in the custom server layer (standalone-server-ws.mjs) since the App Router cannot export WebDAV methods. Basic-Auth (constant-time), path-traversal hardened, password decrypt ported from encryption.ts (parity-tested), DATA_DIR resolution parity-tested against dataPaths.ts. End-to-end Obsidian-over-Tailscale validation is a live VPS step (Rule cheaper-inference#18). * fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (cheaper-inference#3680) Integrated into release/v3.8.22 * feat(dashboard): deactivate/activate accounts from the quota overview (cheaper-inference#3675) Integrated into release/v3.8.22 * fix(dashboard): close review gaps in bulk provider connection actions (cheaper-inference#3271 follow-up) (cheaper-inference#3673) Integrated into release/v3.8.22 — page.tsx conflict (god-component split cheaper-inference#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx * refactor(dashboard): extract useModelCompatState hook + model sections — cheaper-inference#3501 Phase 1e (cheaper-inference#3683) cheaper-inference#3501 Phase 1e: extract useModelCompatState hook (unblocks the model sections) + ModelRow/PassthroughModelsSection/PassthroughModelRow/CustomModelsSection/CompatibleModelsSection. god-component 6,838->4,921 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract useProviderConnections/Settings/Models hooks — cheaper-inference#3501 Phase 1f (cheaper-inference#3684) cheaper-inference#3501 Phase 1f: god-component 4,948->4,062 LOC. Connection state+handlers, settings, and model metadata moved into hooks/. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * chore(release): v3.8.22 CHANGELOG + env-doc sync - Set release date in CHANGELOG [3.8.22] to 2026-06-11 - Add HERMES_HOME to .env.example (from cheaper-inference#3628/cheaper-inference#3663) - Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (cheaper-inference#3628/cheaper-inference#3540) * docs(changelog): credit cheaper-inference#3673 + cheaper-inference#3675 — leninejunior bulk-actions + quota-toggle --------- Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: Abhishek Divekar <adivekar@utexas.edu> Co-authored-by: NOXX - Commiter <artur1992123@mail.ru> Co-authored-by: Nicolas Lorin <androw95220@gmail.com> Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com> Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com> Co-authored-by: kkkayye <98376609+kkkayye@users.noreply.github.com> Co-authored-by: Witroch4 <witalo_rocha@hotmail.com> Co-authored-by: Lenine Júnior <lenine@engrene.com.br>
…ional endpoint (cheaper-inference#3631) Integrated into release/v3.8.22
* chore(release): open v3.8.22 development cycle * refactor(dashboard): extract ProviderDetailPageClient — cheaper-inference#3501 Phase 0 (cheaper-inference#3633) cheaper-inference#3501 Phase 0: extract ProviderDetailPageClient + smoke test. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract auth-import modals — cheaper-inference#3501 Phase 1a (cheaper-inference#3634) cheaper-inference#3501 Phase 1a: extract 3 auth-import modal clusters. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(db): reclassify localDb unexported modules as intentionally-internal (cheaper-inference#3499) (cheaper-inference#3635) Closes cheaper-inference#3499 — reclassify localDb unexported modules as intentionally-internal (audit + honest gate framing). * refactor(db): move call_logs aggregations into callLogStats db module (cheaper-inference#3500) (cheaper-inference#3636) cheaper-inference#3500 slice 1: call_logs aggregations → src/lib/db/callLogStats.ts (Rule cheaper-inference#5). Byte-identical queries; TDD 6/6. * refactor(dashboard): extract EditCompatibleNodeModal — cheaper-inference#3501 Phase 1b (cheaper-inference#3638) cheaper-inference#3501 Phase 1b: extract EditCompatibleNodeModal (cycle-safe via leaf constants module). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(db): move community_servers SQL into gamification db module (cheaper-inference#3500 slice 3) (cheaper-inference#3639) cheaper-inference#3500 slice 3: community_servers SQL → gamification db module. * refactor(db): move usage_history SQL into usageAnalytics module (cheaper-inference#3500 slice 2) (cheaper-inference#3644) cheaper-inference#3500 slice 2: usage_history/daily_usage_summary SQL → usageAnalytics db module. * refactor(db): move skills UPDATE + db-backups SQL into db modules (cheaper-inference#3500 slice 5) (cheaper-inference#3647) cheaper-inference#3500 slice 5: skills UPDATE (allowlist) + db-backups SQL → db modules. * refactor(db): move usage_logs/semantic_cache/proxy_logs SQL into db modules (cheaper-inference#3500 slice 4) (cheaper-inference#3648) cheaper-inference#3500 slice 4: usage_logs/semantic_cache/proxy_logs SQL → db modules. All internal routes done (2 external by-design remain). * chore(db-gate): reclassify external-DB reads, fully close cheaper-inference#3500 (cheaper-inference#3649) Closes cheaper-inference#3500: reclassify external-DB reads; all internal raw-SQL migrated to db/ modules. * refactor(dashboard): extract pure helpers to providerPageHelpers — cheaper-inference#3501 Phase 2 (cheaper-inference#3653) cheaper-inference#3501 Phase 2: extract pure helpers to providerPageHelpers (leaf, cycle-safe). Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract remaining shared helpers to providerPageHelpers — cheaper-inference#3501 Phase 2b (cheaper-inference#3658) cheaper-inference#3501 Phase 2b: extract remaining shared helpers to providerPageHelpers (leaf, cycle-safe). Heavy modals unblocked. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * fix(reasoning): replay reasoning_content on plain DeepSeek turns (cheaper-inference#1682) (cheaper-inference#3632) Integrated into release/v3.8.22 * fix(kiro): route enterprise IAM Identity Center accounts to their regional endpoint (cheaper-inference#3631) Integrated into release/v3.8.22 * refactor: small code cleanup (cheaper-inference#3523) Integrated into release/v3.8.22 * fix(combo): skip same-provider targets on 408/500/502/503/504/524 errors (cheaper-inference#3637) Integrated into release/v3.8.22 — circuit-breaker guard added in review (#1731v2) * feat(providers): add MiMoCode free-tier provider with bootstrap JWT auth (cheaper-inference#3659) Integrated into release/v3.8.22 — page.tsx conflict resolved + NoAuthAccountCard re-applied to ProviderDetailPageClient in review. MiMoCode endpoint validated live. * Log Responses WebSocket calls in history (cheaper-inference#3616) Integrated into release/v3.8.22 — Codex Responses WebSocket call history logging. * Add Claude Code routing preference for unprefixed Claude models (cheaper-inference#3540) Integrated into release/v3.8.22 — page.tsx conflict resolved (re-applied toggle to ProviderDetailPageClient) + disable-test updated for catalog drift in review. * docs(changelog): credit cheaper-inference#3632/cheaper-inference#3631/cheaper-inference#3637/cheaper-inference#3659/cheaper-inference#3540/cheaper-inference#3616/cheaper-inference#3523 (v3.8.22 targeted review round) * fix(mimocode): add required authHeader:"none" to registry entry (cheaper-inference#3659 follow-up) The mimocode RegistryEntry omitted the required authHeader field, which broke typecheck:core (TS2741). Match the no-auth convention (authType:"none" + authHeader:"none") used by veoaifree-web and other free providers. Follow-up to cheaper-inference#3659 (@pizzav-xyz). * fix(responses): detect stream readiness for tool-call-only and object-less chunks (cheaper-inference#3612) (cheaper-inference#3661) Closes cheaper-inference#3612 * fix(mitm): remove duplicated 'Command failed:' error prefix (cheaper-inference#3641) (cheaper-inference#3662) Closes cheaper-inference#3641 * fix(cli): honor HERMES_HOME for Hermes Agent config path (cheaper-inference#3628) (cheaper-inference#3663) Closes cheaper-inference#3628 * fix(api): fetch live OpenCode model catalog for no-auth model picker (cheaper-inference#3611) (cheaper-inference#3664) Closes cheaper-inference#3611 * fix(api): flag provider topology error state by current status, not stale history (cheaper-inference#3619) (cheaper-inference#3666) Closes cheaper-inference#3619 * fix(electron): launch peer-stamping server-ws.mjs entrypoint to avoid 403 LOCAL_ONLY (cheaper-inference#3386) (cheaper-inference#3665) Closes cheaper-inference#3386 * fix(dashboard): restore home topology live in-flight pulse (cheaper-inference#3507) (cheaper-inference#3667) Closes cheaper-inference#3507 * fix(oauth): name Kiro/AWS auto-imported accounts and dedupe by profileArn (cheaper-inference#3615) (cheaper-inference#3671) Closes cheaper-inference#3615 * fix(resilience): clear stale transient connection cooldowns on startup (cheaper-inference#3625) (cheaper-inference#3672) Closes cheaper-inference#3625 * fix(i18n): use logical CSS direction utilities for sidebar and key overlays (RTL cheaper-inference#3541) (cheaper-inference#3670) Closes cheaper-inference#3541 * fix(dashboard): honor auto-hide and switch to visible filter on passthrough Test-all (cheaper-inference#3610) (cheaper-inference#3669) Closes cheaper-inference#3610 * refactor(dashboard): extract AddApiKeyModal + EditConnectionModal — cheaper-inference#3501 Phase 1c (cheaper-inference#3674) cheaper-inference#3501 Phase 1c: extract AddApiKeyModal, EditConnectionModal, WebSessionCredentialGuide into components/; god-component 10,166->8,092 LOC. Reconciles the v3.8.22 file-size drift for this file. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * docs(changelog): reconcile v3.8.22 — credit cheaper-inference#3621/cheaper-inference#3622 + MiMoCode follow-up roll-up * refactor(dashboard): extract ConnectionRow + ModelCompatPopover + SiliconFlowEndpointModal — cheaper-inference#3501 Phase 1d (cheaper-inference#3676) cheaper-inference#3501 Phase 1d: god-component 8,092->6,838 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * feat(obsidian): add WebDAV config route + encrypt creds at rest (cheaper-inference#3485 part 1) (cheaper-inference#3677) Part 1 of cheaper-inference#3485. Adds /api/settings/obsidian/webdav (GET/POST/DELETE) wiring the ready obsidianSync lib, encrypts webdav password + obsidian token at rest, removes the duplicate UI block, drops the KNOWN_MISSING entry. WebDAV file server is part 2. * feat(obsidian): add /api/v1/webdav file server for Obsidian vault sync (cheaper-inference#3485 part 2) (cheaper-inference#3678) Part 2 of cheaper-inference#3485. WebDAV server (PROPFIND/GET/PUT/DELETE/MKCOL/MOVE/OPTIONS) handled in the custom server layer (standalone-server-ws.mjs) since the App Router cannot export WebDAV methods. Basic-Auth (constant-time), path-traversal hardened, password decrypt ported from encryption.ts (parity-tested), DATA_DIR resolution parity-tested against dataPaths.ts. End-to-end Obsidian-over-Tailscale validation is a live VPS step (Rule cheaper-inference#18). * fix(combo): stop premature context compaction — real auto-combo windows + per-target compression limit (cheaper-inference#3680) Integrated into release/v3.8.22 * feat(dashboard): deactivate/activate accounts from the quota overview (cheaper-inference#3675) Integrated into release/v3.8.22 * fix(dashboard): close review gaps in bulk provider connection actions (cheaper-inference#3271 follow-up) (cheaper-inference#3673) Integrated into release/v3.8.22 — page.tsx conflict (god-component split cheaper-inference#3501) resolved by re-applying the bulk-action deltas to ProviderDetailPageClient.tsx * refactor(dashboard): extract useModelCompatState hook + model sections — cheaper-inference#3501 Phase 1e (cheaper-inference#3683) cheaper-inference#3501 Phase 1e: extract useModelCompatState hook (unblocks the model sections) + ModelRow/PassthroughModelsSection/PassthroughModelRow/CustomModelsSection/CompatibleModelsSection. god-component 6,838->4,921 LOC. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * refactor(dashboard): extract useProviderConnections/Settings/Models hooks — cheaper-inference#3501 Phase 1f (cheaper-inference#3684) cheaper-inference#3501 Phase 1f: god-component 4,948->4,062 LOC. Connection state+handlers, settings, and model metadata moved into hooks/. Co-authored-by: oyi77 <oyi77@users.noreply.github.com> * chore(release): v3.8.22 CHANGELOG + env-doc sync - Set release date in CHANGELOG [3.8.22] to 2026-06-11 - Add HERMES_HOME to .env.example (from cheaper-inference#3628/cheaper-inference#3663) - Add HERMES_HOME + OMNIROUTE_PREFER_CLAUDE_CODE_FOR_UNPREFIXED_CLAUDE_MODELS to ENVIRONMENT.md (cheaper-inference#3628/cheaper-inference#3540) * docs(changelog): credit cheaper-inference#3673 + cheaper-inference#3675 — leninejunior bulk-actions + quota-toggle --------- Co-authored-by: oyi77 <oyi77@users.noreply.github.com> Co-authored-by: Abhishek Divekar <adivekar@utexas.edu> Co-authored-by: NOXX - Commiter <artur1992123@mail.ru> Co-authored-by: Nicolas Lorin <androw95220@gmail.com> Co-authored-by: Hernan Javier Ardila Sanchez <hjasgr@gmail.com> Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com> Co-authored-by: kkkayye <98376609+kkkayye@users.noreply.github.com> Co-authored-by: Witroch4 <witalo_rocha@hotmail.com> Co-authored-by: Lenine Júnior <lenine@engrene.com.br>
Problem
Enterprise AWS IAM Identity Center Kiro accounts always fail with
403 "User is not authorized to make this call"even though the same account works in the Kiro IDE.Kiro/CodeWhisperer is region-bound: the access token, the Q Developer profileArn, and the runtime endpoint must all match the region the IdC instance lives in (e.g.
eu-central-1). The backend hardcodedcodewhisperer.us-east-1.amazonaws.comeverywhere.Verified live against AWS for an
eu-central-1account:codewhisperer.us-east-1is accepted but the eu-central-1profileArnyields400 "Improperly formed request".q.eu-central-1.amazonaws.comis what the Kiro IDE uses (arn:aws:codewhisperer:eu-central-1:...:profile/...).codewhisperer.{region}.amazonaws.comdoes not resolve for non-us-east-1 regions; the regional host isq.{region}.amazonaws.com.profileArn, which enterprise accounts require on every call.Fix (3 files)
open-sse/executors/kiro.ts— resolve the region fromproviderSpecificData.region(or parsed from theprofileArn) and POSTgenerateAssistantResponseto the regional host.us-east-1keeps the legacycodewhisperer.us-east-1host, so AWS Builder ID accounts are unaffected.open-sse/services/usage.ts—GetUsageLimitsnow targets the same regional host.src/lib/oauth/providers/kiro.ts— the device-code login (Builder ID / IDC) now discovers the Q DeveloperprofileArnviaListAvailableProfilesagainst the regional endpoint and stores it.Compatibility
us-east-1behavior is byte-for-byte unchanged (Builder ID), so there is no regression for existing accounts. Profile discovery is best-effort and a no-op for accounts without a profile.