mirror of
https://github.com/sst/opencode.git
synced 2025-12-23 10:11:41 +00:00
Merge 0c8f4475e9 into 83397ebde2
This commit is contained in:
commit
79ef8b3b49
3 changed files with 182 additions and 1 deletions
|
|
@ -617,6 +617,25 @@ export namespace Config {
|
|||
.describe(
|
||||
"Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout.",
|
||||
),
|
||||
tls: z
|
||||
.object({
|
||||
rejectUnauthorized: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe("Set to false to accept self-signed certificates. Default is true."),
|
||||
cert: z.string().optional().describe("Path to client certificate file (PEM format) for mTLS."),
|
||||
key: z.string().optional().describe("Path to client private key file (PEM format) for mTLS."),
|
||||
ca: z
|
||||
.union([z.string(), z.array(z.string())])
|
||||
.optional()
|
||||
.describe("Path(s) to CA certificate file(s) (PEM format) to trust."),
|
||||
})
|
||||
.optional()
|
||||
.describe("TLS configuration for secure connections, including mTLS and custom CA certificates."),
|
||||
proxy: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe("Proxy URL for this provider (e.g., http://proxy.example.com:8080). Overrides environment variables."),
|
||||
})
|
||||
.catchall(z.any())
|
||||
.optional(),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import z from "zod"
|
||||
import fuzzysort from "fuzzysort"
|
||||
import os from "os"
|
||||
import path from "path"
|
||||
import { Config } from "../config/config"
|
||||
import { mapValues, mergeDeep, sortBy } from "remeda"
|
||||
import { NoSuchModelError, type Provider as SDK } from "ai"
|
||||
|
|
@ -799,9 +801,17 @@ export namespace Provider {
|
|||
if (existing) return existing
|
||||
|
||||
const customFetch = options["fetch"]
|
||||
const tlsConfig = options["tls"] as
|
||||
| {
|
||||
rejectUnauthorized?: boolean
|
||||
cert?: string
|
||||
key?: string
|
||||
ca?: string | string[]
|
||||
}
|
||||
| undefined
|
||||
const proxyUrl = options["proxy"] as string | undefined
|
||||
|
||||
options["fetch"] = async (input: any, init?: BunFetchRequestInit) => {
|
||||
// Preserve custom fetch if it exists, wrap it with timeout logic
|
||||
const fetchFn = customFetch ?? fetch
|
||||
const opts = init ?? {}
|
||||
|
||||
|
|
@ -815,10 +825,39 @@ export namespace Provider {
|
|||
opts.signal = combined
|
||||
}
|
||||
|
||||
let tls: BunFetchRequestInit["tls"] | undefined
|
||||
if (tlsConfig) {
|
||||
tls = {}
|
||||
if (tlsConfig.rejectUnauthorized !== undefined) {
|
||||
tls.rejectUnauthorized = tlsConfig.rejectUnauthorized
|
||||
}
|
||||
if (tlsConfig.cert) {
|
||||
const certPath = tlsConfig.cert.startsWith("~/")
|
||||
? path.join(os.homedir(), tlsConfig.cert.slice(2))
|
||||
: tlsConfig.cert
|
||||
tls.cert = Bun.file(certPath)
|
||||
}
|
||||
if (tlsConfig.key) {
|
||||
const keyPath = tlsConfig.key.startsWith("~/")
|
||||
? path.join(os.homedir(), tlsConfig.key.slice(2))
|
||||
: tlsConfig.key
|
||||
tls.key = Bun.file(keyPath)
|
||||
}
|
||||
if (tlsConfig.ca) {
|
||||
const caFiles = Array.isArray(tlsConfig.ca) ? tlsConfig.ca : [tlsConfig.ca]
|
||||
tls.ca = caFiles.map((p) => {
|
||||
const caPath = p.startsWith("~/") ? path.join(os.homedir(), p.slice(2)) : p
|
||||
return Bun.file(caPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return fetchFn(input, {
|
||||
...opts,
|
||||
// @ts-ignore see here: https://github.com/oven-sh/bun/issues/16682
|
||||
timeout: false,
|
||||
...(tls && { tls }),
|
||||
...(proxyUrl && { proxy: proxyUrl }),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,8 +50,131 @@ For proxies requiring advanced authentication like NTLM or Kerberos, consider us
|
|||
|
||||
If your enterprise uses custom CAs for HTTPS connections, configure OpenCode to trust them.
|
||||
|
||||
### System certificate store
|
||||
|
||||
Use certificates from your operating system's trusted certificate store (macOS Keychain, Windows Certificate Store, or Linux system certificates):
|
||||
|
||||
```bash
|
||||
# Option 1: Set for all Bun executions
|
||||
export BUN_OPTIONS="--use-system-ca"
|
||||
|
||||
# Option 2: Set via NODE_OPTIONS
|
||||
export NODE_OPTIONS="--use-system-ca"
|
||||
```
|
||||
|
||||
This is ideal for enterprise environments where IT has pre-installed certificates in the system store.
|
||||
|
||||
### Extra CA certificates
|
||||
|
||||
To add additional CA certificates without replacing the default bundle:
|
||||
|
||||
```bash
|
||||
export NODE_EXTRA_CA_CERTS=/path/to/ca-cert.pem
|
||||
```
|
||||
|
||||
This works for both proxy connections and direct API access.
|
||||
|
||||
---
|
||||
|
||||
## Per-provider proxy
|
||||
|
||||
Override the global proxy settings for a specific provider:
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": {
|
||||
"anthropic": {
|
||||
"options": {
|
||||
"proxy": "http://proxy.example.com:8080"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This takes precedence over the `HTTPS_PROXY` and `HTTP_PROXY` environment variables for that provider.
|
||||
|
||||
---
|
||||
|
||||
## Per-provider TLS configuration
|
||||
|
||||
For more granular control over TLS settings, you can configure TLS options per provider in your `opencode.json`:
|
||||
|
||||
### Self-signed certificates
|
||||
|
||||
Accept self-signed certificates for a specific provider:
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": {
|
||||
"my-proxy": {
|
||||
"api": "@ai-sdk/openai-compatible",
|
||||
"options": {
|
||||
"baseURL": "https://my-internal-proxy.example.com",
|
||||
"tls": {
|
||||
"rejectUnauthorized": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::caution
|
||||
Disabling certificate validation (`rejectUnauthorized: false`) bypasses TLS security checks. Only use this for trusted internal services.
|
||||
:::
|
||||
|
||||
### Custom CA certificates
|
||||
|
||||
Trust a custom CA certificate for a provider:
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": {
|
||||
"my-proxy": {
|
||||
"options": {
|
||||
"baseURL": "https://my-internal-proxy.example.com",
|
||||
"tls": {
|
||||
"ca": "/path/to/ca-cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can also specify multiple CA certificates:
|
||||
|
||||
```json
|
||||
{
|
||||
"tls": {
|
||||
"ca": ["/path/to/ca1.pem", "/path/to/ca2.pem"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## mTLS (Mutual TLS)
|
||||
|
||||
For services requiring client certificate authentication, configure both the certificate and private key:
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": {
|
||||
"mtls-proxy": {
|
||||
"api": "@ai-sdk/anthropic",
|
||||
"options": {
|
||||
"baseURL": "https://llm-proxy-mtls.internal.example.com",
|
||||
"tls": {
|
||||
"cert": "/path/to/client-cert.pem",
|
||||
"key": "/path/to/client-key.pem",
|
||||
"ca": "/path/to/ca-cert.pem"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This is useful for enterprise environments with mTLS proxies that provide access to LLM APIs.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue