@hopper-agent/tools 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.
Files changed (47) hide show
  1. package/LICENSE +179 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/src/bash.d.ts +8 -0
  4. package/dist/src/bash.d.ts.map +1 -0
  5. package/dist/src/bash.js +52 -0
  6. package/dist/src/bash.js.map +1 -0
  7. package/dist/src/edit.d.ts +9 -0
  8. package/dist/src/edit.d.ts.map +1 -0
  9. package/dist/src/edit.js +39 -0
  10. package/dist/src/edit.js.map +1 -0
  11. package/dist/src/glob.d.ts +7 -0
  12. package/dist/src/glob.d.ts.map +1 -0
  13. package/dist/src/glob.js +73 -0
  14. package/dist/src/glob.js.map +1 -0
  15. package/dist/src/grep.d.ts +12 -0
  16. package/dist/src/grep.d.ts.map +1 -0
  17. package/dist/src/grep.js +78 -0
  18. package/dist/src/grep.js.map +1 -0
  19. package/dist/src/index.d.ts +59 -0
  20. package/dist/src/index.d.ts.map +1 -0
  21. package/dist/src/index.js +21 -0
  22. package/dist/src/index.js.map +1 -0
  23. package/dist/src/read.d.ts +9 -0
  24. package/dist/src/read.d.ts.map +1 -0
  25. package/dist/src/read.js +61 -0
  26. package/dist/src/read.js.map +1 -0
  27. package/dist/src/reminder.d.ts +7 -0
  28. package/dist/src/reminder.d.ts.map +1 -0
  29. package/dist/src/reminder.js +28 -0
  30. package/dist/src/reminder.js.map +1 -0
  31. package/dist/src/tool.d.ts +28 -0
  32. package/dist/src/tool.d.ts.map +1 -0
  33. package/dist/src/tool.js +63 -0
  34. package/dist/src/tool.js.map +1 -0
  35. package/dist/src/web-fetch.d.ts +7 -0
  36. package/dist/src/web-fetch.d.ts.map +1 -0
  37. package/dist/src/web-fetch.js +51 -0
  38. package/dist/src/web-fetch.js.map +1 -0
  39. package/dist/src/web-search.d.ts +9 -0
  40. package/dist/src/web-search.d.ts.map +1 -0
  41. package/dist/src/web-search.js +61 -0
  42. package/dist/src/web-search.js.map +1 -0
  43. package/dist/src/write.d.ts +7 -0
  44. package/dist/src/write.d.ts.map +1 -0
  45. package/dist/src/write.js +23 -0
  46. package/dist/src/write.js.map +1 -0
  47. package/package.json +32 -0
@@ -0,0 +1,78 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { z } from 'zod';
4
+ import { createTool } from './tool.js';
5
+ const GrepSchema = z.object({
6
+ pattern: z.string().describe('The regular expression pattern to search for'),
7
+ path: z.string().optional().describe('File or directory to search in'),
8
+ glob: z.string().optional().describe('Glob pattern to filter files'),
9
+ type: z.string().optional().describe('File type to search (js, py, ts, etc.)'),
10
+ '-i': z.boolean().optional().describe('Case insensitive search'),
11
+ '-n': z.boolean().optional().describe('Show line numbers'),
12
+ context: z.number().optional().describe('Lines of context before and after'),
13
+ });
14
+ const EXT_MAP = {
15
+ js: ['.js', '.jsx', '.mjs'],
16
+ ts: ['.ts', '.tsx'],
17
+ py: ['.py'],
18
+ rust: ['.rs'],
19
+ go: ['.go'],
20
+ java: ['.java'],
21
+ rb: ['.rb'],
22
+ rs: ['.rs'],
23
+ };
24
+ export const grepTool = createTool('Grep', 'Content search with regex support. Searches file contents for matching patterns.', GrepSchema, async (input, ctx) => {
25
+ const searchPath = input.path ? path.resolve(ctx.cwd, input.path) : ctx.cwd;
26
+ const regexFlags = input['-i'] ? 'gi' : 'g';
27
+ const pattern = input.pattern ?? '';
28
+ const regex = new RegExp(pattern, regexFlags);
29
+ const allowedExts = input.type ? EXT_MAP[input.type] : null;
30
+ const results = [];
31
+ function walk(dir) {
32
+ let entries;
33
+ try {
34
+ entries = fs.readdirSync(dir, { withFileTypes: true });
35
+ }
36
+ catch {
37
+ return;
38
+ }
39
+ for (const entry of entries) {
40
+ const fullPath = path.join(dir, entry.name);
41
+ if (entry.isDirectory()) {
42
+ if (entry.name === 'node_modules' || entry.name === '.git')
43
+ continue;
44
+ walk(fullPath);
45
+ }
46
+ else if (entry.isFile()) {
47
+ if (allowedExts) {
48
+ const ext = path.extname(entry.name).toLowerCase();
49
+ if (!allowedExts.includes(ext))
50
+ continue;
51
+ }
52
+ try {
53
+ const content = fs.readFileSync(fullPath, 'utf-8');
54
+ const lines = content.split('\n');
55
+ for (let i = 0; i < lines.length; i++) {
56
+ regex.lastIndex = 0;
57
+ const line = lines[i];
58
+ if (line && regex.test(line)) {
59
+ results.push({ file: fullPath, line: i + 1, text: line });
60
+ }
61
+ }
62
+ }
63
+ catch {
64
+ // skip binary files
65
+ }
66
+ }
67
+ }
68
+ }
69
+ walk(searchPath);
70
+ return {
71
+ output: {
72
+ pattern: input.pattern,
73
+ matches: results.length,
74
+ results: results.slice(0, 250),
75
+ },
76
+ };
77
+ });
78
+ //# sourceMappingURL=grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../src/grep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ export { type Tool, type ToolResult, type ToolContext, type ToolDef, createTool } from './tool.js';
2
+ export { readTool } from './read.js';
3
+ export { editTool } from './edit.js';
4
+ export { writeTool } from './write.js';
5
+ export { globTool } from './glob.js';
6
+ export { grepTool } from './grep.js';
7
+ export { bashTool } from './bash.js';
8
+ export { reminderTool } from './reminder.js';
9
+ export { webSearchTool } from './web-search.js';
10
+ export { webFetchTool } from './web-fetch.js';
11
+ export declare const allTools: ((import("./tool.js").Tool & {
12
+ validate: (raw: Record<string, unknown>) => {
13
+ message: string;
14
+ scheduled_at: string;
15
+ };
16
+ }) | (import("./tool.js").Tool & {
17
+ validate: (raw: Record<string, unknown>) => {
18
+ file_path: string;
19
+ offset?: number | undefined;
20
+ limit?: number | undefined;
21
+ pages?: string | undefined;
22
+ };
23
+ }) | (import("./tool.js").Tool & {
24
+ validate: (raw: Record<string, unknown>) => {
25
+ file_path: string;
26
+ old_string: string;
27
+ new_string: string;
28
+ replace_all?: boolean | undefined;
29
+ };
30
+ }) | (import("./tool.js").Tool & {
31
+ validate: (raw: Record<string, unknown>) => {
32
+ file_path: string;
33
+ content: string;
34
+ };
35
+ }) | (import("./tool.js").Tool & {
36
+ validate: (raw: Record<string, unknown>) => {
37
+ pattern: string;
38
+ path?: string | undefined;
39
+ };
40
+ }) | (import("./tool.js").Tool & {
41
+ validate: (raw: Record<string, unknown>) => {
42
+ command: string;
43
+ description?: string | undefined;
44
+ timeout?: number | undefined;
45
+ };
46
+ }) | (import("./tool.js").Tool & {
47
+ validate: (raw: Record<string, unknown>) => {
48
+ query: string;
49
+ count?: number | undefined;
50
+ blocked_domains?: string[] | undefined;
51
+ allowed_domains?: string[] | undefined;
52
+ };
53
+ }) | (import("./tool.js").Tool & {
54
+ validate: (raw: Record<string, unknown>) => {
55
+ url: string;
56
+ prompt: string;
57
+ };
58
+ }))[];
59
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACnG,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAY9C,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAA2G,CAAC"}
@@ -0,0 +1,21 @@
1
+ export { createTool } from './tool.js';
2
+ export { readTool } from './read.js';
3
+ export { editTool } from './edit.js';
4
+ export { writeTool } from './write.js';
5
+ export { globTool } from './glob.js';
6
+ export { grepTool } from './grep.js';
7
+ export { bashTool } from './bash.js';
8
+ export { reminderTool } from './reminder.js';
9
+ export { webSearchTool } from './web-search.js';
10
+ export { webFetchTool } from './web-fetch.js';
11
+ import { readTool } from './read.js';
12
+ import { editTool } from './edit.js';
13
+ import { writeTool } from './write.js';
14
+ import { globTool } from './glob.js';
15
+ import { grepTool } from './grep.js';
16
+ import { bashTool } from './bash.js';
17
+ import { reminderTool } from './reminder.js';
18
+ import { webSearchTool } from './web-search.js';
19
+ import { webFetchTool } from './web-fetch.js';
20
+ export const allTools = [readTool, editTool, writeTool, globTool, grepTool, bashTool, reminderTool, webSearchTool, webFetchTool];
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8D,UAAU,EAAE,MAAM,WAAW,CAAC;AACnG,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const readTool: import("./tool.js").Tool & {
2
+ validate: (raw: Record<string, unknown>) => {
3
+ file_path: string;
4
+ offset?: number | undefined;
5
+ limit?: number | undefined;
6
+ pages?: string | undefined;
7
+ };
8
+ };
9
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/read.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,QAAQ;;;;;;;CA+DpB,CAAC"}
@@ -0,0 +1,61 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { z } from 'zod';
4
+ import { createTool, expandPath } from './tool.js';
5
+ const ReadSchema = z.object({
6
+ file_path: z.string().describe('The absolute path to the file to read'),
7
+ offset: z.number().optional().describe('The line number to start reading from'),
8
+ limit: z.number().optional().describe('The number of lines to read'),
9
+ pages: z.string().optional().describe('Page range for PDF files'),
10
+ });
11
+ export const readTool = createTool('Read', 'Reads a file from the local filesystem. Supports text files, PDF, notebooks, and images.', ReadSchema, async (input, ctx) => {
12
+ const filePath = path.resolve(ctx.cwd, expandPath(input.file_path));
13
+ if (!fs.existsSync(filePath)) {
14
+ return { output: null, error: `File not found: ${filePath}` };
15
+ }
16
+ const stat = fs.statSync(filePath);
17
+ if (stat.isDirectory()) {
18
+ const entries = fs.readdirSync(filePath, { withFileTypes: true });
19
+ return { output: entries.map((e) => ({ name: e.name, isDirectory: e.isDirectory(), isFile: e.isFile() })) };
20
+ }
21
+ const ext = path.extname(filePath).toLowerCase();
22
+ if (['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.webp', '.svg'].includes(ext)) {
23
+ const buf = fs.readFileSync(filePath);
24
+ return {
25
+ output: {
26
+ type: 'image',
27
+ path: filePath,
28
+ size: buf.length,
29
+ encoding: 'base64',
30
+ data: buf.toString('base64'),
31
+ },
32
+ };
33
+ }
34
+ if (ext === '.pdf') {
35
+ return { output: null, error: `PDF reading requires a PDF library. Path: ${filePath}` };
36
+ }
37
+ const content = fs.readFileSync(filePath, 'utf-8');
38
+ const lines = content.split('\n');
39
+ let resultLines = lines;
40
+ if (input.offset !== undefined) {
41
+ const start = Math.max(0, input.offset - 1);
42
+ resultLines = lines.slice(start);
43
+ }
44
+ if (input.limit !== undefined) {
45
+ resultLines = resultLines.slice(0, input.limit);
46
+ }
47
+ const numbered = resultLines
48
+ .map((line, i) => {
49
+ const ln = input.offset !== undefined ? input.offset + i : i + 1;
50
+ return `${ln}\t${line}`;
51
+ })
52
+ .join('\n');
53
+ return {
54
+ output: {
55
+ path: filePath,
56
+ totalLines: lines.length,
57
+ content: numbered,
58
+ },
59
+ };
60
+ });
61
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare const reminderTool: import("./tool.js").Tool & {
2
+ validate: (raw: Record<string, unknown>) => {
3
+ message: string;
4
+ scheduled_at: string;
5
+ };
6
+ };
7
+ //# sourceMappingURL=reminder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reminder.d.ts","sourceRoot":"","sources":["../../src/reminder.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,YAAY;;;;;CAuBxB,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+ import { createTool } from './tool.js';
3
+ import { CronManager } from '@hopper-agent/core';
4
+ const CronManagerSingleton = new CronManager();
5
+ const CreateReminderSchema = z.object({
6
+ message: z.string().describe('What to remind the user about'),
7
+ scheduled_at: z.string().describe('ISO 8601 datetime (e.g. "2026-05-03T07:00:00Z")'),
8
+ });
9
+ export const reminderTool = createTool('CreateReminder', 'Creates a reminder notification that will fire at the specified time.', CreateReminderSchema, async (input) => {
10
+ const scheduledAt = new Date(input.scheduled_at).getTime();
11
+ if (isNaN(scheduledAt)) {
12
+ return {
13
+ output: null,
14
+ error: `Invalid datetime: "${input.scheduled_at}". Use ISO 8601 format (e.g. "2026-05-03T07:00:00Z").`,
15
+ };
16
+ }
17
+ const task = CronManagerSingleton.createReminder(input.message, scheduledAt);
18
+ const timeStr = new Date(scheduledAt).toLocaleString();
19
+ return {
20
+ output: {
21
+ id: task.id,
22
+ message: task.message,
23
+ scheduledAt: timeStr,
24
+ status: task.status,
25
+ },
26
+ };
27
+ });
28
+ //# sourceMappingURL=reminder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reminder.js","sourceRoot":"","sources":["../../src/reminder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAoB,MAAM,WAAW,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,oBAAoB,GAAG,IAAI,WAAW,EAAE,CAAC;AAE/C,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAC7D,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iDAAiD,CAAC;CACrF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CACpC,gBAAgB,EAChB,uEAAuE,EACvE,oBAAoB,EACpB,KAAK,EAAE,KAAK,EAAE,EAAE;IACd,MAAM,WAAW,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC;IAC3D,IAAI,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,sBAAsB,KAAK,CAAC,YAAY,uDAAuD;SACvG,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,oBAAoB,CAAC,cAAc,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,cAAc,EAAE,CAAC;IACvD,OAAO;QACL,MAAM,EAAE;YACN,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,OAAO;YACpB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB;KACF,CAAC;AACJ,CAAC,CACF,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+ import type { HopperSettings } from '@hopper-agent/core';
3
+ export interface ToolDef {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: {
7
+ type: 'object';
8
+ properties: Record<string, unknown>;
9
+ required?: string[];
10
+ };
11
+ }
12
+ export interface Tool {
13
+ definition: ToolDef;
14
+ execute: (input: Record<string, unknown>, settings: HopperSettings) => Promise<ToolResult>;
15
+ }
16
+ export interface ToolResult {
17
+ output: unknown;
18
+ error?: string;
19
+ }
20
+ export interface ToolContext {
21
+ cwd: string;
22
+ settings: HopperSettings;
23
+ }
24
+ export declare function expandPath(p: string): string;
25
+ export declare function createTool<Schema extends z.ZodObject<z.ZodRawShape>>(name: string, description: string, schema: Schema, execute: (input: z.infer<Schema>, ctx: ToolContext) => Promise<ToolResult>): Tool & {
26
+ validate: (raw: Record<string, unknown>) => z.infer<Schema>;
27
+ };
28
+ //# sourceMappingURL=tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5F;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK5C;AA6CD,wBAAgB,UAAU,CAAC,MAAM,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EAClE,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,GACzE,IAAI,GAAG;IAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;CAAE,CAiBxE"}
@@ -0,0 +1,63 @@
1
+ import { homedir } from 'node:os';
2
+ export function expandPath(p) {
3
+ if (p.startsWith('~/') || p === '~') {
4
+ return homedir() + p.slice(1);
5
+ }
6
+ return p;
7
+ }
8
+ function zodToJsonSchema(schema) {
9
+ const def = schema._def;
10
+ let result = {};
11
+ switch (def.typeName) {
12
+ case 'ZodString':
13
+ result = { type: 'string' };
14
+ break;
15
+ case 'ZodNumber':
16
+ result = { type: 'number' };
17
+ break;
18
+ case 'ZodBoolean':
19
+ result = { type: 'boolean' };
20
+ break;
21
+ case 'ZodOptional': {
22
+ const inner = zodToJsonSchema(def.innerType);
23
+ result = def.description ? { ...inner, description: def.description } : inner;
24
+ break;
25
+ }
26
+ case 'ZodObject': {
27
+ const shape = def.shape();
28
+ const properties = {};
29
+ const required = [];
30
+ for (const [key, value] of Object.entries(shape)) {
31
+ properties[key] = zodToJsonSchema(value);
32
+ if (value._def.typeName !== 'ZodOptional') {
33
+ required.push(key);
34
+ }
35
+ }
36
+ result = { type: 'object', properties, ...(required.length > 0 ? { required } : {}) };
37
+ break;
38
+ }
39
+ default:
40
+ result = { type: 'string' };
41
+ }
42
+ if (def.description && !result['description']) {
43
+ result = { ...result, description: def.description };
44
+ }
45
+ return result;
46
+ }
47
+ export function createTool(name, description, schema, execute) {
48
+ const jsonSchema = zodToJsonSchema(schema);
49
+ const def = {
50
+ name,
51
+ description,
52
+ inputSchema: jsonSchema,
53
+ };
54
+ return {
55
+ definition: def,
56
+ validate: (raw) => schema.parse(raw),
57
+ async execute(input, settings) {
58
+ const parsed = schema.parse(input);
59
+ return execute(parsed, { cwd: '', settings });
60
+ },
61
+ };
62
+ }
63
+ //# sourceMappingURL=tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AA4BlC,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QACpC,OAAO,OAAO,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,eAAe,CAAC,MAAoB;IAC3C,MAAM,GAAG,GAAI,MAAc,CAAC,IAAI,CAAC;IACjC,IAAI,MAAM,GAA4B,EAAE,CAAC;IAEzC,QAAQ,GAAG,CAAC,QAAkB,EAAE,CAAC;QAC/B,KAAK,WAAW;YACd,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;YAC5B,MAAM;QACR,KAAK,WAAW;YACd,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;YAC5B,MAAM;QACR,KAAK,YAAY;YACf,MAAM,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;YAC7B,MAAM;QACR,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,SAAyB,CAAC,CAAC;YAC7D,MAAM,GAAG,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,WAAqB,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;YACxF,MAAM;QACR,CAAC;QACD,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,KAAK,GAAI,GAAG,CAAC,KAA4C,EAAE,CAAC;YAClE,MAAM,UAAU,GAA4B,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;YAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,UAAU,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;gBACzC,IAAK,KAAa,CAAC,IAAI,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;oBACnD,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YACD,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;YACtF,MAAM;QACR,CAAC;QACD;YACE,MAAM,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAChC,CAAC;IAED,IAAI,GAAG,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9C,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,WAAW,EAAE,GAAG,CAAC,WAAqB,EAAE,CAAC;IACjE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,IAAY,EACZ,WAAmB,EACnB,MAAc,EACd,OAA0E;IAE1E,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IAE3C,MAAM,GAAG,GAAY;QACnB,IAAI;QACJ,WAAW;QACX,WAAW,EAAE,UAAoC;KAClD,CAAC;IAEF,OAAO;QACL,UAAU,EAAE,GAAG;QACf,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;QACpC,KAAK,CAAC,OAAO,CAAC,KAA8B,EAAE,QAAwB;YACpE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAoB,CAAC;YACtD,OAAO,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QAChD,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ export declare const webFetchTool: import("./tool.js").Tool & {
2
+ validate: (raw: Record<string, unknown>) => {
3
+ url: string;
4
+ prompt: string;
5
+ };
6
+ };
7
+ //# sourceMappingURL=web-fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../src/web-fetch.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,YAAY;;;;;CAuCxB,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { z } from 'zod';
2
+ import { createTool } from './tool.js';
3
+ const WebFetchSchema = z.object({
4
+ url: z.string().describe('The URL to fetch content from'),
5
+ prompt: z.string().describe('Description of what content to extract from the page'),
6
+ });
7
+ export const webFetchTool = createTool('WebFetch', 'Fetches a URL and extracts readable content. Returns the extracted text.', WebFetchSchema, async (input, ctx) => {
8
+ let url;
9
+ try {
10
+ url = new URL(input.url);
11
+ }
12
+ catch {
13
+ return {
14
+ output: null,
15
+ error: `Invalid URL: "${input.url}"`,
16
+ };
17
+ }
18
+ const response = await fetch(url.toString(), {
19
+ headers: {
20
+ Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
21
+ 'User-Agent': 'Mozilla/5.0 (compatible; HopperBot/1.0)',
22
+ },
23
+ });
24
+ if (!response.ok) {
25
+ return {
26
+ output: null,
27
+ error: `Failed to fetch ${url.toString()}: ${response.status} ${response.statusText}`,
28
+ };
29
+ }
30
+ const contentType = response.headers.get('content-type') ?? '';
31
+ const body = await response.text();
32
+ let content = body;
33
+ if (contentType.includes('text/html')) {
34
+ content = htmlToText(body);
35
+ }
36
+ return { output: { url: url.toString(), content, contentType } };
37
+ });
38
+ function htmlToText(html) {
39
+ let text = html.replace(/<script[\s\S]*?<\/script>/gi, '');
40
+ text = text.replace(/<style[\s\S]*?<\/style>/gi, '');
41
+ text = text.replace(/<[^>]+>/g, ' ');
42
+ text = text.replace(/&nbsp;/g, ' ')
43
+ .replace(/&amp;/g, '&')
44
+ .replace(/&lt;/g, '<')
45
+ .replace(/&gt;/g, '>')
46
+ .replace(/&quot;/g, '"')
47
+ .replace(/&#39;/g, "'");
48
+ text = text.replace(/\s+/g, ' ').trim();
49
+ return text;
50
+ }
51
+ //# sourceMappingURL=web-fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-fetch.js","sourceRoot":"","sources":["../../src/web-fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAoB,MAAM,WAAW,CAAC;AAEzD,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IACzD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;CACpF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CACpC,UAAU,EACV,0EAA0E,EAC1E,cAAc,EACd,KAAK,EAAE,KAAK,EAAE,GAAgB,EAAE,EAAE;IAChC,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,iBAAiB,KAAK,CAAC,GAAG,GAAG;SACrC,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;QAC3C,OAAO,EAAE;YACP,MAAM,EAAE,iEAAiE;YACzE,YAAY,EAAE,yCAAyC;SACxD;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO;YACL,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,mBAAmB,GAAG,CAAC,QAAQ,EAAE,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE;SACtF,CAAC;IACJ,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC/D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACtC,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC;AACnE,CAAC,CACF,CAAC;AAEF,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;IAC3D,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;IACrD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACrC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SAChC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;SACrB,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC1B,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,9 @@
1
+ export declare const webSearchTool: import("./tool.js").Tool & {
2
+ validate: (raw: Record<string, unknown>) => {
3
+ query: string;
4
+ count?: number | undefined;
5
+ blocked_domains?: string[] | undefined;
6
+ allowed_domains?: string[] | undefined;
7
+ };
8
+ };
9
+ //# sourceMappingURL=web-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search.d.ts","sourceRoot":"","sources":["../../src/web-search.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,aAAa;;;;;;;CAiEzB,CAAC"}
@@ -0,0 +1,61 @@
1
+ import { z } from 'zod';
2
+ import { createTool } from './tool.js';
3
+ const WebSearchSchema = z.object({
4
+ query: z.string().describe('The search query to look up on the web'),
5
+ count: z.number().optional().describe('Number of results to return (max 20, default 10)'),
6
+ blocked_domains: z.array(z.string()).optional().describe('Domains to exclude from search results'),
7
+ allowed_domains: z.array(z.string()).optional().describe('Only return results from these domains'),
8
+ });
9
+ export const webSearchTool = createTool('WebSearch', 'Search the web using Brave Search API. Returns titles, URLs, and snippets.', WebSearchSchema, async (input, ctx) => {
10
+ const apiKey = ctx.settings.BRAVE_SEARCH_API_KEY;
11
+ if (!apiKey) {
12
+ return {
13
+ output: null,
14
+ error: 'BRAVE_SEARCH_API_KEY is not configured in settings.json',
15
+ };
16
+ }
17
+ const count = Math.min(input.count ?? 10, 20);
18
+ const url = new URL('https://api.search.brave.com/res/v1/web/search');
19
+ url.searchParams.set('q', input.query);
20
+ url.searchParams.set('count', String(count));
21
+ if (input.allowed_domains?.length) {
22
+ url.searchParams.set('filters', input.allowed_domains.join(','));
23
+ }
24
+ const response = await fetch(url.toString(), {
25
+ headers: {
26
+ Accept: 'application/json',
27
+ 'Accept-Encoding': 'gzip',
28
+ 'X-Subscription-Token': apiKey,
29
+ },
30
+ });
31
+ if (!response.ok) {
32
+ return {
33
+ output: null,
34
+ error: `Brave Search API error: ${response.status} ${response.statusText}`,
35
+ };
36
+ }
37
+ const data = await response.json();
38
+ const results = [];
39
+ const web = data.web;
40
+ const webResults = web?.results ?? [];
41
+ for (const r of webResults) {
42
+ const title = r.title ?? '';
43
+ const urlStr = r.url ?? '';
44
+ const snippet = r.description ?? '';
45
+ if (input.blocked_domains?.length) {
46
+ try {
47
+ const hostname = new URL(urlStr).hostname;
48
+ if (input.blocked_domains.some((d) => hostname.includes(d)))
49
+ continue;
50
+ }
51
+ catch {
52
+ continue;
53
+ }
54
+ }
55
+ results.push({ title, url: urlStr, snippet });
56
+ if (results.length >= count)
57
+ break;
58
+ }
59
+ return { output: results };
60
+ });
61
+ //# sourceMappingURL=web-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search.js","sourceRoot":"","sources":["../../src/web-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare const writeTool: import("./tool.js").Tool & {
2
+ validate: (raw: Record<string, unknown>) => {
3
+ file_path: string;
4
+ content: string;
5
+ };
6
+ };
7
+ //# sourceMappingURL=write.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/write.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,SAAS;;;;;CAqBrB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { z } from 'zod';
4
+ import { createTool, expandPath } from './tool.js';
5
+ const WriteSchema = z.object({
6
+ file_path: z.string().describe('The absolute path to the file to write'),
7
+ content: z.string().describe('The content to write to the file'),
8
+ });
9
+ export const writeTool = createTool('Write', 'Writes a file to the local filesystem. Creates new files or overwrites existing ones.', WriteSchema, async (input, ctx) => {
10
+ const filePath = path.resolve(ctx.cwd, expandPath(input.file_path));
11
+ const dir = path.dirname(filePath);
12
+ if (!fs.existsSync(dir)) {
13
+ fs.mkdirSync(dir, { recursive: true });
14
+ }
15
+ fs.writeFileSync(filePath, input.content, 'utf-8');
16
+ return {
17
+ output: {
18
+ path: filePath,
19
+ bytes: Buffer.byteLength(input.content, 'utf-8'),
20
+ },
21
+ };
22
+ });
23
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAoB,MAAM,WAAW,CAAC;AAErE,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wCAAwC,CAAC;IACxE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;CACjE,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CACjC,OAAO,EACP,uFAAuF,EACvF,WAAW,EACX,KAAK,EAAE,KAAK,EAAE,GAAgB,EAAE,EAAE;IAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAEpE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAEnD,OAAO;QACL,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;SACjD;KACF,CAAC;AACJ,CAAC,CACF,CAAC"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@hopper-agent/tools",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "main": "./dist/src/index.js",
9
+ "types": "./dist/src/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist/src/index.js",
13
+ "types": "./dist/src/index.d.ts"
14
+ }
15
+ },
16
+ "dependencies": {
17
+ "zod": "^3.25.0",
18
+ "@hopper-agent/core": "0.1.1"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^22.0.0",
22
+ "typescript": "^5.9.0"
23
+ },
24
+ "scripts": {
25
+ "build": "tsc --project tsconfig.json",
26
+ "dev": "tsc --watch --project tsconfig.json",
27
+ "typecheck": "tsc --noEmit --project tsconfig.json",
28
+ "lint": "eslint src/",
29
+ "test": "vitest run",
30
+ "clean": "npx rimraf dist"
31
+ }
32
+ }