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,277 @@
|
|
|
1
|
+
import { getLSPClient } from "@/utils/lspClient";
|
|
2
|
+
import type { Fact } from "@/utils/agentCognition";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import path from "path";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Map LSP symbol kinds to specific graph node types.
|
|
8
|
+
*/
|
|
9
|
+
function kindToType(kind: string): Fact["type"] {
|
|
10
|
+
const map: Record<string, Fact["type"]> = {
|
|
11
|
+
Function: "function",
|
|
12
|
+
Class: "class",
|
|
13
|
+
Interface: "interface",
|
|
14
|
+
Variable: "variable",
|
|
15
|
+
Method: "function",
|
|
16
|
+
Property: "variable",
|
|
17
|
+
Struct: "class",
|
|
18
|
+
Enum: "class",
|
|
19
|
+
Trait: "interface",
|
|
20
|
+
};
|
|
21
|
+
return map[kind] || "symbol";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface SymbolRelation {
|
|
25
|
+
source: string; // Symbol name
|
|
26
|
+
target: string; // Symbol name
|
|
27
|
+
type: "CALLS" | "DEFINES" | "INHERITS" | "IMPORTS";
|
|
28
|
+
weight: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class SymbolExtractor {
|
|
32
|
+
private lsp = getLSPClient();
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Resolve an import module to a file path.
|
|
36
|
+
* Handles relative imports and attempts common resolutions.
|
|
37
|
+
*/
|
|
38
|
+
private resolveImport(
|
|
39
|
+
fromFile: string,
|
|
40
|
+
module: string,
|
|
41
|
+
isRelative: boolean,
|
|
42
|
+
): string | null {
|
|
43
|
+
const dir = path.dirname(fromFile);
|
|
44
|
+
const ext = fromFile.split(".").pop() || "";
|
|
45
|
+
|
|
46
|
+
if (isRelative) {
|
|
47
|
+
// Relative import - try common extensions
|
|
48
|
+
const extensions =
|
|
49
|
+
ext === "py" ? [".py"] : [".ts", ".tsx", ".js", ".jsx"];
|
|
50
|
+
const basePath = path.resolve(dir, module.replace(/\./g, "/"));
|
|
51
|
+
|
|
52
|
+
for (const extTry of extensions) {
|
|
53
|
+
const candidate = basePath + extTry;
|
|
54
|
+
if (fs.existsSync(candidate)) {
|
|
55
|
+
return candidate;
|
|
56
|
+
}
|
|
57
|
+
// Try as directory with index
|
|
58
|
+
const indexCandidate = path.join(basePath, `index${extTry}`);
|
|
59
|
+
if (fs.existsSync(indexCandidate)) {
|
|
60
|
+
return indexCandidate;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Return module name for external imports (can be linked later)
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async analyze(filePath: string): Promise<{
|
|
70
|
+
facts: Omit<Fact, "id" | "timestamp" | "sessionId">[];
|
|
71
|
+
relations: { sourceIdx: number; targetIdx: number; type: string }[];
|
|
72
|
+
}> {
|
|
73
|
+
if (!fs.existsSync(filePath)) return { facts: [], relations: [] };
|
|
74
|
+
|
|
75
|
+
// Standardize on relative paths for the graph
|
|
76
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
77
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
78
|
+
|
|
79
|
+
// Get symbols with detail - this now includes children
|
|
80
|
+
const symbols = await this.lsp.getDocumentSymbolsWithDetails(
|
|
81
|
+
filePath,
|
|
82
|
+
content,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const facts: Omit<Fact, "id" | "timestamp" | "sessionId">[] = [];
|
|
86
|
+
const relations: { sourceIdx: number; targetIdx: number; type: string }[] =
|
|
87
|
+
[];
|
|
88
|
+
|
|
89
|
+
// Track symbol facts to link relations
|
|
90
|
+
const symbolToIdx = new Map<string, number>();
|
|
91
|
+
const filePathToIdx = new Map<string, number>();
|
|
92
|
+
|
|
93
|
+
// 1. Create a fact for the file itself using RELATIVE path
|
|
94
|
+
const fileFact: Omit<Fact, "id" | "timestamp" | "sessionId"> = {
|
|
95
|
+
type: "file",
|
|
96
|
+
content: `File: ${relativePath}`,
|
|
97
|
+
data: { file: relativePath },
|
|
98
|
+
confidence: 1.0,
|
|
99
|
+
validated: Date.now(),
|
|
100
|
+
};
|
|
101
|
+
facts.push(fileFact);
|
|
102
|
+
const fileIdx = 0;
|
|
103
|
+
filePathToIdx.set(relativePath, fileIdx);
|
|
104
|
+
|
|
105
|
+
// 2. Process imports -> IMPORTS relations
|
|
106
|
+
const imports = await this.lsp.getImports(filePath, content);
|
|
107
|
+
for (const imp of imports) {
|
|
108
|
+
const resolvedAbsPath = this.resolveImport(
|
|
109
|
+
filePath,
|
|
110
|
+
imp.module,
|
|
111
|
+
imp.isRelative,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const resolvedPath = resolvedAbsPath
|
|
115
|
+
? path.relative(process.cwd(), resolvedAbsPath)
|
|
116
|
+
: null;
|
|
117
|
+
|
|
118
|
+
// Create a fact for the imported module
|
|
119
|
+
const importFact: Omit<Fact, "id" | "timestamp" | "sessionId"> = {
|
|
120
|
+
type: "module",
|
|
121
|
+
content: `Module: ${imp.alias || imp.module}`,
|
|
122
|
+
data: {
|
|
123
|
+
file: resolvedPath || imp.module,
|
|
124
|
+
module: imp.module,
|
|
125
|
+
alias: imp.alias,
|
|
126
|
+
isExternal: !resolvedPath,
|
|
127
|
+
},
|
|
128
|
+
confidence: resolvedPath ? 1.0 : 0.7,
|
|
129
|
+
validated: Date.now(),
|
|
130
|
+
};
|
|
131
|
+
facts.push(importFact);
|
|
132
|
+
const importIdx = facts.length - 1;
|
|
133
|
+
|
|
134
|
+
relations.push({
|
|
135
|
+
sourceIdx: fileIdx,
|
|
136
|
+
targetIdx: importIdx,
|
|
137
|
+
type: "IMPORTS",
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// 3. Process symbols recursively
|
|
142
|
+
const processSymbol = (sym: any, parentIdx: number) => {
|
|
143
|
+
// Build rich content string for LLM consumption
|
|
144
|
+
let content = `${sym.kind}: ${sym.name} (${relativePath})`;
|
|
145
|
+
if (sym.signature) {
|
|
146
|
+
content += ` ${sym.signature}`;
|
|
147
|
+
}
|
|
148
|
+
if (sym.docstring) {
|
|
149
|
+
content += ` - ${sym.docstring.slice(0, 150)}`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Create symbol fact with enhanced data
|
|
153
|
+
const fact: Omit<Fact, "id" | "timestamp" | "sessionId"> = {
|
|
154
|
+
type: kindToType(sym.kind),
|
|
155
|
+
content,
|
|
156
|
+
data: {
|
|
157
|
+
file: relativePath,
|
|
158
|
+
symbol: sym.name,
|
|
159
|
+
kind: sym.kind,
|
|
160
|
+
type: kindToType(sym.kind),
|
|
161
|
+
line: sym.line,
|
|
162
|
+
signature: sym.signature,
|
|
163
|
+
docstring: sym.docstring,
|
|
164
|
+
exported: sym.exported,
|
|
165
|
+
},
|
|
166
|
+
confidence: 1.0,
|
|
167
|
+
validated: Date.now(),
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
facts.push(fact);
|
|
171
|
+
const symIdx = facts.length - 1;
|
|
172
|
+
symbolToIdx.set(sym.name, symIdx); // Note: Flat map might clash if same name used in nested scopes effectively, but ok for now
|
|
173
|
+
|
|
174
|
+
// Link: Parent DEFINES/CONTAINS Symbol
|
|
175
|
+
relations.push({
|
|
176
|
+
sourceIdx: parentIdx,
|
|
177
|
+
targetIdx: symIdx,
|
|
178
|
+
type: parentIdx === fileIdx ? "DEFINES" : "CONTAINS",
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// Inherits relation if applicable (class extension)
|
|
182
|
+
// Note: LSP usually gives inheritance at top level, but if nested classes existed...
|
|
183
|
+
|
|
184
|
+
// Recurse for children
|
|
185
|
+
if (sym.children && sym.children.length > 0) {
|
|
186
|
+
for (const child of sym.children) {
|
|
187
|
+
processSymbol(child, symIdx);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
for (const sym of symbols) {
|
|
193
|
+
processSymbol(sym, fileIdx);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 4. Extract inheritance -> INHERITS relations
|
|
197
|
+
const inheritance = await this.lsp.getInheritance(filePath, content);
|
|
198
|
+
for (const inh of inheritance) {
|
|
199
|
+
const childIdx = symbolToIdx.get(inh.className);
|
|
200
|
+
let parentIdx = symbolToIdx.get(inh.parentName);
|
|
201
|
+
|
|
202
|
+
if (!parentIdx) {
|
|
203
|
+
// Parent is external - create a symbol fact
|
|
204
|
+
const parentFact: Omit<Fact, "id" | "timestamp" | "sessionId"> = {
|
|
205
|
+
type: "class",
|
|
206
|
+
content: `Class: ${inh.parentName}`,
|
|
207
|
+
data: { symbol: inh.parentName, kind: "Class" },
|
|
208
|
+
confidence: 0.8,
|
|
209
|
+
validated: Date.now(),
|
|
210
|
+
};
|
|
211
|
+
facts.push(parentFact);
|
|
212
|
+
parentIdx = facts.length - 1;
|
|
213
|
+
symbolToIdx.set(inh.parentName, parentIdx);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (childIdx !== undefined) {
|
|
217
|
+
relations.push({
|
|
218
|
+
sourceIdx: childIdx,
|
|
219
|
+
targetIdx: parentIdx,
|
|
220
|
+
type: "INHERITS",
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// 5. Extract calls with source context -> CALLS relations
|
|
226
|
+
// Get all calls from the file
|
|
227
|
+
const allCalls = await this.lsp.getOutgoingCalls(filePath, content, 1, 1);
|
|
228
|
+
|
|
229
|
+
// Group calls by sourceContext and deduplicate
|
|
230
|
+
const processedCalls = new Set<string>();
|
|
231
|
+
for (const call of allCalls) {
|
|
232
|
+
const callKey = `${call.sourceContext || ""}:${call.name}`;
|
|
233
|
+
if (processedCalls.has(callKey)) continue;
|
|
234
|
+
processedCalls.add(callKey);
|
|
235
|
+
|
|
236
|
+
// Find or create target fact
|
|
237
|
+
let targetIdx = symbolToIdx.get(call.name);
|
|
238
|
+
if (targetIdx === undefined) {
|
|
239
|
+
// External call - create a weak symbol fact
|
|
240
|
+
const targetFact: Omit<Fact, "id" | "timestamp" | "sessionId"> = {
|
|
241
|
+
type: "symbol",
|
|
242
|
+
content: `Symbol: ${call.name}`,
|
|
243
|
+
data: {
|
|
244
|
+
file: call.file
|
|
245
|
+
? path.relative(process.cwd(), call.file)
|
|
246
|
+
: undefined,
|
|
247
|
+
symbol: call.name,
|
|
248
|
+
},
|
|
249
|
+
confidence: 0.8,
|
|
250
|
+
validated: Date.now(),
|
|
251
|
+
};
|
|
252
|
+
facts.push(targetFact);
|
|
253
|
+
targetIdx = facts.length - 1;
|
|
254
|
+
symbolToIdx.set(call.name, targetIdx);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Find source (calling function)
|
|
258
|
+
let sourceIdx: number | undefined;
|
|
259
|
+
if (call.sourceContext) {
|
|
260
|
+
sourceIdx = symbolToIdx.get(call.sourceContext);
|
|
261
|
+
}
|
|
262
|
+
if (sourceIdx === undefined) {
|
|
263
|
+
sourceIdx = fileIdx; // Top-level call, link from file
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
relations.push({
|
|
267
|
+
sourceIdx,
|
|
268
|
+
targetIdx,
|
|
269
|
+
type: "CALLS",
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return { facts, relations };
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export default SymbolExtractor;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
import type { OutputItem, OutputItemType } from "@/types/OutputItem";
|
|
3
|
+
import ContextManager from "@/agent/contextManager";
|
|
4
|
+
import log from "@/utils/logger";
|
|
5
|
+
|
|
6
|
+
interface ModelSelectionRequest {
|
|
7
|
+
originalModel: string;
|
|
8
|
+
errorMessage: string;
|
|
9
|
+
resolve: (modelName: string | null) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface FraudeStore {
|
|
13
|
+
executionMode: 0 | 1 | 2; // 0 = Fast, 1 = Plan, 2 = Ask
|
|
14
|
+
outputItems: OutputItem[];
|
|
15
|
+
started: boolean;
|
|
16
|
+
status: number; // 0 = idle, 1 = running, 2 = waiting, 3 = reviewing changes, 4 = awaiting model selection, -1 = interrupted
|
|
17
|
+
elapsedTime: number;
|
|
18
|
+
lastBreak: number;
|
|
19
|
+
statusText?: string;
|
|
20
|
+
contextManager: ContextManager;
|
|
21
|
+
researchCache?: Record<string, string>;
|
|
22
|
+
abortController: AbortController | null;
|
|
23
|
+
pendingModelSelection: ModelSelectionRequest | null;
|
|
24
|
+
interruptAgent: () => void;
|
|
25
|
+
updateOutput: (
|
|
26
|
+
type: OutputItemType,
|
|
27
|
+
content: string,
|
|
28
|
+
config?: {
|
|
29
|
+
duration?: number;
|
|
30
|
+
dontOverride?: boolean;
|
|
31
|
+
},
|
|
32
|
+
) => void;
|
|
33
|
+
requestModelSelection: (
|
|
34
|
+
originalModel: string,
|
|
35
|
+
errorMessage: string,
|
|
36
|
+
) => Promise<string | null>;
|
|
37
|
+
resolveModelSelection: (modelName: string | null) => void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const useFraudeStore = create<FraudeStore>((set, get) => ({
|
|
41
|
+
executionMode: 0 as 0 | 1 | 2,
|
|
42
|
+
outputItems: [],
|
|
43
|
+
started: false,
|
|
44
|
+
status: 0,
|
|
45
|
+
elapsedTime: 0,
|
|
46
|
+
lastBreak: 0,
|
|
47
|
+
statusText: "",
|
|
48
|
+
contextManager: new ContextManager(),
|
|
49
|
+
researchCache: undefined,
|
|
50
|
+
abortController: null,
|
|
51
|
+
pendingModelSelection: null,
|
|
52
|
+
interruptAgent: () => {
|
|
53
|
+
const controller = get().abortController;
|
|
54
|
+
if (controller && !controller.signal.aborted) {
|
|
55
|
+
try {
|
|
56
|
+
controller.abort();
|
|
57
|
+
} catch (e) {
|
|
58
|
+
log(`Abort caught: ${e}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
updateOutput: (type, rawContent, config) => {
|
|
63
|
+
set((state) => {
|
|
64
|
+
const outputItems = [...state.outputItems];
|
|
65
|
+
const latestOutput = outputItems[outputItems.length - 1];
|
|
66
|
+
const dontOverrideType = new Set(["log", "interrupted", "command"]);
|
|
67
|
+
let content = rawContent.replaceAll(process.cwd(), "@");
|
|
68
|
+
if (
|
|
69
|
+
latestOutput &&
|
|
70
|
+
latestOutput.type === type &&
|
|
71
|
+
!dontOverrideType.has(type) &&
|
|
72
|
+
!config?.dontOverride
|
|
73
|
+
) {
|
|
74
|
+
outputItems[outputItems.length - 1] = {
|
|
75
|
+
...latestOutput,
|
|
76
|
+
content,
|
|
77
|
+
duration: config?.duration,
|
|
78
|
+
};
|
|
79
|
+
} else {
|
|
80
|
+
outputItems.push({
|
|
81
|
+
id: crypto.randomUUID(),
|
|
82
|
+
type,
|
|
83
|
+
content,
|
|
84
|
+
duration: config?.duration,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
outputItems,
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
},
|
|
92
|
+
requestModelSelection: (originalModel: string, errorMessage: string) => {
|
|
93
|
+
return new Promise<string | null>((resolve) => {
|
|
94
|
+
set({
|
|
95
|
+
status: 4, // awaiting model selection
|
|
96
|
+
statusText: "Awaiting model selection...",
|
|
97
|
+
pendingModelSelection: {
|
|
98
|
+
originalModel,
|
|
99
|
+
errorMessage,
|
|
100
|
+
resolve,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
// Also add to output items so it renders
|
|
104
|
+
get().updateOutput(
|
|
105
|
+
"modelSelect",
|
|
106
|
+
JSON.stringify({ originalModel, errorMessage }),
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
resolveModelSelection: (modelName: string | null) => {
|
|
111
|
+
const pending = get().pendingModelSelection;
|
|
112
|
+
if (pending) {
|
|
113
|
+
pending.resolve(modelName);
|
|
114
|
+
set({
|
|
115
|
+
status: modelName ? 1 : 0, // back to running or idle
|
|
116
|
+
statusText: modelName ? "Retrying with new model..." : "",
|
|
117
|
+
pendingModelSelection: null,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
}));
|
|
122
|
+
|
|
123
|
+
export default useFraudeStore;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
import { Settings, UpdateSettings } from "../config/settings";
|
|
3
|
+
import { SettingsSchema, type Config } from "../config/schema";
|
|
4
|
+
|
|
5
|
+
interface SettingsActions {
|
|
6
|
+
setOllamaUrl: (url: string) => void;
|
|
7
|
+
syncWithSettings: () => void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
type SettingsState = Config & SettingsActions;
|
|
11
|
+
|
|
12
|
+
const DEFAULTS = SettingsSchema.parse({});
|
|
13
|
+
|
|
14
|
+
const useSettingsStore = create<SettingsState>()((set) => {
|
|
15
|
+
return {
|
|
16
|
+
...DEFAULTS,
|
|
17
|
+
|
|
18
|
+
setOllamaUrl: (url) => {
|
|
19
|
+
try {
|
|
20
|
+
UpdateSettings({ ollamaUrl: url });
|
|
21
|
+
} catch (e) {
|
|
22
|
+
console.error("Failed to save setting ollamaUrl:", e);
|
|
23
|
+
}
|
|
24
|
+
set({ ollamaUrl: url });
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
syncWithSettings: () => {
|
|
28
|
+
try {
|
|
29
|
+
const settings = Settings.getInstance();
|
|
30
|
+
set(settings.getAll());
|
|
31
|
+
} catch (e) {
|
|
32
|
+
console.error("Failed to sync settings:", e);
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
} as SettingsState;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export default useSettingsStore;
|
package/src/theme.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const THEME = {
|
|
2
|
+
primary: "#f5c2e7", // Flamingo - Modern muted pink highlight
|
|
3
|
+
primaryLight: "#f5e0dc", // Rosewater - Very faint for selections/highlights
|
|
4
|
+
primaryDark: "#eba0ac", // Maroon - Muted for borders/non-focus
|
|
5
|
+
primaryDim: "#94e2d5", // Teal - Modern secondary accent
|
|
6
|
+
success: "#a6e3a1", // Green - Standard terminal success
|
|
7
|
+
error: "#f38ba8", // Red - Standard terminal error
|
|
8
|
+
warning: "#f9e2af", // Yellow - Standard terminal warning
|
|
9
|
+
info: "#89b4fa", // Blue - Standard terminal info
|
|
10
|
+
text: "#cdd6f4", // Text - Off-white based on modern palettes
|
|
11
|
+
dim: "#6c7086", // Overlay - Muted grey for metadata
|
|
12
|
+
border: "#313244", // Surface - Subtle dark border
|
|
13
|
+
borderFocus: "#f5c2e7", // Match primary for focused state
|
|
14
|
+
gradient: [
|
|
15
|
+
{ r: 245, g: 194, b: 231 }, // flamingo
|
|
16
|
+
{ r: 203, g: 166, b: 247 }, // mauve
|
|
17
|
+
{ r: 180, g: 190, b: 254 }, // lavender
|
|
18
|
+
{ r: 137, g: 180, b: 250 }, // blue
|
|
19
|
+
{ r: 116, g: 199, b: 236 }, // sapphire
|
|
20
|
+
{ r: 137, g: 220, b: 235 }, // sky
|
|
21
|
+
{ r: 148, g: 226, b: 213 }, // teal
|
|
22
|
+
{ r: 166, g: 227, b: 161 }, // green
|
|
23
|
+
{ r: 249, g: 226, b: 175 }, // yellow
|
|
24
|
+
{ r: 250, g: 179, b: 135 }, // peach
|
|
25
|
+
],
|
|
26
|
+
};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { ModelMessage, ToolSet, TextStreamPart } from "ai";
|
|
3
|
+
import type { TokenUsage } from "./TokenUsage";
|
|
4
|
+
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Agent Configuration Types
|
|
7
|
+
// ============================================================================
|
|
8
|
+
|
|
9
|
+
/** Reasoning effort levels for reasoning models (e.g., OpenAI o-series, GPT-5) */
|
|
10
|
+
export type ReasoningEffort =
|
|
11
|
+
| "none"
|
|
12
|
+
| "minimal"
|
|
13
|
+
| "low"
|
|
14
|
+
| "medium"
|
|
15
|
+
| "high"
|
|
16
|
+
| "xhigh";
|
|
17
|
+
|
|
18
|
+
export interface AgentConfig {
|
|
19
|
+
/** Model identifier (e.g., "llama3.1:latest", "gpt-4", etc.) */
|
|
20
|
+
model: string;
|
|
21
|
+
|
|
22
|
+
/** System prompt that defines agent behavior */
|
|
23
|
+
systemPrompt?: string;
|
|
24
|
+
|
|
25
|
+
/** Temperature for response generation (0.0 - 2.0) */
|
|
26
|
+
temperature?: number;
|
|
27
|
+
|
|
28
|
+
/** Maximum tokens to generate */
|
|
29
|
+
maxTokens?: number;
|
|
30
|
+
|
|
31
|
+
/** Tools available to the agent */
|
|
32
|
+
tools?: ToolSet;
|
|
33
|
+
|
|
34
|
+
/** Maximum number of tool execution steps (default: 5) */
|
|
35
|
+
maxSteps?: number;
|
|
36
|
+
|
|
37
|
+
/** Optional name for the agent instance */
|
|
38
|
+
name?: string;
|
|
39
|
+
|
|
40
|
+
/** Whether to automatically execute tools (default: true) */
|
|
41
|
+
autoExecuteTools?: boolean;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Reasoning effort for reasoning models (OpenAI o-series, GPT-5, etc.)
|
|
45
|
+
* - 'none': No reasoning (only GPT-5.1 models)
|
|
46
|
+
* - 'minimal': Minimal reasoning
|
|
47
|
+
* - 'low': Low reasoning effort
|
|
48
|
+
* - 'medium': Medium reasoning effort (default)
|
|
49
|
+
* - 'high': High reasoning effort
|
|
50
|
+
* - 'xhigh': Extra high reasoning (only GPT-5.1-Codex-Max)
|
|
51
|
+
*/
|
|
52
|
+
reasoningEffort?: ReasoningEffort;
|
|
53
|
+
|
|
54
|
+
/** Callback for tool calls */
|
|
55
|
+
onToolCall?: (toolCall: ToolCallInfo) => void;
|
|
56
|
+
|
|
57
|
+
/** Callback for step completion */
|
|
58
|
+
onStepComplete?: (step: StepInfo) => void;
|
|
59
|
+
|
|
60
|
+
/** Callback for each raw stream chunk (for custom handling like usage tracking) */
|
|
61
|
+
onStreamChunk?: (chunk: TextStreamPart<ToolSet>) => void | Promise<void>;
|
|
62
|
+
|
|
63
|
+
/** Abort signal for cancelling the request */
|
|
64
|
+
abortSignal?: AbortSignal;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Whether to use an isolated context manager instead of the shared global one.
|
|
68
|
+
* Set to true for subagents to prevent context contamination with parent agents.
|
|
69
|
+
* Default: false (uses shared context manager)
|
|
70
|
+
*/
|
|
71
|
+
useIsolatedContext?: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Tool-Related Types
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
export interface ToolCallInfo {
|
|
79
|
+
toolCallId?: string;
|
|
80
|
+
toolName: string;
|
|
81
|
+
args: unknown;
|
|
82
|
+
result?: unknown;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface StepInfo {
|
|
86
|
+
stepNumber: number;
|
|
87
|
+
actions: { role: string; content: string }[];
|
|
88
|
+
toolCalls: ToolCallInfo[];
|
|
89
|
+
finishReason: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ============================================================================
|
|
93
|
+
// Agent Response Types
|
|
94
|
+
// ============================================================================
|
|
95
|
+
|
|
96
|
+
export interface AgentResponse {
|
|
97
|
+
/** The final text response */
|
|
98
|
+
text: string;
|
|
99
|
+
|
|
100
|
+
/** Token usage statistics */
|
|
101
|
+
usage: TokenUsage;
|
|
102
|
+
|
|
103
|
+
/** Finish reason for the generation */
|
|
104
|
+
finishReason: string;
|
|
105
|
+
|
|
106
|
+
/** All steps taken during generation (for multi-step tool use) */
|
|
107
|
+
steps: StepInfo[];
|
|
108
|
+
|
|
109
|
+
/** All tool calls (and results) made during the conversation */
|
|
110
|
+
toolCalls: ToolCallInfo[];
|
|
111
|
+
|
|
112
|
+
/** Raw response from the provider (for advanced use cases) */
|
|
113
|
+
raw?: unknown;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface StructuredAgentResponse<T> {
|
|
117
|
+
/** The structured object matching the provided schema */
|
|
118
|
+
object: T;
|
|
119
|
+
|
|
120
|
+
/** Token usage statistics */
|
|
121
|
+
usage: TokenUsage;
|
|
122
|
+
|
|
123
|
+
/** Finish reason for the generation */
|
|
124
|
+
finishReason: string;
|
|
125
|
+
|
|
126
|
+
/** Raw response from the provider */
|
|
127
|
+
raw?: unknown;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ============================================================================
|
|
131
|
+
// Message Types (Unified format)
|
|
132
|
+
// ============================================================================
|
|
133
|
+
|
|
134
|
+
export type AgentMessage = ModelMessage;
|
|
135
|
+
|
|
136
|
+
export type MessageRole = "system" | "user" | "assistant" | "tool";
|
|
137
|
+
|
|
138
|
+
export interface SimpleMessage {
|
|
139
|
+
role: MessageRole;
|
|
140
|
+
content: string;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ============================================================================
|
|
144
|
+
// Schema Types for Structured Generation
|
|
145
|
+
// ============================================================================
|
|
146
|
+
|
|
147
|
+
export type StructuredSchema<T> = z.ZodType<T>;
|