diff --git a/packages/cli/src/cli-program.ts b/packages/cli/src/cli-program.ts index 8b517a3b..fd7a50ef 100644 --- a/packages/cli/src/cli-program.ts +++ b/packages/cli/src/cli-program.ts @@ -179,6 +179,7 @@ async function runBareInteractiveCommand( skipAgents: false, inputMode: 'auto', yes: false, + cliVersion: context.packageInfo.version, skipLlm: false, skipEmbeddings: false, databaseSchemas: [], diff --git a/packages/cli/src/commands/setup-commands.ts b/packages/cli/src/commands/setup-commands.ts index 1d5a933a..16e3cc28 100644 --- a/packages/cli/src/commands/setup-commands.ts +++ b/packages/cli/src/commands/setup-commands.ts @@ -371,6 +371,7 @@ export function registerSetupCommands(program: Command, context: KtxCliCommandCo skipAgents: options.skipAgents === true, inputMode: options.input === false ? 'disabled' : 'auto', yes: options.yes === true, + cliVersion: context.packageInfo.version, ...(options.anthropicApiKeyEnv ? { anthropicApiKeyEnv: options.anthropicApiKeyEnv } : {}), ...(options.anthropicApiKeyFile ? { anthropicApiKeyFile: options.anthropicApiKeyFile } : {}), ...(options.anthropicModel ? { anthropicModel: options.anthropicModel } : {}), diff --git a/packages/cli/src/index.test.ts b/packages/cli/src/index.test.ts index 4f3a0a59..0e4b4b1a 100644 --- a/packages/cli/src/index.test.ts +++ b/packages/cli/src/index.test.ts @@ -324,6 +324,7 @@ describe('runKtxCli', () => { skipAgents: false, inputMode: 'auto', yes: false, + cliVersion: '0.0.0-private', skipLlm: false, skipEmbeddings: false, databaseSchemas: [], @@ -1015,6 +1016,7 @@ describe('runKtxCli', () => { command: 'run', projectDir: tempDir, inputMode: 'disabled', + cliVersion: '0.0.0-private', anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', anthropicModel: 'claude-sonnet-4-6', skipLlm: false, @@ -1122,6 +1124,7 @@ describe('runKtxCli', () => { projectDir: '/tmp/project', inputMode: 'disabled', yes: true, + cliVersion: '0.0.0-private', skipLlm: true, skipEmbeddings: true, databaseDrivers: ['postgres'], diff --git a/packages/cli/src/setup.test.ts b/packages/cli/src/setup.test.ts index 3e772d92..5901013a 100644 --- a/packages/cli/src/setup.test.ts +++ b/packages/cli/src/setup.test.ts @@ -318,6 +318,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'disabled', yes: true, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, databaseSchemas: [], @@ -364,6 +365,7 @@ describe('setup status', () => { skipAgents: false, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: false, databaseSchemas: [], @@ -410,6 +412,7 @@ describe('setup status', () => { skipAgents: false, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: false, databaseSchemas: [], @@ -434,6 +437,7 @@ describe('setup status', () => { skipAgents: false, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: false, databaseSchemas: [], @@ -472,6 +476,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, databaseSchemas: [], @@ -530,6 +535,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, databaseSchemas: [], @@ -597,6 +603,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, databaseSchemas: [], @@ -661,6 +668,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: true, databaseSchemas: [], @@ -697,6 +705,7 @@ describe('setup status', () => { skipAgents: false, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: false, databaseSchemas: [], @@ -733,6 +742,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'disabled', yes: false, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, databaseSchemas: [], @@ -764,6 +774,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'disabled', yes: false, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, databaseSchemas: [], @@ -791,6 +802,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'disabled', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: true, databaseSchemas: [], @@ -819,6 +831,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'disabled', yes: false, + cliVersion: '0.2.0', anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', anthropicModel: 'claude-sonnet-4-6', skipLlm: false, @@ -858,7 +871,8 @@ describe('setup status', () => { agents: false, skipAgents: true, inputMode: 'disabled', - yes: false, + yes: true, + cliVersion: '0.2.0', anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', anthropicModel: 'claude-sonnet-4-6', skipLlm: false, @@ -878,6 +892,8 @@ describe('setup status', () => { expect.objectContaining({ projectDir: tempDir, inputMode: 'disabled', + cliVersion: '0.2.0', + runtimeInstallPolicy: 'auto', embeddingBackend: 'openai', embeddingApiKeyEnv: 'OPENAI_API_KEY', skipEmbeddings: false, @@ -886,6 +902,43 @@ describe('setup status', () => { ); }); + it('passes no-input runtime policy to the embeddings step', async () => { + const io = makeIo(); + const embeddings = vi.fn(async () => ({ status: 'failed' as const, projectDir: tempDir })); + + await expect( + runKtxSetup( + { + command: 'run', + projectDir: tempDir, + mode: 'new', + agents: false, + agentScope: 'project', + agentInstallMode: 'cli', + skipAgents: true, + inputMode: 'disabled', + yes: false, + cliVersion: '0.2.0', + skipLlm: true, + skipEmbeddings: false, + databaseSchemas: [], + skipDatabases: true, + skipSources: true, + }, + io.io, + { embeddings }, + ), + ).resolves.toBe(1); + + expect(embeddings).toHaveBeenCalledWith( + expect.objectContaining({ + cliVersion: '0.2.0', + runtimeInstallPolicy: 'never', + }), + io.io, + ); + }); + it('lets Back from embedding setup return to the model step instead of exiting', async () => { const testIo = makeIo(); const modelResults = [ @@ -905,6 +958,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: false, databaseSchemas: [], @@ -952,6 +1006,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: false, databaseSchemas: [], @@ -997,6 +1052,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: true, databaseSchemas: [], @@ -1037,6 +1093,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'disabled', yes: false, + cliVersion: '0.2.0', anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', anthropicModel: 'claude-sonnet-4-6', skipLlm: false, @@ -1084,6 +1141,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'disabled', yes: true, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, skipDatabases: true, @@ -1130,6 +1188,7 @@ describe('setup status', () => { agents: false, inputMode: 'disabled', yes: true, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, skipDatabases: true, @@ -1191,6 +1250,7 @@ describe('setup status', () => { agentInstallMode: 'cli', inputMode: 'disabled', yes: true, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, skipDatabases: true, @@ -1244,6 +1304,7 @@ describe('setup status', () => { agentInstallMode: 'cli', inputMode: 'disabled', yes: true, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, skipDatabases: true, @@ -1277,6 +1338,7 @@ describe('setup status', () => { agents: false, inputMode: 'disabled', yes: true, + cliVersion: '0.2.0', skipLlm: true, skipEmbeddings: true, skipDatabases: true, @@ -1375,6 +1437,7 @@ describe('setup status', () => { agents: false, inputMode: 'auto', yes: false, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: false, skipDatabases: false, @@ -1437,6 +1500,7 @@ describe('setup status', () => { agentInstallMode: 'both', inputMode: 'disabled', yes: true, + cliVersion: '0.2.0', skipLlm: false, skipEmbeddings: false, skipDatabases: false, @@ -1485,6 +1549,7 @@ describe('setup status', () => { skipAgents: true, inputMode: 'disabled', yes: false, + cliVersion: '0.2.0', anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', anthropicModel: 'claude-sonnet-4-6', skipLlm: false, diff --git a/packages/cli/src/setup.ts b/packages/cli/src/setup.ts index 09deff37..baf1adeb 100644 --- a/packages/cli/src/setup.ts +++ b/packages/cli/src/setup.ts @@ -60,6 +60,7 @@ export type KtxSetupArgs = skipAgents?: boolean; inputMode: 'auto' | 'disabled'; yes: boolean; + cliVersion: string; anthropicApiKeyEnv?: string; anthropicApiKeyFile?: string; anthropicModel?: string; @@ -397,6 +398,13 @@ function writeContextNotReadyForAgents(projectDir: string, io: KtxCliIo): void { io.stderr.write(`Then install agent integration:\n ktx setup --agents --project-dir ${resolve(projectDir)}\n`); } +function setupRuntimeInstallPolicy(args: Extract): 'prompt' | 'auto' | 'never' { + if (args.yes) { + return 'auto'; + } + return args.inputMode === 'disabled' ? 'never' : 'prompt'; +} + export async function runKtxSetup(args: KtxSetupArgs, io: KtxCliIo, deps: KtxSetupDeps = {}): Promise { try { return await runKtxSetupInner(args, io, deps); @@ -566,6 +574,8 @@ async function runKtxSetupInner(args: KtxSetupArgs, io: KtxCliIo, deps: KtxSetup { projectDir: projectResult.projectDir, inputMode: args.inputMode, + cliVersion: args.cliVersion, + runtimeInstallPolicy: setupRuntimeInstallPolicy(args), ...(args.embeddingBackend ? { embeddingBackend: args.embeddingBackend } : {}), ...(args.embeddingApiKeyEnv ? { embeddingApiKeyEnv: args.embeddingApiKeyEnv } : {}), ...(args.embeddingApiKeyFile ? { embeddingApiKeyFile: args.embeddingApiKeyFile } : {}),