@kaelio/ktx 0.10.0 → 0.12.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 (193) hide show
  1. package/assets/python/{kaelio_ktx-0.10.0-py3-none-any.whl → kaelio_ktx-0.12.0-py3-none-any.whl} +0 -0
  2. package/assets/python/manifest.json +4 -4
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/admin.js +1 -1
  5. package/dist/clack.d.ts +16 -0
  6. package/dist/clack.js +37 -6
  7. package/dist/claude-code-prompt-caching.js +1 -1
  8. package/dist/cli-program.js +7 -3
  9. package/dist/cli-runtime.d.ts +2 -0
  10. package/dist/cli-runtime.js +14 -8
  11. package/dist/commands/connection-commands.js +1 -1
  12. package/dist/commands/ingest-commands.js +4 -4
  13. package/dist/commands/mcp-commands.js +12 -12
  14. package/dist/commands/runtime-commands.js +4 -4
  15. package/dist/commands/setup-commands.js +6 -5
  16. package/dist/commands/sl-commands.js +1 -1
  17. package/dist/commands/sql-commands.js +1 -1
  18. package/dist/commands/status-commands.js +1 -1
  19. package/dist/community-cta.d.ts +11 -0
  20. package/dist/community-cta.js +19 -0
  21. package/dist/connection.js +1 -1
  22. package/dist/connectors/clickhouse/connector.js +1 -1
  23. package/dist/connectors/mysql/connector.js +1 -1
  24. package/dist/connectors/snowflake/connector.d.ts +1 -1
  25. package/dist/connectors/sqlite/connector.js +2 -25
  26. package/dist/connectors/sqlserver/connector.js +3 -3
  27. package/dist/context/connections/connection-type.d.ts +1 -1
  28. package/dist/context/connections/read-only-sql.d.ts +1 -0
  29. package/dist/context/connections/read-only-sql.js +116 -2
  30. package/dist/context/core/git-env.d.ts +12 -1
  31. package/dist/context/core/git-env.js +17 -2
  32. package/dist/context/core/git.service.d.ts +23 -0
  33. package/dist/context/core/git.service.js +86 -15
  34. package/dist/context/ingest/adapters/historic-sql/projection.js +2 -1
  35. package/dist/context/ingest/adapters/looker/client.js +7 -2
  36. package/dist/context/ingest/adapters/looker/factory.d.ts +8 -1
  37. package/dist/context/ingest/adapters/looker/factory.js +9 -0
  38. package/dist/context/ingest/adapters/looker/mapping.js +1 -1
  39. package/dist/context/ingest/adapters/looker/types.d.ts +1 -1
  40. package/dist/context/ingest/adapters/metabase/client.d.ts +1 -1
  41. package/dist/context/ingest/adapters/metabase/client.js +1 -1
  42. package/dist/context/ingest/adapters/metabase/local-metabase.adapter.js +1 -1
  43. package/dist/context/ingest/adapters/metabase/mapping.js +6 -6
  44. package/dist/context/ingest/artifact-gates.d.ts +2 -6
  45. package/dist/context/ingest/artifact-gates.js +5 -47
  46. package/dist/context/ingest/constrained-repair.d.ts +55 -0
  47. package/dist/context/ingest/constrained-repair.js +167 -0
  48. package/dist/context/ingest/final-gate-repair.d.ts +9 -11
  49. package/dist/context/ingest/final-gate-repair.js +40 -128
  50. package/dist/context/ingest/finalization-scope.d.ts +1 -1
  51. package/dist/context/ingest/finalization-scope.js +15 -15
  52. package/dist/context/ingest/ingest-bundle.runner.d.ts +1 -0
  53. package/dist/context/ingest/ingest-bundle.runner.js +101 -67
  54. package/dist/context/ingest/isolated-diff/patch-integrator.d.ts +6 -13
  55. package/dist/context/ingest/isolated-diff/patch-integrator.js +32 -109
  56. package/dist/context/ingest/isolated-diff/textual-conflict-resolver.d.ts +8 -9
  57. package/dist/context/ingest/isolated-diff/textual-conflict-resolver.js +63 -141
  58. package/dist/context/ingest/local-bundle-runtime.d.ts +2 -0
  59. package/dist/context/ingest/local-bundle-runtime.js +9 -10
  60. package/dist/context/ingest/local-ingest.d.ts +2 -0
  61. package/dist/context/ingest/local-ingest.js +2 -0
  62. package/dist/context/ingest/memory-flow/view-model.js +1 -1
  63. package/dist/context/ingest/stages/stage-3-work-units.d.ts +2 -6
  64. package/dist/context/ingest/stages/stage-3-work-units.js +2 -1
  65. package/dist/context/ingest/stages/validate-wu-sources.d.ts +7 -1
  66. package/dist/context/ingest/stages/validate-wu-sources.js +109 -4
  67. package/dist/context/ingest/tools/warehouse-verification/create-warehouse-verification-tools.d.ts +2 -0
  68. package/dist/context/ingest/tools/warehouse-verification/create-warehouse-verification-tools.js +1 -1
  69. package/dist/context/ingest/tools/warehouse-verification/discover-data.tool.js +3 -3
  70. package/dist/context/ingest/tools/warehouse-verification/sql-execution.tool.d.ts +3 -1
  71. package/dist/context/ingest/tools/warehouse-verification/sql-execution.tool.js +15 -1
  72. package/dist/context/llm/ai-sdk-runtime.js +2 -2
  73. package/dist/context/llm/claude-code-runtime.js +1 -1
  74. package/dist/context/llm/local-config.js +1 -1
  75. package/dist/context/llm/runtime-tools.js +2 -2
  76. package/dist/context/mcp/context-tools.js +7 -7
  77. package/dist/context/mcp/local-project-ports.js +23 -54
  78. package/dist/context/memory/local-memory.js +4 -1
  79. package/dist/context/memory/memory-agent.service.js +1 -1
  80. package/dist/context/project/config.d.ts +11 -4
  81. package/dist/context/project/config.js +85 -30
  82. package/dist/context/project/driver-schemas.js +1 -1
  83. package/dist/context/project/mappings-yaml-schema.js +2 -2
  84. package/dist/context/project/project.js +12 -4
  85. package/dist/context/scan/description-generation.js +4 -4
  86. package/dist/context/scan/local-enrichment-artifacts.js +2 -1
  87. package/dist/context/scan/local-scan.js +2 -2
  88. package/dist/context/scan/local-structural-artifacts.js +5 -5
  89. package/dist/context/scan/relationship-benchmark-report.js +1 -1
  90. package/dist/context/scan/relationship-discovery.js +3 -3
  91. package/dist/context/scan/relationship-llm-proposal.js +3 -3
  92. package/dist/context/sl/local-query.js +3 -33
  93. package/dist/context/sl/local-sl.d.ts +0 -8
  94. package/dist/context/sl/local-sl.js +44 -69
  95. package/dist/context/sl/semantic-layer.service.d.ts +25 -8
  96. package/dist/context/sl/semantic-layer.service.js +109 -56
  97. package/dist/context/sl/source-files.d.ts +46 -0
  98. package/dist/context/sl/source-files.js +131 -0
  99. package/dist/context/sl/tools/base-semantic-layer.tool.d.ts +2 -2
  100. package/dist/context/sl/tools/base-semantic-layer.tool.js +2 -7
  101. package/dist/context/sl/tools/sl-edit-source.tool.js +10 -8
  102. package/dist/context/sl/tools/sl-warehouse-validation.js +55 -27
  103. package/dist/context/sl/tools/sl-write-source.tool.js +12 -9
  104. package/dist/context/sql-analysis/dialect.d.ts +2 -0
  105. package/dist/context/sql-analysis/dialect.js +20 -0
  106. package/dist/context/tools/base-tool.d.ts +6 -19
  107. package/dist/context/tools/base-tool.js +0 -14
  108. package/dist/context-build-view.js +5 -5
  109. package/dist/database-tree-picker.js +18 -3
  110. package/dist/demo-assets.js +0 -1
  111. package/dist/doctor.d.ts +1 -1
  112. package/dist/doctor.js +31 -23
  113. package/dist/errors.d.ts +31 -0
  114. package/dist/errors.js +44 -0
  115. package/dist/ingest.d.ts +1 -1
  116. package/dist/ingest.js +8 -2
  117. package/dist/io/symbols.d.ts +2 -0
  118. package/dist/io/symbols.js +2 -0
  119. package/dist/io/tty.d.ts +17 -0
  120. package/dist/io/tty.js +21 -0
  121. package/dist/links.d.ts +1 -0
  122. package/dist/links.js +1 -0
  123. package/dist/llm/embedding-health.js +1 -1
  124. package/dist/llm/embedding-provider.js +3 -3
  125. package/dist/llm/model-provider.js +1 -1
  126. package/dist/local-adapters.d.ts +1 -0
  127. package/dist/local-adapters.js +2 -2
  128. package/dist/local-scan-connectors.js +1 -1
  129. package/dist/managed-local-embeddings.js +17 -8
  130. package/dist/managed-mcp-daemon.js +3 -3
  131. package/dist/managed-python-command.d.ts +7 -0
  132. package/dist/managed-python-command.js +34 -8
  133. package/dist/managed-python-daemon.js +2 -2
  134. package/dist/managed-python-http.js +3 -3
  135. package/dist/managed-python-runtime.d.ts +30 -1
  136. package/dist/managed-python-runtime.js +134 -18
  137. package/dist/managed-uv-release.d.ts +7 -0
  138. package/dist/managed-uv-release.js +11 -0
  139. package/dist/mcp-http-server.js +4 -4
  140. package/dist/mcp-server-factory.js +3 -3
  141. package/dist/mcp-stdio-server.js +1 -1
  142. package/dist/memory-flow-hud.js +2 -2
  143. package/dist/next-steps.js +2 -2
  144. package/dist/prompt-navigation.d.ts +17 -0
  145. package/dist/prompt-navigation.js +49 -3
  146. package/dist/prompts/memory_agent_bundle_ingest_work_unit.md +2 -2
  147. package/dist/prompts/memory_agent_external_ingest.md +2 -2
  148. package/dist/public-ingest-copy.js +1 -1
  149. package/dist/public-ingest.js +3 -3
  150. package/dist/release-version.js +1 -1
  151. package/dist/runtime-requirements.js +1 -1
  152. package/dist/runtime.js +9 -9
  153. package/dist/scan.js +1 -1
  154. package/dist/setup-agents.js +22 -35
  155. package/dist/setup-banner.d.ts +20 -0
  156. package/dist/setup-banner.js +39 -0
  157. package/dist/setup-context.js +24 -15
  158. package/dist/setup-databases.js +31 -59
  159. package/dist/setup-demo-tour.js +12 -8
  160. package/dist/setup-embeddings.js +9 -9
  161. package/dist/setup-interrupt.js +1 -1
  162. package/dist/setup-models.d.ts +4 -1
  163. package/dist/setup-models.js +54 -28
  164. package/dist/setup-project.js +29 -5
  165. package/dist/setup-prompts.js +16 -5
  166. package/dist/setup-ready-menu.js +1 -1
  167. package/dist/setup-sources.js +27 -7
  168. package/dist/setup.d.ts +25 -0
  169. package/dist/setup.js +90 -19
  170. package/dist/skills/analytics/SKILL.md +3 -3
  171. package/dist/skills/dbt_ingest/SKILL.md +3 -3
  172. package/dist/skills/looker_ingest/SKILL.md +3 -3
  173. package/dist/skills/lookml_ingest/SKILL.md +7 -7
  174. package/dist/skills/metabase_ingest/SKILL.md +4 -4
  175. package/dist/skills/metricflow_ingest/SKILL.md +15 -15
  176. package/dist/skills/notion_synthesize/SKILL.md +1 -1
  177. package/dist/skills/sl/SKILL.md +3 -3
  178. package/dist/skills/sl_capture/SKILL.md +1 -1
  179. package/dist/skills/wiki_capture/SKILL.md +1 -1
  180. package/dist/source-mapping.js +1 -1
  181. package/dist/startup-profile.js +1 -1
  182. package/dist/status-project.d.ts +0 -2
  183. package/dist/status-project.js +4 -6
  184. package/dist/telemetry/command-hook.d.ts +24 -0
  185. package/dist/telemetry/command-hook.js +37 -3
  186. package/dist/telemetry/events.d.ts +1 -1
  187. package/dist/telemetry/exception.js +14 -0
  188. package/dist/telemetry/index.d.ts +2 -2
  189. package/dist/telemetry/index.js +2 -2
  190. package/dist/text-ingest.js +1 -1
  191. package/dist/tree-picker-tui.d.ts +0 -1
  192. package/dist/tree-picker-tui.js +2 -3
  193. package/package.json +1 -1
