Skip to content

Commit a809298

Browse files
author
Splash Agent
committed
feat: tools, templates, browser
1 parent d97b697 commit a809298

5 files changed

Lines changed: 181 additions & 40 deletions

File tree

examples/cli.ts

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async function main() {
110110
"version", "help", "init", "setup", "config", "chat", "telegram", "slack",
111111
"whatsapp", "messenger", "discord", "runs", "tui", "dashboard", "self-improve",
112112
"providers", "skills", "memory", "maintenance", "voice", "swarm", "antigravity",
113-
"run", "doctor"
113+
"run", "doctor", "browser"
114114
];
115115

116116
if (!KNOWN_COMMANDS.includes(cmd)) {
@@ -179,6 +179,9 @@ async function main() {
179179
case "skills":
180180
await runSkills(args.slice(1));
181181
return;
182+
case "browser":
183+
await runBrowser(args.slice(1));
184+
return;
182185
case "memory":
183186
await runMemory(args.slice(1));
184187
return;
@@ -1165,23 +1168,89 @@ async function runSkills(args: string[]): Promise<void> {
11651168
const sub = args[0] || "list";
11661169

11671170
if (sub === "list") {
1168-
const alpclaw = await buildAgent();
1169-
const skills = alpclaw.skills.list();
1170-
console.log(pc.bold(`\n Registered Skills (${skills.length})\n`));
1171-
for (const skill of skills) {
1172-
const tags = skill.tags?.join(", ") || "";
1173-
console.log(
1174-
` ${pc.cyan(skill.name.padEnd(20))} ${pc.dim(tags)}`,
1175-
);
1171+
// Read skills without building the agent (no API keys needed)
1172+
let count = 0;
1173+
console.log(pc.bold(`\n Registered Skills\n`));
1174+
1175+
try {
1176+
const skillsPkg = await import("@alpclaw/skills");
1177+
for (const [name, ExportedClass] of Object.entries(skillsPkg)) {
1178+
if (typeof ExportedClass === "function" && name.endsWith("Skill")) {
1179+
try {
1180+
const instance = new (ExportedClass as any)();
1181+
if (instance.manifest) {
1182+
const tags = instance.manifest.tags?.join(", ") || "";
1183+
console.log(` ${pc.cyan(instance.manifest.name.padEnd(20))} ${pc.dim(tags)}`);
1184+
count++;
1185+
}
1186+
} catch {}
1187+
}
1188+
}
1189+
1190+
const toolsPkg = await import("@alpclaw/tools");
1191+
for (const [name, ExportedClass] of Object.entries(toolsPkg)) {
1192+
if (typeof ExportedClass === "function" && name.endsWith("Tool")) {
1193+
try {
1194+
const instance = new (ExportedClass as any)();
1195+
if (instance.manifest) {
1196+
const tags = instance.manifest.tags?.join(", ") || "";
1197+
console.log(` ${pc.cyan(instance.manifest.name.padEnd(20))} ${pc.dim(tags)}`);
1198+
count++;
1199+
}
1200+
} catch {}
1201+
}
1202+
}
1203+
} catch (e) {
1204+
console.error(pc.red(" Failed to load skills list"));
11761205
}
1177-
console.log();
1206+
console.log(pc.dim(`\n Total: ${count}\n`));
11781207
return;
11791208
}
11801209

11811210
console.error(pc.red(`Unknown subcommand: skills ${sub}`));
11821211
console.log(pc.dim(" Available: list"));
11831212
}
11841213

1214+
async function runBrowser(args: string[]): Promise<void> {
1215+
const sub = args[0];
1216+
const url = args[1];
1217+
const pathArg = args[2];
1218+
1219+
if (!sub || !url) {
1220+
console.error(pc.red("Usage: splash browser <open|screenshot> <url> [path]"));
1221+
return;
1222+
}
1223+
1224+
let playwright;
1225+
try {
1226+
playwright = await import("playwright");
1227+
} catch {
1228+
console.error(pc.red("[ERR] Install playwright or puppeteer to use browser tools."));
1229+
return;
1230+
}
1231+
1232+
try {
1233+
const browser = await playwright.chromium.launch({ headless: true });
1234+
const page = await browser.newPage();
1235+
await page.goto(url, { waitUntil: "networkidle" });
1236+
1237+
if (sub === "open") {
1238+
const content = await page.content();
1239+
console.log(`[OK] Snapshot size: ${content.length} bytes`);
1240+
} else if (sub === "screenshot") {
1241+
const sp = pathArg || "screenshot.png";
1242+
await page.screenshot({ path: sp, fullPage: true });
1243+
console.log(`[OK] Screenshot saved to ${sp}`);
1244+
} else {
1245+
console.error(pc.red(`[ERR] Unknown browser command: ${sub}`));
1246+
}
1247+
1248+
await browser.close();
1249+
} catch (e: any) {
1250+
console.error(pc.red(`[ERR] Browser failed: ${e.message}`));
1251+
}
1252+
}
1253+
11851254
// ──────────────────────────────────────────────────────────────────────────
11861255
// Memory
11871256
// ──────────────────────────────────────────────────────────────────────────

packages/core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"@alpclaw/providers": "workspace:*",
1717
"@alpclaw/connectors": "workspace:*",
1818
"@alpclaw/skills": "workspace:*",
19+
"@alpclaw/tools": "workspace:*",
1920
"ink": "^5.0.1",
2021
"react": "^18.3.1",
2122
"zod": "^3.23.0"

packages/core/src/alpclaw.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ import {
5454
ProjectGeneratorSkill,
5555
DocumentGeneratorSkill,
5656
} from "@alpclaw/skills";
57+
import {
58+
FsTool,
59+
ShellTool,
60+
WebTool,
61+
BrowserTool,
62+
MemoryTool,
63+
DocTool,
64+
CodeTool
65+
} from "@alpclaw/tools";
5766
import { createLogger } from "@alpclaw/utils";
5867
import { AgentLoop, type AgentLoopCallbacks } from "./agent-loop.js";
5968

@@ -160,6 +169,15 @@ export class AlpClaw {
160169
this.skills.register(new TaskQueueSkill());
161170
this.skills.register(new ProjectGeneratorSkill());
162171
this.skills.register(new DocumentGeneratorSkill());
172+
173+
// Tools
174+
this.skills.register(new FsTool());
175+
this.skills.register(new ShellTool());
176+
this.skills.register(new WebTool());
177+
this.skills.register(new BrowserTool());
178+
this.skills.register(new MemoryTool());
179+
this.skills.register(new DocTool());
180+
this.skills.register(new CodeTool());
163181

164182
// ── Safety ─────────────────────────────────────────────────────────────
165183
this.safety = new SafetyEngine(config.safety.mode, config.safety.blockedPatterns);

0 commit comments

Comments
 (0)