@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.
- package/assets/python/{kaelio_ktx-0.7.0-py3-none-any.whl → kaelio_ktx-0.9.0-py3-none-any.whl} +0 -0
- package/assets/python/manifest.json +4 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli-program.js +7 -0
- package/dist/cli-runtime.js +50 -3
- package/dist/command-schemas.d.ts +1 -1
- package/dist/command-tree.js +5 -1
- package/dist/commands/completion-commands.d.ts +3 -0
- package/dist/commands/completion-commands.js +38 -0
- package/dist/commands/ingest-commands.js +0 -4
- package/dist/commands/knowledge-commands.js +15 -2
- package/dist/commands/setup-commands.js +3 -3
- package/dist/commands/sl-commands.js +19 -7
- package/dist/completion/complete-engine.d.ts +19 -0
- package/dist/completion/complete-engine.js +128 -0
- package/dist/completion/completion-scripts.d.ts +1 -0
- package/dist/completion/completion-scripts.js +36 -0
- package/dist/completion/dynamic-candidates.d.ts +6 -0
- package/dist/completion/dynamic-candidates.js +98 -0
- package/dist/connection-drivers.d.ts +3 -0
- package/dist/connection-drivers.js +17 -0
- package/dist/connection-recovery.d.ts +34 -0
- package/dist/connection-recovery.js +82 -0
- package/dist/connection.js +3 -1
- package/dist/context/ingest/adapters/historic-sql/bigquery-query-history-reader.js +71 -20
- package/dist/context/ingest/adapters/historic-sql/chunk-unified.js +2 -1
- package/dist/context/ingest/adapters/historic-sql/connection-dialect.d.ts +9 -0
- package/dist/context/ingest/adapters/historic-sql/connection-dialect.js +15 -4
- package/dist/context/ingest/adapters/historic-sql/pattern-inputs.js +8 -2
- package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.d.ts +29 -0
- package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.js +190 -0
- package/dist/context/ingest/adapters/historic-sql/scope-floor.d.ts +18 -0
- package/dist/context/ingest/adapters/historic-sql/scope-floor.js +229 -0
- package/dist/context/ingest/adapters/historic-sql/scope-membership.d.ts +8 -0
- package/dist/context/ingest/adapters/historic-sql/scope-membership.js +29 -0
- package/dist/context/ingest/adapters/historic-sql/snowflake-query-history-reader.js +68 -19
- package/dist/context/ingest/adapters/historic-sql/stage-unified.js +57 -50
- package/dist/context/ingest/adapters/historic-sql/types.d.ts +36 -3
- package/dist/context/ingest/adapters/historic-sql/types.js +14 -2
- package/dist/context/ingest/context-evidence/sqlite-context-evidence-store.d.ts +1 -1
- package/dist/context/ingest/ingest-bundle.runner.d.ts +8 -0
- package/dist/context/ingest/ingest-bundle.runner.js +72 -15
- package/dist/context/ingest/ingest-profile.d.ts +102 -0
- package/dist/context/ingest/ingest-profile.js +306 -0
- package/dist/context/ingest/isolated-diff/patch-integrator.js +75 -5
- package/dist/context/ingest/isolated-diff/work-unit-executor.js +25 -2
- package/dist/context/ingest/local-adapters.js +21 -4
- package/dist/context/ingest/local-bundle-runtime.js +4 -2
- package/dist/context/ingest/local-ingest.d.ts +1 -1
- package/dist/context/ingest/local-ingest.js +6 -4
- package/dist/context/ingest/memory-flow/events.js +2 -1
- package/dist/context/ingest/ports.d.ts +2 -0
- package/dist/context/ingest/reports.d.ts +3 -0
- package/dist/context/ingest/reports.js +10 -0
- package/dist/context/ingest/stages/stage-3-work-units.d.ts +3 -1
- package/dist/context/ingest/stages/stage-3-work-units.js +2 -0
- package/dist/context/ingest/stages/stage-4-reconciliation.d.ts +2 -1
- package/dist/context/ingest/stages/stage-4-reconciliation.js +1 -1
- package/dist/context/ingest/tools/tool-call-logger.d.ts +6 -0
- package/dist/context/ingest/tools/tool-call-logger.js +36 -1
- package/dist/context/llm/ai-sdk-runtime.js +32 -3
- package/dist/context/llm/claude-code-runtime.js +35 -2
- package/dist/context/llm/codex-exec-events.d.ts +20 -0
- package/dist/context/llm/codex-exec-events.js +155 -0
- package/dist/context/llm/codex-isolation.d.ts +3 -0
- package/dist/context/llm/codex-isolation.js +5 -0
- package/dist/context/llm/codex-mcp-runtime-server.d.ts +24 -0
- package/dist/context/llm/codex-mcp-runtime-server.js +51 -0
- package/dist/context/llm/codex-models.d.ts +2 -0
- package/dist/context/llm/codex-models.js +17 -0
- package/dist/context/llm/codex-runtime-config.d.ts +16 -0
- package/dist/context/llm/codex-runtime-config.js +19 -0
- package/dist/context/llm/codex-runtime.d.ts +37 -0
- package/dist/context/llm/codex-runtime.js +304 -0
- package/dist/context/llm/codex-sdk-runner.d.ts +21 -0
- package/dist/context/llm/codex-sdk-runner.js +63 -0
- package/dist/context/llm/local-config.d.ts +2 -0
- package/dist/context/llm/local-config.js +12 -1
- package/dist/context/llm/runtime-port.d.ts +25 -0
- package/dist/context/mcp/context-tools.d.ts +2 -1
- package/dist/context/mcp/context-tools.js +82 -15
- package/dist/context/mcp/server.js +4 -0
- package/dist/context/mcp/types.d.ts +15 -1
- package/dist/context/project/config.d.ts +3 -0
- package/dist/context/project/config.js +6 -2
- package/dist/context/project/driver-schemas.js +1 -1
- package/dist/context/search/discover.js +4 -3
- package/dist/context/sl/local-sl.d.ts +15 -0
- package/dist/context/sl/local-sl.js +30 -0
- package/dist/context/sql-analysis/http-sql-analysis-port.js +32 -2
- package/dist/context/sql-analysis/ports.d.ts +12 -2
- package/dist/context/tools/context-candidate-mark.tool.d.ts +2 -2
- package/dist/context/wiki/local-knowledge.d.ts +10 -0
- package/dist/context/wiki/local-knowledge.js +22 -0
- package/dist/context-build-view.d.ts +0 -3
- package/dist/context-build-view.js +5 -39
- package/dist/ingest.js +7 -10
- package/dist/io/buffered-command-io.d.ts +11 -0
- package/dist/io/buffered-command-io.js +28 -0
- package/dist/knowledge.d.ts +5 -0
- package/dist/knowledge.js +10 -1
- package/dist/llm/types.d.ts +1 -1
- package/dist/local-adapters.d.ts +10 -2
- package/dist/local-adapters.js +19 -3
- package/dist/next-steps.js +1 -2
- package/dist/progress-port-adapter.d.ts +6 -0
- package/dist/progress-port-adapter.js +18 -0
- package/dist/public-ingest-copy.js +1 -1
- package/dist/public-ingest.d.ts +20 -8
- package/dist/public-ingest.js +198 -61
- package/dist/scan.js +3 -1
- package/dist/setup-context.d.ts +2 -0
- package/dist/setup-context.js +138 -64
- package/dist/setup-databases.d.ts +17 -1
- package/dist/setup-databases.js +366 -326
- package/dist/setup-models.d.ts +10 -1
- package/dist/setup-models.js +90 -2
- package/dist/setup-ready-menu.d.ts +16 -2
- package/dist/setup-ready-menu.js +37 -5
- package/dist/setup-sources.js +141 -33
- package/dist/setup.js +24 -12
- package/dist/skills/analytics/SKILL.md +6 -1
- package/dist/sl.d.ts +6 -1
- package/dist/sl.js +32 -8
- package/dist/status-project.d.ts +11 -0
- package/dist/status-project.js +50 -1
- package/dist/telemetry/command-hook.d.ts +1 -0
- package/dist/telemetry/command-hook.js +3 -1
- package/dist/telemetry/emitter.js +1 -1
- package/dist/telemetry/events.d.ts +15 -9
- package/dist/telemetry/events.js +17 -5
- package/dist/telemetry/identity.d.ts +1 -2
- package/dist/telemetry/identity.js +13 -10
- package/dist/telemetry/index.d.ts +13 -1
- package/dist/telemetry/index.js +18 -3
- package/dist/telemetry/scrubber.d.ts +10 -0
- package/dist/telemetry/scrubber.js +20 -0
- package/package.json +20 -19
- package/dist/ingest-depth.d.ts +0 -8
- package/dist/ingest-depth.js +0 -56
- package/dist/setup-database-context-depth.d.ts +0 -23
- package/dist/setup-database-context-depth.js +0 -84
package/dist/setup-context.js
CHANGED
|
@@ -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 {
|
|
10
|
-
import {
|
|
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 (!
|
|
277
|
-
details.push(
|
|
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(
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
io.stdout.write(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
|
523
|
-
if (
|
|
524
|
-
|
|
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 (
|
|
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(
|
|
600
|
+
writeSkippedContext(io);
|
|
552
601
|
return { status: 'skipped', projectDir: args.projectDir };
|
|
553
602
|
}
|
|
554
603
|
}
|
|
555
|
-
|
|
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
|
|
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>;
|