mirror of
https://github.com/voideditor/void
synced 2026-05-23 01:18:25 +00:00
improve special tool config (#6)
This commit is contained in:
parent
dbe29d0f41
commit
f4e5b9e91a
2 changed files with 54 additions and 13 deletions
|
|
@ -227,9 +227,17 @@ const SimpleModelSettingsDialog = ({
|
|||
const currentOverrides = settingsState.overridesOfModel?.[providerName]?.[modelName] ?? undefined;
|
||||
const { recognizedModelName, isUnrecognizedModel } = defaultModelCapabilities
|
||||
|
||||
// Create the placeholder with the default values for allowed keys
|
||||
// Create the placeholder with the default values for allowed keys.
|
||||
// `specialToolFormat` is intentionally excluded: it's now auto-applied per
|
||||
// provider (see `defaultSpecialToolFormat` in modelCapabilities.ts), the
|
||||
// status line above already tells the user which format will be used, and
|
||||
// the preset buttons below offer one-click switching. Including it here
|
||||
// would just suggest the user has to type it themselves.
|
||||
const partialDefaults: Partial<ModelOverrides> = {};
|
||||
for (const k of modelOverrideKeys) { if (defaultModelCapabilities[k]) partialDefaults[k] = defaultModelCapabilities[k] as any; }
|
||||
for (const k of modelOverrideKeys) {
|
||||
if (k === 'specialToolFormat') continue;
|
||||
if (defaultModelCapabilities[k]) partialDefaults[k] = defaultModelCapabilities[k] as any;
|
||||
}
|
||||
const placeholder = JSON.stringify(partialDefaults, null, 2);
|
||||
|
||||
const [overrideEnabled, setOverrideEnabled] = useState<boolean>(() => !!currentOverrides);
|
||||
|
|
@ -319,11 +327,23 @@ const SimpleModelSettingsDialog = ({
|
|||
</button>
|
||||
</div>
|
||||
|
||||
{/* Display model recognition status */}
|
||||
{/* Display model recognition status. For unrecognized models we surface the
|
||||
tool-calling format Void auto-picked based on the provider's wire protocol,
|
||||
so the user knows what to expect (and what to override if their model needs
|
||||
a different format). */}
|
||||
<div className="text-sm text-void-fg-3 mb-4">
|
||||
{type === 'default' ? `${modelName} comes packaged with Void, so you shouldn't need to change these settings.`
|
||||
{type === 'default'
|
||||
? `${modelName} comes packaged with Void, so you shouldn't need to change these settings.`
|
||||
: isUnrecognizedModel
|
||||
? `Model not recognized by Void.`
|
||||
? (() => {
|
||||
const fmt = defaultModelCapabilities.specialToolFormat
|
||||
const fmtLabel = fmt === 'openai-style' ? 'OpenAI-style'
|
||||
: fmt === 'anthropic-style' ? 'Anthropic-style'
|
||||
: fmt === 'gemini-style' ? 'Gemini-style'
|
||||
: 'XML-in-prompt (fallback)'
|
||||
const providerLabel = displayInfoOfProviderName(providerName).title
|
||||
return `Model not recognized by Void. Defaulting to ${fmtLabel} tool calling based on the ${providerLabel} provider — override below if your model needs a different format.`
|
||||
})()
|
||||
: `Void recognizes ${modelName} ("${recognizedModelName}").`}
|
||||
</div>
|
||||
|
||||
|
|
@ -334,10 +354,13 @@ const SimpleModelSettingsDialog = ({
|
|||
<span className="text-void-fg-3 text-sm">Override model defaults</span>
|
||||
</div>
|
||||
|
||||
{/* Informational link */}
|
||||
{overrideEnabled && <div className="text-sm text-void-fg-3 mb-4">
|
||||
<ChatMarkdownRender string={`See the [sourcecode](${sourcecodeOverridesLink}) for a reference on how to set this JSON (advanced).`} chatMessageLocation={undefined} />
|
||||
</div>}
|
||||
{/* Informational link. Shown unconditionally so users can discover the
|
||||
full set of overridable fields (contextWindow, reasoningCapabilities,
|
||||
supportsSystemMessage, etc.) before deciding whether to enable
|
||||
overrides. */}
|
||||
<div className="text-sm text-void-fg-3 mb-4">
|
||||
<ChatMarkdownRender string={`Advanced — see the [sourcecode](${sourcecodeOverridesLink}) for the full list of fields you can override (e.g. \`contextWindow\`, \`reasoningCapabilities\`, \`supportsSystemMessage\`).`} chatMessageLocation={undefined} />
|
||||
</div>
|
||||
|
||||
<textarea
|
||||
key={overrideEnabled + ''}
|
||||
|
|
|
|||
|
|
@ -237,6 +237,11 @@ type VoidStaticProviderInfo = { // doesn't change (not stateful)
|
|||
providerReasoningIOSettings?: ProviderReasoningIOSettings; // input/output settings around thinking (allowed to be empty) - only applied if the model supports reasoning output
|
||||
modelOptions: { [key: string]: VoidStaticModelInfo };
|
||||
modelOptionsFallback: (modelName: string, fallbackKnownValues?: Partial<VoidStaticModelInfo>) => (VoidStaticModelInfo & { modelName: string, recognizedModelName: string }) | null;
|
||||
// Tool format used when neither the per-model entry nor the fallback specifies one.
|
||||
// If unset, `getModelCapabilities` defaults to 'openai-style' since the vast majority
|
||||
// of provider endpoints speak the OpenAI tools API. Only providers whose endpoint
|
||||
// uses a different native format (e.g. anthropic, gemini) need to override this.
|
||||
defaultSpecialToolFormat?: VoidStaticModelInfo['specialToolFormat'];
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -570,6 +575,7 @@ const anthropicModelOptions = {
|
|||
} as const satisfies { [s: string]: VoidStaticModelInfo }
|
||||
|
||||
const anthropicSettings: VoidStaticProviderInfo = {
|
||||
defaultSpecialToolFormat: 'anthropic-style',
|
||||
providerReasoningIOSettings: {
|
||||
input: {
|
||||
includeInPayload: (reasoningInfo) => {
|
||||
|
|
@ -918,6 +924,7 @@ const geminiModelOptions = { // https://ai.google.dev/gemini-api/docs/pricing
|
|||
} as const satisfies { [s: string]: VoidStaticModelInfo }
|
||||
|
||||
const geminiSettings: VoidStaticProviderInfo = {
|
||||
defaultSpecialToolFormat: 'gemini-style',
|
||||
modelOptions: geminiModelOptions,
|
||||
modelOptionsFallback: (modelName) => { return null },
|
||||
}
|
||||
|
|
@ -1491,25 +1498,36 @@ export const getModelCapabilities = (
|
|||
|
||||
const lowercaseModelName = modelName.toLowerCase()
|
||||
|
||||
const { modelOptions, modelOptionsFallback } = modelSettingsOfProvider[providerName]
|
||||
const { modelOptions, modelOptionsFallback, defaultSpecialToolFormat } = modelSettingsOfProvider[providerName]
|
||||
|
||||
// Get any override settings for this model
|
||||
const overrides = overridesOfModel?.[providerName]?.[modelName];
|
||||
|
||||
// Fill in `specialToolFormat` when neither the per-model entry, the fallback, nor
|
||||
// the user override specified one. Most provider endpoints speak the OpenAI tools
|
||||
// API, so 'openai-style' is the global default; providers like anthropic/gemini
|
||||
// opt out via `defaultSpecialToolFormat` on their settings. Without this, an
|
||||
// unrecognized model would silently fall back to brittle XML-in-prompt tools.
|
||||
const providerToolFormatDefault = defaultSpecialToolFormat ?? 'openai-style'
|
||||
const applyProviderToolFormatDefault = <T extends { specialToolFormat?: VoidStaticModelInfo['specialToolFormat'] }>(obj: T): T => {
|
||||
if (!obj.specialToolFormat) obj.specialToolFormat = providerToolFormatDefault
|
||||
return obj
|
||||
}
|
||||
|
||||
// search model options object directly first
|
||||
for (const modelName_ in modelOptions) {
|
||||
const lowercaseModelName_ = modelName_.toLowerCase()
|
||||
if (lowercaseModelName === lowercaseModelName_) {
|
||||
return { ...modelOptions[modelName], ...overrides, modelName, recognizedModelName: modelName, isUnrecognizedModel: false };
|
||||
return applyProviderToolFormatDefault({ ...modelOptions[modelName], ...overrides, modelName, recognizedModelName: modelName, isUnrecognizedModel: false });
|
||||
}
|
||||
}
|
||||
|
||||
const result = modelOptionsFallback(modelName)
|
||||
if (result) {
|
||||
return { ...result, ...overrides, modelName: result.modelName, isUnrecognizedModel: false };
|
||||
return applyProviderToolFormatDefault({ ...result, ...overrides, modelName: result.modelName, isUnrecognizedModel: false });
|
||||
}
|
||||
|
||||
return { modelName, ...defaultModelOptions, ...overrides, isUnrecognizedModel: true };
|
||||
return applyProviderToolFormatDefault({ modelName, ...defaultModelOptions, ...overrides, isUnrecognizedModel: true });
|
||||
}
|
||||
|
||||
// non-model settings
|
||||
|
|
|
|||
Loading…
Reference in a new issue