feat: unify installation model catalog
This commit is contained in:
+32
-2
@@ -32,6 +32,7 @@ export interface AppConfig {
|
||||
piManagementTimeoutMs: number;
|
||||
secretsFile?: string;
|
||||
installationConfigFile?: string;
|
||||
modelCatalogFile?: string;
|
||||
piAuthFile?: string;
|
||||
secretFiles: Readonly<Record<string, string | undefined>>;
|
||||
modelApiKeyFile?: string;
|
||||
@@ -50,6 +51,7 @@ export interface AppConfig {
|
||||
workspaceSecretRuntimeRoot: string;
|
||||
internalQdrantUrl: string;
|
||||
internalEmbeddingUrl: string;
|
||||
internalEmbeddingId: string;
|
||||
internalEmbeddingModel: string;
|
||||
internalEmbeddingDimensions: number;
|
||||
}
|
||||
@@ -189,6 +191,21 @@ function positiveDimension(value: string | undefined, fallback: number): number
|
||||
return parsed;
|
||||
}
|
||||
|
||||
function internalEmbeddingIdentity(
|
||||
identityValue: string | undefined,
|
||||
modelValue: string | undefined,
|
||||
): { id: string; model: string } {
|
||||
const id = identityValue ?? "ollama/qwen3-embedding:0.6b";
|
||||
if (!/^ollama\/[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/.test(id)) {
|
||||
throw new Error("internal embedding identity configuration is invalid");
|
||||
}
|
||||
const model = id.slice(id.indexOf("/") + 1);
|
||||
if (modelValue !== undefined && modelValue !== model) {
|
||||
throw new Error("internal embedding model does not match its canonical identity");
|
||||
}
|
||||
return { id, model };
|
||||
}
|
||||
|
||||
function catalogDatabase(env: Record<string, string | undefined>): CatalogConnectionConfig | undefined {
|
||||
const value = env.THT_CATALOG_DATABASE_URL;
|
||||
if (value !== undefined) {
|
||||
@@ -330,6 +347,13 @@ export function loadConfig(
|
||||
|| installationConfigFile.includes("\0")
|
||||
|| !path.isAbsolute(installationConfigFile)
|
||||
)) throw new Error("installation configuration is invalid");
|
||||
const modelCatalogFile = env.THT_MODEL_CATALOG_FILE;
|
||||
if (modelCatalogFile !== undefined && (
|
||||
modelCatalogFile.trim() !== modelCatalogFile
|
||||
|| modelCatalogFile.length === 0
|
||||
|| modelCatalogFile.includes("\0")
|
||||
|| !path.isAbsolute(modelCatalogFile)
|
||||
)) throw new Error("runtime model catalog configuration is invalid");
|
||||
const piAuthFile = env.THT_PI_AUTH_FILE;
|
||||
if (piAuthFile !== undefined && (
|
||||
piAuthFile.trim() !== piAuthFile || piAuthFile.length === 0 || piAuthFile.includes("\0")
|
||||
@@ -391,6 +415,10 @@ export function loadConfig(
|
||||
"internal embedding URL",
|
||||
["embedding", "localhost"],
|
||||
);
|
||||
const internalEmbedding = internalEmbeddingIdentity(
|
||||
env.THT_INTERNAL_EMBEDDING_ID,
|
||||
env.THT_INTERNAL_EMBEDDING_MODEL,
|
||||
);
|
||||
return {
|
||||
host: env.HOST ?? "127.0.0.1",
|
||||
port: Number(env.PORT ?? 8787),
|
||||
@@ -404,7 +432,7 @@ export function loadConfig(
|
||||
publicExposure,
|
||||
sessionStorage,
|
||||
catalogDatabase: catalogDatabase(env),
|
||||
defaults: { provider: env.PI_PROVIDER, model: env.PI_MODEL, thinking: env.PI_THINKING },
|
||||
defaults: { thinking: env.PI_THINKING },
|
||||
maxPiProcesses: Number(env.MAX_PI_PROCESSES ?? 4),
|
||||
settingsFile,
|
||||
maintenanceFile: env.THT_MAINTENANCE_FILE ?? path.join(path.dirname(settingsFile), "maintenance.json"),
|
||||
@@ -413,6 +441,7 @@ export function loadConfig(
|
||||
piManagementTimeoutMs: piManagementTimeout(env.PI_MANAGEMENT_TIMEOUT_MS),
|
||||
secretsFile,
|
||||
installationConfigFile,
|
||||
modelCatalogFile,
|
||||
piAuthFile,
|
||||
secretFiles,
|
||||
modelApiKeyFile,
|
||||
@@ -425,7 +454,8 @@ export function loadConfig(
|
||||
workspaceSecretRuntimeRoot,
|
||||
internalQdrantUrl,
|
||||
internalEmbeddingUrl,
|
||||
internalEmbeddingModel: env.THT_INTERNAL_EMBEDDING_MODEL ?? "qwen3-embedding:0.6b",
|
||||
internalEmbeddingId: internalEmbedding.id,
|
||||
internalEmbeddingModel: internalEmbedding.model,
|
||||
internalEmbeddingDimensions: positiveDimension(env.THT_INTERNAL_EMBEDDING_DIMENSIONS, 1024),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user