feat(cli): surface embeddings-unavailable status when sl search returns empty

This commit is contained in:
Andrey Avtomonov 2026-05-21 01:47:49 +02:00
parent 1a48ff02a9
commit d63818a790
2 changed files with 39 additions and 0 deletions

View file

@ -627,6 +627,41 @@ joins: []
});
});
it('search prints embeddings status when results are empty', async () => {
const stderr: string[] = [];
const io = {
stdout: { write: (_chunk: string) => {} },
stderr: {
write: (chunk: string) => {
stderr.push(chunk);
},
},
};
const projectDir = join(tempDir, 'empty-status');
const project = await initKtxProject({ projectDir });
await expect(
runKtxSl(
{
command: 'search',
projectDir: project.projectDir,
query: 'nope',
cliVersion: '0.5.0',
},
io,
{
loadProject: async () => project,
resolveEmbeddingProvider: async () => ({
kind: 'managed-unavailable',
reason: 'managed embeddings daemon is not running',
}),
searchLocalSlSources: async () => [],
},
),
).resolves.toBe(0);
expect(stderr.join('')).toMatch(/embeddings: unavailable/);
expect(stderr.join('')).toMatch(/managed embeddings daemon is not running/);
});
it('passes a managed-daemon-backed embedding service into the search', async () => {
const projectDir = join(tempDir, 'resolver-project');
const project = await initKtxProject({ projectDir });

View file

@ -211,6 +211,10 @@ export async function runKtxSl(args: KtxSlArgs, io: KtxSlIo = process, deps: Ktx
embeddingService,
limit: args.limit,
});
if (sources.length === 0 && resolution.kind === 'managed-unavailable' && !args.json) {
const { SYMBOLS } = await import('./io/symbols.js');
io.stderr.write(`embeddings: unavailable ${SYMBOLS.emDash} ${resolution.reason}\n`);
}
await printSlSources({
rows: sources,
emptyMessage: `No semantic-layer sources matched "${args.query}" in ${project.projectDir}`,