fix(proxy): make proxy connectors work on non-EPAM tenant model catalogs - #567
Open
vadimvlasenko wants to merge 17 commits into
Open
vadimvlasenko wants to merge 17 commits into
vadimvlasenko wants to merge 17 commits into
Conversation
Generalizes codex-model-resolver.ts's date-stripping identity-parse shape to strip vendor prefixes (GPT) and match both token orders (Claude) so VS Code Copilot BYOK and Claude Desktop can resolve tenant-shaped model ids (philips-tenant-model-catalog task 1). Generated with AI Co-Authored-By: codemie-ai <[email protected]>
Add fetchTenantModelCatalog and thread a live gateway catalog through buildManagedModels via resolveTenantModelId, so the capability table (previous commit) resolves each family to whatever id the tenant actually registers instead of a fixed EPAM-shaped id. Unmatched families are dropped; a fully unmatched catalog now rejects with no file written. gatewayKey is threaded through writeVsCodeLanguageModelsConfig[AtPath] and connect-orchestrator.ts, which also reports the real resolved model count instead of the static table length (philips-tenant-model-catalog tasks 3-4). Squashed with task 2's vscode-models.ts capability-table rename (VS_CODE_SUPPORTED_MODELS -> VS_CODE_CAPABILITY_TABLE): the rename's sole consumers are vscode.ts and connect-orchestrator.ts, so the two land together to keep every commit typecheck-clean and pre-commit green, matching this repo's hook that runs `tsc --noEmit` on every commit. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
Replace selectPreferredClaudeModels's suffix-only exact/dated matching with the shared resolveTenantModelId, so a tenant that names models version-first (e.g. claude-5-opus) resolves correctly instead of never matching PREFERRED_CLAUDE_MODELS's family-first entries (philips-tenant-model-catalog task 5). Generated with AI Co-Authored-By: codemie-ai <[email protected]>
…Code settings Read settings.json with jsonc-parser (allowTrailingComma) instead of strict JSON.parse, and write the two managed keys via targeted modify()/applyEdits() passes against the original text instead of re-serializing the whole object, so a hand-edited settings.json with // comments survives the write (philips-tenant-model-catalog task 6). A genuinely unparseable file still rejects with ConfigurationError and is left untouched. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
…es by recency RELEASE_DATE_PATTERN only matched separator-delimited dates, so a single-number preferred family (claude-opus-5, claude-sonnet-5) never resolved against a realistically-shaped concatenated-date tenant id (claude-opus-5-20260101) — two-number families only worked by positional coincidence. pickMostRecent's lexicographic tie-break was also unsound across mixed id shapes (vendor-prefixed vs. dated vs. -vertex-suffixed). Extend the date pattern to cover both shapes and rank same-identity candidates by an explicit non-vertex-before-vertex, then parsed-date precedence instead of raw string comparison. philips-tenant-model-catalog CR-001, CR-002 Generated with AI Co-Authored-By: codemie-ai <[email protected]>
…ch fallback
fetchTenantModelCatalog was a ~73-line function mixing fetch, HTTP-status
handling, content-type validation, response-shape parsing, and logging —
over the code-quality function-length/single-responsibility limit. It also
had no timeout on its fetch() call, so a hung gateway blocked `codemie proxy
connect` indefinitely, and its `{ data: [...] }` response branch only read
`m.id`, dropping the same base_name/deployment_name fallback the array
branch already applied.
Extract the parsing and logging into small named helpers, wrap the fetch in
an AbortController-backed timeout (converted into the same ConfigurationError
contract on abort), and apply one shared id/base_name/deployment_name
fallback chain to both response shapes.
philips-tenant-model-catalog CR-003, CR-004, CR-005
Generated with AI
Co-Authored-By: codemie-ai <[email protected]>
…tings writeVsCodeClaudeCodeConfigAtPath's two jsonc-parser modify() calls passed an empty ModificationOptions object, leaving `formattingOptions` undefined. Per jsonc-parser's own contract that inserts the edit completely unformatted — no newline, no indent — rather than falling back to any default, so the managed keys could land jammed onto the same line as the preceding property. Detect the file's actual indentation and EOL from its raw text and pass real formattingOptions to both modify() calls. philips-tenant-model-catalog CR-006 Generated with AI Co-Authored-By: codemie-ai <[email protected]>
Both integration test files still imported the removed VS_CODE_SUPPORTED_MODELS/VsCodeModelDefinition (renamed to VS_CODE_CAPABILITY_TABLE/VsCodeCapabilityEntry, whose entries carry a `family` name instead of a literal tenant id). vscode-byok.test.ts's writeVsCodeLanguageModelsConfigAtPath call was also missing the new required gatewayKey argument, and its mock upstream server never served a /v1/llm_models catalog body, so the connector's catalog fetch found zero models and the test never exercised its own scenario. Update both files to the renamed exports and the family-based shape, pass gatewayKey through, and have the BYOK test's mock server serve a catalog whose ids exactly match every VS_CODE_CAPABILITY_TABLE family so each entry resolves verbatim. philips-tenant-model-catalog CR-007 Generated with AI Co-Authored-By: codemie-ai <[email protected]>
Test fixtures and descriptions named a real customer. Rename them to describe the tenant-naming shape under test instead: PHILIPS_CLAUDE_FIXTURE -> VERSION_FIRST_CLAUDE_FIXTURE (desktop.test.ts) and PHILIPS_FIXTURE -> NON_EPAM_TENANT_FIXTURE (vscode.test.ts), with matching test/describe titles. No behavior change. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
…t-model-catalog Generated with AI Co-Authored-By: codemie-ai <[email protected]>
state.local.json/gate-plan.local.json replaced .state.json/gate-plan.json in the sdlc-factory scripts; the ignore patterns here still named the old filenames, so every finished sdlc run left the task dir looking dirty. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
…atches selectPreferredClaudeModels logged a reordered tenant match (e.g. family claude-opus-5 resolving to tenant id claude-5-opus) as missing because the diagnostic re-derived membership from string prefixes instead of asking resolveTenantModelId directly. Track resolved/missing at the point of resolution instead. Also drops the now-redundant local -vertex fallback: resolveTenantModelId's parseClaudeIdentity already strips -vertex before matching, so the separate string-based fallback could never fire differently from what the resolver already returns. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
fetchTenantModelCatalog built its request URL before the try block, so a malformed proxyUrl escaped as a raw TypeError instead of the ConfigurationError every other failure path in this function guarantees. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
…acts Replace named-customer mentions (Philips, and the reported user's name/ machine path) with generic "non-EPAM tenant" / "reported tenant" phrasing across the run's technical-analysis, spec, plan, and code-review verdict. Also reconcile code-review-final.json: a stray duplicate review-triage dispatch had overwritten it with a 10-item verdict never actually triaged by the caller. Two of those ten findings were genuinely new (desktop.ts's false missing-model diagnostic, tenant-catalog.ts's unwrapped malformed-proxyUrl TypeError); both are now fixed, tested, and noted as resolved in the file. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
docs/superpowers/tasks/2026-09-17-philips-tenant-model-catalog -> 2026-09-17-tenant-model-catalog. Fixes internal path references in plan.md's Spec: line and gate-run.json's branch field to match. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
…mmit A failed pathspec in the rename commit's git add silently dropped these two edits (gate-run.json's branch field, plan.md's Spec: path) before they were committed. Generated with AI Co-Authored-By: codemie-ai <[email protected]>
8 tasks
8nevil8
approved these changes
Sep 18, 2026
Contributor
There was a problem hiding this comment.
Manual Philips-tenant testing:
- VS Code Copilot BYOK: ✅
- Claude Desktop: ✅
- VS Code Claude Code extension: Configuration succeeds ☑️, but chat requests fail ❌
VS Code Claude extension issue:
- Philips CodeMie tenant accepts: claude-5-opus (similar for other Claude models)
- VS Code Claude Code extension sends: claude-opus-5
The current --vscode-claude-code connector configures only ANTHROPIC_BASE_URL and ANTHROPIC_AUTH_TOKEN; it does not make the extension’s model catalog tenant-aware or translate canonical model IDs to tenant-specific IDs.
This branch has not been deployed
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
codemie proxy connectbroke on any tenant whose model catalog doesn't follow EPAM's naming convention (surfaced live on a customer call). Three connectors — VS Code Copilot BYOK, Claude Desktop, and VS Code Claude Code — each hardcoded assumptions about model-id shape or format that only held for EPAM's own tenant. Ref: EPMCDME-15073.Supersedes #566, closed by an accidental branch rename (
feature/philips-tenant-model-catalog→feature/tenant-model-catalog, to remove the client name from the branch) — the rename deleted the old ref and GitHub auto-closed the PR instead of migrating it, and the closed PR could not be reopened once its head ref was gone. Same branch content, continued from there.Changes
vscode.ts,vscode-models.ts, newtenant-catalog.ts): replaced the static 25-model hardcoded list with a capability table intersected against the tenant's liveGET /v1/llm_modelscatalog at connect time; writes the tenant's own model identifier verbatim.desktop.ts, newmodel-name-resolver.ts): preferred-model resolution now handles both EPAM'sclaude-<family>-<version>and version-first (claude-<version>-<family>) naming, plus undated ids and vendor-prefixed ids (e.g.openai.gpt-...), instead of only appending suffixes.vscode-claude-code.ts): switched from strictJSON.parse/JSON.stringifytojsonc-parser, so asettings.jsonwith comments or trailing commas parses correctly and the write preserves the file's existing formatting instead of being silently skipped.github-copilot-*deployments are explicitly excluded from both the VS Code Copilot BYOK picker and Claude Desktop (product decision, documented inspec.md).codex-model-resolver.tsis untouched.Full design rationale, acceptance criteria, and non-goals are in
docs/superpowers/tasks/2026-09-17-tenant-model-catalog/spec.mdandplan.md(committed on this branch), produced by ansdlc-autonomousrun with a full code-review cycle (initial round: 7 findings incl. 1 critical, all fixed and independently re-verified in a check round; two additional findings surfaced by a stray duplicate review round were fixed and verified separately, seecode-review-final.json).Testing
npx vitest run— full suite green.npm run typecheck/npm run lint— clean.spec.md's open risks).Checklist
npm run ci) locally viaqa-gatesmainX-CodeMie-*attribution header, the Responses APIuserfield, or JWT claim overrides — confirmed, out of scope for this change.