@kaelio/ktx 0.13.1 → 0.14.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.13.1-py3-none-any.whl → kaelio_ktx-0.14.0-py3-none-any.whl} +0 -0
- package/assets/python/manifest.json +4 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli-program.js +1 -1
- package/dist/commands/ingest-commands.d.ts +9 -0
- package/dist/commands/ingest-commands.js +37 -1
- package/dist/commands/knowledge-commands.js +3 -0
- package/dist/commands/setup-commands.js +14 -1
- package/dist/connection-drivers.d.ts +2 -0
- package/dist/connection-drivers.js +7 -3
- package/dist/connection.d.ts +3 -0
- package/dist/connection.js +27 -0
- package/dist/connectors/bigquery/connector.d.ts +17 -6
- package/dist/connectors/bigquery/connector.js +152 -76
- package/dist/connectors/bigquery/dialect.d.ts +2 -2
- package/dist/connectors/clickhouse/connector.d.ts +1 -0
- package/dist/connectors/clickhouse/connector.js +45 -16
- package/dist/connectors/clickhouse/dialect.d.ts +2 -2
- package/dist/connectors/mongodb/connector.d.ts +69 -0
- package/dist/connectors/mongodb/connector.js +307 -0
- package/dist/connectors/mongodb/dialect.d.ts +17 -0
- package/dist/connectors/mongodb/dialect.js +50 -0
- package/dist/connectors/mongodb/live-database-introspection.d.ts +10 -0
- package/dist/connectors/mongodb/live-database-introspection.js +24 -0
- package/dist/connectors/mongodb/schema-inference.d.ts +20 -0
- package/dist/connectors/mongodb/schema-inference.js +110 -0
- package/dist/connectors/mysql/connector.d.ts +1 -0
- package/dist/connectors/mysql/connector.js +18 -2
- package/dist/connectors/mysql/dialect.d.ts +2 -2
- package/dist/connectors/postgres/connector.d.ts +1 -0
- package/dist/connectors/postgres/connector.js +20 -3
- package/dist/connectors/postgres/dialect.d.ts +2 -2
- package/dist/connectors/snowflake/connector.d.ts +1 -0
- package/dist/connectors/snowflake/connector.js +27 -3
- package/dist/connectors/snowflake/dialect.d.ts +2 -2
- package/dist/connectors/sqlite/connector.d.ts +11 -1
- package/dist/connectors/sqlite/connector.js +120 -17
- package/dist/connectors/sqlite/dialect.d.ts +2 -2
- package/dist/connectors/sqlite/read-query-child.d.ts +1 -0
- package/dist/connectors/sqlite/read-query-child.js +23 -0
- package/dist/connectors/sqlserver/connector.d.ts +2 -0
- package/dist/connectors/sqlserver/connector.js +20 -3
- package/dist/connectors/sqlserver/dialect.d.ts +2 -2
- package/dist/context/cache/content-result-cache.d.ts +36 -0
- package/dist/context/cache/content-result-cache.js +14 -0
- package/dist/context/cache/sqlite-content-result-cache.d.ts +18 -0
- package/dist/context/cache/sqlite-content-result-cache.js +223 -0
- package/dist/context/connections/bigquery-identifiers.d.ts +1 -0
- package/dist/context/connections/bigquery-identifiers.js +7 -0
- package/dist/context/connections/configured-connections.d.ts +9 -0
- package/dist/context/connections/configured-connections.js +18 -0
- package/dist/context/connections/dialects.d.ts +30 -4
- package/dist/context/connections/dialects.js +38 -11
- package/dist/context/connections/drivers.js +21 -0
- package/dist/context/connections/gdrive-config.d.ts +19 -0
- package/dist/context/connections/gdrive-config.js +57 -0
- package/dist/context/connections/query-deadline.d.ts +31 -0
- package/dist/context/connections/query-deadline.js +37 -0
- package/dist/context/ingest/adapters/gdrive/chunk.d.ts +3 -0
- package/dist/context/ingest/adapters/gdrive/chunk.js +74 -0
- package/dist/context/ingest/adapters/gdrive/detect.d.ts +1 -0
- package/dist/context/ingest/adapters/gdrive/detect.js +20 -0
- package/dist/context/ingest/adapters/gdrive/fetch.d.ts +6 -0
- package/dist/context/ingest/adapters/gdrive/fetch.js +95 -0
- package/dist/context/ingest/adapters/gdrive/gdrive-client.d.ts +30 -0
- package/dist/context/ingest/adapters/gdrive/gdrive-client.js +132 -0
- package/dist/context/ingest/adapters/gdrive/gdrive.adapter.d.ts +11 -0
- package/dist/context/ingest/adapters/gdrive/gdrive.adapter.js +27 -0
- package/dist/context/ingest/adapters/gdrive/normalize.d.ts +2 -0
- package/dist/context/ingest/adapters/gdrive/normalize.js +256 -0
- package/dist/context/ingest/adapters/gdrive/types.d.ts +153 -0
- package/dist/context/ingest/adapters/gdrive/types.js +36 -0
- package/dist/context/ingest/adapters/live-database/daemon-introspection.js +24 -0
- package/dist/context/ingest/adapters/live-database/fetch-report.d.ts +8 -0
- package/dist/context/ingest/adapters/live-database/fetch-report.js +37 -0
- package/dist/context/ingest/adapters/live-database/live-database.adapter.d.ts +2 -1
- package/dist/context/ingest/adapters/live-database/live-database.adapter.js +9 -2
- package/dist/context/ingest/adapters/live-database/manifest.d.ts +2 -0
- package/dist/context/ingest/adapters/live-database/manifest.js +8 -4
- package/dist/context/ingest/adapters/live-database/scan-outcome.d.ts +17 -0
- package/dist/context/ingest/adapters/live-database/scan-outcome.js +40 -0
- package/dist/context/ingest/adapters/live-database/stage.js +5 -5
- package/dist/context/ingest/adapters/metabase/types.d.ts +1 -1
- package/dist/context/ingest/adapters/metabase/types.js +1 -1
- package/dist/context/ingest/artifact-gates.d.ts +32 -1
- package/dist/context/ingest/artifact-gates.js +85 -18
- package/dist/context/ingest/final-gate-prune.d.ts +35 -0
- package/dist/context/ingest/final-gate-prune.js +229 -0
- package/dist/context/ingest/ingest-bundle.runner.d.ts +3 -0
- package/dist/context/ingest/ingest-bundle.runner.js +459 -240
- package/dist/context/ingest/isolated-diff/patch-integrator.d.ts +0 -11
- package/dist/context/ingest/isolated-diff/patch-integrator.js +0 -44
- package/dist/context/ingest/isolated-diff/work-unit-executor.d.ts +1 -0
- package/dist/context/ingest/isolated-diff/work-unit-executor.js +13 -4
- package/dist/context/ingest/local-adapters.js +6 -0
- package/dist/context/ingest/local-bundle-runtime.js +7 -2
- package/dist/context/ingest/local-ingest.js +1 -1
- package/dist/context/ingest/local-stage-ingest.d.ts +3 -1
- package/dist/context/ingest/local-stage-ingest.js +3 -1
- package/dist/context/ingest/ports.d.ts +3 -0
- package/dist/context/ingest/report-snapshot.js +13 -3
- package/dist/context/ingest/reports.d.ts +3 -3
- package/dist/context/ingest/reports.js +3 -1
- package/dist/context/ingest/stages/build-wu-context.d.ts +1 -0
- package/dist/context/ingest/stages/build-wu-context.js +2 -1
- package/dist/context/ingest/stages/stage-3-work-units.d.ts +2 -1
- package/dist/context/ingest/stages/stage-3-work-units.js +4 -10
- package/dist/context/ingest/stages/validate-wu-sources.d.ts +12 -0
- package/dist/context/ingest/stages/validate-wu-sources.js +23 -8
- package/dist/context/ingest/tools/read-raw-file.tool.js +10 -5
- package/dist/context/ingest/tools/read-raw-span.tool.js +10 -5
- package/dist/context/ingest/tools/warehouse-verification/discover-data.tool.js +1 -1
- package/dist/context/ingest/tools/warehouse-verification/entity-details.tool.js +1 -1
- package/dist/context/ingest/tools/warehouse-verification/sql-execution.tool.js +1 -1
- package/dist/context/ingest/types.d.ts +3 -0
- package/dist/context/ingest/wiki-body-refs.d.ts +28 -0
- package/dist/context/ingest/wiki-body-refs.js +37 -8
- package/dist/context/ingest/wiki-sl-ref-repair.d.ts +1 -0
- package/dist/context/ingest/wiki-sl-ref-repair.js +4 -0
- package/dist/context/ingest/work-unit-cache.d.ts +67 -0
- package/dist/context/ingest/work-unit-cache.js +230 -0
- package/dist/context/llm/ai-sdk-runtime.d.ts +1 -0
- package/dist/context/llm/ai-sdk-runtime.js +5 -0
- package/dist/context/llm/claude-code-runtime.d.ts +4 -1
- package/dist/context/llm/claude-code-runtime.js +38 -8
- package/dist/context/llm/codex-runtime.d.ts +4 -1
- package/dist/context/llm/codex-runtime.js +48 -35
- package/dist/context/llm/runtime-port.d.ts +26 -0
- package/dist/context/llm/subprocess-generate-object-child.d.ts +1 -0
- package/dist/context/llm/subprocess-generate-object-child.js +34 -0
- package/dist/context/llm/subprocess-generate-object.d.ts +42 -0
- package/dist/context/llm/subprocess-generate-object.js +122 -0
- package/dist/context/mcp/context-tools.d.ts +2 -0
- package/dist/context/mcp/context-tools.js +111 -17
- package/dist/context/mcp/local-project-ports.d.ts +7 -0
- package/dist/context/mcp/local-project-ports.js +29 -0
- package/dist/context/mcp/logger.d.ts +24 -0
- package/dist/context/mcp/logger.js +49 -0
- package/dist/context/mcp/server.js +2 -0
- package/dist/context/mcp/types.d.ts +17 -0
- package/dist/context/memory/memory-agent.service.js +1 -1
- package/dist/context/project/config.d.ts +42 -0
- package/dist/context/project/config.js +5 -0
- package/dist/context/project/driver-schemas.d.ts +20 -0
- package/dist/context/project/driver-schemas.js +50 -1
- package/dist/context/project/project.js +1 -1
- package/dist/context/project/setup-config.js +1 -0
- package/dist/context/scan/description-generation.d.ts +4 -0
- package/dist/context/scan/description-generation.js +100 -13
- package/dist/context/scan/enabled-tables.d.ts +5 -0
- package/dist/context/scan/enabled-tables.js +13 -1
- package/dist/context/scan/enrichment-state.d.ts +50 -7
- package/dist/context/scan/enrichment-state.js +30 -13
- package/dist/context/scan/local-enrichment-artifacts.d.ts +41 -0
- package/dist/context/scan/local-enrichment-artifacts.js +155 -32
- package/dist/context/scan/local-enrichment.d.ts +39 -4
- package/dist/context/scan/local-enrichment.js +345 -92
- package/dist/context/scan/local-scan.d.ts +4 -1
- package/dist/context/scan/local-scan.js +54 -13
- package/dist/context/scan/local-structural-artifacts.d.ts +3 -1
- package/dist/context/scan/local-structural-artifacts.js +5 -0
- package/dist/context/scan/object-introspection.d.ts +21 -0
- package/dist/context/scan/object-introspection.js +35 -0
- package/dist/context/scan/relationship-benchmarks.js +5 -3
- package/dist/context/scan/relationship-composite-candidates.d.ts +6 -3
- package/dist/context/scan/relationship-composite-candidates.js +13 -1
- package/dist/context/scan/relationship-detection-budget.d.ts +35 -0
- package/dist/context/scan/relationship-detection-budget.js +53 -0
- package/dist/context/scan/relationship-diagnostics.d.ts +5 -0
- package/dist/context/scan/relationship-diagnostics.js +2 -0
- package/dist/context/scan/relationship-discovery.d.ts +9 -3
- package/dist/context/scan/relationship-discovery.js +27 -4
- package/dist/context/scan/relationship-llm-proposal.js +36 -27
- package/dist/context/scan/relationship-profiling.d.ts +7 -3
- package/dist/context/scan/relationship-profiling.js +53 -41
- package/dist/context/scan/relationship-validation.d.ts +6 -4
- package/dist/context/scan/relationship-validation.js +46 -32
- package/dist/context/scan/sqlite-local-enrichment-state-store.d.ts +8 -1
- package/dist/context/scan/sqlite-local-enrichment-state-store.js +71 -159
- package/dist/context/scan/types.d.ts +5 -3
- package/dist/context/scan/types.js +2 -0
- package/dist/context/sl/local-query.js +5 -0
- package/dist/context/sl/pglite-sl-search-prototype.js +1 -1
- package/dist/context/sl/semantic-layer.service.js +1 -1
- package/dist/context/sl/source-files.d.ts +5 -0
- package/dist/context/sl/source-files.js +17 -11
- package/dist/context/sl/tools/connection-id-schema.js +1 -1
- package/dist/context/sql-analysis/dialect-notes.d.ts +9 -0
- package/dist/context/sql-analysis/dialect-notes.js +40 -0
- package/dist/context/sql-analysis/dialects/bigquery.md +13 -0
- package/dist/context/sql-analysis/dialects/clickhouse.md +9 -0
- package/dist/context/sql-analysis/dialects/mysql.md +9 -0
- package/dist/context/sql-analysis/dialects/postgres.md +10 -0
- package/dist/context/sql-analysis/dialects/snowflake.md +10 -0
- package/dist/context/sql-analysis/dialects/sqlite.md +11 -0
- package/dist/context/sql-analysis/dialects/tsql.md +10 -0
- package/dist/context/wiki/keys.js +1 -1
- package/dist/context/wiki/knowledge-wiki.service.d.ts +4 -4
- package/dist/context/wiki/knowledge-wiki.service.js +2 -1
- package/dist/context/wiki/local-knowledge.d.ts +13 -0
- package/dist/context/wiki/local-knowledge.js +50 -6
- package/dist/context/wiki/sqlite-knowledge-index.d.ts +2 -0
- package/dist/context/wiki/sqlite-knowledge-index.js +21 -5
- package/dist/context/wiki/tools/wiki-write.tool.d.ts +2 -0
- package/dist/context/wiki/tools/wiki-write.tool.js +27 -0
- package/dist/context/wiki/types.d.ts +6 -0
- package/dist/context-build-view.d.ts +3 -0
- package/dist/context-build-view.js +1 -0
- package/dist/knowledge.d.ts +2 -0
- package/dist/knowledge.js +12 -1
- package/dist/local-adapters.js +11 -0
- package/dist/mcp-http-server.js +15 -1
- package/dist/mcp-server-factory.d.ts +2 -0
- package/dist/mcp-server-factory.js +15 -1
- package/dist/mcp-stdio-server.js +10 -2
- package/dist/notion-page-picker.js +1 -1
- package/dist/prompts/memory_agent_external_ingest.md +2 -0
- package/dist/public-ingest.d.ts +3 -1
- package/dist/public-ingest.js +3 -0
- package/dist/scan.d.ts +3 -1
- package/dist/scan.js +7 -0
- package/dist/setup-databases.d.ts +1 -1
- package/dist/setup-databases.js +43 -1
- package/dist/setup-sources.d.ts +5 -1
- package/dist/setup-sources.js +124 -48
- package/dist/setup.d.ts +3 -0
- package/dist/setup.js +6 -1
- package/dist/skills/analytics/SKILL.md +200 -2
- package/dist/skills/gdrive_synthesize/SKILL.md +97 -0
- package/dist/skills/wiki_capture/SKILL.md +24 -0
- package/dist/sql.js +4 -0
- package/dist/status-project.d.ts +4 -0
- package/dist/status-project.js +54 -2
- package/dist/telemetry/events.d.ts +2 -2
- package/dist/text-ingest.d.ts +4 -0
- package/dist/text-ingest.js +58 -29
- package/dist/verbatim-ingest.d.ts +46 -0
- package/dist/verbatim-ingest.js +193 -0
- package/package.json +5 -1
- package/dist/context/ingest/final-gate-repair.d.ts +0 -28
- package/dist/context/ingest/final-gate-repair.js +0 -91
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { KtxExpectedError, KtxQueryError, isNativeProgrammingFault } from '../../errors.js';
|
|
2
|
+
import { isDatabaseDriver, normalizeConnectionDriver } from '../../connection-drivers.js';
|
|
3
|
+
import { sqlDialectNotes } from '../../context/sql-analysis/dialect-notes.js';
|
|
2
4
|
import { executeProjectReadOnlySql } from '../../context/connections/project-sql-executor.js';
|
|
3
5
|
import { FEDERATED_CONNECTION_ID, federatedConnectionListing } from '../../context/connections/federation.js';
|
|
6
|
+
import { assertSqlQueryableConnection } from '../../context/connections/dialects.js';
|
|
4
7
|
import { resolveConfiguredConnection } from '../../context/connections/resolve-connection.js';
|
|
5
8
|
import { localConnectionInfoFromConfig, } from '../../context/connections/local-warehouse-descriptor.js';
|
|
6
9
|
import { createKtxEntityDetailsService } from '../../context/scan/entity-details.js';
|
|
@@ -10,6 +13,7 @@ import { compileLocalSlQuery } from '../../context/sl/local-query.js';
|
|
|
10
13
|
import { createKtxDictionarySearchService } from '../../context/sl/dictionary-search.js';
|
|
11
14
|
import { readLocalSlSource } from '../../context/sl/local-sl.js';
|
|
12
15
|
import { assertSafeConnectionId } from '../../context/sl/source-files.js';
|
|
16
|
+
import { assertConfiguredConnectionId } from '../../context/connections/configured-connections.js';
|
|
13
17
|
import { readLocalKnowledgePage, searchLocalKnowledgePages } from '../wiki/local-knowledge.js';
|
|
14
18
|
async function executeValidatedReadOnlySql(project, options, input, onProgress) {
|
|
15
19
|
await onProgress?.({ progress: 0, message: 'Validating SQL' });
|
|
@@ -23,6 +27,9 @@ async function executeValidatedReadOnlySql(project, options, input, onProgress)
|
|
|
23
27
|
const isFederated = input.connectionId === FEDERATED_CONNECTION_ID;
|
|
24
28
|
const connectionId = isFederated ? input.connectionId : assertSafeConnectionId(input.connectionId);
|
|
25
29
|
const connection = isFederated ? undefined : resolveConfiguredConnection(project.config, connectionId);
|
|
30
|
+
if (!isFederated) {
|
|
31
|
+
assertSqlQueryableConnection(connectionId, connection.driver);
|
|
32
|
+
}
|
|
26
33
|
const dialect = sqlAnalysisDialectForDriver(isFederated ? 'duckdb' : connection.driver);
|
|
27
34
|
const validation = await options.sqlAnalysis.validateReadOnly(input.sql, dialect);
|
|
28
35
|
if (!validation.ok) {
|
|
@@ -62,6 +69,18 @@ async function executeValidatedReadOnlySql(project, options, input, onProgress)
|
|
|
62
69
|
await onProgress?.({ progress: 1, message: `Fetched ${response.rowCount} rows` });
|
|
63
70
|
return response;
|
|
64
71
|
}
|
|
72
|
+
/** @internal Resolves a connection's dialect SQL notes; throws KtxExpectedError for an unknown or non-SQL-warehouse connection. */
|
|
73
|
+
export function resolveDialectNotesForConnection(connectionId, connection) {
|
|
74
|
+
if (!connection) {
|
|
75
|
+
throw new KtxExpectedError(`Connection "${connectionId}" is not configured in ktx.yaml`);
|
|
76
|
+
}
|
|
77
|
+
const driver = normalizeConnectionDriver(connection);
|
|
78
|
+
if (!isDatabaseDriver(driver)) {
|
|
79
|
+
throw new KtxExpectedError(`Connection "${connectionId}" uses the "${driver}" context source, not a SQL warehouse; sql_dialect_notes applies only to SQL database connections.`);
|
|
80
|
+
}
|
|
81
|
+
const dialect = sqlAnalysisDialectForDriver(driver);
|
|
82
|
+
return { connectionId, dialect, notes: sqlDialectNotes(dialect) };
|
|
83
|
+
}
|
|
65
84
|
export function createLocalProjectMcpContextPorts(project, options) {
|
|
66
85
|
const embeddingService = options.embeddingService;
|
|
67
86
|
const ports = {
|
|
@@ -86,11 +105,15 @@ export function createLocalProjectMcpContextPorts(project, options) {
|
|
|
86
105
|
},
|
|
87
106
|
knowledge: {
|
|
88
107
|
async search(input) {
|
|
108
|
+
const connectionId = input.connectionId === undefined
|
|
109
|
+
? undefined
|
|
110
|
+
: assertConfiguredConnectionId(project.config.connections, input.connectionId);
|
|
89
111
|
const results = await searchLocalKnowledgePages(project, {
|
|
90
112
|
query: input.query,
|
|
91
113
|
userId: input.userId,
|
|
92
114
|
limit: input.limit,
|
|
93
115
|
embeddingService,
|
|
116
|
+
...(connectionId !== undefined ? { connectionId } : {}),
|
|
94
117
|
});
|
|
95
118
|
return {
|
|
96
119
|
results: results.slice(0, input.limit).map((result) => ({
|
|
@@ -161,6 +184,12 @@ export function createLocalProjectMcpContextPorts(project, options) {
|
|
|
161
184
|
return createKtxDiscoverDataService(project, { userId: 'local', embeddingService }).search(input);
|
|
162
185
|
},
|
|
163
186
|
},
|
|
187
|
+
dialectNotes: {
|
|
188
|
+
async read(input) {
|
|
189
|
+
const connectionId = assertSafeConnectionId(input.connectionId);
|
|
190
|
+
return resolveDialectNotesForConnection(connectionId, project.config.connections[connectionId]);
|
|
191
|
+
},
|
|
192
|
+
},
|
|
164
193
|
};
|
|
165
194
|
if (options.sqlAnalysis && options.localScan?.createConnector) {
|
|
166
195
|
ports.sqlExecution = {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Logger } from 'pino';
|
|
2
|
+
import type { KtxCliIo } from '../../cli-runtime.js';
|
|
3
|
+
export type KtxMcpLogger = Logger;
|
|
4
|
+
/** @internal */
|
|
5
|
+
export declare function mcpLogLevel(env?: NodeJS.ProcessEnv): string;
|
|
6
|
+
/** @internal */
|
|
7
|
+
export declare function mcpSlowToolMs(env?: NodeJS.ProcessEnv): number;
|
|
8
|
+
/**
|
|
9
|
+
* Serialize an error for a structured `err` field. Genuine `Error`s get pino's
|
|
10
|
+
* standard serializer (type + message + stack); everything else is reduced to a
|
|
11
|
+
* message — the in-band tool-error path has already lost the original stack.
|
|
12
|
+
*/
|
|
13
|
+
export declare function serializeMcpError(error: unknown): Record<string, unknown>;
|
|
14
|
+
/**
|
|
15
|
+
* One synchronous pino logger per MCP server process, written to the `io.stderr`
|
|
16
|
+
* sink. stderr is the only universally-correct sink: the stdio transport reserves
|
|
17
|
+
* stdout for JSON-RPC, and the HTTP daemon redirects stderr into `.ktx/logs/mcp.log`.
|
|
18
|
+
* Synchronous writes are load-bearing — a `tool.start` line must reach the fd before
|
|
19
|
+
* a blocking handler runs, so a runaway query still leaves its start record on disk.
|
|
20
|
+
* Format follows the terminal, not a flag: pretty for a TTY, plain JSON otherwise.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createMcpLogger(io: KtxCliIo, options?: {
|
|
23
|
+
isTTY?: boolean;
|
|
24
|
+
}): KtxMcpLogger;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Writable } from 'node:stream';
|
|
2
|
+
import pino from 'pino';
|
|
3
|
+
import PinoPretty from 'pino-pretty';
|
|
4
|
+
const LOG_LEVELS = new Set(['trace', 'debug', 'info', 'warn', 'error', 'fatal', 'silent']);
|
|
5
|
+
const DEFAULT_LEVEL = 'info';
|
|
6
|
+
const DEFAULT_SLOW_TOOL_MS = 10_000;
|
|
7
|
+
/** @internal */
|
|
8
|
+
export function mcpLogLevel(env = process.env) {
|
|
9
|
+
const raw = env.KTX_MCP_LOG_LEVEL?.trim().toLowerCase();
|
|
10
|
+
return raw && LOG_LEVELS.has(raw) ? raw : DEFAULT_LEVEL;
|
|
11
|
+
}
|
|
12
|
+
/** @internal */
|
|
13
|
+
export function mcpSlowToolMs(env = process.env) {
|
|
14
|
+
const raw = Number(env.KTX_MCP_SLOW_TOOL_MS);
|
|
15
|
+
return Number.isFinite(raw) && raw >= 0 ? raw : DEFAULT_SLOW_TOOL_MS;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Serialize an error for a structured `err` field. Genuine `Error`s get pino's
|
|
19
|
+
* standard serializer (type + message + stack); everything else is reduced to a
|
|
20
|
+
* message — the in-band tool-error path has already lost the original stack.
|
|
21
|
+
*/
|
|
22
|
+
export function serializeMcpError(error) {
|
|
23
|
+
if (error instanceof Error) {
|
|
24
|
+
return { ...pino.stdSerializers.err(error) };
|
|
25
|
+
}
|
|
26
|
+
return { message: typeof error === 'string' ? error : String(error) };
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* One synchronous pino logger per MCP server process, written to the `io.stderr`
|
|
30
|
+
* sink. stderr is the only universally-correct sink: the stdio transport reserves
|
|
31
|
+
* stdout for JSON-RPC, and the HTTP daemon redirects stderr into `.ktx/logs/mcp.log`.
|
|
32
|
+
* Synchronous writes are load-bearing — a `tool.start` line must reach the fd before
|
|
33
|
+
* a blocking handler runs, so a runaway query still leaves its start record on disk.
|
|
34
|
+
* Format follows the terminal, not a flag: pretty for a TTY, plain JSON otherwise.
|
|
35
|
+
*/
|
|
36
|
+
export function createMcpLogger(io, options = {}) {
|
|
37
|
+
const level = mcpLogLevel();
|
|
38
|
+
const isTTY = options.isTTY ?? process.stderr.isTTY === true;
|
|
39
|
+
if (isTTY) {
|
|
40
|
+
const sink = new Writable({
|
|
41
|
+
write(chunk, _encoding, callback) {
|
|
42
|
+
io.stderr.write(typeof chunk === 'string' ? chunk : chunk.toString('utf8'));
|
|
43
|
+
callback();
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
return pino({ level }, PinoPretty({ colorize: true, sync: true, destination: sink }));
|
|
47
|
+
}
|
|
48
|
+
return pino({ level }, io.stderr);
|
|
49
|
+
}
|
|
@@ -9,6 +9,7 @@ export function createKtxMcpServer(deps) {
|
|
|
9
9
|
userContext: deps.userContext,
|
|
10
10
|
projectDir: deps.projectDir,
|
|
11
11
|
io: deps.io,
|
|
12
|
+
logger: deps.logger,
|
|
12
13
|
getClientInfo: deps.getClientInfo,
|
|
13
14
|
});
|
|
14
15
|
}
|
|
@@ -25,6 +26,7 @@ export function createDefaultKtxMcpServer(deps) {
|
|
|
25
26
|
contextTools: deps.contextTools,
|
|
26
27
|
projectDir: deps.projectDir,
|
|
27
28
|
io: deps.io,
|
|
29
|
+
logger: deps.logger,
|
|
28
30
|
// The SDK populates the client identity after the initialize handshake, so
|
|
29
31
|
// read it lazily at emit time rather than at registration (undefined here).
|
|
30
32
|
getClientInfo: () => server.server.getClientVersion(),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MemoryIngestService } from '../../context/memory/memory-runs.js';
|
|
2
2
|
import type { KtxCliIo } from '../../cli-runtime.js';
|
|
3
|
+
import type { KtxMcpLogger } from './logger.js';
|
|
3
4
|
import type { KtxEntityDetailsInput, KtxEntityDetailsResponse } from '../scan/entity-details.js';
|
|
4
5
|
import type { KtxDiscoverDataInput, KtxDiscoverDataResponse } from '../../context/search/discover.js';
|
|
5
6
|
import type { KtxDictionarySearchInput, KtxDictionarySearchResponse } from '../../context/sl/dictionary-search.js';
|
|
@@ -24,6 +25,8 @@ interface KtxMcpProgressEvent {
|
|
|
24
25
|
}
|
|
25
26
|
export type KtxMcpProgressCallback = (event: KtxMcpProgressEvent) => void | Promise<void>;
|
|
26
27
|
export interface KtxMcpToolHandlerContext {
|
|
28
|
+
/** Present for the HTTP StreamableHTTP transport (one per session); absent for stdio. */
|
|
29
|
+
sessionId?: string;
|
|
27
30
|
_meta?: {
|
|
28
31
|
progressToken?: string | number;
|
|
29
32
|
[key: string]: unknown;
|
|
@@ -102,6 +105,7 @@ export interface KtxKnowledgeMcpPort {
|
|
|
102
105
|
userId: string;
|
|
103
106
|
query: string;
|
|
104
107
|
limit: number;
|
|
108
|
+
connectionId?: string;
|
|
105
109
|
}): Promise<KtxKnowledgeSearchResponse>;
|
|
106
110
|
read(input: {
|
|
107
111
|
userId: string;
|
|
@@ -163,6 +167,16 @@ export interface KtxSqlExecutionMcpPort {
|
|
|
163
167
|
onProgress?: KtxMcpProgressCallback;
|
|
164
168
|
}): Promise<KtxSqlExecutionResponse>;
|
|
165
169
|
}
|
|
170
|
+
/** @internal */
|
|
171
|
+
export interface KtxDialectNotesMcpPort {
|
|
172
|
+
read(input: {
|
|
173
|
+
connectionId: string;
|
|
174
|
+
}): Promise<{
|
|
175
|
+
connectionId: string;
|
|
176
|
+
dialect: string;
|
|
177
|
+
notes: string;
|
|
178
|
+
}>;
|
|
179
|
+
}
|
|
166
180
|
export interface KtxMcpContextPorts {
|
|
167
181
|
connections?: KtxConnectionsMcpPort;
|
|
168
182
|
knowledge?: KtxKnowledgeMcpPort;
|
|
@@ -171,6 +185,7 @@ export interface KtxMcpContextPorts {
|
|
|
171
185
|
dictionarySearch?: KtxDictionarySearchMcpPort;
|
|
172
186
|
discover?: KtxDiscoverDataMcpPort;
|
|
173
187
|
sqlExecution?: KtxSqlExecutionMcpPort;
|
|
188
|
+
dialectNotes?: KtxDialectNotesMcpPort;
|
|
174
189
|
memoryIngest?: MemoryIngestPort;
|
|
175
190
|
}
|
|
176
191
|
export interface KtxMcpServerDeps {
|
|
@@ -179,6 +194,8 @@ export interface KtxMcpServerDeps {
|
|
|
179
194
|
contextTools?: KtxMcpContextPorts;
|
|
180
195
|
projectDir?: string;
|
|
181
196
|
io?: KtxCliIo;
|
|
197
|
+
/** Shared per-process logger for tool-call observability; tool-call logging is off when absent. */
|
|
198
|
+
logger?: KtxMcpLogger;
|
|
182
199
|
/** Reads the connected client's identity once the initialize handshake completes. */
|
|
183
200
|
getClientInfo?: () => KtxMcpClientInfo | undefined;
|
|
184
201
|
}
|
|
@@ -131,7 +131,7 @@ export class MemoryAgentService {
|
|
|
131
131
|
: '';
|
|
132
132
|
const prompt = [
|
|
133
133
|
`# Wiki Index\n\n${wikiIndex}`,
|
|
134
|
-
hasSL ? `\n# Semantic Layer Sources\n\n${slIndex}` : '',
|
|
134
|
+
hasSL ? `\n# Semantic Layer Sources (connectionId: ${input.connectionId})\n\n${slIndex}` : '',
|
|
135
135
|
'\n---\n',
|
|
136
136
|
assistantSection,
|
|
137
137
|
`\n## User Message\n\n${input.userMessage.trim()}`,
|
|
@@ -102,35 +102,51 @@ declare const scanRelationshipsSchema: z.ZodObject<{
|
|
|
102
102
|
profileConcurrency: z.ZodDefault<z.ZodInt>;
|
|
103
103
|
validationConcurrency: z.ZodDefault<z.ZodInt>;
|
|
104
104
|
validationBudget: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"all">, z.ZodInt]>>;
|
|
105
|
+
detectionBudgetMs: z.ZodDefault<z.ZodInt>;
|
|
105
106
|
}, z.core.$strict>;
|
|
106
107
|
declare const connectionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
107
108
|
driver: z.ZodLiteral<"postgres">;
|
|
108
109
|
url: z.ZodOptional<z.ZodString>;
|
|
109
110
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
111
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
110
112
|
}, z.core.$loose>, z.ZodObject<{
|
|
111
113
|
driver: z.ZodLiteral<"mysql">;
|
|
112
114
|
url: z.ZodOptional<z.ZodString>;
|
|
113
115
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
116
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
114
117
|
}, z.core.$loose>, z.ZodObject<{
|
|
115
118
|
driver: z.ZodLiteral<"snowflake">;
|
|
116
119
|
url: z.ZodOptional<z.ZodString>;
|
|
117
120
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
121
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
118
122
|
}, z.core.$loose>, z.ZodObject<{
|
|
119
123
|
driver: z.ZodLiteral<"bigquery">;
|
|
120
124
|
url: z.ZodOptional<z.ZodString>;
|
|
121
125
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
126
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
122
127
|
}, z.core.$loose>, z.ZodObject<{
|
|
123
128
|
driver: z.ZodLiteral<"sqlite">;
|
|
124
129
|
url: z.ZodOptional<z.ZodString>;
|
|
125
130
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
131
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
126
132
|
}, z.core.$loose>, z.ZodObject<{
|
|
127
133
|
driver: z.ZodLiteral<"clickhouse">;
|
|
128
134
|
url: z.ZodOptional<z.ZodString>;
|
|
129
135
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
136
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
130
137
|
}, z.core.$loose>, z.ZodObject<{
|
|
131
138
|
driver: z.ZodLiteral<"sqlserver">;
|
|
132
139
|
url: z.ZodOptional<z.ZodString>;
|
|
133
140
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
141
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
142
|
+
}, z.core.$loose>, z.ZodObject<{
|
|
143
|
+
driver: z.ZodLiteral<"mongodb">;
|
|
144
|
+
url: z.ZodString;
|
|
145
|
+
database: z.ZodOptional<z.ZodString>;
|
|
146
|
+
databases: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
147
|
+
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
148
|
+
sample_size: z.ZodOptional<z.ZodNumber>;
|
|
149
|
+
order_by: z.ZodOptional<z.ZodString>;
|
|
134
150
|
}, z.core.$loose>, z.ZodObject<{
|
|
135
151
|
driver: z.ZodLiteral<"metabase">;
|
|
136
152
|
api_url: z.ZodString;
|
|
@@ -184,6 +200,11 @@ declare const connectionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
184
200
|
max_pages_per_run: z.ZodOptional<z.ZodNumber>;
|
|
185
201
|
max_knowledge_creates_per_run: z.ZodOptional<z.ZodNumber>;
|
|
186
202
|
max_knowledge_updates_per_run: z.ZodOptional<z.ZodNumber>;
|
|
203
|
+
}, z.core.$loose>, z.ZodObject<{
|
|
204
|
+
driver: z.ZodLiteral<"gdrive">;
|
|
205
|
+
service_account_key_ref: z.ZodString;
|
|
206
|
+
folder_id: z.ZodString;
|
|
207
|
+
recursive: z.ZodOptional<z.ZodBoolean>;
|
|
187
208
|
}, z.core.$loose>, z.ZodObject<{
|
|
188
209
|
driver: z.ZodLiteral<"dbt">;
|
|
189
210
|
source_dir: z.ZodOptional<z.ZodString>;
|
|
@@ -211,30 +232,45 @@ declare const ktxProjectConfigSchema: z.ZodObject<{
|
|
|
211
232
|
driver: z.ZodLiteral<"postgres">;
|
|
212
233
|
url: z.ZodOptional<z.ZodString>;
|
|
213
234
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
235
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
214
236
|
}, z.core.$loose>, z.ZodObject<{
|
|
215
237
|
driver: z.ZodLiteral<"mysql">;
|
|
216
238
|
url: z.ZodOptional<z.ZodString>;
|
|
217
239
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
240
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
218
241
|
}, z.core.$loose>, z.ZodObject<{
|
|
219
242
|
driver: z.ZodLiteral<"snowflake">;
|
|
220
243
|
url: z.ZodOptional<z.ZodString>;
|
|
221
244
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
245
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
222
246
|
}, z.core.$loose>, z.ZodObject<{
|
|
223
247
|
driver: z.ZodLiteral<"bigquery">;
|
|
224
248
|
url: z.ZodOptional<z.ZodString>;
|
|
225
249
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
250
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
226
251
|
}, z.core.$loose>, z.ZodObject<{
|
|
227
252
|
driver: z.ZodLiteral<"sqlite">;
|
|
228
253
|
url: z.ZodOptional<z.ZodString>;
|
|
229
254
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
255
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
230
256
|
}, z.core.$loose>, z.ZodObject<{
|
|
231
257
|
driver: z.ZodLiteral<"clickhouse">;
|
|
232
258
|
url: z.ZodOptional<z.ZodString>;
|
|
233
259
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
260
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
234
261
|
}, z.core.$loose>, z.ZodObject<{
|
|
235
262
|
driver: z.ZodLiteral<"sqlserver">;
|
|
236
263
|
url: z.ZodOptional<z.ZodString>;
|
|
237
264
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
265
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
266
|
+
}, z.core.$loose>, z.ZodObject<{
|
|
267
|
+
driver: z.ZodLiteral<"mongodb">;
|
|
268
|
+
url: z.ZodString;
|
|
269
|
+
database: z.ZodOptional<z.ZodString>;
|
|
270
|
+
databases: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
271
|
+
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
272
|
+
sample_size: z.ZodOptional<z.ZodNumber>;
|
|
273
|
+
order_by: z.ZodOptional<z.ZodString>;
|
|
238
274
|
}, z.core.$loose>, z.ZodObject<{
|
|
239
275
|
driver: z.ZodLiteral<"metabase">;
|
|
240
276
|
api_url: z.ZodString;
|
|
@@ -288,6 +324,11 @@ declare const ktxProjectConfigSchema: z.ZodObject<{
|
|
|
288
324
|
max_pages_per_run: z.ZodOptional<z.ZodNumber>;
|
|
289
325
|
max_knowledge_creates_per_run: z.ZodOptional<z.ZodNumber>;
|
|
290
326
|
max_knowledge_updates_per_run: z.ZodOptional<z.ZodNumber>;
|
|
327
|
+
}, z.core.$loose>, z.ZodObject<{
|
|
328
|
+
driver: z.ZodLiteral<"gdrive">;
|
|
329
|
+
service_account_key_ref: z.ZodString;
|
|
330
|
+
folder_id: z.ZodString;
|
|
331
|
+
recursive: z.ZodOptional<z.ZodBoolean>;
|
|
291
332
|
}, z.core.$loose>, z.ZodObject<{
|
|
292
333
|
driver: z.ZodLiteral<"dbt">;
|
|
293
334
|
source_dir: z.ZodOptional<z.ZodString>;
|
|
@@ -455,6 +496,7 @@ declare const ktxProjectConfigSchema: z.ZodObject<{
|
|
|
455
496
|
profileConcurrency: z.ZodDefault<z.ZodInt>;
|
|
456
497
|
validationConcurrency: z.ZodDefault<z.ZodInt>;
|
|
457
498
|
validationBudget: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"all">, z.ZodInt]>>;
|
|
499
|
+
detectionBudgetMs: z.ZodDefault<z.ZodInt>;
|
|
458
500
|
}, z.core.$strict>>;
|
|
459
501
|
}, z.core.$strict>>;
|
|
460
502
|
}, z.core.$strict>;
|
|
@@ -187,6 +187,11 @@ const scanRelationshipsSchema = z
|
|
|
187
187
|
.union([z.literal('all'), z.int().nonnegative()])
|
|
188
188
|
.optional()
|
|
189
189
|
.describe('Cap on validation queries per scan run. Use "all" for unlimited, an integer for a hard cap, or omit for the runtime default.'),
|
|
190
|
+
detectionBudgetMs: z
|
|
191
|
+
.int()
|
|
192
|
+
.positive()
|
|
193
|
+
.default(600_000)
|
|
194
|
+
.describe('Wall-clock budget (ms) for the whole relationship-detection stage. Checked at table-profile, LLM-proposal, candidate-validation, and composite-probe boundaries; above the per-query deadline. On exhaustion the stage stops scheduling new work and returns the relationships found so far, marked partial. Raise it to trigger a fresher, fuller run.'),
|
|
190
195
|
})
|
|
191
196
|
.describe('Schema-scan relationship discovery and validation tunables.');
|
|
192
197
|
const scanSchema = z
|
|
@@ -3,30 +3,45 @@ export declare const connectionConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
|
|
|
3
3
|
driver: z.ZodLiteral<"postgres">;
|
|
4
4
|
url: z.ZodOptional<z.ZodString>;
|
|
5
5
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
6
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
6
7
|
}, z.core.$loose>, z.ZodObject<{
|
|
7
8
|
driver: z.ZodLiteral<"mysql">;
|
|
8
9
|
url: z.ZodOptional<z.ZodString>;
|
|
9
10
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
11
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
10
12
|
}, z.core.$loose>, z.ZodObject<{
|
|
11
13
|
driver: z.ZodLiteral<"snowflake">;
|
|
12
14
|
url: z.ZodOptional<z.ZodString>;
|
|
13
15
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
16
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
14
17
|
}, z.core.$loose>, z.ZodObject<{
|
|
15
18
|
driver: z.ZodLiteral<"bigquery">;
|
|
16
19
|
url: z.ZodOptional<z.ZodString>;
|
|
17
20
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
21
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
18
22
|
}, z.core.$loose>, z.ZodObject<{
|
|
19
23
|
driver: z.ZodLiteral<"sqlite">;
|
|
20
24
|
url: z.ZodOptional<z.ZodString>;
|
|
21
25
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
22
27
|
}, z.core.$loose>, z.ZodObject<{
|
|
23
28
|
driver: z.ZodLiteral<"clickhouse">;
|
|
24
29
|
url: z.ZodOptional<z.ZodString>;
|
|
25
30
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
31
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
26
32
|
}, z.core.$loose>, z.ZodObject<{
|
|
27
33
|
driver: z.ZodLiteral<"sqlserver">;
|
|
28
34
|
url: z.ZodOptional<z.ZodString>;
|
|
29
35
|
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
36
|
+
query_timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
}, z.core.$loose>, z.ZodObject<{
|
|
38
|
+
driver: z.ZodLiteral<"mongodb">;
|
|
39
|
+
url: z.ZodString;
|
|
40
|
+
database: z.ZodOptional<z.ZodString>;
|
|
41
|
+
databases: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
42
|
+
enabled_tables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
43
|
+
sample_size: z.ZodOptional<z.ZodNumber>;
|
|
44
|
+
order_by: z.ZodOptional<z.ZodString>;
|
|
30
45
|
}, z.core.$loose>, z.ZodObject<{
|
|
31
46
|
driver: z.ZodLiteral<"metabase">;
|
|
32
47
|
api_url: z.ZodString;
|
|
@@ -80,6 +95,11 @@ export declare const connectionConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
|
|
|
80
95
|
max_pages_per_run: z.ZodOptional<z.ZodNumber>;
|
|
81
96
|
max_knowledge_creates_per_run: z.ZodOptional<z.ZodNumber>;
|
|
82
97
|
max_knowledge_updates_per_run: z.ZodOptional<z.ZodNumber>;
|
|
98
|
+
}, z.core.$loose>, z.ZodObject<{
|
|
99
|
+
driver: z.ZodLiteral<"gdrive">;
|
|
100
|
+
service_account_key_ref: z.ZodString;
|
|
101
|
+
folder_id: z.ZodString;
|
|
102
|
+
recursive: z.ZodOptional<z.ZodBoolean>;
|
|
83
103
|
}, z.core.$loose>, z.ZodObject<{
|
|
84
104
|
driver: z.ZodLiteral<"dbt">;
|
|
85
105
|
source_dir: z.ZodOptional<z.ZodString>;
|
|
@@ -21,7 +21,13 @@ function warehouseConnectionSchema(driver) {
|
|
|
21
21
|
enabled_tables: z
|
|
22
22
|
.array(z.string().min(1))
|
|
23
23
|
.optional()
|
|
24
|
-
.describe('Optional allowlist of
|
|
24
|
+
.describe('Optional allowlist of object names to ingest. Accepted forms: "catalog.db.name", "db.name" (schema-qualified), or bare "name". When set, live-database ingest restricts the scan to the listed objects and fails with a clear error if none match. For SQLite, "main.<name>" and the bare "<name>" are equivalent (SQLite exposes a single "main" schema). Useful for smoke-testing ingest on a single table.'),
|
|
25
|
+
query_timeout_ms: z
|
|
26
|
+
.number()
|
|
27
|
+
.int()
|
|
28
|
+
.positive()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('Maximum execution time for a single read-only query, in milliseconds (default 30000). Enforced as a server-side statement timeout for remote engines and by SIGKILL-ing a forked query subprocess for in-process SQLite. A query exceeding it is cancelled and returns a "query exceeded Ns" error so the agent can revise.'),
|
|
25
31
|
})
|
|
26
32
|
.describe(`${driver} warehouse connection. Additional driver-tunable fields (e.g. context.queryHistory) are accepted and passed through.`);
|
|
27
33
|
}
|
|
@@ -34,6 +40,36 @@ const warehouseConnectionSchemas = [
|
|
|
34
40
|
warehouseConnectionSchema('clickhouse'),
|
|
35
41
|
warehouseConnectionSchema('sqlserver'),
|
|
36
42
|
];
|
|
43
|
+
const mongodbConnectionSchema = z
|
|
44
|
+
.looseObject({
|
|
45
|
+
driver: z.literal('mongodb'),
|
|
46
|
+
url: z
|
|
47
|
+
.string()
|
|
48
|
+
.min(1)
|
|
49
|
+
.describe('MongoDB connection string (mongodb:// or mongodb+srv://, including TLS/Atlas); may contain a reference like env:MONGO_URL.'),
|
|
50
|
+
database: z.string().min(1).optional().describe('Single database to introspect when not using databases or a URL path.'),
|
|
51
|
+
databases: z
|
|
52
|
+
.array(z.string().min(1))
|
|
53
|
+
.optional()
|
|
54
|
+
.describe('Databases whose collections ktx introspects as tables. Falls back to the URL path database.'),
|
|
55
|
+
enabled_tables: z
|
|
56
|
+
.array(z.string().min(1))
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Optional allowlist of "database.collection" names to introspect.'),
|
|
59
|
+
sample_size: z
|
|
60
|
+
.number()
|
|
61
|
+
.int()
|
|
62
|
+
.min(1)
|
|
63
|
+
.optional()
|
|
64
|
+
.describe('How many recent documents to sample per collection when inferring the schema (default 1000).'),
|
|
65
|
+
order_by: z
|
|
66
|
+
.string()
|
|
67
|
+
.min(1)
|
|
68
|
+
.optional()
|
|
69
|
+
.describe('Field to sort by descending when sampling. Defaults to _id; set this when _id is not an ObjectId. ' +
|
|
70
|
+
'Should be indexed — an unindexed sort hits MongoDB\'s in-memory sort limit on large collections.'),
|
|
71
|
+
})
|
|
72
|
+
.describe('MongoDB primary-source connection. Schema is inferred by sampling the most recent documents.');
|
|
37
73
|
const positiveIntKeyMessage = (field) => `${field} keys must be positive-integer strings (e.g. "1", "42")`;
|
|
38
74
|
const positiveIntKeyRegex = /^[1-9]\d*$/;
|
|
39
75
|
const metabaseMappingsStrictSchema = metabaseMappingsSchema.superRefine((value, ctx) => {
|
|
@@ -145,6 +181,17 @@ const notionConnectionSchema = z
|
|
|
145
181
|
.describe('Maximum existing wiki pages updated per run.'),
|
|
146
182
|
})
|
|
147
183
|
.describe('Notion context-source connection.');
|
|
184
|
+
const gdriveConnectionSchema = z
|
|
185
|
+
.looseObject({
|
|
186
|
+
driver: z.literal('gdrive'),
|
|
187
|
+
service_account_key_ref: z
|
|
188
|
+
.string()
|
|
189
|
+
.min(1)
|
|
190
|
+
.describe('Reference to a Google service-account JSON key file. Must use file:/absolute/path/to/key.json.'),
|
|
191
|
+
folder_id: z.string().min(1).describe('Google Drive folder ID to ingest.'),
|
|
192
|
+
recursive: z.boolean().optional().describe('When true, recursively traverse subfolders beneath folder_id.'),
|
|
193
|
+
})
|
|
194
|
+
.describe('Google Drive Google Docs context-source connection.');
|
|
148
195
|
const dbtConnectionSchema = z
|
|
149
196
|
.looseObject({
|
|
150
197
|
driver: z.literal('dbt'),
|
|
@@ -173,10 +220,12 @@ const metricflowConnectionSchema = z
|
|
|
173
220
|
.describe('MetricFlow / SL context-source connection.');
|
|
174
221
|
export const connectionConfigSchema = z.discriminatedUnion('driver', [
|
|
175
222
|
...warehouseConnectionSchemas,
|
|
223
|
+
mongodbConnectionSchema,
|
|
176
224
|
metabaseConnectionSchema,
|
|
177
225
|
lookerConnectionSchema,
|
|
178
226
|
lookmlConnectionSchema,
|
|
179
227
|
notionConnectionSchema,
|
|
228
|
+
gdriveConnectionSchema,
|
|
180
229
|
dbtConnectionSchema,
|
|
181
230
|
metricflowConnectionSchema,
|
|
182
231
|
]);
|
|
@@ -7,7 +7,7 @@ import { LocalGitFileStore } from './local-git-file-store.js';
|
|
|
7
7
|
const TRACKED_SCAFFOLD_FILES = [
|
|
8
8
|
{
|
|
9
9
|
path: '.ktx/.gitignore',
|
|
10
|
-
content: 'cache/\ndb.sqlite\ndb.sqlite-*\ningest-transcripts/\nsecrets/\nsetup/\nagents/\n',
|
|
10
|
+
content: 'cache/\ndb.sqlite\ndb.sqlite-*\ningest-transcripts/\nlogs/\nsecrets/\nsetup/\nagents/\n',
|
|
11
11
|
},
|
|
12
12
|
{ path: '.ktx/prompts/.gitkeep', content: '' },
|
|
13
13
|
{ path: '.ktx/skills/.gitkeep', content: '' },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ChildProcess } from 'node:child_process';
|
|
1
2
|
import type { KtxLlmRuntimePort } from '../../context/llm/runtime-port.js';
|
|
2
3
|
import type { KtxColumnSampleInput, KtxColumnSampleResult, KtxScanContext, KtxScanLoggerPort, KtxScanWarning, KtxTableRef, KtxTableSampleInput, KtxTableSampleResult } from './types.js';
|
|
3
4
|
interface KtxDescriptionTableColumn {
|
|
@@ -113,6 +114,8 @@ export interface KtxDescriptionGeneratorOptions {
|
|
|
113
114
|
logger?: KtxScanLoggerPort;
|
|
114
115
|
onWarning?: (warning: KtxScanWarning) => void;
|
|
115
116
|
settings: KtxDescriptionGenerationSettings;
|
|
117
|
+
/** @internal Test seam: spawn the kill-boundary child for subprocess backends. */
|
|
118
|
+
spawnSubprocessGenerateChild?: () => ChildProcess;
|
|
116
119
|
}
|
|
117
120
|
export interface KtxDescriptionPrompt {
|
|
118
121
|
system: string;
|
|
@@ -136,6 +139,7 @@ export declare class KtxDescriptionGenerator {
|
|
|
136
139
|
private readonly logger?;
|
|
137
140
|
private readonly onWarning?;
|
|
138
141
|
private readonly settings;
|
|
142
|
+
private readonly spawnSubprocessGenerateChild?;
|
|
139
143
|
constructor(options: KtxDescriptionGeneratorOptions);
|
|
140
144
|
generateColumnDescriptions(input: KtxGenerateColumnDescriptionsInput): Promise<KtxColumnAnalysisResult>;
|
|
141
145
|
generateTableDescription(input: KtxGenerateTableDescriptionInput): Promise<string | null>;
|