@kaelio/ktx 0.13.1 → 0.15.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.15.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 +15 -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/adapters/sigma/chunk.d.ts +6 -0
- package/dist/context/ingest/adapters/sigma/chunk.js +119 -0
- package/dist/context/ingest/adapters/sigma/client-port.d.ts +45 -0
- package/dist/context/ingest/adapters/sigma/client-port.js +1 -0
- package/dist/context/ingest/adapters/sigma/client.d.ts +33 -0
- package/dist/context/ingest/adapters/sigma/client.js +176 -0
- package/dist/context/ingest/adapters/sigma/detect.d.ts +1 -0
- package/dist/context/ingest/adapters/sigma/detect.js +23 -0
- package/dist/context/ingest/adapters/sigma/fetch.d.ts +14 -0
- package/dist/context/ingest/adapters/sigma/fetch.js +191 -0
- package/dist/context/ingest/adapters/sigma/local-sigma.adapter.d.ts +17 -0
- package/dist/context/ingest/adapters/sigma/local-sigma.adapter.js +41 -0
- package/dist/context/ingest/adapters/sigma/project.d.ts +8 -0
- package/dist/context/ingest/adapters/sigma/project.js +186 -0
- package/dist/context/ingest/adapters/sigma/sigma.adapter.d.ts +18 -0
- package/dist/context/ingest/adapters/sigma/sigma.adapter.js +43 -0
- package/dist/context/ingest/adapters/sigma/types.d.ts +80 -0
- package/dist/context/ingest/adapters/sigma/types.js +82 -0
- 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.d.ts +2 -1
- package/dist/context/ingest/local-adapters.js +28 -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 +72 -0
- package/dist/context/project/config.js +5 -0
- package/dist/context/project/driver-schemas.d.ts +35 -0
- package/dist/context/project/driver-schemas.js +89 -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 +4 -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 +6 -1
- package/dist/setup-sources.js +208 -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/sigma_ingest/SKILL.md +189 -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
package/dist/text-ingest.js
CHANGED
|
@@ -4,11 +4,15 @@ import { createLocalProjectMemoryIngest } from './context/memory/local-memory.js
|
|
|
4
4
|
import { loadKtxProject } from './context/project/project.js';
|
|
5
5
|
import { createRepainter, initViewState, renderContextBuildView } from './context-build-view.js';
|
|
6
6
|
import { formatDuration } from './demo-metrics.js';
|
|
7
|
+
import { createLocalProjectVerbatimIngestor, } from './verbatim-ingest.js';
|
|
7
8
|
const INLINE_TEXT_LABEL_MAX_LENGTH = 50;
|
|
8
9
|
const ANSI_ESCAPE_PATTERN = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
9
10
|
function defaultCreateMemoryIngest(project) {
|
|
10
11
|
return createLocalProjectMemoryIngest(project);
|
|
11
12
|
}
|
|
13
|
+
function defaultCreateVerbatimIngestor(project) {
|
|
14
|
+
return createLocalProjectVerbatimIngestor(project);
|
|
15
|
+
}
|
|
12
16
|
async function defaultReadStdin() {
|
|
13
17
|
const chunks = [];
|
|
14
18
|
process.stdin.setEncoding('utf-8');
|
|
@@ -72,17 +76,17 @@ async function loadItems(args, deps) {
|
|
|
72
76
|
args.texts.forEach((content, index) => {
|
|
73
77
|
const label = textLabel(content, index, usedTextLabels);
|
|
74
78
|
usedTextLabels.add(label);
|
|
75
|
-
items.push({ label, content });
|
|
79
|
+
items.push({ label, content, origin: { kind: 'text' } });
|
|
76
80
|
});
|
|
77
81
|
const readFile = deps.readFile ?? defaultReadFile;
|
|
78
82
|
const readStdin = deps.readStdin ?? defaultReadStdin;
|
|
79
83
|
for (const file of args.files) {
|
|
80
84
|
if (file === '-') {
|
|
81
|
-
items.push({ label: stdinLabel(items), content: await readStdin() });
|
|
85
|
+
items.push({ label: stdinLabel(items), content: await readStdin(), origin: { kind: 'stdin' } });
|
|
82
86
|
}
|
|
83
87
|
else {
|
|
84
88
|
const path = resolve(file);
|
|
85
|
-
items.push({ label: basename(path), content: await readFile(path) });
|
|
89
|
+
items.push({ label: basename(path), content: await readFile(path), origin: { kind: 'file', path } });
|
|
86
90
|
}
|
|
87
91
|
}
|
|
88
92
|
return items;
|
|
@@ -112,13 +116,13 @@ function makeTarget(label) {
|
|
|
112
116
|
function allTargets(state) {
|
|
113
117
|
return [...state.primarySources, ...state.contextSources];
|
|
114
118
|
}
|
|
115
|
-
function renderTextIngestView(state, styled) {
|
|
119
|
+
function renderTextIngestView(state, styled, verbatim) {
|
|
116
120
|
return renderContextBuildView(state, {
|
|
117
121
|
styled,
|
|
118
|
-
title: 'Ingesting text memory',
|
|
119
|
-
contextGroupLabel: 'Texts',
|
|
120
|
-
sourceIngestRunningText: 'capturing...',
|
|
121
|
-
completedItemName: { singular: 'text', plural: 'texts' },
|
|
122
|
+
title: verbatim ? 'Writing verbatim pages' : 'Ingesting text memory',
|
|
123
|
+
contextGroupLabel: verbatim ? 'Documents' : 'Texts',
|
|
124
|
+
sourceIngestRunningText: verbatim ? 'writing...' : 'capturing...',
|
|
125
|
+
completedItemName: verbatim ? { singular: 'page', plural: 'pages' } : { singular: 'text', plural: 'texts' },
|
|
122
126
|
});
|
|
123
127
|
}
|
|
124
128
|
function summarizeCaptured(captured) {
|
|
@@ -173,7 +177,9 @@ export async function runKtxTextIngest(args, io, deps = {}) {
|
|
|
173
177
|
return 1;
|
|
174
178
|
}
|
|
175
179
|
const project = await (deps.loadProject ?? loadKtxProject)({ projectDir: args.projectDir });
|
|
176
|
-
const
|
|
180
|
+
const isVerbatim = args.verbatim === true;
|
|
181
|
+
const verbatimIngestor = isVerbatim ? (deps.createVerbatimIngestor ?? defaultCreateVerbatimIngestor)(project) : null;
|
|
182
|
+
const memoryIngest = isVerbatim ? null : (deps.createMemoryIngest ?? defaultCreateMemoryIngest)(project);
|
|
177
183
|
const now = deps.now ?? (() => Date.now());
|
|
178
184
|
const batchId = now();
|
|
179
185
|
const state = initViewState(items.map((item) => makeTarget(item.label)));
|
|
@@ -182,7 +188,7 @@ export async function runKtxTextIngest(args, io, deps = {}) {
|
|
|
182
188
|
const repainter = isTTY ? createRepainter(io) : null;
|
|
183
189
|
const results = [];
|
|
184
190
|
state.startedAt = now();
|
|
185
|
-
const paint = () => repainter?.paint(renderTextIngestView(state, true));
|
|
191
|
+
const paint = () => repainter?.paint(renderTextIngestView(state, true, isVerbatim));
|
|
186
192
|
paint();
|
|
187
193
|
let spinnerInterval = null;
|
|
188
194
|
if (repainter) {
|
|
@@ -204,28 +210,50 @@ export async function runKtxTextIngest(args, io, deps = {}) {
|
|
|
204
210
|
const target = targets[index];
|
|
205
211
|
target.status = 'running';
|
|
206
212
|
target.startedAt = now();
|
|
207
|
-
target.detailLine = 'capturing...';
|
|
213
|
+
target.detailLine = isVerbatim ? 'writing...' : 'capturing...';
|
|
208
214
|
target.progressUpdatedAtMs = target.startedAt;
|
|
209
215
|
paint();
|
|
210
216
|
let runId = null;
|
|
211
217
|
let result;
|
|
212
218
|
try {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
219
|
+
if (verbatimIngestor) {
|
|
220
|
+
const verbatimItem = {
|
|
221
|
+
origin: item.origin,
|
|
222
|
+
content: item.content,
|
|
223
|
+
...(args.connectionId ? { connectionId: args.connectionId } : {}),
|
|
224
|
+
};
|
|
225
|
+
const outcome = await verbatimIngestor.ingest(verbatimItem);
|
|
226
|
+
result = {
|
|
227
|
+
label: item.label,
|
|
228
|
+
runId: null,
|
|
229
|
+
status: 'done',
|
|
230
|
+
captured: { wiki: [outcome.pageKey], sl: [], xrefs: [] },
|
|
231
|
+
commitHash: outcome.commitHash,
|
|
232
|
+
error: null,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
// memoryIngest is set whenever verbatim is off — they are mutually exclusive.
|
|
237
|
+
if (!memoryIngest) {
|
|
238
|
+
throw new Error('Memory ingest was not initialized.');
|
|
239
|
+
}
|
|
240
|
+
const ingestInput = {
|
|
241
|
+
userId: args.userId,
|
|
242
|
+
chatId: `cli-text-ingest-${batchId}-${index + 1}`,
|
|
243
|
+
userMessage: `Ingest external text artifact ${artifactReference(item.label)} into ktx memory.`,
|
|
244
|
+
assistantMessage: item.content.trim(),
|
|
245
|
+
...(args.connectionId ? { connectionId: args.connectionId } : {}),
|
|
246
|
+
sourceType: 'external_ingest',
|
|
247
|
+
};
|
|
248
|
+
const ingest = await memoryIngest.ingest(ingestInput);
|
|
249
|
+
runId = ingest.runId;
|
|
250
|
+
await memoryIngest.waitForRun(runId);
|
|
251
|
+
const status = await memoryIngest.status(runId);
|
|
252
|
+
if (!status) {
|
|
253
|
+
throw new Error(`Memory ingest run "${runId}" was not found.`);
|
|
254
|
+
}
|
|
255
|
+
result = resultFromStatus(item.label, status);
|
|
227
256
|
}
|
|
228
|
-
result = resultFromStatus(item.label, status);
|
|
229
257
|
}
|
|
230
258
|
catch (error) {
|
|
231
259
|
result = errorResult(item.label, runId, error);
|
|
@@ -254,17 +282,18 @@ export async function runKtxTextIngest(args, io, deps = {}) {
|
|
|
254
282
|
writeJsonResult(args, results, io);
|
|
255
283
|
}
|
|
256
284
|
else if (repainter) {
|
|
257
|
-
repainter.paint(renderTextIngestView(state, true));
|
|
285
|
+
repainter.paint(renderTextIngestView(state, true, isVerbatim));
|
|
258
286
|
writePlainFailures(results, io);
|
|
259
287
|
}
|
|
260
288
|
else {
|
|
261
|
-
io.stdout.write(renderTextIngestView(state, false));
|
|
289
|
+
io.stdout.write(renderTextIngestView(state, false, isVerbatim));
|
|
262
290
|
writePlainFailures(results, io);
|
|
263
291
|
}
|
|
264
292
|
if (!args.json && results.length > 0) {
|
|
265
293
|
const duration = state.totalElapsedMs > 0 ? ` in ${formatDuration(state.totalElapsedMs)}` : '';
|
|
266
294
|
const outcome = results.some((result) => result.status === 'error') ? 'finished with failures' : 'finished';
|
|
267
|
-
|
|
295
|
+
const label = isVerbatim ? 'Verbatim ingest' : 'Text memory ingest';
|
|
296
|
+
io.stdout.write(`${label} ${outcome}${duration}.\n`);
|
|
268
297
|
}
|
|
269
298
|
return results.some((result) => result.status === 'error') ? 1 : 0;
|
|
270
299
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { KtxLlmRuntimePort } from './context/llm/runtime-port.js';
|
|
2
|
+
import type { KtxLocalProject } from './context/project/project.js';
|
|
3
|
+
import type { WikiFrontmatter } from './context/wiki/types.js';
|
|
4
|
+
import type { KtxEmbeddingProvider } from './llm/types.js';
|
|
5
|
+
export interface VerbatimIngestOrigin {
|
|
6
|
+
kind: 'file' | 'text' | 'stdin';
|
|
7
|
+
/** Present only for `kind: 'file'`; the resolved path the key basename is derived from. */
|
|
8
|
+
path?: string;
|
|
9
|
+
}
|
|
10
|
+
/** @internal */
|
|
11
|
+
export declare function splitInputDocument(raw: string): {
|
|
12
|
+
frontmatter: Record<string, unknown>;
|
|
13
|
+
body: string;
|
|
14
|
+
};
|
|
15
|
+
/** @internal */
|
|
16
|
+
export declare function deriveVerbatimPageKey(origin: VerbatimIngestOrigin, body: string): string;
|
|
17
|
+
/** @internal */
|
|
18
|
+
export declare function deriveDegradedSummary(body: string): string;
|
|
19
|
+
/** @internal */
|
|
20
|
+
export declare function buildVerbatimFrontmatter(input: {
|
|
21
|
+
inputFrontmatter: Record<string, unknown>;
|
|
22
|
+
summary: string;
|
|
23
|
+
tags: string[];
|
|
24
|
+
slRefs: string[];
|
|
25
|
+
connectionId?: string;
|
|
26
|
+
}): WikiFrontmatter & Record<string, unknown>;
|
|
27
|
+
export interface VerbatimIngestItem {
|
|
28
|
+
origin: VerbatimIngestOrigin;
|
|
29
|
+
content: string;
|
|
30
|
+
connectionId?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface VerbatimIngestResult {
|
|
33
|
+
pageKey: string;
|
|
34
|
+
outcome: 'written' | 'unchanged';
|
|
35
|
+
connections: string[];
|
|
36
|
+
commitHash: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface VerbatimIngestorPort {
|
|
39
|
+
ingest(item: VerbatimIngestItem): Promise<VerbatimIngestResult>;
|
|
40
|
+
}
|
|
41
|
+
export interface CreateLocalProjectVerbatimIngestorDeps {
|
|
42
|
+
/** `undefined` ⇒ resolve from project config; `null` ⇒ force degraded (offline) metadata. */
|
|
43
|
+
llmRuntime?: KtxLlmRuntimePort | null;
|
|
44
|
+
embeddingProvider?: KtxEmbeddingProvider | null;
|
|
45
|
+
}
|
|
46
|
+
export declare function createLocalProjectVerbatimIngestor(project: KtxLocalProject, deps?: CreateLocalProjectVerbatimIngestorDeps): VerbatimIngestorPort;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { basename, extname, join } from 'node:path';
|
|
2
|
+
import YAML from 'yaml';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { noopLogger } from './context/core/config.js';
|
|
5
|
+
import { assertConfiguredConnectionId } from './context/connections/configured-connections.js';
|
|
6
|
+
import { KtxIngestEmbeddingPortAdapter } from './context/llm/embedding-port.js';
|
|
7
|
+
import { createLocalKtxEmbeddingProviderFromConfig, createLocalKtxLlmRuntimeFromConfig } from './context/llm/local-config.js';
|
|
8
|
+
import { KnowledgeWikiService } from './context/wiki/knowledge-wiki.service.js';
|
|
9
|
+
import { suggestFlatWikiKey } from './context/wiki/keys.js';
|
|
10
|
+
import { SqliteKnowledgeIndex } from './context/wiki/sqlite-knowledge-index.js';
|
|
11
|
+
const LOCAL_AUTHOR = 'ktx';
|
|
12
|
+
const LOCAL_AUTHOR_EMAIL = 'ktx@example.com';
|
|
13
|
+
/** Only the prefix sent to the LLM for metadata is clipped; the stored body is never clipped. */
|
|
14
|
+
const METADATA_CLIP_LENGTH = 48_000;
|
|
15
|
+
const VERBATIM_METADATA_SYSTEM_PROMPT = [
|
|
16
|
+
'You generate search metadata for an authoritative document that ktx stores verbatim.',
|
|
17
|
+
'You never rewrite, summarize into, or alter the document body — you only describe it.',
|
|
18
|
+
'Return a concise one- or two-sentence summary, a few topical tags, and any semantic-layer',
|
|
19
|
+
'source names the document is clearly about. Use empty arrays when none apply.',
|
|
20
|
+
].join(' ');
|
|
21
|
+
const verbatimMetadataSchema = z.object({
|
|
22
|
+
summary: z.string().min(1).describe('A one- or two-sentence description of what the document defines or specifies.'),
|
|
23
|
+
tags: z.array(z.string()).default([]).describe('Short topical keywords that aid lexical and semantic recall.'),
|
|
24
|
+
sl_refs: z
|
|
25
|
+
.array(z.string())
|
|
26
|
+
.default([])
|
|
27
|
+
.describe('Semantic-layer source names the document is clearly about, if any are evident.'),
|
|
28
|
+
});
|
|
29
|
+
const DEGRADED_SUMMARY_MAX_LENGTH = 200;
|
|
30
|
+
const FRONTMATTER_PATTERN = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;
|
|
31
|
+
const HEADING_PATTERN = /^#{1,6}\s+(.+?)\s*#*\s*$/;
|
|
32
|
+
function isUsageMode(value) {
|
|
33
|
+
return value === 'always' || value === 'auto' || value === 'never';
|
|
34
|
+
}
|
|
35
|
+
function nonEmptyString(value) {
|
|
36
|
+
return typeof value === 'string' && value.trim().length > 0 ? value : undefined;
|
|
37
|
+
}
|
|
38
|
+
function stringArray(value) {
|
|
39
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : [];
|
|
40
|
+
}
|
|
41
|
+
/** `connections` accepts a single id or a list in YAML; normalize either to a string list. */
|
|
42
|
+
function stringList(value) {
|
|
43
|
+
if (typeof value === 'string') {
|
|
44
|
+
return value.trim().length > 0 ? [value] : [];
|
|
45
|
+
}
|
|
46
|
+
return stringArray(value);
|
|
47
|
+
}
|
|
48
|
+
function leadingHeadingText(body) {
|
|
49
|
+
const firstLine = body.trimStart().split('\n', 1)[0] ?? '';
|
|
50
|
+
const match = firstLine.match(HEADING_PATTERN);
|
|
51
|
+
return match ? match[1].trim() : null;
|
|
52
|
+
}
|
|
53
|
+
/** @internal */
|
|
54
|
+
export function splitInputDocument(raw) {
|
|
55
|
+
const match = raw.match(FRONTMATTER_PATTERN);
|
|
56
|
+
if (!match) {
|
|
57
|
+
return { frontmatter: {}, body: raw.trim() };
|
|
58
|
+
}
|
|
59
|
+
const parsed = YAML.parse(match[1]);
|
|
60
|
+
const frontmatter = parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
61
|
+
? parsed
|
|
62
|
+
: {};
|
|
63
|
+
return { frontmatter, body: match[2].trim() };
|
|
64
|
+
}
|
|
65
|
+
/** @internal */
|
|
66
|
+
export function deriveVerbatimPageKey(origin, body) {
|
|
67
|
+
if (origin.kind === 'file' && origin.path) {
|
|
68
|
+
return suggestFlatWikiKey(basename(origin.path, extname(origin.path)));
|
|
69
|
+
}
|
|
70
|
+
const heading = leadingHeadingText(body);
|
|
71
|
+
if (!heading) {
|
|
72
|
+
throw new Error('Verbatim inline text needs a leading Markdown heading to derive a stable page key. Add a "# Heading" line, or pass the content as --file <path>.');
|
|
73
|
+
}
|
|
74
|
+
return suggestFlatWikiKey(heading);
|
|
75
|
+
}
|
|
76
|
+
/** @internal */
|
|
77
|
+
export function deriveDegradedSummary(body) {
|
|
78
|
+
const heading = leadingHeadingText(body);
|
|
79
|
+
if (heading) {
|
|
80
|
+
return heading;
|
|
81
|
+
}
|
|
82
|
+
const text = body.trim();
|
|
83
|
+
const sentence = text.match(/^([\s\S]*?[.!?])(\s|$)/);
|
|
84
|
+
const summary = sentence ? sentence[1].trim() : text;
|
|
85
|
+
if (summary.length <= DEGRADED_SUMMARY_MAX_LENGTH) {
|
|
86
|
+
return summary;
|
|
87
|
+
}
|
|
88
|
+
return `${summary.slice(0, DEGRADED_SUMMARY_MAX_LENGTH).trimEnd()}…`;
|
|
89
|
+
}
|
|
90
|
+
/** @internal */
|
|
91
|
+
export function buildVerbatimFrontmatter(input) {
|
|
92
|
+
const { inputFrontmatter } = input;
|
|
93
|
+
const inputConnections = stringList(inputFrontmatter.connections);
|
|
94
|
+
const flagConnections = input.connectionId ? [input.connectionId] : [];
|
|
95
|
+
if (inputConnections.length > 0 &&
|
|
96
|
+
flagConnections.length > 0 &&
|
|
97
|
+
!connectionSetsEqual(inputConnections, flagConnections)) {
|
|
98
|
+
throw new Error(`Connection scope conflict: frontmatter declares connections [${inputConnections.join(', ')}] but --connection-id is "${input.connectionId}". Remove one so the intent is unambiguous.`);
|
|
99
|
+
}
|
|
100
|
+
const connections = inputConnections.length > 0 ? inputConnections : flagConnections;
|
|
101
|
+
const summary = nonEmptyString(inputFrontmatter.summary) ?? input.summary;
|
|
102
|
+
const usageMode = isUsageMode(inputFrontmatter.usage_mode) ? inputFrontmatter.usage_mode : 'auto';
|
|
103
|
+
const tags = inputFrontmatter.tags !== undefined ? stringArray(inputFrontmatter.tags) : input.tags;
|
|
104
|
+
const slRefs = inputFrontmatter.sl_refs !== undefined ? stringArray(inputFrontmatter.sl_refs) : input.slRefs;
|
|
105
|
+
const passthrough = Object.fromEntries(Object.entries(inputFrontmatter).filter(([key]) => !['summary', 'usage_mode', 'tags', 'sl_refs', 'connections'].includes(key)));
|
|
106
|
+
return {
|
|
107
|
+
...passthrough,
|
|
108
|
+
summary,
|
|
109
|
+
usage_mode: usageMode,
|
|
110
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
111
|
+
...(slRefs.length > 0 ? { sl_refs: slRefs } : {}),
|
|
112
|
+
...(connections.length > 0 ? { connections } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function connectionSetsEqual(left, right) {
|
|
116
|
+
if (left.length !== right.length) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
const rightSet = new Set(right);
|
|
120
|
+
return left.every((id) => rightSet.has(id));
|
|
121
|
+
}
|
|
122
|
+
class LocalVerbatimIngestor {
|
|
123
|
+
deps;
|
|
124
|
+
constructor(deps) {
|
|
125
|
+
this.deps = deps;
|
|
126
|
+
}
|
|
127
|
+
async ingest(item) {
|
|
128
|
+
if (item.connectionId) {
|
|
129
|
+
assertConfiguredConnectionId(this.deps.configuredConnections, item.connectionId);
|
|
130
|
+
}
|
|
131
|
+
const { frontmatter: inputFrontmatter, body } = splitInputDocument(item.content);
|
|
132
|
+
const pageKey = deriveVerbatimPageKey(item.origin, body);
|
|
133
|
+
const generated = await this.resolveMetadata(inputFrontmatter, body);
|
|
134
|
+
const frontmatter = buildVerbatimFrontmatter({
|
|
135
|
+
inputFrontmatter,
|
|
136
|
+
summary: generated.summary,
|
|
137
|
+
tags: generated.tags,
|
|
138
|
+
slRefs: generated.slRefs,
|
|
139
|
+
...(item.connectionId ? { connectionId: item.connectionId } : {}),
|
|
140
|
+
});
|
|
141
|
+
const connections = Array.isArray(frontmatter.connections) ? frontmatter.connections : [];
|
|
142
|
+
const existing = await this.deps.wikiService.readPage('GLOBAL', null, pageKey);
|
|
143
|
+
if (existing) {
|
|
144
|
+
if (existing.content === body) {
|
|
145
|
+
return { pageKey, outcome: 'unchanged', connections, commitHash: null };
|
|
146
|
+
}
|
|
147
|
+
throw new Error(`A different page already exists at key "${pageKey}". Re-run with a distinct document name or key, ` +
|
|
148
|
+
'or remove the existing page first — verbatim ingest never overwrites a conflicting page.');
|
|
149
|
+
}
|
|
150
|
+
const writeResult = await this.deps.wikiService.writePageAndSync('GLOBAL', null, pageKey, frontmatter, body, this.deps.author, this.deps.authorEmail, `Ingest verbatim document: ${pageKey}`);
|
|
151
|
+
return { pageKey, outcome: 'written', connections, commitHash: writeResult.commitHash ?? null };
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Generated metadata is only used to gap-fill absent frontmatter fields, so the LLM is
|
|
155
|
+
* skipped entirely when summary, tags, and sl_refs are all explicit. A configured backend
|
|
156
|
+
* that fails surfaces the error (the item fails); degraded derivation is reserved for
|
|
157
|
+
* `backend: none`, never used as a silent fallback that would poison the idempotency check.
|
|
158
|
+
*/
|
|
159
|
+
async resolveMetadata(inputFrontmatter, body) {
|
|
160
|
+
const needsGeneration = nonEmptyString(inputFrontmatter.summary) === undefined ||
|
|
161
|
+
inputFrontmatter.tags === undefined ||
|
|
162
|
+
inputFrontmatter.sl_refs === undefined;
|
|
163
|
+
if (this.deps.llmRuntime && needsGeneration) {
|
|
164
|
+
const clipped = body.length > METADATA_CLIP_LENGTH ? body.slice(0, METADATA_CLIP_LENGTH) : body;
|
|
165
|
+
const generated = await this.deps.llmRuntime.generateObject({
|
|
166
|
+
role: 'triage',
|
|
167
|
+
system: VERBATIM_METADATA_SYSTEM_PROMPT,
|
|
168
|
+
prompt: clipped,
|
|
169
|
+
schema: verbatimMetadataSchema,
|
|
170
|
+
});
|
|
171
|
+
return { summary: generated.summary, tags: generated.tags, slRefs: generated.sl_refs };
|
|
172
|
+
}
|
|
173
|
+
return { summary: deriveDegradedSummary(body), tags: [], slRefs: [] };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
export function createLocalProjectVerbatimIngestor(project, deps = {}) {
|
|
177
|
+
const llmRuntime = deps.llmRuntime !== undefined
|
|
178
|
+
? deps.llmRuntime
|
|
179
|
+
: createLocalKtxLlmRuntimeFromConfig(project.config.llm, { projectDir: project.projectDir });
|
|
180
|
+
const embeddingProvider = deps.embeddingProvider !== undefined
|
|
181
|
+
? deps.embeddingProvider
|
|
182
|
+
: createLocalKtxEmbeddingProviderFromConfig(project.config.ingest.embeddings, { projectDir: project.projectDir });
|
|
183
|
+
const embeddingPort = embeddingProvider ? new KtxIngestEmbeddingPortAdapter(embeddingProvider) : null;
|
|
184
|
+
const knowledgeIndex = new SqliteKnowledgeIndex({ dbPath: join(project.projectDir, '.ktx', 'db.sqlite') });
|
|
185
|
+
const wikiService = new KnowledgeWikiService(project.fileStore, embeddingPort, knowledgeIndex, project.git, noopLogger);
|
|
186
|
+
return new LocalVerbatimIngestor({
|
|
187
|
+
wikiService,
|
|
188
|
+
llmRuntime,
|
|
189
|
+
configuredConnections: project.config.connections,
|
|
190
|
+
author: LOCAL_AUTHOR,
|
|
191
|
+
authorEmail: LOCAL_AUTHOR_EMAIL,
|
|
192
|
+
});
|
|
193
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaelio/ktx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Standalone ktx context layer for data agents",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Kaelio",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"@commander-js/extra-typings": "14.0.0",
|
|
43
43
|
"@duckdb/node-api": "1.5.3-r.3",
|
|
44
44
|
"@google-cloud/bigquery": "^8.3.1",
|
|
45
|
+
"google-auth-library": "10.6.2",
|
|
45
46
|
"@looker/sdk": "^26.8.0",
|
|
46
47
|
"@looker/sdk-node": "^26.8.0",
|
|
47
48
|
"@looker/sdk-rtl": "^21.6.5",
|
|
@@ -56,11 +57,14 @@
|
|
|
56
57
|
"ink": "^7.0.3",
|
|
57
58
|
"lookml-parser": "7.1.0",
|
|
58
59
|
"minimatch": "^10.2.5",
|
|
60
|
+
"mongodb": "^6.12.0",
|
|
59
61
|
"mssql": "^12.5.4",
|
|
60
62
|
"mysql2": "^3.22.3",
|
|
61
63
|
"openai": "^6.38.0",
|
|
62
64
|
"p-limit": "^7.3.0",
|
|
63
65
|
"pg": "^8.21.0",
|
|
66
|
+
"pino": "^10.3.1",
|
|
67
|
+
"pino-pretty": "^13.1.3",
|
|
64
68
|
"posthog-node": "^5.34.9",
|
|
65
69
|
"react": "^19.2.6",
|
|
66
70
|
"semver": "^7.8.1",
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { AgentRunnerPort } from '../../context/llm/runtime-port.js';
|
|
2
|
-
import type { ConstrainedRepairResult, RepairVerification } from './constrained-repair.js';
|
|
3
|
-
import type { IngestTraceWriter } from './ingest-trace.js';
|
|
4
|
-
type FinalGateRepairKind = 'patch_semantic_gate' | 'final_artifact_gate';
|
|
5
|
-
export type FinalGateRepairResult = ConstrainedRepairResult;
|
|
6
|
-
export interface RepairFinalGateFailureInput {
|
|
7
|
-
agentRunner: AgentRunnerPort;
|
|
8
|
-
workdir: string;
|
|
9
|
-
gateError: string;
|
|
10
|
-
allowedPaths: string[];
|
|
11
|
-
trace: IngestTraceWriter;
|
|
12
|
-
repairKind: FinalGateRepairKind;
|
|
13
|
-
/**
|
|
14
|
-
* Re-runs the failed gate against the current worktree. The repair counts
|
|
15
|
-
* as successful only when this passes — editing files is not the success
|
|
16
|
-
* signal.
|
|
17
|
-
*/
|
|
18
|
-
verify(changedPaths: string[]): Promise<RepairVerification>;
|
|
19
|
-
maxAttempts?: number;
|
|
20
|
-
stepBudget?: number;
|
|
21
|
-
abortSignal?: AbortSignal;
|
|
22
|
-
}
|
|
23
|
-
export declare function finalGateRepairPaths(input: {
|
|
24
|
-
changedWikiPageKeys: string[];
|
|
25
|
-
touchedSlSourcePaths: string[];
|
|
26
|
-
}): string[];
|
|
27
|
-
export declare function repairFinalGateFailure(input: RepairFinalGateFailureInput): Promise<FinalGateRepairResult>;
|
|
28
|
-
export {};
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { runConstrainedRepairLoop } from './constrained-repair.js';
|
|
3
|
-
function buildGateRepairSystemPrompt() {
|
|
4
|
-
return `<role>
|
|
5
|
-
You repair one ktx isolated-diff artifact gate failure inside the integration worktree.
|
|
6
|
-
</role>
|
|
7
|
-
|
|
8
|
-
<rules>
|
|
9
|
-
- Use read_gate_error first.
|
|
10
|
-
- Read only files exposed by read_repair_file.
|
|
11
|
-
- Edit only paths exposed by write_repair_file.
|
|
12
|
-
- Prefer the smallest text edit that makes the gate pass.
|
|
13
|
-
- Preserve accepted work-unit, reconciliation, and deterministic projection content.
|
|
14
|
-
- Do not invent warehouse facts, business definitions, or semantic-layer entities.
|
|
15
|
-
- If the gate error requires choosing between conflicting facts without evidence, stop without editing.
|
|
16
|
-
</rules>`;
|
|
17
|
-
}
|
|
18
|
-
function buildGateRepairUserPrompt(input) {
|
|
19
|
-
const previousFailureBlock = input.previousFailure
|
|
20
|
-
? `\nPrevious attempt did not pass the gate:\n${input.previousFailure}\n`
|
|
21
|
-
: '';
|
|
22
|
-
return `Repair isolated-diff artifact gates.
|
|
23
|
-
|
|
24
|
-
Repair kind: ${input.repairKind}
|
|
25
|
-
Attempt: ${input.attempt} of ${input.maxAttempts}
|
|
26
|
-
|
|
27
|
-
Allowed files:
|
|
28
|
-
${input.allowedPaths.map((path) => `- ${path}`).join('\n')}
|
|
29
|
-
|
|
30
|
-
Gate error:
|
|
31
|
-
${input.gateError}
|
|
32
|
-
${previousFailureBlock}
|
|
33
|
-
Use read_gate_error first. Then inspect only the allowed files, write the
|
|
34
|
-
minimal repaired content, and stop.`;
|
|
35
|
-
}
|
|
36
|
-
function buildReadGateErrorTool(gateError) {
|
|
37
|
-
return {
|
|
38
|
-
read_gate_error: {
|
|
39
|
-
name: 'read_gate_error',
|
|
40
|
-
description: 'Read the artifact gate failure that must be repaired.',
|
|
41
|
-
inputSchema: z.object({}),
|
|
42
|
-
execute: async () => ({
|
|
43
|
-
markdown: gateError,
|
|
44
|
-
structured: { gateError },
|
|
45
|
-
}),
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
export function finalGateRepairPaths(input) {
|
|
50
|
-
return [
|
|
51
|
-
...new Set([
|
|
52
|
-
...input.touchedSlSourcePaths,
|
|
53
|
-
...input.changedWikiPageKeys.map((pageKey) => `wiki/global/${pageKey}.md`),
|
|
54
|
-
]),
|
|
55
|
-
].sort();
|
|
56
|
-
}
|
|
57
|
-
export async function repairFinalGateFailure(input) {
|
|
58
|
-
return runConstrainedRepairLoop({
|
|
59
|
-
agentRunner: input.agentRunner,
|
|
60
|
-
workdir: input.workdir,
|
|
61
|
-
allowedPaths: input.allowedPaths,
|
|
62
|
-
trace: input.trace,
|
|
63
|
-
tracePhase: 'gate_repair',
|
|
64
|
-
traceEventName: 'gate_repair',
|
|
65
|
-
traceData: {
|
|
66
|
-
repairKind: input.repairKind,
|
|
67
|
-
gateError: input.gateError,
|
|
68
|
-
},
|
|
69
|
-
systemPrompt: buildGateRepairSystemPrompt(),
|
|
70
|
-
buildUserPrompt: ({ attempt, maxAttempts, previousFailure }) => buildGateRepairUserPrompt({
|
|
71
|
-
gateError: input.gateError,
|
|
72
|
-
allowedPaths: [...input.allowedPaths].sort(),
|
|
73
|
-
repairKind: input.repairKind,
|
|
74
|
-
attempt,
|
|
75
|
-
maxAttempts,
|
|
76
|
-
previousFailure,
|
|
77
|
-
}),
|
|
78
|
-
buildExtraTools: () => buildReadGateErrorTool(input.gateError),
|
|
79
|
-
verify: input.verify,
|
|
80
|
-
noChangeFailureReason: 'gate repair completed without editing an allowed path',
|
|
81
|
-
telemetryTags: {
|
|
82
|
-
operationName: 'ingest-isolated-diff-gate-repair',
|
|
83
|
-
source: input.trace.context.sourceKey,
|
|
84
|
-
jobId: input.trace.context.jobId,
|
|
85
|
-
repairKind: input.repairKind,
|
|
86
|
-
},
|
|
87
|
-
maxAttempts: input.maxAttempts,
|
|
88
|
-
stepBudget: input.stepBudget ?? 16,
|
|
89
|
-
abortSignal: input.abortSignal,
|
|
90
|
-
});
|
|
91
|
-
}
|