fraude-code 0.1.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 (127) hide show
  1. package/README.md +68 -0
  2. package/dist/index.js +179297 -0
  3. package/package.json +88 -0
  4. package/src/agent/agent.ts +475 -0
  5. package/src/agent/contextManager.ts +141 -0
  6. package/src/agent/index.ts +14 -0
  7. package/src/agent/pendingChanges.ts +270 -0
  8. package/src/agent/prompts/AskPrompt.txt +10 -0
  9. package/src/agent/prompts/FastPrompt.txt +40 -0
  10. package/src/agent/prompts/PlannerPrompt.txt +51 -0
  11. package/src/agent/prompts/ReviewerPrompt.txt +57 -0
  12. package/src/agent/prompts/WorkerPrompt.txt +33 -0
  13. package/src/agent/subagents/askAgent.ts +37 -0
  14. package/src/agent/subagents/extractionAgent.ts +123 -0
  15. package/src/agent/subagents/fastAgent.ts +45 -0
  16. package/src/agent/subagents/managerAgent.ts +36 -0
  17. package/src/agent/subagents/relationAgent.ts +76 -0
  18. package/src/agent/subagents/researchSubAgent.ts +79 -0
  19. package/src/agent/subagents/reviewerSubAgent.ts +42 -0
  20. package/src/agent/subagents/workerSubAgent.ts +42 -0
  21. package/src/agent/tools/bashTool.ts +94 -0
  22. package/src/agent/tools/descriptions/bash.txt +47 -0
  23. package/src/agent/tools/descriptions/edit.txt +7 -0
  24. package/src/agent/tools/descriptions/glob.txt +4 -0
  25. package/src/agent/tools/descriptions/grep.txt +8 -0
  26. package/src/agent/tools/descriptions/lsp.txt +20 -0
  27. package/src/agent/tools/descriptions/plan.txt +3 -0
  28. package/src/agent/tools/descriptions/read.txt +9 -0
  29. package/src/agent/tools/descriptions/todo.txt +12 -0
  30. package/src/agent/tools/descriptions/write.txt +8 -0
  31. package/src/agent/tools/editTool.ts +44 -0
  32. package/src/agent/tools/globTool.ts +59 -0
  33. package/src/agent/tools/grepTool.ts +343 -0
  34. package/src/agent/tools/lspTool.ts +429 -0
  35. package/src/agent/tools/planTool.ts +118 -0
  36. package/src/agent/tools/readTool.ts +78 -0
  37. package/src/agent/tools/rememberTool.ts +91 -0
  38. package/src/agent/tools/testRunnerTool.ts +77 -0
  39. package/src/agent/tools/testTool.ts +44 -0
  40. package/src/agent/tools/todoTool.ts +224 -0
  41. package/src/agent/tools/writeTool.ts +33 -0
  42. package/src/commands/COMMANDS.ts +38 -0
  43. package/src/commands/cerebras/auth.ts +27 -0
  44. package/src/commands/cerebras/index.ts +31 -0
  45. package/src/commands/forget.ts +29 -0
  46. package/src/commands/google/auth.ts +24 -0
  47. package/src/commands/google/index.ts +31 -0
  48. package/src/commands/groq/add_model.ts +60 -0
  49. package/src/commands/groq/auth.ts +24 -0
  50. package/src/commands/groq/index.ts +33 -0
  51. package/src/commands/index.ts +65 -0
  52. package/src/commands/knowledge.ts +92 -0
  53. package/src/commands/log.ts +32 -0
  54. package/src/commands/mistral/auth.ts +27 -0
  55. package/src/commands/mistral/index.ts +31 -0
  56. package/src/commands/model/index.ts +145 -0
  57. package/src/commands/models/index.ts +16 -0
  58. package/src/commands/ollama/index.ts +29 -0
  59. package/src/commands/openrouter/add_model.ts +64 -0
  60. package/src/commands/openrouter/auth.ts +24 -0
  61. package/src/commands/openrouter/index.ts +33 -0
  62. package/src/commands/remember.ts +48 -0
  63. package/src/commands/serve.ts +31 -0
  64. package/src/commands/session/index.ts +21 -0
  65. package/src/commands/usage.ts +15 -0
  66. package/src/commands/visualize.ts +773 -0
  67. package/src/components/App.tsx +55 -0
  68. package/src/components/IntroComponent.tsx +70 -0
  69. package/src/components/LoaderComponent.tsx +68 -0
  70. package/src/components/OutputRenderer.tsx +88 -0
  71. package/src/components/SettingsRenderer.tsx +23 -0
  72. package/src/components/input/CommandSuggestions.tsx +41 -0
  73. package/src/components/input/FileSuggestions.tsx +61 -0
  74. package/src/components/input/InputBox.tsx +371 -0
  75. package/src/components/output/CheckpointView.tsx +13 -0
  76. package/src/components/output/CommandView.tsx +13 -0
  77. package/src/components/output/CommentView.tsx +12 -0
  78. package/src/components/output/ConfirmationView.tsx +179 -0
  79. package/src/components/output/ContextUsage.tsx +62 -0
  80. package/src/components/output/DiffView.tsx +202 -0
  81. package/src/components/output/ErrorView.tsx +14 -0
  82. package/src/components/output/InteractiveServerView.tsx +69 -0
  83. package/src/components/output/KnowledgeView.tsx +220 -0
  84. package/src/components/output/MarkdownView.tsx +15 -0
  85. package/src/components/output/ModelSelectView.tsx +71 -0
  86. package/src/components/output/ReasoningView.tsx +21 -0
  87. package/src/components/output/ToolCallView.tsx +45 -0
  88. package/src/components/settings/ModelList.tsx +250 -0
  89. package/src/components/settings/TokenUsage.tsx +274 -0
  90. package/src/config/schema.ts +19 -0
  91. package/src/config/settings.ts +229 -0
  92. package/src/index.tsx +100 -0
  93. package/src/parsers/tree-sitter-python.wasm +0 -0
  94. package/src/providers/providers.ts +71 -0
  95. package/src/services/PluginLoader.ts +123 -0
  96. package/src/services/cerebras.ts +69 -0
  97. package/src/services/embeddingService.ts +229 -0
  98. package/src/services/google.ts +65 -0
  99. package/src/services/graphSerializer.ts +248 -0
  100. package/src/services/groq.ts +23 -0
  101. package/src/services/knowledgeOrchestrator.ts +286 -0
  102. package/src/services/mistral.ts +79 -0
  103. package/src/services/ollama.ts +109 -0
  104. package/src/services/openrouter.ts +23 -0
  105. package/src/services/symbolExtractor.ts +277 -0
  106. package/src/store/useFraudeStore.ts +123 -0
  107. package/src/store/useSettingsStore.ts +38 -0
  108. package/src/theme.ts +26 -0
  109. package/src/types/Agent.ts +147 -0
  110. package/src/types/CommandDefinition.ts +8 -0
  111. package/src/types/Model.ts +94 -0
  112. package/src/types/OutputItem.ts +24 -0
  113. package/src/types/PluginContext.ts +55 -0
  114. package/src/types/TokenUsage.ts +5 -0
  115. package/src/types/assets.d.ts +4 -0
  116. package/src/utils/agentCognition.ts +1152 -0
  117. package/src/utils/fileSuggestions.ts +111 -0
  118. package/src/utils/index.ts +17 -0
  119. package/src/utils/initFraude.ts +8 -0
  120. package/src/utils/logger.ts +24 -0
  121. package/src/utils/lspClient.ts +1415 -0
  122. package/src/utils/paths.ts +24 -0
  123. package/src/utils/queryHandler.ts +227 -0
  124. package/src/utils/router.ts +278 -0
  125. package/src/utils/streamHandler.ts +132 -0
  126. package/src/utils/treeSitterQueries.ts +125 -0
  127. package/tsconfig.json +33 -0
