mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-05 22:32:12 +00:00
feat(providers): reopen model request transport config (#60327)
* feat(providers): reopen model request transport config * chore(config): refresh request override baselines
This commit is contained in:
@@ -9,7 +9,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Channels/context visibility: add configurable `contextVisibility` per channel (`all`, `allowlist`, `allowlist_quote`) so supplemental quote, thread, and fetched history context can be filtered by sender allowlists instead of always passing through as received.
|
||||
- Matrix/exec approvals: add Matrix-native exec approval prompts with account-scoped approvers, channel-or-DM delivery, and room-thread aware resolution handling. (#58635) Thanks @gumadeiras.
|
||||
- Providers/StepFun: add the bundled StepFun provider plugin with standard and Step Plan endpoints, China/global onboarding choices, `step-3.5-flash` on both catalogs, and `step-3.5-flash-2603` currently exposed on Step Plan. (#60032) Thanks @hengm3467.
|
||||
- Providers/config: add `models.providers.*.request` overrides for headers and auth on model-provider paths, and full request transport overrides for media provider HTTP paths.
|
||||
- Providers/config: add full `models.providers.*.request` transport overrides for model-provider paths, including headers, auth, proxy, and TLS, and keep media provider HTTP request transport overrides aligned with the same request-policy surface. Thanks @vincentkoc.
|
||||
- Control UI/skills: add ClawHub search, detail, and install flows directly in the Skills panel. (#60134) Thanks @samzong.
|
||||
- Outbound/runtime seams: split delivery, target-resolution, and session/transcript helper loading into narrower runtime seams so outbound hot paths and their owner tests avoid broader setup fan-out. (#60311) Thanks @shakkernerd.
|
||||
|
||||
|
||||
@@ -4013,6 +4013,26 @@
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "agents.defaults.subagents.allowAgents",
|
||||
"kind": "core",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "agents.defaults.subagents.allowAgents.*",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "agents.defaults.subagents.announceTimeoutMs",
|
||||
"kind": "core",
|
||||
@@ -15601,7 +15621,7 @@
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Overrides",
|
||||
"help": "Optional request overrides for model-provider requests. Today this path supports header and auth overrides only; proxy and TLS transport settings are reserved for request paths that can carry them end to end.",
|
||||
"help": "Optional request overrides for model-provider requests, including extra headers, auth overrides, proxy routing, and TLS client settings. Use these only when your upstream or enterprise network path requires transport customization.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
@@ -15817,6 +15837,521 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy",
|
||||
"kind": "core",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Proxy",
|
||||
"help": "Optional proxy override for model-provider requests. Use \"env-proxy\" to honor environment proxy settings or \"explicit-proxy\" to route through a specific proxy URL.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.mode",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Proxy Mode",
|
||||
"help": "Proxy override mode for model-provider requests: \"env-proxy\" or \"explicit-proxy\".",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls",
|
||||
"kind": "core",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS",
|
||||
"help": "Optional TLS settings used when connecting to the configured proxy.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.ca",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS CA",
|
||||
"help": "Custom CA bundle used to verify the proxy TLS certificate chain.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.ca.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.ca.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.ca.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.cert",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Cert",
|
||||
"help": "Client TLS certificate presented to the proxy when mutual TLS is required.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.cert.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.cert.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.cert.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.insecureSkipVerify",
|
||||
"kind": "core",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Skip Verify",
|
||||
"help": "Skips proxy TLS certificate verification. Use only for controlled development environments.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.key",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Key",
|
||||
"help": "Private key paired with request.proxy.tls.cert for proxy mutual TLS.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.key.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.key.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.key.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Passphrase",
|
||||
"help": "Optional passphrase used to decrypt request.proxy.tls.key.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.serverName",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Server Name",
|
||||
"help": "Optional SNI/server-name override used when establishing TLS to the proxy.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.url",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models",
|
||||
"url-secret"
|
||||
],
|
||||
"label": "Model Provider Request Proxy URL",
|
||||
"help": "Explicit proxy URL used when request.proxy.mode is explicit-proxy. Credentials embedded in the URL are treated as sensitive and redacted from snapshots.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls",
|
||||
"kind": "core",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request TLS",
|
||||
"help": "Optional TLS settings used when connecting directly to the upstream model endpoint.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.ca",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS CA",
|
||||
"help": "Custom CA bundle used to verify the upstream TLS certificate chain.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.ca.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.ca.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.ca.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.cert",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS Cert",
|
||||
"help": "Client TLS certificate presented to the upstream endpoint when mutual TLS is required.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.cert.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.cert.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.cert.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.insecureSkipVerify",
|
||||
"kind": "core",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS Skip Verify",
|
||||
"help": "Skips upstream TLS certificate verification. Use only for controlled development environments.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.key",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS Key",
|
||||
"help": "Private key paired with request.tls.cert for upstream mutual TLS.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.key.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.key.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.key.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.passphrase",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS Passphrase",
|
||||
"help": "Optional passphrase used to decrypt request.tls.key.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.passphrase.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.passphrase.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.passphrase.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.serverName",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request TLS Server Name",
|
||||
"help": "Optional SNI/server-name override used when establishing upstream TLS.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "nodeHost",
|
||||
"kind": "core",
|
||||
|
||||
@@ -4012,6 +4012,26 @@
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "agents.defaults.subagents.allowAgents",
|
||||
"kind": "core",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "agents.defaults.subagents.allowAgents.*",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "agents.defaults.subagents.announceTimeoutMs",
|
||||
"kind": "core",
|
||||
@@ -15600,7 +15620,7 @@
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Overrides",
|
||||
"help": "Optional request overrides for model-provider requests. Today this path supports header and auth overrides only; proxy and TLS transport settings are reserved for request paths that can carry them end to end.",
|
||||
"help": "Optional request overrides for model-provider requests, including extra headers, auth overrides, proxy routing, and TLS client settings. Use these only when your upstream or enterprise network path requires transport customization.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
@@ -15816,6 +15836,521 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy",
|
||||
"kind": "core",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Proxy",
|
||||
"help": "Optional proxy override for model-provider requests. Use \"env-proxy\" to honor environment proxy settings or \"explicit-proxy\" to route through a specific proxy URL.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.mode",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Proxy Mode",
|
||||
"help": "Proxy override mode for model-provider requests: \"env-proxy\" or \"explicit-proxy\".",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls",
|
||||
"kind": "core",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS",
|
||||
"help": "Optional TLS settings used when connecting to the configured proxy.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.ca",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS CA",
|
||||
"help": "Custom CA bundle used to verify the proxy TLS certificate chain.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.ca.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.ca.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.ca.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.cert",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Cert",
|
||||
"help": "Client TLS certificate presented to the proxy when mutual TLS is required.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.cert.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.cert.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.cert.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.insecureSkipVerify",
|
||||
"kind": "core",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Skip Verify",
|
||||
"help": "Skips proxy TLS certificate verification. Use only for controlled development environments.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.key",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Key",
|
||||
"help": "Private key paired with request.proxy.tls.cert for proxy mutual TLS.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.key.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.key.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.key.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Passphrase",
|
||||
"help": "Optional passphrase used to decrypt request.proxy.tls.key.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.tls.serverName",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request Proxy TLS Server Name",
|
||||
"help": "Optional SNI/server-name override used when establishing TLS to the proxy.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.proxy.url",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models",
|
||||
"url-secret"
|
||||
],
|
||||
"label": "Model Provider Request Proxy URL",
|
||||
"help": "Explicit proxy URL used when request.proxy.mode is explicit-proxy. Credentials embedded in the URL are treated as sensitive and redacted from snapshots.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls",
|
||||
"kind": "core",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request TLS",
|
||||
"help": "Optional TLS settings used when connecting directly to the upstream model endpoint.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.ca",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS CA",
|
||||
"help": "Custom CA bundle used to verify the upstream TLS certificate chain.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.ca.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.ca.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.ca.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.cert",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS Cert",
|
||||
"help": "Client TLS certificate presented to the upstream endpoint when mutual TLS is required.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.cert.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.cert.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.cert.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.insecureSkipVerify",
|
||||
"kind": "core",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced",
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS Skip Verify",
|
||||
"help": "Skips upstream TLS certificate verification. Use only for controlled development environments.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.key",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS Key",
|
||||
"help": "Private key paired with request.tls.cert for upstream mutual TLS.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.key.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.key.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.key.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.passphrase",
|
||||
"kind": "core",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"models",
|
||||
"security"
|
||||
],
|
||||
"label": "Model Provider Request TLS Passphrase",
|
||||
"help": "Optional passphrase used to decrypt request.tls.key.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.passphrase.id",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.passphrase.provider",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.passphrase.source",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "models.providers.*.request.tls.serverName",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"models"
|
||||
],
|
||||
"label": "Model Provider Request TLS Server Name",
|
||||
"help": "Optional SNI/server-name override used when establishing upstream TLS.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "nodeHost",
|
||||
"kind": "core",
|
||||
|
||||
@@ -27,6 +27,14 @@ Scope intent:
|
||||
- `models.providers.*.request.auth.token`
|
||||
- `models.providers.*.request.auth.value`
|
||||
- `models.providers.*.request.headers.*`
|
||||
- `models.providers.*.request.proxy.tls.ca`
|
||||
- `models.providers.*.request.proxy.tls.cert`
|
||||
- `models.providers.*.request.proxy.tls.key`
|
||||
- `models.providers.*.request.proxy.tls.passphrase`
|
||||
- `models.providers.*.request.tls.ca`
|
||||
- `models.providers.*.request.tls.cert`
|
||||
- `models.providers.*.request.tls.key`
|
||||
- `models.providers.*.request.tls.passphrase`
|
||||
- `skills.entries.*.apiKey`
|
||||
- `agents.defaults.memorySearch.remote.apiKey`
|
||||
- `agents.list[].memorySearch.remote.apiKey`
|
||||
|
||||
@@ -461,6 +461,62 @@
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "models.providers.*.request.proxy.tls.ca",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "models.providers.*.request.proxy.tls.ca",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "models.providers.*.request.proxy.tls.cert",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "models.providers.*.request.proxy.tls.cert",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "models.providers.*.request.proxy.tls.key",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "models.providers.*.request.proxy.tls.key",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "models.providers.*.request.proxy.tls.passphrase",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "models.providers.*.request.proxy.tls.passphrase",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "models.providers.*.request.tls.ca",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "models.providers.*.request.tls.ca",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "models.providers.*.request.tls.cert",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "models.providers.*.request.tls.cert",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "models.providers.*.request.tls.key",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "models.providers.*.request.tls.key",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "models.providers.*.request.tls.passphrase",
|
||||
"configFile": "openclaw.json",
|
||||
"path": "models.providers.*.request.tls.passphrase",
|
||||
"secretShape": "secret_input",
|
||||
"optIn": true
|
||||
},
|
||||
{
|
||||
"id": "plugins.entries.brave.config.webSearch.apiKey",
|
||||
"configFile": "openclaw.json",
|
||||
|
||||
@@ -136,7 +136,7 @@ describe("config secret refs schema", () => {
|
||||
expect(result.ok).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts model provider request secret refs for auth and headers", () => {
|
||||
it("accepts model provider request secret refs for auth, headers, and tls material", () => {
|
||||
const result = validateConfigObjectRaw({
|
||||
models: {
|
||||
providers: {
|
||||
@@ -150,6 +150,17 @@ describe("config secret refs schema", () => {
|
||||
mode: "authorization-bearer",
|
||||
token: { source: "env", provider: "default", id: "OPENAI_PROVIDER_TOKEN" },
|
||||
},
|
||||
proxy: {
|
||||
mode: "explicit-proxy",
|
||||
url: "http://proxy.example:8080",
|
||||
tls: {
|
||||
ca: { source: "file", provider: "filemain", id: "/tls/provider-proxy-ca" },
|
||||
},
|
||||
},
|
||||
tls: {
|
||||
cert: { source: "file", provider: "filemain", id: "/tls/provider-cert" },
|
||||
key: { source: "file", provider: "filemain", id: "/tls/provider-key" },
|
||||
},
|
||||
},
|
||||
models: [{ id: "gpt-5", name: "gpt-5" }],
|
||||
},
|
||||
@@ -160,7 +171,7 @@ describe("config secret refs schema", () => {
|
||||
expect(result.ok).toBe(true);
|
||||
});
|
||||
|
||||
it("rejects model provider request proxy and tls overrides", () => {
|
||||
it("rejects model provider request proxy url secret refs", () => {
|
||||
const result = validateConfigObjectRaw({
|
||||
models: {
|
||||
providers: {
|
||||
@@ -169,10 +180,7 @@ describe("config secret refs schema", () => {
|
||||
request: {
|
||||
proxy: {
|
||||
mode: "explicit-proxy",
|
||||
url: "http://proxy.example:8080",
|
||||
},
|
||||
tls: {
|
||||
cert: { source: "file", provider: "filemain", id: "/tls/provider-cert" },
|
||||
url: { source: "env", provider: "default", id: "PROVIDER_PROXY_URL" },
|
||||
},
|
||||
},
|
||||
models: [{ id: "gpt-5", name: "gpt-5" }],
|
||||
@@ -184,7 +192,7 @@ describe("config secret refs schema", () => {
|
||||
expect(result.ok).toBe(false);
|
||||
if (!result.ok) {
|
||||
expect(
|
||||
result.issues.some((issue) => issue.path.includes("models.providers.openai.request")),
|
||||
result.issues.some((issue) => issue.path.includes("models.providers.openai.request.proxy")),
|
||||
).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -12,5 +12,6 @@ export const redactSnapshotTestHints: ConfigUiHints = {
|
||||
"models.providers.*.baseUrl": { sensitive: true },
|
||||
"models.providers.*.request.headers.*": { sensitive: true },
|
||||
"models.providers.*.request.auth.token": { sensitive: true },
|
||||
"models.providers.*.request.proxy.url": { sensitive: true },
|
||||
"skills.entries.*.env.GEMINI_API_KEY": { sensitive: true },
|
||||
};
|
||||
|
||||
@@ -330,6 +330,56 @@ describe("redactConfigSnapshot", () => {
|
||||
expect(restored.models.providers.openai.request.auth.token).toBe("provider-secret-token");
|
||||
});
|
||||
|
||||
it("redacts model provider request proxy URLs from config snapshots", () => {
|
||||
const hints = buildConfigSchema().uiHints;
|
||||
const raw = `{
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
models: [],
|
||||
request: {
|
||||
proxy: {
|
||||
mode: "explicit-proxy",
|
||||
url: "http://alice:secret@proxy.example.internal:8080",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}`;
|
||||
const snapshot = makeSnapshot(
|
||||
{
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
models: [],
|
||||
request: {
|
||||
proxy: {
|
||||
mode: "explicit-proxy",
|
||||
url: "http://alice:secret@proxy.example.internal:8080",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
raw,
|
||||
);
|
||||
|
||||
const result = redactConfigSnapshot(snapshot, hints);
|
||||
const cfg = result.config as typeof snapshot.config;
|
||||
expect(cfg.models.providers.openai.request.proxy.url).toBe(REDACTED_SENTINEL);
|
||||
expect(result.raw).toContain(REDACTED_SENTINEL);
|
||||
expect(result.raw).not.toContain("alice:secret@");
|
||||
|
||||
const restored = restoreRedactedValues(result.config, snapshot.config, hints);
|
||||
expect(restored.models.providers.openai.request.proxy.url).toBe(
|
||||
"http://alice:secret@proxy.example.internal:8080",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not redact maxTokens-style fields", () => {
|
||||
const snapshot = makeSnapshot({
|
||||
maxTokens: 16384,
|
||||
|
||||
@@ -1385,6 +1385,864 @@ export const GENERATED_BASE_CONFIG_SCHEMA = {
|
||||
},
|
||||
],
|
||||
},
|
||||
proxy: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
type: "string",
|
||||
const: "env-proxy",
|
||||
},
|
||||
tls: {
|
||||
type: "object",
|
||||
properties: {
|
||||
ca: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
cert: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
key: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
passphrase: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
serverName: {
|
||||
type: "string",
|
||||
},
|
||||
insecureSkipVerify: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
required: ["mode"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
mode: {
|
||||
type: "string",
|
||||
const: "explicit-proxy",
|
||||
},
|
||||
url: {
|
||||
type: "string",
|
||||
minLength: 1,
|
||||
},
|
||||
tls: {
|
||||
type: "object",
|
||||
properties: {
|
||||
ca: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
cert: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
key: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
passphrase: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
serverName: {
|
||||
type: "string",
|
||||
},
|
||||
insecureSkipVerify: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
required: ["mode", "url"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
tls: {
|
||||
type: "object",
|
||||
properties: {
|
||||
ca: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
cert: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
key: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
passphrase: {
|
||||
anyOf: [
|
||||
{
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
oneOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "env",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
pattern: "^[A-Z][A-Z0-9_]{0,127}$",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "file",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
source: {
|
||||
type: "string",
|
||||
const: "exec",
|
||||
},
|
||||
provider: {
|
||||
type: "string",
|
||||
pattern: "^[a-z][a-z0-9_-]{0,63}$",
|
||||
},
|
||||
id: {
|
||||
type: "string",
|
||||
},
|
||||
},
|
||||
required: ["source", "provider", "id"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
serverName: {
|
||||
type: "string",
|
||||
},
|
||||
insecureSkipVerify: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
additionalProperties: false,
|
||||
},
|
||||
@@ -21614,7 +22472,7 @@ export const GENERATED_BASE_CONFIG_SCHEMA = {
|
||||
},
|
||||
"models.providers.*.request": {
|
||||
label: "Model Provider Request Overrides",
|
||||
help: "Optional request overrides for model-provider requests. Use this only for header and auth overrides today; proxy and TLS transport settings are reserved for request paths that can carry them end to end.",
|
||||
help: "Optional request overrides for model-provider requests, including extra headers, auth overrides, proxy routing, and TLS client settings. Use these only when your upstream or enterprise network path requires transport customization.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.providers.*.request.headers": {
|
||||
@@ -21654,6 +22512,99 @@ export const GENERATED_BASE_CONFIG_SCHEMA = {
|
||||
help: "Optional prefix prepended to request.auth.value when auth mode is header.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.providers.*.request.proxy": {
|
||||
label: "Model Provider Request Proxy",
|
||||
help: 'Optional proxy override for model-provider requests. Use "env-proxy" to honor environment proxy settings or "explicit-proxy" to route through a specific proxy URL.',
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.providers.*.request.proxy.mode": {
|
||||
label: "Model Provider Request Proxy Mode",
|
||||
help: 'Proxy override mode for model-provider requests: "env-proxy" or "explicit-proxy".',
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.providers.*.request.proxy.url": {
|
||||
label: "Model Provider Request Proxy URL",
|
||||
help: "Explicit proxy URL used when request.proxy.mode is explicit-proxy. Credentials embedded in the URL are treated as sensitive and redacted from snapshots.",
|
||||
tags: ["models", "url-secret"],
|
||||
},
|
||||
"models.providers.*.request.proxy.tls": {
|
||||
label: "Model Provider Request Proxy TLS",
|
||||
help: "Optional TLS settings used when connecting to the configured proxy.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.providers.*.request.proxy.tls.ca": {
|
||||
label: "Model Provider Request Proxy TLS CA",
|
||||
help: "Custom CA bundle used to verify the proxy TLS certificate chain.",
|
||||
tags: ["security", "models"],
|
||||
sensitive: true,
|
||||
},
|
||||
"models.providers.*.request.proxy.tls.cert": {
|
||||
label: "Model Provider Request Proxy TLS Cert",
|
||||
help: "Client TLS certificate presented to the proxy when mutual TLS is required.",
|
||||
tags: ["security", "models"],
|
||||
sensitive: true,
|
||||
},
|
||||
"models.providers.*.request.proxy.tls.key": {
|
||||
label: "Model Provider Request Proxy TLS Key",
|
||||
help: "Private key paired with request.proxy.tls.cert for proxy mutual TLS.",
|
||||
tags: ["security", "models"],
|
||||
sensitive: true,
|
||||
},
|
||||
"models.providers.*.request.proxy.tls.passphrase": {
|
||||
label: "Model Provider Request Proxy TLS Passphrase",
|
||||
help: "Optional passphrase used to decrypt request.proxy.tls.key.",
|
||||
tags: ["security", "models"],
|
||||
sensitive: true,
|
||||
},
|
||||
"models.providers.*.request.proxy.tls.serverName": {
|
||||
label: "Model Provider Request Proxy TLS Server Name",
|
||||
help: "Optional SNI/server-name override used when establishing TLS to the proxy.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.providers.*.request.proxy.tls.insecureSkipVerify": {
|
||||
label: "Model Provider Request Proxy TLS Skip Verify",
|
||||
help: "Skips proxy TLS certificate verification. Use only for controlled development environments.",
|
||||
tags: ["security", "models", "advanced"],
|
||||
},
|
||||
"models.providers.*.request.tls": {
|
||||
label: "Model Provider Request TLS",
|
||||
help: "Optional TLS settings used when connecting directly to the upstream model endpoint.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.providers.*.request.tls.ca": {
|
||||
label: "Model Provider Request TLS CA",
|
||||
help: "Custom CA bundle used to verify the upstream TLS certificate chain.",
|
||||
tags: ["security", "models"],
|
||||
sensitive: true,
|
||||
},
|
||||
"models.providers.*.request.tls.cert": {
|
||||
label: "Model Provider Request TLS Cert",
|
||||
help: "Client TLS certificate presented to the upstream endpoint when mutual TLS is required.",
|
||||
tags: ["security", "models"],
|
||||
sensitive: true,
|
||||
},
|
||||
"models.providers.*.request.tls.key": {
|
||||
label: "Model Provider Request TLS Key",
|
||||
help: "Private key paired with request.tls.cert for upstream mutual TLS.",
|
||||
tags: ["security", "models"],
|
||||
sensitive: true,
|
||||
},
|
||||
"models.providers.*.request.tls.passphrase": {
|
||||
label: "Model Provider Request TLS Passphrase",
|
||||
help: "Optional passphrase used to decrypt request.tls.key.",
|
||||
tags: ["security", "models"],
|
||||
sensitive: true,
|
||||
},
|
||||
"models.providers.*.request.tls.serverName": {
|
||||
label: "Model Provider Request TLS Server Name",
|
||||
help: "Optional SNI/server-name override used when establishing upstream TLS.",
|
||||
tags: ["models"],
|
||||
},
|
||||
"models.providers.*.request.tls.insecureSkipVerify": {
|
||||
label: "Model Provider Request TLS Skip Verify",
|
||||
help: "Skips upstream TLS certificate verification. Use only for controlled development environments.",
|
||||
tags: ["security", "models", "advanced"],
|
||||
},
|
||||
"models.providers.*.models": {
|
||||
label: "Model Provider Model List",
|
||||
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.",
|
||||
|
||||
@@ -748,7 +748,7 @@ export const FIELD_HELP: Record<string, string> = {
|
||||
"models.providers.*.authHeader":
|
||||
"When true, credentials are sent via the HTTP Authorization header even if alternate auth is possible. Use this only when your provider or proxy explicitly requires Authorization forwarding.",
|
||||
"models.providers.*.request":
|
||||
"Optional request overrides for model-provider requests. Use this only for header and auth overrides today; proxy and TLS transport settings are reserved for request paths that can carry them end to end.",
|
||||
"Optional request overrides for model-provider requests, including extra headers, auth overrides, proxy routing, and TLS client settings. Use these only when your upstream or enterprise network path requires transport customization.",
|
||||
"models.providers.*.request.headers":
|
||||
"Extra headers merged into provider requests after default attribution and auth resolution.",
|
||||
"models.providers.*.request.auth":
|
||||
@@ -763,6 +763,40 @@ export const FIELD_HELP: Record<string, string> = {
|
||||
"Custom auth header value used when auth mode is header.",
|
||||
"models.providers.*.request.auth.prefix":
|
||||
"Optional prefix prepended to request.auth.value when auth mode is header.",
|
||||
"models.providers.*.request.proxy":
|
||||
'Optional proxy override for model-provider requests. Use "env-proxy" to honor environment proxy settings or "explicit-proxy" to route through a specific proxy URL.',
|
||||
"models.providers.*.request.proxy.mode":
|
||||
'Proxy override mode for model-provider requests: "env-proxy" or "explicit-proxy".',
|
||||
"models.providers.*.request.proxy.url":
|
||||
"Explicit proxy URL used when request.proxy.mode is explicit-proxy. Credentials embedded in the URL are treated as sensitive and redacted from snapshots.",
|
||||
"models.providers.*.request.proxy.tls":
|
||||
"Optional TLS settings used when connecting to the configured proxy.",
|
||||
"models.providers.*.request.proxy.tls.ca":
|
||||
"Custom CA bundle used to verify the proxy TLS certificate chain.",
|
||||
"models.providers.*.request.proxy.tls.cert":
|
||||
"Client TLS certificate presented to the proxy when mutual TLS is required.",
|
||||
"models.providers.*.request.proxy.tls.key":
|
||||
"Private key paired with request.proxy.tls.cert for proxy mutual TLS.",
|
||||
"models.providers.*.request.proxy.tls.passphrase":
|
||||
"Optional passphrase used to decrypt request.proxy.tls.key.",
|
||||
"models.providers.*.request.proxy.tls.serverName":
|
||||
"Optional SNI/server-name override used when establishing TLS to the proxy.",
|
||||
"models.providers.*.request.proxy.tls.insecureSkipVerify":
|
||||
"Skips proxy TLS certificate verification. Use only for controlled development environments.",
|
||||
"models.providers.*.request.tls":
|
||||
"Optional TLS settings used when connecting directly to the upstream model endpoint.",
|
||||
"models.providers.*.request.tls.ca":
|
||||
"Custom CA bundle used to verify the upstream TLS certificate chain.",
|
||||
"models.providers.*.request.tls.cert":
|
||||
"Client TLS certificate presented to the upstream endpoint when mutual TLS is required.",
|
||||
"models.providers.*.request.tls.key":
|
||||
"Private key paired with request.tls.cert for upstream mutual TLS.",
|
||||
"models.providers.*.request.tls.passphrase":
|
||||
"Optional passphrase used to decrypt request.tls.key.",
|
||||
"models.providers.*.request.tls.serverName":
|
||||
"Optional SNI/server-name override used when establishing upstream TLS.",
|
||||
"models.providers.*.request.tls.insecureSkipVerify":
|
||||
"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":
|
||||
|
||||
@@ -169,6 +169,7 @@ describe("mapSensitivePaths", () => {
|
||||
expect(hints["gateway.auth.token"]?.sensitive).toBe(true);
|
||||
expect(hints["models.providers.*.headers.*"]?.sensitive).toBe(true);
|
||||
expect(hints["models.providers.*.request.headers.*"]?.sensitive).toBe(true);
|
||||
expect(hints["models.providers.*.request.proxy.tls.cert"]?.sensitive).toBe(true);
|
||||
expect(hints["skills.entries.*.apiKey"]?.sensitive).toBe(true);
|
||||
});
|
||||
|
||||
@@ -194,7 +195,7 @@ describe("collectMatchingSchemaPaths", () => {
|
||||
|
||||
expect(paths.has("mcp.servers.*.url")).toBe(true);
|
||||
expect(paths.has("models.providers.*.baseUrl")).toBe(true);
|
||||
expect(paths.has("models.providers.*.request.proxy.url")).toBe(false);
|
||||
expect(paths.has("models.providers.*.request.proxy.url")).toBe(true);
|
||||
expect(paths.has("tools.media.audio.request.proxy.url")).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -456,6 +456,24 @@ export const FIELD_LABELS: Record<string, string> = {
|
||||
"models.providers.*.request.auth.headerName": "Model Provider Request Auth Header Name",
|
||||
"models.providers.*.request.auth.value": "Model Provider Request Auth Header Value",
|
||||
"models.providers.*.request.auth.prefix": "Model Provider Request Auth Header Prefix",
|
||||
"models.providers.*.request.proxy": "Model Provider Request Proxy",
|
||||
"models.providers.*.request.proxy.mode": "Model Provider Request Proxy Mode",
|
||||
"models.providers.*.request.proxy.url": "Model Provider Request Proxy URL",
|
||||
"models.providers.*.request.proxy.tls": "Model Provider Request Proxy TLS",
|
||||
"models.providers.*.request.proxy.tls.ca": "Model Provider Request Proxy TLS CA",
|
||||
"models.providers.*.request.proxy.tls.cert": "Model Provider Request Proxy TLS Cert",
|
||||
"models.providers.*.request.proxy.tls.key": "Model Provider Request Proxy TLS Key",
|
||||
"models.providers.*.request.proxy.tls.passphrase": "Model Provider Request Proxy TLS Passphrase",
|
||||
"models.providers.*.request.proxy.tls.serverName": "Model Provider Request Proxy TLS Server Name",
|
||||
"models.providers.*.request.proxy.tls.insecureSkipVerify":
|
||||
"Model Provider Request Proxy TLS Skip Verify",
|
||||
"models.providers.*.request.tls": "Model Provider Request TLS",
|
||||
"models.providers.*.request.tls.ca": "Model Provider Request TLS CA",
|
||||
"models.providers.*.request.tls.cert": "Model Provider Request TLS Cert",
|
||||
"models.providers.*.request.tls.key": "Model Provider Request TLS Key",
|
||||
"models.providers.*.request.tls.passphrase": "Model Provider Request TLS Passphrase",
|
||||
"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",
|
||||
|
||||
@@ -42,4 +42,4 @@ export type ConfiguredProviderRequest = {
|
||||
tls?: ConfiguredProviderRequestTls;
|
||||
};
|
||||
|
||||
export type ConfiguredModelProviderRequest = Pick<ConfiguredProviderRequest, "headers" | "auth">;
|
||||
export type ConfiguredModelProviderRequest = ConfiguredProviderRequest;
|
||||
|
||||
@@ -288,13 +288,7 @@ const ConfiguredProviderRequestSchema = z
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
const ConfiguredModelProviderRequestSchema = z
|
||||
.object({
|
||||
headers: z.record(z.string(), SecretInputSchema.register(sensitive)).optional(),
|
||||
auth: ConfiguredProviderRequestAuthSchema,
|
||||
})
|
||||
.strict()
|
||||
.optional();
|
||||
const ConfiguredModelProviderRequestSchema = ConfiguredProviderRequestSchema;
|
||||
|
||||
export const ModelDefinitionSchema = z
|
||||
.object({
|
||||
|
||||
@@ -79,7 +79,7 @@ function collectModelProviderAssignments(params: {
|
||||
context: params.context,
|
||||
active: providerIsActive,
|
||||
inactiveReason: "provider is disabled.",
|
||||
collectTransportSecrets: false,
|
||||
collectTransportSecrets: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +282,18 @@ function buildConfigForOpenClawTarget(entry: SecretRegistryEntry, envId: string)
|
||||
"x-api-key",
|
||||
);
|
||||
}
|
||||
if (entry.id.startsWith("models.providers.*.request.proxy.tls.")) {
|
||||
setPathCreateStrict(
|
||||
config,
|
||||
["models", "providers", "sample", "request", "proxy", "mode"],
|
||||
"explicit-proxy",
|
||||
);
|
||||
setPathCreateStrict(
|
||||
config,
|
||||
["models", "providers", "sample", "request", "proxy", "url"],
|
||||
"http://proxy.example:8080",
|
||||
);
|
||||
}
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
@@ -982,7 +982,7 @@ describe("secrets runtime snapshot", () => {
|
||||
expect(second?.search.selectedProvider).toBe("gemini");
|
||||
});
|
||||
|
||||
it("resolves model provider request secret refs for headers and auth", async () => {
|
||||
it("resolves model provider request secret refs for headers, auth, and tls material", async () => {
|
||||
const config = asConfig({
|
||||
models: {
|
||||
providers: {
|
||||
@@ -996,6 +996,17 @@ describe("secrets runtime snapshot", () => {
|
||||
mode: "authorization-bearer",
|
||||
token: { source: "env", provider: "default", id: "OPENAI_PROVIDER_TOKEN" },
|
||||
},
|
||||
proxy: {
|
||||
mode: "explicit-proxy",
|
||||
url: "http://proxy.example:8080",
|
||||
tls: {
|
||||
ca: { source: "env", provider: "default", id: "OPENAI_PROVIDER_PROXY_CA" },
|
||||
},
|
||||
},
|
||||
tls: {
|
||||
cert: { source: "env", provider: "default", id: "OPENAI_PROVIDER_CERT" },
|
||||
key: { source: "env", provider: "default", id: "OPENAI_PROVIDER_KEY" },
|
||||
},
|
||||
},
|
||||
models: [],
|
||||
},
|
||||
@@ -1008,6 +1019,9 @@ describe("secrets runtime snapshot", () => {
|
||||
env: {
|
||||
OPENAI_PROVIDER_TENANT: "tenant-acme",
|
||||
OPENAI_PROVIDER_TOKEN: "sk-provider-runtime", // pragma: allowlist secret
|
||||
OPENAI_PROVIDER_PROXY_CA: "proxy-ca",
|
||||
OPENAI_PROVIDER_CERT: "client-cert",
|
||||
OPENAI_PROVIDER_KEY: "client-key",
|
||||
},
|
||||
agentDirs: ["/tmp/openclaw-agent-main"],
|
||||
loadAuthStore: () => ({ version: 1, profiles: {} }),
|
||||
@@ -1021,6 +1035,17 @@ describe("secrets runtime snapshot", () => {
|
||||
mode: "authorization-bearer",
|
||||
token: "sk-provider-runtime",
|
||||
},
|
||||
proxy: {
|
||||
mode: "explicit-proxy",
|
||||
url: "http://proxy.example:8080",
|
||||
tls: {
|
||||
ca: "proxy-ca",
|
||||
},
|
||||
},
|
||||
tls: {
|
||||
cert: "client-cert",
|
||||
key: "client-key",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -708,6 +708,110 @@ const SECRET_TARGET_REGISTRY: SecretTargetRegistryEntry[] = [
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "models.providers.*.request.proxy.tls.ca",
|
||||
targetType: "models.providers.request.proxy.tls.ca",
|
||||
targetTypeAliases: ["models.providers.*.request.proxy.tls.ca"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.request.proxy.tls.ca",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "models.providers.*.request.proxy.tls.cert",
|
||||
targetType: "models.providers.request.proxy.tls.cert",
|
||||
targetTypeAliases: ["models.providers.*.request.proxy.tls.cert"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.request.proxy.tls.cert",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "models.providers.*.request.proxy.tls.key",
|
||||
targetType: "models.providers.request.proxy.tls.key",
|
||||
targetTypeAliases: ["models.providers.*.request.proxy.tls.key"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.request.proxy.tls.key",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "models.providers.*.request.proxy.tls.passphrase",
|
||||
targetType: "models.providers.request.proxy.tls.passphrase",
|
||||
targetTypeAliases: ["models.providers.*.request.proxy.tls.passphrase"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.request.proxy.tls.passphrase",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "models.providers.*.request.tls.ca",
|
||||
targetType: "models.providers.request.tls.ca",
|
||||
targetTypeAliases: ["models.providers.*.request.tls.ca"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.request.tls.ca",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "models.providers.*.request.tls.cert",
|
||||
targetType: "models.providers.request.tls.cert",
|
||||
targetTypeAliases: ["models.providers.*.request.tls.cert"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.request.tls.cert",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "models.providers.*.request.tls.key",
|
||||
targetType: "models.providers.request.tls.key",
|
||||
targetTypeAliases: ["models.providers.*.request.tls.key"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.request.tls.key",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "models.providers.*.request.tls.passphrase",
|
||||
targetType: "models.providers.request.tls.passphrase",
|
||||
targetTypeAliases: ["models.providers.*.request.tls.passphrase"],
|
||||
configFile: "openclaw.json",
|
||||
pathPattern: "models.providers.*.request.tls.passphrase",
|
||||
secretShape: SECRET_INPUT_SHAPE,
|
||||
expectedResolvedValue: "string",
|
||||
includeInPlan: true,
|
||||
includeInConfigure: true,
|
||||
includeInAudit: true,
|
||||
providerIdPathSegmentIndex: 2,
|
||||
},
|
||||
{
|
||||
id: "skills.entries.*.apiKey",
|
||||
targetType: "skills.entries.apiKey",
|
||||
|
||||
Reference in New Issue
Block a user