oncall-cli 2.0.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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +172 -0
  3. package/bin/oncall.js +303 -0
  4. package/dist/api.d.ts +1 -0
  5. package/dist/api.js +23 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.js +91 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/code_hierarchy.d.ts +4 -0
  11. package/dist/code_hierarchy.js +92 -0
  12. package/dist/code_hierarchy.js.map +1 -0
  13. package/dist/config.d.ts +9 -0
  14. package/dist/config.js +12 -0
  15. package/dist/config.js.map +1 -0
  16. package/dist/helpers/cli-helpers.d.ts +22 -0
  17. package/dist/helpers/cli-helpers.js +261 -0
  18. package/dist/helpers/cli-helpers.js.map +1 -0
  19. package/dist/helpers/config-helpers.js +161 -0
  20. package/dist/helpers/ripgrep-tool.d.ts +15 -0
  21. package/dist/helpers/ripgrep-tool.js +110 -0
  22. package/dist/helpers/ripgrep-tool.js.map +1 -0
  23. package/dist/index.d.ts +3 -0
  24. package/dist/index.js +545 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/logsManager.d.ts +31 -0
  27. package/dist/logsManager.js +90 -0
  28. package/dist/logsManager.js.map +1 -0
  29. package/dist/tools/ripgrep.d.ts +15 -0
  30. package/dist/tools/ripgrep.js +110 -0
  31. package/dist/tools/ripgrep.js.map +1 -0
  32. package/dist/ui-graph.d.ts +1 -0
  33. package/dist/ui-graph.js +125 -0
  34. package/dist/ui-graph.js.map +1 -0
  35. package/dist/useWebSocket.d.ts +21 -0
  36. package/dist/useWebSocket.js +411 -0
  37. package/dist/useWebSocket.js.map +1 -0
  38. package/dist/utils/version-check.d.ts +2 -0
  39. package/dist/utils/version-check.js +124 -0
  40. package/dist/utils/version-check.js.map +1 -0
  41. package/dist/utils.d.ts +1 -0
  42. package/dist/utils.js +22 -0
  43. package/dist/utils.js.map +1 -0
  44. package/dist/websocket-server.d.ts +24 -0
  45. package/dist/websocket-server.js +221 -0
  46. package/dist/websocket-server.js.map +1 -0
  47. package/package.json +46 -0
