@polpo-ai/tools 0.2.4

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 (89) hide show
  1. package/dist/adapters/node-filesystem.d.ts +12 -0
  2. package/dist/adapters/node-filesystem.d.ts.map +1 -0
  3. package/dist/adapters/node-filesystem.js +46 -0
  4. package/dist/adapters/node-filesystem.js.map +1 -0
  5. package/dist/adapters/node-shell.d.ts +5 -0
  6. package/dist/adapters/node-shell.d.ts.map +1 -0
  7. package/dist/adapters/node-shell.js +34 -0
  8. package/dist/adapters/node-shell.js.map +1 -0
  9. package/dist/audio-tools.d.ts +42 -0
  10. package/dist/audio-tools.d.ts.map +1 -0
  11. package/dist/audio-tools.js +552 -0
  12. package/dist/audio-tools.js.map +1 -0
  13. package/dist/browser-tools.d.ts +36 -0
  14. package/dist/browser-tools.d.ts.map +1 -0
  15. package/dist/browser-tools.js +525 -0
  16. package/dist/browser-tools.js.map +1 -0
  17. package/dist/coding-tools.d.ts +99 -0
  18. package/dist/coding-tools.d.ts.map +1 -0
  19. package/dist/coding-tools.js +434 -0
  20. package/dist/coding-tools.js.map +1 -0
  21. package/dist/docx-tools.d.ts +22 -0
  22. package/dist/docx-tools.d.ts.map +1 -0
  23. package/dist/docx-tools.js +236 -0
  24. package/dist/docx-tools.js.map +1 -0
  25. package/dist/email-tools.d.ts +34 -0
  26. package/dist/email-tools.d.ts.map +1 -0
  27. package/dist/email-tools.js +787 -0
  28. package/dist/email-tools.js.map +1 -0
  29. package/dist/excel-tools.d.ts +25 -0
  30. package/dist/excel-tools.d.ts.map +1 -0
  31. package/dist/excel-tools.js +409 -0
  32. package/dist/excel-tools.js.map +1 -0
  33. package/dist/http-tools.d.ts +23 -0
  34. package/dist/http-tools.d.ts.map +1 -0
  35. package/dist/http-tools.js +214 -0
  36. package/dist/http-tools.js.map +1 -0
  37. package/dist/image-tools.d.ts +40 -0
  38. package/dist/image-tools.d.ts.map +1 -0
  39. package/dist/image-tools.js +522 -0
  40. package/dist/image-tools.js.map +1 -0
  41. package/dist/index.d.ts +33 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +37 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/memory-tools.d.ts +19 -0
  46. package/dist/memory-tools.d.ts.map +1 -0
  47. package/dist/memory-tools.js +104 -0
  48. package/dist/memory-tools.js.map +1 -0
  49. package/dist/outcome-tools.d.ts +25 -0
  50. package/dist/outcome-tools.d.ts.map +1 -0
  51. package/dist/outcome-tools.js +191 -0
  52. package/dist/outcome-tools.js.map +1 -0
  53. package/dist/path-sandbox.d.ts +28 -0
  54. package/dist/path-sandbox.d.ts.map +1 -0
  55. package/dist/path-sandbox.js +58 -0
  56. package/dist/path-sandbox.js.map +1 -0
  57. package/dist/pdf-tools.d.ts +25 -0
  58. package/dist/pdf-tools.d.ts.map +1 -0
  59. package/dist/pdf-tools.js +363 -0
  60. package/dist/pdf-tools.js.map +1 -0
  61. package/dist/phone-tools.d.ts +27 -0
  62. package/dist/phone-tools.d.ts.map +1 -0
  63. package/dist/phone-tools.js +577 -0
  64. package/dist/phone-tools.js.map +1 -0
  65. package/dist/safe-env.d.ts +26 -0
  66. package/dist/safe-env.d.ts.map +1 -0
  67. package/dist/safe-env.js +76 -0
  68. package/dist/safe-env.js.map +1 -0
  69. package/dist/search-tools.d.ts +22 -0
  70. package/dist/search-tools.d.ts.map +1 -0
  71. package/dist/search-tools.js +205 -0
  72. package/dist/search-tools.js.map +1 -0
  73. package/dist/ssrf-guard.d.ts +17 -0
  74. package/dist/ssrf-guard.d.ts.map +1 -0
  75. package/dist/ssrf-guard.js +95 -0
  76. package/dist/ssrf-guard.js.map +1 -0
  77. package/dist/types.d.ts +21 -0
  78. package/dist/types.d.ts.map +1 -0
  79. package/dist/types.js +5 -0
  80. package/dist/types.js.map +1 -0
  81. package/dist/vault-tools.d.ts +26 -0
  82. package/dist/vault-tools.d.ts.map +1 -0
  83. package/dist/vault-tools.js +86 -0
  84. package/dist/vault-tools.js.map +1 -0
  85. package/dist/whatsapp-tools.d.ts +18 -0
  86. package/dist/whatsapp-tools.d.ts.map +1 -0
  87. package/dist/whatsapp-tools.js +206 -0
  88. package/dist/whatsapp-tools.js.map +1 -0
  89. package/package.json +56 -0
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Safe environment variable filtering for child processes.
3
+ *
4
+ * Instead of passing the full `process.env` (which leaks API keys, tokens,
5
+ * and secrets to every subprocess), this module provides a filtered env
6
+ * containing only system-essential variables plus an explicit allowlist.
7
+ *
8
+ * Security motivation:
9
+ * - Bash tool commands can read env vars via `env`, `echo $SECRET`, etc.
10
+ * - Any subprocess with full env access has all API keys and credentials.
11
+ */
12
+ /**
13
+ * System-essential env vars that are always included.
14
+ * These are required for basic shell/process functionality.
15
+ */
16
+ const SYSTEM_VARS = [
17
+ // Core system
18
+ "PATH", "HOME", "USER", "SHELL", "TERM", "LANG", "LC_ALL", "LC_CTYPE",
19
+ // Temp directories
20
+ "TMPDIR", "TMP", "TEMP",
21
+ // Node.js
22
+ "NODE_ENV", "NODE_PATH", "NODE_OPTIONS",
23
+ // Editor (for interactive tools)
24
+ "EDITOR", "VISUAL",
25
+ // XDG base directories
26
+ "XDG_DATA_HOME", "XDG_CONFIG_HOME", "XDG_CACHE_HOME", "XDG_RUNTIME_DIR",
27
+ // Platform-specific
28
+ "DISPLAY", "WAYLAND_DISPLAY", "DBUS_SESSION_BUS_ADDRESS", // Linux
29
+ "SYSTEMROOT", "COMSPEC", "PATHEXT", "APPDATA", "LOCALAPPDATA", "PROGRAMFILES", "WINDIR", // Windows
30
+ // SSH (for git operations)
31
+ "SSH_AUTH_SOCK", "SSH_AGENT_PID",
32
+ // Git
33
+ "GIT_AUTHOR_NAME", "GIT_AUTHOR_EMAIL", "GIT_COMMITTER_NAME", "GIT_COMMITTER_EMAIL",
34
+ // Proxy (for network access)
35
+ "HTTP_PROXY", "HTTPS_PROXY", "NO_PROXY", "http_proxy", "https_proxy", "no_proxy",
36
+ // Timezone
37
+ "TZ",
38
+ ];
39
+ /**
40
+ * Create a filtered copy of process.env containing only safe variables.
41
+ *
42
+ * @param extra - Additional env vars to include (e.g. from MCP config).
43
+ * These take precedence over process.env values.
44
+ * @param allowVars - Additional var names to pass through from process.env.
45
+ * Use this for specific Polpo env vars agents need.
46
+ */
47
+ export function safeEnv(extra, allowVars) {
48
+ const result = {};
49
+ // Include system essentials from process.env
50
+ for (const key of SYSTEM_VARS) {
51
+ if (process.env[key] !== undefined) {
52
+ result[key] = process.env[key];
53
+ }
54
+ }
55
+ // Include explicitly allowed vars
56
+ if (allowVars) {
57
+ for (const key of allowVars) {
58
+ if (process.env[key] !== undefined) {
59
+ result[key] = process.env[key];
60
+ }
61
+ }
62
+ }
63
+ // Override/add extra vars (from config)
64
+ if (extra) {
65
+ Object.assign(result, extra);
66
+ }
67
+ return result;
68
+ }
69
+ /**
70
+ * Convenience: create safe env for bash tool.
71
+ * Includes system vars only — no API keys, no secrets.
72
+ */
73
+ export function bashSafeEnv() {
74
+ return safeEnv();
75
+ }
76
+ //# sourceMappingURL=safe-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-env.js","sourceRoot":"","sources":["../src/safe-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;GAGG;AACH,MAAM,WAAW,GAAG;IAClB,cAAc;IACd,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU;IACrE,mBAAmB;IACnB,QAAQ,EAAE,KAAK,EAAE,MAAM;IACvB,UAAU;IACV,UAAU,EAAE,WAAW,EAAE,cAAc;IACvC,iCAAiC;IACjC,QAAQ,EAAE,QAAQ;IAClB,uBAAuB;IACvB,eAAe,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,iBAAiB;IACvE,oBAAoB;IACpB,SAAS,EAAE,iBAAiB,EAAE,0BAA0B,EAAG,QAAQ;IACnE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAG,UAAU;IACpG,2BAA2B;IAC3B,eAAe,EAAE,eAAe;IAChC,MAAM;IACN,iBAAiB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,qBAAqB;IAClF,6BAA6B;IAC7B,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU;IAChF,WAAW;IACX,IAAI;CACL,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CACrB,KAA8B,EAC9B,SAAoB;IAEpB,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,6CAA6C;IAC7C,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;QAC9B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAClC,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,IAAI,SAAS,EAAE,CAAC;QACd,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBACnC,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO,OAAO,EAAE,CAAC;AACnB,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Web search tools powered by Exa (exa.ai).
3
+ *
4
+ * Provides semantic web search with optional content extraction.
5
+ * Requires EXA_API_KEY in vault or environment.
6
+ *
7
+ * Tools:
8
+ * - search_web: Search the web with a natural language query
9
+ * - search_find_similar: Find pages similar to a given URL
10
+ */
11
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
12
+ import type { ResolvedVault } from "./types.js";
13
+ export type SearchToolName = "search_web" | "search_find_similar";
14
+ export declare const ALL_SEARCH_TOOL_NAMES: readonly SearchToolName[];
15
+ /**
16
+ * Create Exa-powered web search tools.
17
+ *
18
+ * @param vault - Resolved vault credentials (looks for EXA_API_KEY)
19
+ * @param allowedTools - Optional filter
20
+ */
21
+ export declare function createSearchTools(vault?: ResolvedVault, allowedTools?: string[]): AgentTool<any>[];
22
+ //# sourceMappingURL=search-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-tools.d.ts","sourceRoot":"","sources":["../src/search-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAuNhD,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,qBAAqB,CAAC;AAElE,eAAO,MAAM,qBAAqB,EAAE,SAAS,cAAc,EAA0C,CAAC;AAEtG;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,CAAC,EAAE,aAAa,EACrB,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,SAAS,CAAC,GAAG,CAAC,EAAE,CAWlB"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * Web search tools powered by Exa (exa.ai).
3
+ *
4
+ * Provides semantic web search with optional content extraction.
5
+ * Requires EXA_API_KEY in vault or environment.
6
+ *
7
+ * Tools:
8
+ * - search_web: Search the web with a natural language query
9
+ * - search_find_similar: Find pages similar to a given URL
10
+ */
11
+ import { Type } from "@sinclair/typebox";
12
+ const EXA_BASE = "https://api.exa.ai";
13
+ const DEFAULT_NUM_RESULTS = 5;
14
+ const DEFAULT_TIMEOUT = 15_000;
15
+ // ─── Helpers ───
16
+ function getExaApiKey(vault) {
17
+ // Try vault first (service "exa", key "key"), then environment
18
+ return vault?.getKey("exa", "key") ?? process.env.EXA_API_KEY;
19
+ }
20
+ function ok(text, details) { return { content: [{ type: "text", text }], details: details ?? {} }; }
21
+ function err(text) { return { content: [{ type: "text", text }], details: { error: true } }; }
22
+ function formatResults(results, withContent) {
23
+ if (results.length === 0)
24
+ return "(no results)";
25
+ return results.map((r, i) => {
26
+ const parts = [`${i + 1}. **${r.title}**`, ` ${r.url}`];
27
+ if (r.publishedDate)
28
+ parts.push(` Published: ${r.publishedDate}`);
29
+ if (r.author)
30
+ parts.push(` Author: ${r.author}`);
31
+ if (r.summary) {
32
+ parts.push(` Summary: ${r.summary}`);
33
+ }
34
+ else if (withContent && r.text) {
35
+ // Truncate content to avoid token bloat
36
+ const text = r.text.length > 1500 ? r.text.slice(0, 1500) + "..." : r.text;
37
+ parts.push(` Content: ${text}`);
38
+ }
39
+ if (r.highlights?.length) {
40
+ parts.push(` Highlights:`);
41
+ for (const h of r.highlights.slice(0, 3)) {
42
+ parts.push(` - ${h}`);
43
+ }
44
+ }
45
+ return parts.join("\n");
46
+ }).join("\n\n");
47
+ }
48
+ // ─── Tool: search_web ───
49
+ const SearchWebSchema = Type.Object({
50
+ query: Type.String({ description: "Natural language search query. Be descriptive — Exa uses semantic search, not keywords." }),
51
+ numResults: Type.Optional(Type.Number({ description: `Number of results to return (default: ${DEFAULT_NUM_RESULTS}, max: 20)` })),
52
+ includeContent: Type.Optional(Type.Boolean({ description: "Include page content/summary in results (default: true). Costs more but saves a follow-up http_fetch." })),
53
+ includeDomains: Type.Optional(Type.Array(Type.String(), { description: "Only return results from these domains (e.g. ['github.com', 'docs.python.org'])" })),
54
+ excludeDomains: Type.Optional(Type.Array(Type.String(), { description: "Exclude results from these domains" })),
55
+ startPublishedDate: Type.Optional(Type.String({ description: "Only results published after this date (ISO format, e.g. '2024-01-01')" })),
56
+ category: Type.Optional(Type.String({ description: "Filter by category: company, research_paper, news, pdf, github, tweet, personal_site, linkedin_profile" })),
57
+ });
58
+ function createSearchWebTool(vault) {
59
+ return {
60
+ name: "search_web",
61
+ label: "Web Search",
62
+ description: "Search the web using Exa's semantic search. Returns relevant pages with titles, URLs, and optionally content/summaries. " +
63
+ "Use natural language queries — Exa understands meaning, not just keywords. " +
64
+ "Example: 'how to implement OAuth2 with Better Auth in Next.js'",
65
+ parameters: SearchWebSchema,
66
+ async execute(_id, params, signal) {
67
+ const apiKey = getExaApiKey(vault);
68
+ if (!apiKey) {
69
+ return err("Error: EXA_API_KEY not found. Add it to vault (service: exa, key: key) or set as environment variable.");
70
+ }
71
+ const numResults = Math.min(params.numResults ?? DEFAULT_NUM_RESULTS, 20);
72
+ const includeContent = params.includeContent ?? true;
73
+ const body = {
74
+ query: params.query,
75
+ numResults,
76
+ type: "auto",
77
+ };
78
+ if (includeContent) {
79
+ body.contents = {
80
+ text: { maxCharacters: 2000 },
81
+ highlights: { numSentences: 3 },
82
+ summary: { query: params.query },
83
+ };
84
+ }
85
+ if (params.includeDomains?.length)
86
+ body.includeDomains = params.includeDomains;
87
+ if (params.excludeDomains?.length)
88
+ body.excludeDomains = params.excludeDomains;
89
+ if (params.startPublishedDate)
90
+ body.startPublishedDate = params.startPublishedDate;
91
+ if (params.category)
92
+ body.category = params.category;
93
+ try {
94
+ const controller = new AbortController();
95
+ const timeout = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT);
96
+ if (signal)
97
+ signal.addEventListener("abort", () => controller.abort());
98
+ const response = await fetch(`${EXA_BASE}/search`, {
99
+ method: "POST",
100
+ headers: {
101
+ "x-api-key": apiKey,
102
+ "Content-Type": "application/json",
103
+ },
104
+ body: JSON.stringify(body),
105
+ signal: controller.signal,
106
+ });
107
+ clearTimeout(timeout);
108
+ if (!response.ok) {
109
+ const errText = await response.text().catch(() => "");
110
+ return err(`Error: Exa API returned ${response.status}: ${errText}`);
111
+ }
112
+ const data = (await response.json());
113
+ const formatted = formatResults(data.results, includeContent);
114
+ const header = `Found ${data.results.length} result(s) for: "${params.query}"`;
115
+ return ok(`${header}\n\n${formatted}`);
116
+ }
117
+ catch (e) {
118
+ const message = e.name === "AbortError" ? "Search timed out" : e.message;
119
+ return err(`Error: Web search failed — ${message}`);
120
+ }
121
+ },
122
+ };
123
+ }
124
+ // ─── Tool: search_find_similar ───
125
+ const FindSimilarSchema = Type.Object({
126
+ url: Type.String({ description: "URL of a page to find similar content for" }),
127
+ numResults: Type.Optional(Type.Number({ description: `Number of results (default: ${DEFAULT_NUM_RESULTS}, max: 20)` })),
128
+ includeContent: Type.Optional(Type.Boolean({ description: "Include page content/summary (default: false)" })),
129
+ excludeDomains: Type.Optional(Type.Array(Type.String(), { description: "Exclude results from these domains" })),
130
+ });
131
+ function createFindSimilarTool(vault) {
132
+ return {
133
+ name: "search_find_similar",
134
+ label: "Find Similar Pages",
135
+ description: "Find web pages similar to a given URL. Useful for finding alternatives, competitors, or related resources. " +
136
+ "Example: give it a GitHub repo URL to find similar projects.",
137
+ parameters: FindSimilarSchema,
138
+ async execute(_id, params, signal) {
139
+ const apiKey = getExaApiKey(vault);
140
+ if (!apiKey) {
141
+ return err("Error: EXA_API_KEY not found. Add it to vault or set as environment variable.");
142
+ }
143
+ const numResults = Math.min(params.numResults ?? DEFAULT_NUM_RESULTS, 20);
144
+ const includeContent = params.includeContent ?? false;
145
+ const body = {
146
+ url: params.url,
147
+ numResults,
148
+ };
149
+ if (includeContent) {
150
+ body.contents = {
151
+ text: { maxCharacters: 2000 },
152
+ highlights: { numSentences: 3 },
153
+ };
154
+ }
155
+ if (params.excludeDomains?.length)
156
+ body.excludeDomains = params.excludeDomains;
157
+ try {
158
+ const controller = new AbortController();
159
+ const timeout = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT);
160
+ if (signal)
161
+ signal.addEventListener("abort", () => controller.abort());
162
+ const response = await fetch(`${EXA_BASE}/findSimilar`, {
163
+ method: "POST",
164
+ headers: {
165
+ "x-api-key": apiKey,
166
+ "Content-Type": "application/json",
167
+ },
168
+ body: JSON.stringify(body),
169
+ signal: controller.signal,
170
+ });
171
+ clearTimeout(timeout);
172
+ if (!response.ok) {
173
+ const errText = await response.text().catch(() => "");
174
+ return err(`Error: Exa API returned ${response.status}: ${errText}`);
175
+ }
176
+ const data = (await response.json());
177
+ const formatted = formatResults(data.results, includeContent);
178
+ const header = `Found ${data.results.length} page(s) similar to: ${params.url}`;
179
+ return ok(`${header}\n\n${formatted}`);
180
+ }
181
+ catch (e) {
182
+ const message = e.name === "AbortError" ? "Search timed out" : e.message;
183
+ return err(`Error: Find similar failed — ${message}`);
184
+ }
185
+ },
186
+ };
187
+ }
188
+ export const ALL_SEARCH_TOOL_NAMES = ["search_web", "search_find_similar"];
189
+ /**
190
+ * Create Exa-powered web search tools.
191
+ *
192
+ * @param vault - Resolved vault credentials (looks for EXA_API_KEY)
193
+ * @param allowedTools - Optional filter
194
+ */
195
+ export function createSearchTools(vault, allowedTools) {
196
+ const factories = {
197
+ search_web: () => createSearchWebTool(vault),
198
+ search_find_similar: () => createFindSimilarTool(vault),
199
+ };
200
+ const names = allowedTools
201
+ ? ALL_SEARCH_TOOL_NAMES.filter(n => allowedTools.some(a => a.toLowerCase() === n))
202
+ : [...ALL_SEARCH_TOOL_NAMES];
203
+ return names.map(n => factories[n]());
204
+ }
205
+ //# sourceMappingURL=search-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-tools.js","sourceRoot":"","sources":["../src/search-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * SSRF guard — blocks HTTP requests to internal/private network addresses.
3
+ *
4
+ * Prevents agents from making requests to:
5
+ * - localhost (127.0.0.0/8, ::1, 0.0.0.0, localhost)
6
+ * - RFC1918 private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
7
+ * - Link-local / cloud metadata (169.254.0.0/16, metadata.google.internal)
8
+ */
9
+ /**
10
+ * Assert that a URL does not point to a private/internal network address.
11
+ * Throws an Error if the URL is blocked.
12
+ *
13
+ * @param urlString - The URL to check
14
+ * @throws Error with descriptive message if the URL targets an internal address
15
+ */
16
+ export declare function assertUrlAllowed(urlString: string): void;
17
+ //# sourceMappingURL=ssrf-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf-guard.d.ts","sourceRoot":"","sources":["../src/ssrf-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiCH;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAsDxD"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * SSRF guard — blocks HTTP requests to internal/private network addresses.
3
+ *
4
+ * Prevents agents from making requests to:
5
+ * - localhost (127.0.0.0/8, ::1, 0.0.0.0, localhost)
6
+ * - RFC1918 private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
7
+ * - Link-local / cloud metadata (169.254.0.0/16, metadata.google.internal)
8
+ */
9
+ /** Hostnames that are always blocked. */
10
+ const BLOCKED_HOSTNAMES = new Set([
11
+ "localhost",
12
+ "metadata.google.internal",
13
+ ]);
14
+ /**
15
+ * Parse an IPv4 address string into a 32-bit number.
16
+ * Returns undefined if not a valid IPv4 address.
17
+ */
18
+ function parseIPv4(host) {
19
+ const parts = host.split(".");
20
+ if (parts.length !== 4)
21
+ return undefined;
22
+ let num = 0;
23
+ for (const part of parts) {
24
+ const octet = Number(part);
25
+ if (!Number.isInteger(octet) || octet < 0 || octet > 255)
26
+ return undefined;
27
+ num = (num << 8) | octet;
28
+ }
29
+ return num >>> 0; // unsigned 32-bit
30
+ }
31
+ /**
32
+ * Check whether an IPv4 address (as 32-bit number) falls within a CIDR range.
33
+ */
34
+ function inRange(ip, base, bits) {
35
+ const mask = bits === 0 ? 0 : (~0 << (32 - bits)) >>> 0;
36
+ return (ip & mask) === (base & mask);
37
+ }
38
+ /**
39
+ * Assert that a URL does not point to a private/internal network address.
40
+ * Throws an Error if the URL is blocked.
41
+ *
42
+ * @param urlString - The URL to check
43
+ * @throws Error with descriptive message if the URL targets an internal address
44
+ */
45
+ export function assertUrlAllowed(urlString) {
46
+ let parsed;
47
+ try {
48
+ parsed = new URL(urlString);
49
+ }
50
+ catch {
51
+ throw new Error(`Invalid URL: ${urlString}`);
52
+ }
53
+ const hostname = parsed.hostname.toLowerCase();
54
+ // Strip IPv6 brackets
55
+ const bareHost = hostname.startsWith("[") && hostname.endsWith("]")
56
+ ? hostname.slice(1, -1)
57
+ : hostname;
58
+ // Block known hostnames
59
+ if (BLOCKED_HOSTNAMES.has(bareHost)) {
60
+ throw new Error(`SSRF blocked: requests to ${bareHost} are not allowed`);
61
+ }
62
+ // Block IPv6 loopback
63
+ if (bareHost === "::1" || bareHost === "::0" || bareHost === "0:0:0:0:0:0:0:1" || bareHost === "0:0:0:0:0:0:0:0") {
64
+ throw new Error(`SSRF blocked: requests to ${bareHost} are not allowed`);
65
+ }
66
+ // Block 0.0.0.0
67
+ if (bareHost === "0.0.0.0") {
68
+ throw new Error(`SSRF blocked: requests to 0.0.0.0 are not allowed`);
69
+ }
70
+ // Check IPv4 ranges
71
+ const ipv4 = parseIPv4(bareHost);
72
+ if (ipv4 !== undefined) {
73
+ // 127.0.0.0/8 — loopback
74
+ if (inRange(ipv4, 0x7f000000, 8)) {
75
+ throw new Error(`SSRF blocked: requests to ${bareHost} (loopback) are not allowed`);
76
+ }
77
+ // 10.0.0.0/8 — RFC1918
78
+ if (inRange(ipv4, 0x0a000000, 8)) {
79
+ throw new Error(`SSRF blocked: requests to ${bareHost} (private network) are not allowed`);
80
+ }
81
+ // 172.16.0.0/12 — RFC1918
82
+ if (inRange(ipv4, 0xac100000, 12)) {
83
+ throw new Error(`SSRF blocked: requests to ${bareHost} (private network) are not allowed`);
84
+ }
85
+ // 192.168.0.0/16 — RFC1918
86
+ if (inRange(ipv4, 0xc0a80000, 16)) {
87
+ throw new Error(`SSRF blocked: requests to ${bareHost} (private network) are not allowed`);
88
+ }
89
+ // 169.254.0.0/16 — link-local / cloud metadata
90
+ if (inRange(ipv4, 0xa9fe0000, 16)) {
91
+ throw new Error(`SSRF blocked: requests to ${bareHost} (link-local/metadata) are not allowed`);
92
+ }
93
+ }
94
+ }
95
+ //# sourceMappingURL=ssrf-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf-guard.js","sourceRoot":"","sources":["../src/ssrf-guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Types used by tools — local definitions to avoid importing from polpo-ai root.
3
+ */
4
+ /** Resolved vault credentials for an agent. */
5
+ export interface ResolvedVault {
6
+ get(service: string): Record<string, string> | undefined;
7
+ getSmtp(): Record<string, any> | undefined;
8
+ getImap(): Record<string, any> | undefined;
9
+ getKey(service: string, key: string): string | undefined;
10
+ has(service: string): boolean;
11
+ list(): Array<{
12
+ service: string;
13
+ type: string;
14
+ keys: string[];
15
+ }>;
16
+ }
17
+ /** WhatsApp message store interface. Uses any for maximum compatibility. */
18
+ export interface WhatsAppStore {
19
+ [method: string]: (...args: any[]) => any;
20
+ }
21
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IACzD,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;IAC3C,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;IAC3C,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IACzD,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,IAAI,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAClE;AAED,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;CAC3C"}
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Types used by tools — local definitions to avoid importing from polpo-ai root.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Vault tools for agents to access their own credentials at runtime.
3
+ *
4
+ * Provides read-only access to the agent's resolved vault:
5
+ * - vault_get: retrieve credentials for a specific service
6
+ * - vault_list: list available services (keys only, values masked)
7
+ *
8
+ * The vault is pre-resolved at spawn time — ${ENV_VAR} references are already
9
+ * replaced with actual values. Agents can only see their own credentials.
10
+ */
11
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
12
+ import type { ResolvedVault } from "./types.js";
13
+ export declare const ALL_VAULT_TOOL_NAMES: readonly ["vault_get", "vault_list"];
14
+ export type VaultToolName = (typeof ALL_VAULT_TOOL_NAMES)[number];
15
+ /**
16
+ * Create vault tools (core — always included when vault is available).
17
+ * Vault tools are core tools: they are always available to every agent
18
+ * that has a resolved vault, regardless of allowedTools configuration.
19
+ */
20
+ export declare function createVaultToolsCore(vault: ResolvedVault): AgentTool<any>[];
21
+ /**
22
+ * Create vault tools for an agent, filtered by allowedTools.
23
+ * @deprecated Use createVaultToolsCore() — vault tools are now core tools (always available).
24
+ */
25
+ export declare function createVaultTools(vault: ResolvedVault, allowedTools?: string[]): AgentTool<any>[];
26
+ //# sourceMappingURL=vault-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-tools.d.ts","sourceRoot":"","sources":["../src/vault-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,eAAO,MAAM,oBAAoB,sCAAuC,CAAC;AACzE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AA4DlE;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAE3E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAQhG"}
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Vault tools for agents to access their own credentials at runtime.
3
+ *
4
+ * Provides read-only access to the agent's resolved vault:
5
+ * - vault_get: retrieve credentials for a specific service
6
+ * - vault_list: list available services (keys only, values masked)
7
+ *
8
+ * The vault is pre-resolved at spawn time — ${ENV_VAR} references are already
9
+ * replaced with actual values. Agents can only see their own credentials.
10
+ */
11
+ import { Type } from "@sinclair/typebox";
12
+ // ─── Tool names ───
13
+ export const ALL_VAULT_TOOL_NAMES = ["vault_get", "vault_list"];
14
+ // ─── Tool: vault_get ───
15
+ const VaultGetSchema = Type.Object({
16
+ service: Type.String({ description: "Service name to retrieve credentials for (e.g. 'smtp', 'openai', 'stripe')" }),
17
+ });
18
+ function createVaultGetTool(vault) {
19
+ return {
20
+ name: "vault_get",
21
+ label: "Get Vault Credentials",
22
+ description: "Retrieve credentials for a specific service from your vault. Returns all credential key-value pairs for the requested service. Use vault_list first to see available services.",
23
+ parameters: VaultGetSchema,
24
+ async execute(_toolCallId, params) {
25
+ const creds = vault.get(params.service);
26
+ if (!creds) {
27
+ return {
28
+ content: [{ type: "text", text: `No vault entry found for service "${params.service}". Use vault_list to see available services.` }],
29
+ details: { service: params.service, found: false },
30
+ };
31
+ }
32
+ const lines = Object.entries(creds).map(([key, value]) => ` ${key}: ${value}`);
33
+ return {
34
+ content: [{ type: "text", text: `Credentials for "${params.service}":\n${lines.join("\n")}` }],
35
+ details: { service: params.service, found: true, keys: Object.keys(creds) },
36
+ };
37
+ },
38
+ };
39
+ }
40
+ // ─── Tool: vault_list ───
41
+ const VaultListSchema = Type.Object({});
42
+ function createVaultListTool(vault) {
43
+ return {
44
+ name: "vault_list",
45
+ label: "List Vault Services",
46
+ description: "List all available services in your vault. Shows service names, types, and credential key names (values are not shown). Use vault_get to retrieve actual credential values.",
47
+ parameters: VaultListSchema,
48
+ async execute() {
49
+ const services = vault.list();
50
+ if (services.length === 0) {
51
+ return {
52
+ content: [{ type: "text", text: "No vault entries configured for this agent." }],
53
+ details: { count: 0, services: [] },
54
+ };
55
+ }
56
+ const lines = services.map(s => ` - ${s.service} (${s.type}): keys=[${s.keys.join(", ")}]`);
57
+ return {
58
+ content: [{ type: "text", text: `${services.length} vault service(s):\n${lines.join("\n")}` }],
59
+ details: { count: services.length, services: services.map(s => s.service) },
60
+ };
61
+ },
62
+ };
63
+ }
64
+ // ─── Factory ───
65
+ /**
66
+ * Create vault tools (core — always included when vault is available).
67
+ * Vault tools are core tools: they are always available to every agent
68
+ * that has a resolved vault, regardless of allowedTools configuration.
69
+ */
70
+ export function createVaultToolsCore(vault) {
71
+ return [createVaultGetTool(vault), createVaultListTool(vault)];
72
+ }
73
+ /**
74
+ * Create vault tools for an agent, filtered by allowedTools.
75
+ * @deprecated Use createVaultToolsCore() — vault tools are now core tools (always available).
76
+ */
77
+ export function createVaultTools(vault, allowedTools) {
78
+ const tools = [];
79
+ const allowed = (name) => !allowedTools || allowedTools.includes(name);
80
+ if (allowed("vault_get"))
81
+ tools.push(createVaultGetTool(vault));
82
+ if (allowed("vault_list"))
83
+ tools.push(createVaultListTool(vault));
84
+ return tools;
85
+ }
86
+ //# sourceMappingURL=vault-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vault-tools.js","sourceRoot":"","sources":["../src/vault-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * WhatsApp tools — agent-level tools for reading, sending, and searching
3
+ * WhatsApp messages via the Baileys bridge.
4
+ *
5
+ * Requires an active WhatsApp bridge connection (configured in polpo.json).
6
+ * Messages are stored locally in `.polpo/whatsapp.db`.
7
+ */
8
+ import type { AgentTool } from "@mariozechner/pi-agent-core";
9
+ import type { WhatsAppStore } from "./types.js";
10
+ interface WhatsAppToolDeps {
11
+ store: WhatsAppStore;
12
+ sendMessage: (jid: string, text: string) => Promise<string | undefined>;
13
+ }
14
+ export type WhatsAppToolName = "whatsapp_list" | "whatsapp_read" | "whatsapp_send" | "whatsapp_search" | "whatsapp_contacts";
15
+ export declare const ALL_WHATSAPP_TOOL_NAMES: WhatsAppToolName[];
16
+ export declare function createWhatsAppTools(deps: WhatsAppToolDeps, allowedTools?: string[]): AgentTool<any>[];
17
+ export {};
18
+ //# sourceMappingURL=whatsapp-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whatsapp-tools.d.ts","sourceRoot":"","sources":["../src/whatsapp-tools.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmDhD,UAAU,gBAAgB;IACxB,KAAK,EAAE,aAAa,CAAC;IACrB,WAAW,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACzE;AAqKD,MAAM,MAAM,gBAAgB,GACxB,eAAe,GACf,eAAe,GACf,eAAe,GACf,iBAAiB,GACjB,mBAAmB,CAAC;AAExB,eAAO,MAAM,uBAAuB,EAAE,gBAAgB,EAMrD,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,gBAAgB,EACtB,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,SAAS,CAAC,GAAG,CAAC,EAAE,CAclB"}