@kaelio/ktx 0.1.1 → 0.3.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.1-py3-none-any.whl → kaelio_ktx-0.3.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 +161 -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/{dev.test.js → admin.test.js} +36 -31
- package/dist/cli-program.js +7 -7
- package/dist/cli-program.test.js +1 -3
- package/dist/cli-project.d.ts +18 -0
- package/dist/cli-project.js +52 -0
- package/dist/cli-project.test.d.ts +1 -0
- package/dist/cli-project.test.js +149 -0
- package/dist/cli-runtime.d.ts +2 -2
- package/dist/cli-runtime.js +2 -8
- 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/runtime-commands.js +2 -2
- package/dist/commands/sl-commands.js +27 -32
- package/dist/context-build-view.js +1 -1
- package/dist/doctor.test.js +4 -4
- package/dist/example-smoke.test.js +3 -3
- package/dist/index.test.js +97 -85
- package/dist/ingest.js +9 -2
- package/dist/ingest.test.js +27 -3
- package/dist/io/print-list.test.js +4 -4
- package/dist/knowledge.js +1 -1
- package/dist/managed-local-embeddings.d.ts +0 -2
- package/dist/managed-local-embeddings.js +2 -5
- package/dist/managed-local-embeddings.test.js +5 -8
- package/dist/managed-python-command.js +2 -2
- package/dist/managed-python-command.test.js +3 -3
- package/dist/managed-python-daemon.js +2 -2
- package/dist/managed-python-daemon.test.js +1 -1
- package/dist/managed-python-http.js +3 -3
- package/dist/managed-python-http.test.js +6 -6
- package/dist/managed-python-runtime.d.ts +1 -1
- package/dist/managed-python-runtime.js +3 -3
- package/dist/managed-python-runtime.test.js +2 -2
- 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.js +0 -2
- package/dist/print-command-tree.test.js +1 -1
- package/dist/public-ingest.d.ts +4 -2
- package/dist/public-ingest.js +12 -8
- package/dist/public-ingest.test.js +7 -3
- package/dist/release-version.d.ts +1 -5
- package/dist/release-version.js +2 -39
- package/dist/runtime-requirements.js +1 -1
- package/dist/runtime.js +6 -6
- package/dist/runtime.test.js +8 -8
- package/dist/scan.js +7 -2
- package/dist/scan.test.js +3 -3
- package/dist/setup-agents.js +3 -3
- package/dist/setup-agents.test.js +1 -1
- package/dist/setup-embeddings.js +2 -2
- package/dist/setup-embeddings.test.js +5 -5
- package/dist/setup-runtime.test.js +3 -3
- package/dist/sl.js +1 -1
- package/dist/standalone-smoke.test.js +6 -2
- package/node_modules/@ktx/context/dist/core/git.service.d.ts +1 -0
- package/node_modules/@ktx/context/dist/core/git.service.js +12 -0
- 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/historic-sql.adapter.d.ts +2 -1
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/historic-sql.adapter.js +18 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/local-ingest-acceptance.test.js +6 -6
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.d.ts +5 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.js +48 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.test.js +83 -0
- package/node_modules/@ktx/context/dist/ingest/adapters/live-database/daemon-introspection.js +4 -1
- package/node_modules/@ktx/context/dist/ingest/adapters/live-database/daemon-introspection.test.js +32 -0
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.d.ts +22 -0
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.js +95 -0
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.test.d.ts +1 -0
- package/node_modules/@ktx/context/dist/ingest/finalization-scope.test.js +114 -0
- package/node_modules/@ktx/context/dist/ingest/index.d.ts +1 -2
- package/node_modules/@ktx/context/dist/ingest/index.js +0 -1
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.d.ts +2 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.isolated-diff.test.js +166 -0
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.js +235 -45
- package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.test.js +193 -38
- package/node_modules/@ktx/context/dist/ingest/local-bundle-ingest.test.js +22 -3
- package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.js +3 -4
- package/node_modules/@ktx/context/dist/ingest/local-ingest.js +0 -7
- package/node_modules/@ktx/context/dist/ingest/local-stage-ingest.js +15 -5
- package/node_modules/@ktx/context/dist/ingest/local-stage-ingest.test.js +29 -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 +1 -20
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.d.ts +73 -2
- package/node_modules/@ktx/context/dist/ingest/report-snapshot.js +27 -0
- package/node_modules/@ktx/context/dist/ingest/reports.d.ts +23 -5
- package/node_modules/@ktx/context/dist/ingest/reports.js +7 -24
- package/node_modules/@ktx/context/dist/ingest/types.d.ts +33 -0
- package/node_modules/@ktx/context/dist/llm/index.d.ts +1 -1
- package/node_modules/@ktx/context/dist/llm/index.js +1 -1
- package/node_modules/@ktx/context/dist/llm/local-config.d.ts +0 -1
- package/node_modules/@ktx/context/dist/llm/local-config.js +2 -12
- package/node_modules/@ktx/context/dist/llm/local-config.test.js +2 -23
- package/node_modules/@ktx/context/dist/memory/local-memory.js +9 -3
- package/node_modules/@ktx/context/dist/package-exports.test.js +2 -2
- package/node_modules/@ktx/context/dist/project/config.d.ts +16 -0
- package/node_modules/@ktx/context/dist/project/driver-schemas.d.ts +8 -0
- package/node_modules/@ktx/context/dist/project/driver-schemas.js +4 -0
- package/node_modules/@ktx/context/dist/scan/enabled-tables.d.ts +3 -0
- package/node_modules/@ktx/context/dist/scan/enabled-tables.js +15 -0
- package/node_modules/@ktx/context/dist/scan/local-scan.d.ts +2 -4
- package/node_modules/@ktx/context/dist/scan/local-scan.js +2 -15
- 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/package.json +1 -1
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.d.ts +0 -4
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.js +0 -38
- package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.test.js +0 -63
- /package/dist/{dev.test.d.ts → admin-reindex.test.d.ts} +0 -0
- /package/{node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.test.d.ts → dist/admin.test.d.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { MANAGED_SENTENCE_TRANSFORMERS_BASE_URL
|
|
2
|
+
import { MANAGED_SENTENCE_TRANSFORMERS_BASE_URL } from '@ktx/context';
|
|
3
3
|
import { ensureManagedLocalEmbeddingsDaemon, managedLocalEmbeddingHealthConfig, managedLocalEmbeddingProjectConfig, } from './managed-local-embeddings.js';
|
|
4
4
|
function makeIo() {
|
|
5
5
|
let stdout = '';
|
|
@@ -101,7 +101,7 @@ describe('managedLocalEmbeddingProjectConfig', () => {
|
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
describe('managedLocalEmbeddingHealthConfig', () => {
|
|
104
|
-
it('uses the active
|
|
104
|
+
it('uses the active KTX daemon URL for the immediate health check', () => {
|
|
105
105
|
expect(managedLocalEmbeddingHealthConfig({
|
|
106
106
|
baseUrl: 'http://127.0.0.1:61234',
|
|
107
107
|
model: 'all-MiniLM-L6-v2',
|
|
@@ -115,7 +115,7 @@ describe('managedLocalEmbeddingHealthConfig', () => {
|
|
|
115
115
|
});
|
|
116
116
|
});
|
|
117
117
|
describe('ensureManagedLocalEmbeddingsDaemon', () => {
|
|
118
|
-
it('ensures the local-embeddings feature and starts the
|
|
118
|
+
it('ensures the local-embeddings feature and starts the KTX daemon', async () => {
|
|
119
119
|
const io = makeIo();
|
|
120
120
|
const ensureRuntime = vi.fn(async () => runtime());
|
|
121
121
|
const startDaemon = vi.fn(async () => daemonResult('started'));
|
|
@@ -130,9 +130,6 @@ describe('ensureManagedLocalEmbeddingsDaemon', () => {
|
|
|
130
130
|
baseUrl: 'http://127.0.0.1:61234',
|
|
131
131
|
stdoutLog: '/work/proj/.ktx/runtime/daemon.stdout.log',
|
|
132
132
|
stderrLog: '/work/proj/.ktx/runtime/daemon.stderr.log',
|
|
133
|
-
env: {
|
|
134
|
-
[MANAGED_SENTENCE_TRANSFORMERS_BASE_URL_ENV]: 'http://127.0.0.1:61234',
|
|
135
|
-
},
|
|
136
133
|
});
|
|
137
134
|
expect(ensureRuntime).toHaveBeenCalledWith({
|
|
138
135
|
cliVersion: '0.2.0',
|
|
@@ -146,7 +143,7 @@ describe('ensureManagedLocalEmbeddingsDaemon', () => {
|
|
|
146
143
|
features: ['local-embeddings'],
|
|
147
144
|
force: false,
|
|
148
145
|
});
|
|
149
|
-
expect(io.stderr()).toContain('Started KTX
|
|
146
|
+
expect(io.stderr()).toContain('Started KTX daemon: http://127.0.0.1:61234');
|
|
150
147
|
});
|
|
151
148
|
it('reuses an already running daemon without reporting a new start', async () => {
|
|
152
149
|
const io = makeIo();
|
|
@@ -158,6 +155,6 @@ describe('ensureManagedLocalEmbeddingsDaemon', () => {
|
|
|
158
155
|
ensureRuntime: vi.fn(async () => runtime()),
|
|
159
156
|
startDaemon: vi.fn(async () => daemonResult('reused')),
|
|
160
157
|
});
|
|
161
|
-
expect(io.stderr()).toContain('Using KTX
|
|
158
|
+
expect(io.stderr()).toContain('Using KTX daemon: http://127.0.0.1:61234');
|
|
162
159
|
});
|
|
163
160
|
});
|
|
@@ -12,8 +12,8 @@ export function runtimeInstallPolicyFromFlags(options) {
|
|
|
12
12
|
}
|
|
13
13
|
export function managedRuntimeInstallCommand(feature) {
|
|
14
14
|
return feature === 'local-embeddings'
|
|
15
|
-
? 'ktx
|
|
16
|
-
: 'ktx
|
|
15
|
+
? 'ktx admin runtime install --feature local-embeddings --yes'
|
|
16
|
+
: 'ktx admin runtime install --yes';
|
|
17
17
|
}
|
|
18
18
|
function installPrompt(feature) {
|
|
19
19
|
const label = feature === 'local-embeddings' ? 'local embeddings Python runtime' : 'core Python runtime';
|
|
@@ -98,8 +98,8 @@ function makeSpinnerEvents() {
|
|
|
98
98
|
}
|
|
99
99
|
describe('managedRuntimeInstallCommand', () => {
|
|
100
100
|
it('prints the exact command for each managed runtime feature', () => {
|
|
101
|
-
expect(managedRuntimeInstallCommand('core')).toBe('ktx
|
|
102
|
-
expect(managedRuntimeInstallCommand('local-embeddings')).toBe('ktx
|
|
101
|
+
expect(managedRuntimeInstallCommand('core')).toBe('ktx admin runtime install --yes');
|
|
102
|
+
expect(managedRuntimeInstallCommand('local-embeddings')).toBe('ktx admin runtime install --feature local-embeddings --yes');
|
|
103
103
|
});
|
|
104
104
|
});
|
|
105
105
|
describe('runtimeInstallPolicyFromFlags', () => {
|
|
@@ -177,7 +177,7 @@ describe('createManagedPythonSemanticLayerComputePort', () => {
|
|
|
177
177
|
io: io.io,
|
|
178
178
|
readStatus: vi.fn(async () => missingStatus()),
|
|
179
179
|
installRuntime,
|
|
180
|
-
})).rejects.toThrow('KTX Python runtime is required for this command. Run: ktx
|
|
180
|
+
})).rejects.toThrow('KTX Python runtime is required for this command. Run: ktx admin runtime install --yes');
|
|
181
181
|
expect(installRuntime).not.toHaveBeenCalled();
|
|
182
182
|
});
|
|
183
183
|
it('installs the core runtime without prompting when policy is auto', async () => {
|
|
@@ -173,7 +173,7 @@ async function waitForHealth(input) {
|
|
|
173
173
|
return;
|
|
174
174
|
}
|
|
175
175
|
lastDetail = finalHealth.detail;
|
|
176
|
-
throw new Error(`KTX
|
|
176
|
+
throw new Error(`KTX daemon failed to start: ${lastDetail}. stderr: ${input.state.stderrLog}`);
|
|
177
177
|
}
|
|
178
178
|
async function removeState(layout) {
|
|
179
179
|
await rm(layout.daemonStatePath, { force: true });
|
|
@@ -491,7 +491,7 @@ export async function startManagedPythonDaemon(options) {
|
|
|
491
491
|
});
|
|
492
492
|
child.unref();
|
|
493
493
|
if (!child.pid) {
|
|
494
|
-
throw new Error(`KTX
|
|
494
|
+
throw new Error(`KTX daemon did not report a pid. stderr: ${layout.daemonStderrPath}`);
|
|
495
495
|
}
|
|
496
496
|
const state = {
|
|
497
497
|
schemaVersion: 1,
|
|
@@ -100,7 +100,7 @@ function daemonOptionsBase(root) {
|
|
|
100
100
|
runtimeRoot: join(root, 'runtime'),
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
-
describe('
|
|
103
|
+
describe('KTX daemon lifecycle', () => {
|
|
104
104
|
let tempDir;
|
|
105
105
|
beforeEach(async () => {
|
|
106
106
|
tempDir = await mkdtemp(join(tmpdir(), 'ktx-managed-daemon-'));
|
|
@@ -11,7 +11,7 @@ function normalizedBaseUrl(baseUrl) {
|
|
|
11
11
|
function parseJsonObject(raw, path) {
|
|
12
12
|
const parsed = JSON.parse(raw);
|
|
13
13
|
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
14
|
-
throw new Error(`KTX
|
|
14
|
+
throw new Error(`KTX daemon HTTP ${path} returned non-object JSON`);
|
|
15
15
|
}
|
|
16
16
|
return parsed;
|
|
17
17
|
}
|
|
@@ -34,7 +34,7 @@ export async function postManagedDaemonJson(baseUrl, path, payload) {
|
|
|
34
34
|
const text = Buffer.concat(chunks).toString('utf8');
|
|
35
35
|
const statusCode = response.statusCode ?? 0;
|
|
36
36
|
if (statusCode < 200 || statusCode >= 300) {
|
|
37
|
-
reject(new Error(`KTX
|
|
37
|
+
reject(new Error(`KTX daemon HTTP ${path} failed with ${statusCode}: ${text}`));
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
40
|
try {
|
|
@@ -70,7 +70,7 @@ export function createManagedPythonDaemonBaseUrlResolver(options) {
|
|
|
70
70
|
force: false,
|
|
71
71
|
});
|
|
72
72
|
const verb = daemon.status === 'started' ? 'Started' : 'Using existing';
|
|
73
|
-
options.io.stderr.write(`${verb} KTX
|
|
73
|
+
options.io.stderr.write(`${verb} KTX daemon: ${daemon.baseUrl}\n`);
|
|
74
74
|
cachedBaseUrl = daemon.baseUrl;
|
|
75
75
|
return cachedBaseUrl;
|
|
76
76
|
};
|
|
@@ -47,7 +47,7 @@ describe('createManagedPythonDaemonBaseUrlResolver', () => {
|
|
|
47
47
|
features: ['core'],
|
|
48
48
|
force: false,
|
|
49
49
|
});
|
|
50
|
-
expect(testIo.stderr()).toContain('Started KTX
|
|
50
|
+
expect(testIo.stderr()).toContain('Started KTX daemon: http://127.0.0.1:61234');
|
|
51
51
|
});
|
|
52
52
|
it('reports daemon reuse without reinstalling after the first resolved URL', async () => {
|
|
53
53
|
const testIo = io();
|
|
@@ -73,7 +73,7 @@ describe('createManagedPythonDaemonBaseUrlResolver', () => {
|
|
|
73
73
|
await expect(resolveBaseUrl()).resolves.toBe('http://127.0.0.1:61234');
|
|
74
74
|
expect(ensureRuntime).toHaveBeenCalledTimes(1);
|
|
75
75
|
expect(startDaemon).toHaveBeenCalledTimes(1);
|
|
76
|
-
expect(testIo.stderr()).toContain('Using existing KTX
|
|
76
|
+
expect(testIo.stderr()).toContain('Using existing KTX daemon: http://127.0.0.1:61234');
|
|
77
77
|
});
|
|
78
78
|
});
|
|
79
79
|
describe('createManagedDaemonHttpJsonRunner', () => {
|
|
@@ -87,8 +87,8 @@ describe('createManagedDaemonHttpJsonRunner', () => {
|
|
|
87
87
|
expect(postJson).toHaveBeenCalledWith('http://127.0.0.1:61234', '/sql/parse-table-identifier', { items: [] });
|
|
88
88
|
});
|
|
89
89
|
});
|
|
90
|
-
describe('
|
|
91
|
-
it('creates a Looker table parser backed by the
|
|
90
|
+
describe('KTX daemon ingest ports', () => {
|
|
91
|
+
it('creates a Looker table parser backed by the KTX daemon runner', async () => {
|
|
92
92
|
const requestJson = vi.fn(async () => ({
|
|
93
93
|
results: {
|
|
94
94
|
'model.explore': {
|
|
@@ -114,7 +114,7 @@ describe('managed daemon ingest ports', () => {
|
|
|
114
114
|
items: [{ key: 'model.explore', sql_table_name: 'public.orders', dialect: 'postgres' }],
|
|
115
115
|
});
|
|
116
116
|
});
|
|
117
|
-
it('creates a SQL analysis port backed by the
|
|
117
|
+
it('creates a SQL analysis port backed by the KTX daemon runner', async () => {
|
|
118
118
|
const requestJson = vi.fn(async () => ({
|
|
119
119
|
fingerprint: 'select-orders',
|
|
120
120
|
normalized_sql: 'SELECT * FROM public.orders WHERE id = ?',
|
|
@@ -134,7 +134,7 @@ describe('managed daemon ingest ports', () => {
|
|
|
134
134
|
dialect: 'postgres',
|
|
135
135
|
});
|
|
136
136
|
});
|
|
137
|
-
it('routes SQL batch analysis through the
|
|
137
|
+
it('routes SQL batch analysis through the KTX daemon runner', async () => {
|
|
138
138
|
const requestJson = vi.fn(async () => ({
|
|
139
139
|
results: {
|
|
140
140
|
orders: {
|
|
@@ -112,7 +112,7 @@ export interface ManagedPythonRuntimeDoctorCheck {
|
|
|
112
112
|
detail: string;
|
|
113
113
|
fix?: string;
|
|
114
114
|
}
|
|
115
|
-
export declare const MISSING_UV_RUNTIME_INSTALL_MESSAGE = "uv is required to install the KTX Python runtime. KTX does not download uv automatically. Install uv, make sure it is on PATH, and retry: ktx
|
|
115
|
+
export declare const MISSING_UV_RUNTIME_INSTALL_MESSAGE = "uv is required to install the KTX Python runtime. KTX does not download uv automatically. Install uv, make sure it is on PATH, and retry: ktx admin runtime install --yes";
|
|
116
116
|
export declare function managedPythonRuntimeLayout(options: ManagedPythonRuntimeLayoutOptions): ManagedPythonRuntimeLayout;
|
|
117
117
|
export declare function managedPythonDaemonLayout(options: ManagedPythonDaemonLayoutOptions): ManagedPythonDaemonLayout;
|
|
118
118
|
export declare function verifyRuntimeAsset(input: {
|
|
@@ -32,7 +32,7 @@ const installedRuntimeManifestSchema = z.object({
|
|
|
32
32
|
}),
|
|
33
33
|
installLog: z.string().min(1),
|
|
34
34
|
});
|
|
35
|
-
export const MISSING_UV_RUNTIME_INSTALL_MESSAGE = 'uv is required to install the KTX Python runtime. KTX does not download uv automatically. Install uv, make sure it is on PATH, and retry: ktx
|
|
35
|
+
export const MISSING_UV_RUNTIME_INSTALL_MESSAGE = 'uv is required to install the KTX Python runtime. KTX does not download uv automatically. Install uv, make sure it is on PATH, and retry: ktx admin runtime install --yes';
|
|
36
36
|
function defaultAssetDir() {
|
|
37
37
|
return fileURLToPath(new URL('../assets/python/', import.meta.url));
|
|
38
38
|
}
|
|
@@ -331,7 +331,7 @@ export async function doctorManagedPythonRuntime(options) {
|
|
|
331
331
|
id: 'uv',
|
|
332
332
|
label: 'uv',
|
|
333
333
|
detail: error instanceof Error ? error.message : String(error),
|
|
334
|
-
fix: 'Install uv, make sure it is on PATH, and run: ktx
|
|
334
|
+
fix: 'Install uv, make sure it is on PATH, and run: ktx admin runtime install --yes',
|
|
335
335
|
}));
|
|
336
336
|
}
|
|
337
337
|
try {
|
|
@@ -351,7 +351,7 @@ export async function doctorManagedPythonRuntime(options) {
|
|
|
351
351
|
id: 'runtime',
|
|
352
352
|
label: 'Managed Python runtime',
|
|
353
353
|
detail: status.detail,
|
|
354
|
-
...(status.kind === 'ready' ? {} : { fix: 'Run: ktx
|
|
354
|
+
...(status.kind === 'ready' ? {} : { fix: 'Run: ktx admin runtime install --yes' }),
|
|
355
355
|
}));
|
|
356
356
|
return checks;
|
|
357
357
|
}
|
|
@@ -402,7 +402,7 @@ describe('doctorManagedPythonRuntime', () => {
|
|
|
402
402
|
['asset', 'pass'],
|
|
403
403
|
['runtime', 'fail'],
|
|
404
404
|
]);
|
|
405
|
-
expect(checks[2]?.fix).toBe('Run: ktx
|
|
405
|
+
expect(checks[2]?.fix).toBe('Run: ktx admin runtime install --yes');
|
|
406
406
|
});
|
|
407
407
|
it('reports uv as a hard prerequisite when uv is missing', async () => {
|
|
408
408
|
const { assetDir } = await writeAsset(tempDir, { label: 'core-wheel' });
|
|
@@ -420,7 +420,7 @@ describe('doctorManagedPythonRuntime', () => {
|
|
|
420
420
|
label: 'uv',
|
|
421
421
|
status: 'fail',
|
|
422
422
|
detail: MISSING_UV_RUNTIME_INSTALL_MESSAGE,
|
|
423
|
-
fix: 'Install uv, make sure it is on PATH, and run: ktx
|
|
423
|
+
fix: 'Install uv, make sure it is on PATH, and run: ktx admin runtime install --yes',
|
|
424
424
|
});
|
|
425
425
|
});
|
|
426
426
|
});
|
|
@@ -145,8 +145,8 @@ describe('MemoryFlowTuiApp', () => {
|
|
|
145
145
|
expect(frame).toContain('order lifecycle');
|
|
146
146
|
expect(frame).toContain('customer metrics');
|
|
147
147
|
expect(frame).toContain('KTX finished ingesting your data');
|
|
148
|
-
expect(frame).toContain('ktx sl
|
|
149
|
-
expect(frame).toContain('ktx wiki
|
|
148
|
+
expect(frame).toContain('ktx sl');
|
|
149
|
+
expect(frame).toContain('ktx wiki');
|
|
150
150
|
expect(frame).not.toContain('ktx serve --mcp stdio --user-id local');
|
|
151
151
|
expect(frame).not.toContain(['ktx', 'ask'].join(' '));
|
|
152
152
|
expect(frame).not.toContain(['ktx', 'mcp'].join(' '));
|
package/dist/next-steps.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const KTX_CONTEXT_BUILD_COMMANDS: readonly [{
|
|
2
|
-
readonly command: "ktx ingest
|
|
3
|
-
readonly description: "Build or refresh agent-ready context from configured connections";
|
|
2
|
+
readonly command: "ktx ingest";
|
|
3
|
+
readonly description: "Build or refresh agent-ready context from all configured connections";
|
|
4
4
|
}, {
|
|
5
5
|
readonly command: "ktx status";
|
|
6
6
|
readonly description: "Check setup and context readiness";
|
|
@@ -9,20 +9,20 @@ export declare const KTX_NEXT_STEP_DIRECT_COMMANDS: readonly [{
|
|
|
9
9
|
readonly command: "ktx status --json";
|
|
10
10
|
readonly description: "Verify project setup and context readiness";
|
|
11
11
|
}, {
|
|
12
|
-
readonly command: "ktx sl
|
|
12
|
+
readonly command: "ktx sl";
|
|
13
13
|
readonly description: "Inspect generated semantic-layer sources";
|
|
14
14
|
}, {
|
|
15
|
-
readonly command: "ktx wiki
|
|
15
|
+
readonly command: "ktx wiki";
|
|
16
16
|
readonly description: "Inspect generated wiki pages";
|
|
17
17
|
}];
|
|
18
18
|
export declare const KTX_NEXT_STEP_COMMANDS: readonly [{
|
|
19
19
|
readonly command: "ktx status --json";
|
|
20
20
|
readonly description: "Verify project setup and context readiness";
|
|
21
21
|
}, {
|
|
22
|
-
readonly command: "ktx sl
|
|
22
|
+
readonly command: "ktx sl";
|
|
23
23
|
readonly description: "Inspect generated semantic-layer sources";
|
|
24
24
|
}, {
|
|
25
|
-
readonly command: "ktx wiki
|
|
25
|
+
readonly command: "ktx wiki";
|
|
26
26
|
readonly description: "Inspect generated wiki pages";
|
|
27
27
|
}];
|
|
28
28
|
export declare const KTX_NEXT_STEP_COMMAND_WIDTH: number;
|
package/dist/next-steps.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const KTX_CONTEXT_BUILD_COMMANDS = [
|
|
2
2
|
{
|
|
3
|
-
command: 'ktx ingest
|
|
4
|
-
description: 'Build or refresh agent-ready context from configured connections',
|
|
3
|
+
command: 'ktx ingest',
|
|
4
|
+
description: 'Build or refresh agent-ready context from all configured connections',
|
|
5
5
|
},
|
|
6
6
|
{
|
|
7
7
|
command: 'ktx status',
|
|
@@ -14,11 +14,11 @@ export const KTX_NEXT_STEP_DIRECT_COMMANDS = [
|
|
|
14
14
|
description: 'Verify project setup and context readiness',
|
|
15
15
|
},
|
|
16
16
|
{
|
|
17
|
-
command: 'ktx sl
|
|
17
|
+
command: 'ktx sl',
|
|
18
18
|
description: 'Inspect generated semantic-layer sources',
|
|
19
19
|
},
|
|
20
20
|
{
|
|
21
|
-
command: 'ktx wiki
|
|
21
|
+
command: 'ktx wiki',
|
|
22
22
|
description: 'Inspect generated wiki pages',
|
|
23
23
|
},
|
|
24
24
|
];
|
package/dist/next-steps.test.js
CHANGED
|
@@ -4,8 +4,8 @@ describe('KTX demo next steps', () => {
|
|
|
4
4
|
it('uses supported context-build commands before agent usage', () => {
|
|
5
5
|
expect(KTX_CONTEXT_BUILD_COMMANDS).toEqual([
|
|
6
6
|
{
|
|
7
|
-
command: 'ktx ingest
|
|
8
|
-
description: 'Build or refresh agent-ready context from configured connections',
|
|
7
|
+
command: 'ktx ingest',
|
|
8
|
+
description: 'Build or refresh agent-ready context from all configured connections',
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
command: 'ktx status',
|
|
@@ -20,11 +20,11 @@ describe('KTX demo next steps', () => {
|
|
|
20
20
|
description: 'Verify project setup and context readiness',
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
|
-
command: 'ktx sl
|
|
23
|
+
command: 'ktx sl',
|
|
24
24
|
description: 'Inspect generated semantic-layer sources',
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
|
-
command: 'ktx wiki
|
|
27
|
+
command: 'ktx wiki',
|
|
28
28
|
description: 'Inspect generated wiki pages',
|
|
29
29
|
},
|
|
30
30
|
]);
|
|
@@ -54,7 +54,7 @@ describe('KTX demo next steps', () => {
|
|
|
54
54
|
}).join('\n');
|
|
55
55
|
expect(rendered).toContain('Build KTX context next.');
|
|
56
56
|
expect(rendered).toContain('Run ingest to build database schema context before context-source ingest.');
|
|
57
|
-
expect(rendered).toContain('ktx ingest
|
|
57
|
+
expect(rendered).toContain('ktx ingest');
|
|
58
58
|
expect(rendered).not.toContain('resume');
|
|
59
59
|
expect(rendered).not.toContain('scan');
|
|
60
60
|
expect(rendered).toContain('ktx status');
|
|
@@ -8,7 +8,7 @@ describe('renderKtxCommandTree', () => {
|
|
|
8
8
|
const topLevel = lines
|
|
9
9
|
.filter((line) => /^ {2}[├└]── \S/.test(line))
|
|
10
10
|
.map((line) => line.replace(/^ {2}[├└]── /, '').trim().split(' ')[0]);
|
|
11
|
-
for (const expected of ['setup', 'connection', 'ingest', 'sl', 'mcp', '
|
|
11
|
+
for (const expected of ['setup', 'connection', 'ingest', 'sl', 'mcp', 'admin']) {
|
|
12
12
|
expect(topLevel).toContain(expected);
|
|
13
13
|
}
|
|
14
14
|
expect(output).toContain('│ └── test [connectionId]');
|
package/dist/public-ingest.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type KtxLocalProject
|
|
1
|
+
import { type KtxLocalProject } from '@ktx/context/project';
|
|
2
2
|
import type { KtxProgressPort } from '@ktx/context/scan';
|
|
3
3
|
import type { KtxCliIo } from './index.js';
|
|
4
4
|
import type { KtxIngestArgs, KtxIngestDeps, KtxIngestProgressUpdate } from './ingest.js';
|
|
@@ -68,7 +68,9 @@ export interface KtxPublicIngestTargetResult {
|
|
|
68
68
|
export type KtxPublicIngestProject = Pick<KtxLocalProject, 'projectDir' | 'config'>;
|
|
69
69
|
type KtxPublicIngestPhaseKey = 'database-schema' | 'query-history' | 'source-ingest';
|
|
70
70
|
export interface KtxPublicIngestDeps {
|
|
71
|
-
loadProject?: (options:
|
|
71
|
+
loadProject?: (options: {
|
|
72
|
+
projectDir: string;
|
|
73
|
+
}) => Promise<KtxPublicIngestProject>;
|
|
72
74
|
runScan?: (args: KtxScanArgs, io: KtxCliIo, deps?: KtxScanDeps) => Promise<number>;
|
|
73
75
|
runIngest?: (args: KtxIngestArgs, io: KtxCliIo, deps?: KtxIngestDeps) => Promise<number>;
|
|
74
76
|
runContextBuild?: (project: KtxPublicIngestProject, args: KtxPublicContextBuildArgs, io: KtxCliIo) => Promise<{
|
package/dist/public-ingest.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { loadKtxCliProject } from './cli-project.js';
|
|
2
2
|
import { databaseContextDepth, deepReadinessGaps, isDatabaseDriver, normalizeConnectionDriver, } from './ingest-depth.js';
|
|
3
3
|
import { ensureManagedPythonCommandRuntime, } from './managed-python-command.js';
|
|
4
4
|
import { publicIngestOutputLine } from './public-ingest-copy.js';
|
|
@@ -234,12 +234,10 @@ function targetForConnection(connectionId, connection, projectConfig, args, warn
|
|
|
234
234
|
throw new Error(`Connection "${connectionId}" uses unsupported public ingest driver "${driver || 'unknown'}"`);
|
|
235
235
|
}
|
|
236
236
|
export function buildPublicIngestPlan(project, args) {
|
|
237
|
-
|
|
238
|
-
throw new Error('Context build requires a connection id or all targets');
|
|
239
|
-
}
|
|
237
|
+
const allConnections = args.all || !args.targetConnectionId;
|
|
240
238
|
const entries = Object.entries(project.config.connections).sort(([a], [b]) => a.localeCompare(b));
|
|
241
|
-
const selected =
|
|
242
|
-
if (!
|
|
239
|
+
const selected = allConnections ? entries : entries.filter(([connectionId]) => connectionId === args.targetConnectionId);
|
|
240
|
+
if (!allConnections && selected.length === 0) {
|
|
243
241
|
throw new Error(`Connection "${args.targetConnectionId}" is not configured in ktx.yaml`);
|
|
244
242
|
}
|
|
245
243
|
if (selected.length === 0) {
|
|
@@ -393,7 +391,7 @@ function createCapturedPublicIngestIo() {
|
|
|
393
391
|
};
|
|
394
392
|
}
|
|
395
393
|
const INTERNAL_STATUS_LINE_RE = /^(Report|Run|Job|Status|Adapter|Connection|Sync|Diff|Tasks|Work units|Failed tasks|Saved memory|Provenance rows):\s*/;
|
|
396
|
-
const ACTIONABLE_FAILURE_LINE_RE = /^(Missing bundled Python runtime manifest|KTX Python runtime is required|KTX
|
|
394
|
+
const ACTIONABLE_FAILURE_LINE_RE = /^(Missing bundled Python runtime manifest|KTX Python runtime is required|KTX daemon HTTP|Error:|Failed\b|Could not\b|Cannot\b)/;
|
|
397
395
|
const RUNTIME_BACKED_RETRY_LINE_RE = /^Then retry the runtime-backed KTX command\.?$/;
|
|
398
396
|
function trimErrorPrefix(line) {
|
|
399
397
|
return line.replace(/^Error:\s*/, '');
|
|
@@ -538,7 +536,13 @@ export async function executePublicIngestTarget(target, args, io, deps) {
|
|
|
538
536
|
return markTargetResult(target, args, exitCode === 0 ? 'done' : 'failed', 'source-ingest', capturedIngestIo ? capturedFailureMessage(capturedIngestIo.capturedOutput()) : undefined);
|
|
539
537
|
}
|
|
540
538
|
export async function runKtxPublicIngest(args, io, deps = {}) {
|
|
541
|
-
const loadProject = deps.loadProject ??
|
|
539
|
+
const loadProject = deps.loadProject ??
|
|
540
|
+
((options) => loadKtxCliProject({
|
|
541
|
+
projectDir: options.projectDir,
|
|
542
|
+
cliVersion: args.cliVersion ?? '0.0.0-private',
|
|
543
|
+
installPolicy: args.runtimeInstallPolicy ?? 'never',
|
|
544
|
+
io,
|
|
545
|
+
}));
|
|
542
546
|
const project = await loadProject({ projectDir: args.projectDir });
|
|
543
547
|
if (shouldUseForegroundContextBuildView(args, io)) {
|
|
544
548
|
const plan = buildPublicIngestPlan(project, args);
|
|
@@ -109,9 +109,13 @@ describe('buildPublicIngestPlan', () => {
|
|
|
109
109
|
warnings: [],
|
|
110
110
|
});
|
|
111
111
|
});
|
|
112
|
-
it('
|
|
113
|
-
const project = projectWithConnections({
|
|
114
|
-
|
|
112
|
+
it('treats a bare invocation (no connection id, no --all) as all configured connections', () => {
|
|
113
|
+
const project = projectWithConnections({
|
|
114
|
+
warehouse: { driver: 'postgres' },
|
|
115
|
+
docs: { driver: 'notion' },
|
|
116
|
+
});
|
|
117
|
+
const plan = buildPublicIngestPlan(project, { projectDir: '/tmp/project', all: false });
|
|
118
|
+
expect(plan.targets.map((target) => target.connectionId).sort()).toEqual(['docs', 'warehouse']);
|
|
115
119
|
});
|
|
116
120
|
it('resolves database depth from flags, stored context, and defaults', () => {
|
|
117
121
|
const project = projectWithConnections({
|
package/dist/release-version.js
CHANGED
|
@@ -1,44 +1,7 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { dirname, join, parse } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
1
|
const semverPattern = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
5
|
-
function
|
|
6
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
7
|
-
}
|
|
8
|
-
function assertReleaseVersion(value, source) {
|
|
2
|
+
export function assertCliVersion(value, source) {
|
|
9
3
|
if (typeof value !== 'string' || !semverPattern.test(value)) {
|
|
10
|
-
throw new Error(`Invalid KTX
|
|
4
|
+
throw new Error(`Invalid KTX CLI version in ${source}`);
|
|
11
5
|
}
|
|
12
6
|
return value;
|
|
13
7
|
}
|
|
14
|
-
function findReleasePolicyPath(startDir) {
|
|
15
|
-
let current = startDir;
|
|
16
|
-
const root = parse(current).root;
|
|
17
|
-
while (true) {
|
|
18
|
-
const candidate = join(current, 'release-policy.json');
|
|
19
|
-
if (existsSync(candidate)) {
|
|
20
|
-
return candidate;
|
|
21
|
-
}
|
|
22
|
-
if (current === root) {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
current = dirname(current);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function readSourceReleaseVersion(startDir = dirname(fileURLToPath(import.meta.url))) {
|
|
29
|
-
const policyPath = findReleasePolicyPath(startDir);
|
|
30
|
-
if (!policyPath) {
|
|
31
|
-
return undefined;
|
|
32
|
-
}
|
|
33
|
-
const policy = JSON.parse(readFileSync(policyPath, 'utf8'));
|
|
34
|
-
if (!isPlainObject(policy)) {
|
|
35
|
-
throw new Error(`Invalid KTX release policy: ${policyPath}`);
|
|
36
|
-
}
|
|
37
|
-
return assertReleaseVersion(policy.publicNpmPackageVersion, policyPath);
|
|
38
|
-
}
|
|
39
|
-
export function resolveKtxRuntimeVersion(input) {
|
|
40
|
-
if (input.packageName === '@kaelio/ktx') {
|
|
41
|
-
return assertReleaseVersion(input.packageVersion, `${input.packageName}/package.json`);
|
|
42
|
-
}
|
|
43
|
-
return readSourceReleaseVersion(input.startDir) ?? input.packageVersion;
|
|
44
|
-
}
|
|
@@ -45,7 +45,7 @@ export function resolveProjectRuntimeRequirements(config, options = {}) {
|
|
|
45
45
|
requirements.push({
|
|
46
46
|
feature: 'core',
|
|
47
47
|
reason: 'database-introspection',
|
|
48
|
-
detail: 'Database introspection fallback uses the
|
|
48
|
+
detail: 'Database introspection fallback uses the KTX daemon.',
|
|
49
49
|
});
|
|
50
50
|
}
|
|
51
51
|
for (const [connectionId, connection] of Object.entries(config.connections)) {
|
package/dist/runtime.js
CHANGED
|
@@ -15,7 +15,7 @@ function writeInstallResult(io, result) {
|
|
|
15
15
|
}
|
|
16
16
|
function writeDaemonStart(io, result) {
|
|
17
17
|
const verb = result.status === 'reused' ? 'Using existing' : 'Started';
|
|
18
|
-
io.stdout.write(`${verb} KTX
|
|
18
|
+
io.stdout.write(`${verb} KTX daemon\n`);
|
|
19
19
|
io.stdout.write(`url: ${result.baseUrl}\n`);
|
|
20
20
|
io.stdout.write(`pid: ${result.state.pid}\n`);
|
|
21
21
|
io.stdout.write(`version: ${result.state.version}\n`);
|
|
@@ -26,10 +26,10 @@ function writeDaemonStart(io, result) {
|
|
|
26
26
|
}
|
|
27
27
|
function writeDaemonStop(io, result) {
|
|
28
28
|
if (result.status === 'already-stopped') {
|
|
29
|
-
io.stdout.write('KTX
|
|
29
|
+
io.stdout.write('KTX daemon already stopped\n');
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
|
-
io.stdout.write('Stopped KTX
|
|
32
|
+
io.stdout.write('Stopped KTX daemon\n');
|
|
33
33
|
io.stdout.write(`pid: ${result.state?.pid ?? 'unknown'}\n`);
|
|
34
34
|
io.stdout.write(`state: ${result.layout.daemonStatePath}\n`);
|
|
35
35
|
}
|
|
@@ -42,11 +42,11 @@ function writeDaemonStopAll(io, result) {
|
|
|
42
42
|
result.stale.length === 0 &&
|
|
43
43
|
result.failed.length === 0 &&
|
|
44
44
|
result.scanErrors.length === 0) {
|
|
45
|
-
io.stdout.write('No KTX
|
|
45
|
+
io.stdout.write('No KTX daemons found\n');
|
|
46
46
|
return 0;
|
|
47
47
|
}
|
|
48
48
|
if (failed === 0) {
|
|
49
|
-
io.stdout.write(`Stopped ${result.stopped.length} KTX
|
|
49
|
+
io.stdout.write(`Stopped ${result.stopped.length} KTX daemons\n`);
|
|
50
50
|
if (result.stale.length > 0) {
|
|
51
51
|
io.stdout.write(`Cleaned ${result.stale.length} stale daemon states\n`);
|
|
52
52
|
}
|
|
@@ -58,7 +58,7 @@ function writeDaemonStopAll(io, result) {
|
|
|
58
58
|
}
|
|
59
59
|
return 0;
|
|
60
60
|
}
|
|
61
|
-
io.stderr.write(`Stopped ${result.stopped.length} KTX
|
|
61
|
+
io.stderr.write(`Stopped ${result.stopped.length} KTX daemons; failed ${result.failed.length}${result.stale.length > 0 ? `; cleaned stale ${result.stale.length}` : ''}\n`);
|
|
62
62
|
for (const entry of result.failed) {
|
|
63
63
|
io.stderr.write(`pid: ${entry.pid} source: ${entry.source}${entry.url ? ` url: ${entry.url}` : ''}${entry.health ? ` health: ${entry.health}` : ''} detail: ${entry.detail}\n`);
|
|
64
64
|
}
|
package/dist/runtime.test.js
CHANGED
|
@@ -88,7 +88,7 @@ describe('runKtxRuntime', () => {
|
|
|
88
88
|
expect(io.stdout()).toContain('manifest: /runtime/0.2.0/manifest.json');
|
|
89
89
|
expect(io.stderr()).toBe('');
|
|
90
90
|
});
|
|
91
|
-
it('starts the
|
|
91
|
+
it('starts the KTX daemon and prints the base URL', async () => {
|
|
92
92
|
const io = makeIo();
|
|
93
93
|
const deps = {
|
|
94
94
|
startDaemon: vi.fn(async () => ({
|
|
@@ -131,13 +131,13 @@ describe('runKtxRuntime', () => {
|
|
|
131
131
|
features: ['local-embeddings'],
|
|
132
132
|
force: true,
|
|
133
133
|
});
|
|
134
|
-
expect(io.stdout()).toContain('Started KTX
|
|
134
|
+
expect(io.stdout()).toContain('Started KTX daemon');
|
|
135
135
|
expect(io.stdout()).toContain('url: http://127.0.0.1:61234');
|
|
136
136
|
expect(io.stdout()).toContain('pid: 4242');
|
|
137
137
|
expect(io.stdout()).toContain('features: core, local-embeddings');
|
|
138
138
|
expect(io.stdout()).toContain('stderr: /work/proj/.ktx/runtime/daemon.stderr.log');
|
|
139
139
|
});
|
|
140
|
-
it('stops the
|
|
140
|
+
it('stops the KTX daemon', async () => {
|
|
141
141
|
const io = makeIo();
|
|
142
142
|
const deps = {
|
|
143
143
|
stopDaemon: vi.fn(async () => ({
|
|
@@ -174,10 +174,10 @@ describe('runKtxRuntime', () => {
|
|
|
174
174
|
};
|
|
175
175
|
await expect(runKtxRuntime({ command: 'stop', cliVersion: '0.2.0', projectDir: '/work/proj', all: false }, io.io, deps)).resolves.toBe(0);
|
|
176
176
|
expect(deps.stopDaemon).toHaveBeenCalledWith({ cliVersion: '0.2.0', projectDir: '/work/proj' });
|
|
177
|
-
expect(io.stdout()).toContain('Stopped KTX
|
|
177
|
+
expect(io.stdout()).toContain('Stopped KTX daemon');
|
|
178
178
|
expect(io.stdout()).toContain('pid: 4242');
|
|
179
179
|
});
|
|
180
|
-
it('stops all discovered
|
|
180
|
+
it('stops all discovered KTX daemons and reports the summary', async () => {
|
|
181
181
|
const io = makeIo();
|
|
182
182
|
const deps = {
|
|
183
183
|
stopAllDaemons: vi.fn(async () => ({
|
|
@@ -192,7 +192,7 @@ describe('runKtxRuntime', () => {
|
|
|
192
192
|
};
|
|
193
193
|
await expect(runKtxRuntime({ command: 'stop', cliVersion: '0.2.0', projectDir: '/work/proj', all: true }, io.io, deps)).resolves.toBe(0);
|
|
194
194
|
expect(deps.stopAllDaemons).toHaveBeenCalledWith({ cliVersion: '0.2.0', projectDir: '/work/proj' });
|
|
195
|
-
expect(io.stdout()).toContain('Stopped 2 KTX
|
|
195
|
+
expect(io.stdout()).toContain('Stopped 2 KTX daemons');
|
|
196
196
|
expect(io.stdout()).toContain('pid: 4242 source: state url: http://127.0.0.1:61234');
|
|
197
197
|
expect(io.stdout()).toContain('pid: 5252 source: process url: http://127.0.0.1:8765');
|
|
198
198
|
});
|
|
@@ -215,7 +215,7 @@ describe('runKtxRuntime', () => {
|
|
|
215
215
|
})),
|
|
216
216
|
};
|
|
217
217
|
await expect(runKtxRuntime({ command: 'stop', cliVersion: '0.2.0', projectDir: '/work/proj', all: true }, io.io, deps)).resolves.toBe(1);
|
|
218
|
-
expect(io.stderr()).toContain('Stopped 0 KTX
|
|
218
|
+
expect(io.stderr()).toContain('Stopped 0 KTX daemons; failed 1');
|
|
219
219
|
expect(io.stderr()).toContain('pid: 4242 source: state url: http://127.0.0.1:61234');
|
|
220
220
|
expect(io.stderr()).toContain('process scan: ps failed');
|
|
221
221
|
});
|
|
@@ -246,7 +246,7 @@ describe('runKtxRuntime', () => {
|
|
|
246
246
|
label: 'Managed Python runtime',
|
|
247
247
|
status: 'fail',
|
|
248
248
|
detail: 'No runtime manifest at /runtime/0.2.0/manifest.json',
|
|
249
|
-
fix: 'Run: ktx
|
|
249
|
+
fix: 'Run: ktx admin runtime install --yes',
|
|
250
250
|
},
|
|
251
251
|
]),
|
|
252
252
|
};
|