byterover-cli 1.7.2 → 1.8.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/README.md +17 -3
- package/dist/agent/core/domain/tools/constants.d.ts +0 -15
- package/dist/agent/core/domain/tools/constants.js +0 -15
- package/dist/agent/core/interfaces/i-cipher-agent.d.ts +6 -0
- package/dist/agent/core/interfaces/i-curate-service.d.ts +12 -0
- package/dist/agent/infra/llm/internal-llm-service.d.ts +13 -0
- package/dist/agent/infra/llm/internal-llm-service.js +61 -21
- package/dist/agent/infra/tools/implementations/curate-tool.d.ts +133 -0
- package/dist/agent/infra/tools/implementations/curate-tool.js +14 -0
- package/dist/agent/infra/tools/implementations/search-knowledge-service.js +91 -14
- package/dist/agent/infra/tools/index.d.ts +0 -4
- package/dist/agent/infra/tools/index.js +0 -4
- package/dist/agent/infra/tools/tool-registry.js +0 -113
- package/dist/agent/resources/prompts/curate-detail-preservation.yml +73 -0
- package/dist/agent/resources/prompts/system-prompt.yml +69 -3
- package/dist/server/core/domain/knowledge/markdown-writer.d.ts +13 -0
- package/dist/server/core/domain/knowledge/markdown-writer.js +116 -8
- package/dist/server/infra/executor/curate-executor.js +1 -1
- package/dist/server/infra/executor/direct-search-responder.d.ts +45 -0
- package/dist/server/infra/executor/direct-search-responder.js +86 -0
- package/dist/server/infra/executor/folder-pack-executor.d.ts +13 -5
- package/dist/server/infra/executor/folder-pack-executor.js +739 -39
- package/dist/server/infra/executor/query-executor.d.ts +49 -3
- package/dist/server/infra/executor/query-executor.js +194 -9
- package/dist/server/infra/executor/query-result-cache.d.ts +87 -0
- package/dist/server/infra/executor/query-result-cache.js +127 -0
- package/dist/server/infra/executor/query-similarity.d.ts +28 -0
- package/dist/server/infra/executor/query-similarity.js +41 -0
- package/dist/server/infra/process/agent-worker.js +9 -2
- package/dist/server/infra/process/inline-agent-executor.js +16 -5
- package/dist/server/infra/usecase/curate-use-case.js +6 -1
- package/dist/server/infra/usecase/query-use-case.js +10 -0
- package/dist/server/utils/file-validator.js +78 -1
- package/dist/tui/hooks/use-slash-completion.js +25 -4
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/dist/agent/infra/tools/implementations/bash-exec-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/bash-exec-tool.js +0 -110
- package/dist/agent/infra/tools/implementations/bash-output-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/bash-output-tool.js +0 -43
- package/dist/agent/infra/tools/implementations/batch-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/batch-tool.js +0 -142
- package/dist/agent/infra/tools/implementations/create-knowledge-topic-tool.d.ts +0 -11
- package/dist/agent/infra/tools/implementations/create-knowledge-topic-tool.js +0 -149
- package/dist/agent/infra/tools/implementations/delete-memory-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/delete-memory-tool.js +0 -37
- package/dist/agent/infra/tools/implementations/edit-file-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/edit-file-tool.js +0 -50
- package/dist/agent/infra/tools/implementations/edit-memory-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/edit-memory-tool.js +0 -53
- package/dist/agent/infra/tools/implementations/kill-process-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/kill-process-tool.js +0 -55
- package/dist/agent/infra/tools/implementations/list-memories-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/list-memories-tool.js +0 -63
- package/dist/agent/infra/tools/implementations/read-memory-tool.d.ts +0 -12
- package/dist/agent/infra/tools/implementations/read-memory-tool.js +0 -39
- package/dist/agent/infra/tools/implementations/read-todos-tool.d.ts +0 -11
- package/dist/agent/infra/tools/implementations/read-todos-tool.js +0 -39
- package/dist/agent/infra/tools/implementations/search-history-tool.d.ts +0 -10
- package/dist/agent/infra/tools/implementations/search-history-tool.js +0 -36
- package/dist/agent/infra/tools/implementations/spec-analyze-tool.d.ts +0 -7
- package/dist/agent/infra/tools/implementations/spec-analyze-tool.js +0 -78
- package/dist/agent/infra/tools/implementations/write-memory-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/write-memory-tool.js +0 -52
- package/dist/agent/infra/tools/implementations/write-todos-tool.d.ts +0 -13
- package/dist/agent/infra/tools/implementations/write-todos-tool.js +0 -121
|
@@ -4,11 +4,21 @@ import { removeStopwords } from 'stopword';
|
|
|
4
4
|
import { BRV_DIR, CONTEXT_FILE_EXTENSION, CONTEXT_TREE_DIR } from '../../../../server/constants.js';
|
|
5
5
|
const MAX_CONTEXT_TREE_FILES = 10_000;
|
|
6
6
|
const DEFAULT_CACHE_TTL_MS = 5000;
|
|
7
|
+
/** Bump when MINISEARCH_OPTIONS fields/boost change to invalidate cached indexes */
|
|
8
|
+
const INDEX_SCHEMA_VERSION = 3;
|
|
9
|
+
/** Only include results whose score is at least this fraction of the top result's score */
|
|
10
|
+
const SCORE_GAP_RATIO = 0.2;
|
|
11
|
+
/** Minimum absolute score for the top result. Below this, the query is considered out-of-domain */
|
|
12
|
+
const MINIMUM_RELEVANCE_SCORE = 4;
|
|
13
|
+
/** Score threshold above which results are trusted despite unmatched query terms */
|
|
14
|
+
const UNMATCHED_TERM_SCORE_THRESHOLD = 8;
|
|
15
|
+
/** Minimum query term length to consider "significant" for OOD term-based detection */
|
|
16
|
+
const UNMATCHED_TERM_MIN_LENGTH = 4;
|
|
7
17
|
const MINISEARCH_OPTIONS = {
|
|
8
|
-
fields: ['title', 'content'],
|
|
18
|
+
fields: ['title', 'content', 'path'],
|
|
9
19
|
idField: 'id',
|
|
10
20
|
searchOptions: {
|
|
11
|
-
boost: { title:
|
|
21
|
+
boost: { path: 1.5, title: 3 },
|
|
12
22
|
fuzzy: 0.2,
|
|
13
23
|
prefix: true,
|
|
14
24
|
},
|
|
@@ -19,6 +29,24 @@ function filterStopWords(query) {
|
|
|
19
29
|
const filtered = removeStopwords(words);
|
|
20
30
|
return filtered.length > 0 ? filtered.join(' ') : query;
|
|
21
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Checks if any significant query term is completely unmatched across search results.
|
|
34
|
+
* Uses MiniSearch's queryTerms property to identify which terms actually matched.
|
|
35
|
+
* A "significant" term is one with length >= UNMATCHED_TERM_MIN_LENGTH (filters out
|
|
36
|
+
* short generic words that are noisy for OOD detection).
|
|
37
|
+
*/
|
|
38
|
+
function hasUnmatchedSignificantTerms(queryTerms, searchResults) {
|
|
39
|
+
const significantTerms = queryTerms.filter((t) => t.length >= UNMATCHED_TERM_MIN_LENGTH);
|
|
40
|
+
if (significantTerms.length === 0)
|
|
41
|
+
return false;
|
|
42
|
+
const allMatchedQueryTerms = new Set();
|
|
43
|
+
for (const result of searchResults.slice(0, 10)) {
|
|
44
|
+
for (const term of result.queryTerms) {
|
|
45
|
+
allMatchedQueryTerms.add(term);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return significantTerms.some((t) => !allMatchedQueryTerms.has(t));
|
|
49
|
+
}
|
|
22
50
|
function extractTitle(content, fallbackTitle) {
|
|
23
51
|
const match = /^# (.+)$/m.exec(content);
|
|
24
52
|
return match ? match[1].trim() : fallbackTitle;
|
|
@@ -110,6 +138,7 @@ async function buildFreshIndex(fileSystem, contextTreePath, filesWithMtime) {
|
|
|
110
138
|
fileMtimes: new Map(),
|
|
111
139
|
index,
|
|
112
140
|
lastValidatedAt: now,
|
|
141
|
+
schemaVersion: INDEX_SCHEMA_VERSION,
|
|
113
142
|
};
|
|
114
143
|
}
|
|
115
144
|
const documentPromises = filesWithMtime.map(async ({ mtime, path: filePath }) => {
|
|
@@ -145,6 +174,7 @@ async function buildFreshIndex(fileSystem, contextTreePath, filesWithMtime) {
|
|
|
145
174
|
fileMtimes,
|
|
146
175
|
index,
|
|
147
176
|
lastValidatedAt: now,
|
|
177
|
+
schemaVersion: INDEX_SCHEMA_VERSION,
|
|
148
178
|
};
|
|
149
179
|
}
|
|
150
180
|
/**
|
|
@@ -156,6 +186,7 @@ async function acquireIndex(state, fileSystem, contextTreePath, ttlMs) {
|
|
|
156
186
|
// Fast path: TTL-based cache hit (no I/O needed)
|
|
157
187
|
if (state.cachedIndex &&
|
|
158
188
|
state.cachedIndex.contextTreePath === contextTreePath &&
|
|
189
|
+
state.cachedIndex.schemaVersion === INDEX_SCHEMA_VERSION &&
|
|
159
190
|
ttlMs > 0 &&
|
|
160
191
|
now - state.cachedIndex.lastValidatedAt < ttlMs) {
|
|
161
192
|
return state.cachedIndex;
|
|
@@ -181,6 +212,7 @@ async function acquireIndex(state, fileSystem, contextTreePath, ttlMs) {
|
|
|
181
212
|
fileMtimes: new Map(),
|
|
182
213
|
index: emptyIndex,
|
|
183
214
|
lastValidatedAt: 0,
|
|
215
|
+
schemaVersion: INDEX_SCHEMA_VERSION,
|
|
184
216
|
};
|
|
185
217
|
}
|
|
186
218
|
}
|
|
@@ -188,6 +220,7 @@ async function acquireIndex(state, fileSystem, contextTreePath, ttlMs) {
|
|
|
188
220
|
// Re-check cache validity after getting file list (another call may have finished)
|
|
189
221
|
if (state.cachedIndex &&
|
|
190
222
|
state.cachedIndex.contextTreePath === contextTreePath &&
|
|
223
|
+
state.cachedIndex.schemaVersion === INDEX_SCHEMA_VERSION &&
|
|
191
224
|
isCacheValid(state.cachedIndex, currentFiles)) {
|
|
192
225
|
// Update timestamp atomically by creating a new object
|
|
193
226
|
const updatedCache = {
|
|
@@ -266,19 +299,63 @@ export class SearchKnowledgeService {
|
|
|
266
299
|
};
|
|
267
300
|
}
|
|
268
301
|
const filteredQuery = filterStopWords(query);
|
|
269
|
-
const
|
|
302
|
+
const filteredWords = filteredQuery.split(/\s+/).filter((w) => w.length >= 2);
|
|
303
|
+
// AND-first strategy: for multi-word queries, try AND for concentrated scores.
|
|
304
|
+
// If AND returns no results, fall back to OR to ensure no regression.
|
|
305
|
+
let searchResults;
|
|
306
|
+
let andSearchFailed = false;
|
|
307
|
+
if (filteredWords.length >= 2) {
|
|
308
|
+
searchResults = index.search(filteredQuery, { combineWith: 'AND' });
|
|
309
|
+
if (searchResults.length === 0) {
|
|
310
|
+
andSearchFailed = true;
|
|
311
|
+
searchResults = index.search(filteredQuery, { combineWith: 'OR' });
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
searchResults = index.search(filteredQuery, { combineWith: 'OR' });
|
|
316
|
+
}
|
|
270
317
|
const results = [];
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
if (
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
318
|
+
if (searchResults.length > 0) {
|
|
319
|
+
// OOD detection: if the best result scores below the minimum floor,
|
|
320
|
+
// the query has no meaningful match in the knowledge base.
|
|
321
|
+
// Only apply for corpora with enough documents for reliable BM25 scoring.
|
|
322
|
+
if (documentMap.size >= 50 && searchResults[0].score < MINIMUM_RELEVANCE_SCORE) {
|
|
323
|
+
return {
|
|
324
|
+
message: 'No matching knowledge found for this query. The topic may not be covered in the context tree.',
|
|
325
|
+
results: [],
|
|
326
|
+
totalFound: 0,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
// Term-based OOD: when AND search failed, check if significant query terms
|
|
330
|
+
// are completely absent from the corpus. If unmatched terms exist and the
|
|
331
|
+
// score is below the trusted threshold, the query is about an uncovered topic.
|
|
332
|
+
if (andSearchFailed &&
|
|
333
|
+
documentMap.size >= 50 &&
|
|
334
|
+
searchResults[0].score < UNMATCHED_TERM_SCORE_THRESHOLD &&
|
|
335
|
+
hasUnmatchedSignificantTerms(filteredWords, searchResults)) {
|
|
336
|
+
return {
|
|
337
|
+
message: 'No matching knowledge found for this query. The topic may not be covered in the context tree.',
|
|
338
|
+
results: [],
|
|
339
|
+
totalFound: 0,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
const topScore = searchResults[0].score;
|
|
343
|
+
const scoreFloor = topScore * SCORE_GAP_RATIO;
|
|
344
|
+
const resultLimit = Math.min(limit, searchResults.length);
|
|
345
|
+
for (let i = 0; i < resultLimit; i++) {
|
|
346
|
+
const result = searchResults[i];
|
|
347
|
+
// Score-gap filter: skip results too far below the top score
|
|
348
|
+
if (result.score < scoreFloor)
|
|
349
|
+
break;
|
|
350
|
+
const document = documentMap.get(result.id);
|
|
351
|
+
if (document) {
|
|
352
|
+
results.push({
|
|
353
|
+
excerpt: extractExcerpt(document.content, query),
|
|
354
|
+
path: document.path,
|
|
355
|
+
score: Math.round(result.score * 100) / 100,
|
|
356
|
+
title: document.title,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
282
359
|
}
|
|
283
360
|
}
|
|
284
361
|
return {
|
|
@@ -3,14 +3,10 @@ export { ToolName } from '../../core/domain/tools/constants.js';
|
|
|
3
3
|
export type { KnownTool } from '../../core/domain/tools/constants.js';
|
|
4
4
|
export type { JSONSchema7, Tool, ToolExecutionContext, ToolSet } from '../../core/domain/tools/types.js';
|
|
5
5
|
export type { IToolProvider } from '../../core/interfaces/i-tool-provider.js';
|
|
6
|
-
export { createCreateKnowledgeTopicTool } from './implementations/create-knowledge-topic-tool.js';
|
|
7
|
-
export { createEditFileTool } from './implementations/edit-file-tool.js';
|
|
8
6
|
export { createGlobFilesTool } from './implementations/glob-files-tool.js';
|
|
9
7
|
export { createGrepContentTool } from './implementations/grep-content-tool.js';
|
|
10
8
|
export { createReadFileTool } from './implementations/read-file-tool.js';
|
|
11
|
-
export { createSearchHistoryTool } from './implementations/search-history-tool.js';
|
|
12
9
|
export { createSearchKnowledgeTool } from './implementations/search-knowledge-tool.js';
|
|
13
|
-
export { createSpecAnalyzeTool } from './implementations/spec-analyze-tool.js';
|
|
14
10
|
export { createWriteFileTool } from './implementations/write-file-tool.js';
|
|
15
11
|
export { ToolManager } from './tool-manager.js';
|
|
16
12
|
export { ToolProvider } from './tool-provider.js';
|
|
@@ -3,14 +3,10 @@ export { ToolError, ToolExecutionError, ToolNotFoundError, ToolProviderNotInitia
|
|
|
3
3
|
// Constants
|
|
4
4
|
export { ToolName } from '../../core/domain/tools/constants.js';
|
|
5
5
|
// Tool implementations (for direct access if needed)
|
|
6
|
-
export { createCreateKnowledgeTopicTool } from './implementations/create-knowledge-topic-tool.js';
|
|
7
|
-
export { createEditFileTool } from './implementations/edit-file-tool.js';
|
|
8
6
|
export { createGlobFilesTool } from './implementations/glob-files-tool.js';
|
|
9
7
|
export { createGrepContentTool } from './implementations/grep-content-tool.js';
|
|
10
8
|
export { createReadFileTool } from './implementations/read-file-tool.js';
|
|
11
|
-
export { createSearchHistoryTool } from './implementations/search-history-tool.js';
|
|
12
9
|
export { createSearchKnowledgeTool } from './implementations/search-knowledge-tool.js';
|
|
13
|
-
export { createSpecAnalyzeTool } from './implementations/spec-analyze-tool.js';
|
|
14
10
|
export { createWriteFileTool } from './implementations/write-file-tool.js';
|
|
15
11
|
// Registry and provider
|
|
16
12
|
export { ToolManager } from './tool-manager.js';
|
|
@@ -1,30 +1,14 @@
|
|
|
1
1
|
import { ToolName } from '../../core/domain/tools/constants.js';
|
|
2
2
|
import { createCurateService } from '../sandbox/curate-service.js';
|
|
3
|
-
import { createBashExecTool } from './implementations/bash-exec-tool.js';
|
|
4
|
-
import { createBashOutputTool } from './implementations/bash-output-tool.js';
|
|
5
|
-
import { createBatchTool } from './implementations/batch-tool.js';
|
|
6
3
|
import { createCodeExecTool } from './implementations/code-exec-tool.js';
|
|
7
|
-
import { createCreateKnowledgeTopicTool } from './implementations/create-knowledge-topic-tool.js';
|
|
8
4
|
import { createCurateTool } from './implementations/curate-tool.js';
|
|
9
|
-
import { createDeleteMemoryTool } from './implementations/delete-memory-tool.js';
|
|
10
|
-
import { createEditFileTool } from './implementations/edit-file-tool.js';
|
|
11
|
-
import { createEditMemoryTool } from './implementations/edit-memory-tool.js';
|
|
12
|
-
// import {createFindKnowledgeTopicsTool} from './implementations/find-knowledge-topics-tool.js'
|
|
13
5
|
import { createGlobFilesTool } from './implementations/glob-files-tool.js';
|
|
14
6
|
import { createGrepContentTool } from './implementations/grep-content-tool.js';
|
|
15
|
-
import { createKillProcessTool } from './implementations/kill-process-tool.js';
|
|
16
7
|
import { createListDirectoryTool } from './implementations/list-directory-tool.js';
|
|
17
|
-
import { createListMemoriesTool } from './implementations/list-memories-tool.js';
|
|
18
8
|
import { createReadFileTool } from './implementations/read-file-tool.js';
|
|
19
|
-
import { createReadMemoryTool } from './implementations/read-memory-tool.js';
|
|
20
|
-
import { createReadTodosTool } from './implementations/read-todos-tool.js';
|
|
21
|
-
import { createSearchHistoryTool } from './implementations/search-history-tool.js';
|
|
22
9
|
import { createSearchKnowledgeService } from './implementations/search-knowledge-service.js';
|
|
23
10
|
import { createSearchKnowledgeTool } from './implementations/search-knowledge-tool.js';
|
|
24
|
-
import { createSpecAnalyzeTool } from './implementations/spec-analyze-tool.js';
|
|
25
11
|
import { createWriteFileTool } from './implementations/write-file-tool.js';
|
|
26
|
-
import { createWriteMemoryTool } from './implementations/write-memory-tool.js';
|
|
27
|
-
import { createWriteTodosTool } from './implementations/write-todos-tool.js';
|
|
28
12
|
import { ToolMarker } from './tool-markers.js';
|
|
29
13
|
/**
|
|
30
14
|
* Helper function to safely retrieve a required service.
|
|
@@ -51,24 +35,6 @@ function getRequiredService(service, serviceName) {
|
|
|
51
35
|
* 3. Add entry to this registry
|
|
52
36
|
*/
|
|
53
37
|
export const TOOL_REGISTRY = {
|
|
54
|
-
[ToolName.BASH_EXEC]: {
|
|
55
|
-
descriptionFile: 'bash_exec',
|
|
56
|
-
factory: (services) => createBashExecTool(getRequiredService(services.processService, 'processService')),
|
|
57
|
-
markers: [ToolMarker.Execution],
|
|
58
|
-
requiredServices: ['processService'],
|
|
59
|
-
},
|
|
60
|
-
[ToolName.BASH_OUTPUT]: {
|
|
61
|
-
descriptionFile: 'bash_output',
|
|
62
|
-
factory: (services) => createBashOutputTool(getRequiredService(services.processService, 'processService')),
|
|
63
|
-
markers: [ToolMarker.Execution, ToolMarker.Optional],
|
|
64
|
-
requiredServices: ['processService'],
|
|
65
|
-
},
|
|
66
|
-
[ToolName.BATCH]: {
|
|
67
|
-
descriptionFile: 'batch',
|
|
68
|
-
factory: (services) => createBatchTool(getRequiredService(services.getToolProvider, 'getToolProvider')),
|
|
69
|
-
markers: [ToolMarker.Execution, ToolMarker.Core],
|
|
70
|
-
requiredServices: ['getToolProvider'],
|
|
71
|
-
},
|
|
72
38
|
[ToolName.CODE_EXEC]: {
|
|
73
39
|
descriptionFile: 'code_exec',
|
|
74
40
|
factory({ environmentContext, fileSystemService, sandboxService }) {
|
|
@@ -96,13 +62,6 @@ export const TOOL_REGISTRY = {
|
|
|
96
62
|
markers: [ToolMarker.Execution],
|
|
97
63
|
requiredServices: ['sandboxService', 'fileSystemService'],
|
|
98
64
|
},
|
|
99
|
-
[ToolName.CREATE_KNOWLEDGE_TOPIC]: {
|
|
100
|
-
descriptionFile: 'create_knowledge_topic',
|
|
101
|
-
factory: () => createCreateKnowledgeTopicTool(),
|
|
102
|
-
markers: [ToolMarker.ContextBuilding],
|
|
103
|
-
outputGuidance: 'create_knowledge_topic',
|
|
104
|
-
requiredServices: [], // Uses DirectoryManager for file operations
|
|
105
|
-
},
|
|
106
65
|
[ToolName.CURATE]: {
|
|
107
66
|
descriptionFile: 'curate',
|
|
108
67
|
factory: () => createCurateTool(),
|
|
@@ -110,26 +69,6 @@ export const TOOL_REGISTRY = {
|
|
|
110
69
|
outputGuidance: 'curate',
|
|
111
70
|
requiredServices: [], // Uses DirectoryManager and MarkdownWriter for file operations
|
|
112
71
|
},
|
|
113
|
-
[ToolName.DELETE_MEMORY]: {
|
|
114
|
-
descriptionFile: 'delete_memory',
|
|
115
|
-
factory: (services) => createDeleteMemoryTool(getRequiredService(services.memoryManager, 'memoryManager')),
|
|
116
|
-
markers: [ToolMarker.ContextBuilding],
|
|
117
|
-
outputGuidance: 'delete_memory',
|
|
118
|
-
requiredServices: ['memoryManager'],
|
|
119
|
-
},
|
|
120
|
-
[ToolName.EDIT_FILE]: {
|
|
121
|
-
descriptionFile: 'edit_file',
|
|
122
|
-
factory: (services) => createEditFileTool(getRequiredService(services.fileSystemService, 'fileSystemService')),
|
|
123
|
-
markers: [ToolMarker.Modification],
|
|
124
|
-
requiredServices: ['fileSystemService'],
|
|
125
|
-
},
|
|
126
|
-
[ToolName.EDIT_MEMORY]: {
|
|
127
|
-
descriptionFile: 'edit_memory',
|
|
128
|
-
factory: (services) => createEditMemoryTool(getRequiredService(services.memoryManager, 'memoryManager')),
|
|
129
|
-
markers: [ToolMarker.ContextBuilding],
|
|
130
|
-
outputGuidance: 'edit_memory',
|
|
131
|
-
requiredServices: ['memoryManager'],
|
|
132
|
-
},
|
|
133
72
|
[ToolName.GLOB_FILES]: {
|
|
134
73
|
descriptionFile: 'glob_files',
|
|
135
74
|
factory: (services) => createGlobFilesTool(getRequiredService(services.fileSystemService, 'fileSystemService')),
|
|
@@ -142,80 +81,28 @@ export const TOOL_REGISTRY = {
|
|
|
142
81
|
markers: [ToolMarker.Core, ToolMarker.Discovery],
|
|
143
82
|
requiredServices: ['fileSystemService'],
|
|
144
83
|
},
|
|
145
|
-
[ToolName.KILL_PROCESS]: {
|
|
146
|
-
descriptionFile: 'kill_process',
|
|
147
|
-
factory: (services) => createKillProcessTool(getRequiredService(services.processService, 'processService')),
|
|
148
|
-
markers: [ToolMarker.Execution, ToolMarker.Optional],
|
|
149
|
-
requiredServices: ['processService'],
|
|
150
|
-
},
|
|
151
84
|
[ToolName.LIST_DIRECTORY]: {
|
|
152
85
|
descriptionFile: 'list_directory',
|
|
153
86
|
factory: (services) => createListDirectoryTool(getRequiredService(services.fileSystemService, 'fileSystemService')),
|
|
154
87
|
markers: [ToolMarker.Discovery],
|
|
155
88
|
requiredServices: ['fileSystemService'],
|
|
156
89
|
},
|
|
157
|
-
[ToolName.LIST_MEMORIES]: {
|
|
158
|
-
descriptionFile: 'list_memories',
|
|
159
|
-
factory: (services) => createListMemoriesTool(getRequiredService(services.memoryManager, 'memoryManager')),
|
|
160
|
-
markers: [ToolMarker.ContextBuilding, ToolMarker.Discovery],
|
|
161
|
-
outputGuidance: 'list_memories',
|
|
162
|
-
requiredServices: ['memoryManager'],
|
|
163
|
-
},
|
|
164
90
|
[ToolName.READ_FILE]: {
|
|
165
91
|
descriptionFile: 'read_file',
|
|
166
92
|
factory: (services) => createReadFileTool(getRequiredService(services.fileSystemService, 'fileSystemService')),
|
|
167
93
|
markers: [ToolMarker.Core, ToolMarker.Discovery],
|
|
168
94
|
requiredServices: ['fileSystemService'],
|
|
169
95
|
},
|
|
170
|
-
[ToolName.READ_MEMORY]: {
|
|
171
|
-
descriptionFile: 'read_memory',
|
|
172
|
-
factory: (services) => createReadMemoryTool(getRequiredService(services.memoryManager, 'memoryManager')),
|
|
173
|
-
markers: [ToolMarker.ContextBuilding, ToolMarker.Discovery],
|
|
174
|
-
outputGuidance: 'read_memory',
|
|
175
|
-
requiredServices: ['memoryManager'],
|
|
176
|
-
},
|
|
177
|
-
[ToolName.READ_TODOS]: {
|
|
178
|
-
descriptionFile: 'read_todos',
|
|
179
|
-
factory: (services) => createReadTodosTool(getRequiredService(services.todoStorage, 'todoStorage')),
|
|
180
|
-
markers: [ToolMarker.Planning, ToolMarker.Core],
|
|
181
|
-
requiredServices: ['todoStorage'],
|
|
182
|
-
},
|
|
183
|
-
[ToolName.SEARCH_HISTORY]: {
|
|
184
|
-
descriptionFile: 'search_history',
|
|
185
|
-
factory: (_services) => createSearchHistoryTool(),
|
|
186
|
-
markers: [ToolMarker.ContextBuilding, ToolMarker.Discovery],
|
|
187
|
-
requiredServices: [], // No services required yet (stub implementation)
|
|
188
|
-
},
|
|
189
96
|
[ToolName.SEARCH_KNOWLEDGE]: {
|
|
190
97
|
descriptionFile: 'search_knowledge',
|
|
191
98
|
factory: (services) => createSearchKnowledgeTool(getRequiredService(services.fileSystemService, 'fileSystemService')),
|
|
192
99
|
markers: [ToolMarker.ContextBuilding, ToolMarker.Discovery],
|
|
193
100
|
requiredServices: ['fileSystemService'],
|
|
194
101
|
},
|
|
195
|
-
[ToolName.SPEC_ANALYZE]: {
|
|
196
|
-
descriptionFile: 'spec_analyze',
|
|
197
|
-
factory: () => createSpecAnalyzeTool(),
|
|
198
|
-
markers: [ToolMarker.ContextBuilding],
|
|
199
|
-
outputGuidance: 'spec_analyze',
|
|
200
|
-
requiredServices: [], // No services required (validates LLM-detected domains)
|
|
201
|
-
},
|
|
202
102
|
[ToolName.WRITE_FILE]: {
|
|
203
103
|
descriptionFile: 'write_file',
|
|
204
104
|
factory: (services) => createWriteFileTool(getRequiredService(services.fileSystemService, 'fileSystemService')),
|
|
205
105
|
markers: [ToolMarker.Modification],
|
|
206
106
|
requiredServices: ['fileSystemService'],
|
|
207
107
|
},
|
|
208
|
-
[ToolName.WRITE_MEMORY]: {
|
|
209
|
-
descriptionFile: 'write_memory',
|
|
210
|
-
factory: (services) => createWriteMemoryTool(getRequiredService(services.memoryManager, 'memoryManager')),
|
|
211
|
-
markers: [ToolMarker.ContextBuilding],
|
|
212
|
-
outputGuidance: 'write_memory',
|
|
213
|
-
requiredServices: ['memoryManager'],
|
|
214
|
-
},
|
|
215
|
-
[ToolName.WRITE_TODOS]: {
|
|
216
|
-
descriptionFile: 'write_todos',
|
|
217
|
-
factory: (services) => createWriteTodosTool(getRequiredService(services.todoStorage, 'todoStorage')),
|
|
218
|
-
markers: [ToolMarker.Planning, ToolMarker.Core],
|
|
219
|
-
requiredServices: ['todoStorage'],
|
|
220
|
-
},
|
|
221
108
|
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
description: "Detail preservation instructions for curate mode"
|
|
2
|
+
prompt: |
|
|
3
|
+
<CURATE_DETAIL_PRESERVATION>
|
|
4
|
+
## Diagram and Visual Content Preservation
|
|
5
|
+
|
|
6
|
+
When curating content from files or folders, actively look for and preserve:
|
|
7
|
+
|
|
8
|
+
**Diagrams (MUST PRESERVE in narrative.diagrams array):**
|
|
9
|
+
- Mermaid diagrams (```mermaid ... ```) - store with type: "mermaid"
|
|
10
|
+
- PlantUML diagrams (@startuml ... @enduml) - store with type: "plantuml"
|
|
11
|
+
- ASCII art diagrams (box drawings, flow charts using |, -, +, >, arrows) - store with type: "ascii"
|
|
12
|
+
- Sequence diagrams, state diagrams, class diagrams, ER diagrams - identify the format and store accordingly
|
|
13
|
+
- ALWAYS preserve diagram content EXACTLY as-is, character for character
|
|
14
|
+
- NEVER paraphrase or describe a diagram in text instead of storing it
|
|
15
|
+
- NEVER skip a diagram because "it's too complex" - store it verbatim
|
|
16
|
+
|
|
17
|
+
**Tables (MUST PRESERVE):**
|
|
18
|
+
- Markdown tables - preserve the full table in narrative.structure or narrative.features
|
|
19
|
+
- Include column headers and ALL rows - do not summarize table content
|
|
20
|
+
- If a table has 20 rows, store all 20 rows
|
|
21
|
+
|
|
22
|
+
**Step-by-step Procedures:**
|
|
23
|
+
- Numbered instructions - store in narrative.rules with original numbering
|
|
24
|
+
- Decision trees - store as diagrams (ascii type) or in narrative.structure
|
|
25
|
+
- Workflows - capture in rawConcept.flow AND as diagrams if visual representation exists
|
|
26
|
+
|
|
27
|
+
**API Signatures and Interfaces:**
|
|
28
|
+
- Function signatures with parameter types - store in narrative.structure
|
|
29
|
+
- Interface definitions - preserve exact TypeScript/language syntax in snippets
|
|
30
|
+
- Request/response schemas - store complete schema, not summaries
|
|
31
|
+
|
|
32
|
+
**Code Examples:**
|
|
33
|
+
- Inline code examples from documentation - store in narrative.examples with full code
|
|
34
|
+
- Configuration examples - preserve exact syntax and values
|
|
35
|
+
- Command-line examples - store complete commands with flags
|
|
36
|
+
|
|
37
|
+
**Detection Heuristics:**
|
|
38
|
+
- Lines containing box-drawing characters (U+2500-U+257F, or ASCII +--+, | |) = ASCII diagram
|
|
39
|
+
- Fenced blocks with language tag "mermaid", "plantuml", "dot", "graphviz" = diagram
|
|
40
|
+
- Content between @startuml/@enduml = PlantUML diagram
|
|
41
|
+
- Arrow patterns (-->, ==>, ->, =>), combined with indentation = flow/sequence diagram
|
|
42
|
+
|
|
43
|
+
**Storage Rules for Diagrams:**
|
|
44
|
+
- One diagram per entry in the narrative.diagrams array
|
|
45
|
+
- Always set the `type` field correctly (mermaid, plantuml, ascii, other)
|
|
46
|
+
- Use `title` field when the diagram has a caption or label nearby
|
|
47
|
+
- Example:
|
|
48
|
+
```javascript
|
|
49
|
+
narrative: {
|
|
50
|
+
diagrams: [
|
|
51
|
+
{
|
|
52
|
+
type: "mermaid",
|
|
53
|
+
title: "Authentication Flow",
|
|
54
|
+
content: "graph TD\n A[Request] --> B{Has Token?}\n B -->|Yes| C[Validate]\n B -->|No| D[Reject]"
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## General Detail Preservation
|
|
61
|
+
|
|
62
|
+
**Completeness over conciseness:**
|
|
63
|
+
- If a document lists 15 items, store all 15
|
|
64
|
+
- If a config file has 30 settings, capture all relevant ones
|
|
65
|
+
- If there are multiple code examples, store each one
|
|
66
|
+
- Preserve original formatting, indentation, and structure where possible
|
|
67
|
+
|
|
68
|
+
**Do NOT:**
|
|
69
|
+
- Summarize detailed content into brief descriptions
|
|
70
|
+
- Pick "representative examples" instead of storing all items
|
|
71
|
+
- Omit sections because they seem "less important"
|
|
72
|
+
- Flatten hierarchical content into flat descriptions
|
|
73
|
+
</CURATE_DETAIL_PRESERVATION>
|
|
@@ -345,16 +345,33 @@ prompt: |
|
|
|
345
345
|
When using the `curate` tool, use this structured format:
|
|
346
346
|
|
|
347
347
|
**rawConcept** - Essential metadata and technical footprint:
|
|
348
|
+
- IMPORTANT: Before proceeding, analyze the input content for any file path references (e.g., "implemented in auth.ts", "see config.json", "refer to src/utils/helper.h")
|
|
349
|
+
- **Language-Specific File Path Handling**:
|
|
350
|
+
- **TypeScript/TSX ESM**: Import statements use `.js/.jsx` but source files are `.ts/.tsx`
|
|
351
|
+
- Example: `import {foo} from './bar.js'` → actual file is `bar.ts`
|
|
352
|
+
- ALWAYS use actual source extension (.ts, .tsx, .d.ts) NOT import extension (.js, .jsx)
|
|
353
|
+
- When in doubt, verify the .ts/.tsx file exists before assuming .js
|
|
354
|
+
- **Other Languages** (Python, Java, Go, Rust, C/C++, PHP, Ruby, etc.):
|
|
355
|
+
- Use the actual file paths as they appear in the filesystem
|
|
356
|
+
- For languages where imports match file paths (C/C++, PHP, JS), use the import path directly
|
|
357
|
+
- For languages with module systems (Python, Java, Go, Rust), extract the referenced module file
|
|
348
358
|
- `task`: What is being documented (required - always include this)
|
|
349
359
|
- `changes`: Array of changes in the codebase (e.g., ["Added Redis caching", "Created singleton client"])
|
|
350
|
-
- `files`: Array of
|
|
360
|
+
- `files`: Array of actual source file paths (e.g., ["services/auth.ts", "utils/cache.ts", "include/helper.h"])
|
|
361
|
+
- Use the file extension that exists in the filesystem
|
|
362
|
+
- TypeScript ESM: Use .ts/.tsx even when imports show .js/.jsx
|
|
363
|
+
- All other languages: Use the actual file extension (preserve .h, .cpp, .py, .java, .go, .rs, .php, .rb, etc.)
|
|
351
364
|
- `flow`: The execution flow (e.g., "request -> validate -> cache check -> process -> respond")
|
|
352
365
|
- `timestamp`: When created (ISO 8601 format, e.g., "2025-03-18")
|
|
366
|
+
- `author`: Author or source attribution (e.g., "meowso", "Security Team") - optional
|
|
367
|
+
- `patterns`: Array of regex/validation patterns with {pattern, description, flags} - optional
|
|
353
368
|
|
|
354
369
|
**narrative** - Descriptive and structural context:
|
|
355
370
|
- `structure`: Code structure documentation (describe file organization, class hierarchy, etc.)
|
|
356
371
|
- `dependencies`: Dependency management information (external libs, internal dependencies, initialization order)
|
|
357
372
|
- `features`: Feature documentation (behavior, limitations, edge cases, caching TTLs, etc.)
|
|
373
|
+
- `rules`: Exact rules, constraints, or guidelines - preserved verbatim from source - optional
|
|
374
|
+
- `examples`: Concrete examples and use cases - optional
|
|
358
375
|
|
|
359
376
|
**relations** - Optional cross-references to related topics:
|
|
360
377
|
- Array of related topic paths (e.g., ["@structure/redis/overview.md", "@design/security/token-validation.md"])
|
|
@@ -381,12 +398,18 @@ prompt: |
|
|
|
381
398
|
'src/utils/jwt.ts'
|
|
382
399
|
],
|
|
383
400
|
flow: 'request -> extract token -> verify JWT -> check blacklist -> attach user -> proceed',
|
|
384
|
-
timestamp: '2025-01-02'
|
|
401
|
+
timestamp: '2025-01-02',
|
|
402
|
+
author: 'Security Team',
|
|
403
|
+
patterns: [
|
|
404
|
+
{ pattern: '^Bearer\\s+[A-Za-z0-9-._~+/]+=*$', description: 'Validates Bearer token format in Authorization header' }
|
|
405
|
+
]
|
|
385
406
|
},
|
|
386
407
|
narrative: {
|
|
387
408
|
structure: 'Authentication is handled by middleware in src/middleware/auth.ts which delegates to TokenService for JWT operations',
|
|
388
409
|
dependencies: 'Uses jsonwebtoken library for JWT operations, Redis for token blacklist with 24h TTL',
|
|
389
|
-
features: 'Access tokens expire in 15 minutes, refresh tokens in 7 days. Refresh token rotation invalidates old tokens immediately'
|
|
410
|
+
features: 'Access tokens expire in 15 minutes, refresh tokens in 7 days. Refresh token rotation invalidates old tokens immediately',
|
|
411
|
+
rules: 'Rule 1: Access tokens must be verified before use\nRule 2: Expired tokens return 401\nRule 3: Refresh tokens can only be used once',
|
|
412
|
+
examples: 'Example Authorization header: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
|
|
390
413
|
},
|
|
391
414
|
relations: ['@structure/redis/overview.md', '@design/security/token-validation.md']
|
|
392
415
|
},
|
|
@@ -416,6 +439,49 @@ prompt: |
|
|
|
416
439
|
- "The hook system allows registering callbacks for lifecycle events. Register hooks using `HookRegistry.register(hookName, callback)` and trigger them with `HookRegistry.trigger(hookName, context)`. Hooks support async callbacks and are commonly used for: pre/post tool execution, agent lifecycle events, and custom integrations."
|
|
417
440
|
- "Error handling follows a custom error class pattern. All custom errors extend `BaseError` and include: error code, message, context object, and optional cause. Use `ErrorHandler.wrap(fn)` for consistent error boundaries across async operations."
|
|
418
441
|
|
|
442
|
+
### Content Preservation Rules
|
|
443
|
+
|
|
444
|
+
When curating content that contains rules, patterns, or exact specifications, **PRESERVE DETAILS** instead of summarizing:
|
|
445
|
+
|
|
446
|
+
**PRESERVE VERBATIM:**
|
|
447
|
+
- Exact rule text and constraint language - DO NOT paraphrase
|
|
448
|
+
- Regex patterns and validation patterns - include as-is in `patterns` array
|
|
449
|
+
- Author/source attribution - capture in `author` field
|
|
450
|
+
- All enumerated items in lists - DO NOT omit any items
|
|
451
|
+
- Exact configuration values and technical specifications
|
|
452
|
+
- Metadata like version numbers, dates, identifiers
|
|
453
|
+
|
|
454
|
+
**Use appropriate fields:**
|
|
455
|
+
- `rawConcept.patterns` - for regex, validation patterns, matching rules with exact pattern strings
|
|
456
|
+
- `narrative.rules` - for exact rule text, constraints, guidelines (preserve verbatim, do not summarize)
|
|
457
|
+
- `narrative.examples` - for concrete examples and use cases with specific details
|
|
458
|
+
- `rawConcept.author` - for attribution and source info
|
|
459
|
+
- `snippets` - for code blocks and larger text excerpts
|
|
460
|
+
|
|
461
|
+
**When curating rules/guidelines:**
|
|
462
|
+
- Include the EXACT rule text in `narrative.rules`, not a summary
|
|
463
|
+
- Capture ALL rules, not a representative subset
|
|
464
|
+
- Preserve the original numbering/ordering if present
|
|
465
|
+
- Keep qualifiers and specific conditions (e.g., "other than what's explicitly requested")
|
|
466
|
+
|
|
467
|
+
**When curating patterns:**
|
|
468
|
+
- Store in `rawConcept.patterns` array with exact pattern string + description
|
|
469
|
+
- Include regex flags if specified (e.g., "i", "gi")
|
|
470
|
+
- Do not simplify or modify the pattern
|
|
471
|
+
- Include ALL patterns, not just examples
|
|
472
|
+
|
|
473
|
+
**Examples of GOOD preservation:**
|
|
474
|
+
- Original: "Rule 3: Never use apologies" → Store exactly: "Rule 3: Never use apologies" in narrative.rules
|
|
475
|
+
- Original: Has 16 regex patterns → Store all 16 in rawConcept.patterns array
|
|
476
|
+
- Original: "Author: meowso" → Capture: author: "meowso"
|
|
477
|
+
- Original: "Make changes file by file and give me a chance to spot mistakes" → Store complete text, not "Enforced file-by-file changes"
|
|
478
|
+
|
|
479
|
+
**Examples of BAD summarization (AVOID):**
|
|
480
|
+
- Original: "Rule 3: Never use apologies" → "Prohibited apologies" ❌
|
|
481
|
+
- Original: 16 patterns → Store only 3-5 examples ❌
|
|
482
|
+
- Original: Detailed rule with qualifier → Shortened version without qualifier ❌
|
|
483
|
+
- Original: 8 use cases → Store only 2 ❌
|
|
484
|
+
|
|
419
485
|
### Domain/Topic/Subtopic Context
|
|
420
486
|
|
|
421
487
|
When creating NEW domains, topics, or subtopics, provide the appropriate context:
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
export interface RawConcept {
|
|
2
|
+
author?: string;
|
|
2
3
|
changes?: string[];
|
|
3
4
|
files?: string[];
|
|
4
5
|
flow?: string;
|
|
6
|
+
patterns?: Array<{
|
|
7
|
+
description: string;
|
|
8
|
+
flags?: string;
|
|
9
|
+
pattern: string;
|
|
10
|
+
}>;
|
|
5
11
|
task?: string;
|
|
6
12
|
timestamp?: string;
|
|
7
13
|
}
|
|
8
14
|
export interface Narrative {
|
|
9
15
|
dependencies?: string;
|
|
16
|
+
diagrams?: Array<{
|
|
17
|
+
content: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
type: string;
|
|
20
|
+
}>;
|
|
21
|
+
examples?: string;
|
|
10
22
|
features?: string;
|
|
23
|
+
rules?: string;
|
|
11
24
|
structure?: string;
|
|
12
25
|
}
|
|
13
26
|
export interface ContextData {
|