mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-11 02:33:51 +08:00
feat: Add CLAUDE.md freshness tracking and update reminders
- Add SQLite table and CRUD methods for tracking update history - Create freshness calculation service based on git file changes - Add API endpoints for freshness data, marking updates, and history - Display freshness badges in file tree (green/yellow/red indicators) - Show freshness gauge and details in metadata panel - Auto-mark files as updated after CLI sync - Add English and Chinese i18n translations Freshness algorithm: 100 - min((changedFilesCount / 20) * 100, 100) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -51,6 +51,7 @@ const ParamsSchema = z.object({
|
||||
format: z.enum(['json', 'text', 'pretty']).default('json'),
|
||||
languages: z.array(z.string()).optional(),
|
||||
limit: z.number().default(20),
|
||||
enrich: z.boolean().default(false),
|
||||
// Additional fields for internal functions
|
||||
file: z.string().optional(),
|
||||
key: z.string().optional(),
|
||||
@@ -516,7 +517,7 @@ async function initIndex(params: Params): Promise<ExecuteResult> {
|
||||
* @returns Execution result
|
||||
*/
|
||||
async function searchCode(params: Params): Promise<ExecuteResult> {
|
||||
const { query, path = '.', limit = 20, mode = 'auto' } = params;
|
||||
const { query, path = '.', limit = 20, mode = 'auto', enrich = false } = params;
|
||||
|
||||
if (!query) {
|
||||
return { success: false, error: 'Query is required for search action' };
|
||||
@@ -537,6 +538,10 @@ async function searchCode(params: Params): Promise<ExecuteResult> {
|
||||
const cliMode = modeMap[mode] || 'auto';
|
||||
const args = ['search', query, '--limit', limit.toString(), '--mode', cliMode, '--json'];
|
||||
|
||||
if (enrich) {
|
||||
args.push('--enrich');
|
||||
}
|
||||
|
||||
const result = await executeCodexLens(args, { cwd: path });
|
||||
|
||||
if (result.success && result.output) {
|
||||
@@ -557,7 +562,7 @@ async function searchCode(params: Params): Promise<ExecuteResult> {
|
||||
* @returns Execution result
|
||||
*/
|
||||
async function searchFiles(params: Params): Promise<ExecuteResult> {
|
||||
const { query, path = '.', limit = 20, mode = 'auto' } = params;
|
||||
const { query, path = '.', limit = 20, mode = 'auto', enrich = false } = params;
|
||||
|
||||
if (!query) {
|
||||
return { success: false, error: 'Query is required for search_files action' };
|
||||
@@ -578,6 +583,10 @@ async function searchFiles(params: Params): Promise<ExecuteResult> {
|
||||
const cliMode = modeMap[mode] || 'auto';
|
||||
const args = ['search', query, '--files-only', '--limit', limit.toString(), '--mode', cliMode, '--json'];
|
||||
|
||||
if (enrich) {
|
||||
args.push('--enrich');
|
||||
}
|
||||
|
||||
const result = await executeCodexLens(args, { cwd: path });
|
||||
|
||||
if (result.success && result.output) {
|
||||
@@ -764,6 +773,9 @@ Usage:
|
||||
codex_lens(action="search", query="func", mode="hybrid") # Force hybrid search
|
||||
codex_lens(action="search_files", query="x") # Search, return paths only
|
||||
|
||||
Graph Enrichment:
|
||||
codex_lens(action="search", query="func", enrich=true) # Enrich results with code relationships
|
||||
|
||||
Search Modes:
|
||||
- auto: Auto-detect (hybrid if embeddings exist, exact otherwise) [default]
|
||||
- exact/text: Exact FTS for code identifiers
|
||||
@@ -820,6 +832,11 @@ Note: For advanced operations (config, status, clean), use CLI directly: codexle
|
||||
description: 'Maximum number of search results (for search and search_files actions)',
|
||||
default: 20,
|
||||
},
|
||||
enrich: {
|
||||
type: 'boolean',
|
||||
description: 'Enrich search results with code graph relationships (calls, imports)',
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
required: ['action'],
|
||||
},
|
||||
|
||||
@@ -36,6 +36,7 @@ const ParamsSchema = z.object({
|
||||
includeHidden: z.boolean().default(false),
|
||||
languages: z.array(z.string()).optional(),
|
||||
limit: z.number().default(10),
|
||||
enrich: z.boolean().default(false),
|
||||
});
|
||||
|
||||
type Params = z.infer<typeof ParamsSchema>;
|
||||
@@ -59,11 +60,21 @@ interface ExactMatch {
|
||||
content: string;
|
||||
}
|
||||
|
||||
interface RelationshipInfo {
|
||||
type: string; // 'calls', 'imports', 'called_by', 'imported_by'
|
||||
direction: 'outgoing' | 'incoming';
|
||||
target?: string; // Target symbol name (for outgoing)
|
||||
source?: string; // Source symbol name (for incoming)
|
||||
file: string; // File path
|
||||
line?: number; // Line number
|
||||
}
|
||||
|
||||
interface SemanticMatch {
|
||||
file: string;
|
||||
score: number;
|
||||
content: string;
|
||||
symbol: string | null;
|
||||
relationships?: RelationshipInfo[];
|
||||
}
|
||||
|
||||
interface GraphMatch {
|
||||
@@ -635,7 +646,7 @@ async function executeRipgrepMode(params: Params): Promise<SearchResult> {
|
||||
* Requires index
|
||||
*/
|
||||
async function executeCodexLensExactMode(params: Params): Promise<SearchResult> {
|
||||
const { query, path = '.', maxResults = 10 } = params;
|
||||
const { query, path = '.', maxResults = 10, enrich = false } = params;
|
||||
|
||||
if (!query) {
|
||||
return {
|
||||
@@ -657,6 +668,9 @@ async function executeCodexLensExactMode(params: Params): Promise<SearchResult>
|
||||
const indexStatus = await checkIndexStatus(path);
|
||||
|
||||
const args = ['search', query, '--limit', maxResults.toString(), '--mode', 'exact', '--json'];
|
||||
if (enrich) {
|
||||
args.push('--enrich');
|
||||
}
|
||||
const result = await executeCodexLens(args, { cwd: path });
|
||||
|
||||
if (!result.success) {
|
||||
@@ -707,7 +721,7 @@ async function executeCodexLensExactMode(params: Params): Promise<SearchResult>
|
||||
* Requires index with embeddings
|
||||
*/
|
||||
async function executeHybridMode(params: Params): Promise<SearchResult> {
|
||||
const { query, path = '.', maxResults = 10 } = params;
|
||||
const { query, path = '.', maxResults = 10, enrich = false } = params;
|
||||
|
||||
if (!query) {
|
||||
return {
|
||||
@@ -729,6 +743,9 @@ async function executeHybridMode(params: Params): Promise<SearchResult> {
|
||||
const indexStatus = await checkIndexStatus(path);
|
||||
|
||||
const args = ['search', query, '--limit', maxResults.toString(), '--mode', 'hybrid', '--json'];
|
||||
if (enrich) {
|
||||
args.push('--enrich');
|
||||
}
|
||||
const result = await executeCodexLens(args, { cwd: path });
|
||||
|
||||
if (!result.success) {
|
||||
@@ -958,6 +975,9 @@ export const schema: ToolSchema = {
|
||||
smart_search(action="init") # Create FTS index for current directory
|
||||
smart_search(action="status") # Check index and embedding status
|
||||
|
||||
**Graph Enrichment:**
|
||||
smart_search(query="func", enrich=true) # Enrich results with code relationships (calls, imports, called_by, imported_by)
|
||||
|
||||
**Modes:** auto (intelligent routing), hybrid (semantic, needs index), exact (FTS), ripgrep (fast, no index), priority (fallback: hybrid→exact→ripgrep)`,
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
@@ -1021,6 +1041,11 @@ export const schema: ToolSchema = {
|
||||
items: { type: 'string' },
|
||||
description: 'Languages to index (for init action). Example: ["javascript", "typescript"]',
|
||||
},
|
||||
enrich: {
|
||||
type: 'boolean',
|
||||
description: 'Enrich search results with code graph relationships (calls, imports, called_by, imported_by).',
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user