package/dist/ingest.d.ts CHANGED
@@ -60,7 +60,7 @@ export interface KtxIngestDeps {
60
60
  startLiveMemoryFlow?: typeof startLiveMemoryFlowTui;
61
61
  abortSignal?: AbortSignal;
62
62
  env?: NodeJS.ProcessEnv;
63
- localIngestOptions?: Pick<RunLocalIngestOptions, 'agentRunner' | 'llmRuntime' | 'memoryModel' | 'semanticLayerCompute' | 'queryExecutor' | 'logger' | 'pullConfigOptions'>;
63
+ localIngestOptions?: Pick<RunLocalIngestOptions, 'agentRunner' | 'llmRuntime' | 'memoryModel' | 'semanticLayerCompute' | 'queryExecutor' | 'sqlAnalysis' | 'logger' | 'pullConfigOptions'>;
64
64
  progress?: (update: KtxIngestProgressUpdate) => void;
65
65
  runtimeIo?: KtxIngestIo;
66
66
  }
package/dist/ingest.js CHANGED
@@ -11,7 +11,7 @@ import { resolveProjectEmbeddingProvider } from './embedding-resolution.js';
11
11
  import { createKtxCliIngestQueryExecutor } from './ingest-query-executor.js';
12
12
  import { readIngestReportSnapshotFile } from './ingest-report-file.js';
