@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
|
@@ -59,6 +59,13 @@ function optionalString(raw, field) {
|
|
|
59
59
|
}
|
|
60
60
|
throw new Error(`sql analysis response has invalid optional string field ${field}`);
|
|
61
61
|
}
|
|
62
|
+
function optionalNullableStringField(raw, field) {
|
|
63
|
+
const value = raw[field];
|
|
64
|
+
if (value === null || value === undefined || typeof value === 'string') {
|
|
65
|
+
return value ?? null;
|
|
66
|
+
}
|
|
67
|
+
throw new Error(`sql analysis response has invalid optional nullable string field ${field}`);
|
|
68
|
+
}
|
|
62
69
|
function requiredStringArray(raw, field) {
|
|
63
70
|
const value = raw[field];
|
|
64
71
|
if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {
|
|
@@ -136,10 +143,32 @@ function mapColumnsByClause(raw) {
|
|
|
136
143
|
}
|
|
137
144
|
return result;
|
|
138
145
|
}
|
|
146
|
+
function requiredTableRef(raw, field) {
|
|
147
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
148
|
+
throw new Error(`sql analysis response contains invalid table ref in ${field}`);
|
|
149
|
+
}
|
|
150
|
+
const record = raw;
|
|
151
|
+
const name = record.name;
|
|
152
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
153
|
+
throw new Error(`sql analysis response table ref in ${field} is missing name`);
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
catalog: optionalNullableStringField(record, 'catalog'),
|
|
157
|
+
db: optionalNullableStringField(record, 'db'),
|
|
158
|
+
name,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function requiredTableRefArray(raw, field) {
|
|
162
|
+
const value = raw[field];
|
|
163
|
+
if (!Array.isArray(value)) {
|
|
164
|
+
throw new Error(`sql analysis response is missing table-ref[] field ${field}`);
|
|
165
|
+
}
|
|
166
|
+
return value.map((item, index) => requiredTableRef(item, `${field}.${index}`));
|
|
167
|
+
}
|
|
139
168
|
function mapBatchResult(raw) {
|
|
140
169
|
const error = optionalString(raw, 'error');
|
|
141
170
|
return {
|
|
142
|
-
tablesTouched:
|
|
171
|
+
tablesTouched: requiredTableRefArray(raw, 'tables_touched'),
|
|
143
172
|
columnsByClause: mapColumnsByClause(raw),
|
|
144
173
|
...(error !== undefined ? { error } : {}),
|
|
145
174
|
};
|
|
@@ -170,10 +199,11 @@ export function createHttpSqlAnalysisPort(options) {
|
|
|
170
199
|
});
|
|
171
200
|
return mapResult(raw);
|
|
172
201
|
},
|
|
173
|
-
async analyzeBatch(items, dialect) {
|
|
202
|
+
async analyzeBatch(items, dialect, options) {
|
|
174
203
|
const raw = await requestJson('/sql/analyze-batch', {
|
|
175
204
|
dialect,
|
|
176
205
|
items,
|
|
206
|
+
...(options?.catalog ? { catalog: options.catalog } : {}),
|
|
177
207
|
});
|
|
178
208
|
return mapBatchResponse(raw);
|
|
179
209
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { KtxTableRef } from '../scan/types.js';
|
|
1
2
|
export type SqlAnalysisDialect = 'bigquery' | 'snowflake' | 'postgres' | 'redshift' | 'mysql' | 'sqlite' | 'tsql' | 'clickhouse' | (string & {});
|
|
2
3
|
export type SqlAnalysisLiteralSlotType = 'string' | 'number' | 'timestamp' | 'date' | 'boolean' | 'null' | 'unknown';
|
|
3
4
|
export interface SqlAnalysisLiteralSlot {
|
|
@@ -17,8 +18,17 @@ export interface SqlAnalysisBatchItem {
|
|
|
17
18
|
id: string;
|
|
18
19
|
sql: string;
|
|
19
20
|
}
|
|
21
|
+
interface SqlAnalysisCatalogTable extends KtxTableRef {
|
|
22
|
+
columns?: string[];
|
|
23
|
+
}
|
|
24
|
+
interface SqlAnalysisCatalog {
|
|
25
|
+
tables: SqlAnalysisCatalogTable[];
|
|
26
|
+
}
|
|
27
|
+
export interface SqlAnalysisBatchOptions {
|
|
28
|
+
catalog?: SqlAnalysisCatalog;
|
|
29
|
+
}
|
|
20
30
|
export interface SqlAnalysisBatchResult {
|
|
21
|
-
tablesTouched:
|
|
31
|
+
tablesTouched: KtxTableRef[];
|
|
22
32
|
columnsByClause: Partial<Record<SqlAnalysisClause, string[]>>;
|
|
23
33
|
error?: string | null;
|
|
24
34
|
}
|
|
@@ -28,7 +38,7 @@ export interface SqlReadOnlyValidationResult {
|
|
|
28
38
|
}
|
|
29
39
|
export interface SqlAnalysisPort {
|
|
30
40
|
analyzeForFingerprint(sql: string, dialect: SqlAnalysisDialect): Promise<SqlAnalysisFingerprintResult>;
|
|
31
|
-
analyzeBatch(items: SqlAnalysisBatchItem[], dialect: SqlAnalysisDialect): Promise<Map<string, SqlAnalysisBatchResult>>;
|
|
41
|
+
analyzeBatch(items: SqlAnalysisBatchItem[], dialect: SqlAnalysisDialect, options?: SqlAnalysisBatchOptions): Promise<Map<string, SqlAnalysisBatchResult>>;
|
|
32
42
|
validateReadOnly(sql: string, dialect: SqlAnalysisDialect): Promise<SqlReadOnlyValidationResult>;
|
|
33
43
|
}
|
|
34
44
|
export {};
|
|
@@ -8,8 +8,8 @@ declare const contextCandidateMarkInputSchema: z.ZodObject<{
|
|
|
8
8
|
conflict: "conflict";
|
|
9
9
|
merged: "merged";
|
|
10
10
|
pending: "pending";
|
|
11
|
-
promoted: "promoted";
|
|
12
11
|
rejected: "rejected";
|
|
12
|
+
promoted: "promoted";
|
|
13
13
|
}>;
|
|
14
14
|
rejectionReason: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
15
15
|
}, z.core.$strip>;
|
|
@@ -31,8 +31,8 @@ export declare class ContextCandidateMarkTool extends BaseTool<typeof contextCan
|
|
|
31
31
|
conflict: "conflict";
|
|
32
32
|
merged: "merged";
|
|
33
33
|
pending: "pending";
|
|
34
|
-
promoted: "promoted";
|
|
35
34
|
rejected: "rejected";
|
|
35
|
+
promoted: "promoted";
|
|
36
36
|
}>;
|
|
37
37
|
rejectionReason: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
38
38
|
}, z.core.$strip>;
|
|
@@ -50,6 +50,16 @@ export declare function readLocalKnowledgePage(project: KtxLocalProject, input:
|
|
|
50
50
|
export declare function listLocalKnowledgePages(project: KtxLocalProject, input?: {
|
|
51
51
|
userId?: string;
|
|
52
52
|
}): Promise<LocalKnowledgeSummary[]>;
|
|
53
|
+
/**
|
|
54
|
+
* List wiki page keys without reading or parsing file contents.
|
|
55
|
+
*
|
|
56
|
+
* Keys are derived purely from file paths, so this stays cheap enough for
|
|
57
|
+
* shell tab-completion (unlike `listLocalKnowledgePages`, which reads every
|
|
58
|
+
* page to populate summaries).
|
|
59
|
+
*/
|
|
60
|
+
export declare function listLocalKnowledgePageKeys(project: KtxLocalProject, input?: {
|
|
61
|
+
userId?: string;
|
|
62
|
+
}): Promise<string[]>;
|
|
53
63
|
export declare function searchLocalKnowledgePages(project: KtxLocalProject, input: {
|
|
54
64
|
query: string;
|
|
55
65
|
userId?: string;
|
|
@@ -118,6 +118,28 @@ export async function listLocalKnowledgePages(project, input = {}) {
|
|
|
118
118
|
}
|
|
119
119
|
return pages.sort((left, right) => left.path.localeCompare(right.path));
|
|
120
120
|
}
|
|
121
|
+
/**
|
|
122
|
+
* List wiki page keys without reading or parsing file contents.
|
|
123
|
+
*
|
|
124
|
+
* Keys are derived purely from file paths, so this stays cheap enough for
|
|
125
|
+
* shell tab-completion (unlike `listLocalKnowledgePages`, which reads every
|
|
126
|
+
* page to populate summaries).
|
|
127
|
+
*/
|
|
128
|
+
export async function listLocalKnowledgePageKeys(project, input = {}) {
|
|
129
|
+
const userId = input.userId ?? 'local';
|
|
130
|
+
const keys = new Set();
|
|
131
|
+
for (const scope of ['GLOBAL', 'USER']) {
|
|
132
|
+
const root = scope === 'GLOBAL' ? 'wiki/global' : `wiki/user/${assertSafePathToken('user id', userId)}`;
|
|
133
|
+
const listed = await project.fileStore.listFiles(root);
|
|
134
|
+
for (const path of listed.files.filter((file) => file.endsWith('.md'))) {
|
|
135
|
+
const key = keyFromKnowledgePath(path, scope, userId);
|
|
136
|
+
if (key) {
|
|
137
|
+
keys.add(key);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return [...keys].sort();
|
|
142
|
+
}
|
|
121
143
|
function scorePage(page, terms) {
|
|
122
144
|
const haystack = buildKnowledgeSearchText(page.key, page.summary, page.content, page.tags).toLowerCase();
|
|
123
145
|
return terms.some((term) => haystack.includes(term)) ? 3 : 0;
|
|
@@ -39,9 +39,6 @@ export interface ContextBuildArgs {
|
|
|
39
39
|
targetConnectionId?: string;
|
|
40
40
|
all?: boolean;
|
|
41
41
|
entrypoint?: 'setup' | 'ingest';
|
|
42
|
-
depth?: Extract<KtxPublicIngestArgs, {
|
|
43
|
-
command: 'run';
|
|
44
|
-
}>['depth'];
|
|
45
42
|
queryHistory?: Extract<KtxPublicIngestArgs, {
|
|
46
43
|
command: 'run';
|
|
47
44
|
}>['queryHistory'];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { buildPublicIngestPlan, executePublicIngestTarget, publicProgressMessage } from './public-ingest.js';
|
|
2
|
+
import { createAggregateProgressPort } from './progress-port-adapter.js';
|
|
3
3
|
import { formatDuration } from './demo-metrics.js';
|
|
4
4
|
import { profileMark } from './startup-profile.js';
|
|
5
5
|
profileMark('module:context-build-view');
|
|
@@ -241,12 +241,11 @@ function renderMessageGroup(label, messages, styled) {
|
|
|
241
241
|
function retryCommand(input) {
|
|
242
242
|
const projectPart = input.projectDir ? ` --project-dir ${input.projectDir}` : '';
|
|
243
243
|
if (input.entrypoint === 'ingest' && input.connectionId) {
|
|
244
|
-
const depthPart = input.depth ? ` --${input.depth}` : '';
|
|
245
244
|
const queryHistoryPart = input.queryHistory ? ' --query-history' : '';
|
|
246
245
|
const windowPart = input.queryHistory && input.queryHistoryWindowDays !== undefined
|
|
247
246
|
? ` --query-history-window-days ${input.queryHistoryWindowDays}`
|
|
248
247
|
: '';
|
|
249
|
-
return `ktx ingest ${input.connectionId}${projectPart}${
|
|
248
|
+
return `ktx ingest ${input.connectionId}${projectPart}${queryHistoryPart}${windowPart}`;
|
|
250
249
|
}
|
|
251
250
|
return input.projectDir ? `ktx setup --project-dir ${input.projectDir}` : 'ktx setup';
|
|
252
251
|
}
|
|
@@ -563,7 +562,6 @@ function appendRetryIfNeeded(input) {
|
|
|
563
562
|
projectDir: input.projectDir,
|
|
564
563
|
entrypoint: input.entrypoint,
|
|
565
564
|
connectionId: input.target.connectionId,
|
|
566
|
-
depth: input.target.databaseDepth,
|
|
567
565
|
queryHistory: input.target.queryHistory?.enabled === true,
|
|
568
566
|
queryHistoryWindowDays: input.target.queryHistory?.windowDays,
|
|
569
567
|
})}`;
|
|
@@ -578,7 +576,6 @@ function failureTextForTarget(input) {
|
|
|
578
576
|
projectDir: input.projectDir,
|
|
579
577
|
entrypoint: input.entrypoint,
|
|
580
578
|
connectionId: input.target.connectionId,
|
|
581
|
-
depth: input.target.databaseDepth,
|
|
582
579
|
queryHistory: input.target.queryHistory?.enabled === true,
|
|
583
580
|
queryHistoryWindowDays: input.target.queryHistory?.windowDays,
|
|
584
581
|
})}`,
|
|
@@ -593,7 +590,6 @@ function failureTextForTarget(input) {
|
|
|
593
590
|
projectDir: input.projectDir,
|
|
594
591
|
entrypoint: input.entrypoint,
|
|
595
592
|
connectionId: input.target.connectionId,
|
|
596
|
-
depth: input.target.databaseDepth,
|
|
597
593
|
queryHistory: input.target.queryHistory?.enabled === true,
|
|
598
594
|
queryHistoryWindowDays: input.target.queryHistory?.windowDays,
|
|
599
595
|
})}`,
|
|
@@ -622,44 +618,15 @@ export function initViewState(targets) {
|
|
|
622
618
|
totalElapsedMs: 0,
|
|
623
619
|
};
|
|
624
620
|
}
|
|
625
|
-
function publicProgressMessage(message, target) {
|
|
626
|
-
let current = message;
|
|
627
|
-
if (target.operation === 'database-ingest') {
|
|
628
|
-
current = publicDatabaseIngestMessage(current);
|
|
629
|
-
}
|
|
630
|
-
if (target.steps.includes('query-history')) {
|
|
631
|
-
current = publicQueryHistoryMessage(current, target.connectionId);
|
|
632
|
-
}
|
|
633
|
-
return current;
|
|
634
|
-
}
|
|
635
621
|
function formatProgressDetail(update, target) {
|
|
636
622
|
const percent = Math.max(0, Math.min(100, Math.round(update.percent)));
|
|
637
623
|
return `[${percent}%] ${publicProgressMessage(update.message, target)}`;
|
|
638
624
|
}
|
|
639
|
-
function createContextBuildProgressPort(onProgress, state = { progress: 0 }, start = 0, weight = 1) {
|
|
640
|
-
return {
|
|
641
|
-
async update(value, message, options) {
|
|
642
|
-
const absoluteValue = start + Math.max(0, Math.min(1, value)) * weight;
|
|
643
|
-
state.progress = Math.max(state.progress, Math.min(1, absoluteValue));
|
|
644
|
-
if (!message)
|
|
645
|
-
return;
|
|
646
|
-
onProgress({
|
|
647
|
-
percent: Math.max(0, Math.min(100, Math.round(state.progress * 100))),
|
|
648
|
-
message,
|
|
649
|
-
...(options?.transient !== undefined ? { transient: options.transient } : {}),
|
|
650
|
-
});
|
|
651
|
-
},
|
|
652
|
-
startPhase(phaseWeight) {
|
|
653
|
-
return createContextBuildProgressPort(onProgress, state, state.progress, weight * phaseWeight);
|
|
654
|
-
},
|
|
655
|
-
};
|
|
656
|
-
}
|
|
657
625
|
export async function runContextBuild(project, args, io, deps = {}) {
|
|
658
626
|
const plan = buildPublicIngestPlan(project, {
|
|
659
627
|
projectDir: args.projectDir,
|
|
660
628
|
...(args.targetConnectionId ? { targetConnectionId: args.targetConnectionId } : {}),
|
|
661
629
|
all: args.all ?? true,
|
|
662
|
-
...(args.depth ? { depth: args.depth } : {}),
|
|
663
630
|
...(args.queryHistory ? { queryHistory: args.queryHistory } : {}),
|
|
664
631
|
...(args.queryHistoryWindowDays !== undefined ? { queryHistoryWindowDays: args.queryHistoryWindowDays } : {}),
|
|
665
632
|
...(args.scanMode ? { scanMode: args.scanMode } : {}),
|
|
@@ -721,7 +688,6 @@ export async function runContextBuild(project, args, io, deps = {}) {
|
|
|
721
688
|
all: args.all ?? true,
|
|
722
689
|
json: false,
|
|
723
690
|
inputMode: args.inputMode,
|
|
724
|
-
...(args.depth ? { depth: args.depth } : {}),
|
|
725
691
|
...(args.queryHistory ? { queryHistory: args.queryHistory } : {}),
|
|
726
692
|
...(args.queryHistoryWindowDays !== undefined ? { queryHistoryWindowDays: args.queryHistoryWindowDays } : {}),
|
|
727
693
|
...(args.scanMode ? { scanMode: args.scanMode } : {}),
|
|
@@ -808,7 +774,7 @@ export async function runContextBuild(project, args, io, deps = {}) {
|
|
|
808
774
|
hasPendingProgressPublish = !publishSourceProgress(false);
|
|
809
775
|
};
|
|
810
776
|
const progressDeps = {
|
|
811
|
-
scanProgress:
|
|
777
|
+
scanProgress: createAggregateProgressPort(updateSchemaPhase),
|
|
812
778
|
ingestProgress: updateIngestPhase,
|
|
813
779
|
runtimeIo: io,
|
|
814
780
|
onPhaseStart,
|
|
@@ -817,7 +783,7 @@ export async function runContextBuild(project, args, io, deps = {}) {
|
|
|
817
783
|
let result = null;
|
|
818
784
|
let thrownError = null;
|
|
819
785
|
try {
|
|
820
|
-
result = await execTarget(targetState.target, runArgs, capture.io, progressDeps);
|
|
786
|
+
result = await execTarget(targetState.target, runArgs, capture.io, progressDeps, project);
|
|
821
787
|
}
|
|
822
788
|
catch (error) {
|
|
823
789
|
thrownError = error;
|
package/dist/ingest.js
CHANGED
|
@@ -2,7 +2,7 @@ import { buildMemoryFlowViewModel } from './context/ingest/memory-flow/view-mode
|
|
|
2
2
|
import { createMemoryFlowLiveBuffer, sanitizeMemoryFlowError } from './context/ingest/memory-flow/live-buffer.js';
|
|
3
3
|
import { formatMemoryFlowFinalSummary } from './context/ingest/memory-flow/summary.js';
|
|
4
4
|
import { getLatestLocalIngestStatus, getLocalIngestStatus, runLocalIngest, runLocalMetabaseIngest } from './context/ingest/local-ingest.js';
|
|
5
|
-
import { savedMemoryCountsForReport } from './context/ingest/reports.js';
|
|
5
|
+
import { ingestReportOutcome, savedMemoryCountsForReport } from './context/ingest/reports.js';
|
|
6
6
|
import { ingestReportToMemoryFlowReplay } from './context/ingest/memory-flow/events.js';
|
|
7
7
|
import { renderMemoryFlowReplay } from './context/ingest/memory-flow/render.js';
|
|
8
8
|
import { loadKtxProject } from './context/project/project.js';
|
|
@@ -17,9 +17,6 @@ import { renderMemoryFlowTui, startLiveMemoryFlowTui, } from './memory-flow-tui.
|
|
|
17
17
|
import { resolveVizFallback, warnVizFallbackOnce } from './viz-fallback.js';
|
|
18
18
|
import { profileMark } from './startup-profile.js';
|
|
19
19
|
profileMark('module:ingest');
|
|
20
|
-
function reportStatus(report) {
|
|
21
|
-
return report.body.status === 'failed' || report.body.failedWorkUnits.length > 0 ? 'error' : 'done';
|
|
22
|
-
}
|
|
23
20
|
const REPORT_SOURCE_LABELS = new Map([
|
|
24
21
|
['live-database', 'Database schema'],
|
|
25
22
|
['historic-sql', 'Query history'],
|
|
@@ -106,7 +103,7 @@ function writeReportStatus(report, io) {
|
|
|
106
103
|
if (report.body.tracePath) {
|
|
107
104
|
io.stdout.write(`Trace: ${report.body.tracePath}\n`);
|
|
108
105
|
}
|
|
109
|
-
io.stdout.write(`Status: ${
|
|
106
|
+
io.stdout.write(`Status: ${ingestReportOutcome(report)}\n`);
|
|
110
107
|
io.stdout.write(`Source: ${reportSourceLabel(report.sourceKey)}\n`);
|
|
111
108
|
io.stdout.write(`Connection: ${report.connectionId}\n`);
|
|
112
109
|
io.stdout.write(`Sync: ${report.body.syncId}\n`);
|
|
@@ -138,7 +135,7 @@ function writeMetabaseFanoutStatus(result, io) {
|
|
|
138
135
|
}
|
|
139
136
|
io.stdout.write(`Saved memory: ${counts.wikiCount} wiki, ${counts.slCount} SL\n`);
|
|
140
137
|
for (const child of result.children) {
|
|
141
|
-
const status =
|
|
138
|
+
const status = ingestReportOutcome(child.report);
|
|
142
139
|
io.stdout.write(`- target=${child.targetConnectionId} database=${child.metabaseDatabaseId} status=${status} job=${child.jobId} report=${child.report.id}\n`);
|
|
143
140
|
}
|
|
144
141
|
}
|
|
@@ -425,7 +422,7 @@ function initialRunMemoryFlowInput(args, runId) {
|
|
|
425
422
|
};
|
|
426
423
|
}
|
|
427
424
|
function finalRunMemoryFlowInput(snapshot, report) {
|
|
428
|
-
const status =
|
|
425
|
+
const status = ingestReportOutcome(report) === 'error' ? 'error' : 'done';
|
|
429
426
|
return {
|
|
430
427
|
...snapshot,
|
|
431
428
|
runId: report.runId,
|
|
@@ -574,7 +571,7 @@ export async function runKtxIngest(args, io = process, deps = {}) {
|
|
|
574
571
|
finally {
|
|
575
572
|
plainProgress?.flush();
|
|
576
573
|
}
|
|
577
|
-
return result.status === '
|
|
574
|
+
return result.status === 'all_failed' ? 1 : 0;
|
|
578
575
|
}
|
|
579
576
|
const jobId = deps.jobIdFactory?.();
|
|
580
577
|
let liveTui = null;
|
|
@@ -636,7 +633,7 @@ export async function runKtxIngest(args, io = process, deps = {}) {
|
|
|
636
633
|
liveTui?.close();
|
|
637
634
|
liveTui = null;
|
|
638
635
|
io.stdout.write(formatMemoryFlowFinalSummary(latestMemoryFlowSnapshot));
|
|
639
|
-
return
|
|
636
|
+
return ingestReportOutcome(result.report) === 'error' ? 1 : 0;
|
|
640
637
|
}
|
|
641
638
|
plainProgress?.flush();
|
|
642
639
|
await writeReportRecord(result.report, runOutputMode, io, {
|
|
@@ -644,7 +641,7 @@ export async function runKtxIngest(args, io = process, deps = {}) {
|
|
|
644
641
|
renderStoredMemoryFlow: deps.renderStoredMemoryFlow,
|
|
645
642
|
env,
|
|
646
643
|
});
|
|
647
|
-
return
|
|
644
|
+
return ingestReportOutcome(result.report) === 'error' ? 1 : 0;
|
|
648
645
|
}
|
|
649
646
|
finally {
|
|
650
647
|
plainProgress?.flush();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { KtxCliIo } from '../cli-runtime.js';
|
|
2
|
+
export interface BufferedCommandIo extends KtxCliIo {
|
|
3
|
+
stdoutText(): string;
|
|
4
|
+
stderrText(): string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Captures stdout/stderr from a command (e.g. `runKtxConnection`) into buffers
|
|
8
|
+
* instead of the terminal. Callers decide whether to flush the captured text to
|
|
9
|
+
* the user or discard it.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createBufferedCommandIo(): BufferedCommandIo;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Captures stdout/stderr from a command (e.g. `runKtxConnection`) into buffers
|
|
3
|
+
* instead of the terminal. Callers decide whether to flush the captured text to
|
|
4
|
+
* the user or discard it.
|
|
5
|
+
*/
|
|
6
|
+
export function createBufferedCommandIo() {
|
|
7
|
+
let stdout = '';
|
|
8
|
+
let stderr = '';
|
|
9
|
+
return {
|
|
10
|
+
stdout: {
|
|
11
|
+
isTTY: false,
|
|
12
|
+
write(chunk) {
|
|
13
|
+
stdout += chunk;
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
stderr: {
|
|
17
|
+
write(chunk) {
|
|
18
|
+
stderr += chunk;
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
stdoutText() {
|
|
22
|
+
return stdout;
|
|
23
|
+
},
|
|
24
|
+
stderrText() {
|
|
25
|
+
return stderr;
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
package/dist/knowledge.d.ts
CHANGED
|
@@ -18,6 +18,11 @@ export type KtxKnowledgeArgs = {
|
|
|
18
18
|
limit?: number;
|
|
19
19
|
debug?: boolean;
|
|
20
20
|
cliVersion: string;
|
|
21
|
+
} | {
|
|
22
|
+
command: 'read';
|
|
23
|
+
projectDir: string;
|
|
24
|
+
key: string;
|
|
25
|
+
userId: string;
|
|
21
26
|
};
|
|
22
27
|
type KtxKnowledgeIo = import('./cli-runtime.js').KtxCliIo;
|
|
23
28
|
interface KtxKnowledgeDeps {
|
package/dist/knowledge.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { KtxIngestEmbeddingPortAdapter } from './context/llm/embedding-port.js';
|
|
2
2
|
import { loadKtxProject } from './context/project/project.js';
|
|
3
|
-
import { listLocalKnowledgePages, searchLocalKnowledgePages as defaultSearchLocalKnowledgePages } from './context/wiki/local-knowledge.js';
|
|
3
|
+
import { listLocalKnowledgePages, readLocalKnowledgePage, searchLocalKnowledgePages as defaultSearchLocalKnowledgePages, } from './context/wiki/local-knowledge.js';
|
|
4
4
|
import { resolveProjectEmbeddingProvider, } from './embedding-resolution.js';
|
|
5
5
|
import { resolveOutputMode } from './io/mode.js';
|
|
6
6
|
import { createRankBadgeFormatter, printList } from './io/print-list.js';
|
|
@@ -72,6 +72,15 @@ export async function runKtxKnowledge(args, io = process, deps = {}) {
|
|
|
72
72
|
});
|
|
73
73
|
return 0;
|
|
74
74
|
}
|
|
75
|
+
if (args.command === 'read') {
|
|
76
|
+
const page = await readLocalKnowledgePage(project, { key: args.key, userId: args.userId });
|
|
77
|
+
if (!page) {
|
|
78
|
+
throw new Error(`No wiki page found for key '${args.key}'`);
|
|
79
|
+
}
|
|
80
|
+
const raw = await project.fileStore.readFile(page.path);
|
|
81
|
+
io.stdout.write(raw.content);
|
|
82
|
+
return 0;
|
|
83
|
+
}
|
|
75
84
|
if (args.command === 'search') {
|
|
76
85
|
const embeddingService = await wikiSearchEmbeddingService(project, deps, { cliVersion: args.cliVersion }, io);
|
|
77
86
|
const search = deps.searchLocalKnowledgePages ?? defaultSearchLocalKnowledgePages;
|
package/dist/llm/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LanguageModel, TelemetrySettings, ToolCallRepairFunction, ToolSet } from 'ai';
|
|
2
2
|
export declare const KTX_MODEL_ROLES: readonly ["default", "triage", "candidateExtraction", "curator", "reconcile", "repair"];
|
|
3
3
|
export type KtxModelRole = (typeof KTX_MODEL_ROLES)[number];
|
|
4
|
-
type KtxLlmBackend = 'anthropic' | 'vertex' | 'gateway' | 'claude-code';
|
|
4
|
+
type KtxLlmBackend = 'anthropic' | 'vertex' | 'gateway' | 'claude-code' | 'codex';
|
|
5
5
|
export type KtxPromptCacheTtl = '5m' | '1h';
|
|
6
6
|
type KtxJsonValue = null | string | number | boolean | KtxJsonValue[] | {
|
|
7
7
|
[key: string]: KtxJsonValue | undefined;
|
package/dist/local-adapters.d.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { type DefaultLocalIngestAdaptersOptions } from './context/ingest/local-adapters.js';
|
|
2
|
+
import type { HistoricSqlDialect, HistoricSqlReader } from './context/ingest/adapters/historic-sql/types.js';
|
|
2
3
|
import type { SourceAdapter } from './context/ingest/types.js';
|
|
3
4
|
import type { KtxLocalProject } from './context/project/project.js';
|
|
4
5
|
import type { SqlAnalysisPort } from './context/sql-analysis/ports.js';
|
|
5
|
-
import { type
|
|
6
|
+
import { type ManagedPythonDaemonHttpOptions } from './managed-python-http.js';
|
|
6
7
|
import type { KtxOperationalLogger } from './io/logger.js';
|
|
7
8
|
export interface KtxCliLocalIngestAdaptersOptions extends DefaultLocalIngestAdaptersOptions {
|
|
8
9
|
historicSqlConnectionId?: string;
|
|
9
10
|
sqlAnalysis?: SqlAnalysisPort;
|
|
10
11
|
sqlAnalysisUrl?: string;
|
|
11
|
-
managedDaemon?:
|
|
12
|
+
managedDaemon?: ManagedPythonDaemonHttpOptions;
|
|
12
13
|
logger?: KtxOperationalLogger;
|
|
13
14
|
}
|
|
15
|
+
export interface KtxCliHistoricSqlRuntime {
|
|
16
|
+
dialect: HistoricSqlDialect;
|
|
17
|
+
sqlAnalysis: SqlAnalysisPort;
|
|
18
|
+
reader: HistoricSqlReader;
|
|
19
|
+
queryClient: unknown;
|
|
20
|
+
}
|
|
21
|
+
export declare function createKtxCliHistoricSqlRuntime(project: KtxLocalProject, connectionId: string, options?: KtxCliLocalIngestAdaptersOptions): KtxCliHistoricSqlRuntime | undefined;
|
|
14
22
|
export declare function createKtxCliLocalIngestAdapters(project: KtxLocalProject, options?: KtxCliLocalIngestAdaptersOptions): SourceAdapter[];
|
package/dist/local-adapters.js
CHANGED
|
@@ -12,7 +12,7 @@ import { isKtxSqliteConnectionConfig } from './connectors/sqlite/connector.js';
|
|
|
12
12
|
import { createSqlServerLiveDatabaseIntrospection } from './connectors/sqlserver/live-database-introspection.js';
|
|
13
13
|
import { isKtxSqlServerConnectionConfig } from './connectors/sqlserver/connector.js';
|
|
14
14
|
import { BigQueryHistoricSqlQueryHistoryReader } from './context/ingest/adapters/historic-sql/bigquery-query-history-reader.js';
|
|
15
|
-
import {
|
|
15
|
+
import { historicSqlDialectForConnectionDriver } from './context/ingest/adapters/historic-sql/connection-dialect.js';
|
|
16
16
|
import { createDaemonLiveDatabaseIntrospection } from './context/ingest/adapters/live-database/daemon-introspection.js';
|
|
17
17
|
import { createDefaultLocalIngestAdapters } from './context/ingest/local-adapters.js';
|
|
18
18
|
import { LiveDatabaseSourceAdapter } from './context/ingest/adapters/live-database/live-database.adapter.js';
|
|
@@ -224,7 +224,12 @@ function historicSqlOptionsForLocalRun(project, options) {
|
|
|
224
224
|
return undefined;
|
|
225
225
|
}
|
|
226
226
|
const connection = project.config.connections[connectionId];
|
|
227
|
-
|
|
227
|
+
// historicSqlConnectionId is only set when query history was explicitly
|
|
228
|
+
// requested for this run (e.g. `--query-history`), so resolve the dialect from
|
|
229
|
+
// driver capability rather than the persisted context.queryHistory.enabled
|
|
230
|
+
// flag — otherwise the adapter is missing and findAdapter('historic-sql')
|
|
231
|
+
// throws even though the run asked for it.
|
|
232
|
+
const dialect = historicSqlDialectForConnectionDriver(connection);
|
|
228
233
|
if (!dialect) {
|
|
229
234
|
return undefined;
|
|
230
235
|
}
|
|
@@ -234,6 +239,7 @@ function historicSqlOptionsForLocalRun(project, options) {
|
|
|
234
239
|
if (dialect === 'postgres') {
|
|
235
240
|
return {
|
|
236
241
|
...base,
|
|
242
|
+
dialect,
|
|
237
243
|
reader: new PostgresPgssReader(),
|
|
238
244
|
queryClient: createEphemeralPostgresHistoricSqlClient(project, connectionId),
|
|
239
245
|
};
|
|
@@ -245,6 +251,7 @@ function historicSqlOptionsForLocalRun(project, options) {
|
|
|
245
251
|
}
|
|
246
252
|
return {
|
|
247
253
|
...base,
|
|
254
|
+
dialect,
|
|
248
255
|
reader: new BigQueryHistoricSqlQueryHistoryReader({
|
|
249
256
|
projectId: bigQueryProjectId(connection, process.env),
|
|
250
257
|
region: bigQueryRegion(connection),
|
|
@@ -254,6 +261,7 @@ function historicSqlOptionsForLocalRun(project, options) {
|
|
|
254
261
|
}
|
|
255
262
|
return {
|
|
256
263
|
...base,
|
|
264
|
+
dialect,
|
|
257
265
|
reader: new SnowflakeHistoricSqlQueryHistoryReader(),
|
|
258
266
|
queryClient: {
|
|
259
267
|
async executeQuery(query) {
|
|
@@ -264,8 +272,16 @@ function historicSqlOptionsForLocalRun(project, options) {
|
|
|
264
272
|
},
|
|
265
273
|
};
|
|
266
274
|
}
|
|
275
|
+
export function createKtxCliHistoricSqlRuntime(project, connectionId, options = {}) {
|
|
276
|
+
return historicSqlOptionsForLocalRun(project, {
|
|
277
|
+
...options,
|
|
278
|
+
historicSqlConnectionId: connectionId,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
267
281
|
export function createKtxCliLocalIngestAdapters(project, options = {}) {
|
|
268
|
-
const historicSql =
|
|
282
|
+
const historicSql = options.historicSqlConnectionId
|
|
283
|
+
? createKtxCliHistoricSqlRuntime(project, options.historicSqlConnectionId, options)
|
|
284
|
+
: undefined;
|
|
269
285
|
const base = createDefaultLocalIngestAdapters(project, {
|
|
270
286
|
...options,
|
|
271
287
|
databaseIntrospection: ktxCliDaemonDatabaseIntrospectionOptions(options),
|
package/dist/next-steps.js
CHANGED
|
@@ -53,8 +53,7 @@ export function formatSetupNextStepLines(state, indent = ' ') {
|
|
|
53
53
|
}
|
|
54
54
|
if (!state.contextReady) {
|
|
55
55
|
return [
|
|
56
|
-
`${indent}
|
|
57
|
-
`${indent}Run ingest to build database schema context before context-source ingest.`,
|
|
56
|
+
`${indent}Setup is complete. The only step left is to build context for your agents.`,
|
|
58
57
|
...commandLines(KTX_CONTEXT_BUILD_COMMANDS, indent),
|
|
59
58
|
];
|
|
60
59
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { KtxProgressPort } from './context/scan/types.js';
|
|
2
|
+
import type { KtxIngestProgressUpdate } from './ingest.js';
|
|
3
|
+
export interface AggregateProgressState {
|
|
4
|
+
progress: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function createAggregateProgressPort(onProgress: (update: KtxIngestProgressUpdate) => void, state?: AggregateProgressState, start?: number, weight?: number): KtxProgressPort;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function createAggregateProgressPort(onProgress, state = { progress: 0 }, start = 0, weight = 1) {
|
|
2
|
+
return {
|
|
3
|
+
async update(value, message, options) {
|
|
4
|
+
const absoluteValue = start + Math.max(0, Math.min(1, value)) * weight;
|
|
5
|
+
state.progress = Math.max(state.progress, Math.min(1, absoluteValue));
|
|
6
|
+
if (!message)
|
|
7
|
+
return;
|
|
8
|
+
onProgress({
|
|
9
|
+
percent: Math.max(0, Math.min(100, Math.round(state.progress * 100))),
|
|
10
|
+
message,
|
|
11
|
+
...(options?.transient !== undefined ? { transient: options.transient } : {}),
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
startPhase(phaseWeight) {
|
|
15
|
+
return createAggregateProgressPort(onProgress, state, state.progress, weight * phaseWeight);
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -11,7 +11,7 @@ const DATABASE_INGEST_REPLACEMENTS = [
|
|
|
11
11
|
'Database enrichment failed after schema context completed',
|
|
12
12
|
],
|
|
13
13
|
[/\bstructural scan\b/gi, 'schema context'],
|
|
14
|
-
[/\benriched scan\b/gi, '
|
|
14
|
+
[/\benriched scan\b/gi, 'database ingest'],
|
|
15
15
|
[/\bscan results\b/gi, 'database context'],
|
|
16
16
|
];
|
|
17
17
|
export function publicDatabaseIngestMessage(message) {
|