mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-22 08:38:08 +02:00
fix(cli): resolve managed-embeddings daemon URL at project boundary (#184)
A clean `ktx setup` was failing verification because the managed local-embeddings daemon URL was passed library-side through `process.env[KTX_MANAGED_SENTENCE_TRANSFORMERS_BASE_URL]`, and the setup flow never wrote that variable. With no resolved URL the embedding provider was null, the deep scan emitted `scan_enrichment_backend_not_configured`, descriptions + embeddings stayed `skipped`, and the agent-readiness check exited 1. Replace the env-var indirection with CLI-side substitution at the project-load boundary. New `loadKtxCliProject` wraps `loadKtxProject`, ensures the managed daemon when `managed:local-embeddings` is present in `config.ingest.embeddings` or `config.scan.enrichment.embeddings`, and substitutes the resolved baseUrl into the in-memory config. Runtime entry points (scan, ingest, public-ingest, admin-reindex) use the new loader; setup-time persistence paths keep raw `loadKtxProject` so the on-disk `ktx.yaml` keeps the portable sentinel. Cleanup follows from the new design: drop `MANAGED_SENTENCE_TRANSFORMERS_BASE_URL_ENV`, remove the env-var lookup branch in `resolveSentenceTransformersBaseUrl`, drop the `env` field from `ManagedLocalEmbeddingsDaemon`, and collapse the manual daemon-ensure dance in `admin-reindex.ts`.
This commit is contained in:
parent
ad9c9eda0d
commit
c24e07a115
12 changed files with 318 additions and 95 deletions
91
packages/cli/src/cli-project.ts
Normal file
91
packages/cli/src/cli-project.ts
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import { MANAGED_SENTENCE_TRANSFORMERS_BASE_URL } from '@ktx/context';
|
||||
import { loadKtxProject, type KtxLocalProject } from '@ktx/context/project';
|
||||
import type { KtxProjectConfig, KtxProjectEmbeddingConfig } from '@ktx/context/project';
|
||||
import type { KtxCliIo } from './cli-runtime.js';
|
||||
import {
|
||||
ensureManagedLocalEmbeddingsDaemon,
|
||||
type ManagedLocalEmbeddingsDaemon,
|
||||
} from './managed-local-embeddings.js';
|
||||
import type { KtxManagedPythonInstallPolicy } from './managed-python-command.js';
|
||||
|
||||
export interface LoadKtxCliProjectOptions {
|
||||
projectDir: string;
|
||||
cliVersion: string;
|
||||
installPolicy: KtxManagedPythonInstallPolicy;
|
||||
io: KtxCliIo;
|
||||
}
|
||||
|
||||
export interface LoadKtxCliProjectDeps {
|
||||
loadProject?: typeof loadKtxProject;
|
||||
ensureLocalEmbeddings?: (
|
||||
options: Parameters<typeof ensureManagedLocalEmbeddingsDaemon>[0],
|
||||
) => Promise<ManagedLocalEmbeddingsDaemon>;
|
||||
}
|
||||
|
||||
export async function loadKtxCliProject(
|
||||
options: LoadKtxCliProjectOptions,
|
||||
deps: LoadKtxCliProjectDeps = {},
|
||||
): Promise<KtxLocalProject> {
|
||||
const loadProject = deps.loadProject ?? loadKtxProject;
|
||||
const ensureLocalEmbeddings = deps.ensureLocalEmbeddings ?? ensureManagedLocalEmbeddingsDaemon;
|
||||
|
||||
const project = await loadProject({ projectDir: options.projectDir });
|
||||
if (!projectNeedsManagedLocalEmbeddings(project.config)) {
|
||||
return project;
|
||||
}
|
||||
|
||||
const daemon = await ensureLocalEmbeddings({
|
||||
cliVersion: options.cliVersion,
|
||||
projectDir: options.projectDir,
|
||||
installPolicy: options.installPolicy,
|
||||
io: options.io,
|
||||
});
|
||||
|
||||
return {
|
||||
...project,
|
||||
config: substituteManagedLocalEmbeddingsUrl(project.config, daemon.baseUrl),
|
||||
};
|
||||
}
|
||||
|
||||
export function projectNeedsManagedLocalEmbeddings(config: KtxProjectConfig): boolean {
|
||||
return (
|
||||
embeddingUsesManagedSentinel(config.ingest.embeddings) ||
|
||||
embeddingUsesManagedSentinel(config.scan.enrichment.embeddings)
|
||||
);
|
||||
}
|
||||
|
||||
export function substituteManagedLocalEmbeddingsUrl(
|
||||
config: KtxProjectConfig,
|
||||
baseUrl: string,
|
||||
): KtxProjectConfig {
|
||||
const ingestEmbeddings = rewriteManagedEmbeddingConfig(config.ingest.embeddings, baseUrl);
|
||||
const scanEnrichmentEmbeddings = rewriteManagedEmbeddingConfig(config.scan.enrichment.embeddings, baseUrl);
|
||||
return {
|
||||
...config,
|
||||
ingest: { ...config.ingest, embeddings: ingestEmbeddings },
|
||||
scan: {
|
||||
...config.scan,
|
||||
enrichment: { ...config.scan.enrichment, embeddings: scanEnrichmentEmbeddings },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function embeddingUsesManagedSentinel(embedding: KtxProjectEmbeddingConfig | undefined): boolean {
|
||||
return embedding?.sentenceTransformers?.base_url === MANAGED_SENTENCE_TRANSFORMERS_BASE_URL;
|
||||
}
|
||||
|
||||
function rewriteManagedEmbeddingConfig<T extends KtxProjectEmbeddingConfig | undefined>(
|
||||
embedding: T,
|
||||
baseUrl: string,
|
||||
): T {
|
||||
if (!embedding || !embeddingUsesManagedSentinel(embedding)) {
|
||||
return embedding;
|
||||
}
|
||||
return {
|
||||
...embedding,
|
||||
sentenceTransformers: {
|
||||
...embedding.sentenceTransformers,
|
||||
base_url: baseUrl,
|
||||
},
|
||||
} as T;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue