@pimzino/sgrep 1.3.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.
Files changed (73) hide show
  1. package/README.md +413 -0
  2. package/build/.claude-plugin/marketplace.json +20 -0
  3. package/build/commands/ask.d.ts +11 -0
  4. package/build/commands/ask.d.ts.map +1 -0
  5. package/build/commands/ask.js +65 -0
  6. package/build/commands/ask.js.map +1 -0
  7. package/build/commands/enhance.d.ts +16 -0
  8. package/build/commands/enhance.d.ts.map +1 -0
  9. package/build/commands/enhance.js +107 -0
  10. package/build/commands/enhance.js.map +1 -0
  11. package/build/commands/search.d.ts +12 -0
  12. package/build/commands/search.d.ts.map +1 -0
  13. package/build/commands/search.js +65 -0
  14. package/build/commands/search.js.map +1 -0
  15. package/build/commands/watch.d.ts +13 -0
  16. package/build/commands/watch.d.ts.map +1 -0
  17. package/build/commands/watch.js +179 -0
  18. package/build/commands/watch.js.map +1 -0
  19. package/build/index.d.ts +3 -0
  20. package/build/index.d.ts.map +1 -0
  21. package/build/index.js +124 -0
  22. package/build/index.js.map +1 -0
  23. package/build/install/claude-code.d.ts +10 -0
  24. package/build/install/claude-code.d.ts.map +1 -0
  25. package/build/install/claude-code.js +255 -0
  26. package/build/install/claude-code.js.map +1 -0
  27. package/build/install/codex.d.ts +4 -0
  28. package/build/install/codex.d.ts.map +1 -0
  29. package/build/install/codex.js +123 -0
  30. package/build/install/codex.js.map +1 -0
  31. package/build/install/cursor.d.ts +4 -0
  32. package/build/install/cursor.d.ts.map +1 -0
  33. package/build/install/cursor.js +91 -0
  34. package/build/install/cursor.js.map +1 -0
  35. package/build/install/droid.d.ts +4 -0
  36. package/build/install/droid.d.ts.map +1 -0
  37. package/build/install/droid.js +226 -0
  38. package/build/install/droid.js.map +1 -0
  39. package/build/install/opencode.d.ts +4 -0
  40. package/build/install/opencode.d.ts.map +1 -0
  41. package/build/install/opencode.js +276 -0
  42. package/build/install/opencode.js.map +1 -0
  43. package/build/plugins/sgrep/.claude-plugin/plugin.json +9 -0
  44. package/build/plugins/sgrep/hooks/hooks.json +39 -0
  45. package/build/plugins/sgrep/hooks/sgrep_enhance.js +160 -0
  46. package/build/plugins/sgrep/hooks/sgrep_watch.js +240 -0
  47. package/build/plugins/sgrep/hooks/sgrep_watch_kill.js +158 -0
  48. package/build/plugins/sgrep/skills/sgrep/SKILL.md +97 -0
  49. package/build/utils/config.d.ts +26 -0
  50. package/build/utils/config.d.ts.map +1 -0
  51. package/build/utils/config.js +106 -0
  52. package/build/utils/config.js.map +1 -0
  53. package/build/utils/context-manager.d.ts +33 -0
  54. package/build/utils/context-manager.d.ts.map +1 -0
  55. package/build/utils/context-manager.js +244 -0
  56. package/build/utils/context-manager.js.map +1 -0
  57. package/build/utils/context.d.ts +25 -0
  58. package/build/utils/context.d.ts.map +1 -0
  59. package/build/utils/context.js +132 -0
  60. package/build/utils/context.js.map +1 -0
  61. package/build/utils/file-walker.d.ts +20 -0
  62. package/build/utils/file-walker.d.ts.map +1 -0
  63. package/build/utils/file-walker.js +239 -0
  64. package/build/utils/file-walker.js.map +1 -0
  65. package/build/utils/output.d.ts +38 -0
  66. package/build/utils/output.d.ts.map +1 -0
  67. package/build/utils/output.js +150 -0
  68. package/build/utils/output.js.map +1 -0
  69. package/build/utils/prompt-parser.d.ts +12 -0
  70. package/build/utils/prompt-parser.d.ts.map +1 -0
  71. package/build/utils/prompt-parser.js +54 -0
  72. package/build/utils/prompt-parser.js.map +1 -0
  73. package/package.json +59 -0
