sync
parent
c57216f22d
commit
bbbffbf928
|
|
@ -474,15 +474,7 @@ export namespace Config {
|
|||
.extend({
|
||||
whitelist: z.array(z.string()).optional(),
|
||||
blacklist: z.array(z.string()).optional(),
|
||||
models: z
|
||||
.record(
|
||||
z.string(),
|
||||
ModelsDev.Model.partial().refine(
|
||||
(input) => input.id === undefined,
|
||||
"The model.id field can no longer be specified. Use model.target to specify an alternate model id to use when calling the provider.",
|
||||
),
|
||||
)
|
||||
.optional(),
|
||||
models: z.record(z.string(), ModelsDev.Model.partial()).optional(),
|
||||
options: z
|
||||
.object({
|
||||
apiKey: z.string().optional(),
|
||||
|
|
|
|||
|
|
@ -481,8 +481,14 @@ export namespace Provider {
|
|||
function mergeProvider(providerID: string, provider: Partial<Info>) {
|
||||
const match = database[providerID]
|
||||
if (!match) return
|
||||
// @ts-expect-error
|
||||
providers[providerID] = mergeDeep(match, provider)
|
||||
const existing = providers[providerID]
|
||||
if (existing) {
|
||||
// @ts-expect-error
|
||||
providers[providerID] = mergeDeep(existing, provider)
|
||||
} else {
|
||||
// @ts-expect-error
|
||||
providers[providerID] = mergeDeep(match, provider)
|
||||
}
|
||||
}
|
||||
|
||||
// extend database from config
|
||||
|
|
@ -494,7 +500,7 @@ export namespace Provider {
|
|||
env: provider.env ?? existing?.env ?? [],
|
||||
options: mergeDeep(existing?.options ?? {}, provider.options ?? {}),
|
||||
source: "config",
|
||||
models: {},
|
||||
models: existing?.models ?? {},
|
||||
}
|
||||
|
||||
for (const [modelID, model] of Object.entries(provider.models ?? {})) {
|
||||
|
|
@ -520,18 +526,18 @@ export namespace Provider {
|
|||
attachment: model.attachment ?? existing?.capabilities.attachment ?? false,
|
||||
toolcall: model.tool_call ?? existing?.capabilities.toolcall ?? true,
|
||||
input: {
|
||||
text: model.modalities?.input?.includes("text") ?? false,
|
||||
audio: model.modalities?.input?.includes("audio") ?? false,
|
||||
image: model.modalities?.input?.includes("image") ?? false,
|
||||
video: model.modalities?.input?.includes("video") ?? false,
|
||||
pdf: model.modalities?.input?.includes("pdf") ?? false,
|
||||
text: model.modalities?.input?.includes("text") ?? existing?.capabilities.input.text ?? true,
|
||||
audio: model.modalities?.input?.includes("audio") ?? existing?.capabilities.input.audio ?? false,
|
||||
image: model.modalities?.input?.includes("image") ?? existing?.capabilities.input.image ?? false,
|
||||
video: model.modalities?.input?.includes("video") ?? existing?.capabilities.input.video ?? false,
|
||||
pdf: model.modalities?.input?.includes("pdf") ?? existing?.capabilities.input.pdf ?? false,
|
||||
},
|
||||
output: {
|
||||
text: model.modalities?.output?.includes("text") ?? false,
|
||||
audio: model.modalities?.output?.includes("audio") ?? false,
|
||||
image: model.modalities?.output?.includes("image") ?? false,
|
||||
video: model.modalities?.output?.includes("video") ?? false,
|
||||
pdf: model.modalities?.output?.includes("pdf") ?? false,
|
||||
text: model.modalities?.output?.includes("text") ?? existing?.capabilities.output.text ?? true,
|
||||
audio: model.modalities?.output?.includes("audio") ?? existing?.capabilities.output.audio ?? false,
|
||||
image: model.modalities?.output?.includes("image") ?? existing?.capabilities.output.image ?? false,
|
||||
video: model.modalities?.output?.includes("video") ?? existing?.capabilities.output.video ?? false,
|
||||
pdf: model.modalities?.output?.includes("pdf") ?? existing?.capabilities.output.pdf ?? false,
|
||||
},
|
||||
},
|
||||
cost: {
|
||||
|
|
@ -638,12 +644,11 @@ export namespace Provider {
|
|||
|
||||
// load config
|
||||
for (const [providerID, provider] of configProviders) {
|
||||
mergeProvider(providerID, {
|
||||
source: "config",
|
||||
env: provider.env,
|
||||
name: provider.name,
|
||||
options: provider.options,
|
||||
})
|
||||
const partial: Partial<Info> = { source: "config" }
|
||||
if (provider.env) partial.env = provider.env
|
||||
if (provider.name) partial.name = provider.name
|
||||
if (provider.options) partial.options = provider.options
|
||||
mergeProvider(providerID, partial)
|
||||
}
|
||||
|
||||
for (const [providerID, provider] of Object.entries(providers)) {
|
||||
|
|
|
|||
|
|
@ -634,7 +634,7 @@ test("getModel uses realIdByKey for aliased models", async () => {
|
|||
})
|
||||
})
|
||||
|
||||
test("provider api field sets default baseURL", async () => {
|
||||
test("provider api field sets model api.url", async () => {
|
||||
await using tmp = await tmpdir({
|
||||
init: async (dir) => {
|
||||
await Bun.write(
|
||||
|
|
@ -667,7 +667,8 @@ test("provider api field sets default baseURL", async () => {
|
|||
directory: tmp.path,
|
||||
fn: async () => {
|
||||
const providers = await Provider.list()
|
||||
expect(providers["custom-api"].options.baseURL).toBe("https://api.example.com/v1")
|
||||
// api field is stored on model.api.url, used by getSDK to set baseURL
|
||||
expect(providers["custom-api"].models["model-1"].api.url).toBe("https://api.example.com/v1")
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -1122,8 +1123,8 @@ test("provider with multiple env var options only includes apiKey when single en
|
|||
fn: async () => {
|
||||
const providers = await Provider.list()
|
||||
expect(providers["multi-env"]).toBeDefined()
|
||||
// When multiple env options exist, apiKey should NOT be auto-set
|
||||
expect(providers["multi-env"].options.apiKey).toBeUndefined()
|
||||
// When multiple env options exist, key should NOT be auto-set
|
||||
expect(providers["multi-env"].key).toBeUndefined()
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
@ -1164,8 +1165,8 @@ test("provider with single env var includes apiKey automatically", async () => {
|
|||
fn: async () => {
|
||||
const providers = await Provider.list()
|
||||
expect(providers["single-env"]).toBeDefined()
|
||||
// Single env option should auto-set apiKey
|
||||
expect(providers["single-env"].options.apiKey).toBe("my-api-key")
|
||||
// Single env option should auto-set key
|
||||
expect(providers["single-env"].key).toBe("my-api-key")
|
||||
},
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue