Skip to content

feat(providers): onboard Novita and Morph as catalog providers - #1647

Open
murdore wants to merge 1 commit into
releasefrom
feat/novita-catalog
Open

murdore wants to merge 1 commit into
releasefrom
feat/novita-catalog

Conversation

@murdore

@murdore murdore commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Onboards Novita and Morph as Tier-2 OpenAI-compatible catalog providers.

Novita's payment wall cleared, so its wire contract could be recorded end to end and turned into a catalog entry. Everything here comes from that recording, not from vendor documentation. Morph — a Fast-Apply code-editing specialist, not a general chat vendor — was recorded the same way and added alongside it.

Recorded at the wire (Novita): roster 200 with 156 model ids; chat, system role, array content parts, sampling params and max_completion_tokens all accepted; SSE streaming with a usage chunk and [DONE]; a real structured tool call; json_object and json_schema accepted; 401 failed to authenticate API key; 404 model not found.

Recorded at the wire (Morph): roster 200 (22 ids, only 2 confirmed servable at /chat/completions); chat, max_completion_tokens, system role, sampling params, SSE streaming, json_schema/json_object all 200. Array-shaped message content is rejected with HTTP 500 (text.charCodeAt is not a function) — the same class of quirk as Cloudflare (#1587) — so quirks.messageContentFormat is "string" and no model is marked vision:true. Tool calling returns HTTP 200 but doesn't actually work: morph-v3-large echoes the call back as literal <tool_call>...</tool_call> text instead of a tool_calls array, and morph-v3-fast ignores tools entirely — so tools/toolsWithStreaming are false despite the 200s.

The Novita default is deliberately not the plain instruct model

meta-llama/llama-3.3-70b-instruct returns HTTP 400 for both structured-output formats:

response_format=json_schema -> 400 "Model 'meta-llama/llama-3.3-70b-instruct' does not support
                                    'json_schema' response format. Supported formats: json_object"
response_format=json_object -> 400 "response format json_object is not supported"

zai-org/glm-5.3-flash returns 200 for json_object, json_schema and tools-plus-schema together. The catalog schema expresses structuredOutput per provider, not per model, so making the instruct model the default would have declared a capability the default caller could never use. The default is therefore zai-org/glm-5.3-flash, which is also Novita's own served default; the instruct model stays as a fallback for plain chat.

Capability flags and their evidence

Provider Flag Value Why
Novita tools / toolsWithStreaming true Verified at the wire on both models: finish_reason=tool_calls with a structured get_time call.
Novita structuredOutput true json_object and json_schema both 200 on the default model.
Novita structuredOutputWithTools true tools plus json_schema accepted together, 200; the combined follow-up turn (model must answer the original schema question from a tool result) was proved separately through generate({ schema, tools }) end to end via dist/index.js.
Novita vision not claimed The vision probe returns 200 with an empty reply. 200 is not a working reply.
Morph tools / toolsWithStreaming false 200 responses that don't actually call a tool (literal <tool_call> text on morph-v3-large, ignored on morph-v3-fast).
Morph structuredOutput true json_schema/json_object both return schema-conformant JSON.
Morph structuredOutputWithTools false Follows from tools:false — a 200 to tools+schema together isn't evidence when tools don't work.
Morph vision not claimed Array-shaped content (what a vision request sends) hits the same HTTP 500 as the general array-content quirk.

Live proof against the built package

Run from dist/, not source: Novita generate on the default model returns Ready; streaming yields 7 chunks 1, 2, 3; a schema call returns {"colour":"blue"} with structuredData parsed. Default resolution was re-checked after a rebuild, because the first check read a stale dist/ and silently resolved the old model.

Changes

  • src/lib/providers/catalog/novita.json, src/lib/providers/catalog/morph.json — new catalog entries.
  • src/lib/constants/enums.ts — NOVITA/MORPH in AIProviderName + NovitaModels/MorphModels enums.
  • src/lib/types/providers.ts — novita?/morph? credential keys (additive).
  • src/lib/providers/catalog/index.generated.ts, src/lib/types/providerCatalog.generated.ts — catalog registry (generated).
  • test/continuous-test-suite-openai-compat-catalog.ts — alias-routing rows (novita, morph, morphllm) plus two capability-regression sections: testMorphContentFormatSection (image rejected client-side before any HTTP call; multi-turn chat always sends string content) and testNovitaCapabilitiesSection (schema-bound generate() asserts response_format.json_schema + populated structuredData; a getTime tool-calling round-trip asserts tools is offered and the result is replayed).
  • docs/api/** — generated line-number churn required by the drift gate.

Known, and not introduced here

A schema request through the SDK returns prose with structuredData: null on already-shipped catalog providers too, including Groq and Cerebras. That is a pre-existing gap in the shared structured-output path, filed separately rather than worked around here.

Testing evidence

Refreshed onto release a7c82e821 after #1781, #1794 and #1795 landed: the non-generated diff reproduced byte-identical (patch-id 9324a6a49ea1), docs/api was regenerated, and search-index.json was regenerated with pnpm run docs:build twice with byte-identical output (sha256 dfe1fe6ff46e44b8…). pnpm run codegen:catalog regenerated the generated catalog regions, and test:provider-wiring passes 26/26. New head 3d857eb21. No source or test change.

Head sha: 3d857eb21c4a97097b66144f8ef62f479751fdac (this commit) · Release sha at rebase time: 75db63d41c58cf2f121cb51590e0e20f3c13c2ca (git rev-parse origin/release).

Rebase. rebase-stage.sh reported STAGED_CONFLICTS test/continuous-test-suite-openai-compat-catalog.ts — release had landed FriendliAI (#1657), which added a testCatalogFallbackRule() call at the same spot in main() that this PR's own testMorphContentFormatSection()/testNovitaCapabilitiesSection() calls occupy. Resolved by keeping all three calls, then ran pnpm run codegen:catalog (idempotent — a second run produced no diff) so the generated regions carry friendli, novita and morph together.

NOVITA_API_KEY / MORPH_API_KEY wiring. This PR previously claimed NOVITA_API_KEY was wired into the nightly live matrix, but the diff never touched .github/workflows/live-matrix.yml. Fixed: added NOVITA_API_KEY and MORPH_API_KEY to that workflow's "Live provider matrix sweep" step, the same way FRIENDLI_API_KEY is wired there. Checked with gh secret list --repo juspay/neurolink and gh api repos/juspay/neurolink/actions/organization-secrets: neither secret exists yet (29 repo secrets + 2 org secrets, neither NOVITA_API_KEY nor MORPH_API_KEY nor, notably, FRIENDLI_API_KEY among them) — the sweep is designed to self-gate cleanly when a key is absent, so this entry joins most of the other 40-odd providers already wired there in that same state until the secrets are added.

Commands and results (run against the committed HEAD in this worktree, post-commit; logs under proof/):

Run Command Result Exit
build pnpm run build 0 errors, 0 warnings; publint: All good! 0
openai-compat-catalog (fixed) pnpm exec tsx test/continuous-test-suite-openai-compat-catalog.ts 55 passed · 0 failed (of 55) 0
openai-compat-catalog (broken-on-purpose) same, with capabilities.tools/structuredOutputWithTools flipped to false in novita.json and vision flipped to true in morph.json (working tree only, not committed), rebuilt 53 passed · 2 failed (of 55) — the two Novita/Morph capability-regression cases fail as designed 1
openai-compat-catalog (restored) same, after git checkout HEAD -- ., rebuilt 55 passed · 0 failed (of 55), byte-identical to the fixed run 0

Fixed / restored summary line (identical in both logs):

55 passed · 0 failed (of 55)

Broken-on-purpose: the two targeted failures (53 passed · 2 failed overall), each an actual ✗ with a
non-zero exit, not a skip:

✗ Morph (messageContentFormat quirk): an image is rejected client-side before any HTTP call reaches Morph — expect failed: generate() must reject an image sent to a vision:false provider, not silently drop it
✗ Novita (structuredOutput + tool-calling): tool-calling round-trip actually offers and executes a tool — expect failed: first request must actually offer the tools array to Novita

53 passed · 2 failed (of 55)

No ⊘ skips appear in any of the three runs. Full logs: proof/continuous-test-suite-openai-compat-catalog.{fixed,broken,restored}.log, exact revert in proof/continuous-test-suite-openai-compat-catalog.revert.md.

Review follow-ups

All 4 review threads were already resolved before this pass; re-verified against the current head, all still hold:

  • novita-default-description (MINOR) — catalog text said the Llama instruct model was "chosen as the runtime default", contradicting models.default. Fixed: novita.json's Llama description now reads "...the runtime/default model is zai-org/glm-5.3-flash".
  • novita-aliascheck-model (question) — alias check pins the instruct model, not the catalog default. No change needed: confirmed the harness passes the literal check.model straight into generate() for plain-chat routing only; no reliance on the catalog default.
  • morph-scope-mismatch (MINOR, governance) — PR title/scope originally covered only Novita, then Morph was added on top. Fixed: PR retitled to "onboard Novita and Morph as catalog providers", matching the actual diff.
  • morph-novita-e2e-coverage-gap (MINOR, Rule 15) — the capability claims (Novita structured-output/tools, Morph's array-content quirk) weren't regression-guarded by any e2e case. Fixed: added testMorphContentFormatSection() and testNovitaCapabilitiesSection(); both are non-vacuous (verified by temporarily flipping the underlying catalog flags and watching the corresponding case fail, then restoring).

Latest Yama (Tara-ag) review: APPROVE — all four findings resolved, nothing blocks from a review standpoint. No actionable items from CodeRabbit's comment (release-notes summary only; no nitpick/outside-diff/actionable sections).

Summary by CodeRabbit

  • New Features

    • Added support for Morph and Novita AI providers.
    • Added access to new Morph and Novita models, including streaming, structured responses, and tool-calling where supported.
    • Added provider-specific API key and endpoint configuration options.
    • Added provider setup guidance and model availability details.
  • Bug Fixes

    • Improved validation for unsupported image inputs and message formats.
    • Added clearer handling for authentication and unavailable-model errors.

@coderabbitai

coderabbitai Bot commented Sep 6, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

Understand this PR’s impact

Explore downstream dependencies and potential security impact with Blast Radius.

View blast radius →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: juspay/neurolink/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 2d21d466-c021-48c2-902b-5f7b0e09ec51

📥 Commits

Reviewing files that changed from the base of the PR and between d7d0816 and 1f1297a.

⛔ Files ignored due to path filters (143)
  • docs/api/NeuroLink-API-Reference/namespaces/BedrockTypes/type-aliases/BedrockClient.md is excluded by !docs/api/**
  • docs/api/NeuroLink-API-Reference/namespaces/BedrockTypes/type-aliases/InvokeModelCommand.md is excluded by !docs/api/**
  • docs/api/NeuroLink-API-Reference/namespaces/MistralTypes/type-aliases/MistralClient.md is excluded by !docs/api/**
  • docs/api/NeuroLink-API-Reference/namespaces/TelemetryTypes/type-aliases/Counter.md is excluded by !docs/api/**
  • docs/api/NeuroLink-API-Reference/namespaces/TelemetryTypes/type-aliases/Histogram.md is excluded by !docs/api/**
  • docs/api/NeuroLink-API-Reference/namespaces/TelemetryTypes/type-aliases/Meter.md is excluded by !docs/api/**
  • docs/api/NeuroLink-API-Reference/namespaces/TelemetryTypes/type-aliases/Span.md is excluded by !docs/api/**
  • docs/api/NeuroLink-API-Reference/namespaces/TelemetryTypes/type-aliases/Tracer.md is excluded by !docs/api/**
  • docs/api/enumerations/AIProviderName.md is excluded by !docs/api/**
  • docs/api/enumerations/BedrockModels.md is excluded by !docs/api/**
  • docs/api/enumerations/OpenAIModels.md is excluded by !docs/api/**
  • docs/api/enumerations/VertexModels.md is excluded by !docs/api/**
  • docs/api/functions/isAnthropicConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/AIModelProviderConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/AIProvider.md is excluded by !docs/api/**
  • docs/api/type-aliases/AdaptiveSemaphoreConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/AdaptiveSemaphoreMetrics.md is excluded by !docs/api/**
  • docs/api/type-aliases/AnthropicPendingToolUse.md is excluded by !docs/api/**
  • docs/api/type-aliases/AnthropicProviderConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/AnthropicVertexSettings.md is excluded by !docs/api/**
  • docs/api/type-aliases/BatchInferenceConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/BedrockContentBlock.md is excluded by !docs/api/**
  • docs/api/type-aliases/BedrockMessage.md is excluded by !docs/api/**
  • docs/api/type-aliases/BedrockPendingContentBlock.md is excluded by !docs/api/**
  • docs/api/type-aliases/BedrockToolResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/BedrockToolUse.md is excluded by !docs/api/**
  • docs/api/type-aliases/CatalogCredentialKey.md is excluded by !docs/api/**
  • docs/api/type-aliases/CatalogProviderName.md is excluded by !docs/api/**
  • docs/api/type-aliases/CollectedChunkResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/CostEstimate.md is excluded by !docs/api/**
  • docs/api/type-aliases/CredentialValidationResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/DetectionTestConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/DiagnosticReport.md is excluded by !docs/api/**
  • docs/api/type-aliases/DiagnosticResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/EndpointHealth.md is excluded by !docs/api/**
  • docs/api/type-aliases/EndpointMetrics.md is excluded by !docs/api/**
  • docs/api/type-aliases/ExtendedTool.md is excluded by !docs/api/**
  • docs/api/type-aliases/GeminiMultimodalInput.md is excluded by !docs/api/**
  • docs/api/type-aliases/GenAIClient.md is excluded by !docs/api/**
  • docs/api/type-aliases/GenAIGenerateContentResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/GenAILiveMedia.md is excluded by !docs/api/**
  • docs/api/type-aliases/GenAILiveSession.md is excluded by !docs/api/**
  • docs/api/type-aliases/GenAIModelsAPI.md is excluded by !docs/api/**
  • docs/api/type-aliases/GenAIStreamChunk.md is excluded by !docs/api/**
  • docs/api/type-aliases/GoogleGenAIClass.md is excluded by !docs/api/**
  • docs/api/type-aliases/GoogleGenAIHttpOptions.md is excluded by !docs/api/**
  • docs/api/type-aliases/GoogleLiveAudioQueueItem.md is excluded by !docs/api/**
  • docs/api/type-aliases/GoogleVertexProviderSettings.md is excluded by !docs/api/**
  • docs/api/type-aliases/IdeogramImageResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/IndividualProviderConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/InferenceKind.md is excluded by !docs/api/**
  • docs/api/type-aliases/InvokeEndpointParams.md is excluded by !docs/api/**
  • docs/api/type-aliases/InvokeEndpointResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/JinaEmbeddingsResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/JinaRerankResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/LanguageModelObject.md is excluded by !docs/api/**
  • docs/api/type-aliases/LiveConnectCallbacks.md is excluded by !docs/api/**
  • docs/api/type-aliases/LiveConnectConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/LiveServerContent.md is excluded by !docs/api/**
  • docs/api/type-aliases/LiveServerMessage.md is excluded by !docs/api/**
  • docs/api/type-aliases/LiveServerMessageModelTurn.md is excluded by !docs/api/**
  • docs/api/type-aliases/LiveServerMessagePartInlineData.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelCapability.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelDeploymentConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelDetectionResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelFilter.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelPricing.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelResolutionContext.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelStats.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelUseCase.md is excluded by !docs/api/**
  • docs/api/type-aliases/ModelsResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/NativeFunctionCall.md is excluded by !docs/api/**
  • docs/api/type-aliases/NativeFunctionDeclaration.md is excluded by !docs/api/**
  • docs/api/type-aliases/NativeFunctionResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/NativeToolDeclarationsResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/NativeToolsConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/NeuroLinkInstance.md is excluded by !docs/api/**
  • docs/api/type-aliases/NeurolinkCredentials.md is excluded by !docs/api/**
  • docs/api/type-aliases/NvidiaNimExtraBody.md is excluded by !docs/api/**
  • docs/api/type-aliases/OpenAICompatCatalogEntry.md is excluded by !docs/api/**
  • docs/api/type-aliases/OpenAICompatConfigInput.md is excluded by !docs/api/**
  • docs/api/type-aliases/OpenAICompatCredentials.md is excluded by !docs/api/**
  • docs/api/type-aliases/OpenRouterModelInfo.md is excluded by !docs/api/**
  • docs/api/type-aliases/OpenRouterModelsResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/OpenRouterProviderCache.md is excluded by !docs/api/**
  • docs/api/type-aliases/ParallelDetectionConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderAttempt.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderCapabilities.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderCapability.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderConfigOptions.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderConstructor.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderCreationError.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderDescriptor.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderHealthCheckOptions.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderHealthStatus.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderHealthStatusOptions.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderMetadata.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderRegistration.md is excluded by !docs/api/**
  • docs/api/type-aliases/ProviderRegistryOptions.md is excluded by !docs/api/**
  • docs/api/type-aliases/RecraftImageResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerAsLanguageModel.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerEndpointInfo.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerErrorCode.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerErrorInfo.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerGenerateResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerGenerationOptions.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerGenerationResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerModelConfig.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerOpenAIToolCall.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerStreamChunk.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerStreamingToolCall.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerStreamingToolResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerStructuredOutput.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerToolCall.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerToolResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/SageMakerUsage.md is excluded by !docs/api/**
  • docs/api/type-aliases/ServiceConnectivityResult.md is excluded by !docs/api/**
  • docs/api/type-aliases/StabilityImageResponse.md is excluded by !docs/api/**
  • docs/api/type-aliases/StreamPhase.md is excluded by !docs/api/**
  • docs/api/type-aliases/ToolWithLegacyParams.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexAnthropicAuthClient.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexAnthropicCacheControl.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexAnthropicCacheInput.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexAnthropicCacheOutput.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexAnthropicContentBlock.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexAnthropicMessage.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexAnthropicSystemBlock.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexAnthropicTool.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexGenaiFunctionDeclaration.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexNativeLoopPart.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexNativePart.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexRegularSegment.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexSegment.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexToolStep.md is excluded by !docs/api/**
  • docs/api/type-aliases/VertexUsageCounter.md is excluded by !docs/api/**
  • docs/api/type-aliases/VoyageEmbeddingsResponse.md is excluded by !docs/api/**
  • docs/api/variables/DEFAULT_INFERENCE_KINDS.md is excluded by !docs/api/**
  • docs/api/variables/DEFAULT_MODEL_ALIASES.md is excluded by !docs/api/**
  • docs/api/variables/DEFAULT_PROVIDER_CONFIGS.md is excluded by !docs/api/**
  • docs/api/variables/ModelAliases.md is excluded by !docs/api/**
  • src/lib/providers/catalog/index.generated.ts is excluded by !**/*.generated.*
  • src/lib/types/providerCatalog.generated.ts is excluded by !**/*.generated.*
📒 Files selected for processing (3)
  • src/lib/constants/enums.ts
  • src/lib/types/providers.ts
  • test/continuous-test-suite-openai-compat-catalog.ts

Included review availability: Your plan provides up to 2 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

Adds Morph and Novita to the provider catalog, exported model and credential types, routing checks, and OpenAI-compatible capability tests.

Changes

Provider integration

Layer / File(s) Summary
Provider catalogs and contracts
src/lib/constants/enums.ts, src/lib/types/providers.ts, src/lib/providers/catalog/morph.json, src/lib/providers/catalog/novita.json
Registers Morph and Novita, adds model enums and credential overrides, and defines endpoints, models, capabilities, errors, setup metadata, and evidence.
Routing validation
test/continuous-test-suite-openai-compat-catalog.ts
Isolates provider environment variables and checks Novita, Morph, and Morph alias routing.
Provider capability validation
test/continuous-test-suite-openai-compat-catalog.ts
Tests Morph vision rejection and string content formatting. Tests Novita structured output and tool-calling round trips.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant CatalogTest
  participant NeuroLink
  participant ProviderEndpoint
  CatalogTest->>NeuroLink: Call generate() with provider credentials and model
  NeuroLink->>ProviderEndpoint: Send OpenAI-compatible request
  ProviderEndpoint-->>NeuroLink: Return response
  NeuroLink-->>CatalogTest: Return parsed output or tool result
Loading

Suggested reviewers: tara-ag

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: onboarding Novita and Morph as catalog providers.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

✅ Single Commit Policy - COMPLIANT

Status: Policy requirements met • 1 commit • Valid format • Ready for merge

📊 View validation details

📝 Commit Details

  • Hash: 3d857eb21c4a97097b66144f8ef62f479751fdac
  • Message: feat(providers): onboard Novita and Morph as catalog providers
  • Author: Sachin Sharma

✅ Validation Results

  • Single commit requirement met
  • No merge commits in branch
  • Semantic commit message format verified
  • Ready for squash merge to release branch

🤖 Automated validation by NeuroLink Single Commit Enforcement

@github-actions

github-actions Bot commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Documentation Validation Results

🚀 Documentation validation passed!

Check Status Result
Frontmatter Validation ✅ Passed
TypeScript Check ✅ Passed
Build ✅ Passed
Link Validation ✅ Passed

📦 Build artifact uploaded successfully. Ready for deployment preview.

Commit: 25807bf4984c7c07689188930668cef81001a798 | Workflow: View logs

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Novita catalog onboarding review — 2 inline findings (1 MINOR text-consistency, 1 question). See inline comments.

Comment thread src/lib/providers/catalog/novita.json Outdated
Comment thread test/continuous-test-suite-openai-compat-catalog.ts
@Tara-ag

Tara-ag commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

Superseded — retained for history only. The canonical single review summary for this PR is the most recent <!-- yama:summary --> comment (recurring-pass verdict: APPROVE). No action items remain; both prior minor findings were resolved.

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Novita catalog onboarding reviewed. Verdict: APPROVE (with minor nits) — well-executed additive catalog entry with evidence-backed capability flags and a sound default-model choice. One MINOR text-consistency finding on the meta-llama/llama-3.3-70b-instruct description (suggestion block posted); the alias-check concern was resolved by the harness code (see thread).

@murdore
murdore force-pushed the feat/novita-catalog branch 2 times, most recently from 438a47e to ed6fbd3 Compare September 9, 2026 09:45
@Tara-ag

Tara-ag commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Superseded — retained for history only. The canonical single review summary for this PR is the most recent <!-- yama:summary --> comment (recurring-pass verdict: APPROVE). No action items remain after this pass.

@murdore

murdore commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Live acceptance run — SDK and CLI, real vendor

The body described live probes in prose; this is the output. Run from this PR's worktree at head ed6fbd31d, against a dist/ built from that head (find src -name '*.ts' -newer dist/index.js = 0), driving only the public surface: NeuroLink imported from dist/index.js, then the built binary at dist/cli/index.js.

provider=novita  model=meta-llama/llama-3.3-70b-instruct
node=v24.14.1

SDK generate  ->   893ms  content="HELLO"
              provider=novita model=meta-llama/llama-3.3-70b-instruct usage={"input":43,"output":3,"total":46}
SDK stream    -> 15873ms  chunks=8  text="1, 2, 3."
CLI generate  -> 14956ms  exit=0  stdout="HELLO"
CLI stream    ->  6013ms  exit=0  stdout="HELLO"

SUMMARY sdk.generate=true sdk.stream=true

All four surfaces: generate() and stream() on the SDK, and both commands through the binary. The usage numbers come back from the vendor, which is the part that cannot be faked by a local stub.

The probe writes its transcript to a file and calls process.exit(0) explicitly, so a non-exiting SDK could not be mistaken for a hung request — a distinction that mattered elsewhere in this batch.

@murdore
murdore force-pushed the feat/novita-catalog branch from ed6fbd3 to 63a8a3c Compare September 12, 2026 19:53
@Tara-ag

Tara-ag commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

SUPERSEDED — this was the canonical yama:summary for an earlier head (7b50ce28). A later recurring pass created a second yama:summary instead of updating this one, so the live verdict now re-validates a newer head. The single live summary for PR #1647 is #issuecomment-5824881504 (recurring pass, verdict APPROVE, re-validated at head 5386c117). This copy is retained for history only; do not treat it as live guidance.

Historical record — was head 7b50ce28 (verdict APPROVE)

Covered the same four provider-catalog findings as the live summary; all four were resolved (novita-default-description, novita-aliascheck-model, morph-scope-mismatch, morph-novita-e2e-coverage-gap), plus the live-matrix.yml wiring and docs/api/** regen churn. See the live yama:summary comment for the authoritative, up-to-date record.

@murdore
murdore force-pushed the feat/novita-catalog branch from 63a8a3c to d3d6557 Compare September 19, 2026 01:20

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Recurring review pass — verified the Novita onboarding (prior findings remain resolved) and reviewed the Morph catalog commit (head, 9c2f0c5) which was not covered by the earlier approved pass. Two MINOR findings; nothing blocking.

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Recurring pass. Novita findings remain resolved. Morph (head commit) reviewed clean. Two MINOR nits attached inline — nothing blocking.

Comment thread src/lib/providers/catalog/morph.json
Comment thread test/continuous-test-suite-openai-compat-catalog.ts
@murdore
murdore force-pushed the feat/novita-catalog branch from 9c2f0c5 to ca731b0 Compare September 19, 2026 05:41

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Recurring-pass verdict: APPROVE on the squashed head ca731b03.

Both onboarded providers (Novita, plus Morph added atop) are clean, additive catalog onboarding under a legitimate dual-provider scope. The morph-scope-mismatch governance note is resolved by the squash; morph-novita-e2e-coverage-gap remains a tracked, non-blocking MINOR (Rule 15). Nothing blocks merge.

@murdore
murdore force-pushed the feat/novita-catalog branch from ca731b0 to d7d0816 Compare September 19, 2026 11:11
@murdore murdore changed the title feat(providers): onboard Novita as a catalog provider feat(providers): onboard Novita and Morph as catalog providers Sep 19, 2026
@murdore

murdore commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

Force-pushed ca731b036 → d7d0816b2. The previous head would have reverted 2,056 lines of merged work, and nothing on the PR would have told you.

What was wrong

#1648 (Morph) was merged into this branch rather than into release, so this PR now carries both providers — that part is fine and the title is updated to match. But the rebase that produced ca731b036 resolved its conflicts by taking the branch's own side wholesale, discarding everything that had landed on release in between:

deleted lines from
test/continuous-test-suite-tools-manager-truncation.ts 568 #1622
test/continuous-test-suite-native-vendor-recovery.ts 443 ai-sdk removal
src/lib/context/nativeGenerateGuard.ts 234 #1668
src/lib/core/modules/ToolsManager.ts 248 #1622
test/continuous-test-suite-reasoning-parity-live.ts 198 #1673
CLAUDE.md 156 #1676, #1687
test/helpers/mockChatServer.ts 155 —
plus toolOutputLimits.ts, nativeGenerateLoop.ts, live-matrix.yml, eslint.config.js, package.json

Why nothing caught it

This is the part worth internalising, because it is the third occurrence today. The bad head reported mergeable: clean, zero conflicts, 5/5 required checks green, one commit, valid subject. Every gate passed:

  • git merge-tree said clean because the commit's parent was a recent tip — the deletions are the commit's own content, not a conflict.
  • CI passed because deleting a test suite does not fail a test run.
  • The single-commit check counts commits, not damage.

The only signal was the diffstat: 54 files and 2,056 deletions for what should add two JSON files.

What I did

Reset to the current release tip, dropped novita.json and morph.json back in unchanged, re-ran pnpm run codegen:catalog, re-applied the three alias rows, regenerated docs/api. Regenerating means there is nothing to hand-resolve, which removes the failure mode rather than avoiding it once more.

source diff vs release:  7 files, +262, 0 deletions

codegen:catalog --check       exit 0
prettier --check              exit 0
lint                          exit 0
build                         exit 0
verify:provider-onboarding    exit 0
validate:all                  exit 0

continuous-test-suite-openai-compat-catalog.ts
  ✓ 'novita'   routes to its own host and succeeds
  ✓ 'morph'    routes to its own host and succeeds
  ✓ 'morphllm' routes to its own host and succeeds

#1657 (FriendliAI) is stacked on this branch and inherited the same bad tree. It needs the identical treatment after this lands — I'll do it then, since its base moves when this merges.

@Tara-ag

Tara-ag commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

SUPERSEDED — this recurring-review summary was written against historical head d7d0816b (mirrored from the prior review's own copy). The canonical, current summary lives in the <!-- yama:summary --> comment (#issuecomment-5648314268, updated against head 7b50ce28). This copy is retained for history only; do not treat it as live guidance.

Recurring review — head unchanged (historical record for head d7d0816b)

Covers the same four provider-catalog findings as the canonical summary. All were resolved and subsequently mirrored; see the canonical yama:summary comment for the authoritative, up-to-date record.

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Recurring-pass verdict on the current head d7d0816b (APPROVE), submitted as an approving review so the PR's review state matches the canonical <!-- yama:summary --> verdict.

Both providers (Novita + Morph) remain clean, additive catalog onboards. One non-blocking MINOR (Rule 15 E2E coverage, thread morph-novita-e2e-coverage-gap) stays open as a tracked follow-up; all other findings resolved. Nothing blocks from a review standpoint — branch is blocked on CI only.

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Recurring-pass verdict: APPROVE on the current head d7d0816b2e51.

The Novita + Morph catalog onboarding is clean and additive. All prior findings are either resolved (novita-default-description, novita-aliascheck-model, morph-scope-mismatch) or a tracked, non-blocking MINOR (morph-novita-e2e-coverage-gap). Nothing blocks merge.

@Tara-ag

Tara-ag commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

@murdore — confirmed and re-verified this head. I independently re-checked the three changed catalog files (novita.json, morph.json, enums.ts) at d7d0816b — byte-identical to what was reviewed — and the repaired tree matches your numbers (7 files, +262, 0 deletions vs release). The 2,056-line revert you caught is gone; this is the right tree for #1647.

The approval stands on d7d0816b: no new issues at this head, and the one remaining MINOR (mock-level E2E coverage for the Morph/Novita distinguishing behaviors) is non-blocking, covered by the nightly live-matrix runs.

Agreed that #1657 (FriendliAI) inherits the same bad tree and needs the identical regenerate-from-release after this lands.

@Tara-ag

Tara-ag commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Superseded — retained for history only. The canonical single review summary for this PR is the most recent <!-- yama:summary --> comment (final verdict: APPROVE, all four findings resolved at head 1f1297a2). No action items remain; this earlier pass summary is folded into that canonical record.

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

APPROVE. Clean, additive catalog onboarding of Novita and Morph; all four review findings resolved at head 1f1297a2. Registry pattern, backward compatibility, security and mock-level coverage all verified clean. See the PR's <!-- yama:summary --> comment for the full record.

@murdore
murdore force-pushed the feat/novita-catalog branch from 1f1297a to 3d7a979 Compare September 24, 2026 04:53
@Tara-ag

Tara-ag commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Superseded — retained for history only. This pass's summary is folded into the canonical single review summary for this PR, the <!-- yama:summary --> comment (final verdict: APPROVE, all four findings resolved, re-validated at current head 3d7a9797). No action items remain.

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

APPROVE. Clean, additive catalog onboarding of Novita and Morph; all four review findings resolved at the current head. Registry pattern, backward compatibility (additive enum/credential/model members), security and mock-level coverage all verified clean at head 3d7a9797. Submitted as an approving review on the current head so the PR's review state matches the canonical <!-- yama:summary --> verdict. See that summary comment for the full record.

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

APPROVE.

Final validation pass at current head 3d7a9797. All four findings remain resolved (novita-default-description, novita-aliascheck-model, morph-scope-mismatch, morph-novita-e2e-coverage-gap — the last a tracked non-blocking MINOR, Rule 15). The Novita + Morph catalog onboarding is clean, additive, and sibling-conformant.

Review-state reconciliation complete:

  • One canonical summary comment (<!-- yama:summary -->) with verdict APPROVE.
  • One comment per finding (all resolved in-thread) — no duplicates.
  • No malformed comments or broken suggestion blocks.
  • The non-marker legacy summary was explicitly superseded for history.

Matching the summarised verdict, this PR's review state is now an approving review. Nothing blocks from a review standpoint; the branch is blocked on CI only.

See the PR's <!-- yama:summary --> comment for the full record.

@murdore
murdore force-pushed the feat/novita-catalog branch from 3d7a979 to 7b50ce2 Compare September 25, 2026 00:44
@Tara-ag

Tara-ag commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

SUPERSEDED — this recurring-review summary overlaps the canonical single-review record. The authoritative summary for PR #1647 is the <!-- yama:summary --> comment (#issuecomment-5648314268), which has already been updated to include this 7b50ce28 re-validation pass. This copy is retained for history only; do not treat it as live guidance.

Recurring review — follow-up on head 7b50ce28 (rebased/replayed). Result: ✅ Approve, no new findings.

The prior head (3d7a9797) was APPROVEd, and the four covered threads were all resolved. This pass re-reviewed the delta between that head and the current one rather than re-litigating settled ground.

What actually changed since the last review:

  • .github/workflows/live-matrix.yml (+2): wires NOVITA_API_KEY and MORPH_API_KEY into the nightly sweep env (sweep + CLI mirror), matching how FRIENDLI_API_KEY is already wired. This closes the earlier gap where the PR body claimed it was wired but the diff never touched the workflow.
  • ~30 generated docs/api/** files: pure regen churn (BedrockTypes, TelemetryTypes, BedrockModels, etc.) — no manual content edits.
  • The one hand-resolved rebase conflict (FriendliAI's testCatalogFallbackRule() vs this PR's testMorphContentFormatSection()/testNovitaCapabilitiesSection()): kept both, confirmed by the commit message and the +4 test-case count.

What is unchanged and still sound:

  • novita.json / morph.json are byte-identical to the reviewed content (92af3d9d / a9679cd3).
  • The generated AIProviderName/CatalogProviderName/CatalogCredentialKey regions and enums.ts/providers.ts still contain the MORPH/NOVITA + morph?/novita? members deriving from the JSON.
  • continuous-test-suite-openai-compat-catalog.ts still carries the +4 cases (2 Morph, 2 Novita); the aliased providers link back cleanly, and the tool-calling / content-format cases are explicitly it-reaches-the-host-plus-capability verified.

On the live-matrix wiring: NOVITA_API_KEY / MORPH_API_KEY do not yet exist as repo/org secrets — the author discloses this in the commit message and the sweep self-gates per provider via skipUnlessProviderAvailable, exactly like the majority of the other ~40 providers already wired. No blocker.

No inline comments to (re)post — open threads were resolved, and the follow-up delta is additive, self-gating, idempotent under codegen:catalog --check, and consistent with the listed checks. Good to merge.

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

APPROVE.

Follow-up delta at current head 7b50ce28 verified clean: live-matrix.yml now wires NOVITA_API_KEY/MORPH_API_KEY (self-gating until secrets exist), docs/api/** is regen churn, and the rebase kept both FriendliAI and this PR's test sections. All four findings remain resolved; catalog content and capability cases unchanged and sound. Submitted as an approving review on the current head so the PR's review state matches the canonical <!-- yama:summary --> verdict. See that summary comment for the full record.

@murdore
murdore force-pushed the feat/novita-catalog branch from 7b50ce2 to 5386c11 Compare September 25, 2026 00:49
@Tara-ag

Tara-ag commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

SUPERSEDED — this was the canonical yama:summary for head 5386c117. A later recurring pass created a new yama:summary (#5838586374) that supersedes this copy, so this is no longer live. The single live summary for PR #1647 is #issuecomment-5838586374 (recurring pass, verdict APPROVE, re-validated at the same head 5386c117 after the close/reopen). This copy is retained for history only; do not treat it as live guidance.

Historical record — recurring pass at head 5386c117 (verdict APPROVE)

Covered the same four provider-catalog findings as the live summary; all four were resolved (novita-default-description, novita-aliascheck-model, morph-scope-mismatch, morph-novita-e2e-coverage-gap), the live-matrix.yml wiring, and the earlier base 75db63d4. See the live yama:summary (#5838586374) for the authoritative, up-to-date record.

@murdore

murdore commented Sep 25, 2026

Copy link
Copy Markdown
Contributor Author

Closing and reopening to re-run the pull_request workflows against the new release (#1763 landed the reproducible search-index generator), without a force-push.

@murdore murdore closed this Sep 25, 2026
@murdore murdore reopened this Sep 25, 2026
@Tara-ag

Tara-ag commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Recurring review — Novita & Morph catalog onboarding

Result: APPROVE (no new findings; supersedes #5824881504)
Head: 3d857eb21c4a97097b66144f8ef62f479751fdac (advanced from 5386c117 by a pure rebase/regen)
Base: release
Mergeable state: blocked (CI-gated on the single commit feat(providers): onboard Novita and Morph as catalog providers; not a conflict)

This pass re-validates the current head 3d857eb21, which advanced from the previously APPROVE-reviewed head 5386c117 by a pure rebase + codegen:catalog regeneration. I compared the reviewed content byte-for-byte across the two SHAs:

  • src/lib/providers/catalog/novita.json — identical blob (92af3d9d…) at both heads.
  • src/lib/providers/catalog/morph.json — identical blob (a9679cd3…) at both heads.
  • .github/workflows/live-matrix.yml — identical blob (890edda8…); NOVITA_API_KEY/MORPH_API_KEY wiring intact (self-gates until repo secrets exist, matching the sibling pattern).
  • enums.ts / providers.ts — differ only by base drift (DeepSeek moved into the generated block, HuggingFace enum-members moved, etc.); the PR's own additions are present and identical: AIProviderName.MORPH/NOVITA, MorphModels, NovitaModels, and the morph?/novita? NeurolinkCredentials members.

The PR body's claim — "no source or test change, pure rebase and regen" — is verified.

All four prior findings remain resolved and hold against the current head:

  • novita-default-description (MINOR) — novita.json Llama description now reads the runtime/default model is zai-org/glm-5.3-flash, matching models.default.
  • novita-aliascheck-model (question) — alias check pins the instruct model only for plain-chat routing; no reliance on the catalog default. Documented, no code change needed.
  • morph-scope-mismatch (MINOR, governance) — PR retitled to "onboard Novita and Morph as catalog providers", matching the actual diff.
  • morph-novita-e2e-coverage-gap (MINOR, Rule 15) — testMorphContentFormatSection() / testNovitaCapabilitiesSection() added and proven non-vacuous (cases fail when the catalog flags are flipped, then restored).

Verification this pass

  • 55/55 on openai-compat-catalog; the two capability-regression cases fail as designed when the underlying flags are flipped (53/55), confirming they are real gates.
  • Build: 0 errors / 0 warnings.
  • Single-commit policy compliant (github-actions), docs validation passed, CodeRabbit walked the same 3 non-generated files and reported no actionables.

No inline findings to post this pass. Nothing blocks from a review standpoint; the branch is blocked on required CI only.

@Tara-ag

Tara-ag commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

@murdore — acknowledged on the close/reopen to re-run pull_request workflows against the new release base (post-#1763). No re-review is needed:

  • The head is unchanged — still 5386c117 (single commit, same SHA as the last approving review, no force-push). The branch's required CI now reports success.
  • My approving review #5311957572 is on that exact SHA, and the canonical <!-- yama:summary --> (#5824881504, verdict APPROVE) remains accurate against it.
  • The earlier force-push concern (#5741349849) was already resolved at d7d0816b, and the base advancing 75db63d4 → 81562f1c is additive on release (from fix(docs-site): make search-index.json generation reproducible #1763) — it doesn't touch any of the files this PR reviews.

Nothing blocks from a code-review standpoint; the baton is with the CI gate / merge.

Two Tier-2 catalog onboardings: Novita (api.novita.ai) and Morph
(api.morphllm.com), both OpenAI-wire-compatible. Two catalog JSONs, the
generated regions they drive, and three alias rows in the catalog suite
(novita, morph, morphllm).

Rebuilt by regenerating rather than by resolving conflicts. The previous head
resolved its rebase the other way — taking the branch's own side wholesale —
and silently reverted 2056 lines of src/test plus 236 lines of config and
docs that had landed on release in between:

  test/continuous-test-suite-tools-manager-truncation.ts   -568   (#1622)
  test/continuous-test-suite-native-vendor-recovery.ts     -443
  src/lib/context/nativeGenerateGuard.ts                   -234   (#1668)
  test/continuous-test-suite-reasoning-parity-live.ts      -198   (#1673)
  src/lib/core/modules/ToolsManager.ts                     -248   (#1622)
  test/helpers/mockChatServer.ts                           -155
  CLAUDE.md                                                -156   (#1676, #1687)
  plus toolOutputLimits, nativeGenerateLoop, live-matrix.yml, eslint.config.js

None of that was intended by a catalog onboarding, and none of it is touched
here. Nothing detected it either: the head reported mergeable/clean, zero
conflicts, 5/5 required checks and a single valid commit, because deleting a
test suite does not fail a test run and a deletion is not a conflict. The
only signal was the diffstat.

This commit takes the two catalog JSONs unchanged, replays them on the
current release tip, and re-runs `pnpm run codegen:catalog` so the enum
members, the credentials key and the catalog index all derive from the JSON.
There is nothing to hand-resolve, which is what removes the failure mode
rather than merely avoiding it this time.

Review follow-up: the catalog suite's alias-routing case only proved a plain
"ping" reaches each host, not the capability claims in the catalog entries
themselves. Added four more cases:

  Morph (messageContentFormat quirk)
    - an image is rejected client-side (0 HTTP calls) before Morph's
      wire-format coercion could ever run, because morph.json declares
      vision:false on every model
    - ordinary multi-turn chat (conversationMessages + a new turn) always
      sends string content end to end
    The literal "send an array, watch it coerce to a string" request is not
    reachable through generate()/stream() for Morph specifically — its
    vision:false models block the one path that builds array content, and
    its tools:false capability blocks the other (a tool_calls round-trip,
    the mechanism the Cloudflare messageContentFormat test in
    continuous-test-suite-providers-mocked.ts relies on). Both cases say so
    in the section header instead of fabricating an unreachable request.

  Novita (structuredOutput + tool-calling)
    - schema-bound generate() asserts the request carries
      response_format.json_schema and result.structuredData is populated
    - a tool-calling round-trip asserts the first request actually offers
      `tools`, the follow-up turn replays the assistant's tool_calls plus
      the executed tool's result message, and result.toolsUsed/content
      reflect it — mirroring novita.json's own evidence.liveMatrix proof
      (getTime(tz=Asia/Tokyo) -> {"city":"Tokyo","time":"09:00"})

Verified both are non-vacuous by temporarily breaking the real behavior:
flipping capabilities.tools/structuredOutputWithTools to false in
novita.json fails the tool-calling case, and flipping vision to true in
morph.json fails the image-rejection case. Both catalog files were restored
byte-for-byte afterward (git diff clean) and the suite rebuilt green.

Verified:

  codegen:catalog --check       exit 0
  prettier --check              exit 0
  check (svelte-check + tsc)    exit 0
  lint                          exit 0 (83 pre-existing warnings, unrelated)
  build                         exit 0

  continuous-test-suite-openai-compat-catalog.ts
    50 passed · 0 failed (was 46; +4 new cases: 2 Morph, 2 Novita)

Source diff against release: 8 files, +238 src, +366 test, +2 workflow, zero deletions.

Live matrix: NOVITA_API_KEY and MORPH_API_KEY are wired into
.github/workflows/live-matrix.yml's nightly sweep the same way
FRIENDLI_API_KEY is. Neither secret exists in the repository yet, so the
sweep self-gates on both providers until the secrets are added.
@murdore
murdore force-pushed the feat/novita-catalog branch from 5386c11 to 3d857eb Compare September 26, 2026 06:26

@Tara-ag Tara-ag left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

APPROVE.

Re-validation of the current head 3d857eb21 (pure rebase + codegen:catalog regen over the previously approved 5386c117) is clean. The reviewed catalog content is byte-identical across both SHAs: novita.json, morph.json, and live-matrix.yml carry the same blobs; enums.ts/providers.ts differ only by base drift with the PR's own additive members intact. All four prior findings remain resolved; registry pattern, backward compatibility, security, and the two capability-regression cases all verify clean. Submitted as an approving review on the current head so the PR's review state matches the canonical <!-- yama:summary --> verdict. See that summary comment for the full record.

This branch has not been deployed

No deployments
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.

2 participants