@kaelio/ktx 0.7.0 → 0.9.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 (142) hide show
  1. package/assets/python/{kaelio_ktx-0.7.0-py3-none-any.whl → kaelio_ktx-0.9.0-py3-none-any.whl} +0 -0
  2. package/assets/python/manifest.json +4 -4
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/cli-program.js +7 -0
  5. package/dist/cli-runtime.js +50 -3
  6. package/dist/command-schemas.d.ts +1 -1
  7. package/dist/command-tree.js +5 -1
  8. package/dist/commands/completion-commands.d.ts +3 -0
  9. package/dist/commands/completion-commands.js +38 -0
  10. package/dist/commands/ingest-commands.js +0 -4
  11. package/dist/commands/knowledge-commands.js +15 -2
  12. package/dist/commands/setup-commands.js +3 -3
  13. package/dist/commands/sl-commands.js +19 -7
  14. package/dist/completion/complete-engine.d.ts +19 -0
  15. package/dist/completion/complete-engine.js +128 -0
  16. package/dist/completion/completion-scripts.d.ts +1 -0
  17. package/dist/completion/completion-scripts.js +36 -0
  18. package/dist/completion/dynamic-candidates.d.ts +6 -0
  19. package/dist/completion/dynamic-candidates.js +98 -0
  20. package/dist/connection-drivers.d.ts +3 -0
  21. package/dist/connection-drivers.js +17 -0
  22. package/dist/connection-recovery.d.ts +34 -0
  23. package/dist/connection-recovery.js +82 -0
  24. package/dist/connection.js +3 -1
  25. package/dist/context/ingest/adapters/historic-sql/bigquery-query-history-reader.js +71 -20
  26. package/dist/context/ingest/adapters/historic-sql/chunk-unified.js +2 -1
  27. package/dist/context/ingest/adapters/historic-sql/connection-dialect.d.ts +9 -0
  28. package/dist/context/ingest/adapters/historic-sql/connection-dialect.js +15 -4
  29. package/dist/context/ingest/adapters/historic-sql/pattern-inputs.js +8 -2
  30. package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.d.ts +29 -0
  31. package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.js +190 -0
  32. package/dist/context/ingest/adapters/historic-sql/scope-floor.d.ts +18 -0
  33. package/dist/context/ingest/adapters/historic-sql/scope-floor.js +229 -0
  34. package/dist/context/ingest/adapters/historic-sql/scope-membership.d.ts +8 -0
  35. package/dist/context/ingest/adapters/historic-sql/scope-membership.js +29 -0
  36. package/dist/context/ingest/adapters/historic-sql/snowflake-query-history-reader.js +68 -19
  37. package/dist/context/ingest/adapters/historic-sql/stage-unified.js +57 -50
  38. package/dist/context/ingest/adapters/historic-sql/types.d.ts +36 -3
  39. package/dist/context/ingest/adapters/historic-sql/types.js +14 -2
  40. package/dist/context/ingest/context-evidence/sqlite-context-evidence-store.d.ts +1 -1
  41. package/dist/context/ingest/ingest-bundle.runner.d.ts +8 -0
  42. package/dist/context/ingest/ingest-bundle.runner.js +72 -15
  43. package/dist/context/ingest/ingest-profile.d.ts +102 -0
  44. package/dist/context/ingest/ingest-profile.js +306 -0
  45. package/dist/context/ingest/isolated-diff/patch-integrator.js +75 -5
  46. package/dist/context/ingest/isolated-diff/work-unit-executor.js +25 -2
  47. package/dist/context/ingest/local-adapters.js +21 -4
  48. package/dist/context/ingest/local-bundle-runtime.js +4 -2
  49. package/dist/context/ingest/local-ingest.d.ts +1 -1
  50. package/dist/context/ingest/local-ingest.js +6 -4
  51. package/dist/context/ingest/memory-flow/events.js +2 -1
  52. package/dist/context/ingest/ports.d.ts +2 -0
  53. package/dist/context/ingest/reports.d.ts +3 -0
  54. package/dist/context/ingest/reports.js +10 -0
  55. package/dist/context/ingest/stages/stage-3-work-units.d.ts +3 -1
  56. package/dist/context/ingest/stages/stage-3-work-units.js +2 -0
  57. package/dist/context/ingest/stages/stage-4-reconciliation.d.ts +2 -1
  58. package/dist/context/ingest/stages/stage-4-reconciliation.js +1 -1
  59. package/dist/context/ingest/tools/tool-call-logger.d.ts +6 -0
  60. package/dist/context/ingest/tools/tool-call-logger.js +36 -1
  61. package/dist/context/llm/ai-sdk-runtime.js +32 -3
  62. package/dist/context/llm/claude-code-runtime.js +35 -2
  63. package/dist/context/llm/codex-exec-events.d.ts +20 -0
  64. package/dist/context/llm/codex-exec-events.js +155 -0
  65. package/dist/context/llm/codex-isolation.d.ts +3 -0
  66. package/dist/context/llm/codex-isolation.js +5 -0
  67. package/dist/context/llm/codex-mcp-runtime-server.d.ts +24 -0
  68. package/dist/context/llm/codex-mcp-runtime-server.js +51 -0
  69. package/dist/context/llm/codex-models.d.ts +2 -0
  70. package/dist/context/llm/codex-models.js +17 -0
  71. package/dist/context/llm/codex-runtime-config.d.ts +16 -0
  72. package/dist/context/llm/codex-runtime-config.js +19 -0
  73. package/dist/context/llm/codex-runtime.d.ts +37 -0
  74. package/dist/context/llm/codex-runtime.js +304 -0
  75. package/dist/context/llm/codex-sdk-runner.d.ts +21 -0
  76. package/dist/context/llm/codex-sdk-runner.js +63 -0
  77. package/dist/context/llm/local-config.d.ts +2 -0
  78. package/dist/context/llm/local-config.js +12 -1
  79. package/dist/context/llm/runtime-port.d.ts +25 -0
  80. package/dist/context/mcp/context-tools.d.ts +2 -1
  81. package/dist/context/mcp/context-tools.js +82 -15
  82. package/dist/context/mcp/server.js +4 -0
  83. package/dist/context/mcp/types.d.ts +15 -1
  84. package/dist/context/project/config.d.ts +3 -0
  85. package/dist/context/project/config.js +6 -2
  86. package/dist/context/project/driver-schemas.js +1 -1
  87. package/dist/context/search/discover.js +4 -3
  88. package/dist/context/sl/local-sl.d.ts +15 -0
  89. package/dist/context/sl/local-sl.js +30 -0
  90. package/dist/context/sql-analysis/http-sql-analysis-port.js +32 -2
  91. package/dist/context/sql-analysis/ports.d.ts +12 -2
  92. package/dist/context/tools/context-candidate-mark.tool.d.ts +2 -2
  93. package/dist/context/wiki/local-knowledge.d.ts +10 -0
  94. package/dist/context/wiki/local-knowledge.js +22 -0
  95. package/dist/context-build-view.d.ts +0 -3
  96. package/dist/context-build-view.js +5 -39
  97. package/dist/ingest.js +7 -10
  98. package/dist/io/buffered-command-io.d.ts +11 -0
  99. package/dist/io/buffered-command-io.js +28 -0
  100. package/dist/knowledge.d.ts +5 -0
  101. package/dist/knowledge.js +10 -1
  102. package/dist/llm/types.d.ts +1 -1
  103. package/dist/local-adapters.d.ts +10 -2
  104. package/dist/local-adapters.js +19 -3
  105. package/dist/next-steps.js +1 -2
  106. package/dist/progress-port-adapter.d.ts +6 -0
  107. package/dist/progress-port-adapter.js +18 -0
  108. package/dist/public-ingest-copy.js +1 -1
  109. package/dist/public-ingest.d.ts +20 -8
  110. package/dist/public-ingest.js +198 -61
  111. package/dist/scan.js +3 -1
  112. package/dist/setup-context.d.ts +2 -0
  113. package/dist/setup-context.js +138 -64
  114. package/dist/setup-databases.d.ts +17 -1
  115. package/dist/setup-databases.js +366 -326
  116. package/dist/setup-models.d.ts +10 -1
  117. package/dist/setup-models.js +90 -2
  118. package/dist/setup-ready-menu.d.ts +16 -2
  119. package/dist/setup-ready-menu.js +37 -5
  120. package/dist/setup-sources.js +141 -33
  121. package/dist/setup.js +24 -12
  122. package/dist/skills/analytics/SKILL.md +6 -1
  123. package/dist/sl.d.ts +6 -1
  124. package/dist/sl.js +32 -8
  125. package/dist/status-project.d.ts +11 -0
  126. package/dist/status-project.js +50 -1
  127. package/dist/telemetry/command-hook.d.ts +1 -0
  128. package/dist/telemetry/command-hook.js +3 -1
  129. package/dist/telemetry/emitter.js +1 -1
  130. package/dist/telemetry/events.d.ts +15 -9
  131. package/dist/telemetry/events.js +17 -5
  132. package/dist/telemetry/identity.d.ts +1 -2
  133. package/dist/telemetry/identity.js +13 -10
  134. package/dist/telemetry/index.d.ts +13 -1
  135. package/dist/telemetry/index.js +18 -3
  136. package/dist/telemetry/scrubber.d.ts +10 -0
  137. package/dist/telemetry/scrubber.js +20 -0
  138. package/package.json +20 -19
  139. package/dist/ingest-depth.d.ts +0 -8
  140. package/dist/ingest-depth.js +0 -56
  141. package/dist/setup-database-context-depth.d.ts +0 -23
  142. package/dist/setup-database-context-depth.js +0 -84
