@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.
Files changed (146) hide show
  1. package/assets/python/{kaelio_ktx-0.1.1-py3-none-any.whl → kaelio_ktx-0.3.0-py3-none-any.whl} +0 -0
  2. package/assets/python/manifest.json +4 -4
  3. package/dist/admin-reindex.d.ts +15 -0
  4. package/dist/admin-reindex.js +161 -0
  5. package/dist/admin-reindex.test.js +116 -0
  6. package/dist/{dev.d.ts → admin.d.ts} +1 -1
  7. package/dist/{dev.js → admin.js} +14 -12
  8. package/dist/{dev.test.js → admin.test.js} +36 -31
  9. package/dist/cli-program.js +7 -7
  10. package/dist/cli-program.test.js +1 -3
  11. package/dist/cli-project.d.ts +18 -0
  12. package/dist/cli-project.js +52 -0
  13. package/dist/cli-project.test.d.ts +1 -0
  14. package/dist/cli-project.test.js +149 -0
  15. package/dist/cli-runtime.d.ts +2 -2
  16. package/dist/cli-runtime.js +2 -8
  17. package/dist/commands/connection-commands.js +11 -10
  18. package/dist/commands/connection-selection.d.ts +11 -0
  19. package/dist/commands/connection-selection.js +9 -0
  20. package/dist/commands/ingest-commands.js +32 -26
  21. package/dist/commands/knowledge-commands.js +17 -28
  22. package/dist/commands/mcp-commands.js +17 -11
  23. package/dist/commands/runtime-commands.js +2 -2
  24. package/dist/commands/sl-commands.js +27 -32
  25. package/dist/context-build-view.js +1 -1
  26. package/dist/doctor.test.js +4 -4
  27. package/dist/example-smoke.test.js +3 -3
  28. package/dist/index.test.js +97 -85
  29. package/dist/ingest.js +9 -2
  30. package/dist/ingest.test.js +27 -3
  31. package/dist/io/print-list.test.js +4 -4
  32. package/dist/knowledge.js +1 -1
  33. package/dist/managed-local-embeddings.d.ts +0 -2
  34. package/dist/managed-local-embeddings.js +2 -5
  35. package/dist/managed-local-embeddings.test.js +5 -8
  36. package/dist/managed-python-command.js +2 -2
  37. package/dist/managed-python-command.test.js +3 -3
  38. package/dist/managed-python-daemon.js +2 -2
  39. package/dist/managed-python-daemon.test.js +1 -1
  40. package/dist/managed-python-http.js +3 -3
  41. package/dist/managed-python-http.test.js +6 -6
  42. package/dist/managed-python-runtime.d.ts +1 -1
  43. package/dist/managed-python-runtime.js +3 -3
  44. package/dist/managed-python-runtime.test.js +2 -2
  45. package/dist/memory-flow-tui.test.js +2 -2
  46. package/dist/next-steps.d.ts +6 -6
  47. package/dist/next-steps.js +4 -4
  48. package/dist/next-steps.test.js +5 -5
  49. package/dist/print-command-tree.js +0 -2
  50. package/dist/print-command-tree.test.js +1 -1
  51. package/dist/public-ingest.d.ts +4 -2
  52. package/dist/public-ingest.js +12 -8
  53. package/dist/public-ingest.test.js +7 -3
  54. package/dist/release-version.d.ts +1 -5
  55. package/dist/release-version.js +2 -39
  56. package/dist/runtime-requirements.js +1 -1
  57. package/dist/runtime.js +6 -6
  58. package/dist/runtime.test.js +8 -8
  59. package/dist/scan.js +7 -2
  60. package/dist/scan.test.js +3 -3
  61. package/dist/setup-agents.js +3 -3
  62. package/dist/setup-agents.test.js +1 -1
  63. package/dist/setup-embeddings.js +2 -2
  64. package/dist/setup-embeddings.test.js +5 -5
  65. package/dist/setup-runtime.test.js +3 -3
  66. package/dist/sl.js +1 -1
  67. package/dist/standalone-smoke.test.js +6 -2
  68. package/node_modules/@ktx/context/dist/core/git.service.d.ts +1 -0
  69. package/node_modules/@ktx/context/dist/core/git.service.js +12 -0
  70. package/node_modules/@ktx/context/dist/index-sync/index.d.ts +2 -0
  71. package/node_modules/@ktx/context/dist/index-sync/index.js +1 -0
  72. package/node_modules/@ktx/context/dist/index-sync/reindex.d.ts +20 -0
  73. package/node_modules/@ktx/context/dist/index-sync/reindex.js +141 -0
  74. package/node_modules/@ktx/context/dist/index-sync/reindex.test.d.ts +1 -0
  75. package/node_modules/@ktx/context/dist/index-sync/reindex.test.js +139 -0
  76. package/node_modules/@ktx/context/dist/index-sync/types.d.ts +29 -0
  77. package/node_modules/@ktx/context/dist/index-sync/types.js +1 -0
  78. package/node_modules/@ktx/context/dist/index.d.ts +1 -0
  79. package/node_modules/@ktx/context/dist/index.js +1 -0
  80. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/historic-sql.adapter.d.ts +2 -1
  81. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/historic-sql.adapter.js +18 -0
  82. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/local-ingest-acceptance.test.js +6 -6
  83. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.d.ts +5 -0
  84. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.js +48 -0
  85. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/projection.test.js +83 -0
  86. package/node_modules/@ktx/context/dist/ingest/adapters/live-database/daemon-introspection.js +4 -1
  87. package/node_modules/@ktx/context/dist/ingest/adapters/live-database/daemon-introspection.test.js +32 -0
  88. package/node_modules/@ktx/context/dist/ingest/finalization-scope.d.ts +22 -0
  89. package/node_modules/@ktx/context/dist/ingest/finalization-scope.js +95 -0
  90. package/node_modules/@ktx/context/dist/ingest/finalization-scope.test.d.ts +1 -0
  91. package/node_modules/@ktx/context/dist/ingest/finalization-scope.test.js +114 -0
  92. package/node_modules/@ktx/context/dist/ingest/index.d.ts +1 -2
  93. package/node_modules/@ktx/context/dist/ingest/index.js +0 -1
  94. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.d.ts +2 -0
  95. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.isolated-diff.test.js +166 -0
  96. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.js +235 -45
  97. package/node_modules/@ktx/context/dist/ingest/ingest-bundle.runner.test.js +193 -38
  98. package/node_modules/@ktx/context/dist/ingest/local-bundle-ingest.test.js +22 -3
  99. package/node_modules/@ktx/context/dist/ingest/local-bundle-runtime.js +3 -4
  100. package/node_modules/@ktx/context/dist/ingest/local-ingest.js +0 -7
  101. package/node_modules/@ktx/context/dist/ingest/local-stage-ingest.js +15 -5
  102. package/node_modules/@ktx/context/dist/ingest/local-stage-ingest.test.js +29 -0
  103. package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.d.ts +4 -4
  104. package/node_modules/@ktx/context/dist/ingest/memory-flow/schema.js +1 -1
  105. package/node_modules/@ktx/context/dist/ingest/memory-flow/types.d.ts +1 -1
  106. package/node_modules/@ktx/context/dist/ingest/ports.d.ts +1 -20
  107. package/node_modules/@ktx/context/dist/ingest/report-snapshot.d.ts +73 -2
  108. package/node_modules/@ktx/context/dist/ingest/report-snapshot.js +27 -0
  109. package/node_modules/@ktx/context/dist/ingest/reports.d.ts +23 -5
  110. package/node_modules/@ktx/context/dist/ingest/reports.js +7 -24
  111. package/node_modules/@ktx/context/dist/ingest/types.d.ts +33 -0
  112. package/node_modules/@ktx/context/dist/llm/index.d.ts +1 -1
  113. package/node_modules/@ktx/context/dist/llm/index.js +1 -1
  114. package/node_modules/@ktx/context/dist/llm/local-config.d.ts +0 -1
  115. package/node_modules/@ktx/context/dist/llm/local-config.js +2 -12
  116. package/node_modules/@ktx/context/dist/llm/local-config.test.js +2 -23
  117. package/node_modules/@ktx/context/dist/memory/local-memory.js +9 -3
  118. package/node_modules/@ktx/context/dist/package-exports.test.js +2 -2
  119. package/node_modules/@ktx/context/dist/project/config.d.ts +16 -0
  120. package/node_modules/@ktx/context/dist/project/driver-schemas.d.ts +8 -0
  121. package/node_modules/@ktx/context/dist/project/driver-schemas.js +4 -0
  122. package/node_modules/@ktx/context/dist/scan/enabled-tables.d.ts +3 -0
  123. package/node_modules/@ktx/context/dist/scan/enabled-tables.js +15 -0
  124. package/node_modules/@ktx/context/dist/scan/local-scan.d.ts +2 -4
  125. package/node_modules/@ktx/context/dist/scan/local-scan.js +2 -15
  126. package/node_modules/@ktx/context/dist/sl/ports.d.ts +3 -3
  127. package/node_modules/@ktx/context/dist/sl/sl-search.service.d.ts +3 -2
  128. package/node_modules/@ktx/context/dist/sl/sl-search.service.js +47 -45
  129. package/node_modules/@ktx/context/dist/sl/sl-search.service.test.js +61 -0
  130. package/node_modules/@ktx/context/dist/sl/sqlite-sl-sources-index.d.ts +4 -3
  131. package/node_modules/@ktx/context/dist/sl/sqlite-sl-sources-index.js +15 -5
  132. package/node_modules/@ktx/context/dist/sl/sqlite-sl-sources-index.test.js +24 -0
  133. package/node_modules/@ktx/context/dist/wiki/knowledge-wiki.service.d.ts +3 -2
  134. package/node_modules/@ktx/context/dist/wiki/knowledge-wiki.service.js +62 -51
  135. package/node_modules/@ktx/context/dist/wiki/knowledge-wiki.service.test.js +59 -3
  136. package/node_modules/@ktx/context/dist/wiki/ports.d.ts +3 -3
  137. package/node_modules/@ktx/context/dist/wiki/sqlite-knowledge-index.d.ts +33 -0
  138. package/node_modules/@ktx/context/dist/wiki/sqlite-knowledge-index.js +155 -2
  139. package/node_modules/@ktx/context/dist/wiki/sqlite-knowledge-index.test.js +26 -0
  140. package/node_modules/@ktx/context/package.json +5 -0
  141. package/package.json +1 -1
  142. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.d.ts +0 -4
  143. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.js +0 -38
  144. package/node_modules/@ktx/context/dist/ingest/adapters/historic-sql/post-processor.test.js +0 -63
  145. /package/dist/{dev.test.d.ts → admin-reindex.test.d.ts} +0 -0
  146. /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, MANAGED_SENTENCE_TRANSFORMERS_BASE_URL_ENV, } from '@ktx/context';
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 managed daemon URL for the immediate health check', () => {
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 managed daemon', async () => {
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 local embeddings daemon: http://127.0.0.1:61234');
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 local embeddings daemon: http://127.0.0.1:61234');
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 dev runtime install --feature local-embeddings --yes'
16
- : 'ktx dev runtime install --yes';
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 dev runtime install --yes');
102
- expect(managedRuntimeInstallCommand('local-embeddings')).toBe('ktx dev runtime install --feature local-embeddings --yes');
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 dev runtime install --yes');
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 Python daemon failed to start: ${lastDetail}. stderr: ${input.state.stderrLog}`);
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 Python daemon did not report a pid. stderr: ${layout.daemonStderrPath}`);
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('managed Python daemon lifecycle', () => {
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 managed daemon HTTP ${path} returned non-object JSON`);
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 managed daemon HTTP ${path} failed with ${statusCode}: ${text}`));
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 Python daemon: ${daemon.baseUrl}\n`);
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 Python daemon: http://127.0.0.1:61234');
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 Python daemon: http://127.0.0.1:61234');
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('managed daemon ingest ports', () => {
91
- it('creates a Looker table parser backed by the managed daemon runner', async () => {
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 managed daemon runner', async () => {
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 managed daemon runner', async () => {
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 dev runtime install --yes";
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 dev runtime install --yes';
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 dev runtime install --yes',
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 dev runtime install --yes' }),
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 dev runtime install --yes');
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 dev runtime install --yes',
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 list');
149
- expect(frame).toContain('ktx wiki list');
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(' '));
@@ -1,6 +1,6 @@
1
1
  export declare const KTX_CONTEXT_BUILD_COMMANDS: readonly [{
2
- readonly command: "ktx ingest --all";
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 list";
12
+ readonly command: "ktx sl";
13
13
  readonly description: "Inspect generated semantic-layer sources";
14
14
  }, {
15
- readonly command: "ktx wiki list";
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 list";
22
+ readonly command: "ktx sl";
23
23
  readonly description: "Inspect generated semantic-layer sources";
24
24
  }, {
25
- readonly command: "ktx wiki list";
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;
@@ -1,7 +1,7 @@
1
1
  export const KTX_CONTEXT_BUILD_COMMANDS = [
2
2
  {
3
- command: 'ktx ingest --all',
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 list',
17
+ command: 'ktx sl',
18
18
  description: 'Inspect generated semantic-layer sources',
19
19
  },
20
20
  {
21
- command: 'ktx wiki list',
21
+ command: 'ktx wiki',
22
22
  description: 'Inspect generated wiki pages',
23
23
  },
24
24
  ];
@@ -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 --all',
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 list',
23
+ command: 'ktx sl',
24
24
  description: 'Inspect generated semantic-layer sources',
25
25
  },
26
26
  {
27
- command: 'ktx wiki list',
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 --all');
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');
@@ -11,8 +11,6 @@ function stubPackageInfo() {
11
11
  return {
12
12
  name: '@ktx/cli',
13
13
  version: '0.0.0-docs',
14
- packageVersion: '0.0.0-private',
15
- runtimeVersion: '0.0.0-docs',
16
14
  contextPackageName: '@ktx/context',
17
15
  };
18
16
  }
@@ -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', 'dev']) {
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]');
@@ -1,4 +1,4 @@
1
- import { type KtxLocalProject, loadKtxProject } from '@ktx/context/project';
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: Parameters<typeof loadKtxProject>[0]) => Promise<KtxPublicIngestProject>;
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<{
@@ -1,4 +1,4 @@
1
- import { loadKtxProject } from '@ktx/context/project';
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
- if (!args.all && !args.targetConnectionId) {
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 = args.all ? entries : entries.filter(([connectionId]) => connectionId === args.targetConnectionId);
242
- if (!args.all && selected.length === 0) {
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 managed daemon|Error:|Failed\b|Could not\b|Cannot\b)/;
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 ?? loadKtxProject;
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('rejects bare non-interactive ingest until the interactive confirmation slice exists', () => {
113
- const project = projectWithConnections({ warehouse: { driver: 'postgres' } });
114
- expect(() => buildPublicIngestPlan(project, { projectDir: '/tmp/project', all: false })).toThrow('Context build requires a connection id or all targets');
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({
@@ -1,5 +1 @@
1
- export declare function resolveKtxRuntimeVersion(input: {
2
- packageName: string;
3
- packageVersion: string;
4
- startDir?: string;
5
- }): string;
1
+ export declare function assertCliVersion(value: unknown, source: string): string;
@@ -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 isPlainObject(value) {
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 release version in ${source}`);
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 Python daemon.',
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 Python daemon\n`);
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 Python daemon already stopped\n');
29
+ io.stdout.write('KTX daemon already stopped\n');
30
30
  return;
31
31
  }
32
- io.stdout.write('Stopped KTX Python daemon\n');
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 Python daemons found\n');
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 Python daemons\n`);
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 Python daemons; failed ${result.failed.length}${result.stale.length > 0 ? `; cleaned stale ${result.stale.length}` : ''}\n`);
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
  }
@@ -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 managed Python daemon and prints the base URL', async () => {
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 Python daemon');
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 managed Python daemon', async () => {
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 Python daemon');
177
+ expect(io.stdout()).toContain('Stopped KTX daemon');
178
178
  expect(io.stdout()).toContain('pid: 4242');
179
179
  });
180
- it('stops all discovered Python daemons and reports the summary', async () => {
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 Python daemons');
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 Python daemons; failed 1');
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 dev runtime install --yes',
249
+ fix: 'Run: ktx admin runtime install --yes',
250
250
  },
251
251
  ]),
252
252
  };