mirror of
https://github.com/DayuanJiang/next-ai-draw-io.git
synced 2026-09-03 01:50:23 +08:00
* [Feature] Server side multi-pvorider/model support * copilot suggesition implemented * feat: improve model selector UI and auto-select default server model - Replace emoji headers with Lucide icons (Monitor, User) - Fix transition-all to explicit properties per web guidelines - Use CSS padding instead of hardcoded space indentation - Add ModelSelectorSectionHeader component for section headers - Replace Star icon with "default" text label - Style Configure button with muted text color - Auto-select default server model when page loads - Support AI_MODELS_CONFIG env var for cloud deployments - Support custom apiKeyEnv/baseUrlEnv per provider config * docs: update server-side multi-model configuration documentation - Add AI_MODELS_CONFIG env var option for cloud deployments - Document apiKeyEnv and baseUrlEnv fields for custom env var names - Document default field for auto-selecting default model - Remove deprecated version field from examples - Add field reference table for clarity --------- Co-authored-by: dayuan.jiang <jdy.toh@gmail.com>
86 lines
2.7 KiB
TypeScript
86 lines
2.7 KiB
TypeScript
import { afterEach, describe, expect, it } from "vitest"
|
|
import {
|
|
loadFlattenedServerModels,
|
|
type ServerModelsConfig,
|
|
ServerModelsConfigSchema,
|
|
} from "@/lib/server-model-config"
|
|
|
|
const ORIGINAL_ENV = { ...process.env }
|
|
|
|
afterEach(() => {
|
|
process.env.AI_PROVIDER = ORIGINAL_ENV.AI_PROVIDER
|
|
process.env.AI_MODEL = ORIGINAL_ENV.AI_MODEL
|
|
process.env.AI_MODELS_CONFIG_PATH = ORIGINAL_ENV.AI_MODELS_CONFIG_PATH
|
|
process.env.AI_MODELS_CONFIG = ORIGINAL_ENV.AI_MODELS_CONFIG
|
|
})
|
|
|
|
describe("ServerModelsConfigSchema", () => {
|
|
it("accepts valid provider names", () => {
|
|
const config: ServerModelsConfig = {
|
|
providers: [
|
|
{
|
|
name: "OpenAI Server",
|
|
provider: "openai",
|
|
models: ["gpt-4o"],
|
|
},
|
|
],
|
|
}
|
|
|
|
expect(() => ServerModelsConfigSchema.parse(config)).not.toThrow()
|
|
})
|
|
|
|
it("rejects invalid provider names", () => {
|
|
const invalidConfig = {
|
|
providers: [
|
|
{
|
|
name: "Invalid Provider",
|
|
// Cast to any so we can verify runtime validation, not TypeScript
|
|
provider: "invalid-provider" as any,
|
|
models: ["model-1"],
|
|
},
|
|
],
|
|
}
|
|
|
|
expect(() =>
|
|
ServerModelsConfigSchema.parse(invalidConfig as any),
|
|
).toThrow()
|
|
})
|
|
})
|
|
|
|
describe("loadFlattenedServerModels", () => {
|
|
it("returns empty array when config file is missing", async () => {
|
|
// Point to a non-existent config path so fs.readFile throws ENOENT
|
|
process.env.AI_MODELS_CONFIG_PATH = `non-existent-config-${Date.now()}.json`
|
|
|
|
const models = await loadFlattenedServerModels()
|
|
expect(models).toEqual([])
|
|
})
|
|
|
|
it("flattens providers and marks default model from env var config", async () => {
|
|
// Use AI_MODELS_CONFIG env var instead of file
|
|
const config: ServerModelsConfig = {
|
|
providers: [
|
|
{
|
|
name: "OpenAI Server",
|
|
provider: "openai",
|
|
models: ["gpt-4o", "gpt-4o-mini"],
|
|
default: true,
|
|
},
|
|
],
|
|
}
|
|
process.env.AI_MODELS_CONFIG = JSON.stringify(config)
|
|
process.env.AI_MODELS_CONFIG_PATH = "" // Clear file path
|
|
|
|
const models = await loadFlattenedServerModels()
|
|
|
|
expect(models.length).toBe(2)
|
|
|
|
const defaults = models.filter((m) => m.isDefault)
|
|
expect(defaults.length).toBe(1)
|
|
|
|
const defaultModel = defaults[0]
|
|
expect(defaultModel.provider).toBe("openai")
|
|
expect(defaultModel.modelId).toBe("gpt-4o") // First model of default provider
|
|
})
|
|
})
|