joonecli 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/AGENTS.md +56 -0
- package/Handover.md +115 -0
- package/LICENSE +201 -0
- package/PROGRESS.md +160 -0
- package/README.md +114 -0
- package/dist/__tests__/bootstrap.test.d.ts +1 -0
- package/dist/__tests__/bootstrap.test.js +76 -0
- package/dist/__tests__/bootstrap.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +1 -0
- package/dist/__tests__/config.test.js +84 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/m55.test.d.ts +1 -0
- package/dist/__tests__/m55.test.js +160 -0
- package/dist/__tests__/m55.test.js.map +1 -0
- package/dist/__tests__/middleware.test.d.ts +1 -0
- package/dist/__tests__/middleware.test.js +169 -0
- package/dist/__tests__/middleware.test.js.map +1 -0
- package/dist/__tests__/modelFactory.test.d.ts +1 -0
- package/dist/__tests__/modelFactory.test.js +50 -0
- package/dist/__tests__/modelFactory.test.js.map +1 -0
- package/dist/__tests__/optimizations.test.d.ts +1 -0
- package/dist/__tests__/optimizations.test.js +136 -0
- package/dist/__tests__/optimizations.test.js.map +1 -0
- package/dist/__tests__/promptBuilder.test.d.ts +1 -0
- package/dist/__tests__/promptBuilder.test.js +108 -0
- package/dist/__tests__/promptBuilder.test.js.map +1 -0
- package/dist/__tests__/sandbox.test.d.ts +1 -0
- package/dist/__tests__/sandbox.test.js +78 -0
- package/dist/__tests__/sandbox.test.js.map +1 -0
- package/dist/__tests__/security.test.d.ts +1 -0
- package/dist/__tests__/security.test.js +86 -0
- package/dist/__tests__/security.test.js.map +1 -0
- package/dist/__tests__/streaming.test.d.ts +1 -0
- package/dist/__tests__/streaming.test.js +71 -0
- package/dist/__tests__/streaming.test.js.map +1 -0
- package/dist/__tests__/toolRouter.test.d.ts +1 -0
- package/dist/__tests__/toolRouter.test.js +37 -0
- package/dist/__tests__/toolRouter.test.js.map +1 -0
- package/dist/__tests__/tools.test.d.ts +1 -0
- package/dist/__tests__/tools.test.js +112 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/__tests__/tracing.test.d.ts +1 -0
- package/dist/__tests__/tracing.test.js +147 -0
- package/dist/__tests__/tracing.test.js.map +1 -0
- package/dist/cli/config.d.ts +49 -0
- package/dist/cli/config.js +86 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +625 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/modelFactory.d.ts +9 -0
- package/dist/cli/modelFactory.js +154 -0
- package/dist/cli/modelFactory.js.map +1 -0
- package/dist/cli/providers.d.ts +18 -0
- package/dist/cli/providers.js +94 -0
- package/dist/cli/providers.js.map +1 -0
- package/dist/core/agentLoop.d.ts +43 -0
- package/dist/core/agentLoop.js +245 -0
- package/dist/core/agentLoop.js.map +1 -0
- package/dist/core/errors.d.ts +62 -0
- package/dist/core/errors.js +139 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/promptBuilder.d.ts +49 -0
- package/dist/core/promptBuilder.js +84 -0
- package/dist/core/promptBuilder.js.map +1 -0
- package/dist/core/reasoningRouter.d.ts +62 -0
- package/dist/core/reasoningRouter.js +102 -0
- package/dist/core/reasoningRouter.js.map +1 -0
- package/dist/core/retry.d.ts +25 -0
- package/dist/core/retry.js +49 -0
- package/dist/core/retry.js.map +1 -0
- package/dist/core/sessionResumer.d.ts +17 -0
- package/dist/core/sessionResumer.js +78 -0
- package/dist/core/sessionResumer.js.map +1 -0
- package/dist/core/sessionStore.d.ts +45 -0
- package/dist/core/sessionStore.js +167 -0
- package/dist/core/sessionStore.js.map +1 -0
- package/dist/core/tokenCounter.d.ts +17 -0
- package/dist/core/tokenCounter.js +54 -0
- package/dist/core/tokenCounter.js.map +1 -0
- package/dist/evals/dataset.d.ts +4 -0
- package/dist/evals/dataset.js +61 -0
- package/dist/evals/dataset.js.map +1 -0
- package/dist/evals/evaluator.d.ts +21 -0
- package/dist/evals/evaluator.js +68 -0
- package/dist/evals/evaluator.js.map +1 -0
- package/dist/hitl/bridge.d.ts +65 -0
- package/dist/hitl/bridge.js +120 -0
- package/dist/hitl/bridge.js.map +1 -0
- package/dist/middleware/commandSanitizer.d.ts +18 -0
- package/dist/middleware/commandSanitizer.js +50 -0
- package/dist/middleware/commandSanitizer.js.map +1 -0
- package/dist/middleware/loopDetection.d.ts +28 -0
- package/dist/middleware/loopDetection.js +49 -0
- package/dist/middleware/loopDetection.js.map +1 -0
- package/dist/middleware/permission.d.ts +17 -0
- package/dist/middleware/permission.js +59 -0
- package/dist/middleware/permission.js.map +1 -0
- package/dist/middleware/pipeline.d.ts +31 -0
- package/dist/middleware/pipeline.js +62 -0
- package/dist/middleware/pipeline.js.map +1 -0
- package/dist/middleware/preCompletion.d.ts +29 -0
- package/dist/middleware/preCompletion.js +82 -0
- package/dist/middleware/preCompletion.js.map +1 -0
- package/dist/middleware/types.d.ts +40 -0
- package/dist/middleware/types.js +8 -0
- package/dist/middleware/types.js.map +1 -0
- package/dist/sandbox/bootstrap.d.ts +38 -0
- package/dist/sandbox/bootstrap.js +107 -0
- package/dist/sandbox/bootstrap.js.map +1 -0
- package/dist/sandbox/manager.d.ts +72 -0
- package/dist/sandbox/manager.js +180 -0
- package/dist/sandbox/manager.js.map +1 -0
- package/dist/sandbox/sync.d.ts +55 -0
- package/dist/sandbox/sync.js +135 -0
- package/dist/sandbox/sync.js.map +1 -0
- package/dist/skills/loader.d.ts +55 -0
- package/dist/skills/loader.js +132 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/tools.d.ts +5 -0
- package/dist/skills/tools.js +78 -0
- package/dist/skills/tools.js.map +1 -0
- package/dist/skills/types.d.ts +13 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/test_cache.d.ts +1 -0
- package/dist/test_cache.js +55 -0
- package/dist/test_cache.js.map +1 -0
- package/dist/test_google.js +93 -0
- package/dist/tools/askUser.d.ts +10 -0
- package/dist/tools/askUser.js +42 -0
- package/dist/tools/askUser.js.map +1 -0
- package/dist/tools/browser.d.ts +19 -0
- package/dist/tools/browser.js +111 -0
- package/dist/tools/browser.js.map +1 -0
- package/dist/tools/index.d.ts +27 -0
- package/dist/tools/index.js +184 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +31 -0
- package/dist/tools/registry.js +168 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/router.d.ts +34 -0
- package/dist/tools/router.js +73 -0
- package/dist/tools/router.js.map +1 -0
- package/dist/tools/security.d.ts +28 -0
- package/dist/tools/security.js +183 -0
- package/dist/tools/security.js.map +1 -0
- package/dist/tools/webSearch.d.ts +6 -0
- package/dist/tools/webSearch.js +120 -0
- package/dist/tools/webSearch.js.map +1 -0
- package/dist/tracing/analyzer.d.ts +58 -0
- package/dist/tracing/analyzer.js +190 -0
- package/dist/tracing/analyzer.js.map +1 -0
- package/dist/tracing/langsmith.d.ts +38 -0
- package/dist/tracing/langsmith.js +50 -0
- package/dist/tracing/langsmith.js.map +1 -0
- package/dist/tracing/sessionTracer.d.ts +73 -0
- package/dist/tracing/sessionTracer.js +157 -0
- package/dist/tracing/sessionTracer.js.map +1 -0
- package/dist/tracing/types.d.ts +46 -0
- package/dist/tracing/types.js +5 -0
- package/dist/tracing/types.js.map +1 -0
- package/dist/ui/App.d.ts +24 -0
- package/dist/ui/App.js +172 -0
- package/dist/ui/App.js.map +1 -0
- package/dist/ui/components/HITLPrompt.d.ts +15 -0
- package/dist/ui/components/HITLPrompt.js +35 -0
- package/dist/ui/components/HITLPrompt.js.map +1 -0
- package/dist/ui/components/Header.d.ts +8 -0
- package/dist/ui/components/Header.js +6 -0
- package/dist/ui/components/Header.js.map +1 -0
- package/dist/ui/components/MessageBubble.d.ts +13 -0
- package/dist/ui/components/MessageBubble.js +17 -0
- package/dist/ui/components/MessageBubble.js.map +1 -0
- package/dist/ui/components/StatusBar.d.ts +21 -0
- package/dist/ui/components/StatusBar.js +34 -0
- package/dist/ui/components/StatusBar.js.map +1 -0
- package/dist/ui/components/StreamingText.d.ts +13 -0
- package/dist/ui/components/StreamingText.js +24 -0
- package/dist/ui/components/StreamingText.js.map +1 -0
- package/dist/ui/components/ToolCallPanel.d.ts +15 -0
- package/dist/ui/components/ToolCallPanel.js +18 -0
- package/dist/ui/components/ToolCallPanel.js.map +1 -0
- package/docs/01_insights_and_patterns.md +27 -0
- package/docs/02_edge_cases_and_mitigations.md +143 -0
- package/docs/03_initial_implementation_plan.md +66 -0
- package/docs/04_tech_stack_proposal.md +20 -0
- package/docs/05_prd.md +87 -0
- package/docs/06_user_stories.md +72 -0
- package/docs/07_system_architecture.md +138 -0
- package/docs/08_roadmap.md +200 -0
- package/e2b/Dockerfile +26 -0
- package/package.json +57 -0
- package/src/__tests__/bootstrap.test.ts +111 -0
- package/src/__tests__/config.test.ts +97 -0
- package/src/__tests__/m55.test.ts +238 -0
- package/src/__tests__/middleware.test.ts +219 -0
- package/src/__tests__/modelFactory.test.ts +63 -0
- package/src/__tests__/optimizations.test.ts +201 -0
- package/src/__tests__/promptBuilder.test.ts +141 -0
- package/src/__tests__/sandbox.test.ts +102 -0
- package/src/__tests__/security.test.ts +122 -0
- package/src/__tests__/streaming.test.ts +82 -0
- package/src/__tests__/toolRouter.test.ts +52 -0
- package/src/__tests__/tools.test.ts +146 -0
- package/src/__tests__/tracing.test.ts +196 -0
- package/src/agents/agentRegistry.ts +69 -0
- package/src/agents/agentSpec.ts +67 -0
- package/src/agents/builtinAgents.ts +142 -0
- package/src/cli/config.ts +124 -0
- package/src/cli/index.ts +730 -0
- package/src/cli/modelFactory.ts +174 -0
- package/src/cli/providers.ts +107 -0
- package/src/commands/builtinCommands.ts +293 -0
- package/src/commands/commandRegistry.ts +194 -0
- package/src/core/agentLoop.d.ts.map +1 -0
- package/src/core/agentLoop.ts +312 -0
- package/src/core/autoSave.ts +95 -0
- package/src/core/compactor.ts +252 -0
- package/src/core/contextGuard.ts +129 -0
- package/src/core/errors.ts +202 -0
- package/src/core/promptBuilder.d.ts.map +1 -0
- package/src/core/promptBuilder.ts +139 -0
- package/src/core/reasoningRouter.ts +121 -0
- package/src/core/retry.ts +75 -0
- package/src/core/sessionResumer.ts +90 -0
- package/src/core/sessionStore.ts +215 -0
- package/src/core/subAgent.ts +339 -0
- package/src/core/tokenCounter.ts +64 -0
- package/src/evals/dataset.ts +67 -0
- package/src/evals/evaluator.ts +81 -0
- package/src/hitl/bridge.ts +160 -0
- package/src/middleware/commandSanitizer.ts +60 -0
- package/src/middleware/loopDetection.ts +63 -0
- package/src/middleware/permission.ts +72 -0
- package/src/middleware/pipeline.ts +75 -0
- package/src/middleware/preCompletion.ts +94 -0
- package/src/middleware/types.ts +45 -0
- package/src/sandbox/bootstrap.ts +121 -0
- package/src/sandbox/manager.ts +239 -0
- package/src/sandbox/sync.ts +157 -0
- package/src/skills/loader.ts +143 -0
- package/src/skills/tools.ts +99 -0
- package/src/skills/types.ts +13 -0
- package/src/test_cache.ts +72 -0
- package/src/test_google.js +40 -0
- package/src/test_google.ts +40 -0
- package/src/tools/askUser.ts +47 -0
- package/src/tools/browser.ts +137 -0
- package/src/tools/index.d.ts.map +1 -0
- package/src/tools/index.ts +237 -0
- package/src/tools/registry.ts +198 -0
- package/src/tools/router.ts +78 -0
- package/src/tools/security.ts +220 -0
- package/src/tools/spawnAgent.ts +158 -0
- package/src/tools/webSearch.ts +142 -0
- package/src/tracing/analyzer.ts +265 -0
- package/src/tracing/langsmith.ts +63 -0
- package/src/tracing/sessionTracer.ts +202 -0
- package/src/tracing/types.ts +49 -0
- package/src/types/valyu.d.ts +37 -0
- package/src/ui/App.tsx +404 -0
- package/src/ui/components/HITLPrompt.tsx +119 -0
- package/src/ui/components/Header.tsx +51 -0
- package/src/ui/components/MessageBubble.tsx +46 -0
- package/src/ui/components/StatusBar.tsx +138 -0
- package/src/ui/components/StreamingText.tsx +48 -0
- package/src/ui/components/ToolCallPanel.tsx +80 -0
- package/tests/commands/commands.test.ts +356 -0
- package/tests/core/compactor.test.ts +217 -0
- package/tests/core/retryAndErrors.test.ts +164 -0
- package/tests/core/sessionResumer.test.ts +95 -0
- package/tests/core/sessionStore.test.ts +84 -0
- package/tests/core/stability.test.ts +165 -0
- package/tests/core/subAgent.test.ts +238 -0
- package/tests/hitl/hitlBridge.test.ts +115 -0
- package/tsconfig.json +16 -0
- package/vitest.config.ts +10 -0
- package/vitest.out +48 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
// ─── Configuration ──────────────────────────────────────────────────────────────
|
|
4
|
+
/** Maximum file size (in bytes) the agent is allowed to read into context. */
|
|
5
|
+
const MAX_FILE_SIZE_BYTES = 512 * 1024; // 512 KB
|
|
6
|
+
/** Maximum number of lines to return if file exceeds line limit. */
|
|
7
|
+
const MAX_FILE_LINES = 2000;
|
|
8
|
+
// ─── Sandbox reference (set at session start) ───────────────────────────────────
|
|
9
|
+
let _sandboxManager = null;
|
|
10
|
+
let _fileSync = null;
|
|
11
|
+
/**
|
|
12
|
+
* Binds the tools to a SandboxManager and FileSync instance.
|
|
13
|
+
* Must be called at session start before any tool executions.
|
|
14
|
+
*/
|
|
15
|
+
export function bindSandbox(sandbox, fileSync) {
|
|
16
|
+
_sandboxManager = sandbox;
|
|
17
|
+
_fileSync = fileSync;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Security: Validates that a resolved path is strictly inside the given workspace dir.
|
|
21
|
+
* Prevents directory traversal attacks from accessing sensitive host files.
|
|
22
|
+
*/
|
|
23
|
+
export function isPathInsideWorkspace(resolvedPath, workspaceDir = process.cwd()) {
|
|
24
|
+
const normalizedWorkspace = path.resolve(workspaceDir);
|
|
25
|
+
// path.relative returns a path relative to the first argument.
|
|
26
|
+
// If it starts with '..' or is absolute, it means resolvedPath has escaped normalizedWorkspace.
|
|
27
|
+
const relative = path.relative(normalizedWorkspace, resolvedPath);
|
|
28
|
+
return relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
29
|
+
}
|
|
30
|
+
// ─── BashTool ───────────────────────────────────────────────────────────────────
|
|
31
|
+
// Executes shell commands inside the E2B sandbox.
|
|
32
|
+
// The ToolRouter routes this to SANDBOX — the host machine is never exposed.
|
|
33
|
+
export const BashTool = {
|
|
34
|
+
name: "bash",
|
|
35
|
+
description: "Runs a shell command inside an isolated sandbox. Use for tests, scripts, or installing dependencies. The host machine is never exposed.",
|
|
36
|
+
schema: {
|
|
37
|
+
type: "object",
|
|
38
|
+
properties: {
|
|
39
|
+
command: {
|
|
40
|
+
type: "string",
|
|
41
|
+
description: "The shell command to execute",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
required: ["command"],
|
|
45
|
+
},
|
|
46
|
+
execute: async (args) => {
|
|
47
|
+
if (!_sandboxManager || !_sandboxManager.isActive()) {
|
|
48
|
+
throw new Error("Sandbox is not active. Cannot execute bash commands without an active sandbox session.");
|
|
49
|
+
}
|
|
50
|
+
// Sync any dirty files from host → sandbox before executing
|
|
51
|
+
if (_fileSync && _fileSync.pendingCount() > 0) {
|
|
52
|
+
await _fileSync.syncToSandbox(_sandboxManager);
|
|
53
|
+
}
|
|
54
|
+
const result = await _sandboxManager.exec(args.command);
|
|
55
|
+
if (result.exitCode !== 0) {
|
|
56
|
+
return {
|
|
57
|
+
content: `Command failed (exit code ${result.exitCode}):\nSTDOUT:\n${result.stdout}\nSTDERR:\n${result.stderr}`,
|
|
58
|
+
metadata: { exitCode: result.exitCode },
|
|
59
|
+
isError: true
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
content: result.stdout || "(no output)",
|
|
64
|
+
metadata: { exitCode: result.exitCode },
|
|
65
|
+
isError: false
|
|
66
|
+
};
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
// ─── ReadFileTool ───────────────────────────────────────────────────────────────
|
|
70
|
+
// Reads files from the HOST filesystem (so the user's real project is visible).
|
|
71
|
+
// Includes a built-in file size guardrail to prevent sending huge files to the LLM.
|
|
72
|
+
export const ReadFileTool = {
|
|
73
|
+
name: "read_file",
|
|
74
|
+
description: "Reads a file from the host filesystem. Includes a file size guardrail — files over 512KB are truncated to prevent context overflow.",
|
|
75
|
+
schema: {
|
|
76
|
+
type: "object",
|
|
77
|
+
properties: {
|
|
78
|
+
path: {
|
|
79
|
+
type: "string",
|
|
80
|
+
description: "Absolute or relative path to the file",
|
|
81
|
+
},
|
|
82
|
+
startLine: {
|
|
83
|
+
type: "number",
|
|
84
|
+
description: "Optional 1-indexed start line for partial reads",
|
|
85
|
+
},
|
|
86
|
+
endLine: {
|
|
87
|
+
type: "number",
|
|
88
|
+
description: "Optional 1-indexed end line for partial reads",
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
required: ["path"],
|
|
92
|
+
},
|
|
93
|
+
execute: async (args) => {
|
|
94
|
+
const filePath = path.resolve(args.path);
|
|
95
|
+
// ── Security Guardrail ──
|
|
96
|
+
if (!isPathInsideWorkspace(filePath)) {
|
|
97
|
+
return {
|
|
98
|
+
content: `Security Error: Access Denied. Cannot read files outside the current project workspace (${process.cwd()}).`,
|
|
99
|
+
isError: true
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// ── Check existence ──
|
|
103
|
+
if (!fs.existsSync(filePath)) {
|
|
104
|
+
return {
|
|
105
|
+
content: `Error: File not found — ${filePath}`,
|
|
106
|
+
isError: true
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// ── File Size Guardrail ──
|
|
110
|
+
const stat = fs.statSync(filePath);
|
|
111
|
+
if (stat.size > MAX_FILE_SIZE_BYTES) {
|
|
112
|
+
return {
|
|
113
|
+
content: `Error: File too large (${Math.round(stat.size / 1024)}KB). Maximum size is 512KB. Use line ranges or grep_search.`,
|
|
114
|
+
isError: true
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const fileContent = fs.readFileSync(filePath, "utf-8");
|
|
118
|
+
const lines = fileContent.split("\n");
|
|
119
|
+
if (args.startLine !== undefined || args.endLine !== undefined) {
|
|
120
|
+
const start = Math.max(1, args.startLine ?? 1) - 1;
|
|
121
|
+
const end = Math.min(lines.length, args.endLine ?? lines.length);
|
|
122
|
+
const sliced = lines.slice(start, end);
|
|
123
|
+
return { content: sliced.map((line, i) => `${start + i + 1}: ${line}`).join("\n") };
|
|
124
|
+
}
|
|
125
|
+
// ── Line count guardrail ──
|
|
126
|
+
if (lines.length > MAX_FILE_LINES) {
|
|
127
|
+
const truncated = lines.slice(0, MAX_FILE_LINES);
|
|
128
|
+
return {
|
|
129
|
+
content: truncated.map((line, i) => `${i + 1}: ${line}`).join("\n") +
|
|
130
|
+
`\n\n--- Truncated at ${MAX_FILE_LINES} lines (total: ${lines.length}) ---`
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return { content: fileContent };
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
// ─── WriteFileTool ──────────────────────────────────────────────────────────────
|
|
137
|
+
// Writes files to the HOST filesystem (so the user sees changes in their IDE).
|
|
138
|
+
// Marks written files as dirty so FileSync uploads them before sandbox execution.
|
|
139
|
+
export const WriteFileTool = {
|
|
140
|
+
name: "write_file",
|
|
141
|
+
description: "Writes content to a file on the host filesystem. The user will see changes in their IDE immediately. The file is automatically synced to the sandbox before the next command execution.",
|
|
142
|
+
schema: {
|
|
143
|
+
type: "object",
|
|
144
|
+
properties: {
|
|
145
|
+
path: {
|
|
146
|
+
type: "string",
|
|
147
|
+
description: "Absolute or relative path to the file",
|
|
148
|
+
},
|
|
149
|
+
content: {
|
|
150
|
+
type: "string",
|
|
151
|
+
description: "The full file content to write",
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
required: ["path", "content"],
|
|
155
|
+
},
|
|
156
|
+
execute: async (args) => {
|
|
157
|
+
const filePath = path.resolve(args.path);
|
|
158
|
+
// ── Security Guardrail ──
|
|
159
|
+
if (!isPathInsideWorkspace(filePath)) {
|
|
160
|
+
return {
|
|
161
|
+
content: `Security Error: Access Denied. Cannot write files outside the current project workspace (${process.cwd()}).`,
|
|
162
|
+
isError: true
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
// Create parent directories if needed
|
|
166
|
+
const dir = path.dirname(filePath);
|
|
167
|
+
if (!fs.existsSync(dir)) {
|
|
168
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
169
|
+
}
|
|
170
|
+
fs.writeFileSync(filePath, args.content, "utf-8");
|
|
171
|
+
// Mark file as dirty for next sandbox sync
|
|
172
|
+
if (_fileSync) {
|
|
173
|
+
_fileSync.markDirty(filePath);
|
|
174
|
+
}
|
|
175
|
+
return { content: `File written: ${filePath}` };
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
// ─── Core Tool Set ──────────────────────────────────────────────────────────────
|
|
179
|
+
export const CORE_TOOLS = [
|
|
180
|
+
BashTool,
|
|
181
|
+
ReadFileTool,
|
|
182
|
+
WriteFileTool,
|
|
183
|
+
];
|
|
184
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DynamicToolInterface } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Lazy Tool Registry
|
|
4
|
+
*
|
|
5
|
+
* Instead of loading all complex tools into the System Prompt (which burns tokens
|
|
6
|
+
* and risks cache invalidation if changed), this registry maintains "stubs" —
|
|
7
|
+
* lightweight descriptors that let the agent discover tools on demand.
|
|
8
|
+
*
|
|
9
|
+
* Tools in DeferredToolsDB are NOT sent to the LLM by default. The agent can
|
|
10
|
+
* search for them via SearchToolsTool, then activate them via ActivateToolTool.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DeferredToolsDB: Record<string, DynamicToolInterface>;
|
|
13
|
+
/**
|
|
14
|
+
* Returns a tool that has been dynamically activated.
|
|
15
|
+
*/
|
|
16
|
+
export declare function getActivatedTool(name: string): DynamicToolInterface | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Returns all currently activated tools.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getActivatedTools(): DynamicToolInterface[];
|
|
21
|
+
/**
|
|
22
|
+
* Activates a tool from the deferred registry, making it available for execution.
|
|
23
|
+
* Returns the activated tool, or undefined if not found.
|
|
24
|
+
*/
|
|
25
|
+
export declare function activateTool(name: string): DynamicToolInterface | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Resets all activated tools. For testing.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resetActivatedTools(): void;
|
|
30
|
+
export declare const SearchToolsTool: DynamicToolInterface;
|
|
31
|
+
export declare const ActivateToolTool: DynamicToolInterface;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy Tool Registry
|
|
3
|
+
*
|
|
4
|
+
* Instead of loading all complex tools into the System Prompt (which burns tokens
|
|
5
|
+
* and risks cache invalidation if changed), this registry maintains "stubs" —
|
|
6
|
+
* lightweight descriptors that let the agent discover tools on demand.
|
|
7
|
+
*
|
|
8
|
+
* Tools in DeferredToolsDB are NOT sent to the LLM by default. The agent can
|
|
9
|
+
* search for them via SearchToolsTool, then activate them via ActivateToolTool.
|
|
10
|
+
*/
|
|
11
|
+
// ─── Deferred (Lazy) Tools ─────────────────────────────────────────────────────
|
|
12
|
+
export const DeferredToolsDB = {
|
|
13
|
+
git_commit: {
|
|
14
|
+
name: "git_commit",
|
|
15
|
+
description: "Creates a new git commit with staged changes.",
|
|
16
|
+
schema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: { message: { type: "string" } },
|
|
19
|
+
required: ["message"],
|
|
20
|
+
},
|
|
21
|
+
execute: async (args) => ({ content: `Committed with message: ${args.message}` }),
|
|
22
|
+
},
|
|
23
|
+
git_diff: {
|
|
24
|
+
name: "git_diff",
|
|
25
|
+
description: "Shows the diff of uncommitted changes or between two branches/commits.",
|
|
26
|
+
schema: {
|
|
27
|
+
type: "object",
|
|
28
|
+
properties: {
|
|
29
|
+
target: {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Branch, commit, or file path (optional)",
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
execute: async (args) => ({ content: `Diff for: ${args.target || "working directory"}` }),
|
|
36
|
+
},
|
|
37
|
+
git_log: {
|
|
38
|
+
name: "git_log",
|
|
39
|
+
description: "Shows recent commit history with messages and hashes.",
|
|
40
|
+
schema: {
|
|
41
|
+
type: "object",
|
|
42
|
+
properties: {
|
|
43
|
+
count: {
|
|
44
|
+
type: "number",
|
|
45
|
+
description: "Number of recent commits to show (default: 10)",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
execute: async (args) => ({ content: `Showing last ${args.count || 10} commits.` }),
|
|
50
|
+
},
|
|
51
|
+
grep_search: {
|
|
52
|
+
name: "grep_search",
|
|
53
|
+
description: "Searches for a text pattern across project files using ripgrep. Returns matching lines with filenames and line numbers.",
|
|
54
|
+
schema: {
|
|
55
|
+
type: "object",
|
|
56
|
+
properties: {
|
|
57
|
+
query: { type: "string", description: "Search pattern (regex supported)" },
|
|
58
|
+
path: { type: "string", description: "Directory or file to search in (default: .)" },
|
|
59
|
+
includes: { type: "string", description: "File glob filter (e.g., '*.ts')" },
|
|
60
|
+
},
|
|
61
|
+
required: ["query"],
|
|
62
|
+
},
|
|
63
|
+
execute: async (args) => ({ content: `Search results for '${args.query}'` }),
|
|
64
|
+
},
|
|
65
|
+
list_dir: {
|
|
66
|
+
name: "list_dir",
|
|
67
|
+
description: "Lists the contents of a directory — files and subdirectories with sizes.",
|
|
68
|
+
schema: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
path: { type: "string", description: "Directory path to list" },
|
|
72
|
+
},
|
|
73
|
+
required: ["path"],
|
|
74
|
+
},
|
|
75
|
+
execute: async (args) => ({ content: `Directory listing for: ${args.path}` }),
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
// ─── Active Tool Set (starts empty, filled by ActivateToolTool) ─────────────
|
|
79
|
+
const activatedTools = new Map();
|
|
80
|
+
/**
|
|
81
|
+
* Returns a tool that has been dynamically activated.
|
|
82
|
+
*/
|
|
83
|
+
export function getActivatedTool(name) {
|
|
84
|
+
return activatedTools.get(name);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Returns all currently activated tools.
|
|
88
|
+
*/
|
|
89
|
+
export function getActivatedTools() {
|
|
90
|
+
return Array.from(activatedTools.values());
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Activates a tool from the deferred registry, making it available for execution.
|
|
94
|
+
* Returns the activated tool, or undefined if not found.
|
|
95
|
+
*/
|
|
96
|
+
export function activateTool(name) {
|
|
97
|
+
const tool = DeferredToolsDB[name];
|
|
98
|
+
if (!tool)
|
|
99
|
+
return undefined;
|
|
100
|
+
activatedTools.set(name, tool);
|
|
101
|
+
return tool;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Resets all activated tools. For testing.
|
|
105
|
+
*/
|
|
106
|
+
export function resetActivatedTools() {
|
|
107
|
+
activatedTools.clear();
|
|
108
|
+
}
|
|
109
|
+
// ─── SearchToolsTool ────────────────────────────────────────────────────────────
|
|
110
|
+
/**
|
|
111
|
+
* Fuzzy search: matches on tool name OR any word in the description.
|
|
112
|
+
*/
|
|
113
|
+
function fuzzyMatch(query, tool) {
|
|
114
|
+
const q = query.toLowerCase();
|
|
115
|
+
const nameMatch = tool.name.toLowerCase().includes(q);
|
|
116
|
+
const descWords = tool.description.toLowerCase();
|
|
117
|
+
const descMatch = descWords.includes(q);
|
|
118
|
+
return nameMatch || descMatch;
|
|
119
|
+
}
|
|
120
|
+
export const SearchToolsTool = {
|
|
121
|
+
name: "search_tools",
|
|
122
|
+
description: "Search for advanced tools available in the environment. Matches by tool name or description keywords.",
|
|
123
|
+
schema: {
|
|
124
|
+
type: "object",
|
|
125
|
+
properties: {
|
|
126
|
+
query: { type: "string", description: "Search query" },
|
|
127
|
+
},
|
|
128
|
+
required: ["query"],
|
|
129
|
+
},
|
|
130
|
+
execute: async (args) => {
|
|
131
|
+
const matches = Object.values(DeferredToolsDB).filter((tool) => fuzzyMatch(args.query, tool));
|
|
132
|
+
if (matches.length === 0) {
|
|
133
|
+
return { content: `No tools found matching '${args.query}'. Available categories: git, file, search.` };
|
|
134
|
+
}
|
|
135
|
+
const descriptions = matches.map((t) => `- **${t.name}**: ${t.description}`);
|
|
136
|
+
return {
|
|
137
|
+
content: `Found ${matches.length} tool(s):\n${descriptions.join("\n")}\n\n` +
|
|
138
|
+
`To use a tool, call activate_tool with its name.`
|
|
139
|
+
};
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
// ─── ActivateToolTool ───────────────────────────────────────────────────────────
|
|
143
|
+
export const ActivateToolTool = {
|
|
144
|
+
name: "activate_tool",
|
|
145
|
+
description: "Activates a discovered tool for use. Call search_tools first to find available tools.",
|
|
146
|
+
schema: {
|
|
147
|
+
type: "object",
|
|
148
|
+
properties: {
|
|
149
|
+
name: { type: "string", description: "The tool name to activate" },
|
|
150
|
+
},
|
|
151
|
+
required: ["name"],
|
|
152
|
+
},
|
|
153
|
+
execute: async (args) => {
|
|
154
|
+
const tool = activateTool(args.name);
|
|
155
|
+
if (!tool) {
|
|
156
|
+
return {
|
|
157
|
+
content: `Error: Tool '${args.name}' not found in the registry. Use search_tools to see available tools.`,
|
|
158
|
+
isError: true
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
content: `✓ Tool '${args.name}' activated.\n` +
|
|
163
|
+
`Schema: ${JSON.stringify(tool.schema, null, 2)}\n` +
|
|
164
|
+
`You can now call it directly.`
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a tool executes — on the host machine or in the sandbox.
|
|
3
|
+
*/
|
|
4
|
+
export declare enum ToolTarget {
|
|
5
|
+
/** Run on the host (Node.js process). User sees changes in IDE. */
|
|
6
|
+
HOST = "host",
|
|
7
|
+
/** Run inside the E2B sandbox. Commands are isolated. */
|
|
8
|
+
SANDBOX = "sandbox"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Routes tool calls to either the host machine or the E2B sandbox.
|
|
12
|
+
*
|
|
13
|
+
* Design principle: File I/O runs on the host so the user sees changes
|
|
14
|
+
* in their IDE in real-time. Code execution runs in the sandbox for safety.
|
|
15
|
+
*
|
|
16
|
+
* Unknown tools default to SANDBOX (safe-by-default).
|
|
17
|
+
*/
|
|
18
|
+
export declare class ToolRouter {
|
|
19
|
+
/**
|
|
20
|
+
* Determines where a tool should execute.
|
|
21
|
+
*
|
|
22
|
+
* @param toolName The name of the tool being invoked.
|
|
23
|
+
* @returns ToolTarget.HOST or ToolTarget.SANDBOX
|
|
24
|
+
*/
|
|
25
|
+
getTarget(toolName: string): ToolTarget;
|
|
26
|
+
/**
|
|
27
|
+
* Returns true if the tool should run on the host.
|
|
28
|
+
*/
|
|
29
|
+
isHostTool(toolName: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Returns true if the tool should run in the sandbox.
|
|
32
|
+
*/
|
|
33
|
+
isSandboxTool(toolName: string): boolean;
|
|
34
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a tool executes — on the host machine or in the sandbox.
|
|
3
|
+
*/
|
|
4
|
+
export var ToolTarget;
|
|
5
|
+
(function (ToolTarget) {
|
|
6
|
+
/** Run on the host (Node.js process). User sees changes in IDE. */
|
|
7
|
+
ToolTarget["HOST"] = "host";
|
|
8
|
+
/** Run inside the E2B sandbox. Commands are isolated. */
|
|
9
|
+
ToolTarget["SANDBOX"] = "sandbox";
|
|
10
|
+
})(ToolTarget || (ToolTarget = {}));
|
|
11
|
+
/**
|
|
12
|
+
* Tools that execute on the host machine (no code execution risk).
|
|
13
|
+
*/
|
|
14
|
+
const HOST_TOOLS = new Set([
|
|
15
|
+
"write_file",
|
|
16
|
+
"read_file",
|
|
17
|
+
"search_tools",
|
|
18
|
+
"activate_tool",
|
|
19
|
+
"list_files",
|
|
20
|
+
"search_files",
|
|
21
|
+
"web_search",
|
|
22
|
+
"search_skills",
|
|
23
|
+
"load_skill",
|
|
24
|
+
]);
|
|
25
|
+
/**
|
|
26
|
+
* Tools that execute inside the sandboxed environment.
|
|
27
|
+
*/
|
|
28
|
+
const SANDBOX_TOOLS = new Set([
|
|
29
|
+
"bash",
|
|
30
|
+
"run_tests",
|
|
31
|
+
"install_deps",
|
|
32
|
+
"run_command",
|
|
33
|
+
"python",
|
|
34
|
+
"security_scan",
|
|
35
|
+
"dep_scan",
|
|
36
|
+
"browser",
|
|
37
|
+
]);
|
|
38
|
+
/**
|
|
39
|
+
* Routes tool calls to either the host machine or the E2B sandbox.
|
|
40
|
+
*
|
|
41
|
+
* Design principle: File I/O runs on the host so the user sees changes
|
|
42
|
+
* in their IDE in real-time. Code execution runs in the sandbox for safety.
|
|
43
|
+
*
|
|
44
|
+
* Unknown tools default to SANDBOX (safe-by-default).
|
|
45
|
+
*/
|
|
46
|
+
export class ToolRouter {
|
|
47
|
+
/**
|
|
48
|
+
* Determines where a tool should execute.
|
|
49
|
+
*
|
|
50
|
+
* @param toolName The name of the tool being invoked.
|
|
51
|
+
* @returns ToolTarget.HOST or ToolTarget.SANDBOX
|
|
52
|
+
*/
|
|
53
|
+
getTarget(toolName) {
|
|
54
|
+
if (HOST_TOOLS.has(toolName)) {
|
|
55
|
+
return ToolTarget.HOST;
|
|
56
|
+
}
|
|
57
|
+
// Default: sandbox (safe-by-default — never execute unknown tools on host)
|
|
58
|
+
return ToolTarget.SANDBOX;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns true if the tool should run on the host.
|
|
62
|
+
*/
|
|
63
|
+
isHostTool(toolName) {
|
|
64
|
+
return this.getTarget(toolName) === ToolTarget.HOST;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns true if the tool should run in the sandbox.
|
|
68
|
+
*/
|
|
69
|
+
isSandboxTool(toolName) {
|
|
70
|
+
return this.getTarget(toolName) === ToolTarget.SANDBOX;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/tools/router.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAN,IAAY,UAKX;AALD,WAAY,UAAU;IACpB,mEAAmE;IACnE,2BAAa,CAAA;IACb,yDAAyD;IACzD,iCAAmB,CAAA;AACrB,CAAC,EALW,UAAU,KAAV,UAAU,QAKrB;AAED;;GAEG;AACH,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IACzB,YAAY;IACZ,WAAW;IACX,cAAc;IACd,eAAe;IACf,YAAY;IACZ,cAAc;IACd,YAAY;IACZ,eAAe;IACf,YAAY;CACb,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,MAAM;IACN,WAAW;IACX,cAAc;IACd,aAAa;IACb,QAAQ;IACR,eAAe;IACf,UAAU;IACV,SAAS;CACV,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,OAAO,UAAU;IACrB;;;;;OAKG;IACH,SAAS,CAAC,QAAgB;QACxB,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,OAAO,UAAU,CAAC,IAAI,CAAC;QACzB,CAAC;QACD,2EAA2E;QAC3E,OAAO,UAAU,CAAC,OAAO,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,QAAgB;QACzB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,UAAU,CAAC,OAAO,CAAC;IACzD,CAAC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SandboxManager } from "../sandbox/manager.js";
|
|
2
|
+
import { LazyInstaller } from "../sandbox/bootstrap.js";
|
|
3
|
+
import { DynamicToolInterface } from "./index.js";
|
|
4
|
+
/**
|
|
5
|
+
* Binds the security tools to the sandbox and installer.
|
|
6
|
+
* Must be called at session start.
|
|
7
|
+
*/
|
|
8
|
+
export declare function bindSecuritySandbox(sandbox: SandboxManager, installer: LazyInstaller): void;
|
|
9
|
+
/**
|
|
10
|
+
* Scans code for security vulnerabilities using the Gemini CLI Security Extension.
|
|
11
|
+
*
|
|
12
|
+
* Execution flow:
|
|
13
|
+
* 1. LazyInstaller ensures Gemini CLI + security extension are in the sandbox.
|
|
14
|
+
* 2. Runs `gemini -x security:analyze` in the sandbox.
|
|
15
|
+
* 3. Returns the generated security report.
|
|
16
|
+
*
|
|
17
|
+
* If Gemini CLI installation fails, returns a descriptive fallback message
|
|
18
|
+
* suggesting manual review or alternative tools.
|
|
19
|
+
*/
|
|
20
|
+
export declare const SecurityScanTool: DynamicToolInterface;
|
|
21
|
+
/**
|
|
22
|
+
* Scans project dependencies for known vulnerabilities.
|
|
23
|
+
*
|
|
24
|
+
* Execution flow:
|
|
25
|
+
* 1. Try OSV-Scanner (more comprehensive, covers multiple ecosystems).
|
|
26
|
+
* 2. Fall back to `npm audit --json` (always available in Node sandboxes).
|
|
27
|
+
*/
|
|
28
|
+
export declare const DepScanTool: DynamicToolInterface;
|