@@ -5,9 +5,10 @@ import { loadKtxProject } from './context/project/project.js';
5
5
  import { markKtxSetupStateStepComplete, readKtxSetupState } from './context/project/setup-config.js';
6
6
  import { serializeKtxProjectConfig } from './context/project/config.js';
7
7
  import { errorMessage, writePrefixedLines } from './clack.js';
8
+ import { formatErrorDetail } from './telemetry/scrubber.js';
8
9
  import { buildPublicIngestPlan } from './public-ingest.js';
9
- import { databaseContextDepth, } from './ingest-depth.js';
10
- import { ensureSetupDatabaseContextDepths } from './setup-database-context-depth.js';
10
+ import { runKtxConnection } from './connection.js';
11
+ import { createBufferedCommandIo } from './io/buffered-command-io.js';
11
12
  import { runContextBuild, } from './context-build-view.js';
12
13
  import { createKtxSetupPromptAdapter, } from './setup-prompts.js';
13
14
  const SETUP_CONTEXT_STATE_PATH = ['.ktx', 'setup', 'context-build.json'];
@@ -171,6 +172,98 @@ function listContextTargets(project) {
171
172
  .map((target) => target.connectionId),
172
173
  };
173
174
  }
175
+ function requiredConnectionIds(targets) {
176
+ return [...targets.primarySourceConnectionIds, ...targets.contextSourceConnectionIds];
177
+ }
178
+ function connectorTypeLabel(project, connectionId) {
179
+ const driver = String(project.config.connections[connectionId]?.driver ?? '')
180
+ .trim()
181
+ .toLowerCase();
182
+ return driver.length > 0 ? driver : 'unknown';
183
+ }
184
+ async function defaultGateTestConnection(projectDir, connectionId, io) {
185
+ return await runKtxConnection({ command: 'test', projectDir, connectionId }, io);
186
+ }
187
+ /**
188
+ * Runs a live connection test for every connection the build depends on. Each
189
+ * test's output is captured in a buffer and discarded so raw error text never
190
+ * reaches the user — callers surface only the connection id and connector type.
191
+ */
192
+ async function testRequiredConnections(projectDir, project, targets, testConnection) {
193
+ const failures = [];
194
+ for (const connectionId of requiredConnectionIds(targets)) {
195
+ const buffered = createBufferedCommandIo();
196
+ const exitCode = await testConnection(projectDir, connectionId, buffered);
197
+ if (exitCode !== 0) {
198
+ failures.push({ connectionId, driver: connectorTypeLabel(project, connectionId) });
199
+ }
200
+ }
201
+ return failures.length === 0 ? { ok: true } : { ok: false, failures };
202
+ }
203
+ /**
204
+ * Loads the project and resolves the connections the build depends on, applying
205
+ * the empty-targets and preflight-capability checks. Used both on first entry
206
+ * and on interactive retry so a fix that adds, removes, or reconfigures a
207
+ * connection is honored.
208
+ */
209
+ async function prepareBuildTargets(args, io) {
210
+ const project = await loadKtxProject({ projectDir: args.projectDir });
211
+ const targets = listContextTargets(project);
212
+ if (targets.primarySourceConnectionIds.length === 0 && targets.contextSourceConnectionIds.length === 0) {
213
+ if (args.allowEmpty === true) {
214
+ return { kind: 'result', result: { status: 'skipped', projectDir: args.projectDir } };
215
+ }
216
+ io.stderr.write('No databases or context sources are configured for a KTX context build.\n');
217
+ return { kind: 'result', result: { status: 'failed', projectDir: args.projectDir } };
218
+ }
219
+ const preflightPlan = buildPublicIngestPlan(project, { projectDir: project.projectDir, all: true });
220
+ const preflightFailures = preflightPlan.targets.flatMap((target) => target.preflightFailure ? [`${target.connectionId}: ${target.preflightFailure}`] : []);
221
+ if (preflightFailures.length > 0) {
222
+ if (args.allowEmpty === true) {
223
+ return { kind: 'result', result: { status: 'skipped', projectDir: args.projectDir } };
224
+ }
225
+ writeMissingCapabilities(preflightFailures, io);
226
+ return { kind: 'result', result: { status: 'missing-input', projectDir: args.projectDir } };
227
+ }
228
+ return { kind: 'ready', project, targets };
229
+ }
230
+ function writeConnectionGateFailureLines(io, projectDir, failures) {
231
+ io.stderr.write('KTX cannot build context: a required connection failed its live test.\n\n');
232
+ io.stderr.write('Failed connections:\n');
233
+ for (const failure of failures) {
234
+ io.stderr.write(` ${failure.connectionId} (${failure.driver})\n`);
235
+ }
236
+ io.stderr.write('\nEach connection must be reachable before KTX builds context.\n');
237
+ io.stderr.write(`Run \`ktx connection test <id> --project-dir ${resolve(projectDir)}\` to see the error, fix the connection, then retry.\n`);
238
+ }
239
+ function connectionGateFailureReason(failures) {
240
+ const names = failures.map((failure) => `${failure.connectionId} (${failure.driver})`).join(', ');
241
+ return `Required connections failed their live test: ${names}.`;
242
+ }
243
+ async function writeConnectionGateFailedState(args, deps, targets, failures) {
244
+ const at = (deps.now ?? (() => new Date()))().toISOString();
245
+ await writeKtxSetupContextState(args.projectDir, {
246
+ status: 'failed',
247
+ startedAt: at,
248
+ updatedAt: at,
249
+ primarySourceConnectionIds: targets.primarySourceConnectionIds,
250
+ contextSourceConnectionIds: targets.contextSourceConnectionIds,
251
+ reportIds: [],
252
+ artifactPaths: [],
253
+ retryableFailedTargets: [],
254
+ commands: contextBuildCommands(args.projectDir),
255
+ failureReason: connectionGateFailureReason(failures),
256
+ });
257
+ }
258
+ async function promptConnectionGateRetry(prompts) {
259
+ return (await prompts.select({
260
+ message: 'Fix the failing connection, then choose how to proceed.',
261
+ options: [
262
+ { value: 'retry', label: 'Retry connection tests' },
263
+ { value: 'back', label: 'Back' },
264
+ ],
265
+ }));
266
+ }
174
267
  async function hasFileWithExtension(root, extensions, options = {}) {
175
268
  if (!(await pathExists(root))) {
176
269
  return false;
@@ -232,15 +325,6 @@ async function readLatestScanReport(projectDir, connectionId) {
232
325
  reports.sort((left, right) => left.sortKey.localeCompare(right.sortKey));
233
326
  return reports.at(-1)?.report ?? null;
234
327
  }
235
- function scanReportHasSchemaManifest(report, connectionId) {
236
- if (!isRecord(report)) {
237
- return false;
238
- }
239
- if (report.connectionId !== connectionId || report.dryRun === true) {
240
- return false;
241
- }
242
- return stringArrayValue(isRecord(report.artifactPaths) ? report.artifactPaths.manifestShards : undefined).length > 0;
243
- }
244
328
  function scanReportHasCompletedDeepEnrichment(report, connectionId, relationshipsRequired) {
245
329
  if (!isRecord(report)) {
246
330
  return false;
@@ -260,23 +344,13 @@ function scanReportHasCompletedDeepEnrichment(report, connectionId, relationship
260
344
  (!relationshipsRequired || completedStages.includes('relationships')) &&
261
345
  stringArrayValue(report.artifactPaths.manifestShards).length > 0);
262
346
  }
263
- function scanReportSatisfiesDepth(input) {
264
- if (input.depth === 'fast') {
265
- return scanReportHasSchemaManifest(input.report, input.connectionId);
266
- }
267
- return scanReportHasCompletedDeepEnrichment(input.report, input.connectionId, input.relationshipsRequired);
268
- }
269
347
  async function verifyPrimarySourceScans(project, connectionIds) {
270
348
  const details = [];
271
349
  const relationshipsRequired = project.config.scan.relationships.enabled;
272
350
  for (const connectionId of connectionIds) {
273
- const connection = project.config.connections[connectionId];
274
- const depth = connection ? (databaseContextDepth(connection) ?? 'fast') : 'fast';
275
351
  const report = await readLatestScanReport(project.projectDir, connectionId);
276
- if (!scanReportSatisfiesDepth({ report, connectionId, depth, relationshipsRequired })) {
277
- details.push(depth === 'fast'
278
- ? `${connectionId}: schema context has not completed.`
279
- : `${connectionId}: deep database context has not completed.`);
352
+ if (!scanReportHasCompletedDeepEnrichment(report, connectionId, relationshipsRequired)) {
353
+ details.push(`${connectionId}: database context has not completed.`);
280
354
  }
281
355
  }
282
356
  return { ready: details.length === 0, details };
@@ -324,14 +398,12 @@ function writeMissingCapabilities(missing, io) {
324
398
  }
325
399
  io.stderr.write('\nFix this in setup before building context.\n');
326
400
  }
327
- function writeSkippedContext(projectDir, io) {
328
- io.stdout.write('\nKTX is configured, but context has not been built yet.\n\n');
329
- io.stdout.write('Agents were not connected because KTX has not prepared searchable context for them.\n\n');
330
- io.stdout.write(`Resume setup:\n ktx setup --project-dir ${resolve(projectDir)}\n\n`);
331
- io.stdout.write(`Build context:\n ktx setup --project-dir ${resolve(projectDir)}\n\n`);
332
- io.stdout.write(`Check status:\n ktx status --project-dir ${resolve(projectDir)}\n`);
401
+ function writeSkippedContext(io) {
402
+ // The setup completion screen owns "what to do next" (it points at `ktx ingest`),
403
+ // so keep this to a short acknowledgement rather than a competing command list.
404
+ io.stdout.write('\nLeaving context unbuilt for now.\n');
333
405
  }
334
- function writeSuccess(project, readiness, targets, io) {
406
+ function writeSuccess(readiness, targets, io) {
335
407
  io.stdout.write('\nKTX context is ready for agents.\n\n');
336
408
  io.stdout.write('Databases:\n');
337
409
  if (targets.primarySourceConnectionIds.length === 0) {
@@ -339,9 +411,7 @@ function writeSuccess(project, readiness, targets, io) {
339
411
  }
340
412
  else {
341
413
  for (const connectionId of targets.primarySourceConnectionIds) {
342
- const connection = project.config.connections[connectionId];
343
- const depth = connection ? (databaseContextDepth(connection) ?? 'fast') : 'fast';
344
- io.stdout.write(` ${connectionId}: ${depth === 'deep' ? 'deep context complete' : 'schema context complete'}\n`);
414
+ io.stdout.write(` ${connectionId}: database context complete\n`);
345
415
  }
346
416
  }
347
417
  io.stdout.write('\nContext sources:\n');
@@ -466,7 +536,7 @@ async function runBuild(args, io, deps, project, targets) {
466
536
  failureReason: undefined,
467
537
  ...(lastSourceProgress ? { sourceProgress: lastSourceProgress } : {}),
468
538
  });
469
- writeSuccess(project, readiness, targets, io);
539
+ writeSuccess(readiness, targets, io);
470
540
  return { status: 'ready', projectDir: args.projectDir, runId };
471
541
  }
472
542
  async function completeExistingContext(args, io, deps, targets) {
@@ -496,17 +566,7 @@ async function completeExistingContext(args, io, deps, targets) {
496
566
  }
497
567
  export async function runKtxSetupContextStep(args, io, deps = {}) {
498
568
  try {
499
- let project = await loadKtxProject({ projectDir: args.projectDir });
500
569
  const prompts = deps.prompts ?? createPromptAdapter();
501
- const depthProject = await ensureSetupDatabaseContextDepths({
502
- project,
503
- args,
504
- prompts,
505
- });
506
- if (depthProject === 'back') {
507
- return { status: 'back', projectDir: args.projectDir };
508
- }
509
- project = depthProject;
510
570
  const existingState = await readKtxSetupContextState(args.projectDir);
511
571
  const completedSteps = (await readKtxSetupState(args.projectDir)).completed_steps;
512
572
  if (completedSteps.includes('context') && existingState.status === 'completed') {
@@ -519,43 +579,57 @@ export async function runKtxSetupContextStep(args, io, deps = {}) {
519
579
  if (existingState.status === 'stale') {
520
580
  io.stdout.write('Previous context build state is stale; starting a fresh foreground build.\n');
521
581
  }
522
- const targets = listContextTargets(project);
523
- if (targets.primarySourceConnectionIds.length === 0 && targets.contextSourceConnectionIds.length === 0) {
524
- if (args.allowEmpty === true) {
525
- return { status: 'skipped', projectDir: args.projectDir };
526
- }
527
- io.stderr.write('No databases or context sources are configured for a KTX context build.\n');
528
- return { status: 'failed', projectDir: args.projectDir };
529
- }
530
- const preflightPlan = buildPublicIngestPlan(project, { projectDir: project.projectDir, all: true });
531
- const preflightFailures = preflightPlan.targets.flatMap((target) => target.preflightFailure ? [`${target.connectionId}: ${target.preflightFailure}`] : []);
532
- if (preflightFailures.length > 0) {
533
- if (args.allowEmpty === true) {
534
- return { status: 'skipped', projectDir: args.projectDir };
535
- }
536
- writeMissingCapabilities(preflightFailures, io);
537
- return { status: 'missing-input', projectDir: args.projectDir };
582
+ const prepared = await prepareBuildTargets(args, io);
583
+ if (prepared.kind === 'result') {
584
+ return prepared.result;
538
585
  }
586
+ let { project, targets } = prepared;
587
+ const interactive = args.inputMode !== 'disabled' && args.prompt !== false;
539
588
  if (args.forcePrompt !== true && args.prompt !== false && deps.verifyContextReady === undefined) {
540
589
  const existingContextResult = await completeExistingContext(args, io, deps, targets);
541
590
  if (existingContextResult) {
542
591
  return existingContextResult;
543
592
  }
544
593
  }
545
- if (args.inputMode !== 'disabled' && args.prompt !== false) {
594
+ if (interactive) {
546
595
  const choice = await promptForBuild(prompts);
547
596
  if (choice === 'back') {
548
597
  return { status: 'back', projectDir: args.projectDir };
549
598
  }
550
599
  if (choice === 'skip') {
551
- writeSkippedContext(args.projectDir, io);
600
+ writeSkippedContext(io);
552
601
  return { status: 'skipped', projectDir: args.projectDir };
553
602
  }
554
603
  }
555
- return await runBuild(args, io, deps, project, targets);
604
+ // Live-connection gate: every connection the build depends on must pass a
605
+ // live test before the (expensive) build starts. A red connection is a hard
606
+ // stop — we surface only the connection id and connector type, never raw
607
+ // error text.
608
+ const testConnection = deps.testConnection ?? defaultGateTestConnection;
609
+ while (true) {
610
+ const gate = await testRequiredConnections(args.projectDir, project, targets, testConnection);
611
+ if (gate.ok) {
612
+ return await runBuild(args, io, deps, project, targets);
613
+ }
614
+ writeConnectionGateFailureLines(io, args.projectDir, gate.failures);
615
+ if (!interactive) {
616
+ await writeConnectionGateFailedState(args, deps, targets, gate.failures);
617
+ return { status: 'failed', projectDir: args.projectDir };
618
+ }
619
+ const choice = await promptConnectionGateRetry(prompts);
620
+ if (choice === 'back') {
621
+ return { status: 'back', projectDir: args.projectDir };
622
+ }
623
+ const reprepared = await prepareBuildTargets(args, io);
624
+ if (reprepared.kind === 'result') {
625
+ return reprepared.result;
626
+ }
627
+ project = reprepared.project;
628
+ targets = reprepared.targets;
629
+ }
556
630
  }
557
631
  catch (error) {
558
632
  writePrefixedLines((chunk) => io.stderr.write(chunk), errorMessage(error));
559
- return { status: 'failed', projectDir: args.projectDir };
633
+ return { status: 'failed', projectDir: args.projectDir, errorDetail: formatErrorDetail(error) };
560
634
  }
561
635
  }
@@ -1,12 +1,20 @@
1
+ import type { KtxLlmRuntimePort } from './context/llm/runtime-port.js';
2
+ import { type ProposeQueryHistoryServiceAccountFiltersInput, type QueryHistoryFilterProposal } from './context/ingest/adapters/historic-sql/query-history-filter-picker.js';
1
3
  import { type HistoricSqlReadinessProbe } from './context/ingest/historic-sql-probes.js';
4
+ import { loadKtxProject } from './context/project/project.js';
2
5
  import type { KtxTableListEntry } from './context/scan/types.js';
3
- import type { KtxCliIo } from './cli-runtime.js';
6
+ import { type KtxCliIo } from './cli-runtime.js';
4
7
  import { type DatabaseScopePickResult, type PickDatabaseScopeArgs } from './database-tree-picker.js';
8
+ import type { KtxManagedPythonInstallPolicy } from './managed-python-command.js';
9
+ import type { ManagedPythonCoreDaemonOptions } from './managed-python-http.js';
5
10
  import { type KtxSetupPromptOption } from './setup-prompts.js';
6
11
  export type KtxSetupDatabaseDriver = 'sqlite' | 'postgres' | 'mysql' | 'clickhouse' | 'sqlserver' | 'bigquery' | 'snowflake';
7
12
  export interface KtxSetupDatabasesArgs {
8
13
  projectDir: string;
9
14
  inputMode: 'auto' | 'disabled';
15
+ yes?: boolean;
16
+ cliVersion?: string;
17
+ runtimeInstallPolicy?: KtxManagedPythonInstallPolicy;
10
18
  databaseDrivers?: KtxSetupDatabaseDriver[];
11
19
  databaseConnectionIds?: string[];
12
20
  databaseConnectionId?: string;
@@ -77,5 +85,13 @@ export interface KtxSetupDatabasesDeps {
77
85
  listTables?: (projectDir: string, connectionId: string, schemas?: string[]) => Promise<KtxTableListEntry[]>;
78
86
  pickDatabaseScope?: (args: PickDatabaseScopeArgs, io: KtxCliIo) => Promise<DatabaseScopePickResult>;
79
87
  historicSqlReadinessProbe?: HistoricSqlReadinessProbe;
88
+ queryHistoryFilterPicker?: (input: ProposeQueryHistoryServiceAccountFiltersInput) => Promise<QueryHistoryFilterProposal>;
89
+ createQueryHistoryLlmRuntime?: (projectDir: string, project: Awaited<ReturnType<typeof loadKtxProject>>) => KtxLlmRuntimePort | null;
80
90
  }
91
+ /** @internal */
92
+ export declare function managedDaemonOptionsForSetupQueryHistoryPicker(input: {
93
+ projectDir: string;
94
+ args: Pick<KtxSetupDatabasesArgs, 'cliVersion' | 'runtimeInstallPolicy' | 'inputMode'>;
95
+ io: KtxCliIo;
96
+ }): ManagedPythonCoreDaemonOptions;
81
97
  export declare function runKtxSetupDatabasesStep(args: KtxSetupDatabasesArgs, io: KtxCliIo, deps?: KtxSetupDatabasesDeps): Promise<KtxSetupDatabasesResult>;