Compare commits
4
Commits
324549475b
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccd881c689 | ||
|
|
698ce2fa31 | ||
|
|
6953fce7c6 | ||
|
|
52eb90e7c3 |
@@ -56,34 +56,13 @@ const allTargets: {
|
||||
abi?: "musl"
|
||||
avx2?: false
|
||||
}[] = [
|
||||
{
|
||||
os: "linux",
|
||||
arch: "arm64",
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "x64",
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "x64",
|
||||
avx2: false,
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "arm64",
|
||||
abi: "musl",
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "x64",
|
||||
abi: "musl",
|
||||
},
|
||||
{
|
||||
os: "linux",
|
||||
arch: "x64",
|
||||
abi: "musl",
|
||||
avx2: false,
|
||||
},
|
||||
{
|
||||
os: "darwin",
|
||||
@@ -93,24 +72,10 @@ const allTargets: {
|
||||
os: "darwin",
|
||||
arch: "x64",
|
||||
},
|
||||
{
|
||||
os: "darwin",
|
||||
arch: "x64",
|
||||
avx2: false,
|
||||
},
|
||||
{
|
||||
os: "win32",
|
||||
arch: "arm64",
|
||||
},
|
||||
{
|
||||
os: "win32",
|
||||
arch: "x64",
|
||||
},
|
||||
{
|
||||
os: "win32",
|
||||
arch: "x64",
|
||||
avx2: false,
|
||||
},
|
||||
]
|
||||
|
||||
const targets = singleFlag
|
||||
|
||||
@@ -8,6 +8,7 @@ import { ModelsDev } from "@opencode-ai/core/models-dev"
|
||||
import { map, pipe, sortBy, values } from "remeda"
|
||||
import path from "path"
|
||||
import os from "os"
|
||||
import fsNode from "node:fs"
|
||||
import { Config } from "@/config/config"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { Plugin } from "../../plugin"
|
||||
@@ -481,6 +482,38 @@ export const ProvidersLoginCommand = effectCmd({
|
||||
const apiKey = yield* promptValue(key)
|
||||
yield* Effect.orDie(authSvc.set(provider, { type: "api", key: apiKey }))
|
||||
|
||||
// zmo: 询问自定义 base URL(中转地址),留空则用官方默认。
|
||||
// baseURL 不存 auth.json,写入 config 文件的 provider.<id>.options.baseURL。
|
||||
const baseURLInput = yield* Prompt.text({
|
||||
message: "Base URL (中转地址,留空使用官方默认)",
|
||||
placeholder: "https://your-proxy.example.com/v1",
|
||||
})
|
||||
const baseURL = (yield* promptValue(baseURLInput))?.trim()
|
||||
if (baseURL) {
|
||||
try {
|
||||
const configDir = Global.Path.config
|
||||
fsNode.mkdirSync(configDir, { recursive: true })
|
||||
const file = path.join(configDir, "zmo.json")
|
||||
let data: any = {}
|
||||
if (fsNode.existsSync(file)) {
|
||||
try {
|
||||
data = JSON.parse(fsNode.readFileSync(file, "utf8")) ?? {}
|
||||
} catch {
|
||||
data = {}
|
||||
}
|
||||
}
|
||||
if (!data.$schema) data.$schema = "https://zmo.dev/config.json"
|
||||
data.provider ??= {}
|
||||
data.provider[provider] ??= {}
|
||||
data.provider[provider].options ??= {}
|
||||
data.provider[provider].options.baseURL = baseURL
|
||||
fsNode.writeFileSync(file, JSON.stringify(data, null, 2))
|
||||
yield* Prompt.log.info(`Base URL 已保存到 ${file}`)
|
||||
} catch {
|
||||
yield* Prompt.log.warn("Base URL 保存失败,请手动写入 zmo.json")
|
||||
}
|
||||
}
|
||||
|
||||
yield* Prompt.outro("Done")
|
||||
}),
|
||||
})
|
||||
|
||||
@@ -138,7 +138,7 @@ export class Service extends Context.Service<Service, Interface>()("@opencode/Co
|
||||
export const use = serviceUse(Service)
|
||||
|
||||
function globalConfigFile() {
|
||||
const candidates = ["opencode.jsonc", "opencode.json", "config.json"].map((file) =>
|
||||
const candidates = ["zmo.jsonc", "zmo.json", "opencode.jsonc", "opencode.json", "config.json"].map((file) =>
|
||||
path.join(Global.Path.config, file),
|
||||
)
|
||||
for (const file of candidates) {
|
||||
@@ -250,6 +250,8 @@ export const layer = Layer.effect(
|
||||
result = mergeConfig(result, yield* loadFile(path.join(Global.Path.config, "config.json"), env))
|
||||
result = mergeConfig(result, yield* loadFile(path.join(Global.Path.config, "opencode.json"), env))
|
||||
result = mergeConfig(result, yield* loadFile(path.join(Global.Path.config, "opencode.jsonc"), env))
|
||||
result = mergeConfig(result, yield* loadFile(path.join(Global.Path.config, "zmo.json"), env))
|
||||
result = mergeConfig(result, yield* loadFile(path.join(Global.Path.config, "zmo.jsonc"), env))
|
||||
|
||||
const legacy = path.join(Global.Path.config, "config")
|
||||
if (existsSync(legacy)) {
|
||||
@@ -414,7 +416,7 @@ export const layer = Layer.effect(
|
||||
|
||||
for (const dir of directories) {
|
||||
if (dir.endsWith(".opencode") || dir === Flag.OPENCODE_CONFIG_DIR) {
|
||||
for (const file of ["opencode.json", "opencode.jsonc"]) {
|
||||
for (const file of ["zmo.json", "zmo.jsonc", "opencode.json", "opencode.jsonc"]) {
|
||||
const source = path.join(dir, file)
|
||||
log.debug(`loading config from ${source}`)
|
||||
yield* merge(source, yield* loadFile(source, authEnv))
|
||||
@@ -509,7 +511,7 @@ export const layer = Layer.effect(
|
||||
|
||||
const managedDir = ConfigManaged.managedConfigDir()
|
||||
if (existsSync(managedDir)) {
|
||||
for (const file of ["opencode.json", "opencode.jsonc"]) {
|
||||
for (const file of ["zmo.json", "zmo.jsonc", "opencode.json", "opencode.jsonc"]) {
|
||||
const source = path.join(managedDir, file)
|
||||
yield* merge(source, yield* loadFile(source), "global")
|
||||
}
|
||||
|
||||
@@ -1540,6 +1540,17 @@ export const layer = Layer.effect(
|
||||
const provider = s.providers[model.providerID]
|
||||
const options = { ...provider.options }
|
||||
|
||||
// zmo: 支持用环境变量配 baseURL(所有 provider 通用)。
|
||||
// 优先级:config options.baseURL > 专属 <PROVIDER>_BASE_URL > 通用 ZMO_BASE_URL。
|
||||
// 仅当 config 未显式设置 baseURL 时才用环境变量回退。
|
||||
if (typeof options["baseURL"] !== "string" || options["baseURL"] === "") {
|
||||
const envName = model.providerID.toUpperCase().replace(/-/g, "_") + "_BASE_URL"
|
||||
const envBaseURL = envs[envName] ?? envs["ZMO_BASE_URL"]
|
||||
if (typeof envBaseURL === "string" && envBaseURL !== "") {
|
||||
options["baseURL"] = envBaseURL
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
model.providerID === "google-vertex" &&
|
||||
model.api.npm === "@ai-sdk/google-vertex/anthropic" &&
|
||||
|
||||
Reference in New Issue
Block a user