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,132 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
/**
|
|
5
|
+
* SkillLoader — discovers and loads skills from multiple directories.
|
|
6
|
+
*
|
|
7
|
+
* Discovery paths (priority order — project overrides user):
|
|
8
|
+
* 1. Project root: ./skills/, ./.agents/skills/, ./.agent/skills/
|
|
9
|
+
* 2. User home: ~/.joone/skills/, ~/.agents/skills/
|
|
10
|
+
*
|
|
11
|
+
* On Windows, ~ resolves to %USERPROFILE%.
|
|
12
|
+
*
|
|
13
|
+
* Skills are folders containing a SKILL.md with YAML frontmatter:
|
|
14
|
+
* ---
|
|
15
|
+
* name: my-skill
|
|
16
|
+
* description: What this skill does
|
|
17
|
+
* ---
|
|
18
|
+
* ## Instructions
|
|
19
|
+
* ...
|
|
20
|
+
*/
|
|
21
|
+
export class SkillLoader {
|
|
22
|
+
projectRoot;
|
|
23
|
+
userHome;
|
|
24
|
+
cachedSkills = null;
|
|
25
|
+
constructor(projectRoot, userHome) {
|
|
26
|
+
this.projectRoot = projectRoot ?? process.cwd();
|
|
27
|
+
this.userHome = userHome ?? os.homedir();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns all skill discovery directories in priority order.
|
|
31
|
+
* Project-level directories come first (higher priority).
|
|
32
|
+
*/
|
|
33
|
+
getDiscoveryPaths() {
|
|
34
|
+
const home = this.userHome;
|
|
35
|
+
return [
|
|
36
|
+
// Project-level (highest priority)
|
|
37
|
+
{ path: path.join(this.projectRoot, "skills"), source: "project" },
|
|
38
|
+
{ path: path.join(this.projectRoot, ".agents", "skills"), source: "project" },
|
|
39
|
+
{ path: path.join(this.projectRoot, ".agent", "skills"), source: "project" },
|
|
40
|
+
// User-level
|
|
41
|
+
{ path: path.join(home, ".joone", "skills"), source: "user" },
|
|
42
|
+
{ path: path.join(home, ".agents", "skills"), source: "user" },
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parses YAML frontmatter from a SKILL.md content string.
|
|
47
|
+
* Simple parser — handles `name:` and `description:` fields.
|
|
48
|
+
*/
|
|
49
|
+
parseFrontmatter(content) {
|
|
50
|
+
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
51
|
+
if (!match)
|
|
52
|
+
return {};
|
|
53
|
+
const yaml = match[1];
|
|
54
|
+
const nameMatch = yaml.match(/^name:\s*(.+)$/m);
|
|
55
|
+
const descMatch = yaml.match(/^description:\s*(.+)$/m);
|
|
56
|
+
return {
|
|
57
|
+
name: nameMatch?.[1]?.trim(),
|
|
58
|
+
description: descMatch?.[1]?.trim(),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Discovers all available skills from all discovery paths.
|
|
63
|
+
* Deduplicates by name — project-level skills override user-level.
|
|
64
|
+
* Results are cached per session.
|
|
65
|
+
*/
|
|
66
|
+
discoverSkills() {
|
|
67
|
+
if (this.cachedSkills)
|
|
68
|
+
return this.cachedSkills;
|
|
69
|
+
const skills = new Map();
|
|
70
|
+
const paths = this.getDiscoveryPaths();
|
|
71
|
+
for (const { path: dir, source } of paths) {
|
|
72
|
+
if (!fs.existsSync(dir))
|
|
73
|
+
continue;
|
|
74
|
+
let entries;
|
|
75
|
+
try {
|
|
76
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
for (const entry of entries) {
|
|
82
|
+
if (!entry.isDirectory())
|
|
83
|
+
continue;
|
|
84
|
+
const skillMdPath = path.join(dir, entry.name, "SKILL.md");
|
|
85
|
+
if (!fs.existsSync(skillMdPath))
|
|
86
|
+
continue;
|
|
87
|
+
try {
|
|
88
|
+
const content = fs.readFileSync(skillMdPath, "utf-8");
|
|
89
|
+
const frontmatter = this.parseFrontmatter(content);
|
|
90
|
+
const name = frontmatter.name || entry.name;
|
|
91
|
+
// Only add if not already found (project overrides user)
|
|
92
|
+
if (!skills.has(name)) {
|
|
93
|
+
skills.set(name, {
|
|
94
|
+
name,
|
|
95
|
+
description: frontmatter.description || `Skill: ${name}`,
|
|
96
|
+
path: skillMdPath,
|
|
97
|
+
source,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
// Skip unreadable skills
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
this.cachedSkills = Array.from(skills.values());
|
|
107
|
+
return this.cachedSkills;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Loads the full content of a specific skill's SKILL.md.
|
|
111
|
+
* Returns undefined if the skill is not found.
|
|
112
|
+
*/
|
|
113
|
+
loadSkill(name) {
|
|
114
|
+
const skills = this.discoverSkills();
|
|
115
|
+
const skill = skills.find((s) => s.name === name);
|
|
116
|
+
if (!skill)
|
|
117
|
+
return undefined;
|
|
118
|
+
try {
|
|
119
|
+
return fs.readFileSync(skill.path, "utf-8");
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Clears the cached skills. Call when skills directory contents may have changed.
|
|
127
|
+
*/
|
|
128
|
+
clearCache() {
|
|
129
|
+
this.cachedSkills = null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/skills/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { DynamicToolInterface } from "../tools/index.js";
|
|
2
|
+
import { SkillLoader } from "./loader.js";
|
|
3
|
+
export declare function bindSkillLoader(loader: SkillLoader): void;
|
|
4
|
+
export declare const SearchSkillsTool: DynamicToolInterface;
|
|
5
|
+
export declare const LoadSkillTool: DynamicToolInterface;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { SkillLoader } from "./loader.js";
|
|
2
|
+
// ─── Shared SkillLoader instance ──────────────────────────────────────────────
|
|
3
|
+
let _loader = null;
|
|
4
|
+
export function bindSkillLoader(loader) {
|
|
5
|
+
_loader = loader;
|
|
6
|
+
}
|
|
7
|
+
function getLoader() {
|
|
8
|
+
if (!_loader) {
|
|
9
|
+
_loader = new SkillLoader();
|
|
10
|
+
}
|
|
11
|
+
return _loader;
|
|
12
|
+
}
|
|
13
|
+
// ─── SearchSkillsTool ───────────────────────────────────────────────────────────
|
|
14
|
+
export const SearchSkillsTool = {
|
|
15
|
+
name: "search_skills",
|
|
16
|
+
description: "Search for available skills. Skills provide specialized instructions for specific tasks " +
|
|
17
|
+
"(e.g., deployment workflows, testing strategies, coding patterns).",
|
|
18
|
+
schema: {
|
|
19
|
+
type: "object",
|
|
20
|
+
properties: {
|
|
21
|
+
query: {
|
|
22
|
+
type: "string",
|
|
23
|
+
description: "Search query to match against skill names and descriptions (optional — omit to list all)",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
execute: async (args) => {
|
|
28
|
+
const loader = getLoader();
|
|
29
|
+
let skills = loader.discoverSkills();
|
|
30
|
+
if (args?.query) {
|
|
31
|
+
const q = args.query.toLowerCase();
|
|
32
|
+
skills = skills.filter((s) => s.name.toLowerCase().includes(q) ||
|
|
33
|
+
s.description.toLowerCase().includes(q));
|
|
34
|
+
}
|
|
35
|
+
if (skills.length === 0) {
|
|
36
|
+
return {
|
|
37
|
+
content: args?.query
|
|
38
|
+
? `No skills found matching "${args.query}".`
|
|
39
|
+
: "No skills found. Create a skill by adding a folder with SKILL.md to ./skills/ or ~/.joone/skills/."
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
const list = skills
|
|
43
|
+
.map((s) => `- **${s.name}** (${s.source}): ${s.description}`)
|
|
44
|
+
.join("\n");
|
|
45
|
+
return {
|
|
46
|
+
content: `Found ${skills.length} skill(s):\n${list}\n\n` +
|
|
47
|
+
`To load a skill, call \`load_skill\` with the skill name.`
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
// ─── LoadSkillTool ──────────────────────────────────────────────────────────────
|
|
52
|
+
export const LoadSkillTool = {
|
|
53
|
+
name: "load_skill",
|
|
54
|
+
description: "Loads a specific skill's full instructions (SKILL.md content). " +
|
|
55
|
+
"Use search_skills first to discover available skills.",
|
|
56
|
+
schema: {
|
|
57
|
+
type: "object",
|
|
58
|
+
properties: {
|
|
59
|
+
name: {
|
|
60
|
+
type: "string",
|
|
61
|
+
description: "The name of the skill to load",
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
required: ["name"],
|
|
65
|
+
},
|
|
66
|
+
execute: async (args) => {
|
|
67
|
+
const loader = getLoader();
|
|
68
|
+
const content = loader.loadSkill(args.name);
|
|
69
|
+
if (!content) {
|
|
70
|
+
return {
|
|
71
|
+
content: `Error: Skill "${args.name}" not found. Use search_skills to see available skills.`,
|
|
72
|
+
isError: true
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
return { content };
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/skills/tools.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,iFAAiF;AAEjF,IAAI,OAAO,GAAuB,IAAI,CAAC;AAEvC,MAAM,UAAU,eAAe,CAAC,MAAmB;IACjD,OAAO,GAAG,MAAM,CAAC;AACnB,CAAC;AAED,SAAS,SAAS;IAChB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,mFAAmF;AAEnF,MAAM,CAAC,MAAM,gBAAgB,GAAyB;IACpD,IAAI,EAAE,eAAe;IACrB,WAAW,EACT,0FAA0F;QAC1F,oEAAoE;IACtE,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,0FAA0F;aAC7F;SACF;KACF;IACD,OAAO,EAAE,KAAK,EAAE,IAAyB,EAAuB,EAAE;QAChE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,IAAI,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QAErC,IAAI,IAAI,EAAE,KAAK,EAAE,CAAC;YAChB,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;YACnC,MAAM,GAAG,MAAM,CAAC,MAAM,CACpB,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAChC,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAC1C,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO;gBACL,OAAO,EAAE,IAAI,EAAE,KAAK;oBAClB,CAAC,CAAC,6BAA6B,IAAI,CAAC,KAAK,IAAI;oBAC7C,CAAC,CAAC,oGAAoG;aACzG,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,GAAG,MAAM;aAChB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;aAC7D,IAAI,CAAC,IAAI,CAAC,CAAC;QAEd,OAAO;YACL,OAAO,EACL,SAAS,MAAM,CAAC,MAAM,eAAe,IAAI,MAAM;gBAC/C,2DAA2D;SAC9D,CAAC;IACJ,CAAC;CACF,CAAC;AAEF,mFAAmF;AAEnF,MAAM,CAAC,MAAM,aAAa,GAAyB;IACjD,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,iEAAiE;QACjE,uDAAuD;IACzD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+BAA+B;aAC7C;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;IACD,OAAO,EAAE,KAAK,EAAE,IAAsB,EAAuB,EAAE;QAC7D,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE5C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,iBAAiB,IAAI,CAAC,IAAI,yDAAyD;gBAC5F,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill metadata parsed from SKILL.md YAML frontmatter.
|
|
3
|
+
*/
|
|
4
|
+
export interface SkillMeta {
|
|
5
|
+
/** Human-readable name (from YAML `name` field). */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Short description (from YAML `description` field). */
|
|
8
|
+
description: string;
|
|
9
|
+
/** Absolute path to the SKILL.md file. */
|
|
10
|
+
path: string;
|
|
11
|
+
/** Where this skill was discovered. */
|
|
12
|
+
source: "project" | "user";
|
|
13
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/skills/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import "dotenv/config";
|
|
2
|
+
import { ChatAnthropic } from "@langchain/anthropic";
|
|
3
|
+
import { ExecutionHarness } from "./core/agentLoop.js";
|
|
4
|
+
import { HumanMessage } from "@langchain/core/messages";
|
|
5
|
+
async function runCacheTest() {
|
|
6
|
+
console.log("=== Starting Prompt Caching Test ===\n");
|
|
7
|
+
// We need Anthropic API Key for this to actually hit the network and measure cache
|
|
8
|
+
if (!process.env.ANTHROPIC_API_KEY) {
|
|
9
|
+
console.warn("WARNING: ANTHROPIC_API_KEY is not set in .env file. The LLM call will fail.");
|
|
10
|
+
}
|
|
11
|
+
const model = new ChatAnthropic({
|
|
12
|
+
modelName: "claude-3-5-sonnet-20241022",
|
|
13
|
+
temperature: 0,
|
|
14
|
+
maxTokens: 4096,
|
|
15
|
+
}); // No tools needed for this basic string test
|
|
16
|
+
const harness = new ExecutionHarness(model, []);
|
|
17
|
+
// 1. Create a massive static prefix (simulating a lot of project context)
|
|
18
|
+
// We repeat a string many times to ensure we pass the 1024 token minimum for Anthropic caching.
|
|
19
|
+
const massiveProjectMemory = Array(500).fill("Project Rule: Always write clean, modular TypeScript code with strict typings. ").join("\n");
|
|
20
|
+
const state = {
|
|
21
|
+
globalSystemInstructions: "You are a helpful coding assistant. You remember rules carefully.",
|
|
22
|
+
projectMemory: massiveProjectMemory,
|
|
23
|
+
sessionContext: "User OS: Windows 11",
|
|
24
|
+
conversationHistory: []
|
|
25
|
+
};
|
|
26
|
+
console.log("Turn 1: Initial Query (Should create cache)");
|
|
27
|
+
state.conversationHistory.push(new HumanMessage("Hello! What is one of the project rules?"));
|
|
28
|
+
const response1 = await harness.step(state);
|
|
29
|
+
state.conversationHistory.push(response1);
|
|
30
|
+
// In @langchain/anthropic, the actual usage stats (including cache hits/misses)
|
|
31
|
+
// are stored in the response_metadata of the AIMessage.
|
|
32
|
+
console.log(`Response 1: ${response1.content}`);
|
|
33
|
+
console.log(`Token Usage 1: ${JSON.stringify(response1.response_metadata?.usage, null, 2)}\n`);
|
|
34
|
+
// --- TURN 2 ---
|
|
35
|
+
console.log("Turn 2: Follow-up Query (Should hit cache)");
|
|
36
|
+
// We DO NOT change the globalSystemInstructions, projectMemory, or sessionContext.
|
|
37
|
+
// We only append to the conversation history. This preserves the prefix!
|
|
38
|
+
state.conversationHistory.push(new HumanMessage("Could you summarize the rule again briefly?"));
|
|
39
|
+
const response2 = await harness.step(state);
|
|
40
|
+
state.conversationHistory.push(response2);
|
|
41
|
+
console.log(`Response 2: ${response2.content}`);
|
|
42
|
+
console.log(`Token Usage 2: ${JSON.stringify(response2.response_metadata?.usage, null, 2)}\n`);
|
|
43
|
+
// --- TURN 3: The System Reminder Pattern ---
|
|
44
|
+
console.log("Turn 3: Using <system-reminder> to simulate environment change without breaking cache");
|
|
45
|
+
// If a file changed, we DON'T update `state.projectMemory`. We inject a reminder.
|
|
46
|
+
state.conversationHistory.push(new HumanMessage("<system-reminder>\nThe file 'auth.ts' has just been deleted by the user.\n</system-reminder>\nWhat should we do if we need auth now?"));
|
|
47
|
+
const response3 = await harness.step(state);
|
|
48
|
+
state.conversationHistory.push(response3);
|
|
49
|
+
console.log(`Response 3: ${response3.content}`);
|
|
50
|
+
console.log(`Token Usage 3: ${JSON.stringify(response3.response_metadata?.usage, null, 2)}\n`);
|
|
51
|
+
}
|
|
52
|
+
if (require.main === module) {
|
|
53
|
+
runCacheTest().catch(console.error);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=test_cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test_cache.js","sourceRoot":"","sources":["../src/test_cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
var google_genai_1 = require("@langchain/google-genai");
|
|
40
|
+
var messages_1 = require("@langchain/core/messages");
|
|
41
|
+
var dotenv = require("dotenv");
|
|
42
|
+
dotenv.config();
|
|
43
|
+
function main() {
|
|
44
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
45
|
+
var model, messagesGrouped, e_1, messagesMidstream, e_2;
|
|
46
|
+
return __generator(this, function (_a) {
|
|
47
|
+
switch (_a.label) {
|
|
48
|
+
case 0:
|
|
49
|
+
model = new google_genai_1.ChatGoogleGenerativeAI({
|
|
50
|
+
model: "gemini-2.5-flash",
|
|
51
|
+
});
|
|
52
|
+
messagesGrouped = [
|
|
53
|
+
new messages_1.SystemMessage("You are a helpful assistant."),
|
|
54
|
+
new messages_1.SystemMessage("Also, be concise."),
|
|
55
|
+
new messages_1.HumanMessage("Hello!"),
|
|
56
|
+
];
|
|
57
|
+
_a.label = 1;
|
|
58
|
+
case 1:
|
|
59
|
+
_a.trys.push([1, 3, , 4]);
|
|
60
|
+
return [4 /*yield*/, model.invoke(messagesGrouped)];
|
|
61
|
+
case 2:
|
|
62
|
+
_a.sent();
|
|
63
|
+
console.log("Success: Grouped SystemMessages at the start work perfectly.");
|
|
64
|
+
return [3 /*break*/, 4];
|
|
65
|
+
case 3:
|
|
66
|
+
e_1 = _a.sent();
|
|
67
|
+
console.error("Grouped systems failed:", e_1.message);
|
|
68
|
+
return [3 /*break*/, 4];
|
|
69
|
+
case 4:
|
|
70
|
+
messagesMidstream = [
|
|
71
|
+
new messages_1.SystemMessage("You are a helpful assistant."),
|
|
72
|
+
new messages_1.HumanMessage("Hello!"),
|
|
73
|
+
new messages_1.SystemMessage("System recovery hint here."),
|
|
74
|
+
new messages_1.HumanMessage("What did I say?"),
|
|
75
|
+
];
|
|
76
|
+
_a.label = 5;
|
|
77
|
+
case 5:
|
|
78
|
+
_a.trys.push([5, 7, , 8]);
|
|
79
|
+
return [4 /*yield*/, model.invoke(messagesMidstream)];
|
|
80
|
+
case 6:
|
|
81
|
+
_a.sent();
|
|
82
|
+
console.log("Success: Mid-stream SystemMessages work.");
|
|
83
|
+
return [3 /*break*/, 8];
|
|
84
|
+
case 7:
|
|
85
|
+
e_2 = _a.sent();
|
|
86
|
+
console.error("Midstream systems failed:", e_2.message);
|
|
87
|
+
return [3 /*break*/, 8];
|
|
88
|
+
case 8: return [2 /*return*/];
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
main();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DynamicToolInterface } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* AskUserQuestionTool — allows the agent to ask the user a clarifying question mid-turn.
|
|
4
|
+
*
|
|
5
|
+
* Use cases:
|
|
6
|
+
* - Resolving ambiguous requirements before coding.
|
|
7
|
+
* - Getting user preferences (framework choice, styling, naming).
|
|
8
|
+
* - Requesting approval of an implementation plan before proceeding.
|
|
9
|
+
*/
|
|
10
|
+
export declare const AskUserQuestionTool: DynamicToolInterface;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { HITLBridge } from "../hitl/bridge.js";
|
|
2
|
+
/**
|
|
3
|
+
* AskUserQuestionTool — allows the agent to ask the user a clarifying question mid-turn.
|
|
4
|
+
*
|
|
5
|
+
* Use cases:
|
|
6
|
+
* - Resolving ambiguous requirements before coding.
|
|
7
|
+
* - Getting user preferences (framework choice, styling, naming).
|
|
8
|
+
* - Requesting approval of an implementation plan before proceeding.
|
|
9
|
+
*/
|
|
10
|
+
export const AskUserQuestionTool = {
|
|
11
|
+
name: "ask_user_question",
|
|
12
|
+
description: "Ask the user a question and wait for their response. " +
|
|
13
|
+
"Use this when you need clarification on the task, user preferences, " +
|
|
14
|
+
"or approval before proceeding with a significant change. " +
|
|
15
|
+
"You may optionally provide a list of answer choices.",
|
|
16
|
+
schema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
question: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "The question to ask the user.",
|
|
22
|
+
},
|
|
23
|
+
options: {
|
|
24
|
+
type: "array",
|
|
25
|
+
items: { type: "string" },
|
|
26
|
+
description: "Optional list of predefined answer choices.",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ["question"],
|
|
30
|
+
},
|
|
31
|
+
async execute(args) {
|
|
32
|
+
const question = args.question;
|
|
33
|
+
const options = args.options;
|
|
34
|
+
if (!question || question.trim() === "") {
|
|
35
|
+
return { content: "Error: You must provide a non-empty question.", isError: true };
|
|
36
|
+
}
|
|
37
|
+
const bridge = HITLBridge.getInstance();
|
|
38
|
+
const answer = await bridge.askUser(question, options);
|
|
39
|
+
return { content: answer };
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=askUser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"askUser.js","sourceRoot":"","sources":["../../src/tools/askUser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAG/C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAyB;IACrD,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACP,uDAAuD;QACvD,sEAAsE;QACtE,2DAA2D;QAC3D,sDAAsD;IAC1D,MAAM,EAAE;QACJ,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACR,QAAQ,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+BAA+B;aAC/C;YACD,OAAO,EAAE;gBACL,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACzB,WAAW,EAAE,6CAA6C;aAC7D;SACJ;QACD,QAAQ,EAAE,CAAC,UAAU,CAAC;KACzB;IACD,KAAK,CAAC,OAAO,CAAC,IAA6B;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAkB,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAA+B,CAAC;QAErD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACtC,OAAO,EAAE,OAAO,EAAE,+CAA+C,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACvF,CAAC;QAED,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAEvD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAC/B,CAAC;CACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SandboxManager } from "../sandbox/manager.js";
|
|
2
|
+
import { LazyInstaller } from "../sandbox/bootstrap.js";
|
|
3
|
+
import { DynamicToolInterface } from "./index.js";
|
|
4
|
+
export declare function bindBrowserSandbox(sandbox: SandboxManager, installer: LazyInstaller): void;
|
|
5
|
+
/**
|
|
6
|
+
* Web Browser Tool — wraps Vercel Labs' `agent-browser` CLI.
|
|
7
|
+
*
|
|
8
|
+
* Provides compact accessibility-tree output optimized for LLMs
|
|
9
|
+
* (low token usage vs raw HTML). Runs inside the E2B sandbox.
|
|
10
|
+
*
|
|
11
|
+
* Supported actions:
|
|
12
|
+
* - navigate: Go to a URL
|
|
13
|
+
* - snapshot: Get the accessibility tree (compact text representation)
|
|
14
|
+
* - click: Click an element by ref
|
|
15
|
+
* - type: Type text into a form field by ref
|
|
16
|
+
* - screenshot: Capture a screenshot
|
|
17
|
+
* - scroll: Scroll the page up or down
|
|
18
|
+
*/
|
|
19
|
+
export declare const BrowserTool: DynamicToolInterface;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// ─── Sandbox + Installer references ─────────────────────────────────────────
|
|
2
|
+
let _sandboxManager = null;
|
|
3
|
+
let _installer = null;
|
|
4
|
+
export function bindBrowserSandbox(sandbox, installer) {
|
|
5
|
+
_sandboxManager = sandbox;
|
|
6
|
+
_installer = installer;
|
|
7
|
+
}
|
|
8
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────────
|
|
9
|
+
/**
|
|
10
|
+
* Escapes a string so it can be safely used as an argument in a Bash shell command.
|
|
11
|
+
* It wraps the string in single quotes and safely escapes internal single quotes.
|
|
12
|
+
*/
|
|
13
|
+
function escapeBashArg(arg) {
|
|
14
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
15
|
+
}
|
|
16
|
+
// ─── BrowserTool ────────────────────────────────────────────────────────────────
|
|
17
|
+
/**
|
|
18
|
+
* Web Browser Tool — wraps Vercel Labs' `agent-browser` CLI.
|
|
19
|
+
*
|
|
20
|
+
* Provides compact accessibility-tree output optimized for LLMs
|
|
21
|
+
* (low token usage vs raw HTML). Runs inside the E2B sandbox.
|
|
22
|
+
*
|
|
23
|
+
* Supported actions:
|
|
24
|
+
* - navigate: Go to a URL
|
|
25
|
+
* - snapshot: Get the accessibility tree (compact text representation)
|
|
26
|
+
* - click: Click an element by ref
|
|
27
|
+
* - type: Type text into a form field by ref
|
|
28
|
+
* - screenshot: Capture a screenshot
|
|
29
|
+
* - scroll: Scroll the page up or down
|
|
30
|
+
*/
|
|
31
|
+
export const BrowserTool = {
|
|
32
|
+
name: "browser",
|
|
33
|
+
description: "Interact with web pages using a headless browser. Actions: navigate, snapshot, click, type, screenshot, scroll. " +
|
|
34
|
+
"Returns compact accessibility-tree text output optimized for AI consumption.",
|
|
35
|
+
schema: {
|
|
36
|
+
type: "object",
|
|
37
|
+
properties: {
|
|
38
|
+
action: {
|
|
39
|
+
type: "string",
|
|
40
|
+
enum: ["navigate", "snapshot", "click", "type", "screenshot", "scroll"],
|
|
41
|
+
description: "The browser action to perform",
|
|
42
|
+
},
|
|
43
|
+
url: {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "URL to navigate to (required for 'navigate')",
|
|
46
|
+
},
|
|
47
|
+
ref: {
|
|
48
|
+
type: "string",
|
|
49
|
+
description: "Element reference from the accessibility tree (required for 'click' and 'type')",
|
|
50
|
+
},
|
|
51
|
+
text: {
|
|
52
|
+
type: "string",
|
|
53
|
+
description: "Text to type (required for 'type')",
|
|
54
|
+
},
|
|
55
|
+
direction: {
|
|
56
|
+
type: "string",
|
|
57
|
+
enum: ["up", "down"],
|
|
58
|
+
description: "Scroll direction for 'scroll' action (optional, defaults to 'down')",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
required: ["action"],
|
|
62
|
+
},
|
|
63
|
+
execute: async (args) => {
|
|
64
|
+
if (!_sandboxManager || !_sandboxManager.isActive()) {
|
|
65
|
+
return { content: "Sandbox is not active. Cannot use browser tool.", isError: true };
|
|
66
|
+
}
|
|
67
|
+
// Build the CLI command
|
|
68
|
+
let command;
|
|
69
|
+
switch (args.action) {
|
|
70
|
+
case "navigate":
|
|
71
|
+
if (!args.url)
|
|
72
|
+
return { content: "Error: 'url' is required for navigate action.", isError: true };
|
|
73
|
+
command = `agent-browser navigate ${escapeBashArg(args.url)} 2>&1`;
|
|
74
|
+
break;
|
|
75
|
+
case "snapshot":
|
|
76
|
+
command = "agent-browser snapshot 2>&1";
|
|
77
|
+
break;
|
|
78
|
+
case "click":
|
|
79
|
+
if (!args.ref)
|
|
80
|
+
return { content: "Error: 'ref' is required for click action.", isError: true };
|
|
81
|
+
command = `agent-browser click ${escapeBashArg(args.ref)} 2>&1`;
|
|
82
|
+
break;
|
|
83
|
+
case "type":
|
|
84
|
+
if (!args.ref)
|
|
85
|
+
return { content: "Error: 'ref' is required for type action.", isError: true };
|
|
86
|
+
if (!args.text)
|
|
87
|
+
return { content: "Error: 'text' is required for type action.", isError: true };
|
|
88
|
+
command = `agent-browser type ${escapeBashArg(args.ref)} ${escapeBashArg(args.text)} 2>&1`;
|
|
89
|
+
break;
|
|
90
|
+
case "screenshot":
|
|
91
|
+
command = "agent-browser screenshot 2>&1";
|
|
92
|
+
break;
|
|
93
|
+
case "scroll":
|
|
94
|
+
const dir = args.direction || "down";
|
|
95
|
+
command = `agent-browser scroll ${escapeBashArg(dir)} 2>&1`;
|
|
96
|
+
break;
|
|
97
|
+
default:
|
|
98
|
+
return { content: `Error: Unknown action "${args.action}". Use: navigate, snapshot, click, type, screenshot, scroll.`, isError: true };
|
|
99
|
+
}
|
|
100
|
+
const result = await _sandboxManager.exec(command);
|
|
101
|
+
if (result.exitCode !== 0) {
|
|
102
|
+
return {
|
|
103
|
+
content: `Browser action failed (exit code ${result.exitCode}):\n${result.stdout}\n${result.stderr}`,
|
|
104
|
+
metadata: { exitCode: result.exitCode },
|
|
105
|
+
isError: true
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return { content: result.stdout || "(no output)", metadata: { exitCode: result.exitCode }, isError: false };
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/tools/browser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SandboxManager } from "../sandbox/manager.js";
|
|
2
|
+
import { FileSync } from "../sandbox/sync.js";
|
|
3
|
+
export interface ToolResult {
|
|
4
|
+
content: string;
|
|
5
|
+
metadata?: Record<string, any>;
|
|
6
|
+
isError?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface DynamicToolInterface {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
schema: Record<string, any>;
|
|
12
|
+
execute: (args: any) => Promise<ToolResult> | ToolResult;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Binds the tools to a SandboxManager and FileSync instance.
|
|
16
|
+
* Must be called at session start before any tool executions.
|
|
17
|
+
*/
|
|
18
|
+
export declare function bindSandbox(sandbox: SandboxManager, fileSync: FileSync): void;
|
|
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 declare function isPathInsideWorkspace(resolvedPath: string, workspaceDir?: string): boolean;
|
|
24
|
+
export declare const BashTool: DynamicToolInterface;
|
|
25
|
+
export declare const ReadFileTool: DynamicToolInterface;
|
|
26
|
+
export declare const WriteFileTool: DynamicToolInterface;
|
|
27
|
+
export declare const CORE_TOOLS: DynamicToolInterface[];
|