diff --git a/packages/cli/src/sl.test.ts b/packages/cli/src/sl.test.ts index 574420db..b78dfcba 100644 --- a/packages/cli/src/sl.test.ts +++ b/packages/cli/src/sl.test.ts @@ -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 }); diff --git a/packages/cli/src/sl.ts b/packages/cli/src/sl.ts index 5964d4e5..530aef03 100644 --- a/packages/cli/src/sl.ts +++ b/packages/cli/src/sl.ts @@ -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}`,