13
13
  import { createCliOperationalLogger } from './io/logger.js';
14
- import { createKtxCliLocalIngestAdapters } from './local-adapters.js';
14
+ import { createKtxCliLocalIngestAdapters, resolveKtxCliSqlAnalysis } from './local-adapters.js';
15
15
  import { renderMemoryFlowInteractively } from './memory-flow-interactive.js';
16
16
  import { renderMemoryFlowTui, startLiveMemoryFlowTui, } from './memory-flow-tui.js';
17
17
  import { resolveVizFallback, warnVizFallbackOnce } from './viz-fallback.js';
@@ -525,7 +525,7 @@ export async function runKtxIngest(args, io = process, deps = {}) {
525
525
  const localIngestOptions = deps.localIngestOptions ?? {};
526
526
  const managedDaemon = managedDaemonOptionsForIngestRun(args, deps.runtimeIo ?? io);
527
527
  const operationalLogger = createCliOperationalLogger(io, args.outputMode);
528
- const adapterOptions = {
528
+ const baseAdapterOptions = {
529
529
  ...(localIngestOptions.pullConfigOptions ?? {}),
530
530
  ...(args.databaseIntrospectionUrl ? { databaseIntrospectionUrl: args.databaseIntrospectionUrl } : {}),
531
531
  ...(managedDaemon ? { managedDaemon } : {}),
@@ -535,6 +535,10 @@ export async function runKtxIngest(args, io = process, deps = {}) {
535
535
  : {}),
536
536
  logger: operationalLogger,
537
537
  };
538
+ // One parser-backed SQL analysis port per run: the historic-sql adapter and
539
+ // the ingest sql_execution tool share the same daemon-backed validator.
540
+ const sqlAnalysis = localIngestOptions.sqlAnalysis ?? resolveKtxCliSqlAnalysis(baseAdapterOptions);
541
+ const adapterOptions = { ...baseAdapterOptions, sqlAnalysis };
538
542
  const queryExecutor = localIngestOptions.queryExecutor ??
539
543
  (deps.createQueryExecutor ?? createKtxCliIngestQueryExecutor)(ingestProject);
540
544
  if (args.adapter === 'metabase' && args.sourceDir) {
@@ -577,6 +581,7 @@ export async function runKtxIngest(args, io = process, deps = {}) {
577
581
  metabaseConnectionId: args.connectionId,
578
582
  ...localIngestOptions,
579
583
  queryExecutor,
584
+ sqlAnalysis,
580
585
  trigger: 'manual_resync',
581
586
  jobIdFactory: deps.jobIdFactory,
582
587
  embeddingProvider,
@@ -650,6 +655,7 @@ export async function runKtxIngest(args, io = process, deps = {}) {
650
655
  jobId,
651
656
  ...localIngestOptions,
652
657
  queryExecutor,
658
+ sqlAnalysis,
653
659
  pullConfigOptions: adapterOptions,
654
660
  embeddingProvider,
655
661
  ...(args.debugLlmRequestFile ? { llmDebugRequestFile: args.debugLlmRequestFile } : {}),
@@ -1,3 +1,5 @@
1
+ /** Whether the active terminal renders Unicode glyphs (block/box drawing, arrows). */
2
+ export declare const unicodeSupported: boolean;
1
3
  export declare const SYMBOLS: {
2
4
  readonly middot: "-" | "·";
3
5
  readonly emDash: "--" | "—";
@@ -9,6 +9,8 @@ function detectUnicodeSupport(env = process.env) {
9
9
  env.TERM === 'alacritty');
10
10
  }
11
11
  const unicode = detectUnicodeSupport();
12
+ /** Whether the active terminal renders Unicode glyphs (block/box drawing, arrows). */
13
+ export const unicodeSupported = unicode;
12
14
  export const SYMBOLS = {
13
15
  middot: unicode ? '·' : '-',
14
16
  emDash: unicode ? '—' : '--',
@@ -0,0 +1,17 @@
1
+ import type { Writable } from 'node:stream';
2
+ import type { KtxCliIo } from '../cli-runtime.js';
3
+ type KtxCliOutput = (KtxCliIo['stdout'] | KtxCliIo['stderr']) & {
4
+ isTTY?: boolean;
5
+ columns?: number;
6
+ on?: unknown;
7
+ };
8
+ export declare function isWritableTtyOutput(output: KtxCliOutput): output is KtxCliOutput & Writable;
9
+ export declare function shouldUseColorOutput(output: {
10
+ isTTY?: boolean;
11
+ }): boolean;
12
+ /**
13
+ * Color depth in bits for the given output: 1 when color is disabled, the
14
+ * stream-reported depth when available, and a 16-color baseline otherwise.
15
+ */
16
+ export declare function colorDepthForOutput(output: KtxCliOutput): number;
17
+ export {};
package/dist/io/tty.js ADDED
@@ -0,0 +1,21 @@
1
+ export function isWritableTtyOutput(output) {
2
+ return (output.isTTY === true &&
3
+ typeof output.on === 'function' &&
4
+ typeof output.columns !== 'undefined');
5
+ }
6
+ export function shouldUseColorOutput(output) {
7
+ if (output.isTTY !== true)
8
+ return false;
9
+ const env = process.env;
10
+ return !env.NO_COLOR && env.TERM !== 'dumb' && !env.CI;
11
+ }
12
+ /**
13
+ * Color depth in bits for the given output: 1 when color is disabled, the
14
+ * stream-reported depth when available, and a 16-color baseline otherwise.
15
+ */
16
+ export function colorDepthForOutput(output) {
17
+ if (!shouldUseColorOutput(output))
18
+ return 1;
19
+ const getColorDepth = output.getColorDepth;
20
+ return typeof getColorDepth === 'function' ? getColorDepth.call(output) : 4;
21
+ }
@@ -0,0 +1 @@
1
+ export declare const SLACK_URL = "https://ktx.sh/slack";
package/dist/links.js ADDED
@@ -0,0 +1 @@
1
+ export const SLACK_URL = 'https://ktx.sh/slack';
@@ -21,7 +21,7 @@ async function withTimeout(promise, timeoutMs) {
21
21
  export async function runKtxEmbeddingHealthCheck(config, options = {}) {
22
22
  try {
23
23
  const provider = createKtxEmbeddingProvider(config, options.deps);
24
- const embedding = await withTimeout(provider.embed(options.text ?? 'KTX embedding health check'), options.timeoutMs ?? 15_000);
24
+ const embedding = await withTimeout(provider.embed(options.text ?? 'ktx embedding health check'), options.timeoutMs ?? 15_000);
25
25
  if (embedding.length !== config.dimensions) {
26
26
  return {
27
27
  ok: false,
@@ -49,7 +49,7 @@ class OpenAIEmbeddingProvider {
49
49
  this.dimensions = config.dimensions;
50
50
  this.maxBatchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;
51
51
  if (!config.openai?.apiKey) {
52
- throw new Error('openai.apiKey is required when KTX embedding backend is openai');
52
+ throw new Error('openai.apiKey is required when ktx embedding backend is openai');
53
53
  }
54
54
  this.client = deps.createOpenAIClient
55
55
  ? deps.createOpenAIClient({ apiKey: config.openai.apiKey, baseURL: config.openai.baseURL })
@@ -90,7 +90,7 @@ class SentenceTransformersEmbeddingProvider {
90
90
  startupProbe;
91
91
  constructor(config, deps) {
92
92
  if (!config.sentenceTransformers?.baseURL) {
93
- throw new Error('sentenceTransformers.baseURL is required when KTX embedding backend is sentence-transformers');
93
+ throw new Error('sentenceTransformers.baseURL is required when ktx embedding backend is sentence-transformers');
94
94
  }
95
95
  this.dimensions = config.dimensions;
96
96
  this.maxBatchSize = config.batchSize ?? DEFAULT_BATCH_SIZE;
@@ -156,6 +156,6 @@ export function createKtxEmbeddingProvider(config, deps = {}) {
156
156
  case 'sentence-transformers':
157
157
  return new SentenceTransformersEmbeddingProvider(config, deps);
158
158
  default:
159
- throw new Error(`Unsupported KTX embedding backend: ${String(config.backend)}`);
159
+ throw new Error(`Unsupported ktx embedding backend: ${String(config.backend)}`);
160
160
  }
161
161
  }
@@ -121,7 +121,7 @@ class DefaultKtxLlmProvider {
121
121
  }
122
122
  if (config.backend === 'vertex') {
123
123
  if (!config.vertex?.location) {
124
- throw new Error('vertex.location is required when KTX LLM backend is vertex');
124
+ throw new Error('vertex.location is required when ktx LLM backend is vertex');
125
125
  }
126
126
  const vertex = (deps.createVertexAnthropic ?? createVertexAnthropic)({
127
127
  ...(config.vertex.project ? { project: config.vertex.project } : {}),
@@ -5,6 +5,7 @@ import type { KtxLocalProject } from './context/project/project.js';
5
5
  import type { SqlAnalysisPort } from './context/sql-analysis/ports.js';
6
6
  import { type ManagedPythonDaemonHttpOptions } from './managed-python-http.js';
7
7
  import type { KtxOperationalLogger } from './io/logger.js';
8
+ export declare function resolveKtxCliSqlAnalysis(options: KtxCliLocalIngestAdaptersOptions): SqlAnalysisPort;
8
9
  export interface KtxCliLocalIngestAdaptersOptions extends DefaultLocalIngestAdaptersOptions {
9
10
  historicSqlConnectionId?: string;
10
11
  sqlAnalysis?: SqlAnalysisPort;
@@ -45,7 +45,7 @@ function ktxCliLookerOptions(options) {
45
45
  parser: createManagedDaemonLookerTableIdentifierParser(options.managedDaemon),
46
46
  };
47
47
  }
48
- function ktxCliHistoricSqlAnalysis(options) {
48
+ export function resolveKtxCliSqlAnalysis(options) {
49
49
  if (options.sqlAnalysis) {
50
50
  return options.sqlAnalysis;
51
51
  }
@@ -234,7 +234,7 @@ function historicSqlOptionsForLocalRun(project, options) {
234
234
  return undefined;
235
235
  }
236
236
  const base = {
237
- sqlAnalysis: ktxCliHistoricSqlAnalysis(options),
237
+ sqlAnalysis: resolveKtxCliSqlAnalysis(options),
238
238
  };
239
239
  if (dialect === 'postgres') {
240
240
  return {
@@ -11,7 +11,7 @@ export async function createKtxCliScanConnector(project, connectionId) {
11
11
  }
12
12
  const registration = getDriverRegistration(driver);
13
13
  if (!registration) {
14
- throw new Error(`Connection "${connectionId}" uses driver "${driver}", which has no native standalone KTX scan connector. Supported drivers: ${SUPPORTED_DRIVERS}.`);
14
+ throw new Error(`Connection "${connectionId}" uses driver "${driver}", which has no native standalone ktx scan connector. Supported drivers: ${SUPPORTED_DRIVERS}.`);
15
15
  }
16
16
  const connectorModule = await registration.load();
17
17
  if (!connectorModule.isConnectionConfig(connection)) {
@@ -1,4 +1,4 @@
1
- import { writePrefixedLines } from './clack.js';
1
+ import { createCliSpinner } from './clack.js';
2
2
  import { ensureManagedPythonCommandRuntime, } from './managed-python-command.js';
3
3
  import { readManagedPythonDaemonStatus, startManagedPythonDaemon, } from './managed-python-daemon.js';
4
4
  export function managedLocalEmbeddingHealthConfig(input) {
@@ -21,14 +21,23 @@ export async function ensureManagedLocalEmbeddingsDaemon(options) {
21
21
  io: options.io,
22
22
  feature: 'local-embeddings',
23
23
  });
24
- const daemon = await startDaemon({
25
- cliVersion: options.cliVersion,
26
- projectDir: options.projectDir,
27
- features: ['local-embeddings'],
28
- force: false,
29
- });
24
+ const spinner = createCliSpinner(options.io);
25
+ spinner.start('Starting ktx embedding daemon (first run downloads the model)…');
26
+ let daemon;
27
+ try {
28
+ daemon = await startDaemon({
29
+ cliVersion: options.cliVersion,
30
+ projectDir: options.projectDir,
31
+ features: ['local-embeddings'],
32
+ force: false,
33
+ });
34
+ }
35
+ catch (error) {
36
+ spinner.error('ktx embedding daemon failed to start');
37
+ throw error;
38
+ }
30
39
  const verb = daemon.status === 'started' ? 'Started' : 'Using';
31
- writePrefixedLines((chunk) => options.io.stderr.write(chunk), `${verb} KTX daemon: ${daemon.baseUrl}`);
40
+ spinner.stop(`${verb} ktx daemon: ${daemon.baseUrl}`);
32
41
  return {
33
42
  baseUrl: daemon.baseUrl,
34
43
  stdoutLog: daemon.state.stdoutLog,
@@ -92,7 +92,7 @@ export async function startKtxMcpDaemon(options) {
92
92
  url: `http://${existing.host}:${existing.port}/mcp`,
93
93
  };
94
94
  }
95
- throw new Error(`KTX MCP daemon is already running at http://${existing.host}:${existing.port}/mcp ` +
95
+ throw new Error(`ktx MCP daemon is already running at http://${existing.host}:${existing.port}/mcp ` +
96
96
  'with a different configuration. Run `ktx mcp stop` first, then start again.');
97
97
  }
98
98
  const portAvailable = options.portAvailable ?? defaultPortAvailable;
@@ -126,7 +126,7 @@ export async function startKtxMcpDaemon(options) {
126
126
  }),
127
127
  });
128
128
  if (!child.pid) {
129
- throw new Error('Failed to start KTX MCP daemon: child process pid was not available.');
129
+ throw new Error('Failed to start ktx MCP daemon: child process pid was not available.');
130
130
  }
131
131
  child.unref();
132
132
  const state = {
@@ -167,7 +167,7 @@ export async function readKtxMcpDaemonStatus(options) {
167
167
  }
168
168
  return {
169
169
  kind: 'running',
170
- detail: `KTX MCP daemon running at http://${state.host}:${state.port}/mcp`,
170
+ detail: `ktx MCP daemon running at http://${state.host}:${state.port}/mcp`,
171
171
  state,
172
172
  url: `http://${state.host}:${state.port}/mcp`,
173
173
  };
@@ -31,4 +31,11 @@ export interface ManagedPythonSemanticLayerComputeOptions extends ManagedPythonC
31
31
  export declare function managedRuntimeInstallCommand(feature: KtxRuntimeFeature): string;
32
32
  export declare function ensureManagedPythonCommandRuntime(options: ManagedPythonCommandOptions): Promise<ManagedPythonCommandRuntime>;
33
33
  export declare function createManagedPythonSemanticLayerComputePort(options: ManagedPythonSemanticLayerComputeOptions): Promise<KtxSemanticLayerComputePort>;
34
+ /**
35
+ * Defers the managed-runtime install to the first semantic-layer call so a
36
+ * long-lived server (the MCP server) can start and serve context tools that
37
+ * need no Python even when uv is absent. Caches on success only, so a runtime
38
+ * installed mid-session is picked up on the next call.
39
+ */
40
+ export declare function createLazyManagedPythonSemanticLayerComputePort(options: ManagedPythonSemanticLayerComputeOptions): KtxSemanticLayerComputePort;
34
41
  export {};
@@ -1,5 +1,5 @@
1
1
  import { createPythonSemanticLayerComputePort } from './context/daemon/semantic-layer-compute.js';
2
- import { createClackPromptAdapter, createStaticCliSpinner } from './clack.js';
2
+ import { createClackPromptAdapter, createCliSpinner } from './clack.js';
3
3
  import { installManagedPythonRuntime, readManagedPythonRuntimeStatus, } from './managed-python-runtime.js';
4
4
  import { readExistingTelemetryProjectId } from './telemetry/identity.js';
5
5
  export function runtimeInstallPolicyFromFlags(options) {
@@ -19,10 +19,10 @@ export function managedRuntimeInstallCommand(feature) {
19
19
  }
20
20
  function installPrompt(feature) {
21
21
  const label = feature === 'local-embeddings' ? 'local embeddings Python runtime' : 'core Python runtime';
22
- return `KTX needs to install the ${label}. This downloads Python dependencies with uv. Continue?`;
22
+ return `ktx needs to install the ${label}. This downloads a pinned, checksum-verified uv build, Python, and dependencies. Continue?`;
23
23
  }
24
24
  function runtimeRequiredMessage(feature) {
25
- return `KTX Python runtime is required for this command. Run: ${managedRuntimeInstallCommand(feature)}`;
25
+ return `ktx Python runtime is required for this command. Run: ${managedRuntimeInstallCommand(feature)}`;
26
26
  }
27
27
  function hasFeature(manifest, feature) {
28
28
  return manifest.features.includes(feature);
@@ -49,22 +49,22 @@ export async function ensureManagedPythonCommandRuntime(options) {
49
49
  const confirmInstall = options.confirmInstall ?? defaultConfirmInstall;
50
50
  const confirmed = await confirmInstall(installPrompt(feature), options.io);
51
51
  if (!confirmed) {
52
- throw new Error(`KTX Python runtime installation was cancelled. Run: ${managedRuntimeInstallCommand(feature)}`);
52
+ throw new Error(`ktx Python runtime installation was cancelled. Run: ${managedRuntimeInstallCommand(feature)}`);
53
53
  }
54
54
  }
55
- const progress = (options.spinner ?? (() => createStaticCliSpinner(options.io)))();
56
- progress.start(`Installing KTX Python runtime (${feature}) with uv...`);
55
+ const progress = (options.spinner ?? (() => createCliSpinner(options.io)))();
56
+ progress.start(`Installing ktx Python runtime (${feature}) with uv...`);
57
57
  try {
58
58
  const installed = await installRuntime({
59
59
  cliVersion: options.cliVersion,
60
60
  features: [feature],
61
61
  force: false,
62
62
  });
63
- progress.stop(`KTX Python runtime ready: ${installed.layout.versionDir}`);
63
+ progress.stop(`ktx Python runtime ready: ${installed.layout.versionDir}`);
64
64
  return { layout: installed.layout, manifest: installed.manifest };
65
65
  }
66
66
  catch (error) {
67
- progress.error(`KTX Python runtime install failed: ${error instanceof Error ? error.message : String(error)}`);
67
+ progress.error(`ktx Python runtime install failed: ${error instanceof Error ? error.message : String(error)}`);
68
68
  throw error;
69
69
  }
70
70
  }
@@ -89,3 +89,29 @@ export async function createManagedPythonSemanticLayerComputePort(options) {
89
89
  ...(projectId ? { projectId } : {}),
90
90
  });
91
91
  }
92
+ /**
93
+ * Defers the managed-runtime install to the first semantic-layer call so a
94
+ * long-lived server (the MCP server) can start and serve context tools that
95
+ * need no Python even when uv is absent. Caches on success only, so a runtime
96
+ * installed mid-session is picked up on the next call.
97
+ */
98
+ export function createLazyManagedPythonSemanticLayerComputePort(options) {
99
+ let cached;
100
+ const resolve = async () => {
101
+ if (!cached) {
102
+ cached = await createManagedPythonSemanticLayerComputePort(options);
103
+ }
104
+ return cached;
105
+ };
106
+ return {
107
+ async query(input) {
108
+ return (await resolve()).query(input);
109
+ },
110
+ async validateSources(input) {
111
+ return (await resolve()).validateSources(input);
112
+ },
113
+ async generateSources(input) {
114
+ return (await resolve()).generateSources(input);
115
+ },
116
+ };
117
+ }
@@ -11,7 +11,7 @@ export class ManagedPythonDaemonStartError extends Error {
11
11
  detail;
12
12
  stderrLog;
13
13
  constructor(detail, stderrLog) {
14
- super(`KTX daemon failed to start: ${detail}. stderr: ${stderrLog}`);
14
+ super(`ktx daemon failed to start: ${detail}. stderr: ${stderrLog}`);
15
15
  this.name = 'ManagedPythonDaemonStartError';
16
16
  this.detail = detail;
17
17
  this.stderrLog = stderrLog;
@@ -502,7 +502,7 @@ export async function startManagedPythonDaemon(options) {
502
502
  });
503
503
  child.unref();
504
504
  if (!child.pid) {
505
- throw new Error(`KTX daemon did not report a pid. stderr: ${layout.daemonStderrPath}`);
505
+ throw new Error(`ktx daemon did not report a pid. stderr: ${layout.daemonStderrPath}`);
506
506
  }
507
507
  const state = {
508
508
  schemaVersion: 1,
@@ -12,7 +12,7 @@ function normalizedBaseUrl(baseUrl) {
12
12
  function parseJsonObject(raw, path) {
13
13
  const parsed = JSON.parse(raw);
14
14
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
15
- throw new Error(`KTX daemon HTTP ${path} returned non-object JSON`);
15
+ throw new Error(`ktx daemon HTTP ${path} returned non-object JSON`);
16
16
  }
17
17
  return parsed;
18
18
  }
@@ -35,7 +35,7 @@ async function postManagedDaemonJson(baseUrl, path, payload) {
35
35
  const text = Buffer.concat(chunks).toString('utf8');
36
36
  const statusCode = response.statusCode ?? 0;
37
37
  if (statusCode < 200 || statusCode >= 300) {
38
- reject(new Error(`KTX daemon HTTP ${path} failed with ${statusCode}: ${text}`));
38
+ reject(new Error(`ktx daemon HTTP ${path} failed with ${statusCode}: ${text}`));
39
39
  return;
40
40
  }
41
41
  try {
@@ -72,7 +72,7 @@ export function createManagedPythonDaemonBaseUrlResolver(options) {
72
72
  force: false,
73
73
  });
74
74
  const verb = daemon.status === 'started' ? 'Started' : 'Using existing';
75
- writePrefixedLines((chunk) => options.io.stderr.write(chunk), `${verb} KTX daemon: ${daemon.baseUrl}`);
75
+ writePrefixedLines((chunk) => options.io.stderr.write(chunk), `${verb} ktx daemon: ${daemon.baseUrl}`);
76
76
  cachedBaseUrl = daemon.baseUrl;
77
77
  return cachedBaseUrl;
78
78
  };
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { type ManagedUvArtifact, type ManagedUvPlatformKey } from './managed-uv-release.js';
2
3
  export declare const runtimeFeatureSchema: z.ZodEnum<{
3
4
  core: "core";
4
5
  "local-embeddings": "local-embeddings";
@@ -92,6 +93,7 @@ export interface ManagedPythonRuntimeInstallOptions extends ManagedPythonRuntime
92
93
  features: KtxRuntimeFeature[];
93
94
  force?: boolean;
94
95
  exec?: ManagedPythonRuntimeExec;
96
+ fetchUvArtifact?: ManagedUvFetchArtifact;
95
97
  }
96
98
  export interface ManagedPythonRuntimeInstallResult {
97
99
  status: 'ready' | 'installed';
@@ -113,8 +115,22 @@ export interface ManagedPythonRuntimeDoctorCheck {
113
115
  detail: string;
114
116
  fix?: string;
115
117
  }
118
+ export type ManagedUvFetchArtifact = (url: string) => Promise<Uint8Array>;
116
119
  /** @internal */
117
- 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";
120
+ export interface ManagedUvRelease {
121
+ version: string;
122
+ artifacts: Partial<Record<ManagedUvPlatformKey, ManagedUvArtifact>>;
123
+ }
124
+ /** @internal */
125
+ export interface EnsureManagedUvOptions {
126
+ platform?: NodeJS.Platform;
127
+ arch?: string;
128
+ env?: NodeJS.ProcessEnv;
129
+ homeDir?: string;
130
+ runtimeRoot?: string;
131
+ fetchArtifact?: ManagedUvFetchArtifact;
132
+ release?: ManagedUvRelease;
133
+ }
118
134
  /** @internal */
119
135
  export declare function managedPythonRuntimeLayout(options: ManagedPythonRuntimeLayoutOptions): ManagedPythonRuntimeLayout;
120
136
  export declare function managedPythonDaemonLayout(options: ManagedPythonDaemonLayoutOptions): ManagedPythonDaemonLayout;
@@ -122,9 +138,22 @@ export declare function managedPythonDaemonLayout(options: ManagedPythonDaemonLa
122
138
  export declare function verifyRuntimeAsset(input: {
123
139
  assetDir: string;
124
140
  }): Promise<ManagedRuntimeAsset>;
141
+ /** @internal */
142
+ export declare function managedUvPath(options?: EnsureManagedUvOptions): string;
143
+ /**
144
+ * ktx provisions its own pinned uv under the runtime root; uv on PATH is never
145
+ * consulted, so runtime installs behave identically on every machine. All
146
+ * failures here are environment outcomes (offline host, intercepting proxy,
147
+ * unsupported platform) and stay out of Error Tracking via KtxExpectedError —
148
+ * except a pin/layout mismatch inside a checksum-verified archive, which is a
149
+ * ktx release fault and must reach Error Tracking.
150
+ * @internal
151
+ */
152
+ export declare function ensureManagedUv(options?: EnsureManagedUvOptions): Promise<string>;
125
153
  export declare function installManagedPythonRuntime(options: ManagedPythonRuntimeInstallOptions): Promise<ManagedPythonRuntimeInstallResult>;
126
154
  export declare function readManagedPythonRuntimeStatus(options: ManagedPythonRuntimeLayoutOptions): Promise<ManagedPythonRuntimeStatus>;
127
155
  export declare function doctorManagedPythonRuntime(options: ManagedPythonRuntimeLayoutOptions & {
128
156
  exec?: ManagedPythonRuntimeExec;
157
+ fetchUvArtifact?: ManagedUvFetchArtifact;
129
158
  }): Promise<ManagedPythonRuntimeDoctorCheck[]>;
130
159
  export {};