@kaelio/ktx 0.1.0 → 0.2.0
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.0-py3-none-any.whl → kaelio_ktx-0.2.0-py3-none-any.whl} +0 -0
- package/assets/python/manifest.json +4 -4
- package/dist/admin-reindex.d.ts +15 -0
- package/dist/admin-reindex.js +168 -0
- package/dist/admin-reindex.test.js +116 -0
- package/dist/{dev.d.ts → admin.d.ts} +1 -1
- package/dist/{dev.js → admin.js} +14 -12
- package/dist/admin.test.d.ts +1 -0
- package/dist/{dev.test.js → admin.test.js} +36 -31
- package/dist/cli-program.js +7 -7
- package/dist/cli-program.test.js +1 -1
- package/dist/cli-runtime.d.ts +2 -0
- package/dist/commands/connection-commands.js +11 -10
- package/dist/commands/connection-selection.d.ts +11 -0
- package/dist/commands/connection-selection.js +9 -0
- package/dist/commands/ingest-commands.js +32 -26
- package/dist/commands/knowledge-commands.js +17 -28
- package/dist/commands/mcp-commands.js +17 -11
- package/dist/commands/setup-commands.js +14 -26
- package/dist/commands/sl-commands.js +27 -32
- package/dist/doctor.test.js +7 -8
- package/dist/example-smoke.test.js +3 -3
- package/dist/index.test.js +102 -70
- package/dist/ingest-depth.js +0 -1
- package/dist/ingest.test-utils.js +2 -2
- package/dist/ingest.test.js +4 -4
- package/dist/io/print-list.test.js +4 -4
- package/dist/knowledge.js +1 -1
- 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.js +2 -2
- package/dist/managed-python-command.test.js +4 -3
- package/dist/managed-python-daemon.js +3 -2
- package/dist/managed-python-daemon.test.js +20 -0
- package/dist/managed-python-runtime.d.ts +5 -1
- package/dist/managed-python-runtime.js +50 -6
- package/dist/managed-python-runtime.test.js +53 -23
- package/dist/memory-flow-tui.test.js +2 -2
- package/dist/next-steps.d.ts +6 -6
- package/dist/next-steps.js +4 -4
- package/dist/next-steps.test.js +5 -5
- package/dist/print-command-tree.test.js +1 -1
- package/dist/proxy-env.d.ts +1 -0
- package/dist/proxy-env.js +23 -0
- package/dist/proxy-env.test.d.ts +1 -0
- package/dist/proxy-env.test.js +17 -0
- package/dist/public-ingest.js +3 -5
- package/dist/public-ingest.test.js +7 -3
- package/dist/runtime.test.js +2 -1
- package/dist/scan.test.js +2 -2
- package/dist/setup-agents.js +6 -4
- package/dist/setup-agents.test.js +35 -1
- package/dist/setup-embeddings.d.ts +1 -0
- package/dist/setup-embeddings.js +29 -7
- package/dist/setup-embeddings.test.js +49 -7
- 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.test.js +4 -2
- package/dist/setup.d.ts +1 -2
- package/dist/setup.js +21 -5
- package/dist/setup.test.js +160 -43
- package/dist/sl.js +1 -1
- package/dist/sl.test.js +2 -1
- package/dist/standalone-smoke.test.js +8 -5
- package/dist/status-project.js +1 -10
- package/node_modules/@ktx/context/dist/index-sync/index.d.ts +2 -0
- package/node_modules/@ktx/context/dist/index-sync/index.js +1 -0
- package/node_modules/@ktx/context/dist/index-sync/reindex.d.ts +20 -0
- package/node_modules/@ktx/context/dist/index-sync/reindex.js +141 -0
- package/node_modules/@ktx/context/dist/index-sync/reindex.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/index-sync/reindex.test.js +139 -0
- package/node_modules/@ktx/context/dist/index-sync/types.d.ts +29 -0
- package/node_modules/@ktx/context/dist/index-sync/types.js +1 -0
- package/node_modules/@ktx/context/dist/index.d.ts +1 -0
- package/node_modules/@ktx/context/dist/index.js +1 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/local-ingest-acceptance.test.js +1 -1
- package/node_modules/@ktx/context/dist/ingest/local-bundle-ingest.test.js +8 -8
- package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.js +4 -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/memory-flow/schema.d.ts +2 -2
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.d.ts +2 -2
- 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/memory/local-memory.js +9 -3
- 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/context/dist/sl/ports.d.ts +3 -3
- package/node_modules/@ktx/context/dist/sl/sl-search.service.d.ts +3 -2
- package/node_modules/@ktx/context/dist/sl/sl-search.service.js +47 -45
- package/node_modules/@ktx/context/dist/sl/sl-search.service.test.js +61 -0
- package/node_modules/@ktx/context/dist/sl/sqlite-sl-sources-index.d.ts +4 -3
- package/node_modules/@ktx/context/dist/sl/sqlite-sl-sources-index.js +15 -5
- package/node_modules/@ktx/context/dist/sl/sqlite-sl-sources-index.test.js +24 -0
- package/node_modules/@ktx/context/dist/wiki/knowledge-wiki.service.d.ts +3 -2
- package/node_modules/@ktx/context/dist/wiki/knowledge-wiki.service.js +62 -51
- package/node_modules/@ktx/context/dist/wiki/knowledge-wiki.service.test.js +59 -3
- package/node_modules/@ktx/context/dist/wiki/ports.d.ts +3 -3
- package/node_modules/@ktx/context/dist/wiki/sqlite-knowledge-index.d.ts +33 -0
- package/node_modules/@ktx/context/dist/wiki/sqlite-knowledge-index.js +155 -2
- package/node_modules/@ktx/context/dist/wiki/sqlite-knowledge-index.test.js +26 -0
- package/node_modules/@ktx/context/package.json +5 -0
- 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 +1 -1
- /package/dist/{dev.test.d.ts → admin-reindex.test.d.ts} +0 -0
package/dist/setup.d.ts
CHANGED
|
@@ -52,7 +52,7 @@ export interface KtxSetupStatus {
|
|
|
52
52
|
export type KtxSetupArgs = {
|
|
53
53
|
command: 'run';
|
|
54
54
|
projectDir: string;
|
|
55
|
-
mode: 'auto'
|
|
55
|
+
mode: 'auto';
|
|
56
56
|
agents: boolean;
|
|
57
57
|
target?: KtxAgentTarget;
|
|
58
58
|
agentScope?: KtxAgentScope;
|
|
@@ -64,7 +64,6 @@ export type KtxSetupArgs = {
|
|
|
64
64
|
anthropicApiKeyEnv?: string;
|
|
65
65
|
anthropicApiKeyFile?: string;
|
|
66
66
|
llmModel?: string;
|
|
67
|
-
anthropicModel?: string;
|
|
68
67
|
vertexProject?: string;
|
|
69
68
|
vertexLocation?: string;
|
|
70
69
|
skipLlm: boolean;
|
package/dist/setup.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs';
|
|
2
|
+
import { rm } from 'node:fs/promises';
|
|
2
3
|
import { basename, join, resolve } from 'node:path';
|
|
3
4
|
import { getLatestLocalIngestStatus, savedMemoryCountsForReport } from '@ktx/context/ingest';
|
|
4
5
|
import { ktxLocalStateDbPath, loadKtxProject, readKtxSetupState, } from '@ktx/context/project';
|
|
@@ -11,7 +12,7 @@ import { readKtxAgentInstallManifest, runKtxSetupAgentsStep, targetDisplayName,
|
|
|
11
12
|
import { runKtxSetupDatabasesStep, } from './setup-databases.js';
|
|
12
13
|
import { runKtxSetupEmbeddingsStep } from './setup-embeddings.js';
|
|
13
14
|
import { isKtxSetupLlmConfigReady, runKtxSetupAnthropicModelStep, } from './setup-models.js';
|
|
14
|
-
import { runKtxSetupProjectStep } from './setup-project.js';
|
|
15
|
+
import { runKtxSetupProjectStep, } from './setup-project.js';
|
|
15
16
|
import { isKtxPreAgentSetupReady, isKtxSetupReady, runKtxSetupReadyChangeMenu, } from './setup-ready-menu.js';
|
|
16
17
|
import { runKtxSetupSourcesStep } from './setup-sources.js';
|
|
17
18
|
import { runKtxSetupRuntimeStep, } from './setup-runtime.js';
|
|
@@ -54,7 +55,6 @@ async function runKtxSetupDemoFromEntryMenu(args, io, deps) {
|
|
|
54
55
|
function embeddingsReady(status) {
|
|
55
56
|
return (status.backend !== undefined &&
|
|
56
57
|
status.backend !== 'none' &&
|
|
57
|
-
status.backend !== 'deterministic' &&
|
|
58
58
|
typeof status.model === 'string' &&
|
|
59
59
|
status.model.length > 0 &&
|
|
60
60
|
typeof status.dimensions === 'number' &&
|
|
@@ -270,6 +270,17 @@ async function commitSetupConfigChanges(projectDir) {
|
|
|
270
270
|
const project = await loadKtxProject({ projectDir });
|
|
271
271
|
await project.git.commitFile('ktx.yaml', 'setup: update KTX project config', 'ktx setup', 'setup@ktx.local');
|
|
272
272
|
}
|
|
273
|
+
const KTX_SETUP_SCAFFOLD_PATHS = ['ktx.yaml', '.ktx', 'wiki', 'semantic-layer', 'raw-sources', '.git'];
|
|
274
|
+
async function cleanupCreatedProjectScaffold(cleanup) {
|
|
275
|
+
if (!cleanup) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
if (cleanup.kind === 'remove-project-dir') {
|
|
279
|
+
await rm(cleanup.projectDir, { recursive: true, force: true });
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
await Promise.all(KTX_SETUP_SCAFFOLD_PATHS.map((relativePath) => rm(join(cleanup.projectDir, relativePath), { recursive: true, force: true })));
|
|
283
|
+
}
|
|
273
284
|
export async function runKtxSetup(args, io, deps = {}) {
|
|
274
285
|
try {
|
|
275
286
|
return await runKtxSetupInner(args, io, deps);
|
|
@@ -390,7 +401,6 @@ async function runKtxSetupInner(args, io, deps = {}) {
|
|
|
390
401
|
...(args.anthropicApiKeyEnv ? { anthropicApiKeyEnv: args.anthropicApiKeyEnv } : {}),
|
|
391
402
|
...(args.anthropicApiKeyFile ? { anthropicApiKeyFile: args.anthropicApiKeyFile } : {}),
|
|
392
403
|
...(args.llmModel ? { llmModel: args.llmModel } : {}),
|
|
393
|
-
...(args.anthropicModel ? { anthropicModel: args.anthropicModel } : {}),
|
|
394
404
|
...(args.vertexProject ? { vertexProject: args.vertexProject } : {}),
|
|
395
405
|
...(args.vertexLocation ? { vertexLocation: args.vertexLocation } : {}),
|
|
396
406
|
forcePrompt: forcePromptSteps.has('models') || runOnly === 'models',
|
|
@@ -493,7 +503,9 @@ async function runKtxSetupInner(args, io, deps = {}) {
|
|
|
493
503
|
const agentsRunner = deps.agents ?? ((agentArgs, agentIo) => runKtxSetupAgentsStep(agentArgs, agentIo, deps.agentsDeps));
|
|
494
504
|
const agentResult = await agentsRunner({
|
|
495
505
|
projectDir: projectResult.projectDir,
|
|
496
|
-
inputMode: args.inputMode
|
|
506
|
+
inputMode: args.inputMode === 'auto' && io.stdout.isTTY !== true && deps.agentsDeps?.prompts === undefined
|
|
507
|
+
? 'disabled'
|
|
508
|
+
: args.inputMode,
|
|
497
509
|
yes: args.yes,
|
|
498
510
|
agents: true,
|
|
499
511
|
...(args.target ? { target: args.target } : {}),
|
|
@@ -507,7 +519,11 @@ async function runKtxSetupInner(args, io, deps = {}) {
|
|
|
507
519
|
agentNextActions = agentResult.nextActions;
|
|
508
520
|
}
|
|
509
521
|
}
|
|
510
|
-
if (stepResult.status === 'failed'
|
|
522
|
+
if (stepResult.status === 'failed') {
|
|
523
|
+
await cleanupCreatedProjectScaffold(projectResult.createdProjectCleanup);
|
|
524
|
+
return 1;
|
|
525
|
+
}
|
|
526
|
+
if (stepResult.status === 'missing-input') {
|
|
511
527
|
return 1;
|
|
512
528
|
}
|
|
513
529
|
if (stepResult.status === 'back') {
|
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';
|
|
@@ -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');
|
|
@@ -387,7 +385,7 @@ describe('setup status', () => {
|
|
|
387
385
|
await expect(runKtxSetup({
|
|
388
386
|
command: 'run',
|
|
389
387
|
projectDir: tempDir,
|
|
390
|
-
mode: '
|
|
388
|
+
mode: 'auto',
|
|
391
389
|
agents: false,
|
|
392
390
|
target: 'claude-code',
|
|
393
391
|
skipAgents: false,
|
|
@@ -456,6 +454,85 @@ describe('setup status', () => {
|
|
|
456
454
|
expect(testIo.stdout()).not.toContain('Optional MCP:');
|
|
457
455
|
expect(testIo.stderr()).toBe('');
|
|
458
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
|
+
});
|
|
459
536
|
it('shows demo near the bottom of the first setup intent menu before project creation', async () => {
|
|
460
537
|
const testIo = makeIo();
|
|
461
538
|
const select = vi.fn(async (options) => {
|
|
@@ -750,16 +827,16 @@ describe('setup status', () => {
|
|
|
750
827
|
}, testIo.io, { entryMenuDeps: { prompts: { select: vi.fn(async () => 'demo'), cancel: vi.fn() } } })).resolves.toBe(0);
|
|
751
828
|
expect(runDemoTour).toHaveBeenCalledWith({ inputMode: 'auto' }, testIo.io, expect.objectContaining({}));
|
|
752
829
|
});
|
|
753
|
-
it('creates a project through run mode when --
|
|
830
|
+
it('creates a project through run mode when --yes is selected', async () => {
|
|
754
831
|
const testIo = makeIo();
|
|
755
832
|
await expect(runKtxSetup({
|
|
756
833
|
command: 'run',
|
|
757
834
|
projectDir: tempDir,
|
|
758
|
-
mode: '
|
|
835
|
+
mode: 'auto',
|
|
759
836
|
agents: false,
|
|
760
837
|
skipAgents: true,
|
|
761
838
|
inputMode: 'disabled',
|
|
762
|
-
yes:
|
|
839
|
+
yes: true,
|
|
763
840
|
cliVersion: '0.2.0',
|
|
764
841
|
skipLlm: true,
|
|
765
842
|
skipEmbeddings: true,
|
|
@@ -821,14 +898,14 @@ describe('setup status', () => {
|
|
|
821
898
|
await expect(runKtxSetup({
|
|
822
899
|
command: 'run',
|
|
823
900
|
projectDir: tempDir,
|
|
824
|
-
mode: '
|
|
901
|
+
mode: 'auto',
|
|
825
902
|
agents: false,
|
|
826
903
|
skipAgents: true,
|
|
827
904
|
inputMode: 'disabled',
|
|
828
|
-
yes:
|
|
905
|
+
yes: true,
|
|
829
906
|
cliVersion: '0.2.0',
|
|
830
907
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
831
|
-
|
|
908
|
+
llmModel: 'claude-sonnet-4-6',
|
|
832
909
|
skipLlm: false,
|
|
833
910
|
skipEmbeddings: true,
|
|
834
911
|
databaseSchemas: [],
|
|
@@ -839,7 +916,7 @@ describe('setup status', () => {
|
|
|
839
916
|
projectDir: tempDir,
|
|
840
917
|
inputMode: 'disabled',
|
|
841
918
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
842
|
-
|
|
919
|
+
llmModel: 'claude-sonnet-4-6',
|
|
843
920
|
skipLlm: false,
|
|
844
921
|
}), testIo.io);
|
|
845
922
|
});
|
|
@@ -849,16 +926,16 @@ describe('setup status', () => {
|
|
|
849
926
|
await expect(runKtxSetup({
|
|
850
927
|
command: 'run',
|
|
851
928
|
projectDir: tempDir,
|
|
852
|
-
mode: '
|
|
929
|
+
mode: 'auto',
|
|
853
930
|
agents: false,
|
|
854
931
|
skipAgents: true,
|
|
855
932
|
inputMode: 'disabled',
|
|
856
|
-
yes:
|
|
933
|
+
yes: true,
|
|
857
934
|
cliVersion: '0.2.0',
|
|
858
935
|
llmBackend: 'vertex',
|
|
859
936
|
vertexProject: 'local-gcp-project',
|
|
860
937
|
vertexLocation: 'us-east5',
|
|
861
|
-
|
|
938
|
+
llmModel: 'claude-sonnet-4-6',
|
|
862
939
|
skipLlm: false,
|
|
863
940
|
skipEmbeddings: true,
|
|
864
941
|
databaseSchemas: [],
|
|
@@ -871,7 +948,7 @@ describe('setup status', () => {
|
|
|
871
948
|
llmBackend: 'vertex',
|
|
872
949
|
vertexProject: 'local-gcp-project',
|
|
873
950
|
vertexLocation: 'us-east5',
|
|
874
|
-
|
|
951
|
+
llmModel: 'claude-sonnet-4-6',
|
|
875
952
|
skipLlm: false,
|
|
876
953
|
}), testIo.io);
|
|
877
954
|
});
|
|
@@ -882,14 +959,14 @@ describe('setup status', () => {
|
|
|
882
959
|
await expect(runKtxSetup({
|
|
883
960
|
command: 'run',
|
|
884
961
|
projectDir: tempDir,
|
|
885
|
-
mode: '
|
|
962
|
+
mode: 'auto',
|
|
886
963
|
agents: false,
|
|
887
964
|
skipAgents: true,
|
|
888
965
|
inputMode: 'disabled',
|
|
889
966
|
yes: true,
|
|
890
967
|
cliVersion: '0.2.0',
|
|
891
968
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
892
|
-
|
|
969
|
+
llmModel: 'claude-sonnet-4-6',
|
|
893
970
|
skipLlm: false,
|
|
894
971
|
embeddingBackend: 'openai',
|
|
895
972
|
embeddingApiKeyEnv: 'OPENAI_API_KEY', // pragma: allowlist secret
|
|
@@ -911,10 +988,11 @@ describe('setup status', () => {
|
|
|
911
988
|
it('passes no-input runtime policy to the embeddings step', async () => {
|
|
912
989
|
const io = makeIo();
|
|
913
990
|
const embeddings = vi.fn(async () => ({ status: 'failed', projectDir: tempDir }));
|
|
991
|
+
await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
|
|
914
992
|
await expect(runKtxSetup({
|
|
915
993
|
command: 'run',
|
|
916
994
|
projectDir: tempDir,
|
|
917
|
-
mode: '
|
|
995
|
+
mode: 'auto',
|
|
918
996
|
agents: false,
|
|
919
997
|
agentScope: 'project',
|
|
920
998
|
skipAgents: true,
|
|
@@ -936,10 +1014,11 @@ describe('setup status', () => {
|
|
|
936
1014
|
const io = makeIo();
|
|
937
1015
|
const embeddings = vi.fn(async () => ({ status: 'ready', projectDir: tempDir }));
|
|
938
1016
|
const context = vi.fn(async () => ({ status: 'failed', projectDir: tempDir }));
|
|
1017
|
+
await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
|
|
939
1018
|
await expect(runKtxSetup({
|
|
940
1019
|
command: 'run',
|
|
941
1020
|
projectDir: tempDir,
|
|
942
|
-
mode: '
|
|
1021
|
+
mode: 'auto',
|
|
943
1022
|
agents: false,
|
|
944
1023
|
agentScope: 'project',
|
|
945
1024
|
skipAgents: true,
|
|
@@ -966,6 +1045,7 @@ describe('setup status', () => {
|
|
|
966
1045
|
});
|
|
967
1046
|
it('lets Back from embedding setup return to the model step instead of exiting', async () => {
|
|
968
1047
|
const testIo = makeIo();
|
|
1048
|
+
await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
|
|
969
1049
|
const modelResults = [
|
|
970
1050
|
{ status: 'ready', projectDir: tempDir },
|
|
971
1051
|
{ status: 'back', projectDir: tempDir },
|
|
@@ -975,7 +1055,7 @@ describe('setup status', () => {
|
|
|
975
1055
|
await expect(runKtxSetup({
|
|
976
1056
|
command: 'run',
|
|
977
1057
|
projectDir: tempDir,
|
|
978
|
-
mode: '
|
|
1058
|
+
mode: 'auto',
|
|
979
1059
|
agents: false,
|
|
980
1060
|
skipAgents: true,
|
|
981
1061
|
inputMode: 'auto',
|
|
@@ -993,6 +1073,7 @@ describe('setup status', () => {
|
|
|
993
1073
|
});
|
|
994
1074
|
it('lets Back from database selection return to embedding setup', async () => {
|
|
995
1075
|
const testIo = makeIo();
|
|
1076
|
+
await writeFile(join(tempDir, 'ktx.yaml'), 'connections: {}\n', 'utf-8');
|
|
996
1077
|
const modelResults = [
|
|
997
1078
|
{ status: 'ready', projectDir: tempDir },
|
|
998
1079
|
{ status: 'back', projectDir: tempDir },
|
|
@@ -1013,11 +1094,11 @@ describe('setup status', () => {
|
|
|
1013
1094
|
await expect(runKtxSetup({
|
|
1014
1095
|
command: 'run',
|
|
1015
1096
|
projectDir: tempDir,
|
|
1016
|
-
mode: '
|
|
1097
|
+
mode: 'auto',
|
|
1017
1098
|
agents: false,
|
|
1018
1099
|
skipAgents: true,
|
|
1019
1100
|
inputMode: 'auto',
|
|
1020
|
-
yes:
|
|
1101
|
+
yes: true,
|
|
1021
1102
|
cliVersion: '0.2.0',
|
|
1022
1103
|
skipLlm: false,
|
|
1023
1104
|
skipEmbeddings: false,
|
|
@@ -1050,7 +1131,7 @@ describe('setup status', () => {
|
|
|
1050
1131
|
agents: false,
|
|
1051
1132
|
skipAgents: true,
|
|
1052
1133
|
inputMode: 'auto',
|
|
1053
|
-
yes:
|
|
1134
|
+
yes: true,
|
|
1054
1135
|
cliVersion: '0.2.0',
|
|
1055
1136
|
skipLlm: false,
|
|
1056
1137
|
skipEmbeddings: true,
|
|
@@ -1078,14 +1159,14 @@ describe('setup status', () => {
|
|
|
1078
1159
|
await expect(runKtxSetup({
|
|
1079
1160
|
command: 'run',
|
|
1080
1161
|
projectDir: tempDir,
|
|
1081
|
-
mode: '
|
|
1162
|
+
mode: 'auto',
|
|
1082
1163
|
agents: false,
|
|
1083
1164
|
skipAgents: true,
|
|
1084
1165
|
inputMode: 'disabled',
|
|
1085
|
-
yes:
|
|
1166
|
+
yes: true,
|
|
1086
1167
|
cliVersion: '0.2.0',
|
|
1087
1168
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
1088
|
-
|
|
1169
|
+
llmModel: 'claude-sonnet-4-6',
|
|
1089
1170
|
skipLlm: false,
|
|
1090
1171
|
embeddingBackend: 'openai',
|
|
1091
1172
|
embeddingApiKeyEnv: 'OPENAI_API_KEY', // pragma: allowlist secret
|
|
@@ -1124,7 +1205,7 @@ describe('setup status', () => {
|
|
|
1124
1205
|
await expect(runKtxSetup({
|
|
1125
1206
|
command: 'run',
|
|
1126
1207
|
projectDir: tempDir,
|
|
1127
|
-
mode: '
|
|
1208
|
+
mode: 'auto',
|
|
1128
1209
|
agents: false,
|
|
1129
1210
|
skipAgents: true,
|
|
1130
1211
|
inputMode: 'disabled',
|
|
@@ -1187,7 +1268,7 @@ describe('setup status', () => {
|
|
|
1187
1268
|
await expect(runKtxSetup({
|
|
1188
1269
|
command: 'run',
|
|
1189
1270
|
projectDir: tempDir,
|
|
1190
|
-
mode: '
|
|
1271
|
+
mode: 'auto',
|
|
1191
1272
|
agents: false,
|
|
1192
1273
|
skipAgents: true,
|
|
1193
1274
|
inputMode: 'disabled',
|
|
@@ -1224,7 +1305,7 @@ describe('setup status', () => {
|
|
|
1224
1305
|
await expect(runKtxSetup({
|
|
1225
1306
|
command: 'run',
|
|
1226
1307
|
projectDir: tempDir,
|
|
1227
|
-
mode: '
|
|
1308
|
+
mode: 'auto',
|
|
1228
1309
|
agents: false,
|
|
1229
1310
|
skipAgents: true,
|
|
1230
1311
|
inputMode: 'disabled',
|
|
@@ -1263,7 +1344,7 @@ describe('setup status', () => {
|
|
|
1263
1344
|
await expect(runKtxSetup({
|
|
1264
1345
|
command: 'run',
|
|
1265
1346
|
projectDir: tempDir,
|
|
1266
|
-
mode: '
|
|
1347
|
+
mode: 'auto',
|
|
1267
1348
|
agents: false,
|
|
1268
1349
|
inputMode: 'disabled',
|
|
1269
1350
|
yes: true,
|
|
@@ -1315,7 +1396,7 @@ describe('setup status', () => {
|
|
|
1315
1396
|
await expect(runKtxSetup({
|
|
1316
1397
|
command: 'run',
|
|
1317
1398
|
projectDir: tempDir,
|
|
1318
|
-
mode: '
|
|
1399
|
+
mode: 'auto',
|
|
1319
1400
|
agents: false,
|
|
1320
1401
|
inputMode: 'disabled',
|
|
1321
1402
|
yes: true,
|
|
@@ -1356,7 +1437,7 @@ describe('setup status', () => {
|
|
|
1356
1437
|
await expect(runKtxSetup({
|
|
1357
1438
|
command: 'run',
|
|
1358
1439
|
projectDir: tempDir,
|
|
1359
|
-
mode: '
|
|
1440
|
+
mode: 'auto',
|
|
1360
1441
|
agents: true,
|
|
1361
1442
|
target: 'codex',
|
|
1362
1443
|
agentScope: 'project',
|
|
@@ -1406,7 +1487,7 @@ describe('setup status', () => {
|
|
|
1406
1487
|
await expect(runKtxSetup({
|
|
1407
1488
|
command: 'run',
|
|
1408
1489
|
projectDir: tempDir,
|
|
1409
|
-
mode: '
|
|
1490
|
+
mode: 'auto',
|
|
1410
1491
|
agents: true,
|
|
1411
1492
|
target: 'codex',
|
|
1412
1493
|
agentScope: 'project',
|
|
@@ -1429,6 +1510,41 @@ describe('setup status', () => {
|
|
|
1429
1510
|
expect(agents).toHaveBeenCalledTimes(1);
|
|
1430
1511
|
expect(io.stderr()).not.toContain('KTX context is not ready for agents.');
|
|
1431
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');
|
|
1547
|
+
});
|
|
1432
1548
|
it('routes a ready project menu selection to agent setup', async () => {
|
|
1433
1549
|
const calls = [];
|
|
1434
1550
|
const io = makeIo();
|
|
@@ -1478,7 +1594,7 @@ describe('setup status', () => {
|
|
|
1478
1594
|
await expect(runKtxSetup({
|
|
1479
1595
|
command: 'run',
|
|
1480
1596
|
projectDir: tempDir,
|
|
1481
|
-
mode: '
|
|
1597
|
+
mode: 'auto',
|
|
1482
1598
|
agents: false,
|
|
1483
1599
|
inputMode: 'auto',
|
|
1484
1600
|
yes: false,
|
|
@@ -1570,7 +1686,7 @@ describe('setup status', () => {
|
|
|
1570
1686
|
await expect(runKtxSetup({
|
|
1571
1687
|
command: 'run',
|
|
1572
1688
|
projectDir: tempDir,
|
|
1573
|
-
mode: '
|
|
1689
|
+
mode: 'auto',
|
|
1574
1690
|
agents: false,
|
|
1575
1691
|
inputMode: 'auto',
|
|
1576
1692
|
yes: false,
|
|
@@ -1627,7 +1743,7 @@ describe('setup status', () => {
|
|
|
1627
1743
|
await expect(runKtxSetup({
|
|
1628
1744
|
command: 'run',
|
|
1629
1745
|
projectDir: tempDir,
|
|
1630
|
-
mode: '
|
|
1746
|
+
mode: 'auto',
|
|
1631
1747
|
agents: true,
|
|
1632
1748
|
target: 'universal',
|
|
1633
1749
|
agentScope: 'project',
|
|
@@ -1659,19 +1775,20 @@ describe('setup status', () => {
|
|
|
1659
1775
|
await expect(runKtxSetup({
|
|
1660
1776
|
command: 'run',
|
|
1661
1777
|
projectDir: tempDir,
|
|
1662
|
-
mode: '
|
|
1778
|
+
mode: 'auto',
|
|
1663
1779
|
agents: false,
|
|
1664
1780
|
skipAgents: true,
|
|
1665
1781
|
inputMode: 'disabled',
|
|
1666
|
-
yes:
|
|
1782
|
+
yes: true,
|
|
1667
1783
|
cliVersion: '0.2.0',
|
|
1668
1784
|
anthropicApiKeyEnv: 'ANTHROPIC_API_KEY', // pragma: allowlist secret
|
|
1669
|
-
|
|
1785
|
+
llmModel: 'claude-sonnet-4-6',
|
|
1670
1786
|
skipLlm: false,
|
|
1671
1787
|
skipEmbeddings: false,
|
|
1672
1788
|
databaseSchemas: [],
|
|
1673
1789
|
skipDatabases: true,
|
|
1674
1790
|
}, testIo.io, { model, embeddings })).resolves.toBe(1);
|
|
1791
|
+
expect(model).toHaveBeenCalledTimes(1);
|
|
1675
1792
|
expect(embeddings).not.toHaveBeenCalled();
|
|
1676
1793
|
});
|
|
1677
1794
|
});
|
package/dist/sl.js
CHANGED
|
@@ -99,7 +99,7 @@ export async function runKtxSl(args, io = process, deps = {}) {
|
|
|
99
99
|
await printSlSources({
|
|
100
100
|
rows: sources,
|
|
101
101
|
emptyMessage: `No semantic-layer sources matched "${args.query}" in ${project.projectDir}`,
|
|
102
|
-
emptyHint: 'Run `ktx sl
|
|
102
|
+
emptyHint: 'Run `ktx sl` to inspect available sources.',
|
|
103
103
|
command: 'sl search',
|
|
104
104
|
output: args.output,
|
|
105
105
|
json: args.json,
|
package/dist/sl.test.js
CHANGED
|
@@ -76,7 +76,7 @@ async function writeSqliteScanConfig(projectDir, dbPath, enrich = false) {
|
|
|
76
76
|
' enrichment:',
|
|
77
77
|
' mode: deterministic',
|
|
78
78
|
' embeddings:',
|
|
79
|
-
' backend:
|
|
79
|
+
' backend: none',
|
|
80
80
|
' dimensions: 6',
|
|
81
81
|
]
|
|
82
82
|
: []),
|
|
@@ -94,7 +94,6 @@ async function runSetupNewProject(projectDir) {
|
|
|
94
94
|
'setup',
|
|
95
95
|
'--project-dir',
|
|
96
96
|
projectDir,
|
|
97
|
-
'--new',
|
|
98
97
|
'--no-input',
|
|
99
98
|
'--yes',
|
|
100
99
|
'--skip-llm',
|
|
@@ -117,6 +116,10 @@ describe('standalone built ktx CLI smoke', () => {
|
|
|
117
116
|
const init = await runSetupNewProject(projectDir);
|
|
118
117
|
expectSetupStderr(init);
|
|
119
118
|
expect(init.stdout).toContain(`Project: ${projectDir}`);
|
|
119
|
+
const reindex = await runBuiltCli(['--project-dir', projectDir, 'admin', 'reindex', '--output', 'plain']);
|
|
120
|
+
expect(reindex.code).toBe(0);
|
|
121
|
+
expect(reindex.stdout).toContain('reindex\t');
|
|
122
|
+
expect(reindex.stderr).toContain('wiki/global');
|
|
120
123
|
const run = await runBuiltCli([
|
|
121
124
|
'ingest',
|
|
122
125
|
'run',
|
|
@@ -126,7 +129,7 @@ describe('standalone built ktx CLI smoke', () => {
|
|
|
126
129
|
'fake',
|
|
127
130
|
]);
|
|
128
131
|
expect(run).toMatchObject({ code: 1, stdout: '' });
|
|
129
|
-
expect(run.stderr).toContain("unknown option '--
|
|
132
|
+
expect(run.stderr).toContain("unknown option '--adapter'");
|
|
130
133
|
});
|
|
131
134
|
it('rejects the removed agent command through the built binary', async () => {
|
|
132
135
|
const result = await runBuiltCli(['agent']);
|
|
@@ -135,7 +138,7 @@ describe('standalone built ktx CLI smoke', () => {
|
|
|
135
138
|
expect(result.stderr).toContain("unknown command 'agent'");
|
|
136
139
|
});
|
|
137
140
|
it('runs status setup checks through the built binary', async () => {
|
|
138
|
-
const result = await runBuiltCli(['status', '--verbose', '--no-input']);
|
|
141
|
+
const result = await runBuiltCli(['status', '--verbose', '--no-input'], { cwd: tempDir });
|
|
139
142
|
expect(result.stdout).toMatch(/KTX status/);
|
|
140
143
|
if (result.stdout.includes('No project here yet.')) {
|
|
141
144
|
expect(result.stdout).toContain('ktx setup');
|
|
@@ -236,7 +239,7 @@ describe('standalone built ktx CLI smoke', () => {
|
|
|
236
239
|
]);
|
|
237
240
|
expect(add.code).toBe(1);
|
|
238
241
|
expect(add.stdout).toBe('');
|
|
239
|
-
expect(add.stderr).
|
|
242
|
+
expect(add.stderr).toMatch(/unknown (command|option)|too many arguments/);
|
|
240
243
|
const yaml = await readFile(join(projectDir, 'ktx.yaml'), 'utf-8');
|
|
241
244
|
expect(yaml).not.toContain('driver: notion');
|
|
242
245
|
expect(yaml).not.toContain('auth_token_ref: env:NOTION_TOKEN');
|
package/dist/status-project.js
CHANGED
|
@@ -120,15 +120,6 @@ function buildEmbeddingsStatus(config, env) {
|
|
|
120
120
|
detail: 'disabled — semantic search will be skipped',
|
|
121
121
|
};
|
|
122
122
|
}
|
|
123
|
-
if (backend === 'deterministic') {
|
|
124
|
-
return {
|
|
125
|
-
backend,
|
|
126
|
-
model,
|
|
127
|
-
dimensions,
|
|
128
|
-
status: 'warn',
|
|
129
|
-
detail: 'deterministic — semantic search degraded (lexical/dictionary lanes still work)',
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
123
|
if (backend === 'openai') {
|
|
133
124
|
const ref = config.openai?.api_key;
|
|
134
125
|
const resolved = resolveRef(ref, env);
|
|
@@ -469,7 +460,7 @@ function buildVerdict(llm, embeddings, connections, queryHistory, warnings) {
|
|
|
469
460
|
if (llm.status === 'warn')
|
|
470
461
|
reasons.push('LLM credentials missing');
|
|
471
462
|
if (embeddings.status === 'warn') {
|
|
472
|
-
if (embeddings.backend === '
|
|
463
|
+
if (embeddings.backend === 'none') {
|
|
473
464
|
reasons.push('semantic search disabled');
|
|
474
465
|
}
|
|
475
466
|
else {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { discoverReindexScopes, reindexLocalIndexes } from './reindex.js';
|