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,60 @@
|
|
|
1
|
+
import GroqClient from "@/services/groq";
|
|
2
|
+
import type { Model } from "@/types/Model";
|
|
3
|
+
import useSettingsStore from "@/store/useSettingsStore";
|
|
4
|
+
import { UpdateSettings } from "src/config/settings";
|
|
5
|
+
import useFraudeStore from "src/store/useFraudeStore";
|
|
6
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
7
|
+
|
|
8
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
9
|
+
|
|
10
|
+
const addGroqModel = async (args: string[]) => {
|
|
11
|
+
const model = args[0];
|
|
12
|
+
if (!model) {
|
|
13
|
+
updateOutput("error", "No model specified (Groq)");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const modelData: any = await GroqClient.getModelData(model);
|
|
17
|
+
|
|
18
|
+
if (!modelData) {
|
|
19
|
+
throw new Error(`No data found for Groq model ${model}`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const newModel: Model = {
|
|
23
|
+
type: "groq",
|
|
24
|
+
name: model,
|
|
25
|
+
modified_at: new Date(modelData.created * 1000).toISOString(),
|
|
26
|
+
digest: modelData.id,
|
|
27
|
+
capabilities: [],
|
|
28
|
+
usage: {
|
|
29
|
+
promptTokens: 0,
|
|
30
|
+
completionTokens: 0,
|
|
31
|
+
totalTokens: 0,
|
|
32
|
+
},
|
|
33
|
+
details: {
|
|
34
|
+
context_length: modelData.context_window,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const savedModels = useSettingsStore.getState().models || [];
|
|
39
|
+
|
|
40
|
+
const existingIndex = savedModels.findIndex(
|
|
41
|
+
(m) => m.name === newModel.name && m.type === "groq",
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (existingIndex >= 0) {
|
|
45
|
+
savedModels[existingIndex] = newModel;
|
|
46
|
+
} else {
|
|
47
|
+
savedModels.push(newModel);
|
|
48
|
+
}
|
|
49
|
+
await UpdateSettings({ models: savedModels });
|
|
50
|
+
updateOutput("log", "Groq model added: " + model);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const addGroqModelCommand: Command = {
|
|
54
|
+
name: "add",
|
|
55
|
+
description: "Add a Groq model",
|
|
56
|
+
usage: "/groq add <model-name>",
|
|
57
|
+
action: addGroqModel,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export default addGroqModelCommand;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { UpdateSettings } from "src/config/settings";
|
|
2
|
+
import useFraudeStore from "src/store/useFraudeStore";
|
|
3
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
4
|
+
|
|
5
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
6
|
+
|
|
7
|
+
const groqAuth = async (args: string[]) => {
|
|
8
|
+
const apiKey = args[0];
|
|
9
|
+
if (!apiKey) {
|
|
10
|
+
updateOutput("error", "No API key specified (Groq)");
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
await UpdateSettings({ groq_api_key: apiKey });
|
|
14
|
+
updateOutput("log", "Groq API key set");
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const groqAuthCommand: Command = {
|
|
18
|
+
name: "auth",
|
|
19
|
+
description: "Set Groq API key",
|
|
20
|
+
usage: "/groq auth <api-key>",
|
|
21
|
+
action: groqAuth,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default groqAuthCommand;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import groqAuthCommand from "./auth";
|
|
3
|
+
import addGroqModelCommand from "./add_model";
|
|
4
|
+
|
|
5
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
6
|
+
|
|
7
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
8
|
+
|
|
9
|
+
const groqCommands: Command = {
|
|
10
|
+
name: "groq",
|
|
11
|
+
description: "Manage Groq models",
|
|
12
|
+
usage: "/groq <subcommand>",
|
|
13
|
+
action: async (args: string[]) => {
|
|
14
|
+
if (args.length === 0 || args[0] === "list" || args[0] === "models") {
|
|
15
|
+
updateOutput("settings", "/models:groq");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
subcommands: [
|
|
20
|
+
groqAuthCommand,
|
|
21
|
+
addGroqModelCommand,
|
|
22
|
+
{
|
|
23
|
+
name: "list",
|
|
24
|
+
description: "List Groq models",
|
|
25
|
+
usage: "/groq list",
|
|
26
|
+
action: async () => {
|
|
27
|
+
updateOutput("settings", "/models:groq");
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default groqCommands;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import COMMANDS from "./COMMANDS";
|
|
3
|
+
import log from "@/utils/logger";
|
|
4
|
+
|
|
5
|
+
// Class for handling commands
|
|
6
|
+
class CommandCenter {
|
|
7
|
+
private commands: Command[] = [];
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
this.commands = COMMANDS;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async loadPlugins() {
|
|
14
|
+
try {
|
|
15
|
+
const { PluginLoader } = await import("@/services/PluginLoader");
|
|
16
|
+
const loader = new PluginLoader();
|
|
17
|
+
const pluginCommands = await loader.loadPlugins();
|
|
18
|
+
this.commands = [...this.commands, ...pluginCommands];
|
|
19
|
+
log(`Loaded ${pluginCommands.length} plugin commands.`);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
log("Error loading plugins:", error);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
processCommand = async (query: string) => {
|
|
26
|
+
let command = query.slice(1).split(" ");
|
|
27
|
+
const base = command.shift();
|
|
28
|
+
|
|
29
|
+
for (const cmd of this.commands) {
|
|
30
|
+
if (cmd.name === base) {
|
|
31
|
+
if (cmd.subcommands) {
|
|
32
|
+
for (const sub of cmd.subcommands) {
|
|
33
|
+
if (sub.name === command[0]) {
|
|
34
|
+
if (sub.action) return await sub.action(command.slice(1));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// If no subcommand matched, use the base command's action if it exists
|
|
38
|
+
if (cmd.action) return await cmd.action(command);
|
|
39
|
+
} else {
|
|
40
|
+
if (cmd.action) return await cmd.action(command);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
getAllCommands(): Command[] {
|
|
47
|
+
const templates: Command[] = [];
|
|
48
|
+
|
|
49
|
+
for (const cmd of this.commands) {
|
|
50
|
+
if (cmd.usage && !cmd.usage.includes("<subcommand>")) {
|
|
51
|
+
templates.push(cmd);
|
|
52
|
+
}
|
|
53
|
+
// Add subcommands
|
|
54
|
+
if (cmd.subcommands) {
|
|
55
|
+
for (const sub of cmd.subcommands) {
|
|
56
|
+
templates.push(sub);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return templates;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default new CommandCenter();
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
3
|
+
import AgentCognition from "@/utils/agentCognition";
|
|
4
|
+
import type { KnowledgeViewData } from "@/components/output/KnowledgeView";
|
|
5
|
+
|
|
6
|
+
const action = async (args: string[]) => {
|
|
7
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const cognition = AgentCognition.getInstance();
|
|
11
|
+
await cognition.init();
|
|
12
|
+
|
|
13
|
+
if (args.length === 0) {
|
|
14
|
+
// Show summary of all knowledge
|
|
15
|
+
const [decisions, facts, concepts, references] = await Promise.all([
|
|
16
|
+
cognition.findByType("decision"),
|
|
17
|
+
cognition.findByType("fact"),
|
|
18
|
+
cognition.findByType("concept"),
|
|
19
|
+
cognition.findByType("reference"),
|
|
20
|
+
// cognition.findByType("summary"),
|
|
21
|
+
]);
|
|
22
|
+
|
|
23
|
+
const total =
|
|
24
|
+
decisions.length + facts.length + concepts.length + references.length;
|
|
25
|
+
// + summaries.length;
|
|
26
|
+
|
|
27
|
+
if (total === 0) {
|
|
28
|
+
const data: KnowledgeViewData = { mode: "empty" };
|
|
29
|
+
updateOutput("knowledge", JSON.stringify(data));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const data: KnowledgeViewData = {
|
|
34
|
+
mode: "summary",
|
|
35
|
+
data: {
|
|
36
|
+
decisions: decisions.map((d) => ({
|
|
37
|
+
content: d.content,
|
|
38
|
+
type: d.type,
|
|
39
|
+
})),
|
|
40
|
+
facts: facts.map((f) => ({ content: f.content, type: f.type })),
|
|
41
|
+
concepts: concepts.map((c) => ({
|
|
42
|
+
content: c.content,
|
|
43
|
+
type: c.type,
|
|
44
|
+
})),
|
|
45
|
+
references: references.map((r) => ({
|
|
46
|
+
content: r.content,
|
|
47
|
+
type: r.type,
|
|
48
|
+
})),
|
|
49
|
+
// summaries: summaries.map((s) => ({
|
|
50
|
+
// content: s.content,
|
|
51
|
+
// type: s.type,
|
|
52
|
+
// })),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
updateOutput("knowledge", JSON.stringify(data));
|
|
57
|
+
} else {
|
|
58
|
+
// Search knowledge
|
|
59
|
+
const query = args.join(" ");
|
|
60
|
+
const results = await cognition.retrieveRelevant(query, 10);
|
|
61
|
+
|
|
62
|
+
const data: KnowledgeViewData = {
|
|
63
|
+
mode: "search",
|
|
64
|
+
data: {
|
|
65
|
+
query,
|
|
66
|
+
results: results.map((r) => ({ content: r.content, type: r.type })),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
updateOutput("knowledge", JSON.stringify(data));
|
|
71
|
+
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
updateOutput("error", `Failed to retrieve knowledge: ${e}`);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const knowledgeCommand: Command = {
|
|
78
|
+
name: "knowledge",
|
|
79
|
+
description: "View or search stored project knowledge",
|
|
80
|
+
usage: "/knowledge",
|
|
81
|
+
action,
|
|
82
|
+
subcommands: [
|
|
83
|
+
{
|
|
84
|
+
name: "search",
|
|
85
|
+
description: "Search stored project knowledge",
|
|
86
|
+
usage: "/knowledge search <query>",
|
|
87
|
+
action,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default knowledgeCommand;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
4
|
+
import { getLogPath } from "@/utils/logger";
|
|
5
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
6
|
+
|
|
7
|
+
const logCommand: Command = {
|
|
8
|
+
name: "log",
|
|
9
|
+
description: "Save log for current session to local directory",
|
|
10
|
+
usage: "/log",
|
|
11
|
+
action: async () => {
|
|
12
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
13
|
+
try {
|
|
14
|
+
const sourcePath = getLogPath();
|
|
15
|
+
const destPath = path.join(process.cwd(), "debug.log");
|
|
16
|
+
|
|
17
|
+
if (fs.existsSync(sourcePath)) {
|
|
18
|
+
fs.copyFileSync(sourcePath, destPath);
|
|
19
|
+
updateOutput(
|
|
20
|
+
"log",
|
|
21
|
+
`Debug log for current session written to ${destPath}`,
|
|
22
|
+
);
|
|
23
|
+
} else {
|
|
24
|
+
updateOutput("log", "No debug log found.");
|
|
25
|
+
}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
updateOutput("error", `Error writing debug log: ${error}`);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default logCommand;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
2
|
+
import { UpdateSettings } from "@/config/settings";
|
|
3
|
+
import MistralClient from "@/services/mistral";
|
|
4
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
5
|
+
|
|
6
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
7
|
+
|
|
8
|
+
const mistralAuth = async (args: string[]) => {
|
|
9
|
+
const apiKey = args[0];
|
|
10
|
+
if (!apiKey) {
|
|
11
|
+
updateOutput("error", "No API key specified (Mistral)");
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
await UpdateSettings({ mistral_api_key: apiKey });
|
|
15
|
+
updateOutput("log", "✓ Mistral API key set");
|
|
16
|
+
await MistralClient.syncMistralModels();
|
|
17
|
+
updateOutput("log", "✓ Mistral models synced");
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const mistralAuthCommand: Command = {
|
|
21
|
+
name: "auth",
|
|
22
|
+
description: "Set Mistral API key",
|
|
23
|
+
usage: "/mistral auth <api-key>",
|
|
24
|
+
action: mistralAuth,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default mistralAuthCommand;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import mistralAuthCommand from "./auth";
|
|
3
|
+
|
|
4
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
5
|
+
|
|
6
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
7
|
+
|
|
8
|
+
const mistralCommands: Command = {
|
|
9
|
+
name: "mistral",
|
|
10
|
+
description: "Manage Mistral models",
|
|
11
|
+
usage: "/mistral <subcommand>",
|
|
12
|
+
action: async (args: string[]) => {
|
|
13
|
+
if (args.length === 0 || args[0] === "list" || args[0] === "models") {
|
|
14
|
+
updateOutput("settings", "/models:mistral");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
subcommands: [
|
|
19
|
+
mistralAuthCommand,
|
|
20
|
+
{
|
|
21
|
+
name: "list",
|
|
22
|
+
description: "List Mistral models",
|
|
23
|
+
usage: "/mistral list",
|
|
24
|
+
action: async () => {
|
|
25
|
+
updateOutput("settings", "/models:mistral");
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default mistralCommands;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import useSettingsStore from "@/store/useSettingsStore";
|
|
3
|
+
import { UpdateSettings } from "@/config/settings";
|
|
4
|
+
import {
|
|
5
|
+
parseModelDisplayId,
|
|
6
|
+
getModelDisplayId,
|
|
7
|
+
getModelUniqueId,
|
|
8
|
+
} from "@/types/Model";
|
|
9
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
10
|
+
|
|
11
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
12
|
+
|
|
13
|
+
const setModel = async (args: string[]) => {
|
|
14
|
+
const store = useSettingsStore.getState();
|
|
15
|
+
const models = store.models;
|
|
16
|
+
|
|
17
|
+
const subcommand = args[0]?.toLowerCase() ?? "";
|
|
18
|
+
|
|
19
|
+
// Role aliases
|
|
20
|
+
const roleAliases: Record<string, string> = {
|
|
21
|
+
p: "primary",
|
|
22
|
+
primary: "primary",
|
|
23
|
+
s: "secondary",
|
|
24
|
+
secondary: "secondary",
|
|
25
|
+
a: "all",
|
|
26
|
+
all: "all",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Check if first arg is a role command
|
|
30
|
+
const roleCommands = ["all", "primary", "secondary", "p", "s", "a"];
|
|
31
|
+
|
|
32
|
+
let modelName: string;
|
|
33
|
+
let role: string;
|
|
34
|
+
|
|
35
|
+
if (subcommand && roleCommands.includes(subcommand)) {
|
|
36
|
+
// Format: /model <role> <model-name>
|
|
37
|
+
role = roleAliases[subcommand] ?? subcommand;
|
|
38
|
+
modelName = args.slice(1).join(" ");
|
|
39
|
+
} else {
|
|
40
|
+
// Format: /model <model-name> [role]
|
|
41
|
+
// Check if last arg is a role
|
|
42
|
+
const lastArg = args[args.length - 1]?.toLowerCase() ?? "";
|
|
43
|
+
if (args.length > 1 && lastArg && roleAliases[lastArg]) {
|
|
44
|
+
role = roleAliases[lastArg];
|
|
45
|
+
modelName = args.slice(0, -1).join(" ");
|
|
46
|
+
} else {
|
|
47
|
+
role = "all";
|
|
48
|
+
modelName = args.join(" ");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (!modelName) {
|
|
52
|
+
updateOutput(
|
|
53
|
+
"log",
|
|
54
|
+
"Error: No model name specified. Use /model list to see current assignments.",
|
|
55
|
+
);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Try to parse as display ID (e.g., "model-name (provider)")
|
|
60
|
+
const parsed = parseModelDisplayId(modelName);
|
|
61
|
+
let matchedModel;
|
|
62
|
+
|
|
63
|
+
if (parsed) {
|
|
64
|
+
// Match by both name and provider type
|
|
65
|
+
matchedModel = models.find(
|
|
66
|
+
(m) =>
|
|
67
|
+
m.name.toLowerCase() === parsed.name.toLowerCase() &&
|
|
68
|
+
m.type === parsed.type,
|
|
69
|
+
);
|
|
70
|
+
} else {
|
|
71
|
+
// Fall back to name-only matching (for backwards compatibility)
|
|
72
|
+
// If multiple models have the same name, this picks the first one
|
|
73
|
+
matchedModel = models.find(
|
|
74
|
+
(m) => m.name.toLowerCase() === modelName.toLowerCase(),
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!matchedModel) {
|
|
79
|
+
updateOutput(
|
|
80
|
+
"error",
|
|
81
|
+
`Error: Model "${modelName}" not found. Use /model list to see available models.`,
|
|
82
|
+
);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Use unique ID (name|type) for storage to distinguish same-named models
|
|
87
|
+
const finalModelName = getModelUniqueId(matchedModel);
|
|
88
|
+
const displayName = getModelDisplayId(matchedModel);
|
|
89
|
+
const changedRoles: string[] =
|
|
90
|
+
role === "all" ? ["primary", "secondary"] : [role];
|
|
91
|
+
const updates: Record<string, string> = {};
|
|
92
|
+
|
|
93
|
+
switch (role) {
|
|
94
|
+
case "all":
|
|
95
|
+
updates.primaryModel = finalModelName;
|
|
96
|
+
updates.secondaryModel = finalModelName;
|
|
97
|
+
break;
|
|
98
|
+
case "primary":
|
|
99
|
+
updates.primaryModel = finalModelName;
|
|
100
|
+
break;
|
|
101
|
+
case "secondary":
|
|
102
|
+
updates.secondaryModel = finalModelName;
|
|
103
|
+
break;
|
|
104
|
+
default:
|
|
105
|
+
updateOutput(
|
|
106
|
+
"log",
|
|
107
|
+
`Unknown role: ${role}. Use: p|primary, s|secondary, a|all`,
|
|
108
|
+
);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Single write for all updates
|
|
113
|
+
await UpdateSettings(updates);
|
|
114
|
+
|
|
115
|
+
updateOutput(
|
|
116
|
+
"log",
|
|
117
|
+
`✓ Set ${changedRoles.join(", ")} model to: ${displayName}`,
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const modelSetCommands: Command = {
|
|
122
|
+
name: "model",
|
|
123
|
+
description: "Set active model(s) by role",
|
|
124
|
+
usage: "/model <model-name> <role>",
|
|
125
|
+
action: setModel,
|
|
126
|
+
subcommands: [
|
|
127
|
+
{
|
|
128
|
+
name: "all",
|
|
129
|
+
description: "Set model for all roles",
|
|
130
|
+
usage: "/model all <model-name>",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: "primary",
|
|
134
|
+
description: "Set primary model",
|
|
135
|
+
usage: "/model primary <model-name>",
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "secondary",
|
|
139
|
+
description: "Set secondary model",
|
|
140
|
+
usage: "/model secondary <model-name>",
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default modelSetCommands;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
3
|
+
|
|
4
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
5
|
+
|
|
6
|
+
const listModelsCommand: Command = {
|
|
7
|
+
name: "models",
|
|
8
|
+
description: "List available models",
|
|
9
|
+
usage: "/models [provider]",
|
|
10
|
+
action: async (args: string[]) => {
|
|
11
|
+
const provider = args[0]?.toLowerCase();
|
|
12
|
+
updateOutput("settings", provider ? `/models:${provider}` : "/models");
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default listModelsCommand;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
3
|
+
|
|
4
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
5
|
+
|
|
6
|
+
const ollamaCommand: Command = {
|
|
7
|
+
name: "ollama",
|
|
8
|
+
description: "Manage Ollama models",
|
|
9
|
+
usage: "/ollama [subcommand]",
|
|
10
|
+
action: async (args: string[]) => {
|
|
11
|
+
if (args.length === 0 || args[0] === "list" || args[0] === "models") {
|
|
12
|
+
updateOutput("settings", "/models:ollama");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
// Future: handle other ollama subcommands like pull, rm, etc.
|
|
16
|
+
},
|
|
17
|
+
subcommands: [
|
|
18
|
+
{
|
|
19
|
+
name: "list",
|
|
20
|
+
description: "List Ollama models",
|
|
21
|
+
usage: "/ollama list",
|
|
22
|
+
action: async () => {
|
|
23
|
+
updateOutput("settings", "/models:ollama");
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default ollamaCommand;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import { UpdateSettings } from "@/config/settings";
|
|
3
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
4
|
+
import OpenRouterClient from "@/services/openrouter";
|
|
5
|
+
import type { Model } from "@/types/Model";
|
|
6
|
+
import useSettingsStore from "@/store/useSettingsStore";
|
|
7
|
+
|
|
8
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
9
|
+
|
|
10
|
+
const addOpenRouterModel = async (args: string[]) => {
|
|
11
|
+
const model = args[0];
|
|
12
|
+
if (!model) {
|
|
13
|
+
updateOutput("error", "No model specified (OpenRouter)");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const data: any = await OpenRouterClient.getModelData(model);
|
|
17
|
+
const modelData = data.data;
|
|
18
|
+
|
|
19
|
+
if (!modelData) {
|
|
20
|
+
throw new Error(`No data found for OpenRouter model ${model}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const endpoint = modelData.endpoints?.[0];
|
|
24
|
+
|
|
25
|
+
const newModel: Model = {
|
|
26
|
+
type: "openrouter",
|
|
27
|
+
name: modelData.id,
|
|
28
|
+
modified_at: new Date(modelData.created * 1000).toISOString(),
|
|
29
|
+
digest: modelData.id,
|
|
30
|
+
capabilities: endpoint?.supported_parameters || [],
|
|
31
|
+
usage: {
|
|
32
|
+
promptTokens: 0,
|
|
33
|
+
completionTokens: 0,
|
|
34
|
+
totalTokens: 0,
|
|
35
|
+
},
|
|
36
|
+
details: {
|
|
37
|
+
context_length: endpoint?.context_length,
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const savedModels = useSettingsStore.getState().models || [];
|
|
42
|
+
|
|
43
|
+
// Check if model already exists, update if so, else add
|
|
44
|
+
const existingIndex = savedModels.findIndex(
|
|
45
|
+
(m) => m.name === newModel.name && m.type === "openrouter",
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
if (existingIndex >= 0) {
|
|
49
|
+
savedModels[existingIndex] = newModel;
|
|
50
|
+
} else {
|
|
51
|
+
savedModels.push(newModel);
|
|
52
|
+
}
|
|
53
|
+
await UpdateSettings({ models: savedModels });
|
|
54
|
+
updateOutput("log", "OpenRouter model added: " + model);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const addOpenRouterModelCommand: Command = {
|
|
58
|
+
name: "add",
|
|
59
|
+
description: "Add OpenRouter model",
|
|
60
|
+
usage: "/openrouter add <model>",
|
|
61
|
+
action: addOpenRouterModel,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export default addOpenRouterModelCommand;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import { UpdateSettings } from "@/config/settings";
|
|
3
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
4
|
+
|
|
5
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
6
|
+
|
|
7
|
+
const openRouterAuth = async (args: string[]) => {
|
|
8
|
+
const apiKey = args[0];
|
|
9
|
+
if (!apiKey) {
|
|
10
|
+
updateOutput("error", "No API key specified (OpenRouter)");
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
await UpdateSettings({ openrouter_api_key: apiKey });
|
|
14
|
+
updateOutput("log", "OpenRouter API key set");
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const openRouterAuthCommand: Command = {
|
|
18
|
+
name: "auth",
|
|
19
|
+
description: "Set OpenRouter API key",
|
|
20
|
+
usage: "/openrouter auth <api-key>",
|
|
21
|
+
action: openRouterAuth,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export default openRouterAuthCommand;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Command } from "@/types/CommandDefinition";
|
|
2
|
+
import openRouterAuthCommand from "./auth";
|
|
3
|
+
import addOpenRouterModelCommand from "./add_model";
|
|
4
|
+
|
|
5
|
+
import useFraudeStore from "@/store/useFraudeStore";
|
|
6
|
+
|
|
7
|
+
const { updateOutput } = useFraudeStore.getState();
|
|
8
|
+
|
|
9
|
+
const openRouterCommands: Command = {
|
|
10
|
+
name: "openrouter",
|
|
11
|
+
description: "Manage OpenRouter models",
|
|
12
|
+
usage: "/openrouter <subcommand>",
|
|
13
|
+
action: async (args: string[]) => {
|
|
14
|
+
if (args.length === 0 || args[0] === "list" || args[0] === "models") {
|
|
15
|
+
updateOutput("settings", "/models:openrouter");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
subcommands: [
|
|
20
|
+
openRouterAuthCommand,
|
|
21
|
+
addOpenRouterModelCommand,
|
|
22
|
+
{
|
|
23
|
+
name: "list",
|
|
24
|
+
description: "List OpenRouter models",
|
|
25
|
+
usage: "/openrouter list",
|
|
26
|
+
action: async () => {
|
|
27
|
+
updateOutput("settings", "/models:openrouter");
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default openRouterCommands;
|