@kaelio/ktx 0.6.0 → 0.8.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.6.0-py3-none-any.whl → kaelio_ktx-0.8.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/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 +2 -2
- 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/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/work-unit-executor.js +25 -2
- package/dist/context/ingest/local-bundle-runtime.js +1 -0
- 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 +51 -3
- 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 +1 -0
- package/dist/context/project/config.js +4 -0
- 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/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 +1 -7
- package/dist/ingest.js +7 -10
- package/dist/knowledge.d.ts +5 -0
- package/dist/knowledge.js +10 -1
- package/dist/public-ingest-copy.js +1 -1
- package/dist/public-ingest.d.ts +0 -7
- package/dist/public-ingest.js +20 -34
- package/dist/setup-context.js +6 -38
- package/dist/setup-databases.js +13 -82
- package/dist/setup-project.d.ts +0 -8
- package/dist/setup-project.js +3 -27
- package/dist/setup-sources.js +33 -5
- package/dist/setup.js +3 -16
- package/dist/skills/analytics/SKILL.md +6 -1
- package/dist/sl.d.ts +6 -1
- package/dist/sl.js +32 -8
- package/dist/telemetry/emitter.js +1 -1
- package/dist/telemetry/events.d.ts +4 -3
- package/dist/telemetry/events.js +7 -3
- package/dist/telemetry/identity.d.ts +1 -1
- package/dist/telemetry/identity.js +13 -10
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.js +5 -1
- package/package.json +22 -22
- 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/public-ingest.d.ts
CHANGED
|
@@ -2,14 +2,12 @@ import { type KtxLocalProject } from './context/project/project.js';
|
|
|
2
2
|
import type { KtxProgressPort } from './context/scan/types.js';
|
|
3
3
|
import type { KtxCliIo } from './index.js';
|
|
4
4
|
import type { KtxIngestArgs, KtxIngestDeps, KtxIngestProgressUpdate } from './ingest.js';
|
|
5
|
-
import { type KtxDatabaseContextDepth } from './ingest-depth.js';
|
|
6
5
|
import { type KtxManagedPythonInstallPolicy, type ManagedPythonCommandRuntime } from './managed-python-command.js';
|
|
7
6
|
import type { KtxRuntimeFeature } from './managed-python-runtime.js';
|
|
8
7
|
import type { KtxScanArgs, KtxScanDeps } from './scan.js';
|
|
9
8
|
type KtxPublicIngestStepName = 'database-schema' | 'query-history' | 'source-ingest' | 'memory-update';
|
|
10
9
|
type KtxPublicIngestStepStatus = 'done' | 'skipped' | 'failed' | 'not-run';
|
|
11
10
|
type KtxPublicIngestInputMode = 'auto' | 'disabled';
|
|
12
|
-
type KtxPublicIngestDepth = KtxDatabaseContextDepth;
|
|
13
11
|
type KtxPublicIngestQueryHistoryFlag = 'default' | 'enabled' | 'disabled';
|
|
14
12
|
type HistoricSqlDialect = 'postgres' | 'bigquery' | 'snowflake';
|
|
15
13
|
export type KtxPublicIngestArgs = {
|
|
@@ -19,7 +17,6 @@ export type KtxPublicIngestArgs = {
|
|
|
19
17
|
all: boolean;
|
|
20
18
|
json: boolean;
|
|
21
19
|
inputMode: KtxPublicIngestInputMode;
|
|
22
|
-
depth?: KtxPublicIngestDepth;
|
|
23
20
|
queryHistory?: KtxPublicIngestQueryHistoryFlag;
|
|
24
21
|
queryHistoryWindowDays?: number;
|
|
25
22
|
scanMode?: Extract<KtxScanArgs, {
|
|
@@ -37,7 +34,6 @@ export interface KtxPublicIngestPlanTarget {
|
|
|
37
34
|
sourceDir?: string;
|
|
38
35
|
debugCommand: string;
|
|
39
36
|
steps: KtxPublicIngestStepName[];
|
|
40
|
-
databaseDepth?: KtxPublicIngestDepth;
|
|
41
37
|
detectRelationships?: boolean;
|
|
42
38
|
preflightFailure?: string;
|
|
43
39
|
queryHistory?: {
|
|
@@ -46,7 +42,6 @@ export interface KtxPublicIngestPlanTarget {
|
|
|
46
42
|
windowDays?: number;
|
|
47
43
|
pullConfig?: Record<string, unknown>;
|
|
48
44
|
unsupported?: boolean;
|
|
49
|
-
skippedStoredByFast?: boolean;
|
|
50
45
|
};
|
|
51
46
|
}
|
|
52
47
|
export interface KtxPublicIngestPlan {
|
|
@@ -94,7 +89,6 @@ interface KtxPublicContextBuildArgs {
|
|
|
94
89
|
inputMode: 'auto' | 'disabled';
|
|
95
90
|
targetConnectionId?: string;
|
|
96
91
|
all?: boolean;
|
|
97
|
-
depth?: KtxPublicIngestDepth;
|
|
98
92
|
queryHistory?: KtxPublicIngestQueryHistoryFlag;
|
|
99
93
|
queryHistoryWindowDays?: number;
|
|
100
94
|
scanMode?: Extract<KtxScanArgs, {
|
|
@@ -108,7 +102,6 @@ export declare function buildPublicIngestPlan(project: KtxPublicIngestProject, a
|
|
|
108
102
|
projectDir: string;
|
|
109
103
|
targetConnectionId?: string;
|
|
110
104
|
all: boolean;
|
|
111
|
-
depth?: KtxPublicIngestDepth;
|
|
112
105
|
queryHistory?: KtxPublicIngestQueryHistoryFlag;
|
|
113
106
|
queryHistoryWindowDays?: number;
|
|
114
107
|
scanMode?: Extract<KtxScanArgs, {
|
package/dist/public-ingest.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getKtxCliPackageInfo } from './cli-runtime.js';
|
|
2
2
|
import { loadKtxProject } from './context/project/project.js';
|
|
3
|
-
import {
|
|
3
|
+
import { isDatabaseDriver, normalizeConnectionDriver } from './connection-drivers.js';
|
|
4
4
|
import { ensureManagedPythonCommandRuntime, } from './managed-python-command.js';
|
|
5
5
|
import { publicIngestOutputLine } from './public-ingest-copy.js';
|
|
6
6
|
import { resolvePublicIngestRuntimeRequirements } from './runtime-requirements.js';
|
|
@@ -25,7 +25,6 @@ const queryHistoryDialectByDriver = new Map([
|
|
|
25
25
|
function createWarningAccumulator() {
|
|
26
26
|
return {
|
|
27
27
|
warnings: [],
|
|
28
|
-
ignoredDepthForSources: [],
|
|
29
28
|
ignoredQueryHistoryForSources: [],
|
|
30
29
|
unsupportedQueryHistoryForDatabases: [],
|
|
31
30
|
};
|
|
@@ -71,12 +70,6 @@ function finalizeWarnings(accumulator, args) {
|
|
|
71
70
|
...accumulator.warnings,
|
|
72
71
|
...unsupportedQueryHistoryWarnings(accumulator.unsupportedQueryHistoryForDatabases, args.all),
|
|
73
72
|
];
|
|
74
|
-
const depthOption = args.depth ? `--${args.depth}` : null;
|
|
75
|
-
if (depthOption) {
|
|
76
|
-
const warning = sourceIgnoredWarning(depthOption, accumulator.ignoredDepthForSources, args.all);
|
|
77
|
-
if (warning)
|
|
78
|
-
warnings.push(warning);
|
|
79
|
-
}
|
|
80
73
|
if (args.queryHistory === 'enabled' || args.queryHistoryWindowDays !== undefined) {
|
|
81
74
|
const warning = sourceIgnoredWarning('--query-history', accumulator.ignoredQueryHistoryForSources, args.all);
|
|
82
75
|
if (warning)
|
|
@@ -135,7 +128,6 @@ function resolveDatabaseTargetOptions(input) {
|
|
|
135
128
|
const windowOverrideRequested = input.args.queryHistoryWindowDays !== undefined;
|
|
136
129
|
const requestedQh = explicitQueryHistory === 'enabled' ||
|
|
137
130
|
(explicitQueryHistory !== 'disabled' && (windowOverrideRequested || storedEnabled));
|
|
138
|
-
let depth = input.args.depth ?? databaseContextDepth(input.connection) ?? 'fast';
|
|
139
131
|
const queryHistory = {
|
|
140
132
|
enabled: false,
|
|
141
133
|
...(input.args.queryHistoryWindowDays !== undefined
|
|
@@ -151,18 +143,12 @@ function resolveDatabaseTargetOptions(input) {
|
|
|
151
143
|
reason: explicitQueryHistory === 'enabled' || input.args.queryHistoryWindowDays !== undefined ? 'explicit' : 'stored',
|
|
152
144
|
});
|
|
153
145
|
return {
|
|
154
|
-
databaseDepth: depth,
|
|
155
146
|
queryHistory: { ...queryHistory, unsupported: true },
|
|
156
147
|
steps: ['database-schema'],
|
|
157
148
|
};
|
|
158
149
|
}
|
|
159
150
|
if (requestedQh && dialect) {
|
|
160
|
-
if (depth === 'fast') {
|
|
161
|
-
input.warnings.warnings.push(`--query-history requires deep ingest; running ${input.connectionId} with --deep.`);
|
|
162
|
-
}
|
|
163
|
-
depth = 'deep';
|
|
164
151
|
return {
|
|
165
|
-
databaseDepth: depth,
|
|
166
152
|
queryHistory: {
|
|
167
153
|
...queryHistory,
|
|
168
154
|
enabled: true,
|
|
@@ -177,28 +163,30 @@ function resolveDatabaseTargetOptions(input) {
|
|
|
177
163
|
steps: ['database-schema', 'query-history'],
|
|
178
164
|
};
|
|
179
165
|
}
|
|
180
|
-
if (input.args.depth === 'fast' && explicitQueryHistory !== 'enabled' && storedEnabled) {
|
|
181
|
-
input.warnings.warnings.push(`${input.connectionId} has query history enabled in ktx.yaml, but --fast skips query-history processing.`);
|
|
182
|
-
return {
|
|
183
|
-
databaseDepth: 'fast',
|
|
184
|
-
queryHistory: { ...queryHistory, skippedStoredByFast: true },
|
|
185
|
-
steps: ['database-schema'],
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
166
|
return {
|
|
189
|
-
databaseDepth: depth,
|
|
190
167
|
queryHistory,
|
|
191
168
|
steps: ['database-schema'],
|
|
192
169
|
};
|
|
193
170
|
}
|
|
171
|
+
function enrichmentReadinessGaps(config) {
|
|
172
|
+
const gaps = [];
|
|
173
|
+
if (config.llm.provider.backend === 'none' || !config.llm.models.default) {
|
|
174
|
+
gaps.push('model configuration');
|
|
175
|
+
}
|
|
176
|
+
if (config.scan.enrichment.mode !== 'llm') {
|
|
177
|
+
gaps.push('scan enrichment mode');
|
|
178
|
+
}
|
|
179
|
+
const embeddings = config.scan.enrichment.embeddings;
|
|
180
|
+
if (!embeddings || embeddings.backend === 'none' || !embeddings.model || embeddings.dimensions <= 0) {
|
|
181
|
+
gaps.push('scan embeddings');
|
|
182
|
+
}
|
|
183
|
+
return gaps;
|
|
184
|
+
}
|
|
194
185
|
function targetForConnection(connectionId, connection, projectConfig, args, warnings) {
|
|
195
186
|
const driver = normalizeConnectionDriver(connection);
|
|
196
187
|
const adapter = sourceAdapterByDriver.get(driver);
|
|
197
188
|
const sourceDir = sourceDirForConnection(connection);
|
|
198
189
|
if (adapter) {
|
|
199
|
-
if (args.depth) {
|
|
200
|
-
warnings.ignoredDepthForSources.push(connectionId);
|
|
201
|
-
}
|
|
202
190
|
if (args.queryHistory === 'enabled' || args.queryHistoryWindowDays !== undefined) {
|
|
203
191
|
warnings.ignoredQueryHistoryForSources.push(connectionId);
|
|
204
192
|
}
|
|
@@ -214,16 +202,16 @@ function targetForConnection(connectionId, connection, projectConfig, args, warn
|
|
|
214
202
|
}
|
|
215
203
|
if (isDatabaseDriver(driver)) {
|
|
216
204
|
const options = resolveDatabaseTargetOptions({ connectionId, driver, connection, args, warnings });
|
|
217
|
-
const gaps =
|
|
205
|
+
const gaps = enrichmentReadinessGaps(projectConfig);
|
|
218
206
|
return {
|
|
219
207
|
connectionId,
|
|
220
208
|
driver,
|
|
221
209
|
operation: 'database-ingest',
|
|
222
210
|
debugCommand: `ktx ingest ${connectionId} --debug`,
|
|
223
|
-
detectRelationships:
|
|
211
|
+
detectRelationships: projectConfig.scan.relationships.enabled,
|
|
224
212
|
...(gaps.length > 0
|
|
225
213
|
? {
|
|
226
|
-
preflightFailure: `${connectionId}
|
|
214
|
+
preflightFailure: `${connectionId} cannot be ingested: enrichment is not configured (${gaps.join(', ')}). Run ktx setup to configure a model and embeddings.`,
|
|
227
215
|
}
|
|
228
216
|
: {}),
|
|
229
217
|
...options,
|
|
@@ -281,12 +269,11 @@ function defaultSteps(target) {
|
|
|
281
269
|
}
|
|
282
270
|
function retryCommandForTarget(target, args) {
|
|
283
271
|
const projectPart = ` --project-dir ${args.projectDir}`;
|
|
284
|
-
const depthPart = target.databaseDepth ? ` --${target.databaseDepth}` : '';
|
|
285
272
|
const queryHistoryPart = target.queryHistory?.enabled === true ? ' --query-history' : '';
|
|
286
273
|
const windowPart = target.queryHistory?.enabled === true && target.queryHistory.windowDays !== undefined
|
|
287
274
|
? ` --query-history-window-days ${target.queryHistory.windowDays}`
|
|
288
275
|
: '';
|
|
289
|
-
return `ktx ingest ${target.connectionId}${projectPart}${
|
|
276
|
+
return `ktx ingest ${target.connectionId}${projectPart}${queryHistoryPart}${windowPart}`;
|
|
290
277
|
}
|
|
291
278
|
function trimTrailingPeriod(value) {
|
|
292
279
|
return value.endsWith('.') ? value.slice(0, -1) : value;
|
|
@@ -499,7 +486,7 @@ export async function executePublicIngestTarget(target, args, io, deps) {
|
|
|
499
486
|
command: 'run',
|
|
500
487
|
projectDir: args.projectDir,
|
|
501
488
|
connectionId: target.connectionId,
|
|
502
|
-
mode:
|
|
489
|
+
mode: 'enriched',
|
|
503
490
|
detectRelationships: target.detectRelationships === true,
|
|
504
491
|
dryRun: false,
|
|
505
492
|
...(args.cliVersion ? { cliVersion: args.cliVersion } : {}),
|
|
@@ -622,7 +609,6 @@ export async function runKtxPublicIngest(args, io, deps = {}) {
|
|
|
622
609
|
all: args.all,
|
|
623
610
|
entrypoint: 'ingest',
|
|
624
611
|
inputMode: args.inputMode,
|
|
625
|
-
...(args.depth ? { depth: args.depth } : {}),
|
|
626
612
|
...(args.queryHistory ? { queryHistory: args.queryHistory } : {}),
|
|
627
613
|
...(args.queryHistoryWindowDays !== undefined ? { queryHistoryWindowDays: args.queryHistoryWindowDays } : {}),
|
|
628
614
|
...(args.scanMode ? { scanMode: args.scanMode } : {}),
|
package/dist/setup-context.js
CHANGED
|
@@ -6,8 +6,6 @@ import { markKtxSetupStateStepComplete, readKtxSetupState } from './context/proj
|
|
|
6
6
|
import { serializeKtxProjectConfig } from './context/project/config.js';
|
|
7
7
|
import { errorMessage, writePrefixedLines } from './clack.js';
|
|
8
8
|
import { buildPublicIngestPlan } from './public-ingest.js';
|
|
9
|
-
import { databaseContextDepth, } from './ingest-depth.js';
|
|
10
|
-
import { ensureSetupDatabaseContextDepths } from './setup-database-context-depth.js';
|
|
11
9
|
import { runContextBuild, } from './context-build-view.js';
|
|
12
10
|
import { createKtxSetupPromptAdapter, } from './setup-prompts.js';
|
|
13
11
|
const SETUP_CONTEXT_STATE_PATH = ['.ktx', 'setup', 'context-build.json'];
|
|
@@ -232,15 +230,6 @@ async function readLatestScanReport(projectDir, connectionId) {
|
|
|
232
230
|
reports.sort((left, right) => left.sortKey.localeCompare(right.sortKey));
|
|
233
231
|
return reports.at(-1)?.report ?? null;
|
|
234
232
|
}
|
|
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
233
|
function scanReportHasCompletedDeepEnrichment(report, connectionId, relationshipsRequired) {
|
|
245
234
|
if (!isRecord(report)) {
|
|
246
235
|
return false;
|
|
@@ -260,23 +249,13 @@ function scanReportHasCompletedDeepEnrichment(report, connectionId, relationship
|
|
|
260
249
|
(!relationshipsRequired || completedStages.includes('relationships')) &&
|
|
261
250
|
stringArrayValue(report.artifactPaths.manifestShards).length > 0);
|
|
262
251
|
}
|
|
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
252
|
async function verifyPrimarySourceScans(project, connectionIds) {
|
|
270
253
|
const details = [];
|
|
271
254
|
const relationshipsRequired = project.config.scan.relationships.enabled;
|
|
272
255
|
for (const connectionId of connectionIds) {
|
|
273
|
-
const connection = project.config.connections[connectionId];
|
|
274
|
-
const depth = connection ? (databaseContextDepth(connection) ?? 'fast') : 'fast';
|
|
275
256
|
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.`);
|
|
257
|
+
if (!scanReportHasCompletedDeepEnrichment(report, connectionId, relationshipsRequired)) {
|
|
258
|
+
details.push(`${connectionId}: database context has not completed.`);
|
|
280
259
|
}
|
|
281
260
|
}
|
|
282
261
|
return { ready: details.length === 0, details };
|
|
@@ -331,7 +310,7 @@ function writeSkippedContext(projectDir, io) {
|
|
|
331
310
|
io.stdout.write(`Build context:\n ktx setup --project-dir ${resolve(projectDir)}\n\n`);
|
|
332
311
|
io.stdout.write(`Check status:\n ktx status --project-dir ${resolve(projectDir)}\n`);
|
|
333
312
|
}
|
|
334
|
-
function writeSuccess(
|
|
313
|
+
function writeSuccess(readiness, targets, io) {
|
|
335
314
|
io.stdout.write('\nKTX context is ready for agents.\n\n');
|
|
336
315
|
io.stdout.write('Databases:\n');
|
|
337
316
|
if (targets.primarySourceConnectionIds.length === 0) {
|
|
@@ -339,9 +318,7 @@ function writeSuccess(project, readiness, targets, io) {
|
|
|
339
318
|
}
|
|
340
319
|
else {
|
|
341
320
|
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`);
|
|
321
|
+
io.stdout.write(` ${connectionId}: database context complete\n`);
|
|
345
322
|
}
|
|
346
323
|
}
|
|
347
324
|
io.stdout.write('\nContext sources:\n');
|
|
@@ -466,7 +443,7 @@ async function runBuild(args, io, deps, project, targets) {
|
|
|
466
443
|
failureReason: undefined,
|
|
467
444
|
...(lastSourceProgress ? { sourceProgress: lastSourceProgress } : {}),
|
|
468
445
|
});
|
|
469
|
-
writeSuccess(
|
|
446
|
+
writeSuccess(readiness, targets, io);
|
|
470
447
|
return { status: 'ready', projectDir: args.projectDir, runId };
|
|
471
448
|
}
|
|
472
449
|
async function completeExistingContext(args, io, deps, targets) {
|
|
@@ -496,17 +473,8 @@ async function completeExistingContext(args, io, deps, targets) {
|
|
|
496
473
|
}
|
|
497
474
|
export async function runKtxSetupContextStep(args, io, deps = {}) {
|
|
498
475
|
try {
|
|
499
|
-
|
|
476
|
+
const project = await loadKtxProject({ projectDir: args.projectDir });
|
|
500
477
|
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
478
|
const existingState = await readKtxSetupContextState(args.projectDir);
|
|
511
479
|
const completedSteps = (await readKtxSetupState(args.projectDir)).completed_steps;
|
|
512
480
|
if (completedSteps.includes('context') && existingState.status === 'completed') {
|
package/dist/setup-databases.js
CHANGED
|
@@ -14,13 +14,12 @@ import { runKtxConnection } from './connection.js';
|
|
|
14
14
|
import { pickDatabaseScope as defaultPickDatabaseScope, } from './database-tree-picker.js';
|
|
15
15
|
import { withMultiselectNavigation, withTextInputNavigation } from './prompt-navigation.js';
|
|
16
16
|
import { runKtxScan } from './scan.js';
|
|
17
|
-
import { applySetupDatabaseContextDepth } from './setup-database-context-depth.js';
|
|
18
17
|
import { writeProjectLocalSecretReference } from './setup-secrets.js';
|
|
19
18
|
import { isDemoConnection } from './telemetry/demo-detect.js';
|
|
20
19
|
import { emitTelemetryEvent } from './telemetry/index.js';
|
|
21
20
|
import { createKtxSetupPromptAdapter, createKtxSetupUiAdapter, } from './setup-prompts.js';
|
|
22
21
|
const HISTORIC_SQL_WORK_UNIT_MAX_CONCURRENCY = 6;
|
|
23
|
-
const
|
|
22
|
+
const KTX_DEMO_START_URL = 'https://www.kaelio.com/start';
|
|
24
23
|
const execFileAsync = promisify(execFileCallback);
|
|
25
24
|
const DRIVER_OPTIONS = [
|
|
26
25
|
{ value: 'postgres', label: 'PostgreSQL' },
|
|
@@ -1209,39 +1208,10 @@ async function applyHistoricSqlConfigToExistingConnection(input) {
|
|
|
1209
1208
|
});
|
|
1210
1209
|
if (withHistoricSql === 'back')
|
|
1211
1210
|
return 'back';
|
|
1212
|
-
const withContextDepth = await maybeApplyContextDepthConfig({
|
|
1213
|
-
projectDir: input.projectDir,
|
|
1214
|
-
connectionId: input.connectionId,
|
|
1215
|
-
connection: withHistoricSql,
|
|
1216
|
-
args: input.args,
|
|
1217
|
-
prompts: input.prompts,
|
|
1218
|
-
});
|
|
1219
|
-
if (withContextDepth === 'back')
|
|
1220
|
-
return 'back';
|
|
1221
1211
|
await writeConnectionConfig({
|
|
1222
1212
|
projectDir: input.projectDir,
|
|
1223
1213
|
connectionId: input.connectionId,
|
|
1224
|
-
connection:
|
|
1225
|
-
});
|
|
1226
|
-
}
|
|
1227
|
-
async function maybeApplyContextDepthConfig(input) {
|
|
1228
|
-
const project = await loadKtxProject({ projectDir: input.projectDir });
|
|
1229
|
-
return await applySetupDatabaseContextDepth({
|
|
1230
|
-
project: {
|
|
1231
|
-
...project,
|
|
1232
|
-
config: {
|
|
1233
|
-
...project.config,
|
|
1234
|
-
connections: {
|
|
1235
|
-
...project.config.connections,
|
|
1236
|
-
[input.connectionId]: input.connection,
|
|
1237
|
-
},
|
|
1238
|
-
},
|
|
1239
|
-
},
|
|
1240
|
-
connection: input.connection,
|
|
1241
|
-
args: {
|
|
1242
|
-
inputMode: input.args.inputMode === 'disabled' || input.args.databaseUrl ? 'disabled' : input.args.inputMode,
|
|
1243
|
-
},
|
|
1244
|
-
prompts: input.prompts,
|
|
1214
|
+
connection: withHistoricSql,
|
|
1245
1215
|
});
|
|
1246
1216
|
}
|
|
1247
1217
|
async function validateAndScanConnection(input) {
|
|
@@ -1273,7 +1243,7 @@ async function validateAndScanConnection(input) {
|
|
|
1273
1243
|
deps: input.deps,
|
|
1274
1244
|
});
|
|
1275
1245
|
writeSetupSection(input.io, `Building schema context for ${input.connectionId}`, [
|
|
1276
|
-
'Running
|
|
1246
|
+
'Running database scan…',
|
|
1277
1247
|
]);
|
|
1278
1248
|
let scanIo = createBufferedCommandIo();
|
|
1279
1249
|
let scanCode = await scanConnection(input.projectDir, input.connectionId, scanIo);
|
|
@@ -1281,7 +1251,7 @@ async function validateAndScanConnection(input) {
|
|
|
1281
1251
|
const nativeSqliteDetail = nativeSqliteAbiMismatchDetail(`${scanIo.stderrText()}\n${scanIo.stdoutText()}`);
|
|
1282
1252
|
if (nativeSqliteDetail) {
|
|
1283
1253
|
writePrefixedLines((chunk) => input.io.stderr.write(chunk), [
|
|
1284
|
-
`
|
|
1254
|
+
`Database scan failed for ${input.connectionId}.`,
|
|
1285
1255
|
'Native SQLite is built for a different Node.js ABI.',
|
|
1286
1256
|
`Detail: ${nativeSqliteDetail}`,
|
|
1287
1257
|
'Rebuilding Native SQLite with pnpm run native:rebuild…',
|
|
@@ -1289,7 +1259,7 @@ async function validateAndScanConnection(input) {
|
|
|
1289
1259
|
const rebuildNativeSqlite = input.deps.rebuildNativeSqlite ?? defaultRebuildNativeSqlite;
|
|
1290
1260
|
const rebuildCode = await rebuildNativeSqlite(input.io);
|
|
1291
1261
|
if (rebuildCode === 0) {
|
|
1292
|
-
writePrefixedLines((chunk) => input.io.stderr.write(chunk), 'Native SQLite rebuild complete. Retrying
|
|
1262
|
+
writePrefixedLines((chunk) => input.io.stderr.write(chunk), 'Native SQLite rebuild complete. Retrying database scan…');
|
|
1293
1263
|
const retryScanIo = createBufferedCommandIo();
|
|
1294
1264
|
scanCode = await scanConnection(input.projectDir, input.connectionId, retryScanIo);
|
|
1295
1265
|
scanIo = retryScanIo;
|
|
@@ -1297,18 +1267,18 @@ async function validateAndScanConnection(input) {
|
|
|
1297
1267
|
if (scanCode !== 0) {
|
|
1298
1268
|
writePrefixedLines((chunk) => input.io.stderr.write(chunk), [
|
|
1299
1269
|
rebuildCode === 0
|
|
1300
|
-
? `
|
|
1270
|
+
? `Database scan still failed for ${input.connectionId} after rebuilding Native SQLite.`
|
|
1301
1271
|
: `Native SQLite rebuild failed for ${input.connectionId}.`,
|
|
1302
1272
|
'Fix: pnpm run native:rebuild',
|
|
1303
|
-
`Retry: ktx ingest ${input.connectionId} --project-dir ${input.projectDir}
|
|
1273
|
+
`Retry: ktx ingest ${input.connectionId} --project-dir ${input.projectDir}`,
|
|
1304
1274
|
].join('\n'));
|
|
1305
1275
|
}
|
|
1306
1276
|
}
|
|
1307
1277
|
else {
|
|
1308
1278
|
flushPrefixedBufferedCommandOutput(input.io, scanIo);
|
|
1309
1279
|
writePrefixedLines((chunk) => input.io.stderr.write(chunk), [
|
|
1310
|
-
`
|
|
1311
|
-
`Debug command: ktx ingest ${input.connectionId} --project-dir ${input.projectDir} --
|
|
1280
|
+
`Database scan failed for ${input.connectionId}.`,
|
|
1281
|
+
`Debug command: ktx ingest ${input.connectionId} --project-dir ${input.projectDir} --debug`,
|
|
1312
1282
|
].join('\n'));
|
|
1313
1283
|
}
|
|
1314
1284
|
if (scanCode !== 0) {
|
|
@@ -1334,7 +1304,7 @@ async function chooseDrivers(args, io, prompts, options) {
|
|
|
1334
1304
|
return 'missing-input';
|
|
1335
1305
|
}
|
|
1336
1306
|
const initialValues = unique(options?.initialDrivers ?? []);
|
|
1337
|
-
createKtxSetupUiAdapter().note(`Get demo credentials
|
|
1307
|
+
createKtxSetupUiAdapter().note(`Get demo credentials: ${KTX_DEMO_START_URL}`, '🎁 Need a warehouse to play with?', io);
|
|
1338
1308
|
const choices = await prompts.multiselect({
|
|
1339
1309
|
message: withMultiselectNavigation('Which databases should KTX connect to?'),
|
|
1340
1310
|
options: [...DRIVER_OPTIONS],
|
|
@@ -1690,23 +1660,10 @@ export async function runKtxSetupDatabasesStep(args, io, deps = {}) {
|
|
|
1690
1660
|
returnToDriverSelection = true;
|
|
1691
1661
|
break;
|
|
1692
1662
|
}
|
|
1693
|
-
const withContextDepth = await maybeApplyContextDepthConfig({
|
|
1694
|
-
projectDir: args.projectDir,
|
|
1695
|
-
connectionId: connectionChoice.connectionId,
|
|
1696
|
-
connection: withHistoricSql,
|
|
1697
|
-
args,
|
|
1698
|
-
prompts,
|
|
1699
|
-
});
|
|
1700
|
-
if (withContextDepth === 'back') {
|
|
1701
|
-
if (!canReturnToDriverSelection)
|
|
1702
|
-
return { status: 'back', projectDir: args.projectDir };
|
|
1703
|
-
returnToDriverSelection = true;
|
|
1704
|
-
break;
|
|
1705
|
-
}
|
|
1706
1663
|
await writeConnectionConfig({
|
|
1707
1664
|
projectDir: args.projectDir,
|
|
1708
1665
|
connectionId: connectionChoice.connectionId,
|
|
1709
|
-
connection:
|
|
1666
|
+
connection: withHistoricSql,
|
|
1710
1667
|
io,
|
|
1711
1668
|
});
|
|
1712
1669
|
}
|
|
@@ -1719,23 +1676,10 @@ export async function runKtxSetupDatabasesStep(args, io, deps = {}) {
|
|
|
1719
1676
|
returnToDriverSelection = true;
|
|
1720
1677
|
break;
|
|
1721
1678
|
}
|
|
1722
|
-
const withContextDepth = await maybeApplyContextDepthConfig({
|
|
1723
|
-
projectDir: args.projectDir,
|
|
1724
|
-
connectionId: connectionChoice.connectionId,
|
|
1725
|
-
connection: withHistoricSql,
|
|
1726
|
-
args,
|
|
1727
|
-
prompts,
|
|
1728
|
-
});
|
|
1729
|
-
if (withContextDepth === 'back') {
|
|
1730
|
-
if (!canReturnToDriverSelection)
|
|
1731
|
-
return { status: 'back', projectDir: args.projectDir };
|
|
1732
|
-
returnToDriverSelection = true;
|
|
1733
|
-
break;
|
|
1734
|
-
}
|
|
1735
1679
|
await writeConnectionConfig({
|
|
1736
1680
|
projectDir: args.projectDir,
|
|
1737
1681
|
connectionId: connectionChoice.connectionId,
|
|
1738
|
-
connection:
|
|
1682
|
+
connection: withHistoricSql,
|
|
1739
1683
|
io,
|
|
1740
1684
|
});
|
|
1741
1685
|
}
|
|
@@ -1825,23 +1769,10 @@ export async function runKtxSetupDatabasesStep(args, io, deps = {}) {
|
|
|
1825
1769
|
returnToDriverSelection = true;
|
|
1826
1770
|
break;
|
|
1827
1771
|
}
|
|
1828
|
-
const withContextDepth = await maybeApplyContextDepthConfig({
|
|
1829
|
-
projectDir: args.projectDir,
|
|
1830
|
-
connectionId: connectionChoice.connectionId,
|
|
1831
|
-
connection: withHistoricSql,
|
|
1832
|
-
args,
|
|
1833
|
-
prompts,
|
|
1834
|
-
});
|
|
1835
|
-
if (withContextDepth === 'back') {
|
|
1836
|
-
if (!canReturnToDriverSelection)
|
|
1837
|
-
return { status: 'back', projectDir: args.projectDir };
|
|
1838
|
-
returnToDriverSelection = true;
|
|
1839
|
-
break;
|
|
1840
|
-
}
|
|
1841
1772
|
await writeConnectionConfig({
|
|
1842
1773
|
projectDir: args.projectDir,
|
|
1843
1774
|
connectionId: connectionChoice.connectionId,
|
|
1844
|
-
connection:
|
|
1775
|
+
connection: withHistoricSql,
|
|
1845
1776
|
io,
|
|
1846
1777
|
});
|
|
1847
1778
|
setupStatus = await validateAndScanConnection({
|
package/dist/setup-project.d.ts
CHANGED
|
@@ -10,19 +10,11 @@ export interface KtxSetupProjectArgs {
|
|
|
10
10
|
yes: boolean;
|
|
11
11
|
allowBack?: boolean;
|
|
12
12
|
}
|
|
13
|
-
export type KtxSetupCreatedProjectCleanup = {
|
|
14
|
-
kind: 'remove-project-dir';
|
|
15
|
-
projectDir: string;
|
|
16
|
-
} | {
|
|
17
|
-
kind: 'remove-ktx-scaffold';
|
|
18
|
-
projectDir: string;
|
|
19
|
-
};
|
|
20
13
|
export type KtxSetupProjectResult = {
|
|
21
14
|
status: 'ready';
|
|
22
15
|
projectDir: string;
|
|
23
16
|
project: KtxLocalProject;
|
|
24
17
|
confirmedCreation?: boolean;
|
|
25
|
-
createdProjectCleanup?: KtxSetupCreatedProjectCleanup;
|
|
26
18
|
} | {
|
|
27
19
|
status: 'back';
|
|
28
20
|
projectDir: string;
|
package/dist/setup-project.js
CHANGED
|
@@ -39,15 +39,6 @@ async function existingFolderState(projectDir) {
|
|
|
39
39
|
throw error;
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
function cleanupForFolderState(projectDir, state) {
|
|
43
|
-
if (state === 'missing') {
|
|
44
|
-
return { kind: 'remove-project-dir', projectDir };
|
|
45
|
-
}
|
|
46
|
-
if (state === 'empty-directory') {
|
|
47
|
-
return { kind: 'remove-ktx-scaffold', projectDir };
|
|
48
|
-
}
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
42
|
async function confirmProjectDir(selectedDir, io, prompts) {
|
|
52
43
|
const state = await existingFolderState(selectedDir);
|
|
53
44
|
if (state === 'not-directory') {
|
|
@@ -86,7 +77,7 @@ async function confirmProjectDir(selectedDir, io, prompts) {
|
|
|
86
77
|
return { status: 'back' };
|
|
87
78
|
if (action !== 'create')
|
|
88
79
|
return { status: 'cancelled' };
|
|
89
|
-
return { status: 'confirmed', confirmedCreation: true
|
|
80
|
+
return { status: 'confirmed', confirmedCreation: true };
|
|
90
81
|
}
|
|
91
82
|
async function normalizeSetupGitignore(projectDir) {
|
|
92
83
|
const gitignorePath = join(projectDir, '.ktx/.gitignore');
|
|
@@ -162,19 +153,9 @@ async function promptForNewProjectDir(projectDir, homeDir, io, prompts) {
|
|
|
162
153
|
status: 'selected',
|
|
163
154
|
projectDir: selectedDir,
|
|
164
155
|
confirmedCreation: confirmed.confirmedCreation,
|
|
165
|
-
...(confirmed.createdProjectCleanup ? { createdProjectCleanup: confirmed.createdProjectCleanup } : {}),
|
|
166
156
|
};
|
|
167
157
|
}
|
|
168
158
|
}
|
|
169
|
-
async function createProjectWithCleanup(projectDir, deps) {
|
|
170
|
-
const state = await existingFolderState(projectDir);
|
|
171
|
-
const project = await createProject(projectDir, deps);
|
|
172
|
-
const createdProjectCleanup = cleanupForFolderState(projectDir, state);
|
|
173
|
-
return {
|
|
174
|
-
project,
|
|
175
|
-
...(createdProjectCleanup ? { createdProjectCleanup } : {}),
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
159
|
export async function runKtxSetupProjectStep(args, io, deps = {}) {
|
|
179
160
|
const projectDir = resolve(args.projectDir);
|
|
180
161
|
const homeDir = deps.homeDir ?? homedir();
|
|
@@ -203,7 +184,6 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
|
|
|
203
184
|
projectDir: selected.projectDir,
|
|
204
185
|
project,
|
|
205
186
|
confirmedCreation: selected.confirmedCreation,
|
|
206
|
-
...(selected.createdProjectCleanup ? { createdProjectCleanup: selected.createdProjectCleanup } : {}),
|
|
207
187
|
};
|
|
208
188
|
}
|
|
209
189
|
if (exists) {
|
|
@@ -216,13 +196,12 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
|
|
|
216
196
|
io.stderr.write('Missing setup choice: pass --yes to create a project in non-interactive setup.\n');
|
|
217
197
|
return { status: 'missing-input', projectDir };
|
|
218
198
|
}
|
|
219
|
-
const
|
|
199
|
+
const project = await createProject(projectDir, deps);
|
|
220
200
|
printProjectSummary(io, projectDir);
|
|
221
201
|
return {
|
|
222
202
|
status: 'ready',
|
|
223
203
|
projectDir,
|
|
224
204
|
project,
|
|
225
|
-
...(createdProjectCleanup ? { createdProjectCleanup } : {}),
|
|
226
205
|
};
|
|
227
206
|
}
|
|
228
207
|
if (!io.stdout.isTTY && !deps.prompts) {
|
|
@@ -255,13 +234,12 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
|
|
|
255
234
|
return { status: 'cancelled', projectDir };
|
|
256
235
|
}
|
|
257
236
|
if (choice === 'current') {
|
|
258
|
-
const
|
|
237
|
+
const project = await createProject(projectDir, deps);
|
|
259
238
|
printProjectSummary(io, projectDir);
|
|
260
239
|
return {
|
|
261
240
|
status: 'ready',
|
|
262
241
|
projectDir,
|
|
263
242
|
project,
|
|
264
|
-
...(createdProjectCleanup ? { createdProjectCleanup } : {}),
|
|
265
243
|
};
|
|
266
244
|
}
|
|
267
245
|
if (choice === 'new-default') {
|
|
@@ -279,7 +257,6 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
|
|
|
279
257
|
projectDir: defaultProjectDir,
|
|
280
258
|
project,
|
|
281
259
|
confirmedCreation: confirmed.confirmedCreation,
|
|
282
|
-
...(confirmed.createdProjectCleanup ? { createdProjectCleanup: confirmed.createdProjectCleanup } : {}),
|
|
283
260
|
};
|
|
284
261
|
}
|
|
285
262
|
if (choice === 'new-custom') {
|
|
@@ -309,7 +286,6 @@ export async function runKtxSetupProjectStep(args, io, deps = {}) {
|
|
|
309
286
|
projectDir: customDir,
|
|
310
287
|
project,
|
|
311
288
|
confirmedCreation: confirmed.confirmedCreation,
|
|
312
|
-
...(confirmed.createdProjectCleanup ? { createdProjectCleanup: confirmed.createdProjectCleanup } : {}),
|
|
313
289
|
};
|
|
314
290
|
}
|
|
315
291
|
prompts.cancel('Setup cancelled.');
|