@@ -0,0 +1,92 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { fileURLToPath } from "url";
4
+ import ignore from "ignore";
5
+ function findRoot(startDir) {
6
+ let current = startDir;
7
+ while (true) {
8
+ const gi = path.join(current, ".gitignore");
9
+ if (fs.existsSync(gi))
10
+ return current;
11
+ const parent = path.dirname(current);
12
+ if (parent === current)
13
+ return null;
14
+ current = parent;
15
+ }
16
+ }
17
+ function loadIgnoreMatcher(root) {
18
+ const ig = ignore();
19
+ const gitIgnorePath = path.join(root, ".gitignore");
20
+ if (fs.existsSync(gitIgnorePath)) {
21
+ const contents = fs.readFileSync(gitIgnorePath, "utf8");
22
+ ig.add(contents);
23
+ }
24
+ ig.add(".git/");
25
+ return ig;
26
+ }
27
+ function buildTree(root, dir, ig) {
28
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
29
+ const children = [];
30
+ for (const e of entries) {
31
+ const abs = path.join(dir, e.name);
32
+ const rel = path.relative(root, abs);
33
+ const relPosix = rel.replace(/\\/g, "/");
34
+ if (e.isDirectory()) {
35
+ const relDir = relPosix.endsWith("/") ? relPosix : relPosix + "/";
36
+ if (ig.ignores(relDir))
37
+ continue;
38
+ const child = buildTree(root, abs, ig);
39
+ children.push({ name: e.name, type: "dir", children: child.children });
40
+ }
41
+ else if (e.isFile()) {
42
+ if (ig.ignores(relPosix))
43
+ continue;
44
+ children.push({ name: e.name, type: "file" });
45
+ }
46
+ }
47
+ children.sort((a, b) => {
48
+ if (a.type !== b.type)
49
+ return a.type === "dir" ? -1 : 1;
50
+ return a.name.localeCompare(b.name);
51
+ });
52
+ return { name: path.basename(dir), type: "dir", children };
53
+ }
54
+ function toYaml(node, indent = 0) {
55
+ const pad = " ".repeat(indent);
56
+ if (node.type === "file") {
57
+ return `${pad}- ${node.name}`;
58
+ }
59
+ const header = `${pad}- ${node.name}/`;
60
+ if (!node.children || node.children.length === 0) {
61
+ return header;
62
+ }
63
+ const body = node.children
64
+ .map((child) => toYaml(child, indent + 1))
65
+ .join("\n");
66
+ return `${header}\n${body}`;
67
+ }
68
+ export function generateYaml(startDir = process.cwd()) {
69
+ const repoRoot = findRoot(startDir) || startDir;
70
+ const ig = loadIgnoreMatcher(repoRoot);
71
+ const tree = buildTree(repoRoot, repoRoot, ig);
72
+ const yaml = `project:\n${toYaml(tree, 1)}`;
73
+ return { yaml, root: repoRoot };
74
+ }
75
+ const isDirectRun = (() => {
76
+ try {
77
+ const thisFile = path.resolve(fileURLToPath(import.meta.url));
78
+ const invoked = process.argv[1] ? path.resolve(process.argv[1]) : "";
79
+ return thisFile === invoked;
80
+ }
81
+ catch {
82
+ return false;
83
+ }
84
+ })();
85
+ if (isDirectRun) {
86
+ const start = process.cwd();
87
+ const { yaml, root } = generateYaml(start);
88
+ const outPath = path.join(root, "hierarchy.yaml");
89
+ fs.writeFileSync(outPath, yaml + "\n", "utf8");
90
+ console.log(`Hierarchy written to ${outPath}`);
91
+ }
92
+ //# sourceMappingURL=code_hierarchy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code_hierarchy.js","sourceRoot":"","sources":["../code_hierarchy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare const config: {
2
+ redis_username: string;
3
+ redis_password: string;
4
+ redis_host: string;
5
+ redis_port: string;
6
+ websocket_url: string;
7
+ auth_key: string;
8
+ api_base_url: string;
9
+ };
package/dist/config.js ADDED
@@ -0,0 +1,12 @@
1
+ import dotenv from "dotenv";
2
+ dotenv.config();
3
+ export const config = {
4
+ redis_username: process.env.REDIS_USERNAME,
5
+ redis_password: process.env.REDIS_PASSWORD,
6
+ redis_host: process.env.REDIS_HOST,
7
+ redis_port: process.env.REDIS_PORT,
8
+ websocket_url: process.env.WEB_SOCKET_URL || "wss://api.oncall.build/v2/ws",
9
+ auth_key: process.env.AUTH_KEY,
10
+ api_base_url: process.env.API_BASE_URL || "https://api.oncall.build/v2/api",
11
+ };
12
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;IAC1C,cAAc,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;IAC1C,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;IAClC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;IAClC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,8BAA8B;IAC3E,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ;IAC9B,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,iCAAiC;CAC5E,CAAC"}
@@ -0,0 +1,22 @@
1
+ export function printHelp(): void;
2
+ export function ensureConfigDir(): void;
3
+ export function buildYaml(projectId: any, description: any, name: any): string;
4
+ export function loadProjectMetadata(cwdPath?: string): {
5
+ id: any;
6
+ description: any;
7
+ name: any;
8
+ window_id: number;
9
+ logs_available: any;
10
+ code_available: any;
11
+ path: string;
12
+ raw: string;
13
+ };
14
+ export function registerProjectWithCluster(metadata: any, clusterUrl?: string): Promise<any>;
15
+ export function fetchProjectsFromCluster(metadata: any, clusterUrl?: string): Promise<any>;
16
+ export function ensureClusterIsReady(metadata: any, registrationPromise: any): Promise<boolean>;
17
+ export function logd(d: any): void;
18
+ export const HOME_DIR: string;
19
+ export const ONCALL_DIR: string;
20
+ export const CONFIG_PATH: string;
21
+ export const LOGS_DIR: string;
22
+ export const CONFIG_TEMPLATE: "# OnCall Configuration File\n#\n# Place your OnCall API key here.\n# You can get a key from OnCall Web Studio.\n#\nAPI_KEY=\n\n# Project mappings (stored as JSON)\nprojects=[]\n";
@@ -0,0 +1,261 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import os from "os";
4
+ import WebSocket from "ws";
5
+ import YAML from "yaml";
6
+ export const HOME_DIR = os.homedir();
7
+ export const ONCALL_DIR = path.join(HOME_DIR, ".oncall");
8
+ export const CONFIG_PATH = path.join(ONCALL_DIR, "config");
9
+ export const LOGS_DIR = path.join(ONCALL_DIR, "logs");
10
+ export const CONFIG_TEMPLATE = `# OnCall Configuration File
11
+ #
12
+ # Place your OnCall API key here.
13
+ # You can get a key from OnCall Web Studio.
14
+ #
15
+ API_KEY=
16
+
17
+ # Project mappings (stored as JSON)
18
+ projects=[]
19
+ `;
20
+ export function printHelp() {
21
+ console.log(`
22
+ OnCall - Your AI-powered CLI Debugger
23
+
24
+ Usage:
25
+ oncall init [-id <project-id>] -m <description>
26
+ Initialize config and register this directory
27
+ oncall login <your-auth-key> Login to OnCall using your auth key
28
+ oncall cluster Start the lightweight local WebSocket server
29
+ Flags:
30
+ -h, --help Show help
31
+ -v, --version Show version
32
+ `);
33
+ }
34
+ export function ensureConfigDir() {
35
+ if (!fs.existsSync(ONCALL_DIR)) {
36
+ fs.mkdirSync(ONCALL_DIR, { recursive: true });
37
+ console.log(`✅ Created configuration directory: ${ONCALL_DIR}`);
38
+ }
39
+ }
40
+ export function buildYaml(projectId, description, name) {
41
+ const escape = (value) => value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
42
+ const lines = [
43
+ `id: "${escape(projectId)}"`,
44
+ `description: "${escape(description)}"`,
45
+ ];
46
+ if (name) {
47
+ lines.push(`name: "${escape(name)}"`);
48
+ }
49
+ const window_id = Date.now();
50
+ lines.push(`window_id: ${window_id}`);
51
+ lines.push(`logs_available: true`);
52
+ lines.push(`code_available: true`);
53
+ return `${lines.join("\n")}\n`;
54
+ }
55
+ export function loadProjectMetadata(cwdPath = process.cwd()) {
56
+ const yamlPath = path.join(cwdPath, "oncall.yaml");
57
+ if (!fs.existsSync(yamlPath)) {
58
+ return null;
59
+ }
60
+ try {
61
+ const contents = fs.readFileSync(yamlPath, "utf8");
62
+ const data = YAML.parse(contents);
63
+ if (!data?.id || !data?.description) {
64
+ console.warn('oncall.yaml is missing either "id" or "description". Proceeding without project metadata.');
65
+ return null;
66
+ }
67
+ return {
68
+ id: data?.id || "",
69
+ description: data?.description || "",
70
+ name: data?.name || "",
71
+ window_id: data?.window_id ? Number(data.window_id) : undefined,
72
+ logs_available: data?.logs_available || true,
73
+ code_available: data?.code_available || true,
74
+ path: cwdPath,
75
+ raw: contents,
76
+ };
77
+ }
78
+ catch (error) {
79
+ console.warn("Failed to read oncall.yaml. Proceeding without it.", error);
80
+ return null;
81
+ }
82
+ }
83
+ export function registerProjectWithCluster(metadata, clusterUrl = process.env.ONCALL_CLUSTER_URL || "ws://127.0.0.1:4466") {
84
+ return new Promise((resolve) => {
85
+ let settled = false;
86
+ let socket;
87
+ try {
88
+ socket = new WebSocket(clusterUrl);
89
+ }
90
+ catch (error) {
91
+ console.warn("Unable to connect to local cluster server. Continuing without registration.");
92
+ resolve(false);
93
+ return;
94
+ }
95
+ const cleanup = (result) => {
96
+ if (settled)
97
+ return;
98
+ settled = true;
99
+ clearTimeout(timeoutId);
100
+ try {
101
+ socket?.close();
102
+ }
103
+ catch {
104
+ // ignore
105
+ }
106
+ resolve(result);
107
+ };
108
+ const timeoutId = setTimeout(() => {
109
+ cleanup(false);
110
+ }, 2000);
111
+ socket.on("open", () => {
112
+ try {
113
+ const projectPayload = {
114
+ id: metadata.id,
115
+ description: metadata.description,
116
+ name: metadata.name,
117
+ path: metadata.path,
118
+ window_id: typeof metadata.window_id === "number"
119
+ ? metadata.window_id
120
+ : Date.now(),
121
+ logs_available: typeof metadata.logs_available === "boolean"
122
+ ? metadata.logs_available
123
+ : true,
124
+ code_available: typeof metadata.code_available === "boolean"
125
+ ? metadata.code_available
126
+ : true,
127
+ };
128
+ socket.send(JSON.stringify({
129
+ type: "register",
130
+ project: projectPayload,
131
+ }));
132
+ }
133
+ catch (error) {
134
+ console.warn("Failed to send register payload to local cluster server. Continuing without registration.");
135
+ cleanup(false);
136
+ }
137
+ });
138
+ socket.on("message", (data) => {
139
+ try {
140
+ const serialized = typeof data === "string" ? data : data.toString("utf8");
141
+ if (!serialized) {
142
+ return;
143
+ }
144
+ const parsed = JSON.parse(serialized);
145
+ if (parsed.type === "register_ack") {
146
+ cleanup(true);
147
+ }
148
+ }
149
+ catch {
150
+ // ignore malformed ack
151
+ }
152
+ });
153
+ socket.on("close", () => {
154
+ cleanup(true);
155
+ });
156
+ socket.on("error", () => {
157
+ cleanup(false);
158
+ });
159
+ });
160
+ }
161
+ export function fetchProjectsFromCluster(metadata, clusterUrl = process.env.ONCALL_CLUSTER_URL || "ws://127.0.0.1:4466") {
162
+ logd(`Called fetchProjects, ${JSON.stringify(metadata)}`);
163
+ return new Promise((resolve) => {
164
+ let settled = false;
165
+ let socket;
166
+ try {
167
+ logd(`connecting to socket cluster to fetch`);
168
+ socket = new WebSocket(clusterUrl);
169
+ }
170
+ catch (error) {
171
+ console.warn("Unable to connect to local cluster server. Could not fetch projects.");
172
+ logd("Unable to connect to local cluster server. Could not fetch projects.");
173
+ resolve(false);
174
+ return;
175
+ }
176
+ const cleanup = (result) => {
177
+ if (settled)
178
+ return;
179
+ settled = true;
180
+ clearTimeout(timeoutId);
181
+ try {
182
+ socket?.close();
183
+ }
184
+ catch {
185
+ // ignore
186
+ }
187
+ resolve(result);
188
+ };
189
+ const timeoutId = setTimeout(() => {
190
+ logd("Fetching projects timed out");
191
+ cleanup(false);
192
+ }, 2000);
193
+ socket.on("open", () => {
194
+ try {
195
+ socket.send(JSON.stringify({
196
+ type: "fetch_projects",
197
+ id: metadata.id,
198
+ }));
199
+ }
200
+ catch (error) {
201
+ console.warn("Failed to send request to local cluster server. Continuing without fetching projects.");
202
+ logd("error sending fetch_projects req to cluster");
203
+ cleanup(false);
204
+ }
205
+ });
206
+ socket.on("message", (data) => {
207
+ try {
208
+ const serialized = typeof data === "string" ? data : data.toString("utf8");
209
+ if (!serialized) {
210
+ return;
211
+ }
212
+ const parsed = JSON.parse(serialized);
213
+ if (parsed.type === "fetch_projects_ack") {
214
+ cleanup(parsed);
215
+ }
216
+ }
217
+ catch {
218
+ // ignore malformed ack
219
+ logd("Malformed ack");
220
+ }
221
+ });
222
+ socket.on("close", () => {
223
+ logd("Connection closed");
224
+ cleanup(false);
225
+ });
226
+ socket.on("error", () => {
227
+ logd("Connection errored");
228
+ cleanup(false);
229
+ });
230
+ });
231
+ }
232
+ export async function ensureClusterIsReady(metadata, registrationPromise) {
233
+ if (!metadata) {
234
+ await registrationPromise?.catch(() => null);
235
+ return true;
236
+ }
237
+ try {
238
+ const result = await registrationPromise;
239
+ return result !== false;
240
+ }
241
+ catch {
242
+ return false;
243
+ }
244
+ }
245
+ export function logd(d) {
246
+ // try {
247
+ // if (!fs.existsSync(LOGS_DIR)) {
248
+ // fs.mkdirSync(LOGS_DIR, { recursive: true });
249
+ // }
250
+ // const now = new Date();
251
+ // const day = String(now.getDate()).padStart(2, "0");
252
+ // const month = String(now.getMonth() + 1).padStart(2, "0");
253
+ // const year = String(now.getFullYear());
254
+ // const dateStr = `${day}${month}${year}`;
255
+ // const logFilePath = path.join(LOGS_DIR, `logs_${dateStr}.txt`);
256
+ // fs.appendFileSync(logFilePath, `${d}\n`);
257
+ // } catch (error) {
258
+ // console.error("Failed to log to logs file", error);
259
+ // }
260
+ }
261
+ //# sourceMappingURL=cli-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-helpers.js","sourceRoot":"","sources":["../../helpers/cli-helpers.js"],"names":[],"mappings":"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"}
@@ -0,0 +1,161 @@
1
+ import readline from 'readline';
2
+
3
+ function escapeRegExp(value) {
4
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
5
+ }
6
+
7
+ export function upsertConfigValue(contents, key, value) {
8
+ const keyRegex = new RegExp(`^${escapeRegExp(key)}\\s*=.*$`, 'm');
9
+ const nextLine = `${key}=${value}`;
10
+ if (keyRegex.test(contents)) {
11
+ return contents.replace(keyRegex, nextLine);
12
+ }
13
+ const trimmed = contents.trimEnd();
14
+ const prefix = trimmed.length > 0 ? `${trimmed}\n` : '';
15
+ return `${prefix}${nextLine}\n`;
16
+ }
17
+
18
+ export function readProjects(contents) {
19
+ const match = contents.match(/^projects\s*=\s*(\[.*\]|\{.*\})$/m);
20
+ if (!match) {
21
+ return [];
22
+ }
23
+ try {
24
+ const parsed = JSON.parse(match[1]);
25
+ if (Array.isArray(parsed)) {
26
+ return parsed;
27
+ }
28
+ return Object.entries(parsed).map(([id, list]) => ({
29
+ id,
30
+ projects: Array.isArray(list) ? list : [],
31
+ }));
32
+ } catch (err) {
33
+ console.warn('⚠️ Failed to parse projects JSON; resetting to empty array.');
34
+ return [];
35
+ }
36
+ }
37
+
38
+ export function writeProjects(contents, projectsArr) {
39
+ const serialized = JSON.stringify(projectsArr);
40
+ return upsertConfigValue(contents, 'projects', serialized);
41
+ }
42
+
43
+ export function parseConfigFlags(argsList) {
44
+ let projectId = null;
45
+ let message = null;
46
+ for (let i = 1; i < argsList.length; i += 1) {
47
+ const token = argsList[i];
48
+ if (token === '-id') {
49
+ if (projectId !== null) {
50
+ console.error('❌ Duplicate -id flag detected.');
51
+ process.exit(1);
52
+ }
53
+ const next = argsList[i + 1];
54
+ if (!next) {
55
+ console.error('❌ Missing value for -id flag.');
56
+ process.exit(1);
57
+ }
58
+ projectId = next.trim();
59
+ i += 1;
60
+ } else if (token === '-m') {
61
+ if (message !== null) {
62
+ console.error('❌ Duplicate -m flag detected.');
63
+ process.exit(1);
64
+ }
65
+ const next = argsList[i + 1];
66
+ if (!next) {
67
+ console.error('❌ Missing value for -m flag.');
68
+ process.exit(1);
69
+ }
70
+ message = next.trim();
71
+ i += 1;
72
+ }
73
+ }
74
+ if (!message) {
75
+ console.error('❌ Description is required. Use -m <description>.');
76
+ process.exit(1);
77
+ }
78
+ return { projectId, message };
79
+ }
80
+
81
+ function prompt(question) {
82
+ const rl = readline.createInterface({
83
+ input: process.stdin,
84
+ output: process.stdout,
85
+ });
86
+ return new Promise((resolve) => {
87
+ rl.question(question, (answer) => {
88
+ rl.close();
89
+ resolve(answer.trim());
90
+ });
91
+ });
92
+ }
93
+
94
+ async function promptForNewProjectId(projectsList) {
95
+ while (true) {
96
+ const input = await prompt('Enter new project id: ');
97
+ if (!input) {
98
+ console.log('Project id cannot be empty.');
99
+ continue;
100
+ }
101
+ const exists = projectsList.some((entry) => entry.id === input);
102
+ if (exists) {
103
+ console.log('Project id already exists. Please choose a different id.');
104
+ continue;
105
+ }
106
+ return input;
107
+ }
108
+ }
109
+
110
+ async function promptForExistingProject(projectsList) {
111
+ console.log('\nAvailable projects:');
112
+ projectsList.forEach((entry, index) => {
113
+ console.log(` ${index + 1}. ${entry.id}`);
114
+ });
115
+ while (true) {
116
+ const input = await prompt('Select a project by number: ');
117
+ const choice = Number.parseInt(input, 10);
118
+ if (Number.isNaN(choice) || choice < 1 || choice > projectsList.length) {
119
+ console.log('Please enter a valid number from the list.');
120
+ continue;
121
+ }
122
+ return projectsList[choice - 1].id;
123
+ }
124
+ }
125
+
126
+ export async function resolveProjectId(initialId, projectsList) {
127
+ if (initialId) {
128
+ return initialId;
129
+ }
130
+
131
+ console.log('\nChoose an option:');
132
+ console.log(' 1. Create new project');
133
+ console.log(' 2. Use existing project');
134
+
135
+ while (true) {
136
+ const choice = await prompt('Enter choice (1 or 2): ');
137
+ if (choice === '1') {
138
+ return promptForNewProjectId(projectsList);
139
+ }
140
+ if (choice === '2') {
141
+ if (projectsList.length === 0) {
142
+ console.log('No existing projects found. Please create a new project.');
143
+ return promptForNewProjectId(projectsList);
144
+ }
145
+ return promptForExistingProject(projectsList);
146
+ }
147
+ console.log('Invalid choice. Please enter 1 or 2.');
148
+ }
149
+ }
150
+
151
+ export async function promptForInput(message) {
152
+ while (true) {
153
+ const input = await prompt(`${message} `);
154
+ if (!input) {
155
+ console.log('Project id cannot be empty.');
156
+ continue;
157
+ }
158
+ return input;
159
+ }
160
+ }
161
+
@@ -0,0 +1,15 @@
1
+ export interface RipgrepResult {
2
+ filePath: string;
3
+ line?: number | null;
4
+ preview?: string;
5
+ score?: number;
6
+ }
7
+ export interface RipgrepOptions {
8
+ maxResults?: number;
9
+ caseSensitive?: boolean;
10
+ fileTypes?: string[];
11
+ excludePatterns?: string[];
12
+ workingDirectory?: string;
13
+ }
14
+ export declare function ripgrepSearch(query: string, options?: RipgrepOptions): Promise<RipgrepResult[]>;
15
+ export declare function ripgrepSearchMultiple(queries: string[], options?: RipgrepOptions): Promise<RipgrepResult[]>;