feat(platform): support provider-qualified model refs#1583
Conversation
📝 WalkthroughWalkthroughThis PR introduces support for provider-qualified model references throughout the platform (e.g., Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/agents/web-assistant.json (1)
1-16:⚠️ Potential issue | 🟡 MinorFix formatting to pass pipeline check.
The pipeline reports a formatting failure from
oxfmt. Run the formatter to fix the file before merging.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/agents/web-assistant.json` around lines 1 - 16, The JSON file "examples/agents/web-assistant.json" failed the oxfmt pipeline check due to formatting; run the project's formatter (oxfmt) on this file and commit the formatted output so keys like "displayName", "systemInstructions", "toolNames" and others are correctly indented and escaped, ensuring valid JSON (no trailing commas or unescaped newlines) and preserving the exact string content (especially the multi-line systemInstructions) before pushing the fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@examples/agents/crm-assistant.json`:
- Around line 5-12: The JSON in examples/agents/crm-assistant.json is not
formatted to the repo's formatter (oxfmt), causing CI to fail; run the formatter
(e.g., oxfmt or your project's format script) to reformat this file and commit
the updated JSON so oxfmt --check passes; focus on formatting the array/object
entries like "toolNames" and "supportedModels" and ensure the committed changes
include only the formatting updates.
In `@examples/agents/image-creator.json`:
- Around line 5-11: The JSON formatting for the object containing the
"integrationBindings" and "supportedModels" keys is not normalized and fails
oxfmt --check; run the repository formatter (oxfmt) against this JSON, update
the file with the normalized output, and commit the formatted JSON so CI passes
(ensure the JSON follows the project's formatter rules and removes any
trailing/extra whitespace or comma issues).
In `@services/platform/app/features/agents/hooks/use-agents-table-config.tsx`:
- Around line 56-58: The Badge rendering can crash when
stripModelRefQualifier(model) throws on malformed refs; update the rendering in
use-agents-table-config.tsx to call stripModelRefQualifier safely by first
validating or try/catching the result and falling back to the original model
string (e.g., use a safeNormalize variable = safe result || model) before
passing into <Badge> so malformed values like ":x" or "x:" do not break row
render; target the return that currently uses stripModelRefQualifier(model) and
ensure a safe fallback is used.
In
`@services/platform/app/features/chat/components/arena/arena-model-selector.tsx`:
- Around line 83-87: The current getDisplayName collapses provider-qualified
refs by stripping qualifiers before lookup; instead, look up modelInfoMap using
the full ref first (use ref directly), fall back to the stripped plain id only
if the full ref is not present, and when constructing the short name use
getModelShortName(ref) (not the stripped plain) so provider qualifiers remain
part of the label; apply the same change to the other lookup at lines referenced
(the similar logic around the other label generation) so qualified model refs
remain disambiguated.
In `@services/platform/convex/agents/config.ts`:
- Around line 79-85: The code matches on stripped ids using
stripModelRefQualifier(modelId) against supportedModels but then sets
config.model = modelId, which can drop provider pinning; change the assignment
to use the actual matched supportedModels entry (the matched "ref" from the
supportedModels.some/iteration) so config.model is set to the provider-qualified
ref instead of the raw modelId, and keep config.fallbackModels = undefined as
before; locate the logic around stripModelRefQualifier, supportedModels,
config.model and replace the modelId assignment with the matched supported ref.
In `@services/platform/convex/agents/unified_chat.ts`:
- Around line 183-190: The call to stripModelRefQualifier(args.modelId) can
throw and prevent rollbackGenerating() from running; wrap the model-ref parsing
in a try/catch (or validate before calling) inside the same control flow that
runs the access check so any parse error will still call
rollbackGenerating(authUserId, threadId or relevant IDs) before
rethrowing/returning an error. Specifically, guard the stripModelRefQualifier
invocation used when calling
internal.governance.internal_queries.checkModelAccessInternal and ensure
rollbackGenerating (the function used later to clear the thread generating
state) is invoked in the catch/finally path so malformed model refs cannot leave
a thread stuck in generating state.
In `@services/platform/convex/providers/file_actions.ts`:
- Around line 369-411: The ambiguity warning in the resolveModelData logic (the
console.warn inside the firstMatch branch that uses firstMatch,
secondaryMatchProviders, and args.providerName) should be returned to callers
rather than only logged; modify the function that returns the model info to
include an optional warnings?: string[] field and, when
secondaryMatchProviders.length > 0 and args.providerName is falsy, push the
existing ambiguity message into that warnings array (instead of only
console.warn), then update callers such as resolveLanguageModelById to accept
and propagate the warnings (just like saveAgent's warnings?: string[]) so
downstream code can surface the warning to users or logs.
In `@services/platform/lib/shared/utils/model-ref.ts`:
- Around line 1-4: The exported interface ParsedModelRef is declared but unused
externally; remove the export to make it internal (or alternatively use it in
callers) so the symbol is no longer an unused export. Concretely, in the
ParsedModelRef declaration remove the "export" modifier (making it "interface
ParsedModelRef { ... }") or replace usages by importing/consuming ParsedModelRef
in the modules that need it; ensure any references to ParsedModelRef in this
module still compile after the change.
---
Outside diff comments:
In `@examples/agents/web-assistant.json`:
- Around line 1-16: The JSON file "examples/agents/web-assistant.json" failed
the oxfmt pipeline check due to formatting; run the project's formatter (oxfmt)
on this file and commit the formatted output so keys like "displayName",
"systemInstructions", "toolNames" and others are correctly indented and escaped,
ensuring valid JSON (no trailing commas or unescaped newlines) and preserving
the exact string content (especially the multi-line systemInstructions) before
pushing the fix.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b472f995-3581-4614-9480-5f149f3d6f0d
📒 Files selected for processing (27)
docs/platform/admin/providers.mdexamples/agents/chat-agent.jsonexamples/agents/crm-assistant.jsonexamples/agents/file-assistant.jsonexamples/agents/image-creator.jsonexamples/agents/integration-assistant.jsonexamples/agents/researcher.jsonexamples/agents/web-assistant.jsonexamples/agents/workflow-assistant.jsonservices/platform/app/components/ui/forms/model-selector.tsxservices/platform/app/features/agents/components/agent-create-dialog.tsxservices/platform/app/features/agents/hooks/use-agents-table-config.tsxservices/platform/app/features/chat/components/arena/arena-model-selector.tsxservices/platform/app/features/chat/components/model-selector.tsxservices/platform/app/features/chat/context/chat-layout-context.tsxservices/platform/app/routes/dashboard/$id/agents/$agentId/instructions.tsxservices/platform/convex/agents/__tests__/save_agent_validation.test.tsservices/platform/convex/agents/config.tsservices/platform/convex/agents/file_actions.tsservices/platform/convex/agents/unified_chat.tsservices/platform/convex/lib/agent_chat/internal_actions.tsservices/platform/convex/providers/file_actions.tsservices/platform/lib/shared/schemas/agents.tsservices/platform/lib/shared/utils/__tests__/model-ref.test.tsservices/platform/lib/shared/utils/model-ref.tsservices/platform/messages/de.jsonservices/platform/messages/en.json
| "toolNames": [ | ||
| "customer_read", | ||
| "product_read" | ||
| ], | ||
| "supportedModels": [ | ||
| "openrouter:anthropic/claude-opus-4.6", | ||
| "openrouter:openai/gpt-5.2" | ||
| ], |
There was a problem hiding this comment.
Formatting check is failing in CI and needs a formatter pass.
oxfmt --check is currently red for this PR. Please run the formatter and commit the resulting JSON formatting changes so lint passes.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@examples/agents/crm-assistant.json` around lines 5 - 12, The JSON in
examples/agents/crm-assistant.json is not formatted to the repo's formatter
(oxfmt), causing CI to fail; run the formatter (e.g., oxfmt or your project's
format script) to reformat this file and commit the updated JSON so oxfmt
--check passes; focus on formatting the array/object entries like "toolNames"
and "supportedModels" and ensure the committed changes include only the
formatting updates.
| "integrationBindings": [ | ||
| "ai-image" | ||
| ], | ||
| "supportedModels": [ | ||
| "openrouter:moonshotai/kimi-k2.5", | ||
| "openrouter:anthropic/claude-sonnet-4.6" | ||
| ], |
There was a problem hiding this comment.
Formatting is currently blocking this PR.
oxfmt --check is failing for this file in CI. Please run the formatter and commit the normalized JSON output.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@examples/agents/image-creator.json` around lines 5 - 11, The JSON formatting
for the object containing the "integrationBindings" and "supportedModels" keys
is not normalized and fails oxfmt --check; run the repository formatter (oxfmt)
against this JSON, update the file with the normalized output, and commit the
formatted JSON so CI passes (ensure the JSON follows the project's formatter
rules and removes any trailing/extra whitespace or comma issues).
| return ( | ||
| <Badge variant="outline">{stripModelRefQualifier(model)}</Badge> | ||
| ); |
There was a problem hiding this comment.
Guard model ref normalization to avoid render crashes on bad data.
Line 57 can throw for malformed refs (:x, x:), which would break the row render. Add a safe fallback to the raw model string.
🛡️ Safe fallback patch
cell: ({ row }) => {
const model = row.original.supportedModels?.[0];
if (!model) return null;
- return (
- <Badge variant="outline">{stripModelRefQualifier(model)}</Badge>
- );
+ let label = model;
+ try {
+ label = stripModelRefQualifier(model);
+ } catch {
+ // keep raw model label if malformed
+ }
+ return <Badge variant="outline">{label}</Badge>;
},🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/platform/app/features/agents/hooks/use-agents-table-config.tsx`
around lines 56 - 58, The Badge rendering can crash when
stripModelRefQualifier(model) throws on malformed refs; update the rendering in
use-agents-table-config.tsx to call stripModelRefQualifier safely by first
validating or try/catching the result and falling back to the original model
string (e.g., use a safeNormalize variable = safe result || model) before
passing into <Badge> so malformed values like ":x" or "x:" do not break row
render; target the return that currently uses stripModelRefQualifier(model) and
ensure a safe fallback is used.
| const getDisplayName = useCallback( | ||
| (modelId: string) => | ||
| modelInfoMap.get(modelId)?.displayName ?? getModelShortName(modelId), | ||
| (ref: string) => { | ||
| const plain = stripModelRefQualifier(ref); | ||
| return modelInfoMap.get(plain)?.displayName ?? getModelShortName(plain); | ||
| }, |
There was a problem hiding this comment.
Do not collapse provider-qualified options to identical display labels.
At Line 85 and Line 113, stripping qualifiers for label lookup can make two provider-qualified refs appear as the same option when they share a plain modelId. That breaks disambiguation in arena selection.
🔧 Proposed fix
-import { stripModelRefQualifier } from '@/lib/shared/utils/model-ref';
+import {
+ parseModelRef,
+ stripModelRefQualifier,
+} from '@/lib/shared/utils/model-ref';
const getDisplayName = useCallback(
(ref: string) => {
- const plain = stripModelRefQualifier(ref);
- return modelInfoMap.get(plain)?.displayName ?? getModelShortName(plain);
+ const { providerName, modelId } = parseModelRef(ref);
+ const base =
+ modelInfoMap.get(modelId)?.displayName ?? getModelShortName(modelId);
+ return providerName ? `${base} (${providerName})` : base;
},
[modelInfoMap],
);Also applies to: 111-114
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@services/platform/app/features/chat/components/arena/arena-model-selector.tsx`
around lines 83 - 87, The current getDisplayName collapses provider-qualified
refs by stripping qualifiers before lookup; instead, look up modelInfoMap using
the full ref first (use ref directly), fall back to the stripped plain id only
if the full ref is not present, and when constructing the short name use
getModelShortName(ref) (not the stripped plain) so provider qualifiers remain
part of the label; apply the same change to the other lookup at lines referenced
(the similar logic around the other label generation) so qualified model refs
remain disambiguated.
| const target = stripModelRefQualifier(modelId); | ||
| const matched = supportedModels.some( | ||
| (ref) => stripModelRefQualifier(ref) === target, | ||
| ); | ||
| if (matched) { | ||
| config.model = modelId; | ||
| config.fallbackModels = undefined; |
There was a problem hiding this comment.
Preserve provider pinning by assigning the matched supported ref, not raw input.
Current logic matches on stripped ids but sets config.model = modelId. If caller sends an unqualified or different-qualified ref with the same plain id, provider pinning can be lost.
🔧 Proposed fix
export function applyModelOverride(
config: SerializableAgentConfig,
modelId: string,
supportedModels: string[],
): boolean {
const target = stripModelRefQualifier(modelId);
- const matched = supportedModels.some(
- (ref) => stripModelRefQualifier(ref) === target,
- );
- if (matched) {
- config.model = modelId;
+ const exactMatch = supportedModels.find((ref) => ref === modelId);
+ const normalizedMatch = supportedModels.find(
+ (ref) => stripModelRefQualifier(ref) === target,
+ );
+ const matchedRef = exactMatch ?? normalizedMatch;
+
+ if (matchedRef) {
+ config.model = matchedRef;
config.fallbackModels = undefined;
return true;
}
return false;
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/platform/convex/agents/config.ts` around lines 79 - 85, The code
matches on stripped ids using stripModelRefQualifier(modelId) against
supportedModels but then sets config.model = modelId, which can drop provider
pinning; change the assignment to use the actual matched supportedModels entry
(the matched "ref" from the supportedModels.some/iteration) so config.model is
set to the provider-qualified ref instead of the raw modelId, and keep
config.fallbackModels = undefined as before; locate the logic around
stripModelRefQualifier, supportedModels, config.model and replace the modelId
assignment with the matched supported ref.
| if (args.modelId) { | ||
| const accessCheck = await ctx.runQuery( | ||
| internal.governance.internal_queries.checkModelAccessInternal, | ||
| { | ||
| organizationId: args.organizationId, | ||
| userId: authUserId, | ||
| modelId: args.modelId, | ||
| modelId: stripModelRefQualifier(args.modelId), | ||
| }, |
There was a problem hiding this comment.
Guard model-ref parsing so failures still clear generation status.
At Line 189, stripModelRefQualifier(args.modelId) can throw on malformed refs. In that failure path, rollbackGenerating() is skipped, so the thread may remain stuck in generating state.
🔧 Proposed fix
if (args.modelId) {
+ let normalizedModelId: string;
+ try {
+ normalizedModelId = stripModelRefQualifier(args.modelId);
+ } catch {
+ await rollbackGenerating();
+ throw new Error('Invalid model reference.');
+ }
+
const accessCheck = await ctx.runQuery(
internal.governance.internal_queries.checkModelAccessInternal,
{
organizationId: args.organizationId,
userId: authUserId,
- modelId: stripModelRefQualifier(args.modelId),
+ modelId: normalizedModelId,
},
);As per coding guidelines: "Validate and sanitize all user input at system boundaries".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (args.modelId) { | |
| const accessCheck = await ctx.runQuery( | |
| internal.governance.internal_queries.checkModelAccessInternal, | |
| { | |
| organizationId: args.organizationId, | |
| userId: authUserId, | |
| modelId: args.modelId, | |
| modelId: stripModelRefQualifier(args.modelId), | |
| }, | |
| if (args.modelId) { | |
| let normalizedModelId: string; | |
| try { | |
| normalizedModelId = stripModelRefQualifier(args.modelId); | |
| } catch { | |
| await rollbackGenerating(); | |
| throw new Error('Invalid model reference.'); | |
| } | |
| const accessCheck = await ctx.runQuery( | |
| internal.governance.internal_queries.checkModelAccessInternal, | |
| { | |
| organizationId: args.organizationId, | |
| userId: authUserId, | |
| modelId: normalizedModelId, | |
| }, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/platform/convex/agents/unified_chat.ts` around lines 183 - 190, The
call to stripModelRefQualifier(args.modelId) can throw and prevent
rollbackGenerating() from running; wrap the model-ref parsing in a try/catch (or
validate before calling) inside the same control flow that runs the access check
so any parse error will still call rollbackGenerating(authUserId, threadId or
relevant IDs) before rethrowing/returning an error. Specifically, guard the
stripModelRefQualifier invocation used when calling
internal.governance.internal_queries.checkModelAccessInternal and ensure
rollbackGenerating (the function used later to clear the thread generating
state) is invoked in the catch/finally path so malformed model refs cannot leave
a thread stuck in generating state.
| let firstMatch: | ||
| | { | ||
| provider: (typeof candidates)[number]; | ||
| definition: (typeof candidates)[number]['config']['models'][number]; | ||
| } | ||
| | undefined; | ||
| const secondaryMatchProviders: string[] = []; | ||
| for (const provider of candidates) { | ||
| const definition = provider.config.models.find( | ||
| (m) => m.id === args.modelId, | ||
| ); | ||
| if (definition) { | ||
| return { | ||
| providerName: provider.name, | ||
| baseUrl: definition.baseUrl ?? provider.config.baseUrl, | ||
| apiKey: | ||
| provider.secrets.modelKeys?.[definition.id] ?? | ||
| provider.secrets.apiKey, | ||
| modelId: args.modelId, | ||
| maxOutputTokens: definition.maxOutputTokens, | ||
| supportsStructuredOutputs: | ||
| definition.supportsStructuredOutputs ?? | ||
| provider.config.supportsStructuredOutputs ?? | ||
| false, | ||
| inputCentsPerMillion: definition.cost?.inputCentsPerMillion, | ||
| outputCentsPerMillion: definition.cost?.outputCentsPerMillion, | ||
| }; | ||
| if (!definition) continue; | ||
| if (!firstMatch) { | ||
| firstMatch = { provider, definition }; | ||
| } else { | ||
| secondaryMatchProviders.push(provider.name); | ||
| } | ||
| } | ||
|
|
||
| if (firstMatch) { | ||
| if (!args.providerName && secondaryMatchProviders.length > 0) { | ||
| console.warn( | ||
| `[resolveModelData] Unqualified model "${args.modelId}" matches multiple providers ` + | ||
| `(pinned: ${firstMatch.provider.name}; also in: ${secondaryMatchProviders.join(', ')}). ` + | ||
| `Qualify as "${firstMatch.provider.name}:${args.modelId}" to pin explicitly.`, | ||
| ); | ||
| } | ||
| const { provider, definition } = firstMatch; | ||
| return { | ||
| providerName: provider.name, | ||
| baseUrl: definition.baseUrl ?? provider.config.baseUrl, | ||
| apiKey: | ||
| provider.secrets.modelKeys?.[definition.id] ?? | ||
| provider.secrets.apiKey, | ||
| modelId: args.modelId, | ||
| maxOutputTokens: definition.maxOutputTokens, | ||
| supportsStructuredOutputs: | ||
| definition.supportsStructuredOutputs ?? | ||
| provider.config.supportsStructuredOutputs ?? | ||
| false, | ||
| inputCentsPerMillion: definition.cost?.inputCentsPerMillion, | ||
| outputCentsPerMillion: definition.cost?.outputCentsPerMillion, | ||
| }; |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Consider surfacing the ambiguity warning to callers.
The console.warn for unqualified models matching multiple providers is only visible server-side. Based on the relevant code snippet from resolve_model.ts (lines 220-234), resolveLanguageModelById invokes this action and silently uses the returned modelData without any awareness that the model might not be the user's intended choice.
Consider returning the warning as part of the response (similar to how saveAgent returns warnings?: string[]) so downstream callers can surface it to users or logs with more context.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/platform/convex/providers/file_actions.ts` around lines 369 - 411,
The ambiguity warning in the resolveModelData logic (the console.warn inside the
firstMatch branch that uses firstMatch, secondaryMatchProviders, and
args.providerName) should be returned to callers rather than only logged; modify
the function that returns the model info to include an optional warnings?:
string[] field and, when secondaryMatchProviders.length > 0 and
args.providerName is falsy, push the existing ambiguity message into that
warnings array (instead of only console.warn), then update callers such as
resolveLanguageModelById to accept and propagate the warnings (just like
saveAgent's warnings?: string[]) so downstream code can surface the warning to
users or logs.
| export interface ParsedModelRef { | ||
| providerName?: string; | ||
| modelId: string; | ||
| } |
There was a problem hiding this comment.
Remove or consume ParsedModelRef export to unblock CI.
knip is failing because ParsedModelRef is exported but unused outside this module (Line 1). Make it internal (or use it in consumers) so lint passes.
🔧 Minimal fix
-export interface ParsedModelRef {
+interface ParsedModelRef {
providerName?: string;
modelId: string;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export interface ParsedModelRef { | |
| providerName?: string; | |
| modelId: string; | |
| } | |
| interface ParsedModelRef { | |
| providerName?: string; | |
| modelId: string; | |
| } |
🧰 Tools
🪛 GitHub Actions: Lint
[error] 1-1: Knip reported unused exported type: ParsedModelRef (interface) at services/platform/lib/shared/utils/model-ref.ts:1:18
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@services/platform/lib/shared/utils/model-ref.ts` around lines 1 - 4, The
exported interface ParsedModelRef is declared but unused externally; remove the
export to make it internal (or alternatively use it in callers) so the symbol is
no longer an unused export. Concretely, in the ParsedModelRef declaration remove
the "export" modifier (making it "interface ParsedModelRef { ... }") or replace
usages by importing/consuming ParsedModelRef in the modules that need it; ensure
any references to ParsedModelRef in this module still compile after the change.
Add "<provider>:<model-id>" prefix syntax for supportedModels so entries can pin routing when the same id is defined in multiple provider files. Plain entries still resolve to the first matching provider, with a save-time warning when more than one match exists.
…xport - Run oxfmt on the three rebased agent JSONs (crm, image-creator, web) so format:check passes. - Make ParsedModelRef internal — it's only used inside model-ref.ts, so exporting it triggers knip's unused-exports check.
…ucture - Platform Dockerfile: add COPY lines for docs/, packages/tale_knowledge, packages/tale_shared, packages/tale_telemetry package.json files in both workspace-deps and pruner stages so bun install can resolve the workspaces the docs PR #1579 added to root package.json. - docs/package.json: route mintlify through bunx so CI and image builds don't require a global install for broken-link checks. - knip.config.ts: ignore uvx (used by tale_* python packages) alongside the existing uv entry.
…r ruff findings - .dockerignore: add !docs/package.json exception so the Docker build can COPY the workspace manifest the root package.json now references. - tale_knowledge: resolve the pre-existing ruff findings the docs PR left unfixed — zip(strict=True), B904 raise ... from err, SIM110 any(), drop unused imports/unpacked vars — so turbo lint goes green after the mintlify script is unblocked.
Pre-existing ruff errors surfaced after the docs lint step stopped short-circuiting turbo. Fixes: - tale_telemetry: replace en-dash with hyphen in comment (RUF003). - tale_shared/config/base.py: split provider imports so isort is happy. - tale_shared/db/retry.py: move AsyncIterator import to collections.abc. - tale_shared/errors/__init__.py: sort __all__. - tale_shared/logging/__init__.py: add __all__ so re-exports are explicit. - tale_shared/logging/setup.py: wrap the loguru format string across lines so it fits the 120 col limit.
dfadd23 to
73932b9
Compare
Turbo's lint / format:check tasks depend on each workspace's setup task. @tale/rag#setup runs `uv sync --extra dev`, so the lint and format jobs need uv on PATH. The prior `install-python: 'false'` override, added during the CI right-size pass, skipped the uv install and made both jobs exit 127 before any real check ran. Drop the override for these two jobs so the default (Python + uv) kicks back in. Other jobs in lint.yml and elsewhere keep `install-python: false` because their turbo tasks don't chain through setup.
Summary
<provider>:<model-id>prefix syntax forsupportedModelsso agents can pin routing when the same id is defined in multiple provider files.model-refutil (parse / format / strip / validate) with unit tests, wired into the agent Zod schema and the UI model selectors.openrouter:prefixes for the shipped seed agents;docs/platform/admin/providers.mdgains a "Pinning an entry to a specific provider" section.Test plan
npm run lint --workspace=@tale/platformnpx tsc --noEmitfromservices/platform/model-refunit tests and existingsave_agent_validationtests<provider>:form and confirm the warning clearsopenrouter:prefix migrationSummary by CodeRabbit
Release Notes
New Features
Documentation
Improvements