From 0590e0b0971e0598bf4899c8f5c9acbaa3210ea3 Mon Sep 17 00:00:00 2001 From: Andrey Avtomonov Date: Tue, 12 May 2026 23:35:53 +0200 Subject: [PATCH] feat(context): expose warehouse verification tools to ingest --- .../src/ingest/ingest-bundle.runner.test.ts | 32 +++++++++++ .../src/ingest/ingest-bundle.runner.ts | 2 + .../src/ingest/local-bundle-runtime.ts | 54 +++++++++++-------- packages/context/src/tools/tool-session.ts | 1 + 4 files changed, 67 insertions(+), 22 deletions(-) diff --git a/packages/context/src/ingest/ingest-bundle.runner.test.ts b/packages/context/src/ingest/ingest-bundle.runner.test.ts index a4513f63..dc48b18c 100644 --- a/packages/context/src/ingest/ingest-bundle.runner.test.ts +++ b/packages/context/src/ingest/ingest-bundle.runner.test.ts @@ -409,6 +409,38 @@ describe('IngestBundleRunner — Stages 1 → 7', () => { ); }); + it('threads target warehouse connection names into WorkUnit and reconcile tool sessions', async () => { + const deps = makeDeps(); + const sessions: any[] = []; + deps.adapter.listTargetConnectionIds = vi.fn().mockResolvedValue(['warehouse']); + deps.toolsetFactory.createIngestWuToolset.mockImplementation((toolSession: any) => { + sessions.push(toolSession); + return { + toAiSdkTools: vi.fn().mockReturnValue({}), + getAllTools: vi.fn().mockReturnValue([]), + getToolNames: vi.fn().mockReturnValue([]), + }; + }); + deps.agentRunner.runLoop.mockResolvedValue({ stopReason: 'natural' }); + + const runner = buildRunner(deps); + (runner as any).stageRawFilesStage1 = vi.fn().mockResolvedValue({ + currentHashes: new Map([['a.yml', 'h1']]), + rawDirInWorktree: 'raw-sources/notion/fake/s', + }); + (runner as any).resolveStagedDir = vi.fn().mockResolvedValue('/tmp/stage/upload-x'); + + await runner.run({ + jobId: 'j1', + connectionId: 'notion', + sourceKey: 'fake', + trigger: 'upload', + bundleRef: { kind: 'upload', uploadId: 'upload-x' }, + }); + + expect([...sessions[0].allowedConnectionNames].sort()).toEqual(['notion', 'warehouse']); + }); + it('reuses document evidence indexing and page triage for document WorkUnits', async () => { const deps = makeDeps(); deps.adapter.source = 'notion'; diff --git a/packages/context/src/ingest/ingest-bundle.runner.ts b/packages/context/src/ingest/ingest-bundle.runner.ts index 31b444bf..f1ac01de 100644 --- a/packages/context/src/ingest/ingest-bundle.runner.ts +++ b/packages/context/src/ingest/ingest-bundle.runner.ts @@ -662,6 +662,7 @@ export class IngestBundleRunner { touchedSlSources: session.touchedSlSources, actions: sessionActions, allowedRawPaths: new Set(wu.rawFiles), + allowedConnectionNames: new Set(slConnectionIds), semanticLayerService: scopedSemanticLayerService, wikiService: scopedWikiService, configService: sessionWorktree.config, @@ -898,6 +899,7 @@ export class IngestBundleRunner { touchedSlSources: reconcileSession.touchedSlSources, actions: reconcileActions, allowedRawPaths: reconciliationAllowedRawPaths, + allowedConnectionNames: new Set(slConnectionIds), semanticLayerService: rcScopedSl, wikiService: rcScopedWiki, configService: sessionWorktree.config, diff --git a/packages/context/src/ingest/local-bundle-runtime.ts b/packages/context/src/ingest/local-bundle-runtime.ts index 38e37b1d..4e74335a 100644 --- a/packages/context/src/ingest/local-bundle-runtime.ts +++ b/packages/context/src/ingest/local-bundle-runtime.ts @@ -77,6 +77,7 @@ import { ContextEvidenceIndexService, SqliteContextEvidenceStore } from './conte import { DiffSetService } from './diff-set.service.js'; import { IngestBundleRunner } from './ingest-bundle.runner.js'; import { PageTriageService } from './page-triage/index.js'; +import { createWarehouseVerificationTools } from './tools/warehouse-verification/index.js'; import type { IngestBundleRunnerDeps, IngestCommitMessagePort, @@ -486,38 +487,47 @@ class LocalIngestToolsetFactory implements IngestToolsetFactoryPort { slSearchService: deps.slSearchService, authorResolver: deps.authorResolver, }; + const wikiSearchTool = new WikiSearchTool({ + search: async (input) => { + const results = await searchLocalKnowledgePages(deps.project, { + userId: input.userId, + query: input.query, + limit: input.limit, + embeddingService: deps.embedding, + }); + return { + results: results.slice(0, input.limit).map((result) => ({ + key: result.key, + path: result.path, + summary: result.summary, + score: result.score, + matchReasons: result.matchReasons, + lanes: result.lanes, + })), + totalFound: results.length, + }; + }, + }); + const slDiscoverTool = new SlDiscoverTool(slDeps, { maxSources: 25, minRrfScore: 0, maxDetailedSources: 5 }); + const warehouseVerificationTools = createWarehouseVerificationTools({ + connections: deps.connections, + fallbackFileStore: deps.project.fileStore, + wikiSearchTool, + slDiscoverTool, + }); this.baseTools = [ new WikiReadTool(deps.wikiService, deps.knowledgeIndex), - new WikiSearchTool({ - search: async (input) => { - const results = await searchLocalKnowledgePages(deps.project, { - userId: input.userId, - query: input.query, - limit: input.limit, - embeddingService: deps.embedding, - }); - return { - results: results.slice(0, input.limit).map((result) => ({ - key: result.key, - path: result.path, - summary: result.summary, - score: result.score, - matchReasons: result.matchReasons, - lanes: result.lanes, - })), - totalFound: results.length, - }; - }, - }), + wikiSearchTool, new WikiListTagsTool(deps.wikiService, deps.knowledgeIndex), new WikiWriteTool(deps.wikiService, deps.knowledgeIndex, deps.knowledgeEvents), new WikiRemoveTool(deps.wikiService, deps.knowledgeIndex, deps.knowledgeEvents), - new SlDiscoverTool(slDeps, { maxSources: 25, minRrfScore: 0, maxDetailedSources: 5 }), + slDiscoverTool, new SlEditSourceTool(slDeps), new SlReadSourceTool(slDeps), new SlWriteSourceTool(slDeps), new SlValidateTool(slDeps), new SlRollbackTool(deps.slSourcesRepository, deps.connections, 0), + ...warehouseVerificationTools, ]; this.contextTools = [ new ContextEvidenceSearchTool(deps.contextStore, deps.embedding), diff --git a/packages/context/src/tools/tool-session.ts b/packages/context/src/tools/tool-session.ts index d9156258..023a8c8e 100644 --- a/packages/context/src/tools/tool-session.ts +++ b/packages/context/src/tools/tool-session.ts @@ -47,6 +47,7 @@ export interface ToolSession { touchedSlSources: TouchedSlSourceSet; actions: MemoryAction[]; allowedRawPaths?: ReadonlySet; + allowedConnectionNames?: ReadonlySet; semanticLayerService: SemanticLayerService; wikiService: KnowledgeWikiService; configService: KtxFileStorePort;