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.
- package/README.md +68 -0
- package/dist/index.js +179297 -0
- package/package.json +88 -0
- package/src/agent/agent.ts +475 -0
- package/src/agent/contextManager.ts +141 -0
- package/src/agent/index.ts +14 -0
- package/src/agent/pendingChanges.ts +270 -0
- package/src/agent/prompts/AskPrompt.txt +10 -0
- package/src/agent/prompts/FastPrompt.txt +40 -0
- package/src/agent/prompts/PlannerPrompt.txt +51 -0
- package/src/agent/prompts/ReviewerPrompt.txt +57 -0
- package/src/agent/prompts/WorkerPrompt.txt +33 -0
- package/src/agent/subagents/askAgent.ts +37 -0
- package/src/agent/subagents/extractionAgent.ts +123 -0
- package/src/agent/subagents/fastAgent.ts +45 -0
- package/src/agent/subagents/managerAgent.ts +36 -0
- package/src/agent/subagents/relationAgent.ts +76 -0
- package/src/agent/subagents/researchSubAgent.ts +79 -0
- package/src/agent/subagents/reviewerSubAgent.ts +42 -0
- package/src/agent/subagents/workerSubAgent.ts +42 -0
- package/src/agent/tools/bashTool.ts +94 -0
- package/src/agent/tools/descriptions/bash.txt +47 -0
- package/src/agent/tools/descriptions/edit.txt +7 -0
- package/src/agent/tools/descriptions/glob.txt +4 -0
- package/src/agent/tools/descriptions/grep.txt +8 -0
- package/src/agent/tools/descriptions/lsp.txt +20 -0
- package/src/agent/tools/descriptions/plan.txt +3 -0
- package/src/agent/tools/descriptions/read.txt +9 -0
- package/src/agent/tools/descriptions/todo.txt +12 -0
- package/src/agent/tools/descriptions/write.txt +8 -0
- package/src/agent/tools/editTool.ts +44 -0
- package/src/agent/tools/globTool.ts +59 -0
- package/src/agent/tools/grepTool.ts +343 -0
- package/src/agent/tools/lspTool.ts +429 -0
- package/src/agent/tools/planTool.ts +118 -0
- package/src/agent/tools/readTool.ts +78 -0
- package/src/agent/tools/rememberTool.ts +91 -0
- package/src/agent/tools/testRunnerTool.ts +77 -0
- package/src/agent/tools/testTool.ts +44 -0
- package/src/agent/tools/todoTool.ts +224 -0
- package/src/agent/tools/writeTool.ts +33 -0
- package/src/commands/COMMANDS.ts +38 -0
- package/src/commands/cerebras/auth.ts +27 -0
- package/src/commands/cerebras/index.ts +31 -0
- package/src/commands/forget.ts +29 -0
- package/src/commands/google/auth.ts +24 -0
- package/src/commands/google/index.ts +31 -0
- package/src/commands/groq/add_model.ts +60 -0
- package/src/commands/groq/auth.ts +24 -0
- package/src/commands/groq/index.ts +33 -0
- package/src/commands/index.ts +65 -0
- package/src/commands/knowledge.ts +92 -0
- package/src/commands/log.ts +32 -0
- package/src/commands/mistral/auth.ts +27 -0
- package/src/commands/mistral/index.ts +31 -0
- package/src/commands/model/index.ts +145 -0
- package/src/commands/models/index.ts +16 -0
- package/src/commands/ollama/index.ts +29 -0
- package/src/commands/openrouter/add_model.ts +64 -0
- package/src/commands/openrouter/auth.ts +24 -0
- package/src/commands/openrouter/index.ts +33 -0
- package/src/commands/remember.ts +48 -0
- package/src/commands/serve.ts +31 -0
- package/src/commands/session/index.ts +21 -0
- package/src/commands/usage.ts +15 -0
- package/src/commands/visualize.ts +773 -0
- package/src/components/App.tsx +55 -0
- package/src/components/IntroComponent.tsx +70 -0
- package/src/components/LoaderComponent.tsx +68 -0
- package/src/components/OutputRenderer.tsx +88 -0
- package/src/components/SettingsRenderer.tsx +23 -0
- package/src/components/input/CommandSuggestions.tsx +41 -0
- package/src/components/input/FileSuggestions.tsx +61 -0
- package/src/components/input/InputBox.tsx +371 -0
- package/src/components/output/CheckpointView.tsx +13 -0
- package/src/components/output/CommandView.tsx +13 -0
- package/src/components/output/CommentView.tsx +12 -0
- package/src/components/output/ConfirmationView.tsx +179 -0
- package/src/components/output/ContextUsage.tsx +62 -0
- package/src/components/output/DiffView.tsx +202 -0
- package/src/components/output/ErrorView.tsx +14 -0
- package/src/components/output/InteractiveServerView.tsx +69 -0
- package/src/components/output/KnowledgeView.tsx +220 -0
- package/src/components/output/MarkdownView.tsx +15 -0
- package/src/components/output/ModelSelectView.tsx +71 -0
- package/src/components/output/ReasoningView.tsx +21 -0
- package/src/components/output/ToolCallView.tsx +45 -0
- package/src/components/settings/ModelList.tsx +250 -0
- package/src/components/settings/TokenUsage.tsx +274 -0
- package/src/config/schema.ts +19 -0
- package/src/config/settings.ts +229 -0
- package/src/index.tsx +100 -0
- package/src/parsers/tree-sitter-python.wasm +0 -0
- package/src/providers/providers.ts +71 -0
- package/src/services/PluginLoader.ts +123 -0
- package/src/services/cerebras.ts +69 -0
- package/src/services/embeddingService.ts +229 -0
- package/src/services/google.ts +65 -0
- package/src/services/graphSerializer.ts +248 -0
- package/src/services/groq.ts +23 -0
- package/src/services/knowledgeOrchestrator.ts +286 -0
- package/src/services/mistral.ts +79 -0
- package/src/services/ollama.ts +109 -0
- package/src/services/openrouter.ts +23 -0
- package/src/services/symbolExtractor.ts +277 -0
- package/src/store/useFraudeStore.ts +123 -0
- package/src/store/useSettingsStore.ts +38 -0
- package/src/theme.ts +26 -0
- package/src/types/Agent.ts +147 -0
- package/src/types/CommandDefinition.ts +8 -0
- package/src/types/Model.ts +94 -0
- package/src/types/OutputItem.ts +24 -0
- package/src/types/PluginContext.ts +55 -0
- package/src/types/TokenUsage.ts +5 -0
- package/src/types/assets.d.ts +4 -0
- package/src/utils/agentCognition.ts +1152 -0
- package/src/utils/fileSuggestions.ts +111 -0
- package/src/utils/index.ts +17 -0
- package/src/utils/initFraude.ts +8 -0
- package/src/utils/logger.ts +24 -0
- package/src/utils/lspClient.ts +1415 -0
- package/src/utils/paths.ts +24 -0
- package/src/utils/queryHandler.ts +227 -0
- package/src/utils/router.ts +278 -0
- package/src/utils/streamHandler.ts +132 -0
- package/src/utils/treeSitterQueries.ts +125 -0
- 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;
|