@ngao/search 0.1.0 → 0.1.2

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.
Files changed (259) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/.env.example +7 -0
  3. package/.eslintrc.json +20 -0
  4. package/.github/workflows/build.yml +39 -0
  5. package/.github/workflows/release.yml +34 -0
  6. package/.github/workflows/test.yml +35 -0
  7. package/.mcp-config.json +14 -0
  8. package/.prettierrc.json +10 -0
  9. package/LICENSE +17 -0
  10. package/Makefile +26 -0
  11. package/README.md +57 -172
  12. package/config.example.json +8 -0
  13. package/dist/backend/api/search-engine.d.ts +40 -0
  14. package/dist/backend/api/search-engine.d.ts.map +1 -0
  15. package/dist/backend/api/search-engine.js +227 -0
  16. package/dist/backend/api/search-engine.js.map +1 -0
  17. package/dist/backend/core/block-impl.d.ts +32 -0
  18. package/dist/backend/core/block-impl.d.ts.map +1 -0
  19. package/dist/backend/core/block-impl.js +33 -0
  20. package/dist/backend/core/block-impl.js.map +1 -0
  21. package/dist/backend/core/config-loader.d.ts +68 -0
  22. package/dist/backend/core/config-loader.d.ts.map +1 -0
  23. package/dist/backend/core/config-loader.js +234 -0
  24. package/dist/backend/core/config-loader.js.map +1 -0
  25. package/dist/backend/core/constants.d.ts +39 -0
  26. package/dist/backend/core/constants.d.ts.map +1 -0
  27. package/dist/backend/core/constants.js +57 -0
  28. package/dist/backend/core/constants.js.map +1 -0
  29. package/dist/backend/core/enums.d.ts +54 -0
  30. package/dist/backend/core/enums.d.ts.map +1 -0
  31. package/dist/backend/core/enums.js +61 -0
  32. package/dist/backend/core/enums.js.map +1 -0
  33. package/dist/backend/core/errors.d.ts +83 -0
  34. package/dist/backend/core/errors.d.ts.map +1 -0
  35. package/dist/backend/core/errors.js +151 -0
  36. package/dist/backend/core/errors.js.map +1 -0
  37. package/dist/backend/core/logger.d.ts +68 -0
  38. package/dist/backend/core/logger.d.ts.map +1 -0
  39. package/dist/backend/core/logger.js +151 -0
  40. package/dist/backend/core/logger.js.map +1 -0
  41. package/dist/backend/core/models.d.ts +332 -0
  42. package/dist/backend/core/models.d.ts.map +1 -0
  43. package/dist/backend/core/models.js +6 -0
  44. package/dist/backend/core/models.js.map +1 -0
  45. package/dist/backend/core/service-types.d.ts +184 -0
  46. package/dist/backend/core/service-types.d.ts.map +1 -0
  47. package/dist/backend/core/service-types.js +7 -0
  48. package/dist/backend/core/service-types.js.map +1 -0
  49. package/dist/backend/core/types.d.ts +219 -0
  50. package/dist/backend/core/types.d.ts.map +1 -0
  51. package/dist/backend/core/types.js +109 -0
  52. package/dist/backend/core/types.js.map +1 -0
  53. package/dist/backend/index.d.ts +5 -0
  54. package/dist/backend/index.d.ts.map +1 -0
  55. package/dist/backend/index.js +13 -0
  56. package/dist/backend/index.js.map +1 -0
  57. package/dist/backend/indexing/block-extractor.d.ts +22 -0
  58. package/dist/backend/indexing/block-extractor.d.ts.map +1 -0
  59. package/dist/backend/indexing/block-extractor.js +52 -0
  60. package/dist/backend/indexing/block-extractor.js.map +1 -0
  61. package/dist/backend/indexing/index-builder.d.ts +26 -0
  62. package/dist/backend/indexing/index-builder.d.ts.map +1 -0
  63. package/dist/backend/indexing/index-builder.js +71 -0
  64. package/dist/backend/indexing/index-builder.js.map +1 -0
  65. package/dist/backend/parsers/base-file-parser.d.ts +134 -0
  66. package/dist/backend/parsers/base-file-parser.d.ts.map +1 -0
  67. package/dist/backend/parsers/base-file-parser.js +149 -0
  68. package/dist/backend/parsers/base-file-parser.js.map +1 -0
  69. package/dist/backend/parsers/javascript-parser.d.ts +36 -0
  70. package/dist/backend/parsers/javascript-parser.d.ts.map +1 -0
  71. package/dist/backend/parsers/javascript-parser.js +194 -0
  72. package/dist/backend/parsers/javascript-parser.js.map +1 -0
  73. package/dist/backend/parsers/json-parser.d.ts +15 -0
  74. package/dist/backend/parsers/json-parser.d.ts.map +1 -0
  75. package/dist/backend/parsers/json-parser.js +75 -0
  76. package/dist/backend/parsers/json-parser.js.map +1 -0
  77. package/dist/backend/parsers/markdown-parser.d.ts +17 -0
  78. package/dist/backend/parsers/markdown-parser.d.ts.map +1 -0
  79. package/dist/backend/parsers/markdown-parser.js +94 -0
  80. package/dist/backend/parsers/markdown-parser.js.map +1 -0
  81. package/dist/backend/parsers/parser-factory.d.ts +43 -0
  82. package/dist/backend/parsers/parser-factory.d.ts.map +1 -0
  83. package/dist/backend/parsers/parser-factory.js +149 -0
  84. package/dist/backend/parsers/parser-factory.js.map +1 -0
  85. package/dist/backend/parsers/python-parser.d.ts +21 -0
  86. package/dist/backend/parsers/python-parser.d.ts.map +1 -0
  87. package/dist/backend/parsers/python-parser.js +185 -0
  88. package/dist/backend/parsers/python-parser.js.map +1 -0
  89. package/dist/backend/parsers/yaml-parser.d.ts +16 -0
  90. package/dist/backend/parsers/yaml-parser.d.ts.map +1 -0
  91. package/dist/backend/parsers/yaml-parser.js +81 -0
  92. package/dist/backend/parsers/yaml-parser.js.map +1 -0
  93. package/dist/backend/repositories/implementations/lancedb-block-repository.d.ts +125 -0
  94. package/dist/backend/repositories/implementations/lancedb-block-repository.d.ts.map +1 -0
  95. package/dist/backend/repositories/implementations/lancedb-block-repository.js +505 -0
  96. package/dist/backend/repositories/implementations/lancedb-block-repository.js.map +1 -0
  97. package/dist/backend/repositories/implementations/lancedb-metadata-repository.d.ts +107 -0
  98. package/dist/backend/repositories/implementations/lancedb-metadata-repository.d.ts.map +1 -0
  99. package/dist/backend/repositories/implementations/lancedb-metadata-repository.js +275 -0
  100. package/dist/backend/repositories/implementations/lancedb-metadata-repository.js.map +1 -0
  101. package/dist/backend/repositories/implementations/memory-cache.d.ts +18 -0
  102. package/dist/backend/repositories/implementations/memory-cache.d.ts.map +1 -0
  103. package/dist/backend/repositories/implementations/memory-cache.js +53 -0
  104. package/dist/backend/repositories/implementations/memory-cache.js.map +1 -0
  105. package/dist/backend/repositories/repository.interface.d.ts +334 -0
  106. package/dist/backend/repositories/repository.interface.d.ts.map +1 -0
  107. package/dist/backend/repositories/repository.interface.js +7 -0
  108. package/dist/backend/repositories/repository.interface.js.map +1 -0
  109. package/dist/backend/search/context-extractor.d.ts +29 -0
  110. package/dist/backend/search/context-extractor.d.ts.map +1 -0
  111. package/dist/backend/search/context-extractor.js +106 -0
  112. package/dist/backend/search/context-extractor.js.map +1 -0
  113. package/dist/backend/search/multi-index-searcher.d.ts +28 -0
  114. package/dist/backend/search/multi-index-searcher.d.ts.map +1 -0
  115. package/dist/backend/search/multi-index-searcher.js +81 -0
  116. package/dist/backend/search/multi-index-searcher.js.map +1 -0
  117. package/dist/backend/search/query-parser.d.ts +37 -0
  118. package/dist/backend/search/query-parser.d.ts.map +1 -0
  119. package/dist/backend/search/query-parser.js +145 -0
  120. package/dist/backend/search/query-parser.js.map +1 -0
  121. package/dist/backend/search/ranking-engine.d.ts +31 -0
  122. package/dist/backend/search/ranking-engine.d.ts.map +1 -0
  123. package/dist/backend/search/ranking-engine.js +165 -0
  124. package/dist/backend/search/ranking-engine.js.map +1 -0
  125. package/dist/backend/search/result-formatter.d.ts +29 -0
  126. package/dist/backend/search/result-formatter.d.ts.map +1 -0
  127. package/dist/backend/search/result-formatter.js +70 -0
  128. package/dist/backend/search/result-formatter.js.map +1 -0
  129. package/dist/backend/service-types.d.ts +184 -0
  130. package/dist/backend/service-types.d.ts.map +1 -0
  131. package/dist/backend/service-types.js +7 -0
  132. package/dist/backend/service-types.js.map +1 -0
  133. package/dist/backend/services/embedding-service.d.ts +75 -0
  134. package/dist/backend/services/embedding-service.d.ts.map +1 -0
  135. package/dist/backend/services/embedding-service.js +298 -0
  136. package/dist/backend/services/embedding-service.js.map +1 -0
  137. package/dist/backend/services/file-watcher.d.ts +17 -0
  138. package/dist/backend/services/file-watcher.d.ts.map +1 -0
  139. package/dist/backend/services/file-watcher.js +92 -0
  140. package/dist/backend/services/file-watcher.js.map +1 -0
  141. package/dist/backend/services/index-information-service.d.ts +114 -0
  142. package/dist/backend/services/index-information-service.d.ts.map +1 -0
  143. package/dist/backend/services/index-information-service.js +104 -0
  144. package/dist/backend/services/index-information-service.js.map +1 -0
  145. package/dist/backend/services/ngao-search-service.d.ts +107 -0
  146. package/dist/backend/services/ngao-search-service.d.ts.map +1 -0
  147. package/dist/backend/services/ngao-search-service.js +384 -0
  148. package/dist/backend/services/ngao-search-service.js.map +1 -0
  149. package/dist/backend/services/quantization-service.d.ts +53 -0
  150. package/dist/backend/services/quantization-service.d.ts.map +1 -0
  151. package/dist/backend/services/quantization-service.js +84 -0
  152. package/dist/backend/services/quantization-service.js.map +1 -0
  153. package/dist/backend/services/reindex-manager.d.ts +25 -0
  154. package/dist/backend/services/reindex-manager.d.ts.map +1 -0
  155. package/dist/backend/services/reindex-manager.js +78 -0
  156. package/dist/backend/services/reindex-manager.js.map +1 -0
  157. package/dist/backend/services/session-manager.d.ts +115 -0
  158. package/dist/backend/services/session-manager.d.ts.map +1 -0
  159. package/dist/backend/services/session-manager.js +150 -0
  160. package/dist/backend/services/session-manager.js.map +1 -0
  161. package/dist/backend/services/vector-search-service.d.ts +81 -0
  162. package/dist/backend/services/vector-search-service.d.ts.map +1 -0
  163. package/dist/backend/services/vector-search-service.js +143 -0
  164. package/dist/backend/services/vector-search-service.js.map +1 -0
  165. package/dist/backend/utils/file-utils.d.ts +92 -0
  166. package/dist/backend/utils/file-utils.d.ts.map +1 -0
  167. package/dist/backend/utils/file-utils.js +247 -0
  168. package/dist/backend/utils/file-utils.js.map +1 -0
  169. package/dist/cli/setup.d.ts +4 -0
  170. package/dist/cli/setup.d.ts.map +1 -0
  171. package/dist/cli/setup.js +138 -0
  172. package/dist/cli/setup.js.map +1 -0
  173. package/dist/index.d.ts +6 -0
  174. package/dist/index.d.ts.map +1 -0
  175. package/dist/index.js +22 -0
  176. package/dist/index.js.map +1 -0
  177. package/dist/main.d.ts +14 -0
  178. package/dist/main.d.ts.map +1 -0
  179. package/dist/main.js +7 -67075
  180. package/dist/main.js.map +1 -0
  181. package/dist/mcp/tool-schemas.d.ts +205 -0
  182. package/dist/mcp/tool-schemas.d.ts.map +1 -0
  183. package/dist/mcp/tool-schemas.js +391 -0
  184. package/dist/mcp/tool-schemas.js.map +1 -0
  185. package/dist/server/logger.d.ts +50 -0
  186. package/dist/server/logger.d.ts.map +1 -0
  187. package/dist/server/logger.js +77 -0
  188. package/dist/server/logger.js.map +1 -0
  189. package/dist/server/tool-registry.d.ts +64 -0
  190. package/dist/server/tool-registry.d.ts.map +1 -0
  191. package/dist/server/tool-registry.js +93 -0
  192. package/dist/server/tool-registry.js.map +1 -0
  193. package/dist/server/transports/mcp-transport.d.ts +31 -0
  194. package/dist/server/transports/mcp-transport.d.ts.map +1 -0
  195. package/dist/server/transports/mcp-transport.js +331 -0
  196. package/dist/server/transports/mcp-transport.js.map +1 -0
  197. package/dist/server/transports/rest-transport.d.ts +36 -0
  198. package/dist/server/transports/rest-transport.d.ts.map +1 -0
  199. package/dist/server/transports/rest-transport.js +250 -0
  200. package/dist/server/transports/rest-transport.js.map +1 -0
  201. package/docs/API.md +116 -0
  202. package/docs/ARCHITECTURE.md +101 -0
  203. package/docs/FILE_WATCHING.md +120 -0
  204. package/docs/INSTALLATION.md +87 -0
  205. package/docs/MCP_INTEGRATION.md +108 -0
  206. package/docs/README.md +288 -0
  207. package/docs/USAGE.md +123 -0
  208. package/docs/architecture-design-standards/01_ARCHITECTURE.md +863 -0
  209. package/docs/architecture-design-standards/02_SEARCH_ENGINE_DESIGN.md +958 -0
  210. package/docs/architecture-design-standards/03_DATAFLOW.md +1000 -0
  211. package/docs/architecture-design-standards/04_VISUAL_GUIDE.md +922 -0
  212. package/docs/architecture-design-standards/05_REPOSITORY_PATTERN_GUIDE.md +503 -0
  213. package/docs/architecture-design-standards/06_IMPLEMENTATION_PATTERNS.md +1026 -0
  214. package/docs/architecture-design-standards/07_TYPESCRIPT_GUIDE.md +1027 -0
  215. package/docs/architecture-design-standards/08_CODING_STANDARDS.md +1274 -0
  216. package/docs/reference/01_START_HERE.md +108 -0
  217. package/docs/reference/02_QUICK_REFERENCE.md +363 -0
  218. package/docs/reference/03_DOCUMENTATION_INDEX.md +293 -0
  219. package/docs/reference/04_DELIVERY_SUMMARY.md +463 -0
  220. package/docs/reference/05_IMPLEMENTATION_OVERVIEW.md +319 -0
  221. package/docs/reference/06_RESEARCH_SUMMARY.md +519 -0
  222. package/docs/tracking/03_IMPLEMENTATION_ROADMAP.md +788 -0
  223. package/jest.config.json +12 -0
  224. package/package.json +46 -53
  225. package/prepend-shebang.js +18 -0
  226. package/scripts/setup-mcp.sh +66 -0
  227. package/src/backend/index.ts +5 -0
  228. package/src/backend/service-types.ts +219 -0
  229. package/src/backend/services/file-watcher.ts +79 -0
  230. package/src/backend/services/ngao-search-service.ts +430 -0
  231. package/src/backend/services/reindex-manager.ts +90 -0
  232. package/src/backend/services/session-manager.ts +214 -0
  233. package/src/cli/setup.ts +122 -0
  234. package/src/index.ts +6 -0
  235. package/src/main.ts +225 -0
  236. package/src/mcp/tool-schemas.ts +439 -0
  237. package/src/server/logger.ts +88 -0
  238. package/src/server/tool-registry.ts +117 -0
  239. package/src/server/transports/mcp-transport.ts +374 -0
  240. package/src/server/transports/rest-transport.ts +258 -0
  241. package/tests/unit/agent-tools.test.ts +454 -0
  242. package/tests/unit/file-watcher.test.d.ts +2 -0
  243. package/tests/unit/file-watcher.test.d.ts.map +1 -0
  244. package/tests/unit/file-watcher.test.js +9 -0
  245. package/tests/unit/file-watcher.test.js.map +1 -0
  246. package/tests/unit/file-watcher.test.ts +7 -0
  247. package/tests/unit/search-integration.test.ts +256 -0
  248. package/tests/unit/services.test.d.ts +2 -0
  249. package/tests/unit/services.test.d.ts.map +1 -0
  250. package/tests/unit/services.test.js +9 -0
  251. package/tests/unit/services.test.js.map +1 -0
  252. package/tests/unit/services.test.ts +7 -0
  253. package/tsconfig.json +23 -0
  254. package/webpack.backend.config.js +60 -0
  255. package/webpack.config.js +34 -0
  256. package/models/Xenova/all-MiniLM-L6-v2/config.json +0 -25
  257. package/models/Xenova/all-MiniLM-L6-v2/onnx/model_quantized.onnx +0 -0
  258. package/models/Xenova/all-MiniLM-L6-v2/tokenizer.json +0 -30686
  259. package/models/Xenova/all-MiniLM-L6-v2/tokenizer_config.json +0 -15
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Session Manager for NGAO Search
3
+ * Manages user sessions and tracks search history
4
+ */
5
+
6
+ import { v4 as uuid } from 'uuid';
7
+
8
+ /**
9
+ * Represents a user session with search history
10
+ */
11
+ export interface Session {
12
+ /** Unique session identifier */
13
+ sessionId: string;
14
+ /** Unix timestamp when session was created */
15
+ startedAt: number;
16
+ /** Unix timestamp of last activity */
17
+ lastActivity: number;
18
+ /** Search history entries for this session */
19
+ searchHistory: SearchHistoryEntry[];
20
+ }
21
+
22
+ /**
23
+ * Represents a single search query in history
24
+ */
25
+ export interface SearchHistoryEntry {
26
+ /** Unique identifier for this history entry */
27
+ id: string;
28
+ /** Original search query string */
29
+ query: string;
30
+ /** Unix timestamp when search was performed */
31
+ timestamp: number;
32
+ /** Number of results returned */
33
+ resultCount: number;
34
+ /** Execution time in milliseconds */
35
+ executionTimeMs: number;
36
+ /** Optional filters applied to search */
37
+ filters?: Record<string, unknown>;
38
+ /** Item types queried */
39
+ itemTypesQueried?: string[];
40
+ /** File types queried */
41
+ fileTypesQueried?: string[];
42
+ /** Minimum relevance threshold applied */
43
+ minRelevanceApplied?: number;
44
+ /** Brief explanation of why results matched */
45
+ explanation?: string;
46
+ }
47
+
48
+ /**
49
+ * Manages user sessions and search history
50
+ * Provides session lifecycle management and history tracking
51
+ */
52
+ export class SessionManager {
53
+ /** In-memory store of active sessions */
54
+ private _sessions: Map<string, Session> = new Map();
55
+
56
+ /** Cleanup interval timer */
57
+ private _cleanupTimer: ReturnType<typeof setInterval> | null = null;
58
+
59
+ /** Session timeout in milliseconds (30 minutes) */
60
+ private readonly SESSION_TIMEOUT_MS = 30 * 60 * 1000;
61
+
62
+ /** Cleanup interval in milliseconds (1 minute) */
63
+ private readonly CLEANUP_INTERVAL_MS = 60 * 1000;
64
+
65
+ /** Maximum search history size per session */
66
+ private readonly MAX_HISTORY_SIZE = 100;
67
+
68
+ /**
69
+ * Initialize SessionManager and start cleanup timer
70
+ */
71
+ public constructor() {
72
+ this._startCleanupTimer();
73
+ }
74
+
75
+ /**
76
+ * Create a new session
77
+ * @returns New session ID
78
+ */
79
+ public createSession(): string {
80
+ const sessionId = uuid();
81
+ const now = Date.now();
82
+
83
+ this._sessions.set(sessionId, {
84
+ sessionId,
85
+ startedAt: now,
86
+ lastActivity: now,
87
+ searchHistory: [],
88
+ });
89
+
90
+ return sessionId;
91
+ }
92
+
93
+ /**
94
+ * Retrieve an existing session
95
+ * @param sessionId - Session ID to retrieve
96
+ * @returns Session object or null if not found
97
+ */
98
+ public getSession(sessionId: string): Session | null {
99
+ return this._sessions.get(sessionId) || null;
100
+ }
101
+
102
+ /**
103
+ * Add a search entry to session history
104
+ * @param sessionId - Session ID
105
+ * @param entry - Search history entry to add
106
+ */
107
+ public addSearchToHistory(sessionId: string, entry: SearchHistoryEntry): void {
108
+ const session = this._sessions.get(sessionId);
109
+ if (!session) {
110
+ return; // Silently fail if session not found
111
+ }
112
+
113
+ // Add to history
114
+ session.searchHistory.push(entry);
115
+
116
+ // Enforce max history size (keep most recent)
117
+ if (session.searchHistory.length > this.MAX_HISTORY_SIZE) {
118
+ session.searchHistory = session.searchHistory.slice(-this.MAX_HISTORY_SIZE);
119
+ }
120
+
121
+ // Update last activity
122
+ session.lastActivity = Date.now();
123
+ }
124
+
125
+ /**
126
+ * Retrieve search history for a session
127
+ * @param sessionId - Session ID
128
+ * @returns Array of search history entries or null if session not found
129
+ */
130
+ public getSearchHistory(sessionId: string): SearchHistoryEntry[] | null {
131
+ const session = this._sessions.get(sessionId);
132
+ if (!session) {
133
+ return null;
134
+ }
135
+
136
+ // Update last activity
137
+ session.lastActivity = Date.now();
138
+
139
+ return session.searchHistory;
140
+ }
141
+
142
+ /**
143
+ * End a session and remove it
144
+ * @param sessionId - Session ID to end
145
+ */
146
+ public endSession(sessionId: string): void {
147
+ this._sessions.delete(sessionId);
148
+ }
149
+
150
+ /**
151
+ * Get all active sessions
152
+ * @returns Array of all active session IDs
153
+ */
154
+ public getActiveSessions(): string[] {
155
+ return Array.from(this._sessions.keys());
156
+ }
157
+
158
+ /**
159
+ * Cleanup expired sessions
160
+ * @private
161
+ */
162
+ private _cleanupExpiredSessions(): void {
163
+ const now = Date.now();
164
+ const expiredSessionIds: string[] = [];
165
+
166
+ // Find expired sessions
167
+ for (const [sessionId, session] of this._sessions.entries()) {
168
+ if (now - session.lastActivity > this.SESSION_TIMEOUT_MS) {
169
+ expiredSessionIds.push(sessionId);
170
+ }
171
+ }
172
+
173
+ // Remove expired sessions
174
+ for (const sessionId of expiredSessionIds) {
175
+ this._sessions.delete(sessionId);
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Start the cleanup timer
181
+ * @private
182
+ */
183
+ private _startCleanupTimer(): void {
184
+ this._cleanupTimer = setInterval(() => {
185
+ this._cleanupExpiredSessions();
186
+ }, this.CLEANUP_INTERVAL_MS);
187
+
188
+ // Unref timer so it doesn't prevent process exit
189
+ if (this._cleanupTimer.unref) {
190
+ this._cleanupTimer.unref();
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Stop the cleanup timer
196
+ * @private
197
+ */
198
+ private _stopCleanupTimer(): void {
199
+ if (this._cleanupTimer) {
200
+ clearInterval(this._cleanupTimer);
201
+ this._cleanupTimer = null;
202
+ }
203
+ }
204
+
205
+ /**
206
+ * Destroy the session manager (cleanup resources)
207
+ */
208
+ public destroy(): void {
209
+ this._stopCleanupTimer();
210
+ this._sessions.clear();
211
+ }
212
+ }
213
+
214
+
@@ -0,0 +1,122 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as readline from 'readline';
4
+ import { execSync } from 'child_process';
5
+ import { v4 as uuidv4 } from 'uuid';
6
+ import * as os from 'os';
7
+ import { NgaoSearchService } from '../backend/services/ngao-search-service';
8
+
9
+ const rl = readline.createInterface({
10
+ input: process.stdin,
11
+ output: process.stdout,
12
+ });
13
+
14
+ function question(prompt: string): Promise<string> {
15
+ return new Promise((resolve) => {
16
+ rl.question(prompt, (answer) => {
17
+ resolve(answer);
18
+ });
19
+ });
20
+ }
21
+
22
+ export async function setupMCP(): Promise<{ projectDir: string }> {
23
+ console.log('\nšŸ”§ NGAO Search - MCP Setup for Claude Code\n');
24
+
25
+ // Ask for project directory
26
+ const projectDir = await question('šŸ“ Enter your project directory path (or press Enter for current): ');
27
+ const resolvedProjectDir = projectDir.trim() || process.cwd();
28
+
29
+ // Create .ngao-search config in project
30
+ const projectConfigPath = path.join(resolvedProjectDir, '.ngao-search.json');
31
+ if (!fs.existsSync(projectConfigPath)) {
32
+ // Generate UUID for this project to isolate its database
33
+ const projectUUID = uuidv4();
34
+ const projectConfig = {
35
+ projectId: projectUUID,
36
+ includePaths: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx', '**/*.py', '**/*.md'],
37
+ excludePaths: ['node_modules/**', 'dist/**', '.git/**'],
38
+ };
39
+ fs.writeFileSync(projectConfigPath, JSON.stringify(projectConfig, null, 2));
40
+ console.log(`āœ… Project config created: ${projectConfigPath}`);
41
+ console.log(`šŸ“‹ Project ID: ${projectUUID}`);
42
+ }
43
+
44
+ // Create .mcp-config.json in project for reference
45
+ const mcpConfigPath = path.join(resolvedProjectDir, '.mcp-config.json');
46
+ const mcpConfig = {
47
+ mcpServers: {
48
+ 'ngao-search': {
49
+ command: 'npx',
50
+ args: ['ngao-search'],
51
+ env: {
52
+ NGAO_SEARCH_PROJECT: resolvedProjectDir,
53
+ MCP_TRANSPORT: 'stdio',
54
+ },
55
+ },
56
+ },
57
+ };
58
+ fs.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2));
59
+ console.log(`āœ… MCP config created: ${mcpConfigPath}`);
60
+
61
+ // Register with Claude Code CLI using `claude mcp add`
62
+ try {
63
+ console.log('\nšŸ“” Registering with Claude Code CLI...');
64
+ execSync(
65
+ `cd "${resolvedProjectDir}" && claude mcp add -e NGAO_SEARCH_PROJECT="${resolvedProjectDir}" -e MCP_TRANSPORT=stdio -- ngao-search npx ngao-search`,
66
+ { stdio: 'pipe' }
67
+ );
68
+ console.log('āœ… MCP server registered with Claude Code CLI');
69
+ } catch (error) {
70
+ console.log('āš ļø Could not auto-register with Claude Code CLI.');
71
+ console.log(' Please run this command manually in your project directory:');
72
+ console.log(`\n cd "${resolvedProjectDir}"`);
73
+ console.log(' claude mcp add -e NGAO_SEARCH_PROJECT="' + resolvedProjectDir + '" -e MCP_TRANSPORT=stdio -- ngao-search npx ngao-search\n');
74
+ }
75
+
76
+ // Initialize database (embedding model will lazy-load on first search)
77
+ console.log('\nāš™ļø Initializing database...');
78
+ let searchService: NgaoSearchService | null = null;
79
+ try {
80
+ searchService = new NgaoSearchService(resolvedProjectDir);
81
+ await searchService.ensureInitialized();
82
+ console.log('āœ… Database initialized');
83
+ console.log(' Embedding model will load on first search');
84
+ } catch (error) {
85
+ console.warn('āš ļø Warning: Could not initialize database');
86
+ console.warn(` Error: ${String(error)}`);
87
+ console.log(' Database will be initialized on first use instead.\n');
88
+ }
89
+
90
+ // Auto-index the project directory
91
+ if (searchService) {
92
+ console.log('\nšŸ“‘ Auto-indexing project directory...');
93
+ try {
94
+ const indexResult = await searchService.autoIndexProjectDirectory(resolvedProjectDir);
95
+ if (indexResult.success && indexResult.stats) {
96
+ console.log('āœ… Auto-indexing completed');
97
+ console.log(` šŸ“Š Indexed ${indexResult.stats.totalFiles} files with ${indexResult.stats.totalBlocks} code blocks`);
98
+ } else {
99
+ console.warn(`āš ļø Auto-indexing encountered issues: ${indexResult.error || 'Unknown error'}`);
100
+ console.log(' You can manually index later using the search tools\n');
101
+ }
102
+ } catch (error) {
103
+ console.warn('āš ļø Warning: Could not auto-index project directory');
104
+ console.warn(` Error: ${String(error)}`);
105
+ console.log(' You can manually index later using the search tools\n');
106
+ }
107
+ }
108
+
109
+ // Show setup instructions
110
+ console.log('\nšŸ“ Setup Complete!\n');
111
+ console.log('✨ NGAO Search is now integrated with Claude Code');
112
+ console.log('\nā„¹ļø Configuration Details:');
113
+ console.log('šŸ“ Project directory: ' + resolvedProjectDir);
114
+ console.log('šŸ”Œ Server port: Automatically assigned');
115
+ console.log('šŸ“Œ Project config: ' + projectConfigPath);
116
+ console.log('šŸ“Œ MCP config: ' + mcpConfigPath + '\n');
117
+ console.log('šŸš€ You can now use NGAO Search in Claude Code!\n');
118
+
119
+ rl.close();
120
+ return { projectDir: resolvedProjectDir };
121
+ }
122
+
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * NGAO Search - Main Entry Point
3
+ * Re-exports from backend for backward compatibility
4
+ */
5
+
6
+ export * from './backend';
package/src/main.ts ADDED
@@ -0,0 +1,225 @@
1
+ /**
2
+ * Unified Entry Point for NGAO Search
3
+ * Supports multiple transport modes: stdio (MCP) or http (REST)
4
+ *
5
+ * Transport selection via environment variable:
6
+ * - MCP_TRANSPORT=stdio - Start MCP stdio server only (for Claude Desktop)
7
+ * - MCP_TRANSPORT=http - Start REST HTTP server only (default)
8
+ * - --setup - Run interactive MCP setup for Claude
9
+ * - --help, -h - Show help documentation with tool descriptions
10
+ *
11
+ * All transports share the same NgaoSearchService instance
12
+ */
13
+
14
+ import { NgaoSearchService } from './backend/services/ngao-search-service';
15
+ import { McpTransport } from './server/transports/mcp-transport';
16
+ import { RestTransport } from './server/transports/rest-transport';
17
+ import { createLogger } from './server/logger';
18
+
19
+ // Check for --setup flag for interactive setup
20
+ const args = process.argv.slice(2);
21
+ const setupMode = args.includes('--setup') || process.env.NGAO_SETUP;
22
+ const helpMode = args.includes('--help') || args.includes('-h') || process.env.NGAO_HELP;
23
+
24
+ // Show help if requested (check early before anything else)
25
+ if (helpMode) {
26
+ console.log(`
27
+ ╔════════════════════════════════════════════════════════════════════════════╗
28
+ ā•‘ NGAO Search - Model Context Protocol Server ā•‘
29
+ ā•‘ Local Code/Document Search with LLM-Friendly Output ā•‘
30
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
31
+
32
+ šŸ“– USAGE
33
+ ngao-search [COMMAND] [OPTIONS]
34
+ OR with npx:
35
+ npx ngao-search -- --help
36
+ OR with environment variable:
37
+ NGAO_HELP=true npx ngao-search
38
+
39
+ šŸ”§ SETUP
40
+ ngao-search --setup
41
+ OR: npx ngao-search -- --setup
42
+ OR: NGAO_SETUP=true npx ngao-search
43
+ Interactively configure NGAO Search for a project.
44
+ Creates .ngao-search.json with a unique projectId and database isolation.
45
+
46
+ šŸš€ START SERVER
47
+ Default: Start HTTP REST API on a random available port
48
+ MCP_TRANSPORT=stdio ngao-search
49
+ OR: MCP_TRANSPORT=stdio npx ngao-search
50
+ Start MCP stdio server for Claude Code/Desktop integration
51
+
52
+ šŸ’” AVAILABLE TOOLS (for LLMs)
53
+
54
+ 1. search [REQUIRED]
55
+ Search through indexed code and documentation
56
+ Parameters:
57
+ - query: string (required) - Search query
58
+ - maxResults: number (optional) - Max results to return (default: 100)
59
+ - sessionId: string (optional) - Session ID for history tracking
60
+
61
+ 2. index [REQUIRED]
62
+ Index a directory for searching
63
+ Parameters:
64
+ - dirPath: string (required) - Directory path to index
65
+
66
+ 3. list_indexed_dirs
67
+ List all indexed directories
68
+ No parameters required
69
+
70
+ 4. get_stats
71
+ Get indexing statistics
72
+ No parameters required
73
+
74
+ 5. get_index_info
75
+ Get detailed index information with file breakdown
76
+ No parameters required
77
+
78
+ 6. get_file_statistics
79
+ Get per-file index statistics
80
+ Parameters:
81
+ - filePath: string (optional) - Specific file path
82
+
83
+ 7. get_search_history
84
+ Get search history for a session
85
+ Parameters:
86
+ - sessionId: string (required) - Session ID
87
+
88
+ 8. start_reindex
89
+ Start a reindex operation
90
+ Parameters:
91
+ - dirPath: string (required) - Directory to reindex
92
+ - mode: string (optional) - 'incremental' or 'full' (default: 'incremental')
93
+
94
+ 9. get_reindex_status
95
+ Get reindex operation status
96
+ Parameters:
97
+ - reindexId: string (required) - Reindex operation ID
98
+
99
+ šŸ”‘ KEY FEATURES
100
+
101
+ • šŸ“ Multi-Language Support
102
+ Supports TypeScript, JavaScript, Python, Markdown, YAML, JSON, and more
103
+
104
+ • 🧠 Semantic Search
105
+ Uses vector embeddings for intelligent code/doc search
106
+
107
+ • šŸ—‚ļø Project Isolation
108
+ Each project gets a unique database stored in ~/.ngao/ directory
109
+
110
+ • šŸ’¾ Persistent Storage
111
+ Uses LanceDB for reliable vector storage
112
+
113
+ • šŸ“Š Session Tracking
114
+ Track search history within sessions for context awareness
115
+
116
+ • šŸ”„ Reindexing
117
+ Incremental or full reindex support for keeping index up-to-date
118
+
119
+ āš™ļø CONFIGURATION
120
+
121
+ Project config stored in .ngao-search.json:
122
+ {
123
+ "projectId": "unique-uuid-for-database-isolation",
124
+ "includePaths": ["**/*.ts", "**/*.js", "**/*.py", "**/*.md"],
125
+ "excludePaths": ["node_modules/**", "dist/**", ".git/**"]
126
+ }
127
+
128
+ Database Location: ~/.ngao/{projectId}.lancedb
129
+ Metadata Location: ~/.ngao/{projectId}.metadata.json
130
+
131
+ šŸŽÆ WORKFLOW FOR LLMs
132
+
133
+ 1. Call index() with your project directory
134
+ 2. Call search() to find relevant code/docs
135
+ 3. Use get_stats() to check indexing progress
136
+ 4. Use get_index_info() to understand code structure
137
+ 5. Call start_reindex() when code changes
138
+ 6. Track session history with sessionId for context
139
+
140
+ šŸ“š MORE INFO
141
+ github.com/ngao-team/ngao-search
142
+
143
+ `);
144
+ process.exit(0);
145
+ }
146
+
147
+ // When setup completes, auto-start in MCP stdio mode for Claude
148
+ if (setupMode) {
149
+ process.env.MCP_TRANSPORT = 'stdio';
150
+ }
151
+
152
+ const transport = (process.env.MCP_TRANSPORT || 'http').toLowerCase();
153
+
154
+ /**
155
+ * Main async function
156
+ */
157
+ async function main(): Promise<void> {
158
+ // Run setup first if requested, then continue to start server
159
+ if (setupMode) {
160
+ try {
161
+ const { setupMCP } = await import('./cli/setup');
162
+ const { projectDir } = await setupMCP();
163
+ // Set environment vars for server startup
164
+ process.env.NGAO_SEARCH_PROJECT = projectDir;
165
+ console.log('\nšŸš€ Starting NGAO Search MCP server...\n');
166
+ // Continue to server startup below
167
+ } catch (error) {
168
+ console.error('Setup failed:', error);
169
+ process.exit(1);
170
+ }
171
+ }
172
+
173
+ try {
174
+ // Create shared service instance
175
+ const service = new NgaoSearchService();
176
+
177
+ // Eagerly initialize database on startup
178
+ // (embedding model will lazy-load on first search to avoid network dependency)
179
+ try {
180
+ await service.ensureInitialized();
181
+ } catch (error) {
182
+ // Log database initialization errors
183
+ console.warn('Warning: Could not initialize database:', String(error));
184
+ }
185
+
186
+ switch (transport) {
187
+ case 'stdio': {
188
+ const logger = createLogger('stdio');
189
+ logger.info('Transport: MCP stdio (Claude Desktop)');
190
+ logger.info('Initializing NgaoSearchService');
191
+
192
+ const mcpTransport = new McpTransport(service, logger);
193
+ await mcpTransport.start();
194
+
195
+ logger.info('NGAO Search server started successfully');
196
+ break;
197
+ }
198
+
199
+ case 'http': {
200
+ const logger = createLogger('http');
201
+ logger.info('Transport: HTTP REST API');
202
+ logger.info('Initializing NgaoSearchService');
203
+
204
+ const restTransport = new RestTransport(service, logger);
205
+ restTransport.start(0); // 0 = randomly assigned available port
206
+
207
+ logger.info('NGAO Search server started successfully');
208
+ break;
209
+ }
210
+
211
+ default:
212
+ console.error(`āŒ Unknown transport: ${transport}`);
213
+ console.error(' Valid options: stdio, http');
214
+ console.error(' Default: http');
215
+ process.exit(1);
216
+ }
217
+ } catch (error) {
218
+ console.error('āŒ Failed to start NGAO Search server:');
219
+ console.error(error);
220
+ process.exit(1);
221
+ }
222
+ }
223
+
224
+ // Start the server
225
+ main();