mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 05:01:15 +00:00
refactor: move provider discovery config into plugins
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
8bbf281d0c63e38098b2132174b77ed58faf2083fb68cb88f90ebe76d7acda1b config-baseline.json
|
||||
7163170accb9a8b62455ede5437f057d5a9e9ab5da42010cf0f39cbad952071d config-baseline.core.json
|
||||
d5a737eb69a2b2b64526fa0197ef9fe576b1d5d4b949a5c610a8457d5f5706cd config-baseline.json
|
||||
b1a181b667568b5860a80945837d544fdec4f946fba34e871936ce0cd3eb689b config-baseline.core.json
|
||||
3c999707b167138de34f6255e3488b99e404c5132d3fc5879a1fa12d815c31f5 config-baseline.channel.json
|
||||
76d011c68b8bc44ec862afa826dd8ddd7c577d89ce0b822eed306f8e1e9301ab config-baseline.plugin.json
|
||||
031b237717ca108ea2cd314413db4c91edfdfea55f808179e3066331f41af134 config-baseline.plugin.json
|
||||
|
||||
@@ -2301,13 +2301,13 @@ OpenClaw uses the built-in model catalog. Add custom providers via `models.provi
|
||||
- `models.providers.*.models.*.contextWindow`: native model context window metadata.
|
||||
- `models.providers.*.models.*.contextTokens`: optional runtime context cap. Use this when you want a smaller effective context budget than the model's native `contextWindow`.
|
||||
- `models.providers.*.models.*.compat.supportsDeveloperRole`: optional compatibility hint. For `api: "openai-completions"` with a non-empty non-native `baseUrl` (host not `api.openai.com`), OpenClaw forces this to `false` at runtime. Empty/omitted `baseUrl` keeps default OpenAI behavior.
|
||||
- `models.bedrockDiscovery`: Bedrock auto-discovery settings root.
|
||||
- `models.bedrockDiscovery.enabled`: turn discovery polling on/off.
|
||||
- `models.bedrockDiscovery.region`: AWS region for discovery.
|
||||
- `models.bedrockDiscovery.providerFilter`: optional provider-id filter for targeted discovery.
|
||||
- `models.bedrockDiscovery.refreshInterval`: polling interval for discovery refresh.
|
||||
- `models.bedrockDiscovery.defaultContextWindow`: fallback context window for discovered models.
|
||||
- `models.bedrockDiscovery.defaultMaxTokens`: fallback max output tokens for discovered models.
|
||||
- `plugins.entries.amazon-bedrock.config.discovery`: Bedrock auto-discovery settings root.
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.enabled`: turn implicit discovery on/off.
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.region`: AWS region for discovery.
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.providerFilter`: optional provider-id filter for targeted discovery.
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.refreshInterval`: polling interval for discovery refresh.
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow`: fallback context window for discovered models.
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens`: fallback max output tokens for discovered models.
|
||||
|
||||
### Provider examples
|
||||
|
||||
|
||||
@@ -652,7 +652,7 @@ for usage/billing and raise limits as needed.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is AWS Bedrock supported?">
|
||||
Yes. OpenClaw has a bundled **Amazon Bedrock (Converse)** provider. With AWS env markers present, OpenClaw can auto-discover the streaming/text Bedrock catalog and merge it as an implicit `amazon-bedrock` provider; otherwise you can explicitly enable `models.bedrockDiscovery.enabled` or add a manual provider entry. See [Amazon Bedrock](/providers/bedrock) and [Model providers](/providers/models). If you prefer a managed key flow, an OpenAI-compatible proxy in front of Bedrock is still a valid option.
|
||||
Yes. OpenClaw has a bundled **Amazon Bedrock (Converse)** provider. With AWS env markers present, OpenClaw can auto-discover the streaming/text Bedrock catalog and merge it as an implicit `amazon-bedrock` provider; otherwise you can explicitly enable `plugins.entries.amazon-bedrock.config.discovery.enabled` or add a manual provider entry. See [Amazon Bedrock](/providers/bedrock) and [Model providers](/providers/models). If you prefer a managed key flow, an OpenAI-compatible proxy in front of Bedrock is still a valid option.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How does Codex auth work?">
|
||||
|
||||
@@ -27,9 +27,10 @@ cached (default: 1 hour).
|
||||
|
||||
How the implicit provider is enabled:
|
||||
|
||||
- If `models.bedrockDiscovery.enabled` is `true`, OpenClaw will try discovery
|
||||
even when no AWS env marker is present.
|
||||
- If `models.bedrockDiscovery.enabled` is unset, OpenClaw only auto-adds the
|
||||
- If `plugins.entries.amazon-bedrock.config.discovery.enabled` is `true`,
|
||||
OpenClaw will try discovery even when no AWS env marker is present.
|
||||
- If `plugins.entries.amazon-bedrock.config.discovery.enabled` is unset,
|
||||
OpenClaw only auto-adds the
|
||||
implicit Bedrock provider when it sees one of these AWS auth markers:
|
||||
`AWS_BEARER_TOKEN_BEDROCK`, `AWS_ACCESS_KEY_ID` +
|
||||
`AWS_SECRET_ACCESS_KEY`, or `AWS_PROFILE`.
|
||||
@@ -37,18 +38,24 @@ How the implicit provider is enabled:
|
||||
shared config, SSO, and IMDS instance-role auth can work even when discovery
|
||||
needed `enabled: true` to opt in.
|
||||
|
||||
Config options live under `models.bedrockDiscovery`:
|
||||
Config options live under `plugins.entries.amazon-bedrock.config.discovery`:
|
||||
|
||||
```json5
|
||||
{
|
||||
models: {
|
||||
bedrockDiscovery: {
|
||||
enabled: true,
|
||||
region: "us-east-1",
|
||||
providerFilter: ["anthropic", "amazon"],
|
||||
refreshInterval: 3600,
|
||||
defaultContextWindow: 32000,
|
||||
defaultMaxTokens: 4096,
|
||||
plugins: {
|
||||
entries: {
|
||||
"amazon-bedrock": {
|
||||
config: {
|
||||
discovery: {
|
||||
enabled: true,
|
||||
region: "us-east-1",
|
||||
providerFilter: ["anthropic", "amazon"],
|
||||
refreshInterval: 3600,
|
||||
defaultContextWindow: 32000,
|
||||
defaultMaxTokens: 4096,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -120,20 +127,21 @@ export AWS_BEARER_TOKEN_BEDROCK="..."
|
||||
When running OpenClaw on an EC2 instance with an IAM role attached, the AWS SDK
|
||||
can use the instance metadata service (IMDS) for authentication. For Bedrock
|
||||
model discovery, OpenClaw only auto-enables the implicit provider from AWS env
|
||||
markers unless you explicitly set `models.bedrockDiscovery.enabled: true`.
|
||||
markers unless you explicitly set
|
||||
`plugins.entries.amazon-bedrock.config.discovery.enabled: true`.
|
||||
|
||||
Recommended setup for IMDS-backed hosts:
|
||||
|
||||
- Set `models.bedrockDiscovery.enabled` to `true`.
|
||||
- Set `models.bedrockDiscovery.region` (or export `AWS_REGION`).
|
||||
- Set `plugins.entries.amazon-bedrock.config.discovery.enabled` to `true`.
|
||||
- Set `plugins.entries.amazon-bedrock.config.discovery.region` (or export `AWS_REGION`).
|
||||
- You do **not** need a fake API key.
|
||||
- You only need `AWS_PROFILE=default` if you specifically want an env marker
|
||||
for auto mode or status surfaces.
|
||||
|
||||
```bash
|
||||
# Recommended: explicit discovery enable + region
|
||||
openclaw config set models.bedrockDiscovery.enabled true
|
||||
openclaw config set models.bedrockDiscovery.region us-east-1
|
||||
openclaw config set plugins.entries.amazon-bedrock.config.discovery.enabled true
|
||||
openclaw config set plugins.entries.amazon-bedrock.config.discovery.region us-east-1
|
||||
|
||||
# Optional: add an env marker if you want auto mode without explicit enable
|
||||
export AWS_PROFILE=default
|
||||
@@ -176,8 +184,8 @@ aws ec2 associate-iam-instance-profile \
|
||||
--iam-instance-profile Name=EC2-Bedrock-Access
|
||||
|
||||
# 3. On the EC2 instance, enable discovery explicitly
|
||||
openclaw config set models.bedrockDiscovery.enabled true
|
||||
openclaw config set models.bedrockDiscovery.region us-east-1
|
||||
openclaw config set plugins.entries.amazon-bedrock.config.discovery.enabled true
|
||||
openclaw config set plugins.entries.amazon-bedrock.config.discovery.region us-east-1
|
||||
|
||||
# 4. Optional: add an env marker if you want auto mode without explicit enable
|
||||
echo 'export AWS_PROFILE=default' >> ~/.bashrc
|
||||
@@ -194,7 +202,7 @@ openclaw models list
|
||||
- Automatic discovery needs the `bedrock:ListFoundationModels` permission.
|
||||
- If you rely on auto mode, set one of the supported AWS auth env markers on the
|
||||
gateway host. If you prefer IMDS/shared-config auth without env markers, set
|
||||
`models.bedrockDiscovery.enabled: true`.
|
||||
`plugins.entries.amazon-bedrock.config.discovery.enabled: true`.
|
||||
- OpenClaw surfaces the credential source in this order: `AWS_BEARER_TOKEN_BEDROCK`,
|
||||
then `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`, then `AWS_PROFILE`, then the
|
||||
default AWS SDK chain.
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
mergeImplicitBedrockProvider,
|
||||
resetBedrockDiscoveryCacheForTest,
|
||||
resolveBedrockConfigApiKey,
|
||||
resolveImplicitBedrockProvider,
|
||||
} from "./api.js";
|
||||
|
||||
const sendMock = vi.fn();
|
||||
@@ -147,9 +148,9 @@ describe("bedrock discovery", () => {
|
||||
expect(resolveBedrockConfigApiKey({} as NodeJS.ProcessEnv)).toBeUndefined();
|
||||
|
||||
// When AWS_PROFILE is explicitly set, it should return the marker.
|
||||
expect(
|
||||
resolveBedrockConfigApiKey({ AWS_PROFILE: "default" } as NodeJS.ProcessEnv),
|
||||
).toBe("AWS_PROFILE");
|
||||
expect(resolveBedrockConfigApiKey({ AWS_PROFILE: "default" } as NodeJS.ProcessEnv)).toBe(
|
||||
"AWS_PROFILE",
|
||||
);
|
||||
});
|
||||
|
||||
it("merges implicit Bedrock models into explicit provider overrides", () => {
|
||||
@@ -179,4 +180,48 @@ describe("bedrock discovery", () => {
|
||||
}).models?.map((model) => model.id),
|
||||
).toEqual(["amazon.nova-micro-v1:0"]);
|
||||
});
|
||||
|
||||
it("prefers plugin-owned discovery config and still honors legacy fallback", async () => {
|
||||
mockSingleActiveSummary();
|
||||
|
||||
const pluginEnabled = await resolveImplicitBedrockProvider({
|
||||
config: {
|
||||
models: {
|
||||
bedrockDiscovery: {
|
||||
enabled: false,
|
||||
region: "us-west-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
pluginConfig: {
|
||||
discovery: {
|
||||
enabled: true,
|
||||
region: "us-east-1",
|
||||
},
|
||||
},
|
||||
env: {} as NodeJS.ProcessEnv,
|
||||
clientFactory,
|
||||
});
|
||||
|
||||
expect(pluginEnabled?.baseUrl).toBe("https://bedrock-runtime.us-east-1.amazonaws.com");
|
||||
expect(sendMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
mockSingleActiveSummary();
|
||||
|
||||
const legacyEnabled = await resolveImplicitBedrockProvider({
|
||||
config: {
|
||||
models: {
|
||||
bedrockDiscovery: {
|
||||
enabled: true,
|
||||
region: "us-west-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
env: {} as NodeJS.ProcessEnv,
|
||||
clientFactory,
|
||||
});
|
||||
|
||||
expect(legacyEnabled?.baseUrl).toBe("https://bedrock-runtime.us-west-2.amazonaws.com");
|
||||
expect(sendMock).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -242,10 +242,15 @@ export async function discoverBedrockModels(params: {
|
||||
|
||||
export async function resolveImplicitBedrockProvider(params: {
|
||||
config?: { models?: { bedrockDiscovery?: BedrockDiscoveryConfig } };
|
||||
pluginConfig?: { discovery?: BedrockDiscoveryConfig };
|
||||
env?: NodeJS.ProcessEnv;
|
||||
clientFactory?: (region: string) => BedrockClient;
|
||||
}): Promise<ModelProviderConfig | null> {
|
||||
const env = params.env ?? process.env;
|
||||
const discoveryConfig = params.config?.models?.bedrockDiscovery;
|
||||
const discoveryConfig = {
|
||||
...(params.config?.models?.bedrockDiscovery ?? {}),
|
||||
...(params.pluginConfig?.discovery ?? {}),
|
||||
};
|
||||
const enabled = discoveryConfig?.enabled;
|
||||
const hasAwsCreds = resolveAwsSdkEnvVarName(env) !== undefined;
|
||||
if (enabled === false) {
|
||||
@@ -259,6 +264,7 @@ export async function resolveImplicitBedrockProvider(params: {
|
||||
const models = await discoverBedrockModels({
|
||||
region,
|
||||
config: discoveryConfig,
|
||||
clientFactory: params.clientFactory,
|
||||
});
|
||||
if (models.length === 0) {
|
||||
return null;
|
||||
|
||||
@@ -152,12 +152,35 @@ describe("amazon-bedrock provider plugin", () => {
|
||||
});
|
||||
|
||||
describe("guardrail config schema", () => {
|
||||
it("defines guardrail object with correct property types, required fields, and enums", () => {
|
||||
it("defines discovery and guardrail objects with the expected shape", () => {
|
||||
const pluginJson = JSON.parse(
|
||||
readFileSync(resolve(import.meta.dirname, "openclaw.plugin.json"), "utf-8"),
|
||||
);
|
||||
const discovery = pluginJson.configSchema?.properties?.discovery;
|
||||
const guardrail = pluginJson.configSchema?.properties?.guardrail;
|
||||
|
||||
expect(discovery).toBeDefined();
|
||||
expect(discovery.type).toBe("object");
|
||||
expect(discovery.additionalProperties).toBe(false);
|
||||
expect(discovery.properties.enabled).toEqual({ type: "boolean" });
|
||||
expect(discovery.properties.region).toEqual({ type: "string" });
|
||||
expect(discovery.properties.providerFilter).toEqual({
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
});
|
||||
expect(discovery.properties.refreshInterval).toEqual({
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
});
|
||||
expect(discovery.properties.defaultContextWindow).toEqual({
|
||||
type: "integer",
|
||||
minimum: 1,
|
||||
});
|
||||
expect(discovery.properties.defaultMaxTokens).toEqual({
|
||||
type: "integer",
|
||||
minimum: 1,
|
||||
});
|
||||
|
||||
expect(guardrail).toBeDefined();
|
||||
expect(guardrail.type).toBe("object");
|
||||
expect(guardrail.additionalProperties).toBe(false);
|
||||
|
||||
@@ -6,6 +6,21 @@
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"discovery": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": { "type": "boolean" },
|
||||
"region": { "type": "string" },
|
||||
"providerFilter": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"refreshInterval": { "type": "integer", "minimum": 0 },
|
||||
"defaultContextWindow": { "type": "integer", "minimum": 1 },
|
||||
"defaultMaxTokens": { "type": "integer", "minimum": 1 }
|
||||
}
|
||||
},
|
||||
"guardrail": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@@ -18,5 +33,39 @@
|
||||
"required": ["guardrailIdentifier", "guardrailVersion"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"uiHints": {
|
||||
"discovery": {
|
||||
"label": "Model Discovery",
|
||||
"help": "Plugin-owned controls for Amazon Bedrock model auto-discovery."
|
||||
},
|
||||
"discovery.enabled": {
|
||||
"label": "Enable Discovery",
|
||||
"help": "When false, OpenClaw keeps the Amazon Bedrock plugin available but skips implicit startup discovery. When true, discovery can run even without AWS auth env markers."
|
||||
},
|
||||
"discovery.region": {
|
||||
"label": "Discovery Region",
|
||||
"help": "AWS region to use for Bedrock model discovery. Defaults to AWS_REGION, AWS_DEFAULT_REGION, then us-east-1."
|
||||
},
|
||||
"discovery.providerFilter": {
|
||||
"label": "Provider Filter",
|
||||
"help": "Optional Bedrock provider-name allowlist for discovery, such as anthropic or amazon."
|
||||
},
|
||||
"discovery.refreshInterval": {
|
||||
"label": "Discovery Refresh Interval (s)",
|
||||
"help": "How long to cache Bedrock discovery results in seconds. Set to 0 to disable caching."
|
||||
},
|
||||
"discovery.defaultContextWindow": {
|
||||
"label": "Default Context Window",
|
||||
"help": "Fallback context window to assign to discovered Bedrock models."
|
||||
},
|
||||
"discovery.defaultMaxTokens": {
|
||||
"label": "Default Max Tokens",
|
||||
"help": "Fallback max output tokens to assign to discovered Bedrock models."
|
||||
},
|
||||
"guardrail": {
|
||||
"label": "Guardrail",
|
||||
"help": "Amazon Bedrock Guardrails settings applied to Bedrock model invocations."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,18 @@ type GuardrailConfig = {
|
||||
trace?: "enabled" | "disabled" | "enabled_full";
|
||||
};
|
||||
|
||||
type AmazonBedrockPluginConfig = {
|
||||
discovery?: {
|
||||
enabled?: boolean;
|
||||
region?: string;
|
||||
providerFilter?: string[];
|
||||
refreshInterval?: number;
|
||||
defaultContextWindow?: number;
|
||||
defaultMaxTokens?: number;
|
||||
};
|
||||
guardrail?: GuardrailConfig;
|
||||
};
|
||||
|
||||
function createGuardrailWrapStreamFn(
|
||||
innerWrapStreamFn: (ctx: { modelId: string; streamFn?: StreamFn }) => StreamFn | null | undefined,
|
||||
guardrailConfig: GuardrailConfig,
|
||||
@@ -57,9 +69,8 @@ export function registerAmazonBedrockPlugin(api: OpenClawPluginApi): void {
|
||||
const anthropicByModelReplayHooks = buildProviderReplayFamilyHooks({
|
||||
family: "anthropic-by-model",
|
||||
});
|
||||
const guardrail = (api.pluginConfig as Record<string, unknown> | undefined)?.guardrail as
|
||||
| GuardrailConfig
|
||||
| undefined;
|
||||
const pluginConfig = (api.pluginConfig ?? {}) as AmazonBedrockPluginConfig;
|
||||
const guardrail = pluginConfig.guardrail;
|
||||
|
||||
const baseWrapStreamFn = ({ modelId, streamFn }: { modelId: string; streamFn?: StreamFn }) =>
|
||||
isAnthropicBedrockModel(modelId) ? streamFn : createBedrockNoCacheWrapper(streamFn);
|
||||
@@ -79,6 +90,7 @@ export function registerAmazonBedrockPlugin(api: OpenClawPluginApi): void {
|
||||
run: async (ctx) => {
|
||||
const implicit = await resolveImplicitBedrockProvider({
|
||||
config: ctx.config,
|
||||
pluginConfig,
|
||||
env: ctx.env,
|
||||
});
|
||||
if (!implicit) {
|
||||
|
||||
@@ -13,6 +13,10 @@ vi.mock("./register.runtime.js", () => ({
|
||||
import plugin from "./index.js";
|
||||
|
||||
function registerProvider() {
|
||||
return registerProviderWithPluginConfig({});
|
||||
}
|
||||
|
||||
function registerProviderWithPluginConfig(pluginConfig: Record<string, unknown>) {
|
||||
const registerProviderMock = vi.fn();
|
||||
|
||||
plugin.register(
|
||||
@@ -21,6 +25,7 @@ function registerProvider() {
|
||||
name: "GitHub Copilot",
|
||||
source: "test",
|
||||
config: {},
|
||||
pluginConfig,
|
||||
runtime: {} as never,
|
||||
registerProvider: registerProviderMock,
|
||||
}),
|
||||
@@ -31,11 +36,11 @@ function registerProvider() {
|
||||
}
|
||||
|
||||
describe("github-copilot plugin", () => {
|
||||
it("skips catalog discovery when models.copilotDiscovery.enabled is false", async () => {
|
||||
const provider = registerProvider();
|
||||
it("skips catalog discovery when plugin discovery is disabled", async () => {
|
||||
const provider = registerProviderWithPluginConfig({ discovery: { enabled: false } });
|
||||
|
||||
const result = await provider.catalog.run({
|
||||
config: { models: { copilotDiscovery: { enabled: false } } },
|
||||
config: {},
|
||||
agentDir: "/tmp/agent",
|
||||
env: { GH_TOKEN: "gh_test_token" },
|
||||
resolveProviderApiKey: () => ({ apiKey: "gh_test_token" }),
|
||||
|
||||
@@ -11,6 +11,12 @@ import { wrapCopilotProviderStream } from "./stream.js";
|
||||
const COPILOT_ENV_VARS = ["COPILOT_GITHUB_TOKEN", "GH_TOKEN", "GITHUB_TOKEN"];
|
||||
const COPILOT_XHIGH_MODEL_IDS = ["gpt-5.2", "gpt-5.2-codex"] as const;
|
||||
|
||||
type GithubCopilotPluginConfig = {
|
||||
discovery?: {
|
||||
enabled?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
async function loadGithubCopilotRuntime() {
|
||||
return await import("./register.runtime.js");
|
||||
}
|
||||
@@ -19,6 +25,7 @@ export default definePluginEntry({
|
||||
name: "GitHub Copilot Provider",
|
||||
description: "Bundled GitHub Copilot provider plugin",
|
||||
register(api) {
|
||||
const pluginConfig = (api.pluginConfig ?? {}) as GithubCopilotPluginConfig;
|
||||
function resolveFirstGithubToken(params: { agentDir?: string; env: NodeJS.ProcessEnv }): {
|
||||
githubToken: string;
|
||||
hasProfile: boolean;
|
||||
@@ -125,7 +132,9 @@ export default definePluginEntry({
|
||||
catalog: {
|
||||
order: "late",
|
||||
run: async (ctx) => {
|
||||
if (ctx.config?.models?.copilotDiscovery?.enabled === false) {
|
||||
const discoveryEnabled =
|
||||
pluginConfig.discovery?.enabled ?? ctx.config?.models?.copilotDiscovery?.enabled;
|
||||
if (discoveryEnabled === false) {
|
||||
return null;
|
||||
}
|
||||
const { DEFAULT_COPILOT_API_BASE_URL, resolveCopilotApiToken } =
|
||||
|
||||
@@ -20,6 +20,24 @@
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {}
|
||||
"properties": {
|
||||
"discovery": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uiHints": {
|
||||
"discovery": {
|
||||
"label": "Model Discovery",
|
||||
"help": "Plugin-owned controls for GitHub Copilot model auto-discovery."
|
||||
},
|
||||
"discovery.enabled": {
|
||||
"label": "Enable Discovery",
|
||||
"help": "When false, OpenClaw keeps the GitHub Copilot plugin available but skips implicit startup discovery from ambient Copilot credentials."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ vi.mock("./onboard.js", () => ({
|
||||
import plugin from "./index.js";
|
||||
|
||||
function registerProvider() {
|
||||
return registerProviderWithPluginConfig({});
|
||||
}
|
||||
|
||||
function registerProviderWithPluginConfig(pluginConfig: Record<string, unknown>) {
|
||||
const registerProviderMock = vi.fn();
|
||||
|
||||
plugin.register(
|
||||
@@ -29,6 +33,7 @@ function registerProvider() {
|
||||
name: "Hugging Face",
|
||||
source: "test",
|
||||
config: {},
|
||||
pluginConfig,
|
||||
runtime: {} as never,
|
||||
registerProvider: registerProviderMock,
|
||||
}),
|
||||
@@ -39,11 +44,11 @@ function registerProvider() {
|
||||
}
|
||||
|
||||
describe("huggingface plugin", () => {
|
||||
it("skips catalog discovery when models.huggingfaceDiscovery.enabled is false", async () => {
|
||||
const provider = registerProvider();
|
||||
it("skips catalog discovery when plugin discovery is disabled", async () => {
|
||||
const provider = registerProviderWithPluginConfig({ discovery: { enabled: false } });
|
||||
|
||||
const result = await provider.catalog.run({
|
||||
config: { models: { huggingfaceDiscovery: { enabled: false } } },
|
||||
config: {},
|
||||
resolveProviderApiKey: () => ({
|
||||
apiKey: "hf_test_token",
|
||||
discoveryApiKey: "hf_test_token",
|
||||
|
||||
@@ -5,11 +5,18 @@ import { buildHuggingfaceProvider } from "./provider-catalog.js";
|
||||
|
||||
const PROVIDER_ID = "huggingface";
|
||||
|
||||
type HuggingFacePluginConfig = {
|
||||
discovery?: {
|
||||
enabled?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
export default definePluginEntry({
|
||||
id: PROVIDER_ID,
|
||||
name: "Hugging Face Provider",
|
||||
description: "Bundled Hugging Face provider plugin",
|
||||
register(api) {
|
||||
const pluginConfig = (api.pluginConfig ?? {}) as HuggingFacePluginConfig;
|
||||
api.registerProvider({
|
||||
id: PROVIDER_ID,
|
||||
label: "Hugging Face",
|
||||
@@ -41,7 +48,9 @@ export default definePluginEntry({
|
||||
catalog: {
|
||||
order: "simple",
|
||||
run: async (ctx) => {
|
||||
if (ctx.config?.models?.huggingfaceDiscovery?.enabled === false) {
|
||||
const discoveryEnabled =
|
||||
pluginConfig.discovery?.enabled ?? ctx.config?.models?.huggingfaceDiscovery?.enabled;
|
||||
if (discoveryEnabled === false) {
|
||||
return null;
|
||||
}
|
||||
const { apiKey, discoveryApiKey } = ctx.resolveProviderApiKey(PROVIDER_ID);
|
||||
|
||||
@@ -24,6 +24,24 @@
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {}
|
||||
"properties": {
|
||||
"discovery": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uiHints": {
|
||||
"discovery": {
|
||||
"label": "Model Discovery",
|
||||
"help": "Plugin-owned controls for Hugging Face model auto-discovery."
|
||||
},
|
||||
"discovery.enabled": {
|
||||
"label": "Enable Discovery",
|
||||
"help": "When false, OpenClaw keeps the Hugging Face plugin available but skips implicit startup discovery from ambient Hugging Face credentials."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
function registerProvider() {
|
||||
return registerProviderWithPluginConfig({});
|
||||
}
|
||||
|
||||
function registerProviderWithPluginConfig(pluginConfig: Record<string, unknown>) {
|
||||
const registerProviderMock = vi.fn();
|
||||
|
||||
plugin.register(
|
||||
@@ -42,6 +46,7 @@ function registerProvider() {
|
||||
name: "Ollama",
|
||||
source: "test",
|
||||
config: {},
|
||||
pluginConfig,
|
||||
runtime: {} as never,
|
||||
registerProvider: registerProviderMock,
|
||||
}),
|
||||
@@ -109,11 +114,11 @@ describe("ollama plugin", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("skips ambient discovery when models.ollamaDiscovery.enabled is false", async () => {
|
||||
const provider = registerProvider();
|
||||
it("skips ambient discovery when plugin discovery is disabled", async () => {
|
||||
const provider = registerProviderWithPluginConfig({ discovery: { enabled: false } });
|
||||
|
||||
const result = await provider.discovery.run({
|
||||
config: { models: { ollamaDiscovery: { enabled: false } } },
|
||||
config: {},
|
||||
env: {},
|
||||
resolveProviderApiKey: () => ({ apiKey: "", discoveryApiKey: "" }),
|
||||
} as never);
|
||||
|
||||
@@ -31,6 +31,12 @@ const OPENAI_COMPATIBLE_REPLAY_HOOKS = buildProviderReplayFamilyHooks({
|
||||
family: "openai-compatible",
|
||||
});
|
||||
|
||||
type OllamaPluginConfig = {
|
||||
discovery?: {
|
||||
enabled?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
function resolveOllamaDiscoveryApiKey(params: {
|
||||
env: NodeJS.ProcessEnv;
|
||||
explicitApiKey?: string;
|
||||
@@ -51,6 +57,7 @@ export default definePluginEntry({
|
||||
name: "Ollama Provider",
|
||||
description: "Bundled Ollama provider plugin",
|
||||
register(api: OpenClawPluginApi) {
|
||||
const pluginConfig = (api.pluginConfig ?? {}) as OllamaPluginConfig;
|
||||
api.registerWebSearchProvider(createOllamaWebSearchProvider());
|
||||
api.registerProvider({
|
||||
id: PROVIDER_ID,
|
||||
@@ -102,7 +109,9 @@ export default definePluginEntry({
|
||||
run: async (ctx: ProviderDiscoveryContext) => {
|
||||
const explicit = ctx.config.models?.providers?.ollama;
|
||||
const hasExplicitModels = Array.isArray(explicit?.models) && explicit.models.length > 0;
|
||||
if (!hasExplicitModels && ctx.config.models?.ollamaDiscovery?.enabled === false) {
|
||||
const discoveryEnabled =
|
||||
pluginConfig.discovery?.enabled ?? ctx.config.models?.ollamaDiscovery?.enabled;
|
||||
if (!hasExplicitModels && discoveryEnabled === false) {
|
||||
return null;
|
||||
}
|
||||
const ollamaKey = ctx.resolveProviderApiKey(PROVIDER_ID).apiKey;
|
||||
|
||||
@@ -23,6 +23,24 @@
|
||||
"configSchema": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {}
|
||||
"properties": {
|
||||
"discovery": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": { "type": "boolean" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uiHints": {
|
||||
"discovery": {
|
||||
"label": "Model Discovery",
|
||||
"help": "Plugin-owned controls for Ollama model auto-discovery."
|
||||
},
|
||||
"discovery.enabled": {
|
||||
"label": "Enable Discovery",
|
||||
"help": "When false, OpenClaw keeps the Ollama plugin available but skips implicit startup discovery of ambient local or remote Ollama models."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2893,105 +2893,6 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
||||
description:
|
||||
"Provider map keyed by provider ID containing connection/auth settings and concrete model definitions. Use stable provider keys so references from agents and tooling remain portable across environments.",
|
||||
},
|
||||
bedrockDiscovery: {
|
||||
type: "object",
|
||||
properties: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
title: "Bedrock Discovery Enabled",
|
||||
description:
|
||||
"Enables periodic Bedrock model discovery and catalog refresh for Bedrock-backed providers. Keep disabled unless Bedrock is actively used and IAM permissions are correctly configured.",
|
||||
},
|
||||
region: {
|
||||
type: "string",
|
||||
title: "Bedrock Discovery Region",
|
||||
description:
|
||||
"AWS region used for Bedrock discovery calls when discovery is enabled for your deployment. Use the region where your Bedrock models are provisioned to avoid empty discovery results.",
|
||||
},
|
||||
providerFilter: {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "string",
|
||||
},
|
||||
title: "Bedrock Discovery Provider Filter",
|
||||
description:
|
||||
"Optional provider allowlist filter for Bedrock discovery so only selected providers are refreshed. Use this to limit discovery scope in multi-provider environments.",
|
||||
},
|
||||
refreshInterval: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
maximum: 9007199254740991,
|
||||
title: "Bedrock Discovery Refresh Interval (s)",
|
||||
description:
|
||||
"Refresh cadence for Bedrock discovery polling in seconds to detect newly available models over time. Use longer intervals in production to reduce API cost and control-plane noise.",
|
||||
},
|
||||
defaultContextWindow: {
|
||||
type: "integer",
|
||||
exclusiveMinimum: 0,
|
||||
maximum: 9007199254740991,
|
||||
title: "Bedrock Default Context Window",
|
||||
description:
|
||||
"Fallback context-window value applied to discovered models when provider metadata lacks explicit limits. Use realistic defaults to avoid oversized prompts that exceed true provider constraints.",
|
||||
},
|
||||
defaultMaxTokens: {
|
||||
type: "integer",
|
||||
exclusiveMinimum: 0,
|
||||
maximum: 9007199254740991,
|
||||
title: "Bedrock Default Max Tokens",
|
||||
description:
|
||||
"Fallback max-token value applied to discovered models without explicit output token limits. Use conservative defaults to reduce truncation surprises and unexpected token spend.",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
title: "Bedrock Model Discovery",
|
||||
description:
|
||||
"Automatic AWS Bedrock model discovery settings used to synthesize provider model entries from account visibility. Keep discovery scoped and refresh intervals conservative to reduce API churn.",
|
||||
},
|
||||
copilotDiscovery: {
|
||||
type: "object",
|
||||
properties: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
title: "Copilot Discovery Enabled",
|
||||
description:
|
||||
"Set to false to prevent Copilot discovery from running even when GitHub tokens are detected. Useful when GH_TOKEN is set for other tools and you do not want Copilot provider auto-registration.",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
title: "Copilot Model Discovery",
|
||||
description:
|
||||
"GitHub Copilot implicit discovery settings. Controls whether OpenClaw probes for Copilot API access when GH_TOKEN or GITHUB_TOKEN is present.",
|
||||
},
|
||||
huggingfaceDiscovery: {
|
||||
type: "object",
|
||||
properties: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
title: "Hugging Face Discovery Enabled",
|
||||
description:
|
||||
"Set to false to prevent Hugging Face model discovery from running even when HF_TOKEN is detected. Useful when the token is set for other tools like transformers-cli.",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
title: "Hugging Face Model Discovery",
|
||||
description:
|
||||
"Hugging Face implicit discovery settings. Controls whether OpenClaw fetches the Hugging Face model catalog when HF_TOKEN is present.",
|
||||
},
|
||||
ollamaDiscovery: {
|
||||
type: "object",
|
||||
properties: {
|
||||
enabled: {
|
||||
type: "boolean",
|
||||
title: "Ollama Discovery Enabled",
|
||||
description:
|
||||
"Set to false to prevent Ollama discovery from probing localhost:11434 on startup. Useful when Ollama is not intended for OpenClaw or the local probe causes startup delays.",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
title: "Ollama Model Discovery",
|
||||
description:
|
||||
"Ollama implicit discovery settings. Controls whether OpenClaw probes the local Ollama server for available models on startup.",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
title: "Models",
|
||||
@@ -24941,71 +24842,6 @@ export const GENERATED_BASE_CONFIG_SCHEMA: BaseConfigSchemaResponse = {
|
||||
help: "Declared model list for a provider including identifiers, metadata, and optional compatibility/cost hints. Keep IDs exact to provider catalog values so selection and fallback resolve correctly.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.bedrockDiscovery": {
|
||||
label: "Bedrock Model Discovery",
|
||||
help: "Automatic AWS Bedrock model discovery settings used to synthesize provider model entries from account visibility. Keep discovery scoped and refresh intervals conservative to reduce API churn.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.bedrockDiscovery.enabled": {
|
||||
label: "Bedrock Discovery Enabled",
|
||||
help: "Enables periodic Bedrock model discovery and catalog refresh for Bedrock-backed providers. Keep disabled unless Bedrock is actively used and IAM permissions are correctly configured.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.bedrockDiscovery.region": {
|
||||
label: "Bedrock Discovery Region",
|
||||
help: "AWS region used for Bedrock discovery calls when discovery is enabled for your deployment. Use the region where your Bedrock models are provisioned to avoid empty discovery results.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.bedrockDiscovery.providerFilter": {
|
||||
label: "Bedrock Discovery Provider Filter",
|
||||
help: "Optional provider allowlist filter for Bedrock discovery so only selected providers are refreshed. Use this to limit discovery scope in multi-provider environments.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.bedrockDiscovery.refreshInterval": {
|
||||
label: "Bedrock Discovery Refresh Interval (s)",
|
||||
help: "Refresh cadence for Bedrock discovery polling in seconds to detect newly available models over time. Use longer intervals in production to reduce API cost and control-plane noise.",
|
||||
tags: ["performance", "models"],
|
||||
},
|
||||
"models.bedrockDiscovery.defaultContextWindow": {
|
||||
label: "Bedrock Default Context Window",
|
||||
help: "Fallback context-window value applied to discovered models when provider metadata lacks explicit limits. Use realistic defaults to avoid oversized prompts that exceed true provider constraints.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.bedrockDiscovery.defaultMaxTokens": {
|
||||
label: "Bedrock Default Max Tokens",
|
||||
help: "Fallback max-token value applied to discovered models without explicit output token limits. Use conservative defaults to reduce truncation surprises and unexpected token spend.",
|
||||
tags: ["security", "auth", "performance", "models"],
|
||||
},
|
||||
"models.copilotDiscovery": {
|
||||
label: "Copilot Model Discovery",
|
||||
help: "GitHub Copilot implicit discovery settings. Controls whether OpenClaw probes for Copilot API access when GH_TOKEN or GITHUB_TOKEN is present.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.copilotDiscovery.enabled": {
|
||||
label: "Copilot Discovery Enabled",
|
||||
help: "Set to false to prevent Copilot discovery from running even when GitHub tokens are detected. Useful when GH_TOKEN is set for other tools and you do not want Copilot provider auto-registration.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.huggingfaceDiscovery": {
|
||||
label: "Hugging Face Model Discovery",
|
||||
help: "Hugging Face implicit discovery settings. Controls whether OpenClaw fetches the Hugging Face model catalog when HF_TOKEN is present.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.huggingfaceDiscovery.enabled": {
|
||||
label: "Hugging Face Discovery Enabled",
|
||||
help: "Set to false to prevent Hugging Face model discovery from running even when HF_TOKEN is detected. Useful when the token is set for other tools like transformers-cli.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.ollamaDiscovery": {
|
||||
label: "Ollama Model Discovery",
|
||||
help: "Ollama implicit discovery settings. Controls whether OpenClaw probes the local Ollama server for available models on startup.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.ollamaDiscovery.enabled": {
|
||||
label: "Ollama Discovery Enabled",
|
||||
help: "Set to false to prevent Ollama discovery from probing localhost:11434 on startup. Useful when Ollama is not intended for OpenClaw or the local probe causes startup delays.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"auth.cooldowns.billingBackoffHours": {
|
||||
label: "Billing Backoff (hours)",
|
||||
help: "Base backoff (hours) when a profile fails due to billing/insufficient credits (default: 5).",
|
||||
|
||||
@@ -366,19 +366,6 @@ const TARGET_KEYS = [
|
||||
"models.providers.*.api",
|
||||
"models.providers.*.headers",
|
||||
"models.providers.*.models",
|
||||
"models.bedrockDiscovery",
|
||||
"models.bedrockDiscovery.enabled",
|
||||
"models.bedrockDiscovery.region",
|
||||
"models.bedrockDiscovery.providerFilter",
|
||||
"models.bedrockDiscovery.refreshInterval",
|
||||
"models.bedrockDiscovery.defaultContextWindow",
|
||||
"models.bedrockDiscovery.defaultMaxTokens",
|
||||
"models.copilotDiscovery",
|
||||
"models.copilotDiscovery.enabled",
|
||||
"models.huggingfaceDiscovery",
|
||||
"models.huggingfaceDiscovery.enabled",
|
||||
"models.ollamaDiscovery",
|
||||
"models.ollamaDiscovery.enabled",
|
||||
"agents",
|
||||
"agents.defaults",
|
||||
"agents.list",
|
||||
@@ -782,10 +769,6 @@ describe("config help copy quality", () => {
|
||||
expect(modelsMode.includes("SecretRef-managed")).toBe(true);
|
||||
expect(modelsMode.includes("preserve")).toBe(true);
|
||||
|
||||
const bedrockRefresh = FIELD_HELP["models.bedrockDiscovery.refreshInterval"];
|
||||
expect(/refresh|seconds|interval/i.test(bedrockRefresh)).toBe(true);
|
||||
expect(/cost|noise|api/i.test(bedrockRefresh)).toBe(true);
|
||||
|
||||
const authCooldowns = FIELD_HELP["auth.cooldowns"];
|
||||
expect(/cooldown|backoff|retry/i.test(authCooldowns)).toBe(true);
|
||||
});
|
||||
|
||||
@@ -789,32 +789,6 @@ export const FIELD_HELP: Record<string, string> = {
|
||||
"Skips upstream TLS certificate verification. Use only for controlled development environments.",
|
||||
"models.providers.*.models":
|
||||
"Declared model list for a provider including identifiers, metadata, and optional compatibility/cost hints. Keep IDs exact to provider catalog values so selection and fallback resolve correctly.",
|
||||
"models.bedrockDiscovery":
|
||||
"Automatic AWS Bedrock model discovery settings used to synthesize provider model entries from account visibility. Keep discovery scoped and refresh intervals conservative to reduce API churn.",
|
||||
"models.bedrockDiscovery.enabled":
|
||||
"Enables periodic Bedrock model discovery and catalog refresh for Bedrock-backed providers. Keep disabled unless Bedrock is actively used and IAM permissions are correctly configured.",
|
||||
"models.bedrockDiscovery.region":
|
||||
"AWS region used for Bedrock discovery calls when discovery is enabled for your deployment. Use the region where your Bedrock models are provisioned to avoid empty discovery results.",
|
||||
"models.bedrockDiscovery.providerFilter":
|
||||
"Optional provider allowlist filter for Bedrock discovery so only selected providers are refreshed. Use this to limit discovery scope in multi-provider environments.",
|
||||
"models.bedrockDiscovery.refreshInterval":
|
||||
"Refresh cadence for Bedrock discovery polling in seconds to detect newly available models over time. Use longer intervals in production to reduce API cost and control-plane noise.",
|
||||
"models.bedrockDiscovery.defaultContextWindow":
|
||||
"Fallback context-window value applied to discovered models when provider metadata lacks explicit limits. Use realistic defaults to avoid oversized prompts that exceed true provider constraints.",
|
||||
"models.bedrockDiscovery.defaultMaxTokens":
|
||||
"Fallback max-token value applied to discovered models without explicit output token limits. Use conservative defaults to reduce truncation surprises and unexpected token spend.",
|
||||
"models.copilotDiscovery":
|
||||
"GitHub Copilot implicit discovery settings. Controls whether OpenClaw probes for Copilot API access when GH_TOKEN or GITHUB_TOKEN is present.",
|
||||
"models.copilotDiscovery.enabled":
|
||||
"Set to false to prevent Copilot discovery from running even when GitHub tokens are detected. Useful when GH_TOKEN is set for other tools and you do not want Copilot provider auto-registration.",
|
||||
"models.huggingfaceDiscovery":
|
||||
"Hugging Face implicit discovery settings. Controls whether OpenClaw fetches the Hugging Face model catalog when HF_TOKEN is present.",
|
||||
"models.huggingfaceDiscovery.enabled":
|
||||
"Set to false to prevent Hugging Face model discovery from running even when HF_TOKEN is detected. Useful when the token is set for other tools like transformers-cli.",
|
||||
"models.ollamaDiscovery":
|
||||
"Ollama implicit discovery settings. Controls whether OpenClaw probes the local Ollama server for available models on startup.",
|
||||
"models.ollamaDiscovery.enabled":
|
||||
"Set to false to prevent Ollama discovery from probing localhost:11434 on startup. Useful when Ollama is not intended for OpenClaw or the local probe causes startup delays.",
|
||||
auth: "Authentication profile root used for multi-profile provider credentials and cooldown-based failover ordering. Keep profiles minimal and explicit so automatic failover behavior stays auditable.",
|
||||
"channels.matrix.allowBots":
|
||||
'Allow messages from other configured Matrix bot accounts to trigger replies (default: false). Set "mentions" to only accept bot messages that visibly mention this bot.',
|
||||
|
||||
@@ -476,19 +476,6 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"models.providers.*.request.tls.serverName": "Model Provider Request TLS Server Name",
|
||||
"models.providers.*.request.tls.insecureSkipVerify": "Model Provider Request TLS Skip Verify",
|
||||
"models.providers.*.models": "Model Provider Model List",
|
||||
"models.bedrockDiscovery": "Bedrock Model Discovery",
|
||||
"models.bedrockDiscovery.enabled": "Bedrock Discovery Enabled",
|
||||
"models.bedrockDiscovery.region": "Bedrock Discovery Region",
|
||||
"models.bedrockDiscovery.providerFilter": "Bedrock Discovery Provider Filter",
|
||||
"models.bedrockDiscovery.refreshInterval": "Bedrock Discovery Refresh Interval (s)",
|
||||
"models.bedrockDiscovery.defaultContextWindow": "Bedrock Default Context Window",
|
||||
"models.bedrockDiscovery.defaultMaxTokens": "Bedrock Default Max Tokens",
|
||||
"models.copilotDiscovery": "Copilot Model Discovery",
|
||||
"models.copilotDiscovery.enabled": "Copilot Discovery Enabled",
|
||||
"models.huggingfaceDiscovery": "Hugging Face Model Discovery",
|
||||
"models.huggingfaceDiscovery.enabled": "Hugging Face Discovery Enabled",
|
||||
"models.ollamaDiscovery": "Ollama Model Discovery",
|
||||
"models.ollamaDiscovery.enabled": "Ollama Discovery Enabled",
|
||||
"auth.cooldowns.billingBackoffHours": "Billing Backoff (hours)",
|
||||
"auth.cooldowns.billingBackoffHoursByProvider": "Billing Backoff Overrides",
|
||||
"auth.cooldowns.billingMaxHours": "Billing Backoff Cap (hours)",
|
||||
|
||||
@@ -99,6 +99,8 @@ export type DiscoveryToggleConfig = {
|
||||
export type ModelsConfig = {
|
||||
mode?: "merge" | "replace";
|
||||
providers?: Record<string, ModelProviderConfig>;
|
||||
// Deprecated legacy compat aliases. Kept in the runtime type surface so
|
||||
// doctor/runtime fallbacks can read older configs until migration completes.
|
||||
bedrockDiscovery?: BedrockDiscoveryConfig;
|
||||
copilotDiscovery?: DiscoveryToggleConfig;
|
||||
huggingfaceDiscovery?: DiscoveryToggleConfig;
|
||||
|
||||
@@ -342,21 +342,10 @@ export const BedrockDiscoverySchema = z
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
export const DiscoveryToggleSchema = z
|
||||
.object({
|
||||
enabled: z.boolean().optional(),
|
||||
})
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
export const ModelsConfigSchema = z
|
||||
.object({
|
||||
mode: z.union([z.literal("merge"), z.literal("replace")]).optional(),
|
||||
providers: z.record(z.string(), ModelProviderSchema).optional(),
|
||||
bedrockDiscovery: BedrockDiscoverySchema,
|
||||
copilotDiscovery: DiscoveryToggleSchema,
|
||||
huggingfaceDiscovery: DiscoveryToggleSchema,
|
||||
ollamaDiscovery: DiscoveryToggleSchema,
|
||||
})
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
Reference in New Issue
Block a user