@kaelio/ktx 0.1.0-rc.6 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/python/{kaelio_ktx-0.1.0rc6-py3-none-any.whl → kaelio_ktx-0.1.1-py3-none-any.whl} +0 -0
- package/assets/python/manifest.json +4 -4
- package/dist/commands/mcp-commands.js +11 -3
- package/dist/commands/mcp-commands.test.js +30 -1
- package/dist/commands/setup-commands.js +14 -26
- package/dist/doctor.test.js +3 -4
- package/dist/index.test.js +26 -10
- package/dist/ingest-depth.js +0 -1
- package/dist/ingest.test-utils.js +2 -2
- package/dist/ingest.test.js +6 -30
- package/dist/managed-local-embeddings.d.ts +2 -0
- package/dist/managed-local-embeddings.js +2 -0
- package/dist/managed-local-embeddings.test.js +2 -0
- package/dist/managed-mcp-daemon.js +3 -2
- package/dist/managed-mcp-daemon.test.js +25 -0
- package/dist/managed-python-command.test.js +1 -0
- package/dist/managed-python-daemon.js +3 -2
- package/dist/managed-python-daemon.test.js +20 -0
- package/dist/managed-python-runtime.d.ts +4 -0
- package/dist/managed-python-runtime.js +47 -3
- package/dist/managed-python-runtime.test.js +51 -21
- package/dist/next-steps.js +1 -1
- package/dist/next-steps.test.js +2 -0
- package/dist/proxy-env.d.ts +1 -0
- package/dist/proxy-env.js +23 -0
- package/dist/proxy-env.test.js +17 -0
- package/dist/runtime-requirements.d.ts +1 -2
- package/dist/runtime-requirements.js +0 -7
- package/dist/runtime-requirements.test.js +2 -2
- package/dist/runtime.test.js +1 -0
- package/dist/setup-agents.d.ts +11 -3
- package/dist/setup-agents.js +400 -135
- package/dist/setup-agents.test.js +394 -62
- package/dist/setup-embeddings.d.ts +1 -0
- package/dist/setup-embeddings.js +28 -6
- package/dist/setup-embeddings.test.js +46 -4
- package/dist/setup-models.d.ts +0 -1
- package/dist/setup-models.js +2 -3
- package/dist/setup-models.test.js +8 -10
- package/dist/setup-project.d.ts +9 -1
- package/dist/setup-project.js +52 -25
- package/dist/setup-project.test.js +8 -8
- package/dist/setup-runtime.d.ts +0 -1
- package/dist/setup-runtime.js +0 -1
- package/dist/setup-runtime.test.js +9 -13
- package/dist/setup.d.ts +4 -2
- package/dist/setup.js +72 -30
- package/dist/setup.test.js +271 -58
- package/dist/sl.test.js +2 -1
- package/dist/standalone-smoke.test.js +2 -3
- package/dist/status-project.js +1 -10
- package/node_modules/@ktx/connector-clickhouse/dist/package-exports.test.js +1 -1
- package/node_modules/@ktx/context/dist/core/git.service.d.ts +0 -1
- package/node_modules/@ktx/context/dist/core/git.service.js +0 -12
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/historic-sql.adapter.d.ts +1 -2
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/historic-sql.adapter.js +0 -18
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/local-ingest-acceptance.test.js +7 -7
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.d.ts +4 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.js +38 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.test.js +63 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.d.ts +0 -5
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.js +0 -48
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.test.js +0 -83
- package/node_modules/@ktx/context/dist/ingest/index.d.ts +2 -1
- package/node_modules/@ktx/context/dist/ingest/index.js +1 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.d.ts +0 -2
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.isolated-diff.test.js +0 -166
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.js +45 -235
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.test.js +38 -193
- package/node_modules/@ktx/context/dist/ingest/local-bundle-ingest.test.js +11 -30
- package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.js +5 -1
- package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.test.js +3 -3
- package/node_modules/@ktx/context/dist/ingest/local-embedding-provider.integration.test.js +9 -10
- package/node_modules/@ktx/context/dist/ingest/local-ingest.js +7 -0
- package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.d.ts +4 -4
- package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.js +1 -1
- package/node_modules/@ktx/context/dist/ingest/memory-flow/types.d.ts +1 -1
- package/node_modules/@ktx/context/dist/ingest/ports.d.ts +20 -1
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.d.ts +2 -73
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.js +0 -27
- package/node_modules/@ktx/context/dist/ingest/reports.d.ts +5 -23
- package/node_modules/@ktx/context/dist/ingest/reports.js +24 -7
- package/node_modules/@ktx/context/dist/ingest/types.d.ts +0 -33
- package/node_modules/@ktx/context/dist/llm/local-config.js +2 -15
- package/node_modules/@ktx/context/dist/llm/local-config.test.js +3 -7
- package/node_modules/@ktx/context/dist/package-exports.test.js +1 -2
- package/node_modules/@ktx/context/dist/project/config.d.ts +0 -5
- package/node_modules/@ktx/context/dist/project/config.js +5 -5
- package/node_modules/@ktx/context/dist/project/config.test.js +4 -7
- package/node_modules/@ktx/context/dist/scan/enrichment-state.test.js +4 -4
- package/node_modules/@ktx/context/dist/scan/index.d.ts +1 -1
- package/node_modules/@ktx/context/dist/scan/local-enrichment.d.ts +2 -6
- package/node_modules/@ktx/context/dist/scan/local-enrichment.js +31 -47
- package/node_modules/@ktx/context/dist/scan/local-enrichment.test.js +35 -18
- package/node_modules/@ktx/context/dist/scan/local-scan.test.js +2 -3
- package/node_modules/@ktx/llm/dist/embedding-provider.d.ts +0 -7
- package/node_modules/@ktx/llm/dist/embedding-provider.js +12 -138
- package/node_modules/@ktx/llm/dist/embedding-provider.test.js +10 -25
- package/node_modules/@ktx/llm/dist/types.d.ts +1 -1
- package/package.json +4 -4
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.d.ts +0 -22
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.js +0 -95
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.test.js +0 -114
- /package/{node_modules/@ktx/context/dist/ingest/finalization-scope.test.d.ts → dist/proxy-env.test.d.ts} +0 -0
package/dist/setup.test.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
|
-
import { mkdir, mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { promisify } from 'node:util';
|
|
@@ -8,7 +8,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
8
8
|
import { localFakeBundleReport, persistLocalBundleReport } from './ingest.test-utils.js';
|
|
9
9
|
import { contextBuildCommands, writeKtxSetupContextState } from './setup-context.js';
|
|
10
10
|
import { runDemoTour } from './setup-demo-tour.js';
|
|
11
|
-
import { formatKtxSetupStatus, readKtxSetupStatus, runKtxSetup } from './setup.js';
|
|
11
|
+
import { formatKtxSetupCompletionSummary, formatKtxSetupStatus, readKtxSetupStatus, runKtxSetup } from './setup.js';
|
|
12
12
|
vi.mock('./setup-demo-tour.js', () => ({
|
|
13
13
|
runDemoTour: vi.fn(async () => 0),
|
|
14
14
|
}));
|
|
@@ -88,7 +88,7 @@ describe('setup status', () => {
|
|
|
88
88
|
agents: [],
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
|
-
it('reports
|
|
91
|
+
it('reports disabled default embeddings as not setup-ready', async () => {
|
|
92
92
|
await mkdir(tempDir, { recursive: true });
|
|
93
93
|
await writeFile(join(tempDir, 'ktx.yaml'), [
|
|
94
94
|
'llm:',
|
|
@@ -100,15 +100,14 @@ describe('setup status', () => {
|
|
|
100
100
|
' default: claude-sonnet-4-6',
|
|
101
101
|
'ingest:',
|
|
102
102
|
' embeddings:',
|
|
103
|
-
' backend:
|
|
104
|
-
' model: deterministic',
|
|
103
|
+
' backend: none',
|
|
105
104
|
' dimensions: 8',
|
|
106
105
|
'connections: {}',
|
|
107
106
|
].join('\n'), 'utf-8');
|
|
108
107
|
await expect(readKtxSetupStatus(tempDir)).resolves.toMatchObject({
|
|
109
108
|
project: { path: tempDir, ready: true },
|
|
110
109
|
llm: { backend: 'anthropic', ready: true, model: 'claude-sonnet-4-6' },
|
|
111
|
-
embeddings: { backend: '
|
|
110
|
+
embeddings: { backend: 'none', ready: false, dimensions: 8 },
|
|
112
111
|
});
|
|
113
112
|
});
|
|
114
113
|
it.each([
|
|
@@ -299,8 +298,7 @@ describe('setup status', () => {
|
|
|
299
298
|
' default: claude-sonnet-4-6',
|
|
300
299
|
'ingest:',
|
|
301
300
|
' embeddings:',
|
|
302
|
-
' backend:
|
|
303
|
-
' model: deterministic',
|
|
301
|
+
' backend: none',
|
|
304
302
|
' dimensions: 8',
|
|
305
303
|
'',
|
|
306
304
|
].join('\n'), 'utf-8');
|
|
@@ -337,6 +335,98 @@ describe('setup status', () => {
|
|
|
337
335
|
expect(rendered).toContain('KTX context built: no');
|
|
338
336
|
expect(rendered).not.toContain('No KTX project found.');
|
|
339
337
|
});
|
|
338
|
+
it('formats a concise ready summary for completed agent setup', () => {
|
|
339
|
+
const rendered = formatKtxSetupCompletionSummary({
|
|
340
|
+
project: { path: tempDir, ready: true },
|
|
341
|
+
llm: { ready: true, model: 'sonnet' },
|
|
342
|
+
embeddings: { ready: true, model: 'text-embedding-3-small' },
|
|
343
|
+
databases: [{ connectionId: 'postgres-warehouse', ready: true }],
|
|
344
|
+
sources: [{ connectionId: 'dbt-main', type: 'dbt', ready: true }],
|
|
345
|
+
runtime: { required: true, ready: true, features: ['core'] },
|
|
346
|
+
context: { ready: true, status: 'completed' },
|
|
347
|
+
agents: [
|
|
348
|
+
{ target: 'claude-code', scope: 'project', ready: true },
|
|
349
|
+
{ target: 'claude-desktop', scope: 'global', ready: true },
|
|
350
|
+
],
|
|
351
|
+
}, {
|
|
352
|
+
agentNextActions: [
|
|
353
|
+
'1. Start MCP',
|
|
354
|
+
' Run this command before using Claude Code:',
|
|
355
|
+
'',
|
|
356
|
+
' RUN:',
|
|
357
|
+
` ktx mcp start --project-dir ${tempDir}`,
|
|
358
|
+
'',
|
|
359
|
+
' If you need to stop MCP later:',
|
|
360
|
+
` ktx mcp stop --project-dir ${tempDir}`,
|
|
361
|
+
'',
|
|
362
|
+
'2. Open Claude Code',
|
|
363
|
+
' Open Claude Code from the KTX project directory:',
|
|
364
|
+
'',
|
|
365
|
+
' RUN:',
|
|
366
|
+
` cd '${tempDir}'`,
|
|
367
|
+
' claude',
|
|
368
|
+
].join('\n'),
|
|
369
|
+
});
|
|
370
|
+
expect(rendered).toContain(`Project\n ${tempDir}`);
|
|
371
|
+
expect(rendered).toContain('Context\n built');
|
|
372
|
+
expect(rendered).toContain('Agents configured\n Claude Code, Claude Desktop');
|
|
373
|
+
expect(rendered).toContain('REQUIRED BEFORE USING AGENTS\n\n 1. Start MCP');
|
|
374
|
+
expect(rendered).toContain(' Run this command before using Claude Code:');
|
|
375
|
+
expect(rendered).toContain(' RUN:');
|
|
376
|
+
expect(rendered).toContain(' If you need to stop MCP later:');
|
|
377
|
+
expect(rendered).toContain(`ktx mcp stop --project-dir ${tempDir}`);
|
|
378
|
+
expect(rendered).toContain('After that, try\n Ask your agent: "Use KTX to show me the available tables."');
|
|
379
|
+
expect(rendered).not.toContain('Verify');
|
|
380
|
+
expect(rendered).not.toContain('Project ready: yes');
|
|
381
|
+
expect(rendered).not.toContain('What you can do next');
|
|
382
|
+
});
|
|
383
|
+
it('prints agent next actions inside the final ready summary during full setup', async () => {
|
|
384
|
+
const testIo = makeIo();
|
|
385
|
+
await expect(runKtxSetup({
|
|
386
|
+
command: 'run',
|
|
387
|
+
projectDir: tempDir,
|
|
388
|
+
mode: 'auto',
|
|
389
|
+
agents: false,
|
|
390
|
+
target: 'claude-code',
|
|
391
|
+
skipAgents: false,
|
|
392
|
+
inputMode: 'disabled',
|
|
393
|
+
yes: true,
|
|
394
|
+
cliVersion: '0.2.0',
|
|
395
|
+
skipLlm: true,
|
|
396
|
+
skipEmbeddings: true,
|
|
397
|
+
skipDatabases: true,
|
|
398
|
+
skipSources: true,
|
|
399
|
+
databaseSchemas: [],
|
|
400
|
+
}, testIo.io, {
|
|
401
|
+
runtime: async () => runtimeReady(tempDir),
|
|
402
|
+
context: async () => {
|
|
403
|
+
await writeKtxSetupContextState(tempDir, {
|
|
404
|
+
runId: 'setup-context-local-test',
|
|
405
|
+
status: 'completed',
|
|
406
|
+
primarySourceConnectionIds: [],
|
|
407
|
+
contextSourceConnectionIds: [],
|
|
408
|
+
reportIds: [],
|
|
409
|
+
artifactPaths: [],
|
|
410
|
+
retryableFailedTargets: [],
|
|
411
|
+
commands: contextBuildCommands(tempDir, 'setup-context-local-test'),
|
|
412
|
+
});
|
|
413
|
+
await writeKtxSetupState(tempDir, { completed_steps: ['project', 'context'] });
|
|
414
|
+
return { status: 'ready', projectDir: tempDir, runId: 'setup-context-local-test' };
|
|
415
|
+
},
|
|
416
|
+
})).resolves.toBe(0);
|
|
417
|
+
const output = testIo.stdout();
|
|
418
|
+
expect(output).toContain('Claude Code · Project scope');
|
|
419
|
+
expect(output).toContain(join(tempDir, '.mcp.json'));
|
|
420
|
+
expect(output).toContain('Requires MCP to be started.');
|
|
421
|
+
expect(output).toContain('Analytics skill installed.');
|
|
422
|
+
expect(output).not.toContain('Agent integration complete');
|
|
423
|
+
expect(output).toContain('Finish KTX agent setup');
|
|
424
|
+
expect(output).not.toContain('KTX project ready');
|
|
425
|
+
expect(output).toContain('REQUIRED BEFORE USING AGENTS');
|
|
426
|
+
expect(output).toContain('Run this command before using Claude Code:');
|
|
427
|
+
expect(output).toContain(`ktx mcp start --project-dir ${tempDir}`);
|
|
428
|
+
expect(output).not.toContain('Finish agent setup');
|
|
429
|
+
});
|
|
340
430
|
it('prints the setup shell intro for auto-created run mode', async () => {
|
|
341
431
|
const testIo = makeIo();
|
|
342
432
|
await expect(runKtxSetup({
|
|
@@ -364,6 +454,85 @@ describe('setup status', () => {
|
|
|
364
454
|
expect(testIo.stdout()).not.toContain('Optional MCP:');
|
|
365
455
|
expect(testIo.stderr()).toBe('');
|
|
366
456
|
});
|
|
457
|
+
it('removes a newly created missing project directory when a later runtime step fails', async () => {
|
|
458
|
+
const projectDir = join(tempDir, 'missing-project');
|
|
459
|
+
const testIo = makeIo();
|
|
460
|
+
await expect(runKtxSetup({
|
|
461
|
+
command: 'run',
|
|
462
|
+
projectDir,
|
|
463
|
+
mode: 'auto',
|
|
464
|
+
agents: false,
|
|
465
|
+
skipAgents: true,
|
|
466
|
+
inputMode: 'disabled',
|
|
467
|
+
yes: true,
|
|
468
|
+
cliVersion: '0.2.0',
|
|
469
|
+
skipLlm: true,
|
|
470
|
+
skipEmbeddings: true,
|
|
471
|
+
databaseSchemas: [],
|
|
472
|
+
skipDatabases: true,
|
|
473
|
+
skipSources: true,
|
|
474
|
+
}, testIo.io, {
|
|
475
|
+
model: async () => ({ status: 'skipped', projectDir }),
|
|
476
|
+
embeddings: async () => ({ status: 'skipped', projectDir }),
|
|
477
|
+
databases: async () => ({ status: 'skipped', projectDir }),
|
|
478
|
+
sources: async () => ({ status: 'skipped', projectDir }),
|
|
479
|
+
runtime: async () => ({ status: 'failed', projectDir, requirements: { features: ['core'], requirements: [] } }),
|
|
480
|
+
})).resolves.toBe(1);
|
|
481
|
+
await expect(stat(projectDir)).rejects.toThrow();
|
|
482
|
+
});
|
|
483
|
+
it('removes KTX scaffold files from an initially empty project directory when runtime setup fails', async () => {
|
|
484
|
+
const testIo = makeIo();
|
|
485
|
+
await expect(runKtxSetup({
|
|
486
|
+
command: 'run',
|
|
487
|
+
projectDir: tempDir,
|
|
488
|
+
mode: 'auto',
|
|
489
|
+
agents: false,
|
|
490
|
+
skipAgents: true,
|
|
491
|
+
inputMode: 'disabled',
|
|
492
|
+
yes: true,
|
|
493
|
+
cliVersion: '0.2.0',
|
|
494
|
+
skipLlm: true,
|
|
495
|
+
skipEmbeddings: true,
|
|
496
|
+
databaseSchemas: [],
|
|
497
|
+
skipDatabases: true,
|
|
498
|
+
skipSources: true,
|
|
499
|
+
}, testIo.io, {
|
|
500
|
+
model: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
501
|
+
embeddings: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
502
|
+
databases: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
503
|
+
sources: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
504
|
+
runtime: async () => ({ status: 'failed', projectDir: tempDir, requirements: { features: ['core'], requirements: [] } }),
|
|
505
|
+
})).resolves.toBe(1);
|
|
506
|
+
await expect(stat(tempDir)).resolves.toBeDefined();
|
|
507
|
+
expect(await readdir(tempDir)).toEqual([]);
|
|
508
|
+
});
|
|
509
|
+
it('preserves a pre-existing non-empty project directory when runtime setup fails', async () => {
|
|
510
|
+
await writeFile(join(tempDir, 'notes.txt'), 'keep me\n', 'utf-8');
|
|
511
|
+
const testIo = makeIo();
|
|
512
|
+
await expect(runKtxSetup({
|
|
513
|
+
command: 'run',
|
|
514
|
+
projectDir: tempDir,
|
|
515
|
+
mode: 'auto',
|
|
516
|
+
agents: false,
|
|
517
|
+
skipAgents: true,
|
|
518
|
+
inputMode: 'disabled',
|
|
519
|
+
yes: true,
|
|
520
|
+
cliVersion: '0.2.0',
|
|
521
|
+
skipLlm: true,
|
|
522
|
+
skipEmbeddings: true,
|
|
523
|
+
databaseSchemas: [],
|
|
524
|
+
skipDatabases: true,
|
|
525
|
+
skipSources: true,
|
|
526
|
+
}, testIo.io, {
|
|
527
|
+
model: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
528
|
+
embeddings: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
529
|
+
databases: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
530
|
+
sources: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
531
|
+
runtime: async () => ({ status: 'failed', projectDir: tempDir, requirements: { features: ['core'], requirements: [] } }),
|
|
532
|
+
})).resolves.toBe(1);
|
|
533
|
+
await expect(readFile(join(tempDir, 'notes.txt'), 'utf-8')).resolves.toBe('keep me\n');
|
|
534
|
+
await expect(stat(join(tempDir, 'ktx.yaml'))).resolves.toBeDefined();
|
|
535
|
+
});
|
|
367
536
|
it('shows demo near the bottom of the first setup intent menu before project creation', async () => {
|
|
368
537
|
const testIo = makeIo();
|
|
369
538
|
const select = vi.fn(async (options) => {
|
|
@@ -658,16 +827,16 @@ describe('setup status', () => {
|
|
|
658
827
|
}, testIo.io, { entryMenuDeps: { prompts: { select: vi.fn(async () => 'demo'), cancel: vi.fn() } } })).resolves.toBe(0);
|
|
659
828
|
expect(runDemoTour).toHaveBeenCalledWith({ inputMode: 'auto' }, testIo.io, expect.objectContaining({}));
|
|
660
829
|
});
|
|
661
|
-
it('creates a project through run mode when --
|
|
830
|
+
it('creates a project through run mode when --yes is selected', async () => {
|
|
662
831
|
const testIo = makeIo();
|
|
663
832
|
await expect(runKtxSetup({
|
|
664
833
|
command: 'run',
|
|
665
834
|
projectDir: tempDir,
|
|
666
|
-
mode: '
|
|
835
|
+
mode: 'auto',
|
|
667
836
|
agents: false,
|
|
668
837
|
skipAgents: true,
|
|
669
838
|
inputMode: 'disabled',
|
|
670
|
-
yes:
|
|
839
|
+
yes: true,
|
|
671
840
|
cliVersion: '0.2.0',
|
|
672
841
|
skipLlm: true,
|
|
673
842
|
skipEmbeddings: true,
|
|
@@ -729,14 +898,14 @@ describe('setup status', () => {
|
|
|
729
898
|
await expect(runKtxSetup({
|
|
730
899
|
command: 'run',
|
|
731
900
|
projectDir: tempDir,
|
|
732
|
-
mode: '
|
|
901
|
+
mode: 'auto',
|
|
733
902
|
agents: false,
|
|
734
903
|
skipAgents: true,
|
|
735
904
|
inputMode: 'disabled',
|
|
736
|
-
yes:
|
|
905
|
+
yes: true,
|
|
737
906
|
cliVersion: '0.2.0',
|
|
738
907
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
739
|
-
|
|
908
|
+
llmModel: 'claude-sonnet-4-6',
|
|
740
909
|
skipLlm: false,
|
|
741
910
|
skipEmbeddings: true,
|
|
742
911
|
databaseSchemas: [],
|
|
@@ -747,7 +916,7 @@ describe('setup status', () => {
|
|
|
747
916
|
projectDir: tempDir,
|
|
748
917
|
inputMode: 'disabled',
|
|
749
918
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
750
|
-
|
|
919
|
+
llmModel: 'claude-sonnet-4-6',
|
|
751
920
|
skipLlm: false,
|
|
752
921
|
}), testIo.io);
|
|
753
922
|
});
|
|
@@ -757,16 +926,16 @@ describe('setup status', () => {
|
|
|
757
926
|
await expect(runKtxSetup({
|
|
758
927
|
command: 'run',
|
|
759
928
|
projectDir: tempDir,
|
|
760
|
-
mode: '
|
|
929
|
+
mode: 'auto',
|
|
761
930
|
agents: false,
|
|
762
931
|
skipAgents: true,
|
|
763
932
|
inputMode: 'disabled',
|
|
764
|
-
yes:
|
|
933
|
+
yes: true,
|
|
765
934
|
cliVersion: '0.2.0',
|
|
766
935
|
llmBackend: 'vertex',
|
|
767
936
|
vertexProject: 'local-gcp-project',
|
|
768
937
|
vertexLocation: 'us-east5',
|
|
769
|
-
|
|
938
|
+
llmModel: 'claude-sonnet-4-6',
|
|
770
939
|
skipLlm: false,
|
|
771
940
|
skipEmbeddings: true,
|
|
772
941
|
databaseSchemas: [],
|
|
@@ -779,7 +948,7 @@ describe('setup status', () => {
|
|
|
779
948
|
llmBackend: 'vertex',
|
|
780
949
|
vertexProject: 'local-gcp-project',
|
|
781
950
|
vertexLocation: 'us-east5',
|
|
782
|
-
|
|
951
|
+
llmModel: 'claude-sonnet-4-6',
|
|
783
952
|
skipLlm: false,
|
|
784
953
|
}), testIo.io);
|
|
785
954
|
});
|
|
@@ -790,14 +959,14 @@ describe('setup status', () => {
|
|
|
790
959
|
await expect(runKtxSetup({
|
|
791
960
|
command: 'run',
|
|
792
961
|
projectDir: tempDir,
|
|
793
|
-
mode: '
|
|
962
|
+
mode: 'auto',
|
|
794
963
|
agents: false,
|
|
795
964
|
skipAgents: true,
|
|
796
965
|
inputMode: 'disabled',
|
|
797
966
|
yes: true,
|
|
798
967
|
cliVersion: '0.2.0',
|
|
799
968
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
800
|
-
|
|
969
|
+
llmModel: 'claude-sonnet-4-6',
|
|
801
970
|
skipLlm: false,
|
|
802
971
|
embeddingBackend: 'openai',
|
|
803
972
|
embeddingApiKeyEnv: 'OPENAI_API_KEY', // pragma: allowlist secret
|
|
@@ -819,10 +988,11 @@ describe('setup status', () => {
|
|
|
819
988
|
it('passes no-input runtime policy to the embeddings step', async () => {
|
|
820
989
|
const io = makeIo();
|
|
821
990
|
const embeddings = vi.fn(async () => ({ status: 'failed', projectDir: tempDir }));
|
|
991
|
+
await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
|
|
822
992
|
await expect(runKtxSetup({
|
|
823
993
|
command: 'run',
|
|
824
994
|
projectDir: tempDir,
|
|
825
|
-
mode: '
|
|
995
|
+
mode: 'auto',
|
|
826
996
|
agents: false,
|
|
827
997
|
agentScope: 'project',
|
|
828
998
|
skipAgents: true,
|
|
@@ -844,10 +1014,11 @@ describe('setup status', () => {
|
|
|
844
1014
|
const io = makeIo();
|
|
845
1015
|
const embeddings = vi.fn(async () => ({ status: 'ready', projectDir: tempDir }));
|
|
846
1016
|
const context = vi.fn(async () => ({ status: 'failed', projectDir: tempDir }));
|
|
1017
|
+
await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
|
|
847
1018
|
await expect(runKtxSetup({
|
|
848
1019
|
command: 'run',
|
|
849
1020
|
projectDir: tempDir,
|
|
850
|
-
mode: '
|
|
1021
|
+
mode: 'auto',
|
|
851
1022
|
agents: false,
|
|
852
1023
|
agentScope: 'project',
|
|
853
1024
|
skipAgents: true,
|
|
@@ -874,6 +1045,7 @@ describe('setup status', () => {
|
|
|
874
1045
|
});
|
|
875
1046
|
it('lets Back from embedding setup return to the model step instead of exiting', async () => {
|
|
876
1047
|
const testIo = makeIo();
|
|
1048
|
+
await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
|
|
877
1049
|
const modelResults = [
|
|
878
1050
|
{ status: 'ready', projectDir: tempDir },
|
|
879
1051
|
{ status: 'back', projectDir: tempDir },
|
|
@@ -883,7 +1055,7 @@ describe('setup status', () => {
|
|
|
883
1055
|
await expect(runKtxSetup({
|
|
884
1056
|
command: 'run',
|
|
885
1057
|
projectDir: tempDir,
|
|
886
|
-
mode: '
|
|
1058
|
+
mode: 'auto',
|
|
887
1059
|
agents: false,
|
|
888
1060
|
skipAgents: true,
|
|
889
1061
|
inputMode: 'auto',
|
|
@@ -901,6 +1073,7 @@ describe('setup status', () => {
|
|
|
901
1073
|
});
|
|
902
1074
|
it('lets Back from database selection return to embedding setup', async () => {
|
|
903
1075
|
const testIo = makeIo();
|
|
1076
|
+
await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
|
|
904
1077
|
const modelResults = [
|
|
905
1078
|
{ status: 'ready', projectDir: tempDir },
|
|
906
1079
|
{ status: 'back', projectDir: tempDir },
|
|
@@ -921,11 +1094,11 @@ describe('setup status', () => {
|
|
|
921
1094
|
await expect(runKtxSetup({
|
|
922
1095
|
command: 'run',
|
|
923
1096
|
projectDir: tempDir,
|
|
924
|
-
mode: '
|
|
1097
|
+
mode: 'auto',
|
|
925
1098
|
agents: false,
|
|
926
1099
|
skipAgents: true,
|
|
927
1100
|
inputMode: 'auto',
|
|
928
|
-
yes:
|
|
1101
|
+
yes: true,
|
|
929
1102
|
cliVersion: '0.2.0',
|
|
930
1103
|
skipLlm: false,
|
|
931
1104
|
skipEmbeddings: false,
|
|
@@ -958,7 +1131,7 @@ describe('setup status', () => {
|
|
|
958
1131
|
agents: false,
|
|
959
1132
|
skipAgents: true,
|
|
960
1133
|
inputMode: 'auto',
|
|
961
|
-
yes:
|
|
1134
|
+
yes: true,
|
|
962
1135
|
cliVersion: '0.2.0',
|
|
963
1136
|
skipLlm: false,
|
|
964
1137
|
skipEmbeddings: true,
|
|
@@ -986,14 +1159,14 @@ describe('setup status', () => {
|
|
|
986
1159
|
await expect(runKtxSetup({
|
|
987
1160
|
command: 'run',
|
|
988
1161
|
projectDir: tempDir,
|
|
989
|
-
mode: '
|
|
1162
|
+
mode: 'auto',
|
|
990
1163
|
agents: false,
|
|
991
1164
|
skipAgents: true,
|
|
992
1165
|
inputMode: 'disabled',
|
|
993
|
-
yes:
|
|
1166
|
+
yes: true,
|
|
994
1167
|
cliVersion: '0.2.0',
|
|
995
1168
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
996
|
-
|
|
1169
|
+
llmModel: 'claude-sonnet-4-6',
|
|
997
1170
|
skipLlm: false,
|
|
998
1171
|
embeddingBackend: 'openai',
|
|
999
1172
|
embeddingApiKeyEnv: 'OPENAI_API_KEY', // pragma: allowlist secret
|
|
@@ -1032,7 +1205,7 @@ describe('setup status', () => {
|
|
|
1032
1205
|
await expect(runKtxSetup({
|
|
1033
1206
|
command: 'run',
|
|
1034
1207
|
projectDir: tempDir,
|
|
1035
|
-
mode: '
|
|
1208
|
+
mode: 'auto',
|
|
1036
1209
|
agents: false,
|
|
1037
1210
|
skipAgents: true,
|
|
1038
1211
|
inputMode: 'disabled',
|
|
@@ -1095,7 +1268,7 @@ describe('setup status', () => {
|
|
|
1095
1268
|
await expect(runKtxSetup({
|
|
1096
1269
|
command: 'run',
|
|
1097
1270
|
projectDir: tempDir,
|
|
1098
|
-
mode: '
|
|
1271
|
+
mode: 'auto',
|
|
1099
1272
|
agents: false,
|
|
1100
1273
|
skipAgents: true,
|
|
1101
1274
|
inputMode: 'disabled',
|
|
@@ -1132,7 +1305,7 @@ describe('setup status', () => {
|
|
|
1132
1305
|
await expect(runKtxSetup({
|
|
1133
1306
|
command: 'run',
|
|
1134
1307
|
projectDir: tempDir,
|
|
1135
|
-
mode: '
|
|
1308
|
+
mode: 'auto',
|
|
1136
1309
|
agents: false,
|
|
1137
1310
|
skipAgents: true,
|
|
1138
1311
|
inputMode: 'disabled',
|
|
@@ -1171,7 +1344,7 @@ describe('setup status', () => {
|
|
|
1171
1344
|
await expect(runKtxSetup({
|
|
1172
1345
|
command: 'run',
|
|
1173
1346
|
projectDir: tempDir,
|
|
1174
|
-
mode: '
|
|
1347
|
+
mode: 'auto',
|
|
1175
1348
|
agents: false,
|
|
1176
1349
|
inputMode: 'disabled',
|
|
1177
1350
|
yes: true,
|
|
@@ -1223,7 +1396,7 @@ describe('setup status', () => {
|
|
|
1223
1396
|
await expect(runKtxSetup({
|
|
1224
1397
|
command: 'run',
|
|
1225
1398
|
projectDir: tempDir,
|
|
1226
|
-
mode: '
|
|
1399
|
+
mode: 'auto',
|
|
1227
1400
|
agents: false,
|
|
1228
1401
|
inputMode: 'disabled',
|
|
1229
1402
|
yes: true,
|
|
@@ -1257,14 +1430,14 @@ describe('setup status', () => {
|
|
|
1257
1430
|
const committedConfig = await execFileAsync('git', ['-C', tempDir, 'show', 'HEAD:ktx.yaml']);
|
|
1258
1431
|
expect(committedConfig.stdout).toContain('warehouse:');
|
|
1259
1432
|
});
|
|
1260
|
-
it('runs agent setup
|
|
1433
|
+
it('runs agent setup without runtime or context in --agents mode', async () => {
|
|
1261
1434
|
const calls = [];
|
|
1262
1435
|
const io = makeIo();
|
|
1263
1436
|
await writeFile(join(tempDir, 'ktx.yaml'), ['connections: {}', ''].join('\n'), 'utf-8');
|
|
1264
1437
|
await expect(runKtxSetup({
|
|
1265
1438
|
command: 'run',
|
|
1266
1439
|
projectDir: tempDir,
|
|
1267
|
-
mode: '
|
|
1440
|
+
mode: 'auto',
|
|
1268
1441
|
agents: true,
|
|
1269
1442
|
target: 'codex',
|
|
1270
1443
|
agentScope: 'project',
|
|
@@ -1284,11 +1457,11 @@ describe('setup status', () => {
|
|
|
1284
1457
|
sources: async () => ({ status: 'skipped', projectDir: tempDir }),
|
|
1285
1458
|
runtime: async () => {
|
|
1286
1459
|
calls.push('runtime');
|
|
1287
|
-
|
|
1460
|
+
throw new Error('runtime should not run');
|
|
1288
1461
|
},
|
|
1289
1462
|
context: async () => {
|
|
1290
1463
|
calls.push('context');
|
|
1291
|
-
|
|
1464
|
+
throw new Error('context should not run');
|
|
1292
1465
|
},
|
|
1293
1466
|
agents: async () => {
|
|
1294
1467
|
calls.push('agents');
|
|
@@ -1299,10 +1472,12 @@ describe('setup status', () => {
|
|
|
1299
1472
|
};
|
|
1300
1473
|
},
|
|
1301
1474
|
})).resolves.toBe(0);
|
|
1302
|
-
expect(calls).toEqual(['
|
|
1475
|
+
expect(calls).toEqual(['agents']);
|
|
1303
1476
|
});
|
|
1304
|
-
it('
|
|
1477
|
+
it('installs agents when non-interactive --agents finds context incomplete', async () => {
|
|
1305
1478
|
const io = makeIo();
|
|
1479
|
+
const runtime = vi.fn(async () => runtimeReady(tempDir));
|
|
1480
|
+
const context = vi.fn(async () => ({ status: 'skipped', projectDir: tempDir }));
|
|
1306
1481
|
const agents = vi.fn(async () => ({
|
|
1307
1482
|
status: 'ready',
|
|
1308
1483
|
projectDir: tempDir,
|
|
@@ -1312,7 +1487,7 @@ describe('setup status', () => {
|
|
|
1312
1487
|
await expect(runKtxSetup({
|
|
1313
1488
|
command: 'run',
|
|
1314
1489
|
projectDir: tempDir,
|
|
1315
|
-
mode: '
|
|
1490
|
+
mode: 'auto',
|
|
1316
1491
|
agents: true,
|
|
1317
1492
|
target: 'codex',
|
|
1318
1493
|
agentScope: 'project',
|
|
@@ -1326,12 +1501,49 @@ describe('setup status', () => {
|
|
|
1326
1501
|
skipAgents: false,
|
|
1327
1502
|
databaseSchemas: [],
|
|
1328
1503
|
}, io.io, {
|
|
1329
|
-
runtime
|
|
1330
|
-
context
|
|
1504
|
+
runtime,
|
|
1505
|
+
context,
|
|
1331
1506
|
agents,
|
|
1332
|
-
})).resolves.toBe(
|
|
1333
|
-
expect(
|
|
1334
|
-
expect(
|
|
1507
|
+
})).resolves.toBe(0);
|
|
1508
|
+
expect(runtime).not.toHaveBeenCalled();
|
|
1509
|
+
expect(context).not.toHaveBeenCalled();
|
|
1510
|
+
expect(agents).toHaveBeenCalledTimes(1);
|
|
1511
|
+
expect(io.stderr()).not.toContain('KTX context is not ready for agents.');
|
|
1512
|
+
});
|
|
1513
|
+
it('runs non-TTY --agents with a target without requiring --no-input or --yes', async () => {
|
|
1514
|
+
const io = makeIo();
|
|
1515
|
+
const agents = vi.fn(async () => ({
|
|
1516
|
+
status: 'ready',
|
|
1517
|
+
projectDir: tempDir,
|
|
1518
|
+
installs: [{ target: 'claude-code', scope: 'project', mode: 'mcp' }],
|
|
1519
|
+
}));
|
|
1520
|
+
await writeFile(join(tempDir, 'ktx.yaml'), ['connections: {}', ''].join('\n'), 'utf-8');
|
|
1521
|
+
await expect(runKtxSetup({
|
|
1522
|
+
command: 'run',
|
|
1523
|
+
projectDir: tempDir,
|
|
1524
|
+
mode: 'auto',
|
|
1525
|
+
agents: true,
|
|
1526
|
+
target: 'claude-code',
|
|
1527
|
+
agentScope: 'project',
|
|
1528
|
+
inputMode: 'auto',
|
|
1529
|
+
yes: false,
|
|
1530
|
+
cliVersion: '0.2.0',
|
|
1531
|
+
skipLlm: false,
|
|
1532
|
+
skipEmbeddings: false,
|
|
1533
|
+
skipDatabases: false,
|
|
1534
|
+
skipSources: false,
|
|
1535
|
+
skipAgents: false,
|
|
1536
|
+
databaseSchemas: [],
|
|
1537
|
+
}, io.io, { agents })).resolves.toBe(0);
|
|
1538
|
+
expect(agents).toHaveBeenCalledWith(expect.objectContaining({
|
|
1539
|
+
inputMode: 'disabled',
|
|
1540
|
+
yes: false,
|
|
1541
|
+
agents: true,
|
|
1542
|
+
target: 'claude-code',
|
|
1543
|
+
scope: 'project',
|
|
1544
|
+
mode: 'mcp',
|
|
1545
|
+
}), io.io);
|
|
1546
|
+
expect(io.stderr()).not.toContain('Interactive setup requires a terminal');
|
|
1335
1547
|
});
|
|
1336
1548
|
it('routes a ready project menu selection to agent setup', async () => {
|
|
1337
1549
|
const calls = [];
|
|
@@ -1382,7 +1594,7 @@ describe('setup status', () => {
|
|
|
1382
1594
|
await expect(runKtxSetup({
|
|
1383
1595
|
command: 'run',
|
|
1384
1596
|
projectDir: tempDir,
|
|
1385
|
-
mode: '
|
|
1597
|
+
mode: 'auto',
|
|
1386
1598
|
agents: false,
|
|
1387
1599
|
inputMode: 'auto',
|
|
1388
1600
|
yes: false,
|
|
@@ -1433,7 +1645,7 @@ describe('setup status', () => {
|
|
|
1433
1645
|
process.env.KTX_RUNTIME_ROOT = previousRuntimeRoot;
|
|
1434
1646
|
}
|
|
1435
1647
|
}
|
|
1436
|
-
expect(calls).toEqual(['
|
|
1648
|
+
expect(calls).toEqual(['agents']);
|
|
1437
1649
|
});
|
|
1438
1650
|
it('skips to agent setup when context is ready but agents are not configured', async () => {
|
|
1439
1651
|
const calls = [];
|
|
@@ -1474,7 +1686,7 @@ describe('setup status', () => {
|
|
|
1474
1686
|
await expect(runKtxSetup({
|
|
1475
1687
|
command: 'run',
|
|
1476
1688
|
projectDir: tempDir,
|
|
1477
|
-
mode: '
|
|
1689
|
+
mode: 'auto',
|
|
1478
1690
|
agents: false,
|
|
1479
1691
|
inputMode: 'auto',
|
|
1480
1692
|
yes: false,
|
|
@@ -1517,9 +1729,9 @@ describe('setup status', () => {
|
|
|
1517
1729
|
},
|
|
1518
1730
|
})).resolves.toBe(0);
|
|
1519
1731
|
expect(readyMenuSelect).not.toHaveBeenCalled();
|
|
1520
|
-
expect(calls).toEqual(['
|
|
1732
|
+
expect(calls).toEqual(['agents']);
|
|
1521
1733
|
});
|
|
1522
|
-
it('runs only project resolution
|
|
1734
|
+
it('runs only project resolution and agent setup in --agents mode', async () => {
|
|
1523
1735
|
const io = makeIo();
|
|
1524
1736
|
const runtime = vi.fn(async () => runtimeReady(tempDir));
|
|
1525
1737
|
const context = vi.fn(async () => ({ status: 'ready', projectDir: tempDir, runId: 'setup-context-local-test' }));
|
|
@@ -1531,7 +1743,7 @@ describe('setup status', () => {
|
|
|
1531
1743
|
await expect(runKtxSetup({
|
|
1532
1744
|
command: 'run',
|
|
1533
1745
|
projectDir: tempDir,
|
|
1534
|
-
mode: '
|
|
1746
|
+
mode: 'auto',
|
|
1535
1747
|
agents: true,
|
|
1536
1748
|
target: 'universal',
|
|
1537
1749
|
agentScope: 'project',
|
|
@@ -1552,8 +1764,8 @@ describe('setup status', () => {
|
|
|
1552
1764
|
context,
|
|
1553
1765
|
agents,
|
|
1554
1766
|
})).resolves.toBe(0);
|
|
1555
|
-
expect(runtime).
|
|
1556
|
-
expect(context).
|
|
1767
|
+
expect(runtime).not.toHaveBeenCalled();
|
|
1768
|
+
expect(context).not.toHaveBeenCalled();
|
|
1557
1769
|
expect(agents).toHaveBeenCalledTimes(1);
|
|
1558
1770
|
});
|
|
1559
1771
|
it('does not run embedding setup when the model step fails', async () => {
|
|
@@ -1563,19 +1775,20 @@ describe('setup status', () => {
|
|
|
1563
1775
|
await expect(runKtxSetup({
|
|
1564
1776
|
command: 'run',
|
|
1565
1777
|
projectDir: tempDir,
|
|
1566
|
-
mode: '
|
|
1778
|
+
mode: 'auto',
|
|
1567
1779
|
agents: false,
|
|
1568
1780
|
skipAgents: true,
|
|
1569
1781
|
inputMode: 'disabled',
|
|
1570
|
-
yes:
|
|
1782
|
+
yes: true,
|
|
1571
1783
|
cliVersion: '0.2.0',
|
|
1572
1784
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
1573
|
-
|
|
1785
|
+
llmModel: 'claude-sonnet-4-6',
|
|
1574
1786
|
skipLlm: false,
|
|
1575
1787
|
skipEmbeddings: false,
|
|
1576
1788
|
databaseSchemas: [],
|
|
1577
1789
|
skipDatabases: true,
|
|
1578
1790
|
}, testIo.io, { model, embeddings })).resolves.toBe(1);
|
|
1791
|
+
expect(model).toHaveBeenCalledTimes(1);
|
|
1579
1792
|
expect(embeddings).not.toHaveBeenCalled();
|
|
1580
1793
|
});
|
|
1581
1794
|
});
|
package/dist/sl.test.js
CHANGED