@@ -0,0 +1,343 @@
1
+ import { tool } from "ai";
2
+ import { z } from "zod";
3
+ import { rgPath } from "@vscode/ripgrep";
4
+ import useFraudeStore from "@/store/useFraudeStore";
5
+ import pendingChanges from "@/agent/pendingChanges";
6
+ import DESCRIPTION from "./descriptions/grep.txt" with { type: "text" };
7
+
8
+ const { updateOutput } = useFraudeStore.getState();
9
+
10
+ const grepTool = tool({
11
+ description: DESCRIPTION,
12
+ strict: true,
13
+ inputSchema: z.object({
14
+ pattern: z
15
+ .string()
16
+ .describe("The regex pattern to search for in file contents"),
17
+ path: z
18
+ .string()
19
+ .optional()
20
+ .describe(
21
+ "The directory to search in. Defaults to the current working directory.",
22
+ ),
23
+ include: z
24
+ .string()
25
+ .optional()
26
+ .describe(
27
+ 'File pattern to include in the search (e.g. "*.js", "*.{ts,tsx}")',
28
+ ),
29
+ }),
30
+ execute: async ({
31
+ pattern,
32
+ path,
33
+ include,
34
+ }: {
35
+ pattern: string;
36
+ path?: string;
37
+ include?: string;
38
+ }) => {
39
+ updateOutput(
40
+ "toolCall",
41
+ JSON.stringify({
42
+ action: "Searching For " + pattern,
43
+ details: path,
44
+ }),
45
+ { dontOverride: true },
46
+ );
47
+ // Resolve path to absolute and normalize to handling trailing slashes/dots
48
+ const { resolve } = await import("path");
49
+ const cwd = path ? resolve(process.cwd(), path) : process.cwd();
50
+
51
+ // Step 1: Attempt RipGrep (Fastest + Respects .gitignore)
52
+ const rgResult = await runRipGrep(pattern, cwd, include);
53
+ if (rgResult) return formatOutput(rgResult);
54
+
55
+ // Step 2: Fallback to Git Grep
56
+ const gitResult = await runGitGrep(pattern, cwd, include);
57
+ if (gitResult) return formatOutput(gitResult);
58
+
59
+ // Step 3: Attempt System Grep (Fast, Standard)
60
+ const sysResult = await runSystemGrep(pattern, cwd, include);
61
+
62
+ // Combine results (prefer git/system, fallback to bun)
63
+ let results = sysResult || (await runBunGrep(pattern, cwd, include));
64
+
65
+ // --- Merge with Pending Changes ---
66
+ const regex = new RegExp(pattern);
67
+ const changes = pendingChanges.getChanges();
68
+ const processedFiles = new Set<string>();
69
+
70
+ for (const change of changes) {
71
+ // Skip if not in cwd or doesn't match include pattern (basic check)
72
+ // ideally we use minimatch here but for now basic string check
73
+ if (!change.path.startsWith(cwd)) continue;
74
+
75
+ processedFiles.add(change.path);
76
+
77
+ // Does the NEW content match?
78
+ if (regex.test(change.newContent)) {
79
+ // Add/Overwrite matches for this file
80
+ // First remove existing matches for this file from disk results
81
+ results = results.filter((r) => r.file !== change.path);
82
+
83
+ // Add new matches
84
+ const lines = change.newContent.split("\n");
85
+ lines.forEach((line, idx) => {
86
+ if (regex.test(line)) {
87
+ results.push({
88
+ file: change.path,
89
+ line: idx + 1,
90
+ content: line.trim(),
91
+ mtime: Date.now(), // It's fresh
92
+ });
93
+ }
94
+ });
95
+ } else {
96
+ // If known file but new content DOESN'T match, remove it from results
97
+ results = results.filter((r) => r.file !== change.path);
98
+ }
99
+ }
100
+
101
+ // Sort combined results
102
+ results.sort((a, b) => b.mtime - a.mtime);
103
+
104
+ updateOutput(
105
+ "toolCall",
106
+ JSON.stringify({
107
+ action: "Found " + results.length + " Match(es)",
108
+ details: pattern,
109
+ }),
110
+ { dontOverride: true },
111
+ );
112
+
113
+ return formatOutput(results);
114
+ },
115
+ });
116
+
117
+ // --- Internal Types ---
118
+ type MatchResult = {
119
+ file: string;
120
+ line?: number;
121
+ content: string;
122
+ mtime: number;
123
+ };
124
+
125
+ // --- Strategy 1: RipGrep ---
126
+ async function runRipGrep(
127
+ pattern: string,
128
+ cwd: string,
129
+ include?: string,
130
+ ): Promise<MatchResult[] | null> {
131
+ try {
132
+ // --vimgrep: file:line:column:text
133
+ // --color never: no ANSI codes
134
+ // --smart-case: case insensitive unless pattern has uppercase
135
+ const args = [
136
+ rgPath,
137
+ "--line-number",
138
+ "--no-heading",
139
+ "--color",
140
+ "never",
141
+ "--smart-case",
142
+ ];
143
+
144
+ // Add include pattern if specified
145
+ if (include) {
146
+ args.push("-g", include);
147
+ }
148
+
149
+ args.push(pattern, ".");
150
+
151
+ const proc = Bun.spawn(args, { cwd, stderr: "pipe" });
152
+ const text = await new Response(proc.stdout).text();
153
+
154
+ if ((await proc.exited) !== 0 && !text) return null; // No matches or error
155
+ return await parseAndStat(text, cwd);
156
+ } catch (e) {
157
+ return null;
158
+ }
159
+ }
160
+
161
+ // --- Strategy 1: Git Grep ---
162
+ async function runGitGrep(
163
+ pattern: string,
164
+ cwd: string,
165
+ include?: string,
166
+ ): Promise<MatchResult[] | null> {
167
+ // Check if we are in a git repo first to avoid noisy errors
168
+ const isGit =
169
+ (await Bun.spawn(["git", "rev-parse", "--is-inside-work-tree"], { cwd })
170
+ .exited) === 0;
171
+ if (!isGit) return null;
172
+
173
+ try {
174
+ // -I: Ignore binary, -n: Line numbers, --full-name: path relative to root
175
+ const args = ["git", "grep", "-I", "-n", "--full-name", pattern];
176
+
177
+ // Add include pattern if specified (git grep uses -- 'pattern' syntax)
178
+ if (include) {
179
+ args.push("--", include);
180
+ }
181
+
182
+ const proc = Bun.spawn(args, { cwd, stderr: "pipe" });
183
+ const text = await new Response(proc.stdout).text();
184
+
185
+ if ((await proc.exited) !== 0 && !text) return null; // No matches or error
186
+ return await parseAndStat(text, cwd);
187
+ } catch (e) {
188
+ return null;
189
+ }
190
+ }
191
+
192
+ // --- Strategy 2: System Grep ---
193
+ async function runSystemGrep(
194
+ pattern: string,
195
+ cwd: string,
196
+ include?: string,
197
+ ): Promise<MatchResult[] | null> {
198
+ try {
199
+ // -r: Recursive, -I: Ignore binary, -n: Line numbers
200
+ const args = ["grep", "-rIn"];
201
+
202
+ // Add include pattern if specified
203
+ if (include) {
204
+ args.push(`--include=${include}`);
205
+ }
206
+
207
+ args.push(pattern, ".");
208
+
209
+ const proc = Bun.spawn(args, {
210
+ cwd,
211
+ stderr: "pipe",
212
+ });
213
+ const text = await new Response(proc.stdout).text();
214
+
215
+ // Grep returns exit code 1 if no matches found (valid case)
216
+ if ((await proc.exited) === 1 && !text) return [];
217
+ if ((await proc.exited) !== 0) return null; // Real error
218
+
219
+ return await parseAndStat(text, cwd);
220
+ } catch (e) {
221
+ return null;
222
+ }
223
+ }
224
+
225
+ // --- Strategy 3: Bun Native (Fallback) ---
226
+ async function runBunGrep(
227
+ pattern: string,
228
+ cwd: string,
229
+ include?: string,
230
+ ): Promise<MatchResult[]> {
231
+ const { Glob } = await import("bun");
232
+ // Use include pattern if specified, otherwise match all files
233
+ const globPattern = include ? `**/${include}` : "**/*";
234
+ const glob = new Glob(globPattern);
235
+ const matches: MatchResult[] = [];
236
+
237
+ // Create a regex from the pattern
238
+ const regex = new RegExp(pattern);
239
+
240
+ // Simple ignore list (Simulating .gitignore)
241
+ // In a real app, you might parse .gitignore lines here
242
+ const IGNORE = ["node_modules", ".git", "dist", "build", ".lock"];
243
+
244
+ for await (const file of glob.scan({ cwd })) {
245
+ // 1. Manual Ignore Filter
246
+ if (IGNORE.some((ignore) => file.includes(ignore))) continue;
247
+
248
+ // 2. Read & Search
249
+ const f = Bun.file(`${cwd}/${file}`);
250
+
251
+ // Safety: Skip large files or binaries if possible (basic heuristic)
252
+ if (f.size > 1024 * 1024) continue;
253
+
254
+ const content = await f.text().catch(() => ""); // Handle read errors silently
255
+ if (!content) continue;
256
+
257
+ if (regex.test(content)) {
258
+ // 3. Get Stats
259
+ const mtime = await f.lastModified;
260
+
261
+ // 4. Extract Lines (Simulate grep output)
262
+ const lines = content.split("\n");
263
+ lines.forEach((lineContent, idx) => {
264
+ if (regex.test(lineContent)) {
265
+ matches.push({
266
+ file,
267
+ line: idx + 1,
268
+ content: lineContent.trim(),
269
+ mtime,
270
+ });
271
+ }
272
+ });
273
+ }
274
+ }
275
+
276
+ // Native matches need sorting too
277
+ return matches.sort((a, b) => b.mtime - a.mtime);
278
+ }
279
+
280
+ // --- Helper: Parse Grep Output & Attach Stats ---
281
+ async function parseAndStat(
282
+ rawOutput: string,
283
+ cwd: string,
284
+ ): Promise<MatchResult[]> {
285
+ const lines = rawOutput.trim().split("\n");
286
+ if (!lines.length || (lines.length === 1 && !lines[0])) return [];
287
+
288
+ // 1. Parse lines into objects
289
+ const parsed = lines
290
+ .map((line) => {
291
+ // Grep format: file:line:content
292
+ // We limit split to 3 parts to handle colons in the content
293
+ const parts = line.split(":");
294
+ if (parts.length < 3) return null;
295
+
296
+ return {
297
+ file: parts[0],
298
+ line: parseInt(parts[1]!, 10),
299
+ content: parts.slice(2).join(":").trim(),
300
+ };
301
+ })
302
+ .filter(Boolean) as Omit<MatchResult, "mtime">[];
303
+
304
+ // 2. Get unique files to stat (performance optimization)
305
+ const uniqueFiles = [...new Set(parsed.map((p) => p.file))];
306
+
307
+ // 3. Fetch mtimes in parallel
308
+ const mtimeMap = new Map<string, number>();
309
+ await Promise.all(
310
+ uniqueFiles.map(async (f) => {
311
+ const stats = await Bun.file(`${cwd}/${f}`).lastModified;
312
+ mtimeMap.set(f, stats);
313
+ }),
314
+ );
315
+
316
+ // 4. Attach mtime and Sort (Newest First)
317
+ return parsed
318
+ .map((p) => ({ ...p, mtime: mtimeMap.get(p.file) || 0 }))
319
+ .sort((a, b) => b.mtime - a.mtime);
320
+ }
321
+
322
+ // --- Helper: Format for LLM ---
323
+ function formatOutput(results: MatchResult[]): string {
324
+ if (results.length === 0) return "No matches found.";
325
+
326
+ const truncated = results.length > 200;
327
+ const displayResults = truncated ? results.slice(0, 200) : results;
328
+
329
+ let output = displayResults
330
+ .map(
331
+ (r) =>
332
+ `[${new Date(r.mtime).toISOString()}] ${r.file}:${r.line} ${r.content}`,
333
+ )
334
+ .join("\n");
335
+
336
+ if (truncated) {
337
+ output += `\n... (${results.length - 200} more matches truncated)`;
338
+ }
339
+
340
+ return output;
341
+ }
342
+
343
+ export default grepTool;