@matterailab/orbcode 0.1.3
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/LICENSE +21 -0
- package/README.md +471 -0
- package/bin/orbcode.js +2 -0
- package/dist/api/client.js +141 -0
- package/dist/api/headers.js +14 -0
- package/dist/api/models.js +49 -0
- package/dist/api/stream.js +1 -0
- package/dist/auth/auth.js +172 -0
- package/dist/branding.js +31 -0
- package/dist/config/promptHistory.js +33 -0
- package/dist/config/settings.js +112 -0
- package/dist/core/agent.js +459 -0
- package/dist/core/events.js +1 -0
- package/dist/core/sessions.js +44 -0
- package/dist/headless.js +64 -0
- package/dist/index.js +84 -0
- package/dist/prompts/system.js +379 -0
- package/dist/tools/executors/executeCommand.js +58 -0
- package/dist/tools/executors/files.js +197 -0
- package/dist/tools/executors/listFiles.js +65 -0
- package/dist/tools/executors/searchFiles.js +104 -0
- package/dist/tools/executors/web.js +72 -0
- package/dist/tools/index.js +85 -0
- package/dist/tools/schemas/ask_followup_question.js +40 -0
- package/dist/tools/schemas/attempt_completion.js +19 -0
- package/dist/tools/schemas/browser_action.js +60 -0
- package/dist/tools/schemas/check_past_chat_memories.js +23 -0
- package/dist/tools/schemas/codebase_search.js +23 -0
- package/dist/tools/schemas/execute_command.js +31 -0
- package/dist/tools/schemas/fetch_instructions.js +20 -0
- package/dist/tools/schemas/file_edit.js +31 -0
- package/dist/tools/schemas/file_write.js +27 -0
- package/dist/tools/schemas/generate_image.js +27 -0
- package/dist/tools/schemas/index.js +29 -0
- package/dist/tools/schemas/list_code_definition_names.js +19 -0
- package/dist/tools/schemas/list_files.js +23 -0
- package/dist/tools/schemas/lsp.js +46 -0
- package/dist/tools/schemas/multi_file_edit.js +42 -0
- package/dist/tools/schemas/new_task.js +27 -0
- package/dist/tools/schemas/read_file.js +27 -0
- package/dist/tools/schemas/run_slash_command.js +23 -0
- package/dist/tools/schemas/search_files.js +27 -0
- package/dist/tools/schemas/switch_mode.js +23 -0
- package/dist/tools/schemas/update_todo_list.js +19 -0
- package/dist/tools/schemas/use_skill.js +19 -0
- package/dist/tools/schemas/web_fetch.js +19 -0
- package/dist/tools/schemas/web_search.js +19 -0
- package/dist/tools/types.js +7 -0
- package/dist/ui/App.js +569 -0
- package/dist/ui/LoginView.js +82 -0
- package/dist/ui/components/ApprovalPrompt.js +21 -0
- package/dist/ui/components/FollowupPrompt.js +45 -0
- package/dist/ui/components/Header.js +12 -0
- package/dist/ui/components/InputBox.js +220 -0
- package/dist/ui/components/ModelPicker.js +51 -0
- package/dist/ui/components/SessionPicker.js +52 -0
- package/dist/ui/components/Spinner.js +19 -0
- package/dist/ui/components/StatusBar.js +18 -0
- package/dist/ui/components/rows.js +106 -0
- package/dist/ui/markdown.js +64 -0
- package/dist/utils/diff.js +144 -0
- package/dist/utils/shell.js +19 -0
- package/package.json +62 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { resolveWorkspacePath } from "../types.js";
|
|
4
|
+
const IGNORED_DIRS = new Set([
|
|
5
|
+
"node_modules",
|
|
6
|
+
".git",
|
|
7
|
+
"dist",
|
|
8
|
+
"build",
|
|
9
|
+
"out",
|
|
10
|
+
".next",
|
|
11
|
+
".turbo",
|
|
12
|
+
"__pycache__",
|
|
13
|
+
".venv",
|
|
14
|
+
"venv",
|
|
15
|
+
]);
|
|
16
|
+
const MAX_ENTRIES = 800;
|
|
17
|
+
export function walkFiles(root, recursive, maxEntries = MAX_ENTRIES) {
|
|
18
|
+
const entries = [];
|
|
19
|
+
const queue = [root];
|
|
20
|
+
while (queue.length > 0 && entries.length < maxEntries) {
|
|
21
|
+
const dir = queue.shift();
|
|
22
|
+
let dirents;
|
|
23
|
+
try {
|
|
24
|
+
dirents = fs.readdirSync(dir, { withFileTypes: true });
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
dirents.sort((a, b) => a.name.localeCompare(b.name));
|
|
30
|
+
for (const dirent of dirents) {
|
|
31
|
+
if (entries.length >= maxEntries)
|
|
32
|
+
break;
|
|
33
|
+
const full = path.join(dir, dirent.name);
|
|
34
|
+
// Always report forward-slash paths: the UI (@-mention filtering) and
|
|
35
|
+
// the model both treat "/" as the separator, even on Windows.
|
|
36
|
+
const rel = path.relative(root, full).split(path.sep).join("/");
|
|
37
|
+
if (dirent.isDirectory()) {
|
|
38
|
+
entries.push(rel + "/");
|
|
39
|
+
if (recursive && !IGNORED_DIRS.has(dirent.name) && !dirent.name.startsWith(".")) {
|
|
40
|
+
queue.push(full);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
entries.push(rel);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return entries;
|
|
49
|
+
}
|
|
50
|
+
export async function listFiles(args, context) {
|
|
51
|
+
const dirPath = resolveWorkspacePath(context.cwd, String(args.path ?? "."));
|
|
52
|
+
const recursive = Boolean(args.recursive);
|
|
53
|
+
if (!fs.existsSync(dirPath)) {
|
|
54
|
+
return { text: `Directory not found: ${dirPath}`, isError: true };
|
|
55
|
+
}
|
|
56
|
+
const entries = walkFiles(dirPath, recursive);
|
|
57
|
+
if (entries.length === 0) {
|
|
58
|
+
return { text: `Directory ${dirPath} is empty.` };
|
|
59
|
+
}
|
|
60
|
+
let text = entries.join("\n");
|
|
61
|
+
if (entries.length >= MAX_ENTRIES) {
|
|
62
|
+
text += `\n\n(Truncated at ${MAX_ENTRIES} entries.)`;
|
|
63
|
+
}
|
|
64
|
+
return { text };
|
|
65
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import picomatch from "picomatch";
|
|
4
|
+
import { resolveWorkspacePath } from "../types.js";
|
|
5
|
+
const IGNORED_DIRS = new Set([
|
|
6
|
+
"node_modules",
|
|
7
|
+
".git",
|
|
8
|
+
"dist",
|
|
9
|
+
"build",
|
|
10
|
+
"out",
|
|
11
|
+
".next",
|
|
12
|
+
".turbo",
|
|
13
|
+
"__pycache__",
|
|
14
|
+
".venv",
|
|
15
|
+
"venv",
|
|
16
|
+
]);
|
|
17
|
+
const MAX_RESULTS = 300;
|
|
18
|
+
const MAX_FILE_SIZE = 2 * 1024 * 1024; // skip files over 2MB
|
|
19
|
+
const MAX_LINE_LENGTH = 500;
|
|
20
|
+
export async function searchFiles(args, context) {
|
|
21
|
+
const dirPath = resolveWorkspacePath(context.cwd, String(args.path ?? "."));
|
|
22
|
+
const regexSource = String(args.regex ?? "");
|
|
23
|
+
const filePattern = args.file_pattern == null || args.file_pattern === "" ? null : String(args.file_pattern);
|
|
24
|
+
let regex;
|
|
25
|
+
try {
|
|
26
|
+
regex = new RegExp(regexSource);
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
return { text: `Invalid regex: ${error.message}`, isError: true };
|
|
30
|
+
}
|
|
31
|
+
if (!fs.existsSync(dirPath)) {
|
|
32
|
+
return { text: `Directory not found: ${dirPath}`, isError: true };
|
|
33
|
+
}
|
|
34
|
+
// A bare pattern like "*.ts" should match at any depth, like ripgrep -g.
|
|
35
|
+
const isMatch = filePattern
|
|
36
|
+
? picomatch(filePattern.includes("/") ? filePattern : `**/${filePattern}`, { dot: true })
|
|
37
|
+
: () => true;
|
|
38
|
+
const results = [];
|
|
39
|
+
let matchCount = 0;
|
|
40
|
+
const walk = (dir) => {
|
|
41
|
+
if (matchCount >= MAX_RESULTS)
|
|
42
|
+
return;
|
|
43
|
+
let dirents;
|
|
44
|
+
try {
|
|
45
|
+
dirents = fs.readdirSync(dir, { withFileTypes: true });
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
for (const dirent of dirents) {
|
|
51
|
+
if (matchCount >= MAX_RESULTS)
|
|
52
|
+
return;
|
|
53
|
+
const full = path.join(dir, dirent.name);
|
|
54
|
+
if (dirent.isDirectory()) {
|
|
55
|
+
if (!IGNORED_DIRS.has(dirent.name) && !dirent.name.startsWith("."))
|
|
56
|
+
walk(full);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// picomatch only understands forward slashes, so normalize Windows paths.
|
|
60
|
+
const rel = path.relative(dirPath, full).split(path.sep).join("/");
|
|
61
|
+
if (!isMatch(rel))
|
|
62
|
+
continue;
|
|
63
|
+
let stat;
|
|
64
|
+
try {
|
|
65
|
+
stat = fs.statSync(full);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (stat.size > MAX_FILE_SIZE)
|
|
71
|
+
continue;
|
|
72
|
+
let content;
|
|
73
|
+
try {
|
|
74
|
+
content = fs.readFileSync(full, "utf8");
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (content.includes("\u0000"))
|
|
80
|
+
continue; // binary
|
|
81
|
+
const lines = content.split("\n");
|
|
82
|
+
const fileMatches = [];
|
|
83
|
+
for (let i = 0; i < lines.length && matchCount < MAX_RESULTS; i++) {
|
|
84
|
+
if (regex.test(lines[i])) {
|
|
85
|
+
matchCount++;
|
|
86
|
+
const lineText = lines[i].length > MAX_LINE_LENGTH ? lines[i].slice(0, MAX_LINE_LENGTH) + "…" : lines[i];
|
|
87
|
+
fileMatches.push(` ${i + 1}: ${lineText}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (fileMatches.length > 0) {
|
|
91
|
+
results.push(`${rel}\n${fileMatches.join("\n")}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
walk(dirPath);
|
|
96
|
+
if (results.length === 0) {
|
|
97
|
+
return { text: `No matches found for "${regexSource}" in ${dirPath}.` };
|
|
98
|
+
}
|
|
99
|
+
let text = `Found ${matchCount} match${matchCount === 1 ? "" : "es"}:\n\n${results.join("\n\n")}`;
|
|
100
|
+
if (matchCount >= MAX_RESULTS) {
|
|
101
|
+
text += `\n\n(Truncated at ${MAX_RESULTS} matches. Narrow your regex or file_pattern.)`;
|
|
102
|
+
}
|
|
103
|
+
return { text };
|
|
104
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { getUrlFromToken } from "../../auth/auth.js";
|
|
2
|
+
export async function webSearch(args, context) {
|
|
3
|
+
const query = String(args.query ?? "");
|
|
4
|
+
if (!query)
|
|
5
|
+
return { text: "FAILED: query is empty", isError: true };
|
|
6
|
+
try {
|
|
7
|
+
const url = getUrlFromToken("https://api.matterai.so/axoncode/websearch", context.token);
|
|
8
|
+
const response = await fetch(url, {
|
|
9
|
+
method: "POST",
|
|
10
|
+
headers: {
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
Authorization: `Bearer ${context.token}`,
|
|
13
|
+
},
|
|
14
|
+
body: JSON.stringify({ query }),
|
|
15
|
+
signal: AbortSignal.timeout(30_000),
|
|
16
|
+
});
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
return { text: `Web search failed (${response.status})`, isError: true };
|
|
19
|
+
}
|
|
20
|
+
const data = (await response.json());
|
|
21
|
+
const results = data.results;
|
|
22
|
+
if (!results || results.length === 0) {
|
|
23
|
+
return { text: `No results found for query: "${query}"` };
|
|
24
|
+
}
|
|
25
|
+
const formatted = results
|
|
26
|
+
.map((result, index) => {
|
|
27
|
+
let entry = `[${index + 1}] ${result.title}\nURL: ${result.url}`;
|
|
28
|
+
if (result.publish_date)
|
|
29
|
+
entry += `\nPublished: ${result.publish_date}`;
|
|
30
|
+
if (result.excerpts && result.excerpts.length > 0)
|
|
31
|
+
entry += `\n\n${result.excerpts.join("\n\n")}`;
|
|
32
|
+
return entry;
|
|
33
|
+
})
|
|
34
|
+
.join("\n\n---\n\n");
|
|
35
|
+
return { text: `Web search results for "${query}":\n\n${formatted}` };
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
return { text: `Web search failed: ${error.message}`, isError: true };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export async function webFetch(args, context) {
|
|
42
|
+
const targetUrl = String(args.url ?? "");
|
|
43
|
+
try {
|
|
44
|
+
new URL(targetUrl);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return { text: `Invalid URL format: ${targetUrl}`, isError: true };
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const apiUrl = getUrlFromToken("https://api.matterai.so/axoncode/webFetch", context.token);
|
|
51
|
+
const response = await fetch(apiUrl, {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: {
|
|
54
|
+
"Content-Type": "application/json",
|
|
55
|
+
Authorization: `Bearer ${context.token}`,
|
|
56
|
+
},
|
|
57
|
+
body: JSON.stringify({ url: targetUrl }),
|
|
58
|
+
signal: AbortSignal.timeout(30_000),
|
|
59
|
+
});
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
return { text: `Web fetch failed (${response.status})`, isError: true };
|
|
62
|
+
}
|
|
63
|
+
const data = (await response.json());
|
|
64
|
+
if (!data.excerpts || data.excerpts.length === 0) {
|
|
65
|
+
return { text: `No content could be extracted from URL: "${targetUrl}"` };
|
|
66
|
+
}
|
|
67
|
+
return { text: `Content from ${targetUrl}:\n\n${data.excerpts.join("\n\n")}` };
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
return { text: `Web fetch failed: ${error.message}`, isError: true };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { nativeTools } from "./schemas/index.js";
|
|
2
|
+
import { fileEdit, fileWrite, multiFileEdit, readFile } from "./executors/files.js";
|
|
3
|
+
import { listFiles } from "./executors/listFiles.js";
|
|
4
|
+
import { searchFiles } from "./executors/searchFiles.js";
|
|
5
|
+
import { executeCommand } from "./executors/executeCommand.js";
|
|
6
|
+
import { webFetch, webSearch } from "./executors/web.js";
|
|
7
|
+
export { nativeTools };
|
|
8
|
+
/** Tools that modify the user's system and need approval before running. */
|
|
9
|
+
export function getApprovalKind(toolName, args) {
|
|
10
|
+
switch (toolName) {
|
|
11
|
+
case "file_edit":
|
|
12
|
+
case "multi_file_edit":
|
|
13
|
+
case "file_write":
|
|
14
|
+
return "edit";
|
|
15
|
+
case "execute_command":
|
|
16
|
+
return "command";
|
|
17
|
+
default:
|
|
18
|
+
return "none";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** One-line human summary of a tool call, shown in the UI. */
|
|
22
|
+
export function describeToolCall(toolName, args) {
|
|
23
|
+
switch (toolName) {
|
|
24
|
+
case "read_file":
|
|
25
|
+
return String(args.file_path ?? "");
|
|
26
|
+
case "file_write":
|
|
27
|
+
return String(args.file_path ?? "");
|
|
28
|
+
case "file_edit":
|
|
29
|
+
return String(args.file_path ?? "");
|
|
30
|
+
case "multi_file_edit": {
|
|
31
|
+
const edits = Array.isArray(args.edits) ? args.edits : [];
|
|
32
|
+
const files = [...new Set(edits.map((e) => e.file_path ?? ""))];
|
|
33
|
+
return `${edits.length} edits in ${files.length} file${files.length === 1 ? "" : "s"}`;
|
|
34
|
+
}
|
|
35
|
+
case "execute_command":
|
|
36
|
+
return String(args.command ?? "");
|
|
37
|
+
case "list_files":
|
|
38
|
+
return `${args.path ?? "."}${args.recursive ? " (recursive)" : ""}`;
|
|
39
|
+
case "search_files":
|
|
40
|
+
return `/${args.regex ?? ""}/ in ${args.path ?? "."}${args.file_pattern ? ` (${args.file_pattern})` : ""}`;
|
|
41
|
+
case "web_search":
|
|
42
|
+
return String(args.query ?? "");
|
|
43
|
+
case "web_fetch":
|
|
44
|
+
return String(args.url ?? "");
|
|
45
|
+
case "update_todo_list":
|
|
46
|
+
return "updating tasks";
|
|
47
|
+
case "ask_followup_question":
|
|
48
|
+
return String(args.question ?? "");
|
|
49
|
+
case "attempt_completion":
|
|
50
|
+
return "task complete";
|
|
51
|
+
default:
|
|
52
|
+
return toolName;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const executors = {
|
|
56
|
+
read_file: readFile,
|
|
57
|
+
file_write: fileWrite,
|
|
58
|
+
file_edit: fileEdit,
|
|
59
|
+
multi_file_edit: multiFileEdit,
|
|
60
|
+
list_files: listFiles,
|
|
61
|
+
search_files: searchFiles,
|
|
62
|
+
execute_command: executeCommand,
|
|
63
|
+
web_search: webSearch,
|
|
64
|
+
web_fetch: webFetch,
|
|
65
|
+
update_todo_list: async (args, context) => {
|
|
66
|
+
context.setTodos(String(args.todos ?? ""));
|
|
67
|
+
return { text: "Todo list updated." };
|
|
68
|
+
},
|
|
69
|
+
// ask_followup_question and attempt_completion are handled by the agent loop.
|
|
70
|
+
};
|
|
71
|
+
export async function executeTool(toolName, args, context) {
|
|
72
|
+
const executor = executors[toolName];
|
|
73
|
+
if (!executor) {
|
|
74
|
+
return { text: `Tool "${toolName}" is not available in OrbCode CLI.`, isError: true };
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
return await executor(args, context);
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
return { text: `Tool ${toolName} failed: ${error.message}`, isError: true };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function getActiveTools() {
|
|
84
|
+
return nativeTools;
|
|
85
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "ask_followup_question",
|
|
5
|
+
description: "Ask the user a question to gather additional information needed to complete the task. Use when clarification or more detail is required before proceeding.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
question: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Clear, specific question that captures the missing information you need",
|
|
13
|
+
},
|
|
14
|
+
follow_up: {
|
|
15
|
+
type: ["array", "null"],
|
|
16
|
+
description: "Optional list of 2-4 suggested responses; each suggestion must be a complete, actionable answer and may include a mode switch",
|
|
17
|
+
items: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
text: {
|
|
21
|
+
type: "string",
|
|
22
|
+
description: "Suggested answer the user can pick",
|
|
23
|
+
},
|
|
24
|
+
mode: {
|
|
25
|
+
type: ["string", "null"],
|
|
26
|
+
description: "Optional mode slug to switch to if this suggestion is chosen (e.g., agent, plan)",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ["text", "mode"],
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
minItems: 2,
|
|
33
|
+
maxItems: 4,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
required: ["question"],
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "attempt_completion",
|
|
5
|
+
description: "After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must confirm that you've received successful results from the user for any previous tool uses. If not, then DO NOT use this tool.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
result: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Final result message to deliver to the user once the task is complete",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
required: ["result"],
|
|
16
|
+
additionalProperties: false,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "browser_action",
|
|
5
|
+
description: "Interact with a Puppeteer-controlled browser session. Always start by launching at a URL and always finish by closing the browser. While the browser is active, do not call any other tools. Use coordinates within the viewport to hover or click, provide text for typing, and ensure actions are grounded in the latest screenshot and console logs.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
action: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Browser action to perform",
|
|
13
|
+
enum: ["launch", "hover", "click", "type", "resize", "scroll_down", "scroll_up", "close"],
|
|
14
|
+
},
|
|
15
|
+
url: {
|
|
16
|
+
type: ["string", "null"],
|
|
17
|
+
description: "URL to open when performing the launch action; must include protocol",
|
|
18
|
+
},
|
|
19
|
+
coordinate: {
|
|
20
|
+
type: ["object", "null"],
|
|
21
|
+
description: "Screen coordinate for hover or click actions; target the center of the desired element",
|
|
22
|
+
properties: {
|
|
23
|
+
x: {
|
|
24
|
+
type: "number",
|
|
25
|
+
description: "Horizontal pixel position within the current viewport",
|
|
26
|
+
},
|
|
27
|
+
y: {
|
|
28
|
+
type: "number",
|
|
29
|
+
description: "Vertical pixel position within the current viewport",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
required: ["x", "y"],
|
|
33
|
+
additionalProperties: false,
|
|
34
|
+
},
|
|
35
|
+
size: {
|
|
36
|
+
type: ["object", "null"],
|
|
37
|
+
description: "Viewport dimensions to apply when performing the resize action",
|
|
38
|
+
properties: {
|
|
39
|
+
width: {
|
|
40
|
+
type: "number",
|
|
41
|
+
description: "Viewport width in pixels",
|
|
42
|
+
},
|
|
43
|
+
height: {
|
|
44
|
+
type: "number",
|
|
45
|
+
description: "Viewport height in pixels",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
required: ["width", "height"],
|
|
49
|
+
additionalProperties: false,
|
|
50
|
+
},
|
|
51
|
+
text: {
|
|
52
|
+
type: ["string", "null"],
|
|
53
|
+
description: "Text to type when performing the type action",
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
required: ["action"],
|
|
57
|
+
additionalProperties: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "check_past_chat_memories",
|
|
5
|
+
description: "Search through previous chat completion results to find relevant context from past tasks. Use this when you need to recall what was implemented or fixed in previous chats.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
regex: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Regular expression pattern to search memory contents",
|
|
13
|
+
},
|
|
14
|
+
workspace: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Filter by workspace directory (optional, defaults to current workspace)",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
required: ["regex"],
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "codebase_search",
|
|
5
|
+
description: "Run a semantic search across the workspace to find files relevant to a natural-language query. Reuse the user's wording where possible and keep queries in English.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
query: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Meaning-based search query describing the information you need",
|
|
13
|
+
},
|
|
14
|
+
path: {
|
|
15
|
+
type: ["string", "null"],
|
|
16
|
+
description: "Optional subdirectory (relative to the workspace) to limit the search scope",
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
required: ["query"],
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "execute_command",
|
|
5
|
+
description: "Run a CLI command on the user's system. Tailor the command to the environment, explain what it does, and prefer relative paths or shell-appropriate chaining. Use the cwd parameter only when directed to run in a different directory.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
command: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Shell command to execute",
|
|
13
|
+
},
|
|
14
|
+
cwd: {
|
|
15
|
+
type: ["string", "null"],
|
|
16
|
+
description: "Optional working directory for the command, relative or absolute",
|
|
17
|
+
},
|
|
18
|
+
message: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "A clear, concise one-line description of what the command does, shown to the user for approval (e.g. 'Install project dependencies with npm')",
|
|
21
|
+
},
|
|
22
|
+
isDangerous: {
|
|
23
|
+
type: "boolean",
|
|
24
|
+
description: "Set true when the command is potentially destructive or irreversible — e.g. deletes/overwrites files (rm, mv over existing paths), force-pushes or resets git history, drops/migrates databases, changes system/network/permission state, installs globally, or sends data to external services. Set false for safe read-only or routine commands (ls, cat, build, test, install local deps). The user's selected approval mode may auto-approve only commands marked false.",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ["command"],
|
|
28
|
+
additionalProperties: false,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "fetch_instructions",
|
|
5
|
+
description: "Retrieve detailed instructions for performing a predefined task, such as creating an MCP server or creating a mode.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
task: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Task identifier to fetch instructions for",
|
|
13
|
+
enum: ["create_mcp_server", "create_mode"],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
required: ["task"],
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "file_edit",
|
|
5
|
+
description: "Make exactly ONE text replacement in ONE file. DO NOT call this tool multiple times in sequence — if you have 2 or more edits, you MUST use multi_file_edit instead. Provide the current text (`old_string`) and the desired text (`new_string`). By default only a single uniquely matched occurrence is replaced; set `replace_all` to true to update every matching occurrence. old_string and new_string cannot be the same.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
file_path: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Absolute path to the file to modify (e.g., /Users/username/project/src/file.ts)",
|
|
13
|
+
},
|
|
14
|
+
old_string: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Exact text to replace. Provide enough context for a unique match. Use an empty string to replace the entire file.",
|
|
17
|
+
},
|
|
18
|
+
new_string: {
|
|
19
|
+
type: "string",
|
|
20
|
+
description: "Replacement text. This will be inserted in place of the matched section. Can be an empty string to delete the match.",
|
|
21
|
+
},
|
|
22
|
+
replace_all: {
|
|
23
|
+
type: "boolean",
|
|
24
|
+
description: "Set to true to replace every occurrence of the matched text. Defaults to false (replace a single uniquely identified occurrence).",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
required: ["file_path", "old_string", "new_string"],
|
|
28
|
+
additionalProperties: false,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "file_write",
|
|
5
|
+
description: "Create a new file that does not exists yet or overwrite a file with all the new content. Use this tool to write new files or completely rewrite existing files. The tool will create missing directories automatically. For partial edits to existing files, you will only use file_edit tool instead.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
file_path: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Absolute path to the file to write (e.g., /Users/username/project/src/file.ts)",
|
|
13
|
+
},
|
|
14
|
+
content: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Full content to write to the file. For new files, this is the complete file content. For existing files, this will replace the entire file content. Use actual newlines for line breaks; JSON escape sequences are handled automatically.",
|
|
17
|
+
},
|
|
18
|
+
line_count: {
|
|
19
|
+
type: "integer",
|
|
20
|
+
description: "Total number of lines in the content, counting blank lines. Used to verify content completeness.",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
required: ["file_path", "content", "line_count"],
|
|
24
|
+
additionalProperties: false,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
type: "function",
|
|
3
|
+
function: {
|
|
4
|
+
name: "generate_image",
|
|
5
|
+
description: "Create a new image or edit an existing one using OpenRouter image models. Provide a prompt describing the desired output, choose where to save the image in the current workspace, and optionally supply an input image to transform.",
|
|
6
|
+
strict: true,
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
prompt: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Text description of the image to generate or the edits to apply",
|
|
13
|
+
},
|
|
14
|
+
path: {
|
|
15
|
+
type: "string",
|
|
16
|
+
description: "Filesystem path (relative to the workspace) where the resulting image should be saved",
|
|
17
|
+
},
|
|
18
|
+
image: {
|
|
19
|
+
type: ["string", "null"],
|
|
20
|
+
description: "Optional path (relative to the workspace) to an existing image to edit; supports PNG, JPG, JPEG, GIF, and WEBP",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
required: ["prompt", "path"],
|
|
24
|
+
additionalProperties: false,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fileEdit from "./file_edit.js";
|
|
2
|
+
import multiFileEdit from "./multi_file_edit.js";
|
|
3
|
+
import fileWrite from "./file_write.js";
|
|
4
|
+
import askFollowupQuestion from "./ask_followup_question.js";
|
|
5
|
+
import attemptCompletion from "./attempt_completion.js";
|
|
6
|
+
import executeCommand from "./execute_command.js";
|
|
7
|
+
import listFiles from "./list_files.js";
|
|
8
|
+
import { read_file_single } from "./read_file.js";
|
|
9
|
+
import searchFiles from "./search_files.js";
|
|
10
|
+
import updateTodoList from "./update_todo_list.js";
|
|
11
|
+
import webFetch from "./web_fetch.js";
|
|
12
|
+
import webSearch from "./web_search.js";
|
|
13
|
+
// Native tool schemas ported verbatim from the Orbital extension (native-tools).
|
|
14
|
+
// Tools that depend on IDE-only services (codebase_search, lsp, use_skill,
|
|
15
|
+
// check_past_chat_memories, browser_action, …) are not active in the CLI.
|
|
16
|
+
export const nativeTools = [
|
|
17
|
+
fileEdit,
|
|
18
|
+
multiFileEdit,
|
|
19
|
+
fileWrite,
|
|
20
|
+
askFollowupQuestion,
|
|
21
|
+
attemptCompletion,
|
|
22
|
+
executeCommand,
|
|
23
|
+
listFiles,
|
|
24
|
+
read_file_single,
|
|
25
|
+
searchFiles,
|
|
26
|
+
updateTodoList,
|
|
27
|
+
webFetch,
|
|
28
|
+
webSearch,
|
|
29
|
+
];
|