@@ -0,0 +1,106 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import * as os from "os";
4
+ const CONFIG_FILE_NAME = ".sgreprc.json";
5
+ const GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".config", "sgrep");
6
+ const GLOBAL_CONFIG_FILE = path.join(GLOBAL_CONFIG_DIR, "config.json");
7
+ /**
8
+ * Searches for a config file starting from the given directory,
9
+ * walking up parent directories until one is found or root is reached.
10
+ */
11
+ function findLocalConfigFile(startDir) {
12
+ let currentDir = path.resolve(startDir);
13
+ const root = path.parse(currentDir).root;
14
+ while (currentDir !== root) {
15
+ const configPath = path.join(currentDir, CONFIG_FILE_NAME);
16
+ if (fs.existsSync(configPath)) {
17
+ return configPath;
18
+ }
19
+ currentDir = path.dirname(currentDir);
20
+ }
21
+ // Check root directory
22
+ const rootConfigPath = path.join(root, CONFIG_FILE_NAME);
23
+ if (fs.existsSync(rootConfigPath)) {
24
+ return rootConfigPath;
25
+ }
26
+ return null;
27
+ }
28
+ /**
29
+ * Safely reads and parses a JSON config file.
30
+ */
31
+ function readConfigFile(filePath) {
32
+ try {
33
+ const content = fs.readFileSync(filePath, "utf-8");
34
+ return JSON.parse(content);
35
+ }
36
+ catch {
37
+ // Ignore invalid config files
38
+ return null;
39
+ }
40
+ }
41
+ /**
42
+ * Loads configuration with cascading priority:
43
+ * 1. CLI flags (handled by caller)
44
+ * 2. Environment variables
45
+ * 3. Local config file (.sgreprc.json)
46
+ * 4. Global config file (~/.config/sgrep/config.json)
47
+ */
48
+ export function loadConfig(workingDir = process.cwd()) {
49
+ const config = {};
50
+ // Load global config (lowest priority)
51
+ const globalConfig = readConfigFile(GLOBAL_CONFIG_FILE);
52
+ if (globalConfig) {
53
+ Object.assign(config, globalConfig);
54
+ }
55
+ // Load local config (higher priority)
56
+ const localConfigPath = findLocalConfigFile(workingDir);
57
+ if (localConfigPath) {
58
+ const localConfig = readConfigFile(localConfigPath);
59
+ if (localConfig) {
60
+ Object.assign(config, localConfig);
61
+ }
62
+ }
63
+ // Environment variables (highest priority before CLI flags)
64
+ if (process.env.SGREP_DIR) {
65
+ config.defaultDir = process.env.SGREP_DIR;
66
+ }
67
+ if (process.env.SGREP_DEBUG === "true" || process.env.SGREP_DEBUG === "1") {
68
+ config.debug = true;
69
+ }
70
+ if (process.env.SGREP_MAX_RESULTS) {
71
+ const maxResults = parseInt(process.env.SGREP_MAX_RESULTS, 10);
72
+ if (!isNaN(maxResults) && maxResults > 0) {
73
+ config.maxResults = maxResults;
74
+ }
75
+ }
76
+ if (process.env.SGREP_FORMAT === "json") {
77
+ config.outputFormat = "json";
78
+ }
79
+ if (process.env.NO_COLOR === "1" || process.env.SGREP_NO_COLOR === "1") {
80
+ config.noColor = true;
81
+ }
82
+ return config;
83
+ }
84
+ /**
85
+ * Merges CLI options with config, CLI options take precedence.
86
+ */
87
+ export function mergeWithCliOptions(config, cliOptions) {
88
+ const merged = { ...config };
89
+ if (cliOptions.dir !== undefined) {
90
+ merged.defaultDir = cliOptions.dir;
91
+ }
92
+ if (cliOptions.maxResults !== undefined) {
93
+ merged.maxResults = cliOptions.maxResults;
94
+ }
95
+ if (cliOptions.json !== undefined && cliOptions.json) {
96
+ merged.outputFormat = "json";
97
+ }
98
+ if (cliOptions.noColor !== undefined) {
99
+ merged.noColor = cliOptions.noColor;
100
+ }
101
+ if (cliOptions.debug !== undefined) {
102
+ merged.debug = cliOptions.debug;
103
+ }
104
+ return merged;
105
+ }
106
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { DirectContext } from "@augmentcode/auggie-sdk";
2
+ export type IndexUpdateType = "added" | "changed" | "removed" | "indexed";
3
+ export interface IndexUpdateEvent {
4
+ type: IndexUpdateType;
5
+ files: string[];
6
+ totalIndexed: number;
7
+ }
8
+ export interface ContextManagerOptions {
9
+ directory: string;
10
+ debug?: boolean;
11
+ debounceMs?: number;
12
+ enableWatcher?: boolean;
13
+ onIndexUpdate?: (event: IndexUpdateEvent) => void;
14
+ }
15
+ export interface ContextManager {
16
+ context: DirectContext;
17
+ directory: string;
18
+ search: (query: string) => Promise<string>;
19
+ searchAndAsk: (query: string, question?: string) => Promise<string>;
20
+ close: () => Promise<void>;
21
+ getIndexedFileCount: () => number;
22
+ }
23
+ /**
24
+ * Creates a DirectContext with optional file watching for incremental updates.
25
+ *
26
+ * This approach:
27
+ * 1. Initially indexes all files in the directory
28
+ * 2. Optionally watches for file changes using chokidar
29
+ * 3. Incrementally updates the index when files change
30
+ * 4. Debounces rapid changes to avoid thrashing
31
+ */
32
+ export declare function createContextManager(options: ContextManagerOptions): Promise<ContextManager>;
33
+ //# sourceMappingURL=context-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-manager.d.ts","sourceRoot":"","sources":["../../src/utils/context-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAMxD,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAE1E,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,aAAa,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B,mBAAmB,EAAE,MAAM,MAAM,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgQlG"}
@@ -0,0 +1,244 @@
1
+ import { DirectContext } from "@augmentcode/auggie-sdk";
2
+ import * as chokidar from "chokidar";
3
+ import * as path from "path";
4
+ import { walkDirectory, readFileForIndex, shouldIgnorePath } from "./file-walker.js";
5
+ import { debug as debugLog } from "./output.js";
6
+ /**
7
+ * Creates a DirectContext with optional file watching for incremental updates.
8
+ *
9
+ * This approach:
10
+ * 1. Initially indexes all files in the directory
11
+ * 2. Optionally watches for file changes using chokidar
12
+ * 3. Incrementally updates the index when files change
13
+ * 4. Debounces rapid changes to avoid thrashing
14
+ */
15
+ export async function createContextManager(options) {
16
+ const { directory, debug = false, debounceMs = 1000, enableWatcher = false, onIndexUpdate } = options;
17
+ const log = debug ? (msg) => debugLog(msg) : () => { };
18
+ log("Creating DirectContext...");
19
+ const context = await DirectContext.create({ debug });
20
+ log("DirectContext created");
21
+ // Track indexed files and pending updates
22
+ const indexedPaths = new Set();
23
+ const pendingAdds = new Map();
24
+ const pendingRemoves = new Set();
25
+ let debounceTimer = null;
26
+ let isProcessingUpdates = false;
27
+ let watcher = null;
28
+ // Track which files are new vs changed
29
+ const newFiles = new Set();
30
+ /**
31
+ * Emit an index update event
32
+ */
33
+ function emitUpdate(type, files) {
34
+ if (onIndexUpdate && files.length > 0) {
35
+ onIndexUpdate({
36
+ type,
37
+ files,
38
+ totalIndexed: indexedPaths.size,
39
+ });
40
+ }
41
+ }
42
+ /**
43
+ * Process pending file updates (debounced)
44
+ */
45
+ async function processPendingUpdates() {
46
+ if (isProcessingUpdates) {
47
+ return;
48
+ }
49
+ isProcessingUpdates = true;
50
+ try {
51
+ // Collect updates to process
52
+ const filesToAdd = Array.from(pendingAdds.values());
53
+ const filesToRemove = Array.from(pendingRemoves);
54
+ // Separate new files from changed files
55
+ const addedFiles = [];
56
+ const changedFiles = [];
57
+ for (const file of filesToAdd) {
58
+ if (newFiles.has(file.path)) {
59
+ addedFiles.push(file.path);
60
+ newFiles.delete(file.path);
61
+ }
62
+ else {
63
+ changedFiles.push(file.path);
64
+ }
65
+ }
66
+ // Clear pending queues
67
+ pendingAdds.clear();
68
+ pendingRemoves.clear();
69
+ // Process removals first
70
+ if (filesToRemove.length > 0) {
71
+ log(`Removing ${filesToRemove.length} files from index`);
72
+ try {
73
+ await context.removeFromIndex(filesToRemove);
74
+ for (const filePath of filesToRemove) {
75
+ indexedPaths.delete(filePath);
76
+ }
77
+ log(`Removed ${filesToRemove.length} files`);
78
+ emitUpdate("removed", filesToRemove);
79
+ }
80
+ catch (error) {
81
+ log(`Error removing files: ${error}`);
82
+ }
83
+ }
84
+ // Process additions
85
+ if (filesToAdd.length > 0) {
86
+ log(`Adding/updating ${filesToAdd.length} files in index`);
87
+ try {
88
+ await context.addToIndex(filesToAdd, { waitForIndexing: true });
89
+ for (const file of filesToAdd) {
90
+ indexedPaths.add(file.path);
91
+ }
92
+ log(`Added/updated ${filesToAdd.length} files`);
93
+ // Emit separate events for added vs changed
94
+ if (addedFiles.length > 0) {
95
+ emitUpdate("added", addedFiles);
96
+ }
97
+ if (changedFiles.length > 0) {
98
+ emitUpdate("changed", changedFiles);
99
+ }
100
+ }
101
+ catch (error) {
102
+ log(`Error adding files: ${error}`);
103
+ }
104
+ }
105
+ }
106
+ finally {
107
+ isProcessingUpdates = false;
108
+ }
109
+ }
110
+ /**
111
+ * Schedule a debounced update
112
+ */
113
+ function scheduleUpdate() {
114
+ if (debounceTimer) {
115
+ clearTimeout(debounceTimer);
116
+ }
117
+ debounceTimer = setTimeout(() => {
118
+ processPendingUpdates().catch((error) => {
119
+ log(`Error processing updates: ${error}`);
120
+ });
121
+ }, debounceMs);
122
+ }
123
+ /**
124
+ * Queue a file for addition/update
125
+ */
126
+ function queueFileAdd(relativePath, isNew) {
127
+ // Check if path should be ignored
128
+ if (shouldIgnorePath(directory, relativePath)) {
129
+ log(`Ignoring file change: ${relativePath}`);
130
+ return;
131
+ }
132
+ const file = readFileForIndex(directory, relativePath, { debug });
133
+ if (file) {
134
+ // If file was queued for removal, cancel that
135
+ pendingRemoves.delete(file.path);
136
+ pendingAdds.set(file.path, file);
137
+ if (isNew) {
138
+ newFiles.add(file.path);
139
+ }
140
+ log(`Queued for ${isNew ? "add" : "update"}: ${relativePath}`);
141
+ scheduleUpdate();
142
+ }
143
+ }
144
+ /**
145
+ * Queue a file for removal
146
+ */
147
+ function queueFileRemove(relativePath) {
148
+ const normalizedPath = relativePath.replace(/\\/g, "/");
149
+ // Only queue for removal if it was indexed
150
+ if (indexedPaths.has(normalizedPath)) {
151
+ // If file was queued for addition, cancel that
152
+ pendingAdds.delete(normalizedPath);
153
+ newFiles.delete(normalizedPath);
154
+ pendingRemoves.add(normalizedPath);
155
+ log(`Queued for removal: ${relativePath}`);
156
+ scheduleUpdate();
157
+ }
158
+ }
159
+ // Initial indexing
160
+ log("Performing initial index of directory...");
161
+ const files = await walkDirectory(directory, { debug });
162
+ log(`Found ${files.length} files to index`);
163
+ if (files.length > 0) {
164
+ log("Adding files to index...");
165
+ await context.addToIndex(files, { waitForIndexing: true });
166
+ for (const file of files) {
167
+ indexedPaths.add(file.path);
168
+ }
169
+ log(`Indexed ${files.length} files`);
170
+ }
171
+ // Set up file watcher if enabled
172
+ if (enableWatcher) {
173
+ log("Setting up file watcher...");
174
+ watcher = chokidar.watch(directory, {
175
+ ignored: [
176
+ "**/node_modules/**",
177
+ "**/.git/**",
178
+ "**/dist/**",
179
+ "**/build/**",
180
+ "**/.next/**",
181
+ "**/.nuxt/**",
182
+ "**/coverage/**",
183
+ "**/__pycache__/**",
184
+ "**/.pytest_cache/**",
185
+ "**/.venv/**",
186
+ "**/venv/**",
187
+ ],
188
+ persistent: true,
189
+ ignoreInitial: true,
190
+ awaitWriteFinish: {
191
+ stabilityThreshold: 300,
192
+ pollInterval: 100,
193
+ },
194
+ });
195
+ watcher.on("add", (filePath) => {
196
+ const relativePath = path.relative(directory, filePath);
197
+ log(`File added: ${relativePath}`);
198
+ queueFileAdd(relativePath, true);
199
+ });
200
+ watcher.on("change", (filePath) => {
201
+ const relativePath = path.relative(directory, filePath);
202
+ log(`File changed: ${relativePath}`);
203
+ queueFileAdd(relativePath, false);
204
+ });
205
+ watcher.on("unlink", (filePath) => {
206
+ const relativePath = path.relative(directory, filePath);
207
+ log(`File removed: ${relativePath}`);
208
+ queueFileRemove(relativePath);
209
+ });
210
+ watcher.on("error", (error) => {
211
+ log(`Watcher error: ${error.message}`);
212
+ });
213
+ log("File watcher initialized");
214
+ }
215
+ // Return context manager interface
216
+ return {
217
+ context,
218
+ directory,
219
+ async search(query) {
220
+ return context.search(query);
221
+ },
222
+ async searchAndAsk(query, question) {
223
+ return context.searchAndAsk(query, question);
224
+ },
225
+ getIndexedFileCount() {
226
+ return indexedPaths.size;
227
+ },
228
+ async close() {
229
+ log("Closing context manager...");
230
+ // Stop the file watcher if it exists
231
+ if (watcher) {
232
+ await watcher.close();
233
+ log("File watcher closed");
234
+ }
235
+ // Clear any pending debounce timer
236
+ if (debounceTimer) {
237
+ clearTimeout(debounceTimer);
238
+ debounceTimer = null;
239
+ }
240
+ log("Context manager closed");
241
+ },
242
+ };
243
+ }
244
+ //# sourceMappingURL=context-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-manager.js","sourceRoot":"","sources":["../../src/utils/context-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { type ContextManager, type IndexUpdateEvent } from "./context-manager.js";
2
+ export type { IndexUpdateEvent };
3
+ /**
4
+ * Initialize and return the context manager.
5
+ * Caches the context for the session to avoid re-indexing.
6
+ */
7
+ export declare function getContext(directory: string, enableWatcher?: boolean): Promise<ContextManager>;
8
+ /**
9
+ * Close the context manager and clean up resources.
10
+ */
11
+ export declare function closeContext(): Promise<void>;
12
+ /**
13
+ * Perform a semantic search on the codebase.
14
+ */
15
+ export declare function search(directory: string, query: string): Promise<string>;
16
+ /**
17
+ * Ask a question about the codebase.
18
+ */
19
+ export declare function ask(directory: string, question: string): Promise<string>;
20
+ /**
21
+ * Create a context manager with file watching enabled and an update callback.
22
+ * Used by the watch command.
23
+ */
24
+ export declare function createWatchContext(directory: string, onIndexUpdate: (event: IndexUpdateEvent) => void): Promise<ContextManager>;
25
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAKxG,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC;;;GAGG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,GAAE,OAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAwC3G;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAUlD;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY9E;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAY9E;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,GAC/C,OAAO,CAAC,cAAc,CAAC,CAiCzB"}
@@ -0,0 +1,132 @@
1
+ import { createContextManager } from "./context-manager.js";
2
+ import { debug, printAuthError } from "./output.js";
3
+ let contextManager = null;
4
+ /**
5
+ * Initialize and return the context manager.
6
+ * Caches the context for the session to avoid re-indexing.
7
+ */
8
+ export async function getContext(directory, enableWatcher = false) {
9
+ // Return cached context if same directory
10
+ if (contextManager && contextManager.directory === directory) {
11
+ debug("Using cached context manager");
12
+ return contextManager;
13
+ }
14
+ // Close existing context if switching directories
15
+ if (contextManager) {
16
+ debug("Closing existing context manager for directory switch");
17
+ await closeContext();
18
+ }
19
+ debug(`Creating context manager for: ${directory}`);
20
+ try {
21
+ contextManager = await createContextManager({
22
+ directory,
23
+ debug: false, // Debug is controlled by initOutput
24
+ debounceMs: 1000,
25
+ enableWatcher,
26
+ });
27
+ debug(`Context manager created successfully (${contextManager.getIndexedFileCount()} files indexed)`);
28
+ return contextManager;
29
+ }
30
+ catch (error) {
31
+ const errorMessage = error instanceof Error ? error.message : String(error);
32
+ // Check for common auth errors
33
+ if (errorMessage.includes("auth") ||
34
+ errorMessage.includes("login") ||
35
+ errorMessage.includes("token") ||
36
+ errorMessage.includes("unauthorized") ||
37
+ errorMessage.includes("API key")) {
38
+ printAuthError();
39
+ }
40
+ throw new Error(`Failed to initialize codebase context: ${errorMessage}`);
41
+ }
42
+ }
43
+ /**
44
+ * Close the context manager and clean up resources.
45
+ */
46
+ export async function closeContext() {
47
+ if (contextManager) {
48
+ debug("Closing context manager");
49
+ try {
50
+ await contextManager.close();
51
+ }
52
+ catch (error) {
53
+ debug(`Error closing context: ${error}`);
54
+ }
55
+ contextManager = null;
56
+ }
57
+ }
58
+ /**
59
+ * Perform a semantic search on the codebase.
60
+ */
61
+ export async function search(directory, query) {
62
+ const ctx = await getContext(directory);
63
+ debug(`Searching for: ${query}`);
64
+ try {
65
+ const results = await ctx.search(query);
66
+ debug(`Search returned ${results.length} characters`);
67
+ return results;
68
+ }
69
+ catch (error) {
70
+ const errorMessage = error instanceof Error ? error.message : String(error);
71
+ throw new Error(`Search failed: ${errorMessage}`);
72
+ }
73
+ }
74
+ /**
75
+ * Ask a question about the codebase.
76
+ */
77
+ export async function ask(directory, question) {
78
+ const ctx = await getContext(directory);
79
+ debug(`Asking: ${question}`);
80
+ try {
81
+ const answer = await ctx.searchAndAsk(question);
82
+ debug(`Answer returned ${answer.length} characters`);
83
+ return answer;
84
+ }
85
+ catch (error) {
86
+ const errorMessage = error instanceof Error ? error.message : String(error);
87
+ throw new Error(`Question failed: ${errorMessage}`);
88
+ }
89
+ }
90
+ /**
91
+ * Create a context manager with file watching enabled and an update callback.
92
+ * Used by the watch command.
93
+ */
94
+ export async function createWatchContext(directory, onIndexUpdate) {
95
+ // Close any existing context
96
+ if (contextManager) {
97
+ await closeContext();
98
+ }
99
+ debug(`Creating watch context manager for: ${directory}`);
100
+ try {
101
+ contextManager = await createContextManager({
102
+ directory,
103
+ debug: false,
104
+ debounceMs: 1000,
105
+ enableWatcher: true,
106
+ onIndexUpdate,
107
+ });
108
+ debug(`Watch context manager created successfully (${contextManager.getIndexedFileCount()} files indexed)`);
109
+ return contextManager;
110
+ }
111
+ catch (error) {
112
+ const errorMessage = error instanceof Error ? error.message : String(error);
113
+ if (errorMessage.includes("auth") ||
114
+ errorMessage.includes("login") ||
115
+ errorMessage.includes("token") ||
116
+ errorMessage.includes("unauthorized") ||
117
+ errorMessage.includes("API key")) {
118
+ printAuthError();
119
+ }
120
+ throw new Error(`Failed to initialize codebase context: ${errorMessage}`);
121
+ }
122
+ }
123
+ // Register cleanup handlers
124
+ process.on("SIGINT", async () => {
125
+ await closeContext();
126
+ process.exit(0);
127
+ });
128
+ process.on("SIGTERM", async () => {
129
+ await closeContext();
130
+ process.exit(0);
131
+ });
132
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/utils/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAA8C,MAAM,sBAAsB,CAAC;AACxG,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEpD,IAAI,cAAc,GAA0B,IAAI,CAAC;AAIjD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAAiB,EAAE,gBAAyB,KAAK;IAChF,0CAA0C;IAC1C,IAAI,cAAc,IAAI,cAAc,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC7D,KAAK,CAAC,8BAA8B,CAAC,CAAC;QACtC,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,kDAAkD;IAClD,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC/D,MAAM,YAAY,EAAE,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,iCAAiC,SAAS,EAAE,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,cAAc,GAAG,MAAM,oBAAoB,CAAC;YAC1C,SAAS;YACT,KAAK,EAAE,KAAK,EAAE,oCAAoC;YAClD,UAAU,EAAE,IAAI;YAChB,aAAa;SACd,CAAC,CAAC;QACH,KAAK,CAAC,yCAAyC,cAAc,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;QACtG,OAAO,cAAc,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE5E,+BAA+B;QAC/B,IACE,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC7B,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC9B,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC9B,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC;YACrC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,EAChC,CAAC;YACD,cAAc,EAAE,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,0CAA0C,YAAY,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,CAAC,yBAAyB,CAAC,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,cAAc,CAAC,KAAK,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;QAC3C,CAAC;QACD,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,SAAiB,EAAE,KAAa;IAC3D,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC;IACxC,KAAK,CAAC,kBAAkB,KAAK,EAAE,CAAC,CAAC;IAEjC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACxC,KAAK,CAAC,mBAAmB,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC;QACtD,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,IAAI,KAAK,CAAC,kBAAkB,YAAY,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,SAAiB,EAAE,QAAgB;IAC3D,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC;IACxC,KAAK,CAAC,WAAW,QAAQ,EAAE,CAAC,CAAC;IAE7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAChD,KAAK,CAAC,mBAAmB,MAAM,CAAC,MAAM,aAAa,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,IAAI,KAAK,CAAC,oBAAoB,YAAY,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,SAAiB,EACjB,aAAgD;IAEhD,6BAA6B;IAC7B,IAAI,cAAc,EAAE,CAAC;QACnB,MAAM,YAAY,EAAE,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,uCAAuC,SAAS,EAAE,CAAC,CAAC;IAE1D,IAAI,CAAC;QACH,cAAc,GAAG,MAAM,oBAAoB,CAAC;YAC1C,SAAS;YACT,KAAK,EAAE,KAAK;YACZ,UAAU,EAAE,IAAI;YAChB,aAAa,EAAE,IAAI;YACnB,aAAa;SACd,CAAC,CAAC;QACH,KAAK,CAAC,+CAA+C,cAAc,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;QAC5G,OAAO,cAAc,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAE5E,IACE,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC7B,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC9B,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC;YAC9B,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC;YACrC,YAAY,CAAC,QAAQ,CAAC,SAAS,CAAC,EAChC,CAAC;YACD,cAAc,EAAE,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,0CAA0C,YAAY,EAAE,CAAC,CAAC;IAC5E,CAAC;AACH,CAAC;AAED,4BAA4B;AAC5B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;IAC9B,MAAM,YAAY,EAAE,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;IAC/B,MAAM,YAAY,EAAE,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface IndexableFile {
2
+ path: string;
3
+ contents: string;
4
+ }
5
+ export interface FileWalkerOptions {
6
+ debug?: boolean;
7
+ }
8
+ /**
9
+ * Recursively walk a directory and collect indexable files
10
+ */
11
+ export declare function walkDirectory(directory: string, options?: FileWalkerOptions): Promise<IndexableFile[]>;
12
+ /**
13
+ * Read a single file for indexing
14
+ */
15
+ export declare function readFileForIndex(directory: string, relativePath: string, options?: FileWalkerOptions): IndexableFile | null;
16
+ /**
17
+ * Check if a path should be ignored based on ignore patterns
18
+ */
19
+ export declare function shouldIgnorePath(directory: string, relativePath: string): boolean;
20
+ //# sourceMappingURL=file-walker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-walker.d.ts","sourceRoot":"","sources":["../../src/utils/file-walker.ts"],"names":[],"mappings":"AAqDA,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAyDD;;GAEG;AACH,wBAAsB,aAAa,CACjC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,aAAa,EAAE,CAAC,CAwF1B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,iBAAsB,GAC9B,aAAa,GAAG,IAAI,CAuDtB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAIjF"}