@vfarcic/dot-ai 1.23.1 → 1.24.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/dist/core/index.d.ts +0 -5
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -11
- package/dist/core/knowledge-migration.d.ts +30 -0
- package/dist/core/knowledge-migration.d.ts.map +1 -0
- package/dist/core/knowledge-migration.js +289 -0
- package/dist/core/knowledge-service.d.ts +46 -0
- package/dist/core/knowledge-service.d.ts.map +1 -0
- package/dist/core/knowledge-service.js +185 -0
- package/dist/core/knowledge-types.d.ts +14 -0
- package/dist/core/knowledge-types.d.ts.map +1 -1
- package/dist/core/schema.d.ts +13 -12
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +105 -170
- package/dist/core/user-prompts-loader.d.ts.map +1 -1
- package/dist/core/user-prompts-loader.js +13 -6
- package/dist/interfaces/rest-api.d.ts.map +1 -1
- package/dist/interfaces/rest-api.js +7 -6
- package/dist/mcp/server.js +12 -0
- package/dist/tools/manage-knowledge.d.ts +0 -22
- package/dist/tools/manage-knowledge.d.ts.map +1 -1
- package/dist/tools/manage-knowledge.js +71 -131
- package/dist/tools/operate-analysis.d.ts.map +1 -1
- package/dist/tools/operate-analysis.js +7 -6
- package/dist/tools/operate.d.ts +23 -11
- package/dist/tools/operate.d.ts.map +1 -1
- package/dist/tools/operate.js +40 -58
- package/dist/tools/organizational-data.d.ts +5 -8
- package/dist/tools/organizational-data.d.ts.map +1 -1
- package/dist/tools/organizational-data.js +19 -74
- package/dist/tools/query.d.ts +17 -0
- package/dist/tools/query.d.ts.map +1 -1
- package/dist/tools/query.js +36 -1
- package/dist/tools/version.d.ts +1 -12
- package/dist/tools/version.d.ts.map +1 -1
- package/dist/tools/version.js +10 -19
- package/package.json +2 -2
- package/prompts/knowledge-classification.md +24 -0
- package/prompts/operate-user.md +7 -8
- package/dist/core/organizational-types.d.ts +0 -43
- package/dist/core/organizational-types.d.ts.map +0 -1
- package/dist/core/organizational-types.js +0 -8
- package/dist/core/pattern-operations.d.ts +0 -50
- package/dist/core/pattern-operations.d.ts.map +0 -1
- package/dist/core/pattern-operations.js +0 -445
- package/dist/core/pattern-types.d.ts +0 -8
- package/dist/core/pattern-types.d.ts.map +0 -1
- package/dist/core/pattern-types.js +0 -8
- package/dist/core/pattern-vector-service.d.ts +0 -27
- package/dist/core/pattern-vector-service.d.ts.map +0 -1
- package/dist/core/pattern-vector-service.js +0 -65
- package/dist/core/policy-operations.d.ts +0 -136
- package/dist/core/policy-operations.d.ts.map +0 -1
- package/dist/core/policy-operations.js +0 -623
- package/dist/core/policy-vector-service.d.ts +0 -27
- package/dist/core/policy-vector-service.d.ts.map +0 -1
- package/dist/core/policy-vector-service.js +0 -64
- package/dist/core/unified-creation-session.d.ts +0 -88
- package/dist/core/unified-creation-session.d.ts.map +0 -1
- package/dist/core/unified-creation-session.js +0 -948
- package/dist/core/unified-creation-types.d.ts +0 -68
- package/dist/core/unified-creation-types.d.ts.map +0 -1
- package/dist/core/unified-creation-types.js +0 -61
package/dist/mcp/server.js
CHANGED
|
@@ -48,6 +48,7 @@ const index_js_1 = require("../core/index.js");
|
|
|
48
48
|
const index_js_2 = require("../core/tracing/index.js");
|
|
49
49
|
const index_js_3 = require("../core/telemetry/index.js");
|
|
50
50
|
const plugin_registry_js_1 = require("../core/plugin-registry.js");
|
|
51
|
+
const knowledge_migration_js_1 = require("../core/knowledge-migration.js");
|
|
51
52
|
const mcp_client_registry_js_1 = require("../core/mcp-client-registry.js");
|
|
52
53
|
const mcp_client_manager_js_1 = require("../core/mcp-client-manager.js");
|
|
53
54
|
const fs_1 = require("fs");
|
|
@@ -156,6 +157,11 @@ async function main() {
|
|
|
156
157
|
process.stderr.write(`Background discovery: Plugin '${plugin.name}' now available with ${plugin.tools.length} tool(s)\n`);
|
|
157
158
|
// Note: Tools are automatically registered via pluginManager's internal maps
|
|
158
159
|
// The version tool will reflect the updated plugin status
|
|
160
|
+
if (plugin.tools.some((tool) => tool.name === 'vector_store')) {
|
|
161
|
+
(0, knowledge_migration_js_1.runKnowledgeMigration)(new error_handling_js_1.ConsoleLogger('KnowledgeMigration')).catch((err) => {
|
|
162
|
+
process.stderr.write(`Knowledge migration (post-discovery) error: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
159
165
|
});
|
|
160
166
|
pluginManager.startBackgroundDiscovery();
|
|
161
167
|
}
|
|
@@ -168,6 +174,12 @@ async function main() {
|
|
|
168
174
|
if (pluginConfigs.length > 0) {
|
|
169
175
|
(0, plugin_registry_js_1.initializePluginRegistry)(pluginManager);
|
|
170
176
|
}
|
|
177
|
+
// PRD #375: Auto-migrate legacy patterns/policies into unified knowledge-base
|
|
178
|
+
if (pluginConfigs.length > 0) {
|
|
179
|
+
const migrationLogger = new error_handling_js_1.ConsoleLogger('KnowledgeMigration');
|
|
180
|
+
process.stderr.write('Checking for legacy knowledge collections to migrate...\n');
|
|
181
|
+
await (0, knowledge_migration_js_1.runKnowledgeMigration)(migrationLogger);
|
|
182
|
+
}
|
|
171
183
|
// PRD #358: Initialize MCP client for connecting to external MCP servers
|
|
172
184
|
const mcpClientLogger = new error_handling_js_1.ConsoleLogger('McpClientManager');
|
|
173
185
|
const mcpClientManager = new mcp_client_manager_js_1.McpClientManager(mcpClientLogger);
|
|
@@ -9,7 +9,6 @@
|
|
|
9
9
|
import { z } from 'zod';
|
|
10
10
|
import { Logger } from '../core/error-handling';
|
|
11
11
|
import { DotAI } from '../core/index';
|
|
12
|
-
import { KnowledgeSearchResultItem } from '../core/knowledge-types';
|
|
13
12
|
export declare const MANAGE_KNOWLEDGE_TOOL_NAME = "manageKnowledge";
|
|
14
13
|
export declare const MANAGE_KNOWLEDGE_TOOL_DESCRIPTION: string;
|
|
15
14
|
export declare const MANAGE_KNOWLEDGE_TOOL_INPUT_SCHEMA: {
|
|
@@ -39,27 +38,6 @@ export interface ManageKnowledgeInput {
|
|
|
39
38
|
uriFilter?: string;
|
|
40
39
|
interaction_id?: string;
|
|
41
40
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Result type for the reusable search function
|
|
44
|
-
*/
|
|
45
|
-
export interface SearchKnowledgeBaseResult {
|
|
46
|
-
success: boolean;
|
|
47
|
-
chunks: KnowledgeSearchResultItem[];
|
|
48
|
-
totalMatches: number;
|
|
49
|
-
error?: string;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Reusable knowledge base search function.
|
|
53
|
-
* Can be called from MCP tool handler or HTTP endpoints.
|
|
54
|
-
*
|
|
55
|
-
* @param params Search parameters
|
|
56
|
-
* @returns Search results with chunks or error
|
|
57
|
-
*/
|
|
58
|
-
export declare function searchKnowledgeBase(params: {
|
|
59
|
-
query: string;
|
|
60
|
-
limit?: number;
|
|
61
|
-
uriFilter?: string;
|
|
62
|
-
}): Promise<SearchKnowledgeBaseResult>;
|
|
63
41
|
/**
|
|
64
42
|
* MCP response format with content array
|
|
65
43
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manage-knowledge.d.ts","sourceRoot":"","sources":["../../src/tools/manage-knowledge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"manage-knowledge.d.ts","sourceRoot":"","sources":["../../src/tools/manage-knowledge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAuFtC,eAAO,MAAM,0BAA0B,oBAAoB,CAAC;AAC5D,eAAO,MAAM,iCAAiC,QAKgB,CAAC;AAG/D,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;CAkC9C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,QAAQ,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAwcD;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAgBD;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,oBAAoB,EAC1B,MAAM,EAAE,KAAK,GAAG,IAAI,EACpB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAiD1B"}
|
|
@@ -9,17 +9,67 @@
|
|
|
9
9
|
*/
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.MANAGE_KNOWLEDGE_TOOL_INPUT_SCHEMA = exports.MANAGE_KNOWLEDGE_TOOL_DESCRIPTION = exports.MANAGE_KNOWLEDGE_TOOL_NAME = void 0;
|
|
12
|
-
exports.searchKnowledgeBase = searchKnowledgeBase;
|
|
13
12
|
exports.handleManageKnowledgeTool = handleManageKnowledgeTool;
|
|
14
13
|
const zod_1 = require("zod");
|
|
15
14
|
const plugin_registry_1 = require("../core/plugin-registry");
|
|
16
15
|
const embedding_service_1 = require("../core/embedding-service");
|
|
17
16
|
const request_context_1 = require("../interfaces/request-context");
|
|
18
17
|
const rbac_1 = require("../core/rbac");
|
|
18
|
+
const ai_provider_factory_1 = require("../core/ai-provider-factory");
|
|
19
|
+
const shared_prompt_loader_1 = require("../core/shared-prompt-loader");
|
|
20
|
+
const knowledge_service_1 = require("../core/knowledge-service");
|
|
19
21
|
/**
|
|
20
|
-
*
|
|
22
|
+
* Valid classification tags for document content
|
|
23
|
+
* PRD #375: Unified Knowledge Base
|
|
21
24
|
*/
|
|
22
|
-
const
|
|
25
|
+
const VALID_CLASSIFICATION_TAGS = ['policy', 'pattern'];
|
|
26
|
+
/**
|
|
27
|
+
* Classify a document using AI to determine its content type.
|
|
28
|
+
* Returns a list of applicable tags (["policy"], ["pattern"], ["policy","pattern"], or []).
|
|
29
|
+
*
|
|
30
|
+
* Classification is done on the full document before chunking for better context.
|
|
31
|
+
* The same tags are applied to all chunks from the same document.
|
|
32
|
+
*
|
|
33
|
+
* Fails gracefully: if AI is unavailable or returns unexpected format, returns [].
|
|
34
|
+
*
|
|
35
|
+
* PRD #375: Milestone 2 - AI Classification During Ingestion
|
|
36
|
+
*/
|
|
37
|
+
async function classifyDocument(content) {
|
|
38
|
+
// Skip classification for empty content
|
|
39
|
+
if (!content || content.trim().length === 0) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const aiProvider = (0, ai_provider_factory_1.createAIProvider)();
|
|
44
|
+
if (!aiProvider.isInitialized()) {
|
|
45
|
+
// AI not configured - gracefully skip classification
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
const prompt = (0, shared_prompt_loader_1.loadPrompt)('knowledge-classification', {
|
|
49
|
+
documentContent: content,
|
|
50
|
+
});
|
|
51
|
+
const response = await aiProvider.sendMessage(prompt, 'knowledge-classification');
|
|
52
|
+
// Parse the JSON array from AI response
|
|
53
|
+
// AI should return only a JSON array like [] or ["policy"] or ["policy","pattern"]
|
|
54
|
+
const rawContent = response.content.trim();
|
|
55
|
+
// Extract JSON array (handle potential extra text)
|
|
56
|
+
const jsonMatch = rawContent.match(/\[.*?\]/s);
|
|
57
|
+
if (!jsonMatch) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
61
|
+
if (!Array.isArray(parsed)) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
// Filter to only valid classification tags
|
|
65
|
+
const validTags = parsed.filter((tag) => typeof tag === 'string' && VALID_CLASSIFICATION_TAGS.includes(tag));
|
|
66
|
+
return validTags;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Classification failure is non-blocking — return empty tags
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
23
73
|
// Tool metadata for MCP registration
|
|
24
74
|
exports.MANAGE_KNOWLEDGE_TOOL_NAME = 'manageKnowledge';
|
|
25
75
|
exports.MANAGE_KNOWLEDGE_TOOL_DESCRIPTION = 'Manage the knowledge base: ingest documents, search with natural language, or delete chunks. ' +
|
|
@@ -59,10 +109,6 @@ exports.MANAGE_KNOWLEDGE_TOOL_INPUT_SCHEMA = {
|
|
|
59
109
|
.describe('Optional URL prefix to filter search results (e.g., "https://github.com/org/repo/").'),
|
|
60
110
|
interaction_id: zod_1.z.string().optional().describe('INTERNAL ONLY - Do not populate.'),
|
|
61
111
|
};
|
|
62
|
-
/**
|
|
63
|
-
* Plugin name for agentic-tools
|
|
64
|
-
*/
|
|
65
|
-
const PLUGIN_NAME = 'agentic-tools';
|
|
66
112
|
/**
|
|
67
113
|
* Create error response matching other tool patterns
|
|
68
114
|
*/
|
|
@@ -123,9 +169,15 @@ async function handleIngestOperation(args, logger, requestId) {
|
|
|
123
169
|
chunksDeleted: deletedCount,
|
|
124
170
|
});
|
|
125
171
|
}
|
|
172
|
+
// Step 1b: AI Classification — classify the full document before chunking
|
|
173
|
+
// Same tags are applied to all chunks from this document (document-level classification)
|
|
174
|
+
// PRD #375: Milestone 2 - AI Classification During Ingestion
|
|
175
|
+
logger.debug('Classifying document with AI', { requestId, uri });
|
|
176
|
+
const documentTags = await classifyDocument(content);
|
|
177
|
+
logger.info('Document classified', { requestId, uri, tags: documentTags });
|
|
126
178
|
// Step 2: Chunk the document
|
|
127
179
|
logger.debug('Calling knowledge_chunk plugin tool', { requestId, uri });
|
|
128
|
-
const chunkResponse = await (0, plugin_registry_1.invokePluginTool)(PLUGIN_NAME, 'knowledge_chunk', {
|
|
180
|
+
const chunkResponse = await (0, plugin_registry_1.invokePluginTool)(knowledge_service_1.PLUGIN_NAME, 'knowledge_chunk', {
|
|
129
181
|
content,
|
|
130
182
|
uri,
|
|
131
183
|
});
|
|
@@ -163,8 +215,8 @@ async function handleIngestOperation(args, logger, requestId) {
|
|
|
163
215
|
// Step 3: Initialize collection via plugin
|
|
164
216
|
const vectorSize = embeddingService.getDimensions();
|
|
165
217
|
logger.debug('Initializing knowledge collection via plugin', { requestId, vectorSize });
|
|
166
|
-
const initResponse = await (0, plugin_registry_1.invokePluginTool)(PLUGIN_NAME, 'collection_initialize', {
|
|
167
|
-
collection: KNOWLEDGE_COLLECTION,
|
|
218
|
+
const initResponse = await (0, plugin_registry_1.invokePluginTool)(knowledge_service_1.PLUGIN_NAME, 'collection_initialize', {
|
|
219
|
+
collection: knowledge_service_1.KNOWLEDGE_COLLECTION,
|
|
168
220
|
vectorSize,
|
|
169
221
|
createTextIndex: true,
|
|
170
222
|
});
|
|
@@ -197,6 +249,7 @@ async function handleIngestOperation(args, logger, requestId) {
|
|
|
197
249
|
ingestedAt,
|
|
198
250
|
chunkIndex: chunk.chunkIndex,
|
|
199
251
|
totalChunks: chunk.totalChunks,
|
|
252
|
+
tags: documentTags, // PRD #375: Document-level AI classification tags (same for all chunks)
|
|
200
253
|
extractedPolicyIds: [],
|
|
201
254
|
};
|
|
202
255
|
logger.debug('Storing chunk via plugin', {
|
|
@@ -206,8 +259,8 @@ async function handleIngestOperation(args, logger, requestId) {
|
|
|
206
259
|
totalChunks: chunk.totalChunks,
|
|
207
260
|
});
|
|
208
261
|
// Store via plugin
|
|
209
|
-
const storeResponse = await (0, plugin_registry_1.invokePluginTool)(PLUGIN_NAME, 'vector_store', {
|
|
210
|
-
collection: KNOWLEDGE_COLLECTION,
|
|
262
|
+
const storeResponse = await (0, plugin_registry_1.invokePluginTool)(knowledge_service_1.PLUGIN_NAME, 'vector_store', {
|
|
263
|
+
collection: knowledge_service_1.KNOWLEDGE_COLLECTION,
|
|
211
264
|
id: chunk.id,
|
|
212
265
|
embedding,
|
|
213
266
|
payload,
|
|
@@ -251,124 +304,11 @@ async function handleIngestOperation(args, logger, requestId) {
|
|
|
251
304
|
});
|
|
252
305
|
}
|
|
253
306
|
}
|
|
254
|
-
/**
|
|
255
|
-
* Default limit for search results
|
|
256
|
-
*/
|
|
257
|
-
const DEFAULT_SEARCH_LIMIT = 20;
|
|
258
|
-
/**
|
|
259
|
-
* Reusable knowledge base search function.
|
|
260
|
-
* Can be called from MCP tool handler or HTTP endpoints.
|
|
261
|
-
*
|
|
262
|
-
* @param params Search parameters
|
|
263
|
-
* @returns Search results with chunks or error
|
|
264
|
-
*/
|
|
265
|
-
async function searchKnowledgeBase(params) {
|
|
266
|
-
const { query, limit = DEFAULT_SEARCH_LIMIT, uriFilter } = params;
|
|
267
|
-
// Check plugin availability
|
|
268
|
-
if (!(0, plugin_registry_1.isPluginInitialized)()) {
|
|
269
|
-
return {
|
|
270
|
-
success: false,
|
|
271
|
-
chunks: [],
|
|
272
|
-
totalMatches: 0,
|
|
273
|
-
error: 'Plugin system not available',
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
// Check embedding service availability
|
|
277
|
-
const embeddingService = new embedding_service_1.EmbeddingService();
|
|
278
|
-
if (!embeddingService.isAvailable()) {
|
|
279
|
-
const status = embeddingService.getStatus();
|
|
280
|
-
return {
|
|
281
|
-
success: false,
|
|
282
|
-
chunks: [],
|
|
283
|
-
totalMatches: 0,
|
|
284
|
-
error: `Embedding service not available: ${status.reason}`,
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
// Generate embedding for the search query
|
|
288
|
-
const queryEmbedding = await embeddingService.generateEmbedding(query);
|
|
289
|
-
// Build filter if uriFilter is provided
|
|
290
|
-
let filter;
|
|
291
|
-
if (uriFilter) {
|
|
292
|
-
filter = {
|
|
293
|
-
must: [
|
|
294
|
-
{
|
|
295
|
-
key: 'uri',
|
|
296
|
-
match: {
|
|
297
|
-
value: uriFilter,
|
|
298
|
-
},
|
|
299
|
-
},
|
|
300
|
-
],
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
// Call vector_search plugin tool
|
|
304
|
-
const searchResponse = await (0, plugin_registry_1.invokePluginTool)(PLUGIN_NAME, 'vector_search', {
|
|
305
|
-
collection: KNOWLEDGE_COLLECTION,
|
|
306
|
-
embedding: queryEmbedding,
|
|
307
|
-
limit,
|
|
308
|
-
filter,
|
|
309
|
-
scoreThreshold: 0, // Return all results up to limit, let consumer filter by score
|
|
310
|
-
});
|
|
311
|
-
if (!searchResponse.success) {
|
|
312
|
-
const error = searchResponse.error;
|
|
313
|
-
const errorMessage = error?.message || error?.error || 'Search failed';
|
|
314
|
-
// If collection doesn't exist (Not Found), return empty result (not error)
|
|
315
|
-
if (errorMessage.includes('Not Found') || errorMessage.includes('not found')) {
|
|
316
|
-
return {
|
|
317
|
-
success: true,
|
|
318
|
-
chunks: [],
|
|
319
|
-
totalMatches: 0,
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
return {
|
|
323
|
-
success: false,
|
|
324
|
-
chunks: [],
|
|
325
|
-
totalMatches: 0,
|
|
326
|
-
error: errorMessage,
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
// Extract results from plugin response
|
|
330
|
-
const searchResult = searchResponse.result;
|
|
331
|
-
if (!searchResult.success) {
|
|
332
|
-
const errorMessage = searchResult.error || searchResult.message;
|
|
333
|
-
// If collection doesn't exist, return empty result (not error)
|
|
334
|
-
if (errorMessage.includes('Not Found') || errorMessage.includes('not found')) {
|
|
335
|
-
return {
|
|
336
|
-
success: true,
|
|
337
|
-
chunks: [],
|
|
338
|
-
totalMatches: 0,
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
return {
|
|
342
|
-
success: false,
|
|
343
|
-
chunks: [],
|
|
344
|
-
totalMatches: 0,
|
|
345
|
-
error: errorMessage,
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
// Transform results to KnowledgeSearchResultItem format
|
|
349
|
-
const results = searchResult.data || [];
|
|
350
|
-
const chunks = results.map((result) => ({
|
|
351
|
-
id: result.id,
|
|
352
|
-
content: result.payload.content,
|
|
353
|
-
score: result.score,
|
|
354
|
-
matchType: 'semantic', // Dense vector search only (BM25 deferred)
|
|
355
|
-
uri: result.payload.uri,
|
|
356
|
-
metadata: result.payload.metadata || {},
|
|
357
|
-
chunkIndex: result.payload.chunkIndex,
|
|
358
|
-
totalChunks: result.payload.totalChunks,
|
|
359
|
-
extractedPolicies: undefined, // Populated by PRD #357
|
|
360
|
-
}));
|
|
361
|
-
return {
|
|
362
|
-
success: true,
|
|
363
|
-
chunks,
|
|
364
|
-
totalMatches: chunks.length,
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
307
|
/**
|
|
368
308
|
* Handle the search operation (MCP tool handler)
|
|
369
309
|
*/
|
|
370
310
|
async function handleSearchOperation(args, logger, requestId) {
|
|
371
|
-
const { query, limit = DEFAULT_SEARCH_LIMIT, uriFilter } = args;
|
|
311
|
+
const { query, limit = knowledge_service_1.DEFAULT_SEARCH_LIMIT, uriFilter } = args;
|
|
372
312
|
// Validate required parameters
|
|
373
313
|
if (!query) {
|
|
374
314
|
return createErrorResponse('Missing required parameter: query', {
|
|
@@ -384,7 +324,7 @@ async function handleSearchOperation(args, logger, requestId) {
|
|
|
384
324
|
});
|
|
385
325
|
try {
|
|
386
326
|
// Use the reusable search function
|
|
387
|
-
const searchResult = await searchKnowledgeBase({ query, limit, uriFilter });
|
|
327
|
+
const searchResult = await (0, knowledge_service_1.searchKnowledgeBase)({ query, limit, uriFilter });
|
|
388
328
|
if (!searchResult.success) {
|
|
389
329
|
logger.error('Knowledge base search failed', new Error(searchResult.error), { requestId });
|
|
390
330
|
return createErrorResponse('Search failed', {
|
|
@@ -433,8 +373,8 @@ async function handleSearchOperation(args, logger, requestId) {
|
|
|
433
373
|
*/
|
|
434
374
|
async function deleteChunksByUri(uri, logger, requestId) {
|
|
435
375
|
// Query all chunks matching the URI
|
|
436
|
-
const queryResponse = await (0, plugin_registry_1.invokePluginTool)(PLUGIN_NAME, 'vector_query', {
|
|
437
|
-
collection: KNOWLEDGE_COLLECTION,
|
|
376
|
+
const queryResponse = await (0, plugin_registry_1.invokePluginTool)(knowledge_service_1.PLUGIN_NAME, 'vector_query', {
|
|
377
|
+
collection: knowledge_service_1.KNOWLEDGE_COLLECTION,
|
|
438
378
|
filter: {
|
|
439
379
|
must: [{ key: 'uri', match: { value: uri } }],
|
|
440
380
|
},
|
|
@@ -471,8 +411,8 @@ async function deleteChunksByUri(uri, logger, requestId) {
|
|
|
471
411
|
let deletedCount = 0;
|
|
472
412
|
for (const chunk of chunksToDelete) {
|
|
473
413
|
logger.debug('Deleting chunk', { requestId, chunkId: chunk.id });
|
|
474
|
-
const deleteResponse = await (0, plugin_registry_1.invokePluginTool)(PLUGIN_NAME, 'vector_delete', {
|
|
475
|
-
collection: KNOWLEDGE_COLLECTION,
|
|
414
|
+
const deleteResponse = await (0, plugin_registry_1.invokePluginTool)(knowledge_service_1.PLUGIN_NAME, 'vector_delete', {
|
|
415
|
+
collection: knowledge_service_1.KNOWLEDGE_COLLECTION,
|
|
476
416
|
id: chunk.id,
|
|
477
417
|
});
|
|
478
418
|
if (!deleteResponse.success) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operate-analysis.d.ts","sourceRoot":"","sources":["../../src/tools/operate-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAIhD,OAAO,EAEL,kBAAkB,EAElB,eAAe,
|
|
1
|
+
{"version":3,"file":"operate-analysis.d.ts","sourceRoot":"","sources":["../../src/tools/operate-analysis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAIhD,OAAO,EAEL,kBAAkB,EAElB,eAAe,EAIhB,MAAM,WAAW,CAAC;AAwBnB;;GAEG;AACH,UAAU,qBAAqB;IAC7B,MAAM,EAAE,wBAAwB,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,OAAO,CAAC;QACtB,eAAe,EAAE,eAAe,CAAC;QACjC,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,gBAAgB,EAAE;YAChB,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;YAC7B,OAAO,EAAE,MAAM,CAAC;SACjB,CAAC;QACF,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC3B,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,KAAK,EAAE;YACL,KAAK,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;YACjC,WAAW,EAAE,MAAM,CAAC;SACrB,CAAC;QACF,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,qBAAqB,CAAC,kBAAkB,CAAC,EACzD,aAAa,EAAE,aAAa,EAC5B,SAAS,CAAC,EAAE,MAAM,EAClB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,qBAAqB,CAAC,CA2DhC"}
|
|
@@ -65,19 +65,20 @@ function loadSystemPrompt() {
|
|
|
65
65
|
return (0, shared_prompt_loader_1.loadPrompt)('operate-system');
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
* Builds dynamic user message with intent and embedded context
|
|
69
|
-
* Uses template from prompts/operate-user.md and formatting functions from operate.ts
|
|
68
|
+
* Builds dynamic user message with intent and embedded context.
|
|
69
|
+
* Uses template from prompts/operate-user.md and formatting functions from operate.ts.
|
|
70
|
+
*
|
|
71
|
+
* PRD #375: Unified Knowledge Base — uses single knowledgeContext instead of
|
|
72
|
+
* separate patterns/policies sections.
|
|
70
73
|
*/
|
|
71
74
|
function buildUserMessage(intent, context) {
|
|
72
75
|
// Format context sections using shared formatting functions
|
|
73
|
-
const
|
|
74
|
-
const policiesText = (0, operate_1.formatPolicies)(context.policies);
|
|
76
|
+
const knowledgeContextText = (0, operate_1.formatKnowledgeContext)(context.knowledgeChunks);
|
|
75
77
|
const capabilitiesText = (0, operate_1.formatCapabilities)(context.capabilities);
|
|
76
78
|
// Use loadPrompt with Handlebars template variables
|
|
77
79
|
return (0, shared_prompt_loader_1.loadPrompt)('operate-user', {
|
|
78
80
|
intent,
|
|
79
|
-
|
|
80
|
-
policies: policiesText,
|
|
81
|
+
knowledgeContext: knowledgeContextText,
|
|
81
82
|
capabilities: capabilitiesText,
|
|
82
83
|
});
|
|
83
84
|
}
|
package/dist/tools/operate.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { Logger } from '../core/error-handling';
|
|
6
6
|
import { PluginManager } from '../core/plugin-manager';
|
|
7
|
-
import {
|
|
7
|
+
import { KnowledgeSearchResultItem } from '../core/knowledge-types';
|
|
8
8
|
import { ResourceCapability } from '../core/capabilities';
|
|
9
9
|
import { BaseVisualizationData } from '../core/visualization';
|
|
10
10
|
export declare const OPERATE_TOOL_NAME = "operate";
|
|
@@ -51,9 +51,15 @@ export type OperateSession = {
|
|
|
51
51
|
updatedAt: string;
|
|
52
52
|
data: OperateSessionData;
|
|
53
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Embedded context for operate analysis.
|
|
56
|
+
* PRD #375: Unified Knowledge Base — patterns and policies are now unified
|
|
57
|
+
* in the knowledge-base collection. knowledgeChunks replaces separate
|
|
58
|
+
* patterns[] and policies[] fields. Chunks include tags for type identification.
|
|
59
|
+
*/
|
|
54
60
|
export interface EmbeddedContext {
|
|
55
|
-
|
|
56
|
-
|
|
61
|
+
/** Knowledge chunks from unified knowledge base (includes policy, pattern, and general content) */
|
|
62
|
+
knowledgeChunks: KnowledgeSearchResultItem[];
|
|
57
63
|
capabilities: ResourceCapability[];
|
|
58
64
|
}
|
|
59
65
|
export interface ProposedChanges {
|
|
@@ -106,20 +112,26 @@ export interface OperateOutput {
|
|
|
106
112
|
agentInstructions?: string;
|
|
107
113
|
}
|
|
108
114
|
/**
|
|
109
|
-
* Embed context (
|
|
115
|
+
* Embed context (knowledge, capabilities) for AI analysis.
|
|
116
|
+
*
|
|
117
|
+
* PRD #375: Unified Knowledge Base — searches single knowledge-base collection
|
|
118
|
+
* instead of separate pattern/policy collections. Results include tags so the
|
|
119
|
+
* AI can distinguish policy, pattern, and general knowledge content.
|
|
120
|
+
*
|
|
110
121
|
* @param intent User's operational intent
|
|
111
|
-
* @
|
|
122
|
+
* @param logger Logger instance
|
|
123
|
+
* @returns Embedded context with knowledge chunks and capabilities
|
|
112
124
|
* @throws Error if capabilities are not available (mandatory)
|
|
113
125
|
*/
|
|
114
126
|
export declare function embedContext(intent: string, logger: Logger): Promise<EmbeddedContext>;
|
|
115
127
|
/**
|
|
116
|
-
* Format
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
*
|
|
128
|
+
* Format knowledge chunks for template placeholder.
|
|
129
|
+
*
|
|
130
|
+
* PRD #375: Unified Knowledge Base — replaces separate formatPatterns/formatPolicies.
|
|
131
|
+
* Chunks include tags so the AI can interpret what type each result represents.
|
|
132
|
+
* Tags: "policy" = enforcement rule, "pattern" = reusable architecture, [] = general content.
|
|
121
133
|
*/
|
|
122
|
-
export declare function
|
|
134
|
+
export declare function formatKnowledgeContext(chunks: KnowledgeSearchResultItem[]): string;
|
|
123
135
|
/**
|
|
124
136
|
* Format capabilities for template placeholder
|
|
125
137
|
* Capabilities are already ordered by relevance from vector search
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operate.d.ts","sourceRoot":"","sources":["../../src/tools/operate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAIL,MAAM,EAEP,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"operate.d.ts","sourceRoot":"","sources":["../../src/tools/operate.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/operate.js
CHANGED
|
@@ -38,8 +38,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
exports.OPERATE_TOOL_INPUT_SCHEMA = exports.OPERATE_TOOL_DESCRIPTION = exports.OPERATE_TOOL_NAME = void 0;
|
|
40
40
|
exports.embedContext = embedContext;
|
|
41
|
-
exports.
|
|
42
|
-
exports.formatPolicies = formatPolicies;
|
|
41
|
+
exports.formatKnowledgeContext = formatKnowledgeContext;
|
|
43
42
|
exports.formatCapabilities = formatCapabilities;
|
|
44
43
|
exports.operate = operate;
|
|
45
44
|
exports.handleOperateTool = handleOperateTool;
|
|
@@ -48,9 +47,8 @@ const error_handling_1 = require("../core/error-handling");
|
|
|
48
47
|
const generic_session_manager_1 = require("../core/generic-session-manager");
|
|
49
48
|
const request_context_1 = require("../interfaces/request-context");
|
|
50
49
|
const rbac_1 = require("../core/rbac");
|
|
51
|
-
const pattern_vector_service_1 = require("../core/pattern-vector-service");
|
|
52
|
-
const policy_vector_service_1 = require("../core/policy-vector-service");
|
|
53
50
|
const capability_vector_service_1 = require("../core/capability-vector-service");
|
|
51
|
+
const knowledge_service_1 = require("../core/knowledge-service");
|
|
54
52
|
const index_1 = require("../core/index");
|
|
55
53
|
// Tool metadata for direct MCP registration
|
|
56
54
|
exports.OPERATE_TOOL_NAME = 'operate';
|
|
@@ -89,43 +87,41 @@ const sessionManager = new generic_session_manager_1.GenericSessionManager('opr'
|
|
|
89
87
|
// Initialize logger
|
|
90
88
|
const logger = new error_handling_1.ConsoleLogger('OperateTool');
|
|
91
89
|
/**
|
|
92
|
-
* Embed context (
|
|
90
|
+
* Embed context (knowledge, capabilities) for AI analysis.
|
|
91
|
+
*
|
|
92
|
+
* PRD #375: Unified Knowledge Base — searches single knowledge-base collection
|
|
93
|
+
* instead of separate pattern/policy collections. Results include tags so the
|
|
94
|
+
* AI can distinguish policy, pattern, and general knowledge content.
|
|
95
|
+
*
|
|
93
96
|
* @param intent User's operational intent
|
|
94
|
-
* @
|
|
97
|
+
* @param logger Logger instance
|
|
98
|
+
* @returns Embedded context with knowledge chunks and capabilities
|
|
95
99
|
* @throws Error if capabilities are not available (mandatory)
|
|
96
100
|
*/
|
|
97
101
|
async function embedContext(intent, logger) {
|
|
98
102
|
const context = {
|
|
99
|
-
|
|
100
|
-
policies: [],
|
|
103
|
+
knowledgeChunks: [],
|
|
101
104
|
capabilities: [],
|
|
102
105
|
};
|
|
103
|
-
// Search
|
|
106
|
+
// Search unified knowledge base (optional - non-blocking)
|
|
107
|
+
// Results include tags so AI can see which are policies, patterns, or general content
|
|
104
108
|
try {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
const knowledgeResult = await (0, knowledge_service_1.searchKnowledgeBase)({ query: intent, limit: 20 });
|
|
110
|
+
if (knowledgeResult.success) {
|
|
111
|
+
context.knowledgeChunks = knowledgeResult.chunks;
|
|
112
|
+
logger.info(`Found ${context.knowledgeChunks.length} relevant knowledge chunks (unified knowledge base)`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
logger.warn('Knowledge base search failed, continuing without organizational context', {
|
|
116
|
+
error: knowledgeResult.error,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
111
119
|
}
|
|
112
120
|
catch (error) {
|
|
113
|
-
logger.warn('
|
|
121
|
+
logger.warn('Knowledge base search failed, continuing without organizational context', {
|
|
114
122
|
error,
|
|
115
123
|
});
|
|
116
124
|
}
|
|
117
|
-
// Search for relevant policies (optional - non-blocking)
|
|
118
|
-
try {
|
|
119
|
-
const policyService = new policy_vector_service_1.PolicyVectorService();
|
|
120
|
-
const policyResults = await policyService.searchPolicyIntents(intent, {
|
|
121
|
-
limit: 5,
|
|
122
|
-
});
|
|
123
|
-
context.policies = policyResults.map(result => result.data);
|
|
124
|
-
logger.info(`Found ${context.policies.length} relevant organizational policies`);
|
|
125
|
-
}
|
|
126
|
-
catch (error) {
|
|
127
|
-
logger.warn('Policy search failed, continuing without policies', { error });
|
|
128
|
-
}
|
|
129
125
|
// Search for relevant cluster capabilities (MANDATORY)
|
|
130
126
|
try {
|
|
131
127
|
// Use QDRANT_CAPABILITIES_COLLECTION env var for collection name
|
|
@@ -157,39 +153,25 @@ async function embedContext(intent, logger) {
|
|
|
157
153
|
return context;
|
|
158
154
|
}
|
|
159
155
|
/**
|
|
160
|
-
* Format
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
let formatted = '';
|
|
167
|
-
patterns.forEach((pattern, index) => {
|
|
168
|
-
formatted += `### Pattern ${index + 1}: ${pattern.description}\n\n`;
|
|
169
|
-
formatted += `**Triggers:** ${pattern.triggers.join(', ')}\n\n`;
|
|
170
|
-
formatted += `**Suggested Resources:** ${pattern.suggestedResources.join(', ')}\n\n`;
|
|
171
|
-
formatted += `**Rationale:** ${pattern.rationale}\n\n`;
|
|
172
|
-
if (index < patterns.length - 1) {
|
|
173
|
-
formatted += '---\n\n';
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
return formatted;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Format policies for template placeholder
|
|
156
|
+
* Format knowledge chunks for template placeholder.
|
|
157
|
+
*
|
|
158
|
+
* PRD #375: Unified Knowledge Base — replaces separate formatPatterns/formatPolicies.
|
|
159
|
+
* Chunks include tags so the AI can interpret what type each result represents.
|
|
160
|
+
* Tags: "policy" = enforcement rule, "pattern" = reusable architecture, [] = general content.
|
|
180
161
|
*/
|
|
181
|
-
function
|
|
182
|
-
if (
|
|
183
|
-
return 'No organizational
|
|
162
|
+
function formatKnowledgeContext(chunks) {
|
|
163
|
+
if (chunks.length === 0) {
|
|
164
|
+
return 'No relevant organizational knowledge found matching this intent.';
|
|
184
165
|
}
|
|
185
166
|
let formatted = '';
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
formatted += `**
|
|
192
|
-
|
|
167
|
+
chunks.forEach((chunk, index) => {
|
|
168
|
+
const typeLabel = chunk.tags.length > 0
|
|
169
|
+
? chunk.tags.map(t => t.charAt(0).toUpperCase() + t.slice(1)).join(' + ')
|
|
170
|
+
: 'General';
|
|
171
|
+
formatted += `### Knowledge ${index + 1} [${typeLabel}]\n\n`;
|
|
172
|
+
formatted += `**Source:** ${chunk.uri}\n\n`;
|
|
173
|
+
formatted += (chunk.content.length > 300 ? chunk.content.substring(0, 300) + '...' : chunk.content) + '\n\n';
|
|
174
|
+
if (index < chunks.length - 1) {
|
|
193
175
|
formatted += '---\n\n';
|
|
194
176
|
}
|
|
195
177
|
});
|