mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-07 07:55:13 +02:00
fix(cli): treat omitted sentence-transformers base_url as managed daemon
After PR #184 and #192 moved managed-embeddings URL resolution to the CLI project boundary and made `ktx setup` persist `ktx.yaml` without a `base_url`, the status command still treated the empty value as misconfiguration and printed "no base_url configured", dragging the verdict down to "Partially ready — embedding credentials missing". Update `buildEmbeddingsStatus` to recognize the managed-daemon convention and report it as ok. Add a `status-project.test.ts` covering the explicit-url, omitted, empty-string, and openai-missing-key paths.
This commit is contained in:
parent
7737ccaf1a
commit
31c3ccea9d
2 changed files with 128 additions and 3 deletions
126
packages/cli/src/status-project.test.ts
Normal file
126
packages/cli/src/status-project.test.ts
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import { buildDefaultKtxProjectConfig, type KtxLocalProject, type KtxProjectConfig } from '@ktx/context/project';
|
||||
import { buildProjectStatus } from './status-project.js';
|
||||
|
||||
function projectWithConfig(config: KtxProjectConfig): KtxLocalProject {
|
||||
return {
|
||||
projectDir: '/work/proj',
|
||||
configPath: '/work/proj/ktx.yaml',
|
||||
config,
|
||||
coreConfig: {} as KtxLocalProject['coreConfig'],
|
||||
git: {} as KtxLocalProject['git'],
|
||||
fileStore: {} as KtxLocalProject['fileStore'],
|
||||
};
|
||||
}
|
||||
|
||||
function withEmbeddings(
|
||||
config: KtxProjectConfig,
|
||||
embeddings: KtxProjectConfig['ingest']['embeddings'],
|
||||
): KtxProjectConfig {
|
||||
return {
|
||||
...config,
|
||||
ingest: { ...config.ingest, embeddings },
|
||||
scan: { ...config.scan, enrichment: { ...config.scan.enrichment, embeddings } },
|
||||
};
|
||||
}
|
||||
|
||||
function withClaudeCodeLlm(config: KtxProjectConfig): KtxProjectConfig {
|
||||
return {
|
||||
...config,
|
||||
llm: {
|
||||
...config.llm,
|
||||
provider: { backend: 'claude-code' },
|
||||
models: { ...config.llm.models, default: 'sonnet' },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function baseProjectConfig(): KtxProjectConfig {
|
||||
return withClaudeCodeLlm(buildDefaultKtxProjectConfig());
|
||||
}
|
||||
|
||||
const stubClaudeCodeAuthProbe = async () => ({ ok: true as const });
|
||||
|
||||
describe('buildProjectStatus embeddings', () => {
|
||||
it('reports sentence-transformers with explicit base_url as ok', async () => {
|
||||
const project = projectWithConfig(
|
||||
withEmbeddings(baseProjectConfig(), {
|
||||
backend: 'sentence-transformers',
|
||||
model: 'all-MiniLM-L6-v2',
|
||||
dimensions: 384,
|
||||
sentenceTransformers: { base_url: 'http://my-st:8080', pathPrefix: '' },
|
||||
}),
|
||||
);
|
||||
|
||||
const status = await buildProjectStatus(project, {
|
||||
claudeCodeAuthProbe: stubClaudeCodeAuthProbe,
|
||||
});
|
||||
|
||||
expect(status.embeddings).toMatchObject({
|
||||
backend: 'sentence-transformers',
|
||||
status: 'ok',
|
||||
detail: 'service: http://my-st:8080',
|
||||
});
|
||||
});
|
||||
|
||||
it('reports sentence-transformers with omitted base_url as managed daemon (ok)', async () => {
|
||||
const project = projectWithConfig(
|
||||
withEmbeddings(baseProjectConfig(), {
|
||||
backend: 'sentence-transformers',
|
||||
model: 'all-MiniLM-L6-v2',
|
||||
dimensions: 384,
|
||||
}),
|
||||
);
|
||||
|
||||
const status = await buildProjectStatus(project, {
|
||||
claudeCodeAuthProbe: stubClaudeCodeAuthProbe,
|
||||
});
|
||||
|
||||
expect(status.embeddings).toMatchObject({
|
||||
backend: 'sentence-transformers',
|
||||
status: 'ok',
|
||||
detail: 'managed local embeddings daemon',
|
||||
});
|
||||
expect(status.verdictReason).not.toMatch(/embedding credentials missing/);
|
||||
});
|
||||
|
||||
it('reports sentence-transformers with empty base_url string as managed daemon (ok)', async () => {
|
||||
const project = projectWithConfig(
|
||||
withEmbeddings(baseProjectConfig(), {
|
||||
backend: 'sentence-transformers',
|
||||
model: 'all-MiniLM-L6-v2',
|
||||
dimensions: 384,
|
||||
sentenceTransformers: { base_url: '', pathPrefix: '' },
|
||||
}),
|
||||
);
|
||||
|
||||
const status = await buildProjectStatus(project, {
|
||||
claudeCodeAuthProbe: stubClaudeCodeAuthProbe,
|
||||
});
|
||||
|
||||
expect(status.embeddings).toMatchObject({
|
||||
backend: 'sentence-transformers',
|
||||
status: 'ok',
|
||||
detail: 'managed local embeddings daemon',
|
||||
});
|
||||
});
|
||||
|
||||
it('reports openai backend with missing key as warn', async () => {
|
||||
const project = projectWithConfig(
|
||||
withEmbeddings(baseProjectConfig(), {
|
||||
backend: 'openai',
|
||||
model: 'text-embedding-3-small',
|
||||
dimensions: 1536,
|
||||
openai: { api_key: 'env:OPENAI_API_KEY' }, // pragma: allowlist secret
|
||||
}),
|
||||
);
|
||||
|
||||
const status = await buildProjectStatus(project, {
|
||||
env: {},
|
||||
claudeCodeAuthProbe: stubClaudeCodeAuthProbe,
|
||||
});
|
||||
|
||||
expect(status.embeddings.status).toBe('warn');
|
||||
expect(status.verdictReason).toMatch(/embedding credentials missing/);
|
||||
});
|
||||
});
|
||||
|
|
@ -267,9 +267,8 @@ function buildEmbeddingsStatus(config: KtxProjectEmbeddingConfig, env: NodeJS.Pr
|
|||
backend,
|
||||
model,
|
||||
dimensions,
|
||||
status: 'warn',
|
||||
detail: 'no base_url configured',
|
||||
fix: 'Rerun `ktx setup`',
|
||||
status: 'ok',
|
||||
detail: 'managed local embeddings daemon',
|
||||
};
|
||||
}
|
||||
return { backend, model, dimensions, status: 'warn', detail: 'unknown embedding backend' };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue