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,14 @@
|
|
|
1
|
+
// Agent module exports
|
|
2
|
+
export { default as Agent } from "./agent";
|
|
3
|
+
|
|
4
|
+
export type {
|
|
5
|
+
AgentConfig,
|
|
6
|
+
AgentResponse,
|
|
7
|
+
StructuredAgentResponse,
|
|
8
|
+
ToolCallInfo,
|
|
9
|
+
StepInfo,
|
|
10
|
+
SimpleMessage,
|
|
11
|
+
AgentMessage,
|
|
12
|
+
MessageRole,
|
|
13
|
+
StructuredSchema,
|
|
14
|
+
} from "@/types/Agent";
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { structuredPatch } from "diff";
|
|
2
|
+
import { projectPath } from "@/utils";
|
|
3
|
+
import log from "@/utils/logger";
|
|
4
|
+
import { unlink } from "node:fs/promises";
|
|
5
|
+
import AgentCognition from "@/utils/agentCognition";
|
|
6
|
+
|
|
7
|
+
export interface Hunk {
|
|
8
|
+
oldStart: number;
|
|
9
|
+
oldLines: number;
|
|
10
|
+
newStart: number;
|
|
11
|
+
newLines: number;
|
|
12
|
+
lines: string[];
|
|
13
|
+
linedelimiters?: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DiffPatch {
|
|
17
|
+
oldFileName?: string;
|
|
18
|
+
newFileName?: string;
|
|
19
|
+
oldHeader?: string;
|
|
20
|
+
newHeader?: string;
|
|
21
|
+
hunks: Hunk[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface PendingChange {
|
|
25
|
+
id: string;
|
|
26
|
+
path: string;
|
|
27
|
+
type: "edit" | "write";
|
|
28
|
+
originalContent: string | null;
|
|
29
|
+
newContent: string;
|
|
30
|
+
diff: DiffPatch;
|
|
31
|
+
feedback?: string;
|
|
32
|
+
hidden?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class PendingChangesManager {
|
|
36
|
+
private changes: Map<string, PendingChange> = new Map();
|
|
37
|
+
|
|
38
|
+
public async addChange(
|
|
39
|
+
path: string,
|
|
40
|
+
newContent: string,
|
|
41
|
+
type: "edit" | "write",
|
|
42
|
+
options?: { hidden?: boolean },
|
|
43
|
+
): Promise<PendingChange> {
|
|
44
|
+
// Normalize to absolute path
|
|
45
|
+
if (!path.startsWith("/")) {
|
|
46
|
+
path = `${process.cwd()}/${path}`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Clean up any double slashes or .
|
|
50
|
+
// Ideally use path.resolve but simple string concat is often enough or import path module
|
|
51
|
+
const { resolve } = await import("path");
|
|
52
|
+
path = resolve(path);
|
|
53
|
+
|
|
54
|
+
// Check if there are existing changes for this path
|
|
55
|
+
const changesList = Array.from(this.changes.values());
|
|
56
|
+
const latestChange = changesList.reverse().find((c) => c.path === path);
|
|
57
|
+
// Inherit hidden status if strictly true (was created hidden)
|
|
58
|
+
// If explicitly provided in options, use that. Otherwise use inherited.
|
|
59
|
+
const isHidden = options?.hidden ?? latestChange?.hidden;
|
|
60
|
+
|
|
61
|
+
const originalContent = latestChange
|
|
62
|
+
? latestChange.newContent
|
|
63
|
+
: (await Bun.file(path).exists())
|
|
64
|
+
? await Bun.file(path).text()
|
|
65
|
+
: "";
|
|
66
|
+
|
|
67
|
+
// Create unified diff
|
|
68
|
+
// For new files, originalContent is empty string.
|
|
69
|
+
// We use path as both old and new filename for the patch header
|
|
70
|
+
const diff = structuredPatch(
|
|
71
|
+
projectPath(path),
|
|
72
|
+
projectPath(path),
|
|
73
|
+
originalContent || "",
|
|
74
|
+
newContent,
|
|
75
|
+
"",
|
|
76
|
+
"",
|
|
77
|
+
{ context: 2 },
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const change: PendingChange = {
|
|
81
|
+
id: crypto.randomUUID(),
|
|
82
|
+
path,
|
|
83
|
+
type,
|
|
84
|
+
originalContent: type === "edit" ? originalContent : null,
|
|
85
|
+
newContent,
|
|
86
|
+
diff,
|
|
87
|
+
hidden: isHidden,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
this.changes.set(change.id, change);
|
|
91
|
+
return change;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public getChange(id: string): PendingChange | undefined {
|
|
95
|
+
return this.changes.get(id);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public getChanges(): PendingChange[] {
|
|
99
|
+
return Array.from(this.changes.values()).filter((c) => !c.hidden);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public getAllChangesGrouped(): Record<string, PendingChange[]> {
|
|
103
|
+
const grouped: Record<string, PendingChange[]> = {};
|
|
104
|
+
for (const change of this.changes.values()) {
|
|
105
|
+
if (change.hidden) continue;
|
|
106
|
+
if (!grouped[change.path]) {
|
|
107
|
+
grouped[change.path] = [];
|
|
108
|
+
}
|
|
109
|
+
grouped[change.path]?.push(change);
|
|
110
|
+
}
|
|
111
|
+
return grouped;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
public hasChanges(): boolean {
|
|
115
|
+
return Array.from(this.changes.values()).some((c) => !c.hidden);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
public async applyChange(id: string): Promise<boolean> {
|
|
119
|
+
const change = this.changes.get(id);
|
|
120
|
+
if (!change) return false;
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
await Bun.write(change.path, change.newContent);
|
|
124
|
+
this.changes.delete(id);
|
|
125
|
+
log(`Applied change to ${change.path}`);
|
|
126
|
+
|
|
127
|
+
// Index the file to update knowledge graph
|
|
128
|
+
try {
|
|
129
|
+
const cognition = AgentCognition.getInstance();
|
|
130
|
+
await cognition.init();
|
|
131
|
+
// Fire and forget indexing to avoid blocking UI
|
|
132
|
+
cognition
|
|
133
|
+
.indexFile(change.path)
|
|
134
|
+
.catch((e) => log(`Indexing failed for ${change.path}: ${e}`));
|
|
135
|
+
} catch (e) {
|
|
136
|
+
log(`Failed to trigger indexing: ${e}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return true;
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (change) {
|
|
142
|
+
log(`Failed to apply change to ${change.path}: ${error}`);
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
public async applyAll(): Promise<void> {
|
|
149
|
+
for (const [id, change] of this.changes) {
|
|
150
|
+
if (change.hidden) continue;
|
|
151
|
+
await this.applyChange(id);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public async applyChangeTemporary(id: string): Promise<boolean> {
|
|
156
|
+
const change = this.changes.get(id);
|
|
157
|
+
if (!change) return false;
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
await Bun.write(change.path, change.newContent);
|
|
161
|
+
// Differs from applyChange: DOES NOT DELETE from this.changes
|
|
162
|
+
log(`Temporarily applied change to ${change.path}`);
|
|
163
|
+
return true;
|
|
164
|
+
} catch (error) {
|
|
165
|
+
if (change) {
|
|
166
|
+
log(`Failed to apply temporary change to ${change.path}: ${error}`);
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
public async applyAllTemporary(): Promise<void> {
|
|
173
|
+
log(`applyAllTemporary called with ${this.changes.size} changes`);
|
|
174
|
+
for (const id of this.changes.keys()) {
|
|
175
|
+
await this.applyChangeTemporary(id);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public async restoreChange(id: string): Promise<boolean> {
|
|
180
|
+
const change = this.changes.get(id);
|
|
181
|
+
if (!change) return false;
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
if (change.originalContent === null) {
|
|
185
|
+
// It was a new file, so delete it
|
|
186
|
+
const file = Bun.file(change.path);
|
|
187
|
+
if (await file.exists()) {
|
|
188
|
+
await unlink(change.path);
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
// Restore original content
|
|
192
|
+
await Bun.write(change.path, change.originalContent);
|
|
193
|
+
}
|
|
194
|
+
// Note: We do NOT delete the change from the map, because we are just reverting the disk state
|
|
195
|
+
// but keeping the "pending change" in memory (e.g. for further editing or final apply).
|
|
196
|
+
log(`Restored ${change.path}`);
|
|
197
|
+
return true;
|
|
198
|
+
} catch (error) {
|
|
199
|
+
log(`Failed to restore ${change.path}: ${error}`);
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
public async restoreAll(): Promise<void> {
|
|
205
|
+
log(`restoreAll called with ${this.changes.size} changes`);
|
|
206
|
+
// Restore in reverse order to correct handle multiple changes to the same file
|
|
207
|
+
const ids = Array.from(this.changes.keys()).reverse();
|
|
208
|
+
for (const id of ids) {
|
|
209
|
+
await this.restoreChange(id);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
public rejectChange(id: string): boolean {
|
|
214
|
+
return this.changes.delete(id);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
public rejectAll(): void {
|
|
218
|
+
this.changes.clear();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
public addFeedback(id: string, feedback: string): boolean {
|
|
222
|
+
const change = this.changes.get(id);
|
|
223
|
+
if (!change) return false;
|
|
224
|
+
|
|
225
|
+
change.feedback = feedback;
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public clear() {
|
|
230
|
+
this.changes.clear();
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Gets the content of a file, accounting for any pending changes.
|
|
234
|
+
* If there are pending changes, returns the new content of the most recent change.
|
|
235
|
+
* Otherwise, reads the file from disk.
|
|
236
|
+
*/
|
|
237
|
+
public async getLatestContent(path: string): Promise<string> {
|
|
238
|
+
// Check pending changes first (reverse order to find latest)
|
|
239
|
+
// We include hidden changes here because the agent (e.g., test runner)
|
|
240
|
+
// needs to see the "current state" including temporary files it just created.
|
|
241
|
+
const changes = Array.from(this.changes.values()).reverse();
|
|
242
|
+
const latestChange = changes.find((c) => c.path === path);
|
|
243
|
+
|
|
244
|
+
if (latestChange) {
|
|
245
|
+
return latestChange.newContent;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// If no pending changes, read from disk
|
|
249
|
+
const file = Bun.file(path);
|
|
250
|
+
if (await file.exists()) {
|
|
251
|
+
return await file.text();
|
|
252
|
+
}
|
|
253
|
+
return "";
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
public getDiffStats(diff: DiffPatch): { added: number; removed: number } {
|
|
257
|
+
let added = 0;
|
|
258
|
+
let removed = 0;
|
|
259
|
+
for (const hunk of diff.hunks) {
|
|
260
|
+
for (const line of hunk.lines) {
|
|
261
|
+
if (line.startsWith("+")) added++;
|
|
262
|
+
if (line.startsWith("-")) removed++;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return { added, removed };
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const pendingChanges = new PendingChangesManager();
|
|
270
|
+
export default pendingChanges;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
You are an expert software engineer. Your job is to answer the user's question without making any changes to the codebase.
|
|
2
|
+
|
|
3
|
+
**WORKFLOW:**
|
|
4
|
+
1. **Analyze** the request. Identify unknowns.
|
|
5
|
+
2. **Research** the unknowns. Use the tools provided to gather information about the codebase.
|
|
6
|
+
- Use glob tool to find files
|
|
7
|
+
- Use grep tool to search for specific patterns
|
|
8
|
+
- Use read tool to read specific files
|
|
9
|
+
- Use bash tool only to run commands that dont change the codebase like `ls`, `pwd`, `cat`, `echo`, etc. Dont use bash tool unless absolutely necessary.
|
|
10
|
+
3. **Answer** the question.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
You are an expert software engineer. Your job is to make changes to the codebase based on the user's request.
|
|
2
|
+
|
|
3
|
+
**WORKFLOW:**
|
|
4
|
+
|
|
5
|
+
## Phase 1: Research
|
|
6
|
+
1. **Analyze** the request. Identify unknowns.
|
|
7
|
+
2. **Research** any information needed to complete the request using researchSubAgentTool: Which files? How does current implementation work? Dependencies?
|
|
8
|
+
- CHECK HISTORY: Have you already researched this? If yes, use those facts.
|
|
9
|
+
- BATCH QUERIES: Ask for all related file context in one go if possible.
|
|
10
|
+
- DO NOT repeat the same query twice.
|
|
11
|
+
|
|
12
|
+
## Phase 2: Implementation
|
|
13
|
+
Now that you have all the information you need, you can implement the changes.
|
|
14
|
+
**Complete Request** using the tools provided.
|
|
15
|
+
- Prioritize using the `editTool` to modify existing files
|
|
16
|
+
- Use `writeTool` if you need to create a new file
|
|
17
|
+
|
|
18
|
+
## Phase 3: Testing
|
|
19
|
+
Determine if automated testing is possible:
|
|
20
|
+
|
|
21
|
+
**IF testable programmatically:**
|
|
22
|
+
1. Use the `testTool` to create a temporary test script (e.g., `temp_test_<task_name>.ts`).
|
|
23
|
+
|
|
24
|
+
2. Run the test using `testRunnerTool`.
|
|
25
|
+
- `testRunnerTool` will temporarily apply your pending changes, run the command, and then revert the disk state.
|
|
26
|
+
- This ensures you are testing the code AS MODIFIED but keeping the environment clean.
|
|
27
|
+
- **Ensure Correct Imports:** Since tests run in a temporary context or subdirectory, relative imports must be handled carefully.
|
|
28
|
+
- **Python:** Add the project root to `sys.path` before importing.
|
|
29
|
+
```python
|
|
30
|
+
import sys; import os
|
|
31
|
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
32
|
+
```
|
|
33
|
+
- **Node/TS:** Use correct relative paths (e.g., `import { foo } from "../src/foo"`) or ensure `tsconfig.json` paths are respected by the runner (e.g., using `bun test`).
|
|
34
|
+
|
|
35
|
+
3. Capture and analyze output
|
|
36
|
+
4. **Refine Test:** If the test failed due to a syntax error or logic issue IN THE TEST ITSELF (not the code being tested), you can run `testTool` again with the same path to overwrite/fix the test file.
|
|
37
|
+
|
|
38
|
+
**IF NOT testable programmatically** (UI changes, config changes, env-dependent):
|
|
39
|
+
1. Document what manual verification is needed
|
|
40
|
+
2. Note specific steps the user should take to verify
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
You are a Lead Architect creating implementation plans. Analyze → Research → Plan → Create tasks. You do NOT execute code.
|
|
2
|
+
|
|
3
|
+
**WORKFLOW:**
|
|
4
|
+
1. **Analyze** the request. Identify unknowns.
|
|
5
|
+
2. **Research** using researchSubAgentTool: Which files? How does current implementation work? Dependencies?
|
|
6
|
+
- CHECK HISTORY: Have you already researched this? If yes, use those facts.
|
|
7
|
+
- BATCH QUERIES: Ask for all related file context in one go if possible.
|
|
8
|
+
- DO NOT repeat the same query twice.
|
|
9
|
+
3. **Create plan** using planTool: objective, file paths, approach.
|
|
10
|
+
4. **Create tasks** using todoTool—one atomic task per change.
|
|
11
|
+
5. **FINISH** Once you have created all tasks, STOP.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
**TASK RULES (VIOLATIONS = WORKER FAILURE)**
|
|
16
|
+
|
|
17
|
+
Workers execute in **parallel with zero shared context**. No chat history. No research results. No execution order.
|
|
18
|
+
|
|
19
|
+
**Atomic tasks:**
|
|
20
|
+
- ONE change, ONE file, ONE concern per task
|
|
21
|
+
- "and" in description → split into separate tasks
|
|
22
|
+
|
|
23
|
+
**Isolation test:** "Can this task succeed if run first, alone?"
|
|
24
|
+
- GOOD: `"Add User type to src/types/User.ts"`
|
|
25
|
+
- BAD: `"Use the User type from Task 1"` (dependency = failure)
|
|
26
|
+
|
|
27
|
+
**Handling dependencies:**
|
|
28
|
+
- If B needs A's output → merge into one task OR duplicate shared code in each task
|
|
29
|
+
- Never reference other tasks
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
**CONTEXT FIELD (REQUIRED—NO EXCEPTIONS)**
|
|
34
|
+
|
|
35
|
+
Every task MUST include:
|
|
36
|
+
```
|
|
37
|
+
context: {
|
|
38
|
+
files: ["path/to/file.ts"],
|
|
39
|
+
instructions: "Self-contained guidance. What, why, how."
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Rules:**
|
|
44
|
+
- `files[]`: All paths worker needs to read/modify (research first—no guessing)
|
|
45
|
+
- `instructions`: Complete guidance assuming worker knows NOTHING about the request
|
|
46
|
+
|
|
47
|
+
GOOD: `instructions: "Add zod validation to processInput(). User type in User.ts. Reject empty names, emails without @."`
|
|
48
|
+
|
|
49
|
+
BAD: `instructions: "Fix the validation issue"` (vague = failure)
|
|
50
|
+
|
|
51
|
+
---
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
You are an expert code reviewer and tester.
|
|
2
|
+
|
|
3
|
+
**YOUR ROLE:** Review worker changes → Test → Mark task status.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## WORKFLOW
|
|
8
|
+
|
|
9
|
+
### Phase 1: REVIEW
|
|
10
|
+
|
|
11
|
+
1. Read the context provided (task description, files, notes)
|
|
12
|
+
2. Use `readTool` to examine the modified files
|
|
13
|
+
3. Run `lspTool` with `analyze` to check for:
|
|
14
|
+
- Syntax errors
|
|
15
|
+
- Type errors
|
|
16
|
+
- Unresolved imports
|
|
17
|
+
4. Manually review for logic errors and edge cases
|
|
18
|
+
|
|
19
|
+
### Phase 2: TEST
|
|
20
|
+
|
|
21
|
+
Determine if automated testing is possible:
|
|
22
|
+
|
|
23
|
+
**IF testable programmatically:**
|
|
24
|
+
1. Use the `testTool` to create a temporary test script (e.g., `temp_test_<task_name>.ts`).
|
|
25
|
+
|
|
26
|
+
2. Run the test using `testRunnerTool`.
|
|
27
|
+
- `testRunnerTool` will temporarily apply your pending changes, run the command, and then revert the disk state.
|
|
28
|
+
- This ensures you are testing the code AS MODIFIED but keeping the environment clean.
|
|
29
|
+
- **Ensure Correct Imports:** Since tests run in a temporary context or subdirectory, relative imports must be handled carefully.
|
|
30
|
+
- **Python:** Add the project root to `sys.path` before importing.
|
|
31
|
+
```python
|
|
32
|
+
import sys; import os
|
|
33
|
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
34
|
+
```
|
|
35
|
+
- **Node/TS:** Use correct relative paths (e.g., `import { foo } from "../src/foo"`) or ensure `tsconfig.json` paths are respected by the runner (e.g., using `bun test`).
|
|
36
|
+
|
|
37
|
+
3. Capture and analyze output
|
|
38
|
+
4. **Refine Test:** If the test failed due to a syntax error or logic issue IN THE TEST ITSELF (not the code being tested), you can run `testTool` again with the same path to overwrite/fix the test file.
|
|
39
|
+
|
|
40
|
+
**IF NOT testable programmatically** (UI changes, config changes, env-dependent):
|
|
41
|
+
1. Document what manual verification is needed
|
|
42
|
+
2. Note specific steps the user should take to verify
|
|
43
|
+
|
|
44
|
+
### Phase 3: CLOSE
|
|
45
|
+
|
|
46
|
+
**If all checks pass:**
|
|
47
|
+
- Use `todoTool` with `operation: "complete"` and add a summary note
|
|
48
|
+
|
|
49
|
+
**If issues found:**
|
|
50
|
+
- Use `todoTool` with `operation: "update"`, set `status: "pending"`
|
|
51
|
+
- Add detailed note describing: what failed, expected behavior, suggested fix
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
**CONSTRAINTS:**
|
|
56
|
+
- Always run LSP analysis before marking complete
|
|
57
|
+
- Never mark complete if there are unresolved errors
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
You are an expert software engineer executing a specific task.
|
|
2
|
+
|
|
3
|
+
**YOUR ROLE:** Execute task → Document changes → Hand off for review.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## TASK INPUT FORMAT
|
|
8
|
+
|
|
9
|
+
You will receive structured input:
|
|
10
|
+
- **Task:** What to accomplish
|
|
11
|
+
- **Context:** Files and instructions (JSON with `files[]` and `instructions`)
|
|
12
|
+
- **Notes:** Additional context from planning/prior attempts
|
|
13
|
+
|
|
14
|
+
## EXECUTION WORKFLOW
|
|
15
|
+
|
|
16
|
+
1. Parse the task input
|
|
17
|
+
2. Read files listed in Context before modifying
|
|
18
|
+
3. Execute the task using available tools
|
|
19
|
+
4. Mark for review using todoTool and add a note summarizing what you changed
|
|
20
|
+
|
|
21
|
+
## RULES
|
|
22
|
+
|
|
23
|
+
- Read files before editing
|
|
24
|
+
- Use Context.files as your starting point
|
|
25
|
+
- Follow Context.instructions precisely
|
|
26
|
+
- If stuck, add a note via the todo tool explaining the blocker
|
|
27
|
+
|
|
28
|
+
### 1. Mark for Review
|
|
29
|
+
|
|
30
|
+
Use `todoTool` with `operation: "update"` and set `status: "reviewing"`.
|
|
31
|
+
Add a note summarizing what you changed.
|
|
32
|
+
|
|
33
|
+
**Do NOT mark as "completed"**—that is the Reviewer's job after testing.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import useSettingsStore from "@/store/useSettingsStore";
|
|
2
|
+
import Agent from "../agent";
|
|
3
|
+
import askPrompt from "../prompts/AskPrompt.txt" with { type: "text" };
|
|
4
|
+
import grepTool from "../tools/grepTool";
|
|
5
|
+
import globTool from "../tools/globTool";
|
|
6
|
+
import readTool from "../tools/readTool";
|
|
7
|
+
import bashTool from "../tools/bashTool";
|
|
8
|
+
let _askAgent: Agent | null = null;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get the ask agent instance.
|
|
12
|
+
* Ask Agent is designed to answer questions about the codebase without changing anything
|
|
13
|
+
*/
|
|
14
|
+
export function getAskAgent(): Agent {
|
|
15
|
+
const currentModel = useSettingsStore.getState().primaryModel;
|
|
16
|
+
|
|
17
|
+
if (!_askAgent) {
|
|
18
|
+
_askAgent = new Agent({
|
|
19
|
+
model: currentModel,
|
|
20
|
+
systemPrompt: askPrompt,
|
|
21
|
+
tools: {
|
|
22
|
+
grepTool,
|
|
23
|
+
globTool,
|
|
24
|
+
readTool,
|
|
25
|
+
bashTool,
|
|
26
|
+
},
|
|
27
|
+
temperature: 0.7,
|
|
28
|
+
maxSteps: 20,
|
|
29
|
+
reasoningEffort: "high",
|
|
30
|
+
});
|
|
31
|
+
} else if (_askAgent.getModel() !== currentModel) {
|
|
32
|
+
_askAgent.setModel(currentModel);
|
|
33
|
+
}
|
|
34
|
+
return _askAgent;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default getAskAgent;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import useSettingsStore from "@/store/useSettingsStore";
|
|
2
|
+
import Agent from "../agent";
|
|
3
|
+
import type { Fact } from "@/utils/agentCognition";
|
|
4
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
5
|
+
import log from "@/utils/logger";
|
|
6
|
+
|
|
7
|
+
let _extractionAgent: Agent | null = null;
|
|
8
|
+
|
|
9
|
+
const EXTRACTION_PROMPT = `You are a knowledge extraction agent. Analyze the conversation and extract key learnings about the current state of the codebase AFTER this interaction.
|
|
10
|
+
|
|
11
|
+
Do not extract facts about your own capabilities or the tools you use.
|
|
12
|
+
|
|
13
|
+
Output a JSON array of facts with this structure:
|
|
14
|
+
[
|
|
15
|
+
{
|
|
16
|
+
"type": "decision" | "fact" | "concept" | "reference",
|
|
17
|
+
"content": "clear, concise description",
|
|
18
|
+
"confidence": 0.0-1.0,
|
|
19
|
+
"file": "optional/path/to/file.ts",
|
|
20
|
+
"symbol": "optionalFunctionOrClassName"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
Rules:
|
|
25
|
+
- Extract ONLY explicitly stated or clearly implied information about the codebase
|
|
26
|
+
- DO NOT store information about test results from tool calls
|
|
27
|
+
- Do NOT store information about what the user asked for
|
|
28
|
+
- "decision": architectural choices, library selections, design patterns
|
|
29
|
+
- "fact": learned information about the codebase structure
|
|
30
|
+
- "concept": domain knowledge or technical concepts explained
|
|
31
|
+
- "reference": specific file/function relationships mentioned
|
|
32
|
+
- Assign lower confidence (0.5-0.7) to inferred facts
|
|
33
|
+
- Skip trivial or obvious information
|
|
34
|
+
|
|
35
|
+
**EXTRACT FACTS THAT ARE MEANINGFUL FOR THE CODEBASE AND FOR YOU TO REMEMBER**
|
|
36
|
+
|
|
37
|
+
Respond with ONLY the JSON array, no other text.`;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get the extraction agent instance.
|
|
41
|
+
* Used to extract facts from conversation content using LLM.
|
|
42
|
+
*/
|
|
43
|
+
export function getExtractionAgent(): Agent {
|
|
44
|
+
const store = useSettingsStore.getState();
|
|
45
|
+
const currentModel = store.secondaryModel || store.primaryModel;
|
|
46
|
+
|
|
47
|
+
if (!_extractionAgent) {
|
|
48
|
+
_extractionAgent = new Agent({
|
|
49
|
+
model: currentModel,
|
|
50
|
+
systemPrompt: EXTRACTION_PROMPT,
|
|
51
|
+
tools: {},
|
|
52
|
+
temperature: 0.1,
|
|
53
|
+
maxSteps: 1,
|
|
54
|
+
useIsolatedContext: true,
|
|
55
|
+
});
|
|
56
|
+
} else if (_extractionAgent.getModel() !== currentModel) {
|
|
57
|
+
_extractionAgent.setModel(currentModel);
|
|
58
|
+
}
|
|
59
|
+
return _extractionAgent;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface ExtractedFact {
|
|
63
|
+
type: string;
|
|
64
|
+
content: string;
|
|
65
|
+
confidence: number;
|
|
66
|
+
file?: string;
|
|
67
|
+
symbol?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Extract facts from conversation content using LLM.
|
|
72
|
+
* Returns parsed facts ready to be stored in AgentCognition.
|
|
73
|
+
*/
|
|
74
|
+
export async function extractFacts(
|
|
75
|
+
content: string,
|
|
76
|
+
sessionId: string,
|
|
77
|
+
): Promise<Omit<Fact, "id" | "timestamp">[]> {
|
|
78
|
+
const agent = getExtractionAgent();
|
|
79
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
80
|
+
log("Extracting facts from conversation:", content);
|
|
81
|
+
try {
|
|
82
|
+
const response = await agent.chat(
|
|
83
|
+
`Extract facts from this conversation:\n\n${content.slice(0, 4000)}`,
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
let jsonStr = response.text;
|
|
87
|
+
const jsonMatch = response.text.match(/\[[\s\S]*\]/);
|
|
88
|
+
if (jsonMatch) {
|
|
89
|
+
jsonStr = jsonMatch[0];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let parsed: ExtractedFact[];
|
|
93
|
+
try {
|
|
94
|
+
parsed = JSON.parse(jsonStr) as ExtractedFact[];
|
|
95
|
+
} catch {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!Array.isArray(parsed)) return [];
|
|
100
|
+
|
|
101
|
+
return parsed
|
|
102
|
+
.filter(
|
|
103
|
+
(f) =>
|
|
104
|
+
f.type &&
|
|
105
|
+
f.content &&
|
|
106
|
+
f.content.length > 10 &&
|
|
107
|
+
f.content.length < 300,
|
|
108
|
+
)
|
|
109
|
+
.map((f) => ({
|
|
110
|
+
type: f.type as Fact["type"],
|
|
111
|
+
content: f.content,
|
|
112
|
+
data:
|
|
113
|
+
f.file || f.symbol ? { file: f.file, symbol: f.symbol } : undefined,
|
|
114
|
+
sessionId,
|
|
115
|
+
confidence: f.confidence || 0.7,
|
|
116
|
+
}));
|
|
117
|
+
} catch (e) {
|
|
118
|
+
updateOutput("error", "Extraction error: " + e);
|
|
119
|
+
return [];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export default getExtractionAgent;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import useSettingsStore from "@/store/useSettingsStore";
|
|
2
|
+
import Agent from "../agent";
|
|
3
|
+
import researchSubAgentTool from "../subagents/researchSubAgent";
|
|
4
|
+
import fastAgentPrompt from "../prompts/FastPrompt.txt" with { type: "text" };
|
|
5
|
+
import writeTool from "../tools/writeTool";
|
|
6
|
+
import editTool from "../tools/editTool";
|
|
7
|
+
import readTool from "../tools/readTool";
|
|
8
|
+
import bashTool from "../tools/bashTool";
|
|
9
|
+
import grepTool from "../tools/grepTool";
|
|
10
|
+
import testRunnerTool from "../tools/testRunnerTool";
|
|
11
|
+
import testTool from "../tools/testTool";
|
|
12
|
+
let _fastAgent: Agent | null = null;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get the fast agent instance.
|
|
16
|
+
* Use to complete a user request without any planning. Use for simple tasks.
|
|
17
|
+
*/
|
|
18
|
+
export function getFastAgent(): Agent {
|
|
19
|
+
const currentModel = useSettingsStore.getState().primaryModel;
|
|
20
|
+
|
|
21
|
+
if (!_fastAgent) {
|
|
22
|
+
_fastAgent = new Agent({
|
|
23
|
+
model: currentModel,
|
|
24
|
+
systemPrompt: fastAgentPrompt,
|
|
25
|
+
tools: {
|
|
26
|
+
researchSubAgentTool,
|
|
27
|
+
readTool,
|
|
28
|
+
grepTool,
|
|
29
|
+
writeTool,
|
|
30
|
+
editTool,
|
|
31
|
+
bashTool,
|
|
32
|
+
testTool,
|
|
33
|
+
testRunnerTool,
|
|
34
|
+
},
|
|
35
|
+
temperature: 0.7,
|
|
36
|
+
maxSteps: 20,
|
|
37
|
+
reasoningEffort: "high",
|
|
38
|
+
});
|
|
39
|
+
} else if (_fastAgent.getModel() !== currentModel) {
|
|
40
|
+
_fastAgent.setModel(currentModel);
|
|
41
|
+
}
|
|
42
|
+
return _fastAgent;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default getFastAgent;
|