Skip to content

feat(openrouter): use org-specific models endpoint when user has an organization#2326

Open
kilo-code-bot[bot] wants to merge 10 commits intomainfrom
feat/org-models-for-authed-users
Open

feat(openrouter): use org-specific models endpoint when user has an organization#2326
kilo-code-bot[bot] wants to merge 10 commits intomainfrom
feat/org-models-for-authed-users

Conversation

@kilo-code-bot
Copy link
Copy Markdown
Contributor

@kilo-code-bot kilo-code-bot bot commented Apr 11, 2026

Summary

When getUserFromAuth returns an organizationId (i.e., the request includes an x-kilocode-organizationid header from the extension), the /api/openrouter/models endpoint now delegates to caller.organizations.settings.listAvailableModels. This means org members get:

  • Enterprise deny-list filtering (model and provider deny lists)
  • Organization-level BYOK models
  • Custom LLMs configured for the organization

Previously, this endpoint always returned the global model list + user-level BYOK models regardless of organization context.

Verification

  • Reviewed the listAvailableModels tRPC procedure to confirm it handles org-level BYOK, custom LLMs, and enterprise deny-lists.
  • Confirmed the organizationId field in GetAuthResponse is only set when a valid x-kilocode-organizationid header is present.
  • Ran git diff to verify the change is minimal and correct.

Visual Changes

N/A

Reviewer Notes

The non-org path is unchanged. The getDirectByokModels helper (user-level BYOK) is only called in the non-org branch. Org-level BYOK is handled inside listAvailableModels. Note that getUserFromAuth is called once at the top of GET to check for organizationId; the helper getDirectByokModels also calls it internally, but Next.js caches the headers() call per request so there is no meaningful overhead.

): Promise<NextResponse<{ error: string; message: string } | OpenRouterModelsResponse>> {
request: NextRequest
): Promise<NextResponse<{ error: string; message?: string } | OpenRouterModelsResponse>> {
const { organizationId } = await getUserFromAuth({ adminOnly: false });
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Auth lookup can fail the public models endpoint

getDirectByokModels() currently swallows getUserFromAuth/database failures and falls back to the public OpenRouter list. Moving getUserFromAuth to the top level means any exception from session or user lookup aborts the handler before getEnhancedOpenRouterModels() runs, so a transient auth/database failure now turns this otherwise public endpoint into a 500 instead of a degraded response.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: is now wrapped in with a try/catch, matching the same defensive pattern as the original . Errors fall back to the non-org path, so the endpoint remains available even if auth/database is unavailable.

@kilo-code-bot
Copy link
Copy Markdown
Contributor Author

kilo-code-bot bot commented Apr 11, 2026

Code Review Summary

Status: 1 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 1
WARNING 0
SUGGESTION 0

Fix these issues in Kilo Cloud

Issue Details (click to expand)

CRITICAL

File Line Issue
apps/web/src/routers/organizations/organization-settings-router.ts 16 The refactor removed the createAllowPredicateFromDenyList import even though later mutations in the same file still call it, which breaks typecheck/build.
Other Observations (not in diff)

None.

Files Reviewed (4 files)
  • apps/web/src/app/api/openrouter/models/route.ts - no new issues
  • apps/web/src/lib/organizations/organization-models.ts - no new issues
  • apps/web/src/routers/kilo-pass-router.test.ts - no new issues
  • apps/web/src/routers/organizations/organization-settings-router.ts - 1 issue

Reviewed by gpt-5.4-20260305 · 611,220 tokens

user: { id: 'test-user-id' },
authFailedResponse: null,
})),
getUserFromAuth: jest.fn().mockImplementation(async () => ({
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: resetAllMocks() clears this implementation before each test

This suite still calls jest.resetAllMocks() in beforeEach, which resets getUserFromAuth back to a no-op mock. GET() now immediately destructures organizationId from that result, so the tests will start throwing before they reach the route logic unless the implementation is re-applied in beforeEach (or the suite switches to clearAllMocks()).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed: the route was restructured so getUserFromAuth is called defensively in getAuthContext() (try/catch), and tests don't need to mock it. The resetAllMocks() issue no longer applies.

import { KILO_ORGANIZATION_ID } from '@/lib/organizations/constants';
import { listAvailableCustomLlms } from '@/lib/custom-llm/listAvailableCustomLlms';
import { getDirectByokModelsForOrganization } from '@/lib/providers/direct-byok';
import { createAllowPredicateFromDenyList } from '@/lib/model-allow.server';
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CRITICAL: Missing import breaks this router

This refactor removed createAllowPredicateFromDenyList from the imports, but updateAllowLists and updateDefaultModel still call it later in the file. That leaves organization-settings-router.ts with an unresolved identifier and should fail typecheck/build as soon as this file is compiled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant