visionclaw 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -0
- package/dist/agent/context.d.ts +56 -0
- package/dist/agent/context.d.ts.map +1 -0
- package/dist/agent/context.js +142 -0
- package/dist/agent/context.js.map +1 -0
- package/dist/agent/loop.d.ts +18 -0
- package/dist/agent/loop.d.ts.map +1 -0
- package/dist/agent/loop.js +323 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/session.d.ts +49 -0
- package/dist/agent/session.d.ts.map +1 -0
- package/dist/agent/session.js +200 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/system-prompt.d.ts +10 -0
- package/dist/agent/system-prompt.d.ts.map +1 -0
- package/dist/agent/system-prompt.js +167 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/calendar/google-calendar.d.ts +46 -0
- package/dist/calendar/google-calendar.d.ts.map +1 -0
- package/dist/calendar/google-calendar.js +132 -0
- package/dist/calendar/google-calendar.js.map +1 -0
- package/dist/calendar/scheduler.d.ts +7 -0
- package/dist/calendar/scheduler.d.ts.map +1 -0
- package/dist/calendar/scheduler.js +33 -0
- package/dist/calendar/scheduler.js.map +1 -0
- package/dist/channels/discord.d.ts +19 -0
- package/dist/channels/discord.d.ts.map +1 -0
- package/dist/channels/discord.js +169 -0
- package/dist/channels/discord.js.map +1 -0
- package/dist/channels/gmail.d.ts +31 -0
- package/dist/channels/gmail.d.ts.map +1 -0
- package/dist/channels/gmail.js +300 -0
- package/dist/channels/gmail.js.map +1 -0
- package/dist/channels/interface.d.ts +45 -0
- package/dist/channels/interface.d.ts.map +1 -0
- package/dist/channels/interface.js +2 -0
- package/dist/channels/interface.js.map +1 -0
- package/dist/channels/manager.d.ts +36 -0
- package/dist/channels/manager.d.ts.map +1 -0
- package/dist/channels/manager.js +108 -0
- package/dist/channels/manager.js.map +1 -0
- package/dist/channels/queue.d.ts +17 -0
- package/dist/channels/queue.d.ts.map +1 -0
- package/dist/channels/queue.js +85 -0
- package/dist/channels/queue.js.map +1 -0
- package/dist/channels/slack.d.ts +17 -0
- package/dist/channels/slack.d.ts.map +1 -0
- package/dist/channels/slack.js +142 -0
- package/dist/channels/slack.js.map +1 -0
- package/dist/channels/sms.d.ts +19 -0
- package/dist/channels/sms.d.ts.map +1 -0
- package/dist/channels/sms.js +111 -0
- package/dist/channels/sms.js.map +1 -0
- package/dist/channels/telegram.d.ts +28 -0
- package/dist/channels/telegram.d.ts.map +1 -0
- package/dist/channels/telegram.js +246 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/channels/whatsapp.d.ts +28 -0
- package/dist/channels/whatsapp.d.ts.map +1 -0
- package/dist/channels/whatsapp.js +292 -0
- package/dist/channels/whatsapp.js.map +1 -0
- package/dist/config/index.d.ts +24 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +104 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/types.d.ts +227 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +45 -0
- package/dist/config/types.js.map +1 -0
- package/dist/files.d.ts +20 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +82 -0
- package/dist/files.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +76 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +384 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory/store.d.ts +24 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +71 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/obs/server.d.ts +10 -0
- package/dist/obs/server.d.ts.map +1 -0
- package/dist/obs/server.js +406 -0
- package/dist/obs/server.js.map +1 -0
- package/dist/onboarding/google-auth.d.ts +11 -0
- package/dist/onboarding/google-auth.d.ts.map +1 -0
- package/dist/onboarding/google-auth.js +113 -0
- package/dist/onboarding/google-auth.js.map +1 -0
- package/dist/onboarding/index.d.ts +2 -0
- package/dist/onboarding/index.d.ts.map +1 -0
- package/dist/onboarding/index.js +213 -0
- package/dist/onboarding/index.js.map +1 -0
- package/dist/onboarding/macos-permissions.d.ts +37 -0
- package/dist/onboarding/macos-permissions.d.ts.map +1 -0
- package/dist/onboarding/macos-permissions.js +207 -0
- package/dist/onboarding/macos-permissions.js.map +1 -0
- package/dist/skills/install.d.ts +7 -0
- package/dist/skills/install.d.ts.map +1 -0
- package/dist/skills/install.js +63 -0
- package/dist/skills/install.js.map +1 -0
- package/dist/tools/browser.d.ts +7 -0
- package/dist/tools/browser.d.ts.map +1 -0
- package/dist/tools/browser.js +202 -0
- package/dist/tools/browser.js.map +1 -0
- package/dist/tools/calendar.d.ts +12 -0
- package/dist/tools/calendar.d.ts.map +1 -0
- package/dist/tools/calendar.js +210 -0
- package/dist/tools/calendar.js.map +1 -0
- package/dist/tools/computer-use.d.ts +28 -0
- package/dist/tools/computer-use.d.ts.map +1 -0
- package/dist/tools/computer-use.js +311 -0
- package/dist/tools/computer-use.js.map +1 -0
- package/dist/tools/coordinate-resolver.d.ts +26 -0
- package/dist/tools/coordinate-resolver.d.ts.map +1 -0
- package/dist/tools/coordinate-resolver.js +157 -0
- package/dist/tools/coordinate-resolver.js.map +1 -0
- package/dist/tools/desktop-executor.d.ts +52 -0
- package/dist/tools/desktop-executor.d.ts.map +1 -0
- package/dist/tools/desktop-executor.js +202 -0
- package/dist/tools/desktop-executor.js.map +1 -0
- package/dist/tools/finish.d.ts +5 -0
- package/dist/tools/finish.d.ts.map +1 -0
- package/dist/tools/finish.js +18 -0
- package/dist/tools/finish.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +37 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/memory.d.ts +14 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +269 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/notify.d.ts +12 -0
- package/dist/tools/notify.d.ts.map +1 -0
- package/dist/tools/notify.js +108 -0
- package/dist/tools/notify.js.map +1 -0
- package/dist/tools/screenshot.d.ts +7 -0
- package/dist/tools/screenshot.d.ts.map +1 -0
- package/dist/tools/screenshot.js +189 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/skill.d.ts +8 -0
- package/dist/tools/skill.d.ts.map +1 -0
- package/dist/tools/skill.js +133 -0
- package/dist/tools/skill.js.map +1 -0
- package/dist/tools/upgrade.d.ts +5 -0
- package/dist/tools/upgrade.d.ts.map +1 -0
- package/dist/tools/upgrade.js +89 -0
- package/dist/tools/upgrade.js.map +1 -0
- package/dist/tools/wait.d.ts +5 -0
- package/dist/tools/wait.d.ts.map +1 -0
- package/dist/tools/wait.js +21 -0
- package/dist/tools/wait.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { tool } from "@anthropic-ai/claude-agent-sdk";
|
|
3
|
+
import { getAgentState } from "../agent/loop.js";
|
|
4
|
+
export const notifyUserTool = tool("notify_user", "Send a message to the user through a messaging channel. Supports text and optional image/file attachments. Use this to communicate results, answer questions, request help, or send files.", {
|
|
5
|
+
message: z
|
|
6
|
+
.string()
|
|
7
|
+
.describe("The text message to send to the user"),
|
|
8
|
+
channel: z
|
|
9
|
+
.string()
|
|
10
|
+
.optional()
|
|
11
|
+
.describe("Channel to send through (e.g. 'gmail', 'telegram', 'slack'). Defaults to the channel the last message came from."),
|
|
12
|
+
to: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe("Recipient identifier (email, chat ID, etc.). Defaults to the sender of the last received message."),
|
|
16
|
+
image_url: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("URL of an image to send with the message"),
|
|
20
|
+
image_path: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Absolute local file path of an image to send (e.g. /tmp/resized.jpg)"),
|
|
24
|
+
file_url: z
|
|
25
|
+
.string()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("URL of a file to send with the message"),
|
|
28
|
+
file_path: z
|
|
29
|
+
.string()
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Absolute local file path of a file to send"),
|
|
32
|
+
file_name: z
|
|
33
|
+
.string()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Display filename for the attached file"),
|
|
36
|
+
}, async (args) => {
|
|
37
|
+
const state = getAgentState();
|
|
38
|
+
const channel = args.channel ?? state.lastMessageChannel ?? "gmail";
|
|
39
|
+
const to = args.to ?? state.lastMessageSender ?? "";
|
|
40
|
+
if (!to) {
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: "text",
|
|
45
|
+
text: "Error: No recipient specified and no recent message sender to reply to.",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
isError: true,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
// Build attachments array from optional params
|
|
52
|
+
const attachments = [];
|
|
53
|
+
if (args.image_url) {
|
|
54
|
+
attachments.push({
|
|
55
|
+
type: "image",
|
|
56
|
+
url: args.image_url,
|
|
57
|
+
mimeType: "image/png",
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (args.image_path) {
|
|
61
|
+
attachments.push({
|
|
62
|
+
type: "image",
|
|
63
|
+
localPath: args.image_path,
|
|
64
|
+
mimeType: "image/jpeg",
|
|
65
|
+
filename: args.file_name ?? args.image_path.split("/").pop(),
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
if (args.file_url) {
|
|
69
|
+
attachments.push({
|
|
70
|
+
type: "file",
|
|
71
|
+
url: args.file_url,
|
|
72
|
+
filename: args.file_name,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (args.file_path) {
|
|
76
|
+
attachments.push({
|
|
77
|
+
type: "file",
|
|
78
|
+
localPath: args.file_path,
|
|
79
|
+
filename: args.file_name ?? args.file_path.split("/").pop(),
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
await state.channelManager.sendMessage(channel, to, args.message, attachments.length > 0 ? attachments : undefined);
|
|
84
|
+
const attNote = attachments.length > 0
|
|
85
|
+
? ` with ${attachments.length} attachment(s)`
|
|
86
|
+
: "";
|
|
87
|
+
return {
|
|
88
|
+
content: [
|
|
89
|
+
{
|
|
90
|
+
type: "text",
|
|
91
|
+
text: `Message sent via ${channel} to ${to}${attNote}.`,
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
return {
|
|
98
|
+
content: [
|
|
99
|
+
{
|
|
100
|
+
type: "text",
|
|
101
|
+
text: `Failed to send message via ${channel}: ${err instanceof Error ? err.message : String(err)}`,
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
isError: true,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/tools/notify.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Take a screenshot of the current desktop.
|
|
3
|
+
* Returns the base64-encoded PNG image. Compresses to under 2MB if needed.
|
|
4
|
+
*/
|
|
5
|
+
export declare function takeScreenshot(): Promise<string>;
|
|
6
|
+
export declare const screenshotTool: import("@anthropic-ai/claude-agent-sdk").SdkMcpToolDefinition<{}>;
|
|
7
|
+
//# sourceMappingURL=screenshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.d.ts","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"AAsGA;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAiEtD;AAED,eAAO,MAAM,cAAc,mEA6B1B,CAAC"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import sharp from "sharp";
|
|
7
|
+
import { tool } from "@anthropic-ai/claude-agent-sdk";
|
|
8
|
+
import { logger } from "../logger.js";
|
|
9
|
+
const execAsync = promisify(exec);
|
|
10
|
+
const MAX_SCREENSHOT_SIZE = 2 * 1024 * 1024; // 2MB
|
|
11
|
+
/** Resolve the absolute path to ffmpeg, checking common Homebrew / system locations. */
|
|
12
|
+
let _ffmpegPath;
|
|
13
|
+
async function findFfmpeg() {
|
|
14
|
+
if (_ffmpegPath !== undefined)
|
|
15
|
+
return _ffmpegPath;
|
|
16
|
+
// Try PATH first
|
|
17
|
+
try {
|
|
18
|
+
const { stdout } = await execAsync("which ffmpeg");
|
|
19
|
+
const p = stdout.trim();
|
|
20
|
+
if (p) {
|
|
21
|
+
_ffmpegPath = p;
|
|
22
|
+
return p;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch { /* not on PATH */ }
|
|
26
|
+
// Check well-known locations
|
|
27
|
+
for (const candidate of [
|
|
28
|
+
"/opt/homebrew/bin/ffmpeg",
|
|
29
|
+
"/usr/local/bin/ffmpeg",
|
|
30
|
+
"/usr/bin/ffmpeg",
|
|
31
|
+
]) {
|
|
32
|
+
try {
|
|
33
|
+
fs.accessSync(candidate, fs.constants.X_OK);
|
|
34
|
+
_ffmpegPath = candidate;
|
|
35
|
+
return candidate;
|
|
36
|
+
}
|
|
37
|
+
catch { /* next */ }
|
|
38
|
+
}
|
|
39
|
+
_ffmpegPath = null;
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compress a PNG file on disk using ffmpeg two-pass palette quantization.
|
|
44
|
+
* Pass 1: generate an optimal palette with up to `maxColors` colours.
|
|
45
|
+
* Pass 2: re-encode the image using that palette with Bayer dithering.
|
|
46
|
+
*
|
|
47
|
+
* Returns true if the output file was written successfully.
|
|
48
|
+
*/
|
|
49
|
+
async function compressWithFfmpeg(inputPath, outputPath, maxColors = 128) {
|
|
50
|
+
const ffmpeg = await findFfmpeg();
|
|
51
|
+
if (!ffmpeg) {
|
|
52
|
+
logger.warn("ffmpeg not found on this system");
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
const palettePath = inputPath.replace(/\.png$/, "-palette.png");
|
|
56
|
+
try {
|
|
57
|
+
// Pass 1: palette generation
|
|
58
|
+
await execAsync(`"${ffmpeg}" -y -i "${inputPath}" -vf "palettegen=max_colors=${maxColors}" "${palettePath}"`);
|
|
59
|
+
// Pass 2: apply palette
|
|
60
|
+
await execAsync(`"${ffmpeg}" -y -i "${inputPath}" -i "${palettePath}" -lavfi "paletteuse=dither=bayer" -compression_level 100 "${outputPath}"`);
|
|
61
|
+
return fs.existsSync(outputPath);
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
logger.warn(`ffmpeg compression failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
try {
|
|
69
|
+
fs.unlinkSync(palettePath);
|
|
70
|
+
}
|
|
71
|
+
catch { /* noop */ }
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Compress a PNG buffer if it exceeds the size threshold.
|
|
76
|
+
* Uses sharp in-process (works in dev, may fail in bundled app).
|
|
77
|
+
*/
|
|
78
|
+
async function compressIfNeeded(buffer, maxSize = MAX_SCREENSHOT_SIZE) {
|
|
79
|
+
if (buffer.length <= maxSize)
|
|
80
|
+
return buffer;
|
|
81
|
+
try {
|
|
82
|
+
const compressed = await sharp(buffer)
|
|
83
|
+
.png({ quality: 80, compressionLevel: 9, palette: true })
|
|
84
|
+
.toBuffer();
|
|
85
|
+
if (compressed.length < buffer.length) {
|
|
86
|
+
logger.debug(`Screenshot sharp compress: ${buffer.length} → ${compressed.length} bytes`);
|
|
87
|
+
return compressed;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
logger.warn(`Screenshot sharp compression failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
92
|
+
}
|
|
93
|
+
return buffer;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Take a screenshot of the current desktop.
|
|
97
|
+
* Returns the base64-encoded PNG image. Compresses to under 2MB if needed.
|
|
98
|
+
*/
|
|
99
|
+
export async function takeScreenshot() {
|
|
100
|
+
const tmpFile = path.join(os.tmpdir(), `visionclaw-screenshot-${Date.now()}.png`);
|
|
101
|
+
try {
|
|
102
|
+
if (process.platform === "darwin") {
|
|
103
|
+
await execAsync(`screencapture -x -C "${tmpFile}"`);
|
|
104
|
+
}
|
|
105
|
+
else if (process.platform === "win32") {
|
|
106
|
+
await execAsync(`powershell -command "Add-Type -AssemblyName System.Windows.Forms; ` +
|
|
107
|
+
`$screen = [System.Windows.Forms.Screen]::PrimaryScreen; ` +
|
|
108
|
+
`$bitmap = New-Object System.Drawing.Bitmap($screen.Bounds.Width, $screen.Bounds.Height); ` +
|
|
109
|
+
`$graphics = [System.Drawing.Graphics]::FromImage($bitmap); ` +
|
|
110
|
+
`$graphics.CopyFromScreen($screen.Bounds.Location, [System.Drawing.Point]::Empty, $screen.Bounds.Size); ` +
|
|
111
|
+
`$bitmap.Save('${tmpFile}'); ` +
|
|
112
|
+
`$graphics.Dispose(); $bitmap.Dispose()"`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
try {
|
|
116
|
+
await execAsync(`scrot "${tmpFile}"`);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
await execAsync(`gnome-screenshot -f "${tmpFile}"`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const rawBuffer = fs.readFileSync(tmpFile);
|
|
123
|
+
// Try sharp in-process first (works in dev, may fail in bundled app)
|
|
124
|
+
const compressed = await compressIfNeeded(rawBuffer);
|
|
125
|
+
if (compressed.length <= MAX_SCREENSHOT_SIZE) {
|
|
126
|
+
return compressed.toString("base64");
|
|
127
|
+
}
|
|
128
|
+
// Sharp failed or didn't compress enough — use ffmpeg
|
|
129
|
+
const compressedPath = tmpFile.replace(/\.png$/, "-compressed.png");
|
|
130
|
+
try {
|
|
131
|
+
// Try progressively fewer colours until under threshold
|
|
132
|
+
for (const maxColors of [128, 64]) {
|
|
133
|
+
const ok = await compressWithFfmpeg(tmpFile, compressedPath, maxColors);
|
|
134
|
+
if (ok) {
|
|
135
|
+
const compressedBuffer = fs.readFileSync(compressedPath);
|
|
136
|
+
if (compressedBuffer.length <= MAX_SCREENSHOT_SIZE) {
|
|
137
|
+
logger.debug(`Screenshot ffmpeg compress (${maxColors} colours): ${rawBuffer.length} → ${compressedBuffer.length} bytes`);
|
|
138
|
+
return compressedBuffer.toString("base64");
|
|
139
|
+
}
|
|
140
|
+
logger.debug(`Screenshot ffmpeg ${maxColors} colours: ${compressedBuffer.length} bytes (still over ${MAX_SCREENSHOT_SIZE})`);
|
|
141
|
+
return compressedBuffer.toString("base64"); // Return best effort even if still too large
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
finally {
|
|
146
|
+
try {
|
|
147
|
+
fs.unlinkSync(compressedPath);
|
|
148
|
+
}
|
|
149
|
+
catch { /* noop */ }
|
|
150
|
+
}
|
|
151
|
+
// Last resort: return original uncompressed PNG
|
|
152
|
+
logger.warn(`Screenshot compression unavailable, returning ${rawBuffer.length}-byte original`);
|
|
153
|
+
return rawBuffer.toString("base64");
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
try {
|
|
157
|
+
fs.unlinkSync(tmpFile);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Ignore cleanup errors
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export const screenshotTool = tool("take_screenshot", "Capture a screenshot of the current desktop screen. Returns the image as base64 PNG.", {}, async (_args) => {
|
|
165
|
+
try {
|
|
166
|
+
const base64 = await takeScreenshot();
|
|
167
|
+
return {
|
|
168
|
+
content: [
|
|
169
|
+
{
|
|
170
|
+
type: "image",
|
|
171
|
+
data: base64,
|
|
172
|
+
mimeType: "image/png",
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
return {
|
|
179
|
+
content: [
|
|
180
|
+
{
|
|
181
|
+
type: "text",
|
|
182
|
+
text: `Screenshot failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
isError: true,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
//# sourceMappingURL=screenshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const manageSkillsTool: import("@anthropic-ai/claude-agent-sdk").SdkMcpToolDefinition<{
|
|
3
|
+
action: z.ZodEnum<["create", "update", "delete", "list"]>;
|
|
4
|
+
name: z.ZodOptional<z.ZodString>;
|
|
5
|
+
description: z.ZodOptional<z.ZodString>;
|
|
6
|
+
content: z.ZodOptional<z.ZodString>;
|
|
7
|
+
}>;
|
|
8
|
+
//# sourceMappingURL=skill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/tools/skill.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,gBAAgB;;;;;EAgJ5B,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { tool } from "@anthropic-ai/claude-agent-sdk";
|
|
5
|
+
import { getSkillsDir } from "../config/index.js";
|
|
6
|
+
export const manageSkillsTool = tool("manage_skills", "Manage your skills. Skills are SKILL.md files that the SDK discovers and you can invoke via the Skill tool when relevant. You can create, update, list, and delete skills.", {
|
|
7
|
+
action: z
|
|
8
|
+
.enum(["create", "update", "delete", "list"])
|
|
9
|
+
.describe("Action to perform"),
|
|
10
|
+
name: z
|
|
11
|
+
.string()
|
|
12
|
+
.regex(/^[a-z0-9-]+$/)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Skill name (required for create, update, delete)"),
|
|
15
|
+
description: z
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Short description of when this skill should be used (required for create/update)"),
|
|
19
|
+
content: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Skill instructions in Markdown (required for create/update)"),
|
|
23
|
+
}, (args) => {
|
|
24
|
+
try {
|
|
25
|
+
const skillsDir = getSkillsDir();
|
|
26
|
+
switch (args.action) {
|
|
27
|
+
case "create":
|
|
28
|
+
case "update": {
|
|
29
|
+
if (!args.name || !args.description || !args.content) {
|
|
30
|
+
return Promise.resolve({
|
|
31
|
+
content: [{
|
|
32
|
+
type: "text",
|
|
33
|
+
text: "Error: name, description, and content are required for create/update.",
|
|
34
|
+
}],
|
|
35
|
+
isError: true,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
const skillDir = path.join(skillsDir, args.name);
|
|
39
|
+
if (!fs.existsSync(skillDir)) {
|
|
40
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
41
|
+
}
|
|
42
|
+
const filePath = path.join(skillDir, "SKILL.md");
|
|
43
|
+
const existed = fs.existsSync(filePath);
|
|
44
|
+
const skillContent = `---\ndescription: ${args.description}\n---\n\n${args.content}\n`;
|
|
45
|
+
fs.writeFileSync(filePath, skillContent, "utf-8");
|
|
46
|
+
return Promise.resolve({
|
|
47
|
+
content: [{
|
|
48
|
+
type: "text",
|
|
49
|
+
text: `Skill "${args.name}" ${existed ? "updated" : "created"} at ${filePath}.`,
|
|
50
|
+
}],
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
case "delete": {
|
|
54
|
+
if (!args.name) {
|
|
55
|
+
return Promise.resolve({
|
|
56
|
+
content: [{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: "Error: name is required for delete.",
|
|
59
|
+
}],
|
|
60
|
+
isError: true,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const skillDir = path.join(skillsDir, args.name);
|
|
64
|
+
if (!fs.existsSync(skillDir)) {
|
|
65
|
+
return Promise.resolve({
|
|
66
|
+
content: [{
|
|
67
|
+
type: "text",
|
|
68
|
+
text: `Skill "${args.name}" not found.`,
|
|
69
|
+
}],
|
|
70
|
+
isError: true,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
fs.rmSync(skillDir, { recursive: true });
|
|
74
|
+
return Promise.resolve({
|
|
75
|
+
content: [{
|
|
76
|
+
type: "text",
|
|
77
|
+
text: `Skill "${args.name}" deleted.`,
|
|
78
|
+
}],
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
case "list": {
|
|
82
|
+
if (!fs.existsSync(skillsDir)) {
|
|
83
|
+
return Promise.resolve({
|
|
84
|
+
content: [{ type: "text", text: "No skills directory found." }],
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
88
|
+
const skills = entries.filter((e) => e.isDirectory());
|
|
89
|
+
if (skills.length === 0) {
|
|
90
|
+
return Promise.resolve({
|
|
91
|
+
content: [{ type: "text", text: "No skills installed." }],
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const lines = skills.map((dir) => {
|
|
95
|
+
const skillFile = path.join(skillsDir, dir.name, "SKILL.md");
|
|
96
|
+
let desc = "(no description)";
|
|
97
|
+
if (fs.existsSync(skillFile)) {
|
|
98
|
+
const raw = fs.readFileSync(skillFile, "utf-8");
|
|
99
|
+
const match = /^description:\s*(.+)$/m.exec(raw);
|
|
100
|
+
if (match) {
|
|
101
|
+
desc = match[1];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return `- ${dir.name}: ${desc}`;
|
|
105
|
+
});
|
|
106
|
+
return Promise.resolve({
|
|
107
|
+
content: [{
|
|
108
|
+
type: "text",
|
|
109
|
+
text: `${skills.length} skill(s):\n${lines.join("\n")}`,
|
|
110
|
+
}],
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
default:
|
|
114
|
+
return Promise.resolve({
|
|
115
|
+
content: [{
|
|
116
|
+
type: "text",
|
|
117
|
+
text: `Unknown action: ${args.action}`,
|
|
118
|
+
}],
|
|
119
|
+
isError: true,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
return Promise.resolve({
|
|
125
|
+
content: [{
|
|
126
|
+
type: "text",
|
|
127
|
+
text: `Skill operation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
128
|
+
}],
|
|
129
|
+
isError: true,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=skill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/tools/skill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/tools/upgrade.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,eAAO,MAAM,WAAW;;EA+FvB,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { exec } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { tool } from "@anthropic-ai/claude-agent-sdk";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
const execAsync = promisify(exec);
|
|
8
|
+
const GITHUB_REPO = "babelcloud/visionclaw";
|
|
9
|
+
const PACKAGE_JSON_PATH = path.resolve(new URL(".", import.meta.url).pathname, "../../package.json");
|
|
10
|
+
export const upgradeTool = tool("upgrade", "Check for new versions of VisionClaw and upgrade if available. The agent can upgrade itself.", {
|
|
11
|
+
check_only: z
|
|
12
|
+
.boolean()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("If true, only check for updates without installing"),
|
|
15
|
+
}, async (args) => {
|
|
16
|
+
try {
|
|
17
|
+
// Read current version
|
|
18
|
+
let currentVersion = "0.0.0";
|
|
19
|
+
try {
|
|
20
|
+
const pkg = JSON.parse(fs.readFileSync(PACKAGE_JSON_PATH, "utf-8"));
|
|
21
|
+
currentVersion = pkg.version ?? "0.0.0";
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Ignore
|
|
25
|
+
}
|
|
26
|
+
// Check latest release on GitHub
|
|
27
|
+
const { stdout } = await execAsync(`curl -s "https://api.github.com/repos/${GITHUB_REPO}/releases/latest"`);
|
|
28
|
+
let latestVersion = "0.0.0";
|
|
29
|
+
let releaseUrl = "";
|
|
30
|
+
try {
|
|
31
|
+
const release = JSON.parse(stdout);
|
|
32
|
+
latestVersion = (release.tag_name ?? "").replace(/^v/, "");
|
|
33
|
+
releaseUrl = release.html_url ?? "";
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return {
|
|
37
|
+
content: [
|
|
38
|
+
{
|
|
39
|
+
type: "text",
|
|
40
|
+
text: "Could not check for updates. GitHub API returned invalid response.",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
isError: true,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (latestVersion <= currentVersion) {
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: "text",
|
|
51
|
+
text: `Already up to date. Current version: ${currentVersion}`,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (args.check_only) {
|
|
57
|
+
return {
|
|
58
|
+
content: [
|
|
59
|
+
{
|
|
60
|
+
type: "text",
|
|
61
|
+
text: `Update available: ${currentVersion} -> ${latestVersion}\nRelease: ${releaseUrl}`,
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Perform upgrade via pnpm
|
|
67
|
+
const { stdout: installOut, stderr: installErr } = await execAsync(`pnpm add -g visionclaw@latest`);
|
|
68
|
+
return {
|
|
69
|
+
content: [
|
|
70
|
+
{
|
|
71
|
+
type: "text",
|
|
72
|
+
text: `Upgraded from ${currentVersion} to ${latestVersion}.\n${installOut}\n${installErr}\nRestart may be required for changes to take effect.`,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
return {
|
|
79
|
+
content: [
|
|
80
|
+
{
|
|
81
|
+
type: "text",
|
|
82
|
+
text: `Upgrade failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
isError: true,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=upgrade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/tools/upgrade.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAEtD,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,MAAM,WAAW,GAAG,uBAAuB,CAAC;AAC5C,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CACpC,IAAI,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EACtC,oBAAoB,CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAC7B,SAAS,EACT,8FAA8F,EAC9F;IACE,UAAU,EAAE,CAAC;SACV,OAAO,EAAE;SACT,QAAQ,EAAE;SACV,QAAQ,CAAC,oDAAoD,CAAC;CAClE,EACD,KAAK,EAAE,IAAI,EAA2B,EAAE;IACtC,IAAI,CAAC;QACH,uBAAuB;QACvB,IAAI,cAAc,GAAG,OAAO,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAEjE,CAAC;YACF,cAAc,GAAG,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QAED,iCAAiC;QACjC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAChC,yCAAyC,WAAW,mBAAmB,CACxE,CAAC;QAEF,IAAI,aAAa,GAAG,OAAO,CAAC;QAC5B,IAAI,UAAU,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAGhC,CAAC;YACF,aAAa,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3D,UAAU,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;QACtC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,oEAAoE;qBAC3E;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,IAAI,cAAc,EAAE,CAAC;YACpC,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,wCAAwC,cAAc,EAAE;qBAC/D;iBACF;aACF,CAAC;QACJ,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,qBAAqB,cAAc,OAAO,aAAa,cAAc,UAAU,EAAE;qBACxF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,2BAA2B;QAC3B,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,SAAS,CAChE,+BAA+B,CAChC,CAAC;QAEF,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,iBAAiB,cAAc,OAAO,aAAa,MAAM,UAAU,KAAK,UAAU,uDAAuD;iBAChJ;aACF;SACF,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,mBAAmB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;iBAC5E;aACF;YACD,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait.d.ts","sourceRoot":"","sources":["../../src/tools/wait.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,QAAQ;;EAsBpB,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { tool } from "@anthropic-ai/claude-agent-sdk";
|
|
3
|
+
export const waitTool = tool("wait", "Wait (pause) for a specified number of seconds before continuing.", {
|
|
4
|
+
seconds: z
|
|
5
|
+
.number()
|
|
6
|
+
.min(1)
|
|
7
|
+
.max(300)
|
|
8
|
+
.describe("Number of seconds to wait (1-300)"),
|
|
9
|
+
}, async (args) => {
|
|
10
|
+
const { seconds } = args;
|
|
11
|
+
await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
|
12
|
+
return {
|
|
13
|
+
content: [
|
|
14
|
+
{
|
|
15
|
+
type: "text",
|
|
16
|
+
text: `Waited ${seconds} second(s).`,
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=wait.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait.js","sourceRoot":"","sources":["../../src/tools/wait.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAGtD,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,CAC1B,MAAM,EACN,mEAAmE,EACnE;IACE,OAAO,EAAE,CAAC;SACP,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,CAAC,mCAAmC,CAAC;CACjD,EACD,KAAK,EAAE,IAAI,EAA2B,EAAE;IACtC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACzB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC;IACpE,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,UAAU,OAAO,aAAa;aACrC;SACF;KACF,CAAC;AACJ,CAAC,CACF,CAAC"}
|