ktx/packages/cli/src/setup-embeddings.ts

500 lines
17 KiB
TypeScript
Raw Normal View History

import { readFile, writeFile } from 'node:fs/promises';
import { resolveKtxConfigReference } from './context/core/index.js';
2026-05-10 23:12:26 +02:00
import {
2026-05-10 23:51:24 +02:00
type KtxProjectConfig,
type KtxProjectEmbeddingConfig,
loadKtxProject,
markKtxSetupStateStepComplete,
readKtxSetupState,
2026-05-10 23:51:24 +02:00
serializeKtxProjectConfig,
} from './context/project/index.js';
import { type KtxEmbeddingConfig, type KtxEmbeddingHealthCheckResult, runKtxEmbeddingHealthCheck } from './llm/index.js';
2026-05-10 23:51:24 +02:00
import type { KtxCliIo } from './cli-runtime.js';
import { createStaticCliSpinner, type KtxCliSpinner } from './clack.js';
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
import {
ensureManagedLocalEmbeddingsDaemon,
managedLocalEmbeddingHealthConfig,
type ManagedLocalEmbeddingsDaemon,
} from './managed-local-embeddings.js';
import type { KtxManagedPythonInstallPolicy } from './managed-python-command.js';
import { withTextInputNavigation } from './prompt-navigation.js';
2026-05-10 23:12:26 +02:00
import { envCredentialReference, writeProjectLocalSecretReference } from './setup-secrets.js';
import {
createKtxSetupPromptAdapter,
type KtxSetupPromptOption,
} from './setup-prompts.js';
2026-05-10 23:12:26 +02:00
2026-05-10 23:51:24 +02:00
export type KtxSetupEmbeddingBackend = 'openai' | 'sentence-transformers';
2026-05-10 23:12:26 +02:00
2026-05-10 23:51:24 +02:00
export interface KtxSetupEmbeddingsArgs {
2026-05-10 23:12:26 +02:00
projectDir: string;
inputMode: 'auto' | 'disabled';
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
cliVersion: string;
runtimeInstallPolicy: KtxManagedPythonInstallPolicy;
2026-05-10 23:51:24 +02:00
embeddingBackend?: KtxSetupEmbeddingBackend;
2026-05-10 23:12:26 +02:00
embeddingApiKeyEnv?: string;
embeddingApiKeyFile?: string;
forcePrompt?: boolean;
showPromptInstructions?: boolean;
skipEmbeddings: boolean;
}
2026-05-10 23:51:24 +02:00
export type KtxSetupEmbeddingsResult =
2026-05-10 23:12:26 +02:00
| { status: 'ready'; projectDir: string }
| { status: 'skipped'; projectDir: string }
| { status: 'back'; projectDir: string }
| { status: 'missing-input'; projectDir: string }
| { status: 'failed'; projectDir: string };
/** @internal */
2026-05-10 23:51:24 +02:00
export interface KtxSetupEmbeddingsPromptAdapter {
select(options: { message: string; options: KtxSetupPromptOption[] }): Promise<string>;
2026-05-10 23:12:26 +02:00
password(options: { message: string }): Promise<string | undefined>;
cancel(message: string): void;
}
2026-05-10 23:51:24 +02:00
export interface KtxSetupEmbeddingsDeps {
2026-05-10 23:12:26 +02:00
env?: NodeJS.ProcessEnv;
2026-05-10 23:51:24 +02:00
prompts?: KtxSetupEmbeddingsPromptAdapter;
healthCheck?: (config: KtxEmbeddingConfig) => Promise<KtxEmbeddingHealthCheckResult>;
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
ensureLocalEmbeddings?: (options: {
cliVersion: string;
projectDir: string;
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
installPolicy: KtxManagedPythonInstallPolicy;
io: KtxCliIo;
}) => Promise<ManagedLocalEmbeddingsDaemon>;
spinner?: () => KtxCliSpinner;
2026-05-10 23:12:26 +02:00
}
2026-05-10 23:51:24 +02:00
type BackendChoice = KtxSetupEmbeddingBackend | 'back';
2026-05-10 23:12:26 +02:00
const DEFAULTS: Record<
2026-05-10 23:51:24 +02:00
KtxSetupEmbeddingBackend,
2026-05-10 23:12:26 +02:00
{ model: string; dimensions: number; envName?: string; baseUrl?: string; pathPrefix?: string }
> = {
openai: { model: 'text-embedding-3-small', dimensions: 1536, envName: 'OPENAI_API_KEY' },
'sentence-transformers': {
model: 'all-MiniLM-L6-v2',
dimensions: 384,
baseUrl: 'http://127.0.0.1:8765',
pathPrefix: '',
},
};
2026-05-10 23:51:24 +02:00
const LOCAL_EMBEDDING_BACKEND: KtxSetupEmbeddingBackend = 'sentence-transformers';
2026-05-10 23:12:26 +02:00
const EMBEDDING_OPTION_PROMPT_CONTEXT =
2026-05-10 23:51:24 +02:00
'KTX uses embeddings for semantic search over semantic-layer sources, wiki context, schema metadata, ' +
2026-05-10 23:12:26 +02:00
'and relationship evidence.';
const LOCAL_EMBEDDING_HEALTH_TIMEOUT_MS = 120_000;
const LOCAL_EMBEDDING_STDERR_TAIL_LINES = 40;
2026-05-10 23:12:26 +02:00
2026-05-10 23:51:24 +02:00
function createPromptAdapter(): KtxSetupEmbeddingsPromptAdapter {
return createKtxSetupPromptAdapter({ selectCancelValue: 'back' });
2026-05-10 23:12:26 +02:00
}
async function hasCompletedEmbeddings(projectDir: string, config: KtxProjectConfig): Promise<boolean> {
2026-05-10 23:12:26 +02:00
return (
(await readKtxSetupState(projectDir)).completed_steps.includes('embeddings') &&
2026-05-10 23:12:26 +02:00
config.ingest.embeddings.backend !== 'none' &&
typeof config.ingest.embeddings.model === 'string' &&
config.ingest.embeddings.model.length > 0 &&
config.ingest.embeddings.dimensions > 0
);
}
function buildProjectEmbeddingConfig(input: {
2026-05-10 23:51:24 +02:00
backend: KtxSetupEmbeddingBackend;
2026-05-10 23:12:26 +02:00
model: string;
dimensions: number;
credentialRef?: string;
2026-05-10 23:51:24 +02:00
}): KtxProjectEmbeddingConfig {
2026-05-10 23:12:26 +02:00
if (input.backend === 'openai') {
return {
backend: 'openai',
model: input.model,
dimensions: input.dimensions,
openai: {
...(input.credentialRef ? { api_key: input.credentialRef } : {}),
},
};
}
const defaults = DEFAULTS[input.backend];
return {
backend: input.backend,
model: input.model,
dimensions: input.dimensions,
sentenceTransformers: {
base_url: defaults.baseUrl ?? '',
pathPrefix: defaults.pathPrefix ?? '',
},
};
}
function buildHealthConfig(input: {
2026-05-10 23:51:24 +02:00
backend: KtxSetupEmbeddingBackend;
2026-05-10 23:12:26 +02:00
model: string;
dimensions: number;
credentialValue?: string;
2026-05-10 23:51:24 +02:00
}): KtxEmbeddingConfig {
2026-05-10 23:12:26 +02:00
if (input.backend === 'openai') {
return {
backend: 'openai',
model: input.model,
dimensions: input.dimensions,
openai: {
...(input.credentialValue ? { apiKey: input.credentialValue } : {}),
},
};
}
const defaults = DEFAULTS[input.backend];
return {
backend: input.backend,
model: input.model,
dimensions: input.dimensions,
sentenceTransformers: {
baseURL: defaults.baseUrl ?? '',
pathPrefix: defaults.pathPrefix ?? '',
},
};
}
2026-05-10 23:51:24 +02:00
function embeddingBackendDisplayName(backend: KtxSetupEmbeddingBackend): string {
2026-05-10 23:12:26 +02:00
if (backend === 'openai') {
return 'OpenAI';
}
return 'sentence-transformers';
}
2026-05-10 23:51:24 +02:00
async function persistEmbeddingConfig(projectDir: string, embeddings: KtxProjectEmbeddingConfig): Promise<void> {
const project = await loadKtxProject({ projectDir });
const config = {
...project.config,
ingest: {
...project.config.ingest,
embeddings,
},
scan: {
...project.config.scan,
enrichment: {
...project.config.scan.enrichment,
2026-05-10 23:12:26 +02:00
embeddings,
},
},
};
2026-05-10 23:51:24 +02:00
await writeFile(project.configPath, serializeKtxProjectConfig(config), 'utf-8');
await markKtxSetupStateStepComplete(projectDir, 'embeddings');
2026-05-10 23:12:26 +02:00
}
async function chooseCredentialRef(
2026-05-10 23:51:24 +02:00
backend: Extract<KtxSetupEmbeddingBackend, 'openai'>,
args: KtxSetupEmbeddingsArgs,
io: KtxCliIo,
deps: KtxSetupEmbeddingsDeps,
2026-05-10 23:12:26 +02:00
): Promise<{ status: 'ready'; ref: string; value: string } | { status: 'back' | 'missing-input' }> {
const env = deps.env ?? process.env;
if (args.embeddingApiKeyEnv) {
const ref = envCredentialReference(args.embeddingApiKeyEnv);
2026-05-10 23:51:24 +02:00
const value = resolveKtxConfigReference(ref, env);
2026-05-10 23:12:26 +02:00
if (!value) {
io.stderr.write(`Missing embedding API key: ${args.embeddingApiKeyEnv} is not set.\n`);
return { status: 'missing-input' };
}
return { status: 'ready', ref, value };
}
if (args.embeddingApiKeyFile) {
const ref = `file:${args.embeddingApiKeyFile}`;
let value: string | undefined;
try {
2026-05-10 23:51:24 +02:00
value = resolveKtxConfigReference(ref, env);
2026-05-10 23:12:26 +02:00
} catch {
value = undefined;
}
if (!value) {
io.stderr.write(`Missing embedding API key file: ${args.embeddingApiKeyFile}\n`);
return { status: 'missing-input' };
}
return { status: 'ready', ref, value };
}
if (args.inputMode === 'disabled') {
io.stderr.write('Missing embedding API key: pass --embedding-api-key-env or --embedding-api-key-file.\n');
return { status: 'missing-input' };
}
const defaultEnv = DEFAULTS[backend].envName ?? 'EMBEDDING_API_KEY';
const prompts = deps.prompts ?? createPromptAdapter();
const choice = await prompts.select({
2026-05-10 23:51:24 +02:00
message: `How should KTX find your ${embeddingBackendDisplayName(backend)} embedding API key?`,
2026-05-10 23:12:26 +02:00
options: [
{ value: 'env', label: `Use ${defaultEnv} from the environment` },
{ value: 'paste', label: 'Paste a key and save it as a local secret file' },
{ value: 'back', label: 'Back' },
],
});
if (choice === 'back') {
return { status: 'back' };
}
if (choice === 'paste') {
io.stdout.write(
`${[
2026-05-10 23:51:24 +02:00
`KTX will save the key in .ktx/secrets/${backend}-api-key with local file permissions,`,
'then write a file: reference in ktx.yaml.',
2026-05-10 23:12:26 +02:00
].join(' ')}\n`,
);
const value = await prompts.password({ message: withTextInputNavigation(`${backend} embedding API key`) });
if (value === undefined) {
return { status: 'back' };
}
if (!value.trim()) {
return { status: 'missing-input' };
}
const ref = await writeProjectLocalSecretReference({
projectDir: args.projectDir,
fileName: `${backend}-api-key`,
value,
});
return { status: 'ready', ref, value: value.trim() };
}
const ref = envCredentialReference(defaultEnv);
2026-05-10 23:51:24 +02:00
const value = resolveKtxConfigReference(ref, env);
2026-05-10 23:12:26 +02:00
if (!value) {
io.stderr.write(`Missing embedding API key: ${defaultEnv} is not set.\n`);
return { status: 'missing-input' };
}
return { status: 'ready', ref, value };
}
async function chooseEmbeddingBackend(
2026-05-10 23:51:24 +02:00
args: KtxSetupEmbeddingsArgs,
deps: KtxSetupEmbeddingsDeps,
2026-05-10 23:12:26 +02:00
): Promise<BackendChoice> {
if (args.embeddingBackend) {
return args.embeddingBackend;
}
if (args.inputMode === 'disabled') {
return LOCAL_EMBEDDING_BACKEND;
}
const choice = await (deps.prompts ?? createPromptAdapter()).select({
2026-05-10 23:51:24 +02:00
message: `Which embedding option should KTX use?\n\n${EMBEDDING_OPTION_PROMPT_CONTEXT}`,
2026-05-10 23:12:26 +02:00
options: [
{ value: 'sentence-transformers', label: 'Local sentence-transformers embeddings' },
{ value: 'openai', label: 'OpenAI embeddings', hint: 'recommended' },
2026-05-10 23:12:26 +02:00
{ value: 'back', label: 'Back' },
],
});
if (choice === 'openai' || choice === 'sentence-transformers' || choice === 'back') {
return choice;
}
return 'back';
}
async function readLocalEmbeddingDaemonStderrTail(stderrLog: string | undefined): Promise<string[]> {
if (!stderrLog) {
return [];
}
try {
const lines = (await readFile(stderrLog, 'utf8'))
.split(/\r?\n/)
.map((line) => line.trimEnd())
.filter((line) => line.trim().length > 0);
return lines.slice(-LOCAL_EMBEDDING_STDERR_TAIL_LINES);
} catch {
return [];
}
}
function localEmbeddingSetupMessage(message: string, stderrTail: string[] = []): string {
const lines = [
2026-05-10 23:12:26 +02:00
`Local embedding health check failed: ${message}`,
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
'Local embeddings use the KTX-managed Python runtime.',
'Prepare the runtime with: ktx admin runtime start --feature local-embeddings',
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
'Use --yes with setup to install and start the runtime without prompting.',
'The first run may download Python packages and the all-MiniLM-L6-v2 model.',
];
if (stderrTail.length > 0) {
refactor(release): drop release-policy.json runtime dep and next branch (#180) * chore: standardize daemon naming on "KTX daemon" Replace inconsistent names ("KTX Python daemon", "KTX local embeddings daemon", "KTX managed daemon", "Python daemon") with the single name "KTX daemon" in CLI output, errors, command descriptions, test assertions, smoke scripts, docs, AGENTS.md, issue templates, and codecov flags. The daemon is a portable compute server with endpoints for SQL analysis, semantic layer, LookML, database introspection, and embeddings; the previous labels misrepresented it as embeddings-only or exposed implementation details ("Python", "managed"). The "KTX Python runtime" concept (installed interpreter + packages) is deliberately left as-is — it is a separate concept from the daemon process. * refactor(release): drop release-policy.json runtime dep and next branch Strips the release-policy.json fallback from release-version.ts so the CLI reads its version straight from packages/cli/package.json. dev → 0.0.0-private, installed @kaelio/ktx → the real semver baked into the published package.json. KtxCliPackageInfo collapses to { name, version, contextPackageName }; /health no longer depends on version files surviving past a CI run. Replaces the dual-branch (main + next) semantic-release model with a single- branch model on main. rcs and stables interleave on the same branch via { name: 'main', prerelease: 'rc', channel: 'next' } / ['main']. Drops @semantic-release/git and @semantic-release/changelog (nothing is committed back to the repo on any channel) and the workflow's "Prepare next prerelease branch" step plus the KTX_PRERELEASE_BRANCH plumbing. The git tag plus the published npm artifact carry the version forward. Updates docs/release.md, removes the two now-unused devDeps, regenerates pnpm-lock.yaml. 611/611 @ktx/cli tests, 173/173 script tests, type-check, biome, knip all clean. * fix(release): don't throw on non-main branches at config-load time knip loads .releaserc.cjs on every PR run, where GITHUB_REF_NAME is the merge ref (e.g. 180/merge). The previous version of releaseBranches threw immediately when the branch wasn't main, which made knip fail to evaluate the config and then mis-flag @semantic-release/exec as an unused dep. semantic-release already refuses to publish when the current branch doesn't match a configured release branch, so the explicit throw was redundant. Drop it (and the unused currentBranch helper) and replace the "rejects releases from non-main" assertion with one that exercises a CI- shaped GITHUB_REF_NAME and confirms the config loads.
2026-05-20 13:53:14 +02:00
lines.push('Recent KTX daemon stderr:', ...stderrTail);
}
return lines.join('\n');
2026-05-10 23:12:26 +02:00
}
async function promptAfterLocalEmbeddingFailure(
2026-05-10 23:51:24 +02:00
deps: KtxSetupEmbeddingsDeps,
): Promise<'retry' | Extract<KtxSetupEmbeddingBackend, 'openai'> | 'back'> {
2026-05-10 23:12:26 +02:00
const choice = await (deps.prompts ?? createPromptAdapter()).select({
2026-05-10 23:51:24 +02:00
message: 'Local embeddings are not reachable. Start the local KTX daemon, then retry.',
2026-05-10 23:12:26 +02:00
options: [
{ value: 'retry', label: 'Retry' },
{ value: 'openai', label: 'Use OpenAI embeddings' },
{ value: 'back', label: 'Back' },
],
});
if (choice === 'openai' || choice === 'back') {
return choice;
}
return 'retry';
}
2026-05-10 23:51:24 +02:00
function healthCheckStartText(backend: KtxSetupEmbeddingBackend, model: string, dimensions: number): string {
2026-05-10 23:12:26 +02:00
if (backend === LOCAL_EMBEDDING_BACKEND) {
return `Testing local embeddings (${model})`;
2026-05-10 23:12:26 +02:00
}
return `Checking ${backend} embeddings (${model}, ${dimensions} dimensions).`;
}
function startHealthCheckProgress(
spinner: KtxCliSpinner,
message: string,
): { succeed(msg: string): void; fail(msg: string): void } {
spinner.start(message);
2026-05-10 23:12:26 +02:00
return {
succeed(msg: string) {
spinner.stop(msg);
2026-05-10 23:12:26 +02:00
},
fail(msg: string) {
spinner.error(msg);
2026-05-10 23:12:26 +02:00
},
};
}
2026-05-10 23:51:24 +02:00
export async function runKtxSetupEmbeddingsStep(
args: KtxSetupEmbeddingsArgs,
io: KtxCliIo,
deps: KtxSetupEmbeddingsDeps = {},
): Promise<KtxSetupEmbeddingsResult> {
2026-05-10 23:12:26 +02:00
if (args.skipEmbeddings) {
io.stdout.write('│ Embeddings setup skipped.\n');
2026-05-10 23:12:26 +02:00
return { status: 'skipped', projectDir: args.projectDir };
}
2026-05-10 23:51:24 +02:00
const project = await loadKtxProject({ projectDir: args.projectDir });
2026-05-10 23:12:26 +02:00
if (
args.forcePrompt !== true &&
(await hasCompletedEmbeddings(args.projectDir, project.config)) &&
2026-05-10 23:12:26 +02:00
!args.embeddingBackend &&
!args.embeddingApiKeyEnv &&
!args.embeddingApiKeyFile
) {
io.stdout.write(`│ Embeddings ready: yes (${project.config.ingest.embeddings.model})\n`);
2026-05-10 23:12:26 +02:00
return { status: 'ready', projectDir: args.projectDir };
}
const healthCheck =
deps.healthCheck ??
2026-05-10 23:51:24 +02:00
((config: KtxEmbeddingConfig) =>
runKtxEmbeddingHealthCheck(config, { timeoutMs: LOCAL_EMBEDDING_HEALTH_TIMEOUT_MS }));
let selectedBackend: KtxSetupEmbeddingBackend | undefined;
2026-05-10 23:12:26 +02:00
while (true) {
if (!selectedBackend) {
const backend = await chooseEmbeddingBackend(args, deps);
if (backend === 'back') {
return { status: 'back', projectDir: args.projectDir };
}
selectedBackend = backend;
}
const defaults = DEFAULTS[selectedBackend];
const model = defaults.model;
const dimensions = defaults.dimensions;
let credentialRef: string | undefined;
let credentialValue: string | undefined;
if (selectedBackend === 'openai') {
const credential = await chooseCredentialRef(selectedBackend, args, io, deps);
if (credential.status === 'back' && !args.embeddingBackend && args.inputMode !== 'disabled') {
selectedBackend = undefined;
continue;
}
if (credential.status !== 'ready') {
return { status: credential.status, projectDir: args.projectDir };
}
credentialRef = credential.ref;
credentialValue = credential.value;
}
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
let managedLocalEmbeddings: ManagedLocalEmbeddingsDaemon | undefined;
if (selectedBackend === LOCAL_EMBEDDING_BACKEND) {
const ensureLocalEmbeddings = deps.ensureLocalEmbeddings ?? ensureManagedLocalEmbeddingsDaemon;
try {
managedLocalEmbeddings = await ensureLocalEmbeddings({
cliVersion: args.cliVersion,
projectDir: args.projectDir,
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
installPolicy: args.runtimeInstallPolicy,
io,
});
} catch (error) {
io.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
return { status: 'failed', projectDir: args.projectDir };
}
}
const healthConfig =
selectedBackend === LOCAL_EMBEDDING_BACKEND && managedLocalEmbeddings
? managedLocalEmbeddingHealthConfig({
baseUrl: managedLocalEmbeddings.baseUrl,
model,
dimensions,
})
: buildHealthConfig({
backend: selectedBackend,
model,
dimensions,
credentialValue,
});
const healthSpinner = (deps.spinner ?? (() => createStaticCliSpinner(io)))();
const progress = startHealthCheckProgress(healthSpinner, healthCheckStartText(selectedBackend, model, dimensions));
2026-05-10 23:51:24 +02:00
let health: KtxEmbeddingHealthCheckResult;
2026-05-10 23:12:26 +02:00
try {
health = await healthCheck(healthConfig);
} catch (error) {
progress.fail('Embedding test failed');
throw error;
}
if (health.ok) {
progress.succeed(`Embedding test passed (${model}, ${dimensions} dimensions)`);
await persistEmbeddingConfig(
args.projectDir,
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
selectedBackend === LOCAL_EMBEDDING_BACKEND
? {
backend: 'sentence-transformers' as const,
model,
dimensions,
}
feat: npm-managed Python runtime for @kaelio/ktx (#7) * docs: add npm managed python runtime design * build: add bundled python runtime wheel builder * build: make local embedding dependencies optional * build: bundle python runtime wheel in cli artifacts * build: track bundled python runtime release artifact * test: verify bundled python runtime wheel * docs: add plan for bundled python runtime wheel * test: cover managed python runtime lifecycle * feat: add managed python runtime installer * feat: add runtime command runner * feat: expose runtime management commands * test: verify managed python runtime commands * docs: add plan for managed python runtime installer * feat: add managed python command helper * feat: use managed runtime for sl query compute * feat: route sl query managed runtime policy * docs: add plan for managed runtime sl query integration * feat: add managed runtime daemon metadata * feat: manage python daemon lifecycle * feat: add runtime daemon start stop commands * fix: verify managed runtime daemon lifecycle * docs: add plan for managed runtime daemon lifecycle * feat: add managed local embeddings config marker * feat: add managed local embeddings daemon helper * feat: use managed runtime for local embedding setup * feat: pass managed runtime policy through setup * docs: add plan for managed local embeddings runtime * feat: read CLI package metadata dynamically * feat: assemble public kaelio ktx npm package * feat: release one public kaelio ktx npm artifact * test: cover public kaelio ktx package invocations * chore: verify public kaelio ktx package artifacts * docs: add plan for public kaelio ktx npm package * test: verify managed runtime in public package smoke * test: finalize managed runtime release smoke * docs: add plan for managed runtime release smoke * test: specify local embeddings release smoke * feat: add local embeddings runtime smoke * chore: register local embeddings smoke * fix: verify local embeddings smoke * fix: restore artifact smoke python env helper * docs: add plan for managed local embeddings release smoke * refactor: share managed runtime install policy parsing * feat: use managed runtime for agent semantic queries * feat: use managed runtime for MCP semantic compute * docs: add plan for managed agent and MCP semantic runtime * feat(cli): add managed daemon HTTP helpers * feat(cli): route local adapters through managed daemon * feat(cli): use managed daemon for ingest helpers * feat(cli): pass managed daemon options to scan * feat(context): pass MCP ingest pull config options * feat(cli): pass managed daemon options to serve ingest * test: verify managed local ingest daemon runtime * docs: add plan for managed local ingest daemon runtime * docs: align managed runtime examples * docs: add plan for managed runtime docs cleanup * test: cover published package runtime smoke commands * test: validate published package smoke outputs * docs: add plan for published package runtime smoke * build: stamp public npm package version * release: add npm public release policy * release: add guarded npm publish script * release: document public npm release handoff * docs: add plan for public npm release handoff * test: cover managed runtime prune in package smoke * docs: document managed runtime prune * docs: add plan for managed runtime prune smoke and docs * chore: encode uv runtime prerequisite policy * fix: clarify missing uv runtime error * docs: document uv runtime prerequisite * docs: add plan for uv runtime prerequisite contract * refactor: limit release artifacts to public package runtime * chore: align release policy with bundled runtime wheel * docs: describe single public runtime artifact surface * test: verify single public runtime artifact contract * docs: add plan for single public runtime artifact cleanup * fix: align local embeddings smoke with public version * docs: add plan for local embeddings smoke public version * release: soft-launch as @kaelio/ktx@0.1.0-rc.0 on next tag Publish target moves to the pre-release version 0.1.0-rc.0 under the next dist-tag so npm install @kaelio/ktx (which resolves to latest) does not pick up the soft-launch build. Users opt in via @kaelio/ktx@next. * Fix release script boundary checks * Remove PostHog from public package bundle
2026-05-11 15:50:34 +02:00
: buildProjectEmbeddingConfig({
backend: selectedBackend,
model,
dimensions,
credentialRef,
}),
2026-05-10 23:12:26 +02:00
);
io.stdout.write(`│ Embeddings ready: yes (${model}, ${dimensions} dimensions)\n`);
2026-05-10 23:12:26 +02:00
return { status: 'ready', projectDir: args.projectDir };
}
progress.fail('Embedding test failed');
const stderrTail =
selectedBackend === 'sentence-transformers'
? await readLocalEmbeddingDaemonStderrTail(managedLocalEmbeddings?.stderrLog)
: [];
2026-05-10 23:12:26 +02:00
io.stderr.write(
selectedBackend === 'sentence-transformers'
? `${localEmbeddingSetupMessage(health.message, stderrTail)}\n`
2026-05-10 23:12:26 +02:00
: `Embedding health check failed: ${health.message}\n`,
);
if (args.inputMode === 'disabled') {
return { status: 'failed', projectDir: args.projectDir };
}
if (selectedBackend !== 'sentence-transformers' && (args.embeddingApiKeyEnv || args.embeddingApiKeyFile)) {
return { status: 'failed', projectDir: args.projectDir };
}
const nextAction =
selectedBackend === 'sentence-transformers' ? await promptAfterLocalEmbeddingFailure(deps) : 'retry';
if (nextAction === 'back') {
return { status: 'back', projectDir: args.projectDir };
}
if (nextAction === 'openai') {
selectedBackend = nextAction;
}
}
}