fix(llm-pi-ai): describing a model must not fail on a bad profile level
`resolveModel` validated the profile's reasoning level against the exact model and threw when it did not fit. That call builds the model catalog, and the catalog build catches per PROVIDER — so one mis-set field took the whole provider out of every picker behind a single error row, hiding even the models that do support the level. Measured: `anthropic` set to `max` threw for six of its eight models. Describing what a model can do now reports an unusable profile level as no default rather than throwing; the request path still refuses it, which is where a bad configuration belongs. The existing spec asserted the old throw and now asserts both halves of that split. Known gap, left deliberately: a model that cannot take the route's level still fails its first request while the picker shows 「Default」 for it, because the request path keeps using the profile level as the fallback. Reaching that needs a hand-written `settings.yaml` — the Models page no longer writes the field — and the error names the model and the level, so selecting a supported level is a way out. Closing it properly means giving `AgentOptions` a `reasoningEffort` so compositions without a model picker keep an entry point, then dropping the provider-scoped field altogether; that is its own change.
This commit is contained in:
@@ -94,6 +94,29 @@ function profileOptions(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The profile default this exact model can actually take, for DESCRIBING it.
|
||||
* A configured level the model does not support yields none rather than
|
||||
* throwing: `resolveModel` builds the model catalog, and a catalog that fails
|
||||
* takes its whole provider out of every picker — so one mis-set profile field
|
||||
* would hide every model on the route, including the ones that support the
|
||||
* level. The request path still refuses, which is where a bad configuration
|
||||
* belongs: describing what a model can do must not fail because a deployment
|
||||
* asked it for something it cannot.
|
||||
* @param model - the resolved model descriptor.
|
||||
* @param effort - the profile's configured level, if any.
|
||||
* @returns the level when this model supports it, otherwise undefined.
|
||||
*/
|
||||
function describableReasoningLevel(
|
||||
model: Model<Api>,
|
||||
effort: ReasoningEffortIdType | ModelThinkingLevel | undefined,
|
||||
): ModelThinkingLevel | undefined {
|
||||
if (effort === undefined) return undefined
|
||||
return getSupportedThinkingLevels(model).some(level => level === effort)
|
||||
? effort as ModelThinkingLevel
|
||||
: undefined
|
||||
}
|
||||
|
||||
/** Validate an explicit Harness/profile effort without invoking pi-ai's clamp. */
|
||||
function resolveReasoningLevel(
|
||||
model: Model<Api>,
|
||||
@@ -229,7 +252,7 @@ export class PiAiAdapter extends LlmAdapter {
|
||||
const snapshot = this.current()
|
||||
const profile = this.profileOf(snapshot, provider)
|
||||
const resolvedModel = this.modelOf(snapshot, provider, model)
|
||||
const defaultLevel = resolveReasoningLevel(resolvedModel, profile.reasoning)
|
||||
const defaultLevel = describableReasoningLevel(resolvedModel, profile.reasoning)
|
||||
// Only a cap the deployment configured is a request default; the
|
||||
// catalog's `maxTokens` sizes the model and stops there.
|
||||
const configuredMaxTokens = profile.configuredMaxTokens.get(model)
|
||||
|
||||
Reference in New Issue
Block a user