aidex-mcp 1.4.1
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/CHANGELOG.md +128 -0
- package/LICENSE +21 -0
- package/MCP-API-REFERENCE.md +690 -0
- package/README.md +314 -0
- package/build/commands/files.d.ts +28 -0
- package/build/commands/files.js +124 -0
- package/build/commands/index.d.ts +14 -0
- package/build/commands/index.js +14 -0
- package/build/commands/init.d.ts +24 -0
- package/build/commands/init.js +396 -0
- package/build/commands/link.d.ts +45 -0
- package/build/commands/link.js +167 -0
- package/build/commands/note.d.ts +29 -0
- package/build/commands/note.js +105 -0
- package/build/commands/query.d.ts +36 -0
- package/build/commands/query.js +176 -0
- package/build/commands/scan.d.ts +25 -0
- package/build/commands/scan.js +104 -0
- package/build/commands/session.d.ts +52 -0
- package/build/commands/session.js +216 -0
- package/build/commands/signature.d.ts +52 -0
- package/build/commands/signature.js +171 -0
- package/build/commands/summary.d.ts +56 -0
- package/build/commands/summary.js +324 -0
- package/build/commands/update.d.ts +36 -0
- package/build/commands/update.js +273 -0
- package/build/constants.d.ts +10 -0
- package/build/constants.js +10 -0
- package/build/db/database.d.ts +69 -0
- package/build/db/database.js +126 -0
- package/build/db/index.d.ts +7 -0
- package/build/db/index.js +6 -0
- package/build/db/queries.d.ts +163 -0
- package/build/db/queries.js +273 -0
- package/build/db/schema.sql +136 -0
- package/build/index.d.ts +13 -0
- package/build/index.js +74 -0
- package/build/parser/extractor.d.ts +41 -0
- package/build/parser/extractor.js +249 -0
- package/build/parser/index.d.ts +7 -0
- package/build/parser/index.js +7 -0
- package/build/parser/languages/c.d.ts +28 -0
- package/build/parser/languages/c.js +70 -0
- package/build/parser/languages/cpp.d.ts +28 -0
- package/build/parser/languages/cpp.js +91 -0
- package/build/parser/languages/csharp.d.ts +32 -0
- package/build/parser/languages/csharp.js +97 -0
- package/build/parser/languages/go.d.ts +28 -0
- package/build/parser/languages/go.js +83 -0
- package/build/parser/languages/index.d.ts +21 -0
- package/build/parser/languages/index.js +107 -0
- package/build/parser/languages/java.d.ts +28 -0
- package/build/parser/languages/java.js +58 -0
- package/build/parser/languages/php.d.ts +28 -0
- package/build/parser/languages/php.js +75 -0
- package/build/parser/languages/python.d.ts +28 -0
- package/build/parser/languages/python.js +67 -0
- package/build/parser/languages/ruby.d.ts +28 -0
- package/build/parser/languages/ruby.js +68 -0
- package/build/parser/languages/rust.d.ts +28 -0
- package/build/parser/languages/rust.js +73 -0
- package/build/parser/languages/typescript.d.ts +28 -0
- package/build/parser/languages/typescript.js +82 -0
- package/build/parser/tree-sitter.d.ts +30 -0
- package/build/parser/tree-sitter.js +132 -0
- package/build/server/mcp-server.d.ts +7 -0
- package/build/server/mcp-server.js +36 -0
- package/build/server/tools.d.ts +18 -0
- package/build/server/tools.js +1245 -0
- package/build/viewer/git-status.d.ts +25 -0
- package/build/viewer/git-status.js +163 -0
- package/build/viewer/index.d.ts +5 -0
- package/build/viewer/index.js +5 -0
- package/build/viewer/server.d.ts +12 -0
- package/build/viewer/server.js +1122 -0
- package/package.json +66 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* session command - Session tracking and external change detection
|
|
3
|
+
*
|
|
4
|
+
* Tracks session start/end times and detects files changed outside of sessions.
|
|
5
|
+
* This enables:
|
|
6
|
+
* - "What did we do last session?" queries using time filtering
|
|
7
|
+
* - Automatic detection of externally modified files that need re-indexing
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, readFileSync } from 'fs';
|
|
10
|
+
import { join, resolve } from 'path';
|
|
11
|
+
import { createHash } from 'crypto';
|
|
12
|
+
import { PRODUCT_NAME, INDEX_DIR, TOOL_PREFIX } from '../constants.js';
|
|
13
|
+
import { openDatabase, createQueries } from '../db/index.js';
|
|
14
|
+
import { update } from './update.js';
|
|
15
|
+
// ============================================================
|
|
16
|
+
// Constants
|
|
17
|
+
// ============================================================
|
|
18
|
+
const KEY_LAST_SESSION_START = 'last_session_start';
|
|
19
|
+
const KEY_LAST_SESSION_END = 'last_session_end';
|
|
20
|
+
const KEY_CURRENT_SESSION_START = 'current_session_start';
|
|
21
|
+
const KEY_SESSION_NOTE = 'session_note';
|
|
22
|
+
// Session is considered "new" if more than 5 minutes have passed since last activity
|
|
23
|
+
const SESSION_TIMEOUT_MS = 5 * 60 * 1000;
|
|
24
|
+
// ============================================================
|
|
25
|
+
// Implementation
|
|
26
|
+
// ============================================================
|
|
27
|
+
/**
|
|
28
|
+
* Start or continue a session.
|
|
29
|
+
* - If new session: detect external changes, store previous session times
|
|
30
|
+
* - Always: update session_end timestamp
|
|
31
|
+
*/
|
|
32
|
+
export function session(params) {
|
|
33
|
+
const { path: projectPath } = params;
|
|
34
|
+
// Validate project path
|
|
35
|
+
const dbPath = join(projectPath, INDEX_DIR, 'index.db');
|
|
36
|
+
if (!existsSync(dbPath)) {
|
|
37
|
+
return {
|
|
38
|
+
success: false,
|
|
39
|
+
isNewSession: false,
|
|
40
|
+
sessionInfo: { lastSessionStart: null, lastSessionEnd: null, currentSessionStart: null },
|
|
41
|
+
externalChanges: [],
|
|
42
|
+
reindexed: [],
|
|
43
|
+
note: null,
|
|
44
|
+
error: `No ${PRODUCT_NAME} index found at ${projectPath}. Run ${TOOL_PREFIX}init first.`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const db = openDatabase(dbPath, false);
|
|
48
|
+
const queries = createQueries(db);
|
|
49
|
+
const now = Date.now();
|
|
50
|
+
try {
|
|
51
|
+
// Get current session info
|
|
52
|
+
const currentStart = db.getMetadata(KEY_CURRENT_SESSION_START);
|
|
53
|
+
const lastEnd = db.getMetadata(KEY_LAST_SESSION_END);
|
|
54
|
+
// Determine if this is a new session
|
|
55
|
+
const lastActivity = lastEnd ? parseInt(lastEnd, 10) : (currentStart ? parseInt(currentStart, 10) : 0);
|
|
56
|
+
const isNewSession = !currentStart || (now - lastActivity > SESSION_TIMEOUT_MS);
|
|
57
|
+
let sessionInfo;
|
|
58
|
+
let externalChanges = [];
|
|
59
|
+
let reindexed = [];
|
|
60
|
+
if (isNewSession) {
|
|
61
|
+
// Archive previous session times
|
|
62
|
+
if (currentStart) {
|
|
63
|
+
db.setMetadata(KEY_LAST_SESSION_START, currentStart);
|
|
64
|
+
}
|
|
65
|
+
if (lastEnd) {
|
|
66
|
+
// Use the last recorded end time as last_session_end
|
|
67
|
+
}
|
|
68
|
+
else if (currentStart) {
|
|
69
|
+
db.setMetadata(KEY_LAST_SESSION_END, currentStart);
|
|
70
|
+
}
|
|
71
|
+
// Start new session
|
|
72
|
+
db.setMetadata(KEY_CURRENT_SESSION_START, now.toString());
|
|
73
|
+
// Detect external changes
|
|
74
|
+
externalChanges = detectExternalChanges(projectPath, queries);
|
|
75
|
+
// Auto-reindex modified files
|
|
76
|
+
for (const change of externalChanges) {
|
|
77
|
+
if (change.reason === 'modified') {
|
|
78
|
+
const result = update({ path: projectPath, file: change.path });
|
|
79
|
+
if (result.success) {
|
|
80
|
+
reindexed.push(change.path);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
sessionInfo = {
|
|
85
|
+
lastSessionStart: currentStart ? parseInt(currentStart, 10) : null,
|
|
86
|
+
lastSessionEnd: lastEnd ? parseInt(lastEnd, 10) : null,
|
|
87
|
+
currentSessionStart: now,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Continue existing session
|
|
92
|
+
sessionInfo = {
|
|
93
|
+
lastSessionStart: db.getMetadata(KEY_LAST_SESSION_START) ? parseInt(db.getMetadata(KEY_LAST_SESSION_START), 10) : null,
|
|
94
|
+
lastSessionEnd: db.getMetadata(KEY_LAST_SESSION_END) ? parseInt(db.getMetadata(KEY_LAST_SESSION_END), 10) : null,
|
|
95
|
+
currentSessionStart: parseInt(currentStart, 10),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Always update session end time (heartbeat)
|
|
99
|
+
db.setMetadata(KEY_LAST_SESSION_END, now.toString());
|
|
100
|
+
// Get session note
|
|
101
|
+
const note = db.getMetadata(KEY_SESSION_NOTE);
|
|
102
|
+
db.close();
|
|
103
|
+
return {
|
|
104
|
+
success: true,
|
|
105
|
+
isNewSession,
|
|
106
|
+
sessionInfo,
|
|
107
|
+
externalChanges,
|
|
108
|
+
reindexed,
|
|
109
|
+
note,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
db.close();
|
|
114
|
+
return {
|
|
115
|
+
success: false,
|
|
116
|
+
isNewSession: false,
|
|
117
|
+
sessionInfo: { lastSessionStart: null, lastSessionEnd: null, currentSessionStart: null },
|
|
118
|
+
externalChanges: [],
|
|
119
|
+
reindexed: [],
|
|
120
|
+
note: null,
|
|
121
|
+
error: error instanceof Error ? error.message : String(error),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Update session heartbeat (call periodically during session)
|
|
127
|
+
*/
|
|
128
|
+
export function updateSessionHeartbeat(projectPath) {
|
|
129
|
+
const dbPath = join(projectPath, INDEX_DIR, 'index.db');
|
|
130
|
+
if (!existsSync(dbPath)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const db = openDatabase(dbPath, false);
|
|
135
|
+
db.setMetadata(KEY_LAST_SESSION_END, Date.now().toString());
|
|
136
|
+
db.close();
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Silently ignore errors
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get session info without starting/updating
|
|
144
|
+
*/
|
|
145
|
+
export function getSessionInfo(projectPath) {
|
|
146
|
+
const dbPath = join(projectPath, INDEX_DIR, 'index.db');
|
|
147
|
+
if (!existsSync(dbPath)) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const db = openDatabase(dbPath, true);
|
|
152
|
+
const info = {
|
|
153
|
+
lastSessionStart: db.getMetadata(KEY_LAST_SESSION_START) ? parseInt(db.getMetadata(KEY_LAST_SESSION_START), 10) : null,
|
|
154
|
+
lastSessionEnd: db.getMetadata(KEY_LAST_SESSION_END) ? parseInt(db.getMetadata(KEY_LAST_SESSION_END), 10) : null,
|
|
155
|
+
currentSessionStart: db.getMetadata(KEY_CURRENT_SESSION_START) ? parseInt(db.getMetadata(KEY_CURRENT_SESSION_START), 10) : null,
|
|
156
|
+
};
|
|
157
|
+
db.close();
|
|
158
|
+
return info;
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// ============================================================
|
|
165
|
+
// Helper functions
|
|
166
|
+
// ============================================================
|
|
167
|
+
/**
|
|
168
|
+
* Detect files that were changed outside of the session
|
|
169
|
+
*/
|
|
170
|
+
function detectExternalChanges(projectPath, queries) {
|
|
171
|
+
const changes = [];
|
|
172
|
+
const projectRoot = resolve(projectPath);
|
|
173
|
+
// Get all indexed files
|
|
174
|
+
const indexedFiles = queries.getAllFiles();
|
|
175
|
+
for (const file of indexedFiles) {
|
|
176
|
+
const fullPath = join(projectRoot, file.path);
|
|
177
|
+
if (!existsSync(fullPath)) {
|
|
178
|
+
// File was deleted
|
|
179
|
+
changes.push({ path: file.path, reason: 'deleted' });
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
// Check if file hash changed
|
|
183
|
+
try {
|
|
184
|
+
const content = readFileSync(fullPath);
|
|
185
|
+
const currentHash = createHash('sha256').update(content).digest('hex');
|
|
186
|
+
if (currentHash !== file.hash) {
|
|
187
|
+
changes.push({ path: file.path, reason: 'modified' });
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
// Can't read file - skip
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return changes;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Format session time for display
|
|
198
|
+
*/
|
|
199
|
+
export function formatSessionTime(timestamp) {
|
|
200
|
+
if (!timestamp)
|
|
201
|
+
return 'N/A';
|
|
202
|
+
return new Date(timestamp).toISOString();
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Format duration between two timestamps
|
|
206
|
+
*/
|
|
207
|
+
export function formatDuration(startMs, endMs) {
|
|
208
|
+
const durationMs = endMs - startMs;
|
|
209
|
+
const minutes = Math.floor(durationMs / 60000);
|
|
210
|
+
const hours = Math.floor(minutes / 60);
|
|
211
|
+
if (hours > 0) {
|
|
212
|
+
return `${hours}h ${minutes % 60}m`;
|
|
213
|
+
}
|
|
214
|
+
return `${minutes}m`;
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signature commands for AiDex
|
|
3
|
+
* Retrieves file signatures (header comments, types, methods)
|
|
4
|
+
*/
|
|
5
|
+
export interface SignatureParams {
|
|
6
|
+
/** Project path (containing index dir) */
|
|
7
|
+
path: string;
|
|
8
|
+
/** Relative file path within the project */
|
|
9
|
+
file: string;
|
|
10
|
+
}
|
|
11
|
+
export interface SignatureResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
file: string;
|
|
14
|
+
headerComments: string | null;
|
|
15
|
+
types: Array<{
|
|
16
|
+
name: string;
|
|
17
|
+
kind: string;
|
|
18
|
+
lineNumber: number;
|
|
19
|
+
}>;
|
|
20
|
+
methods: Array<{
|
|
21
|
+
name: string;
|
|
22
|
+
prototype: string;
|
|
23
|
+
lineNumber: number;
|
|
24
|
+
visibility: string | null;
|
|
25
|
+
isStatic: boolean;
|
|
26
|
+
isAsync: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
error?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface SignaturesParams {
|
|
31
|
+
/** Project path (containing index dir) */
|
|
32
|
+
path: string;
|
|
33
|
+
/** Glob pattern to match files (e.g., "src/Core/**.cs") */
|
|
34
|
+
pattern?: string;
|
|
35
|
+
/** Explicit list of relative file paths */
|
|
36
|
+
files?: string[];
|
|
37
|
+
}
|
|
38
|
+
export interface SignaturesResult {
|
|
39
|
+
success: boolean;
|
|
40
|
+
signatures: SignatureResult[];
|
|
41
|
+
totalFiles: number;
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get signature for a single file
|
|
46
|
+
*/
|
|
47
|
+
export declare function signature(params: SignatureParams): SignatureResult;
|
|
48
|
+
/**
|
|
49
|
+
* Get signatures for multiple files
|
|
50
|
+
*/
|
|
51
|
+
export declare function signatures(params: SignaturesParams): SignaturesResult;
|
|
52
|
+
//# sourceMappingURL=signature.d.ts.map
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signature commands for AiDex
|
|
3
|
+
* Retrieves file signatures (header comments, types, methods)
|
|
4
|
+
*/
|
|
5
|
+
import { join } from 'path';
|
|
6
|
+
import { existsSync } from 'fs';
|
|
7
|
+
import { PRODUCT_NAME, INDEX_DIR, TOOL_PREFIX } from '../constants.js';
|
|
8
|
+
import { openDatabase } from '../db/index.js';
|
|
9
|
+
import { createQueries } from '../db/queries.js';
|
|
10
|
+
// ============================================================
|
|
11
|
+
// Implementation
|
|
12
|
+
// ============================================================
|
|
13
|
+
/**
|
|
14
|
+
* Get signature for a single file
|
|
15
|
+
*/
|
|
16
|
+
export function signature(params) {
|
|
17
|
+
const { path: projectPath } = params;
|
|
18
|
+
// Normalize path to forward slashes
|
|
19
|
+
const file = params.file.replace(/\\/g, '/');
|
|
20
|
+
// Validate project path
|
|
21
|
+
const indexDir = join(projectPath, INDEX_DIR);
|
|
22
|
+
const dbPath = join(indexDir, 'index.db');
|
|
23
|
+
if (!existsSync(dbPath)) {
|
|
24
|
+
return {
|
|
25
|
+
success: false,
|
|
26
|
+
file,
|
|
27
|
+
headerComments: null,
|
|
28
|
+
types: [],
|
|
29
|
+
methods: [],
|
|
30
|
+
error: `No ${PRODUCT_NAME} index found at ${projectPath}. Run ${TOOL_PREFIX}init first.`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Open database
|
|
34
|
+
const db = openDatabase(dbPath, true); // readonly
|
|
35
|
+
const queries = createQueries(db);
|
|
36
|
+
try {
|
|
37
|
+
// Find file in database
|
|
38
|
+
const fileRow = queries.getFileByPath(file);
|
|
39
|
+
if (!fileRow) {
|
|
40
|
+
db.close();
|
|
41
|
+
return {
|
|
42
|
+
success: false,
|
|
43
|
+
file,
|
|
44
|
+
headerComments: null,
|
|
45
|
+
types: [],
|
|
46
|
+
methods: [],
|
|
47
|
+
error: `File "${file}" not found in index. It may not be indexed or the path is incorrect.`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
// Get signature data
|
|
51
|
+
const signatureRow = queries.getSignatureByFile(fileRow.id);
|
|
52
|
+
const methodRows = queries.getMethodsByFile(fileRow.id);
|
|
53
|
+
const typeRows = queries.getTypesByFile(fileRow.id);
|
|
54
|
+
db.close();
|
|
55
|
+
return {
|
|
56
|
+
success: true,
|
|
57
|
+
file: fileRow.path,
|
|
58
|
+
headerComments: signatureRow?.header_comments ?? null,
|
|
59
|
+
types: typeRows.map(t => ({
|
|
60
|
+
name: t.name,
|
|
61
|
+
kind: t.kind,
|
|
62
|
+
lineNumber: t.line_number,
|
|
63
|
+
})),
|
|
64
|
+
methods: methodRows.map(m => ({
|
|
65
|
+
name: m.name,
|
|
66
|
+
prototype: m.prototype,
|
|
67
|
+
lineNumber: m.line_number,
|
|
68
|
+
visibility: m.visibility,
|
|
69
|
+
isStatic: m.is_static === 1,
|
|
70
|
+
isAsync: m.is_async === 1,
|
|
71
|
+
})),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
db.close();
|
|
76
|
+
return {
|
|
77
|
+
success: false,
|
|
78
|
+
file,
|
|
79
|
+
headerComments: null,
|
|
80
|
+
types: [],
|
|
81
|
+
methods: [],
|
|
82
|
+
error: `Error retrieving signature: ${error instanceof Error ? error.message : String(error)}`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Get signatures for multiple files
|
|
88
|
+
*/
|
|
89
|
+
export function signatures(params) {
|
|
90
|
+
const { path: projectPath, pattern, files } = params;
|
|
91
|
+
// Validate project path
|
|
92
|
+
const indexDir = join(projectPath, INDEX_DIR);
|
|
93
|
+
const dbPath = join(indexDir, 'index.db');
|
|
94
|
+
if (!existsSync(dbPath)) {
|
|
95
|
+
return {
|
|
96
|
+
success: false,
|
|
97
|
+
signatures: [],
|
|
98
|
+
totalFiles: 0,
|
|
99
|
+
error: `No ${PRODUCT_NAME} index found at ${projectPath}. Run ${TOOL_PREFIX}init first.`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// Determine which files to query
|
|
103
|
+
let filesToQuery = [];
|
|
104
|
+
if (files && files.length > 0) {
|
|
105
|
+
// Use explicit file list (paths as-is, signature() handles normalization)
|
|
106
|
+
filesToQuery = files;
|
|
107
|
+
}
|
|
108
|
+
else if (pattern) {
|
|
109
|
+
// Use glob pattern against indexed files
|
|
110
|
+
const db = openDatabase(dbPath, true);
|
|
111
|
+
const queries = createQueries(db);
|
|
112
|
+
const allFiles = queries.getAllFiles();
|
|
113
|
+
db.close();
|
|
114
|
+
// Convert glob pattern to regex (normalize pattern to forward slashes)
|
|
115
|
+
const normalizedPattern = pattern.replace(/\\/g, '/');
|
|
116
|
+
const regex = globToRegex(normalizedPattern);
|
|
117
|
+
// Test against both original path and forward-slash normalized version
|
|
118
|
+
filesToQuery = allFiles
|
|
119
|
+
.map(f => f.path)
|
|
120
|
+
.filter(p => {
|
|
121
|
+
const normalizedPath = p.replace(/\\/g, '/');
|
|
122
|
+
return regex.test(normalizedPath);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
return {
|
|
127
|
+
success: false,
|
|
128
|
+
signatures: [],
|
|
129
|
+
totalFiles: 0,
|
|
130
|
+
error: 'Either pattern or files parameter is required.',
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
// Get signatures for all matched files
|
|
134
|
+
const results = [];
|
|
135
|
+
for (const file of filesToQuery) {
|
|
136
|
+
const result = signature({ path: projectPath, file });
|
|
137
|
+
results.push(result);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
success: true,
|
|
141
|
+
signatures: results,
|
|
142
|
+
totalFiles: results.length,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Convert a glob pattern to a regular expression
|
|
147
|
+
* Supports: *, **, ?
|
|
148
|
+
*/
|
|
149
|
+
function globToRegex(pattern) {
|
|
150
|
+
// Normalize to forward slashes
|
|
151
|
+
pattern = pattern.replace(/\\/g, '/');
|
|
152
|
+
// Escape regex special chars except * and ?
|
|
153
|
+
let regex = pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&');
|
|
154
|
+
// Convert glob patterns to regex:
|
|
155
|
+
// ** matches any path (including /)
|
|
156
|
+
// * matches any characters except /
|
|
157
|
+
// ? matches any single character except /
|
|
158
|
+
// Handle ** first (must match across directories)
|
|
159
|
+
// **/ at start or middle means "any path prefix"
|
|
160
|
+
regex = regex.replace(/\*\*\//g, '(.*/)?');
|
|
161
|
+
// /** at end means "any path suffix"
|
|
162
|
+
regex = regex.replace(/\/\*\*/g, '(/.*)?');
|
|
163
|
+
// Standalone ** (rare)
|
|
164
|
+
regex = regex.replace(/\*\*/g, '.*');
|
|
165
|
+
// Handle single * (matches within directory)
|
|
166
|
+
regex = regex.replace(/\*/g, '[^/]*');
|
|
167
|
+
// Handle ? (single character)
|
|
168
|
+
regex = regex.replace(/\?/g, '[^/]');
|
|
169
|
+
return new RegExp(`^${regex}$`, 'i');
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=signature.js.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* summary and tree commands
|
|
3
|
+
*
|
|
4
|
+
* - summary: Get project summary with auto-detected info
|
|
5
|
+
* - tree: Get indexed file tree with optional stats
|
|
6
|
+
*/
|
|
7
|
+
export interface SummaryParams {
|
|
8
|
+
path: string;
|
|
9
|
+
}
|
|
10
|
+
export interface SummaryResult {
|
|
11
|
+
success: boolean;
|
|
12
|
+
name: string;
|
|
13
|
+
content: string;
|
|
14
|
+
autoGenerated: {
|
|
15
|
+
entryPoints: string[];
|
|
16
|
+
mainTypes: string[];
|
|
17
|
+
fileCount: number;
|
|
18
|
+
languages: string[];
|
|
19
|
+
};
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface TreeParams {
|
|
23
|
+
path: string;
|
|
24
|
+
subpath?: string;
|
|
25
|
+
depth?: number;
|
|
26
|
+
includeStats?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface TreeEntry {
|
|
29
|
+
path: string;
|
|
30
|
+
type: 'file' | 'directory';
|
|
31
|
+
itemCount?: number;
|
|
32
|
+
methodCount?: number;
|
|
33
|
+
typeCount?: number;
|
|
34
|
+
}
|
|
35
|
+
export interface TreeResult {
|
|
36
|
+
success: boolean;
|
|
37
|
+
root: string;
|
|
38
|
+
entries: TreeEntry[];
|
|
39
|
+
totalFiles: number;
|
|
40
|
+
error?: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function summary(params: SummaryParams): SummaryResult;
|
|
43
|
+
export declare function tree(params: TreeParams): TreeResult;
|
|
44
|
+
export interface DescribeParams {
|
|
45
|
+
path: string;
|
|
46
|
+
section: 'purpose' | 'architecture' | 'concepts' | 'patterns' | 'notes';
|
|
47
|
+
content: string;
|
|
48
|
+
replace?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface DescribeResult {
|
|
51
|
+
success: boolean;
|
|
52
|
+
section: string;
|
|
53
|
+
error?: string;
|
|
54
|
+
}
|
|
55
|
+
export declare function describe(params: DescribeParams): DescribeResult;
|
|
56
|
+
//# sourceMappingURL=summary.d.ts.map
|