@kaelio/ktx 0.1.0-rc.5 → 0.1.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 +0 -0
- package/assets/python/manifest.json +2 -2
- package/dist/clack.d.ts +6 -0
- package/dist/clack.js +23 -0
- package/dist/cli-program.js +5 -2
- package/dist/cli-program.test.js +7 -1
- package/dist/cli-runtime.d.ts +4 -0
- package/dist/cli-runtime.js +8 -1
- package/dist/command-schemas.d.ts +1 -1
- package/dist/commands/ingest-commands.js +1 -0
- package/dist/commands/knowledge-commands.js +5 -0
- package/dist/commands/mcp-commands.js +11 -3
- package/dist/commands/mcp-commands.test.js +30 -1
- package/dist/commands/sql-commands.d.ts +3 -0
- package/dist/commands/sql-commands.js +43 -0
- package/dist/commands/sql-commands.test.d.ts +1 -0
- package/dist/commands/sql-commands.test.js +68 -0
- package/dist/context-build-view.js +5 -1
- package/dist/dev.test.js +27 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.test.js +56 -21
- package/dist/ingest.js +123 -18
- package/dist/ingest.test.js +206 -0
- package/dist/io/print-list.d.ts +2 -1
- package/dist/io/print-list.js +7 -0
- package/dist/io/print-list.test.js +13 -11
- package/dist/io/symbols.d.ts +2 -2
- package/dist/knowledge.d.ts +1 -0
- package/dist/knowledge.js +34 -16
- package/dist/knowledge.test.js +27 -0
- package/dist/managed-python-command.d.ts +2 -0
- package/dist/managed-python-command.js +17 -9
- package/dist/managed-python-command.test.js +59 -4
- package/dist/next-steps.js +1 -1
- package/dist/next-steps.test.js +2 -0
- package/dist/print-command-tree.js +7 -1
- package/dist/public-ingest.d.ts +9 -1
- package/dist/public-ingest.js +50 -7
- package/dist/public-ingest.test.js +69 -2
- package/dist/release-version.d.ts +5 -0
- package/dist/release-version.js +44 -0
- package/dist/runtime-requirements.d.ts +23 -0
- package/dist/runtime-requirements.js +99 -0
- package/dist/runtime-requirements.test.d.ts +1 -0
- package/dist/runtime-requirements.test.js +63 -0
- package/dist/setup-agents.d.ts +11 -3
- package/dist/setup-agents.js +397 -134
- package/dist/setup-agents.test.js +359 -61
- package/dist/setup-embeddings.js +3 -6
- package/dist/setup-embeddings.test.js +18 -2
- package/dist/setup-models.js +2 -2
- package/dist/setup-models.test.js +5 -3
- package/dist/setup-ready-menu.d.ts +1 -1
- package/dist/setup-ready-menu.js +2 -0
- package/dist/setup-ready-menu.test.js +3 -0
- package/dist/setup-runtime.d.ts +45 -0
- package/dist/setup-runtime.js +47 -0
- package/dist/setup-runtime.test.d.ts +1 -0
- package/dist/setup-runtime.test.js +110 -0
- package/dist/setup-sources-notion.test.d.ts +1 -0
- package/dist/setup-sources-notion.test.js +107 -0
- package/dist/setup-sources.js +5 -2
- package/dist/setup.d.ts +19 -1
- package/dist/setup.js +104 -29
- package/dist/setup.test.js +221 -57
- package/dist/sl.js +2 -2
- package/dist/sl.test.js +10 -0
- package/dist/source-mapping.js +9 -1
- package/dist/source-mapping.test.d.ts +1 -0
- package/dist/source-mapping.test.js +65 -0
- package/dist/sql.d.ts +22 -0
- package/dist/sql.js +125 -0
- package/dist/sql.test.d.ts +1 -0
- package/dist/sql.test.js +226 -0
- package/node_modules/@ktx/connector-clickhouse/dist/package-exports.test.js +1 -1
- package/node_modules/@ktx/context/dist/connections/connection-type.d.ts +4 -4
- package/node_modules/@ktx/context/dist/core/git.service.d.ts +3 -0
- package/node_modules/@ktx/context/dist/core/git.service.js +47 -1
- package/node_modules/@ktx/context/dist/core/git.service.patch.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/core/git.service.patch.test.js +40 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/types.d.ts +5 -5
- package/node_modules/@ktx/context/dist/ingest/adapters/looker/looker.adapter.d.ts +2 -2
- package/node_modules/@ktx/context/dist/ingest/adapters/looker/tools/looker-query-to-sl.tool.d.ts +2 -2
- package/node_modules/@ktx/context/dist/ingest/adapters/looker/types.d.ts +16 -16
- package/node_modules/@ktx/context/dist/ingest/adapters/lookml/pull-config.d.ts +1 -1
- package/node_modules/@ktx/context/dist/ingest/adapters/metabase/fetch.js +16 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/metabase/fetch.test.js +41 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/metricflow.adapter.d.ts +2 -1
- package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/metricflow.adapter.js +40 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/metricflow.adapter.test.js +116 -1
- package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/projection-config.d.ts +29 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/projection-config.js +40 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/metricflow/pull-config.d.ts +1 -1
- package/node_modules/@ktx/context/dist/ingest/artifact-gates.d.ts +25 -0
- package/node_modules/@ktx/context/dist/ingest/artifact-gates.js +149 -0
- package/node_modules/@ktx/context/dist/ingest/artifact-gates.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/artifact-gates.test.js +167 -0
- package/node_modules/@ktx/context/dist/ingest/final-gate-repair.d.ts +29 -0
- package/node_modules/@ktx/context/dist/ingest/final-gate-repair.js +178 -0
- package/node_modules/@ktx/context/dist/ingest/final-gate-repair.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/final-gate-repair.test.js +109 -0
- package/node_modules/@ktx/context/dist/ingest/index.d.ts +8 -1
- package/node_modules/@ktx/context/dist/ingest/index.js +7 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.d.ts +18 -2
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.isolated-diff.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.isolated-diff.test.js +1761 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.js +1695 -901
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.test.js +135 -118
- package/node_modules/@ktx/context/dist/ingest/ingest-trace.d.ts +50 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-trace.js +88 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-trace.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-trace.test.js +76 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/git-patch.d.ts +16 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/git-patch.js +78 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/git-patch.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/git-patch.test.js +76 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/patch-integrator.d.ts +58 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/patch-integrator.js +223 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/patch-integrator.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/patch-integrator.test.js +369 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/textual-conflict-resolver.d.ts +23 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/textual-conflict-resolver.js +190 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/textual-conflict-resolver.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/textual-conflict-resolver.test.js +101 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/work-unit-executor.d.ts +15 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/work-unit-executor.js +61 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/work-unit-executor.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/isolated-diff/work-unit-executor.test.js +137 -0
- package/node_modules/@ktx/context/dist/ingest/local-bundle-ingest.test.js +7 -0
- package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.js +54 -10
- package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.test.js +65 -0
- package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.d.ts +23 -5
- package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.js +17 -0
- package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.test.js +1 -0
- package/node_modules/@ktx/context/dist/ingest/memory-flow/types.d.ts +6 -0
- package/node_modules/@ktx/context/dist/ingest/parsed-target-table.d.ts +1 -1
- package/node_modules/@ktx/context/dist/ingest/ports.d.ts +3 -0
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.d.ts +32 -7
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.js +25 -0
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.test.js +124 -0
- package/node_modules/@ktx/context/dist/ingest/reports.d.ts +23 -0
- package/node_modules/@ktx/context/dist/ingest/semantic-layer-target-policy.d.ts +11 -0
- package/node_modules/@ktx/context/dist/ingest/semantic-layer-target-policy.js +26 -0
- package/node_modules/@ktx/context/dist/ingest/semantic-layer-target-policy.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/semantic-layer-target-policy.test.js +25 -0
- package/node_modules/@ktx/context/dist/ingest/stages/stage-3-work-units.d.ts +4 -0
- package/node_modules/@ktx/context/dist/ingest/stages/stage-3-work-units.js +4 -0
- package/node_modules/@ktx/context/dist/ingest/stages/stage-3-work-units.test.js +29 -0
- package/node_modules/@ktx/context/dist/ingest/tools/emit-unmapped-fallback.tool.d.ts +1 -1
- package/node_modules/@ktx/context/dist/ingest/types.d.ts +24 -0
- package/node_modules/@ktx/context/dist/ingest/wiki-body-refs.d.ts +24 -0
- package/node_modules/@ktx/context/dist/ingest/wiki-body-refs.js +111 -0
- package/node_modules/@ktx/context/dist/ingest/wiki-body-refs.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/wiki-body-refs.test.js +138 -0
- package/node_modules/@ktx/context/dist/llm/claude-code-runtime.js +19 -2
- package/node_modules/@ktx/context/dist/llm/claude-code-runtime.test.js +33 -0
- package/node_modules/@ktx/context/dist/project/setup-config.d.ts +1 -1
- package/node_modules/@ktx/context/dist/project/setup-config.js +10 -1
- package/node_modules/@ktx/context/dist/project/setup-config.test.js +3 -2
- package/node_modules/@ktx/context/dist/sl/tools/sl-edit-source.tool.js +5 -1
- package/node_modules/@ktx/context/dist/sl/tools/sl-edit-source.tool.test.js +15 -0
- package/node_modules/@ktx/context/dist/sl/tools/sl-write-source.tool.js +5 -1
- package/node_modules/@ktx/context/dist/sl/tools/sl-write-source.tool.test.js +22 -0
- package/node_modules/@ktx/context/dist/tools/action-target-connection.d.ts +9 -0
- package/node_modules/@ktx/context/dist/tools/action-target-connection.js +14 -0
- package/node_modules/@ktx/context/dist/tools/context-candidate-write.tool.d.ts +4 -4
- package/node_modules/@ktx/context/dist/tools/index.d.ts +1 -0
- package/node_modules/@ktx/context/dist/tools/index.js +1 -0
- package/node_modules/@ktx/context/dist/wiki/local-knowledge.js +4 -1
- package/node_modules/@ktx/context/dist/wiki/local-knowledge.test.js +44 -0
- package/node_modules/@ktx/context/dist/wiki/tools/wiki-write.tool.js +3 -48
- package/node_modules/@ktx/context/dist/wiki/tools/wiki-write.tool.test.js +28 -0
- package/node_modules/@ktx/context/dist/wiki/wiki-ref-validation.d.ts +17 -0
- package/node_modules/@ktx/context/dist/wiki/wiki-ref-validation.js +79 -0
- package/node_modules/@ktx/context/dist/wiki/wiki-ref-validation.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/wiki/wiki-ref-validation.test.js +64 -0
- package/node_modules/@ktx/context/prompts/memory_agent_bundle_ingest_work_unit.md +23 -4
- package/node_modules/@ktx/context/skills/ingest_triage/SKILL.md +7 -3
- package/package.json +4 -4
|
Binary file
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"version": "0.1.0",
|
|
6
6
|
"wheel": {
|
|
7
7
|
"file": "kaelio_ktx-0.1.0-py3-none-any.whl",
|
|
8
|
-
"sha256": "
|
|
9
|
-
"bytes":
|
|
8
|
+
"sha256": "1145cf0c90879270dc335a8d0ca49a598f81e0f47a37fdf646fc6c6798fe3c8b",
|
|
9
|
+
"bytes": 80523
|
|
10
10
|
}
|
|
11
11
|
}
|
package/dist/clack.d.ts
CHANGED
|
@@ -4,6 +4,11 @@ export interface KtxCliSpinner {
|
|
|
4
4
|
stop(message: string): void;
|
|
5
5
|
error(message: string): void;
|
|
6
6
|
}
|
|
7
|
+
export interface KtxCliSpinnerIo {
|
|
8
|
+
stderr: {
|
|
9
|
+
write(chunk: string): void;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
7
12
|
export interface KtxCliPromptAdapter {
|
|
8
13
|
confirm(options: {
|
|
9
14
|
message: string;
|
|
@@ -23,4 +28,5 @@ export declare class KtxCliPromptCancelledError extends Error {
|
|
|
23
28
|
constructor(message?: string);
|
|
24
29
|
}
|
|
25
30
|
export declare function createClackSpinner(): KtxCliSpinner;
|
|
31
|
+
export declare function createStaticCliSpinner(io: KtxCliSpinnerIo): KtxCliSpinner;
|
|
26
32
|
export declare function createClackPromptAdapter(): KtxCliPromptAdapter;
|
package/dist/clack.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { cancel, confirm, isCancel, log, spinner } from '@clack/prompts';
|
|
2
|
+
const ESC = String.fromCharCode(0x1b);
|
|
2
3
|
export class KtxCliPromptCancelledError extends Error {
|
|
3
4
|
constructor(message = 'Operation cancelled.') {
|
|
4
5
|
super(message);
|
|
@@ -8,6 +9,28 @@ export class KtxCliPromptCancelledError extends Error {
|
|
|
8
9
|
export function createClackSpinner() {
|
|
9
10
|
return spinner();
|
|
10
11
|
}
|
|
12
|
+
function magenta(text) {
|
|
13
|
+
return `${ESC}[35m${text}${ESC}[39m`;
|
|
14
|
+
}
|
|
15
|
+
function red(text) {
|
|
16
|
+
return `${ESC}[31m${text}${ESC}[39m`;
|
|
17
|
+
}
|
|
18
|
+
export function createStaticCliSpinner(io) {
|
|
19
|
+
return {
|
|
20
|
+
start(message) {
|
|
21
|
+
io.stderr.write(`${magenta('◐')} ${message}\n`);
|
|
22
|
+
},
|
|
23
|
+
message(message) {
|
|
24
|
+
io.stderr.write(`${magenta('│')} ${message}\n`);
|
|
25
|
+
},
|
|
26
|
+
stop(message) {
|
|
27
|
+
io.stderr.write(`${magenta('◇')} ${message}\n`);
|
|
28
|
+
},
|
|
29
|
+
error(message) {
|
|
30
|
+
io.stderr.write(`${red('■')} ${message}\n`);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
11
34
|
export function createClackPromptAdapter() {
|
|
12
35
|
return {
|
|
13
36
|
async confirm(options) {
|
package/dist/cli-program.js
CHANGED
|
@@ -7,13 +7,15 @@ import { registerWikiCommands } from './commands/knowledge-commands.js';
|
|
|
7
7
|
import { registerMcpCommands } from './commands/mcp-commands.js';
|
|
8
8
|
import { registerSetupCommands } from './commands/setup-commands.js';
|
|
9
9
|
import { registerSlCommands } from './commands/sl-commands.js';
|
|
10
|
+
import { registerSqlCommands } from './commands/sql-commands.js';
|
|
10
11
|
import { registerStatusCommands } from './commands/status-commands.js';
|
|
11
12
|
import { registerDevCommands } from './dev.js';
|
|
12
13
|
import { renderMissingProjectMessage } from './doctor.js';
|
|
13
14
|
import { findNearestKtxProjectDir, resolveKtxProjectDir } from './project-resolver.js';
|
|
14
15
|
import { profileMark, profileSpan } from './startup-profile.js';
|
|
15
16
|
profileMark('module:cli-program');
|
|
16
|
-
const PROJECT_AWARE_ROOT_COMMANDS = new Set(['setup', 'connection', 'ingest', 'wiki', 'sl', 'status', 'mcp']);
|
|
17
|
+
const PROJECT_AWARE_ROOT_COMMANDS = new Set(['setup', 'connection', 'ingest', 'wiki', 'sl', 'sql', 'status', 'mcp']);
|
|
18
|
+
const PROJECT_INDEPENDENT_DEV_COMMANDS = new Set(['runtime', 'schema']);
|
|
17
19
|
const COMMANDS_THAT_CREATE_PROJECT = new Set(['setup', 'ktx dev init']);
|
|
18
20
|
const COMMANDS_WITH_OWN_MISSING_PROJECT_HANDLING = new Set(['status']);
|
|
19
21
|
const GLOBAL_OPTIONS_WITH_VALUE = new Set(['--project-dir']);
|
|
@@ -104,7 +106,7 @@ function isProjectAwareCommand(path) {
|
|
|
104
106
|
}
|
|
105
107
|
const rootCommand = path[1];
|
|
106
108
|
if (rootCommand === 'dev') {
|
|
107
|
-
return path[2] !== undefined && path[2]
|
|
109
|
+
return path[2] !== undefined && !PROJECT_INDEPENDENT_DEV_COMMANDS.has(path[2]);
|
|
108
110
|
}
|
|
109
111
|
return rootCommand !== undefined && PROJECT_AWARE_ROOT_COMMANDS.has(rootCommand);
|
|
110
112
|
}
|
|
@@ -310,6 +312,7 @@ export function buildKtxProgram(options) {
|
|
|
310
312
|
});
|
|
311
313
|
registerWikiCommands(program, context);
|
|
312
314
|
registerSlCommands(program, context);
|
|
315
|
+
registerSqlCommands(program, context);
|
|
313
316
|
registerStatusCommands(program, context);
|
|
314
317
|
registerMcpCommands(program, context);
|
|
315
318
|
registerDevCommands(program, context);
|
package/dist/cli-program.test.js
CHANGED
|
@@ -7,7 +7,13 @@ function stubIo() {
|
|
|
7
7
|
};
|
|
8
8
|
}
|
|
9
9
|
function stubPackageInfo() {
|
|
10
|
-
return {
|
|
10
|
+
return {
|
|
11
|
+
name: '@ktx/cli',
|
|
12
|
+
version: '0.0.0-test',
|
|
13
|
+
packageVersion: '0.0.0-private',
|
|
14
|
+
runtimeVersion: '0.0.0-test',
|
|
15
|
+
contextPackageName: '@ktx/context',
|
|
16
|
+
};
|
|
11
17
|
}
|
|
12
18
|
describe('buildKtxProgram', () => {
|
|
13
19
|
it('returns a Command named "ktx" with all registered top-level subcommands', () => {
|
package/dist/cli-runtime.d.ts
CHANGED
|
@@ -5,10 +5,13 @@ import type { KtxPublicIngestArgs } from './public-ingest.js';
|
|
|
5
5
|
import type { KtxRuntimeArgs } from './runtime.js';
|
|
6
6
|
import type { KtxSetupArgs } from './setup.js';
|
|
7
7
|
import type { KtxSlArgs } from './sl.js';
|
|
8
|
+
import type { KtxSqlArgs } from './sql.js';
|
|
8
9
|
import type { KtxTextIngestArgs } from './text-ingest.js';
|
|
9
10
|
export interface KtxCliPackageInfo {
|
|
10
11
|
name: string;
|
|
11
12
|
version: string;
|
|
13
|
+
packageVersion: string;
|
|
14
|
+
runtimeVersion: string;
|
|
12
15
|
contextPackageName: '@ktx/context';
|
|
13
16
|
}
|
|
14
17
|
export interface KtxCliIo {
|
|
@@ -30,6 +33,7 @@ export interface KtxCliDeps {
|
|
|
30
33
|
runtime?: (args: KtxRuntimeArgs, io: KtxCliIo) => Promise<number>;
|
|
31
34
|
knowledge?: (args: KtxKnowledgeArgs, io: KtxCliIo) => Promise<number>;
|
|
32
35
|
sl?: (args: KtxSlArgs, io: KtxCliIo) => Promise<number>;
|
|
36
|
+
sql?: (args: KtxSqlArgs, io: KtxCliIo) => Promise<number>;
|
|
33
37
|
mcp?: {
|
|
34
38
|
startDaemon?: typeof import('./managed-mcp-daemon.js').startKtxMcpDaemon;
|
|
35
39
|
stopDaemon?: typeof import('./managed-mcp-daemon.js').stopKtxMcpDaemon;
|
package/dist/cli-runtime.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
import { profileMark, profileSpan } from './startup-profile.js';
|
|
3
|
+
import { resolveKtxRuntimeVersion } from './release-version.js';
|
|
3
4
|
profileMark('module:cli-runtime');
|
|
4
5
|
const requirePackageJson = createRequire(import.meta.url);
|
|
5
6
|
export function getKtxCliPackageInfo() {
|
|
@@ -14,9 +15,15 @@ export function packageInfoFromJson(packageJson) {
|
|
|
14
15
|
typeof packageJson.version !== 'string') {
|
|
15
16
|
throw new Error('Invalid KTX CLI package metadata');
|
|
16
17
|
}
|
|
18
|
+
const runtimeVersion = resolveKtxRuntimeVersion({
|
|
19
|
+
packageName: packageJson.name,
|
|
20
|
+
packageVersion: packageJson.version,
|
|
21
|
+
});
|
|
17
22
|
return {
|
|
18
23
|
name: packageJson.name,
|
|
19
|
-
version:
|
|
24
|
+
version: runtimeVersion,
|
|
25
|
+
packageVersion: packageJson.version,
|
|
26
|
+
runtimeVersion,
|
|
20
27
|
contextPackageName: '@ktx/context',
|
|
21
28
|
};
|
|
22
29
|
}
|
|
@@ -26,9 +26,9 @@ export declare const slQueryCommandSchema: z.ZodObject<{
|
|
|
26
26
|
execute: z.ZodBoolean;
|
|
27
27
|
cliVersion: z.ZodString;
|
|
28
28
|
runtimeInstallPolicy: z.ZodEnum<{
|
|
29
|
-
auto: "auto";
|
|
30
29
|
never: "never";
|
|
31
30
|
prompt: "prompt";
|
|
31
|
+
auto: "auto";
|
|
32
32
|
}>;
|
|
33
33
|
maxRows: z.ZodOptional<z.ZodNumber>;
|
|
34
34
|
}, z.core.$strip>;
|
|
@@ -17,6 +17,7 @@ export function registerIngestCommands(program, context, commandOptions) {
|
|
|
17
17
|
.option('--query-history-window-days <days>', 'Query-history lookback window for this run', parsePositiveIntegerOption)
|
|
18
18
|
.addOption(new Option('--plain', 'Print plain text output').conflicts(['json']))
|
|
19
19
|
.addOption(new Option('--json', 'Print JSON output').conflicts(['plain']))
|
|
20
|
+
.option('--yes', 'Install required managed runtime features without prompting')
|
|
20
21
|
.option('--no-input', 'Disable interactive terminal input')
|
|
21
22
|
.showHelpAfterError();
|
|
22
23
|
ingest.action(async (connectionId, options, command) => {
|
|
@@ -6,6 +6,10 @@ async function runKnowledgeArgs(context, args) {
|
|
|
6
6
|
const runner = context.deps.knowledge ?? (await import('../knowledge.js')).runKtxKnowledge;
|
|
7
7
|
context.setExitCode(await runner(args, context.io));
|
|
8
8
|
}
|
|
9
|
+
function isDebugEnabled(command) {
|
|
10
|
+
const options = (command.optsWithGlobals ? command.optsWithGlobals() : command.opts());
|
|
11
|
+
return options.debug === true;
|
|
12
|
+
}
|
|
9
13
|
export function registerWikiCommands(program, context) {
|
|
10
14
|
const wiki = program
|
|
11
15
|
.command('wiki')
|
|
@@ -51,6 +55,7 @@ export function registerWikiCommands(program, context) {
|
|
|
51
55
|
userId: options.userId,
|
|
52
56
|
output: options.output,
|
|
53
57
|
json: options.json,
|
|
58
|
+
...(isDebugEnabled(command) ? { debug: true } : {}),
|
|
54
59
|
...(options.limit !== undefined ? { limit: options.limit } : {}),
|
|
55
60
|
});
|
|
56
61
|
});
|
|
@@ -11,6 +11,16 @@ function tokenFromOption(value) {
|
|
|
11
11
|
function binPath() {
|
|
12
12
|
return fileURLToPath(new URL('../bin.js', import.meta.url));
|
|
13
13
|
}
|
|
14
|
+
function formatMcpStartResultMessage(input) {
|
|
15
|
+
return [
|
|
16
|
+
input.status === 'started' ? `KTX MCP daemon started: ${input.url}` : `KTX MCP daemon already running: ${input.url}`,
|
|
17
|
+
'',
|
|
18
|
+
'KTX is ready for configured agents.',
|
|
19
|
+
'Open your agent for this KTX project and ask a data question, for example:',
|
|
20
|
+
' "Use KTX to show me the available tables and metrics."',
|
|
21
|
+
'',
|
|
22
|
+
].join('\n');
|
|
23
|
+
}
|
|
14
24
|
export function registerMcpCommands(program, context) {
|
|
15
25
|
const mcp = program.command('mcp').description('Run the KTX MCP HTTP server');
|
|
16
26
|
mcp
|
|
@@ -66,9 +76,7 @@ export function registerMcpCommands(program, context) {
|
|
|
66
76
|
allowedOrigins: options.allowedOrigin,
|
|
67
77
|
binPath: binPath(),
|
|
68
78
|
});
|
|
69
|
-
context.io.stdout.write(result.status
|
|
70
|
-
? `KTX MCP daemon started: ${result.url}\n`
|
|
71
|
-
: `KTX MCP daemon already running: ${result.url}\n`);
|
|
79
|
+
context.io.stdout.write(formatMcpStartResultMessage({ status: result.status, url: result.url }));
|
|
72
80
|
});
|
|
73
81
|
mcp
|
|
74
82
|
.command('stop')
|
|
@@ -65,7 +65,36 @@ describe('registerMcpCommands', () => {
|
|
|
65
65
|
registerMcpCommands(program, context);
|
|
66
66
|
await program.parseAsync(['--project-dir', '/tmp/ktx-already', 'mcp', 'start'], { from: 'user' });
|
|
67
67
|
expect(startDaemon).toHaveBeenCalledTimes(1);
|
|
68
|
-
expect(context.io.stdout.write).toHaveBeenCalledWith(
|
|
68
|
+
expect(context.io.stdout.write).toHaveBeenCalledWith([
|
|
69
|
+
'KTX MCP daemon already running: http://127.0.0.1:7878/mcp',
|
|
70
|
+
'',
|
|
71
|
+
'KTX is ready for configured agents.',
|
|
72
|
+
'Open your agent for this KTX project and ask a data question, for example:',
|
|
73
|
+
' "Use KTX to show me the available tables and metrics."',
|
|
74
|
+
'',
|
|
75
|
+
].join('\n'));
|
|
76
|
+
});
|
|
77
|
+
it('prints a friendly next step after starting the daemon', async () => {
|
|
78
|
+
const program = new Command().exitOverride().option('--project-dir <path>');
|
|
79
|
+
const startDaemon = vi.fn().mockResolvedValue({
|
|
80
|
+
status: 'started',
|
|
81
|
+
url: 'http://127.0.0.1:7878/mcp',
|
|
82
|
+
state: {
|
|
83
|
+
schemaVersion: 1,
|
|
84
|
+
pid: 4242,
|
|
85
|
+
host: '127.0.0.1',
|
|
86
|
+
port: 7878,
|
|
87
|
+
tokenAuth: false,
|
|
88
|
+
projectDir: '/tmp/ktx-started',
|
|
89
|
+
startedAt: '2026-05-14T00:00:00.000Z',
|
|
90
|
+
logPath: '/tmp/ktx-started/.ktx/logs/mcp.log',
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
const context = makeContext({ deps: { mcp: { startDaemon } } });
|
|
94
|
+
registerMcpCommands(program, context);
|
|
95
|
+
await program.parseAsync(['--project-dir', '/tmp/ktx-started', 'mcp', 'start'], { from: 'user' });
|
|
96
|
+
expect(context.io.stdout.write).toHaveBeenCalledWith(expect.stringContaining('KTX MCP daemon started: http://127.0.0.1:7878/mcp\n\nKTX is ready for configured agents.'));
|
|
97
|
+
expect(context.io.stdout.write).toHaveBeenCalledWith(expect.stringContaining('"Use KTX to show me the available tables and metrics."'));
|
|
69
98
|
});
|
|
70
99
|
it('runs the stdio server with the resolved project directory', async () => {
|
|
71
100
|
const program = new Command().exitOverride().option('--project-dir <path>');
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { InvalidArgumentError, Option } from '@commander-js/extra-typings';
|
|
2
|
+
import { resolveCommandProjectDir } from '../cli-program.js';
|
|
3
|
+
import { profileMark } from '../startup-profile.js';
|
|
4
|
+
profileMark('module:commands/sql-commands');
|
|
5
|
+
const DEFAULT_MAX_ROWS = 1000;
|
|
6
|
+
const MAX_ROWS_CAP = 10_000;
|
|
7
|
+
function parseSqlMaxRowsOption(value) {
|
|
8
|
+
const parsed = Number(value);
|
|
9
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > MAX_ROWS_CAP) {
|
|
10
|
+
throw new InvalidArgumentError(`must be an integer between 1 and ${MAX_ROWS_CAP}`);
|
|
11
|
+
}
|
|
12
|
+
return parsed;
|
|
13
|
+
}
|
|
14
|
+
async function runSqlArgs(context, args) {
|
|
15
|
+
const runner = context.deps.sql ?? (await import('../sql.js')).runKtxSql;
|
|
16
|
+
context.setExitCode(await runner(args, context.io));
|
|
17
|
+
}
|
|
18
|
+
export function registerSqlCommands(program, context) {
|
|
19
|
+
program
|
|
20
|
+
.command('sql')
|
|
21
|
+
.description('Execute parser-validated read-only SQL against a configured connection')
|
|
22
|
+
.argument('<sql...>', 'SQL query to execute')
|
|
23
|
+
.requiredOption('-c, --connection <id>', 'KTX connection id')
|
|
24
|
+
.option('--max-rows <n>', 'Maximum rows to return', parseSqlMaxRowsOption, DEFAULT_MAX_ROWS)
|
|
25
|
+
.addOption(new Option('--output <mode>', 'Output mode: pretty (default), plain (TSV), or json').choices([
|
|
26
|
+
'pretty',
|
|
27
|
+
'plain',
|
|
28
|
+
'json',
|
|
29
|
+
]))
|
|
30
|
+
.option('--json', 'Shortcut for --output=json (overrides --output)', false)
|
|
31
|
+
.action(async (sqlParts, options, command) => {
|
|
32
|
+
await runSqlArgs(context, {
|
|
33
|
+
command: 'execute',
|
|
34
|
+
projectDir: resolveCommandProjectDir(command),
|
|
35
|
+
connectionId: options.connection,
|
|
36
|
+
sql: sqlParts.join(' '),
|
|
37
|
+
maxRows: options.maxRows,
|
|
38
|
+
output: options.output,
|
|
39
|
+
json: options.json === true,
|
|
40
|
+
cliVersion: context.packageInfo.version,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Command } from '@commander-js/extra-typings';
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { registerSqlCommands } from './sql-commands.js';
|
|
4
|
+
function makeContext(overrides = {}) {
|
|
5
|
+
let exitCode = 0;
|
|
6
|
+
return {
|
|
7
|
+
io: {
|
|
8
|
+
stdout: { write: vi.fn() },
|
|
9
|
+
stderr: { write: vi.fn() },
|
|
10
|
+
},
|
|
11
|
+
deps: {},
|
|
12
|
+
packageInfo: { name: '@ktx/cli', version: '0.0.0-test', contextPackageName: '@ktx/context' },
|
|
13
|
+
setExitCode: (code) => {
|
|
14
|
+
exitCode = code;
|
|
15
|
+
},
|
|
16
|
+
runInit: vi.fn(),
|
|
17
|
+
writeDebug: vi.fn(),
|
|
18
|
+
...overrides,
|
|
19
|
+
get exitCode() {
|
|
20
|
+
return exitCode;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
describe('registerSqlCommands', () => {
|
|
25
|
+
it('routes positional SQL through the sql runner', async () => {
|
|
26
|
+
const program = new Command().exitOverride().option('--project-dir <path>');
|
|
27
|
+
const sql = vi.fn(async () => 0);
|
|
28
|
+
const context = makeContext({ deps: { sql } });
|
|
29
|
+
registerSqlCommands(program, context);
|
|
30
|
+
await expect(program.parseAsync(['--project-dir', '/tmp/ktx-sql', 'sql', '--connection', 'warehouse', 'select', '1'], { from: 'user' })).resolves.toBe(program);
|
|
31
|
+
expect(sql).toHaveBeenCalledWith({
|
|
32
|
+
command: 'execute',
|
|
33
|
+
projectDir: '/tmp/ktx-sql',
|
|
34
|
+
connectionId: 'warehouse',
|
|
35
|
+
sql: 'select 1',
|
|
36
|
+
maxRows: 1000,
|
|
37
|
+
output: undefined,
|
|
38
|
+
json: false,
|
|
39
|
+
cliVersion: '0.0.0-test',
|
|
40
|
+
}, context.io);
|
|
41
|
+
});
|
|
42
|
+
it('supports the short connection flag', async () => {
|
|
43
|
+
const program = new Command().exitOverride().option('--project-dir <path>');
|
|
44
|
+
const sql = vi.fn(async () => 0);
|
|
45
|
+
const context = makeContext({ deps: { sql } });
|
|
46
|
+
registerSqlCommands(program, context);
|
|
47
|
+
await expect(program.parseAsync(['--project-dir', '/tmp/ktx-sql', 'sql', '-c', 'warehouse', 'select 1'], {
|
|
48
|
+
from: 'user',
|
|
49
|
+
})).resolves.toBe(program);
|
|
50
|
+
expect(sql).toHaveBeenCalledWith(expect.objectContaining({ connectionId: 'warehouse', sql: 'select 1' }), context.io);
|
|
51
|
+
});
|
|
52
|
+
it('rejects missing SQL before invoking the runner', async () => {
|
|
53
|
+
const program = new Command().exitOverride().option('--project-dir <path>');
|
|
54
|
+
const sql = vi.fn(async () => 0);
|
|
55
|
+
registerSqlCommands(program, makeContext({ deps: { sql } }));
|
|
56
|
+
await expect(program.parseAsync(['--project-dir', '/tmp/ktx-sql', 'sql', '--connection', 'warehouse'], {
|
|
57
|
+
from: 'user',
|
|
58
|
+
})).rejects.toThrow('missing required argument');
|
|
59
|
+
expect(sql).not.toHaveBeenCalled();
|
|
60
|
+
});
|
|
61
|
+
it('rejects maxRows above the CLI cap', async () => {
|
|
62
|
+
const program = new Command().exitOverride().option('--project-dir <path>');
|
|
63
|
+
const sql = vi.fn(async () => 0);
|
|
64
|
+
registerSqlCommands(program, makeContext({ deps: { sql } }));
|
|
65
|
+
await expect(program.parseAsync(['--project-dir', '/tmp/ktx-sql', 'sql', '--connection', 'warehouse', '--max-rows', '10001', 'select 1'], { from: 'user' })).rejects.toThrow('must be an integer between 1 and 10000');
|
|
66
|
+
expect(sql).not.toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -533,6 +533,9 @@ function failedStepDetail(result) {
|
|
|
533
533
|
}
|
|
534
534
|
const INTERNAL_FAILURE_LINE_RE = /^(Report|Run|Job|Status|Adapter|Connection|Sync|Mode|Dry run|Diff|Tasks|Work units|Failed tasks|Saved memory|Provenance rows):\s*/;
|
|
535
535
|
const ACTIONABLE_FAILURE_LINE_RE = /^(Missing bundled Python runtime manifest|KTX Python runtime is required|KTX managed daemon|Error:|Failed\b|Could not\b|Cannot\b)/;
|
|
536
|
+
function trimErrorPrefix(line) {
|
|
537
|
+
return line.replace(/^Error:\s*/, '');
|
|
538
|
+
}
|
|
536
539
|
function firstCapturedFailureLine(output) {
|
|
537
540
|
const lines = (output ?? '')
|
|
538
541
|
.split(/\r?\n/)
|
|
@@ -540,7 +543,8 @@ function firstCapturedFailureLine(output) {
|
|
|
540
543
|
.filter((candidate) => candidate.length > 0)
|
|
541
544
|
.filter((candidate) => !candidate.startsWith('KTX scan completed'))
|
|
542
545
|
.filter((candidate) => !INTERNAL_FAILURE_LINE_RE.test(candidate));
|
|
543
|
-
|
|
546
|
+
const line = lines.find((candidate) => ACTIONABLE_FAILURE_LINE_RE.test(candidate)) ?? lines.at(-1) ?? null;
|
|
547
|
+
return line ? trimErrorPrefix(line) : null;
|
|
544
548
|
}
|
|
545
549
|
function isGenericFailedAtDetail(target, detail) {
|
|
546
550
|
return new RegExp(`^${target.connectionId} failed at [a-z-]+\\.?(?: Retry: .*)?$`).test(detail ?? '');
|
package/dist/dev.test.js
CHANGED
|
@@ -88,6 +88,33 @@ describe('dev Commander tree', () => {
|
|
|
88
88
|
await rm(tempDir, { recursive: true, force: true });
|
|
89
89
|
}
|
|
90
90
|
});
|
|
91
|
+
it('prints config schema without requiring a KTX project directory', async () => {
|
|
92
|
+
const { mkdtemp, rm } = await import('node:fs/promises');
|
|
93
|
+
const { tmpdir } = await import('node:os');
|
|
94
|
+
const { join } = await import('node:path');
|
|
95
|
+
const tempDir = await mkdtemp(join(tmpdir(), 'ktx-dev-schema-'));
|
|
96
|
+
const missingProjectDir = join(tempDir, 'missing-project');
|
|
97
|
+
const originalProjectDir = process.env.KTX_PROJECT_DIR;
|
|
98
|
+
const testIo = makeIo();
|
|
99
|
+
try {
|
|
100
|
+
process.env.KTX_PROJECT_DIR = missingProjectDir;
|
|
101
|
+
await expect(runKtxCli(['dev', 'schema'], testIo.io)).resolves.toBe(0);
|
|
102
|
+
expect(JSON.parse(testIo.stdout())).toMatchObject({
|
|
103
|
+
title: 'ktx.yaml',
|
|
104
|
+
type: 'object',
|
|
105
|
+
});
|
|
106
|
+
expect(testIo.stderr()).toBe('');
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
if (originalProjectDir === undefined) {
|
|
110
|
+
delete process.env.KTX_PROJECT_DIR;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
process.env.KTX_PROJECT_DIR = originalProjectDir;
|
|
114
|
+
}
|
|
115
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
116
|
+
}
|
|
117
|
+
});
|
|
91
118
|
it('rejects removed dev command groups', async () => {
|
|
92
119
|
for (const argv of [
|
|
93
120
|
['dev', 'doctor', 'setup'],
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export { runKtxSetupEmbeddingsStep } from './setup-embeddings.js';
|
|
|
7
7
|
export type { KtxSetupSourcesArgs, KtxSetupSourcesDeps, KtxSetupSourcesPromptAdapter, KtxSetupSourcesResult, KtxSetupSourceType, } from './setup-sources.js';
|
|
8
8
|
export { runKtxSetupSourcesStep } from './setup-sources.js';
|
|
9
9
|
export { runKtxRuntime, type KtxRuntimeArgs, type KtxRuntimeDeps } from './runtime.js';
|
|
10
|
+
export { runKtxSql, type KtxSqlArgs, type KtxSqlDeps } from './sql.js';
|
|
10
11
|
export { allocateDaemonPort, readManagedPythonDaemonStatus, stopAllManagedPythonDaemons, startManagedPythonDaemon, stopManagedPythonDaemon, } from './managed-python-daemon.js';
|
|
11
12
|
export type { ManagedPythonDaemonProcessInfo, ManagedPythonDaemonStartResult, ManagedPythonDaemonState, ManagedPythonDaemonStatus, ManagedPythonDaemonStopAllEntry, ManagedPythonDaemonStopAllFailure, ManagedPythonDaemonStopAllResult, ManagedPythonDaemonStopResult, } from './managed-python-daemon.js';
|
|
12
13
|
export { ensureManagedLocalEmbeddingsDaemon, managedLocalEmbeddingHealthConfig, managedLocalEmbeddingProjectConfig, type ManagedLocalEmbeddingsDaemon, type ManagedLocalEmbeddingsOptions, } from './managed-local-embeddings.js';
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { runKtxSetupDatabasesStep } from './setup-databases.js';
|
|
|
5
5
|
export { runKtxSetupEmbeddingsStep } from './setup-embeddings.js';
|
|
6
6
|
export { runKtxSetupSourcesStep } from './setup-sources.js';
|
|
7
7
|
export { runKtxRuntime } from './runtime.js';
|
|
8
|
+
export { runKtxSql } from './sql.js';
|
|
8
9
|
export { allocateDaemonPort, readManagedPythonDaemonStatus, stopAllManagedPythonDaemons, startManagedPythonDaemon, stopManagedPythonDaemon, } from './managed-python-daemon.js';
|
|
9
10
|
export { ensureManagedLocalEmbeddingsDaemon, managedLocalEmbeddingHealthConfig, managedLocalEmbeddingProjectConfig, } from './managed-local-embeddings.js';
|
|
10
11
|
export { renderMemoryFlowTui, sanitizeMemoryFlowTuiError, startLiveMemoryFlowTui, } from './memory-flow-tui.js';
|