@easynet/agent-tool-buildin 0.0.1 → 0.0.2

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../context.ts","../CoreAdapter.ts","../CoreToolsModule.ts","../types.ts","../fs/readText.ts","../security/sandbox.ts","../fs/writeText.ts","../fs/listDir.ts","../fs/searchText.ts","../fs/sha256.ts","../fs/deletePath.ts","../security/ssrf.ts","../http/fetchText.ts","../http/fetchJson.ts","../http/downloadFile.ts","../http/head.ts","../http/duckduckgoSearch.ts","../http/fetchPageMainContent.ts","../util/jsonSelect.ts","../util/truncate.ts","../util/hashText.ts","../util/now.ts","../util/templateRender.ts","../exec/runCommand.ts"],"sourcesContent":["/**\n * Run context for builtin-tools: config + execCtx injected by the adapter before each invoke.\n * Handlers use getBuiltinContext() so they stay @tool-signature (args only) for scan.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { CoreToolContext } from \"./types.js\";\n\nconst storage = new AsyncLocalStorage<CoreToolContext>();\n\nexport function setBuiltinContext(ctx: CoreToolContext): void {\n storage.enterWith(ctx);\n}\n\nexport function getBuiltinContext(): CoreToolContext {\n const ctx = storage.getStore();\n if (!ctx) throw new Error(\"Builtin context not set; invoke only through CoreAdapter.\");\n return ctx;\n}\n\nexport function runWithBuiltinContext<T>(ctx: CoreToolContext, fn: () => Promise<T>): Promise<T> {\n return storage.run(ctx, fn);\n}\n","import type { ToolAdapter, ToolSpec } from \"@easynet/agent-tool\";\nimport type { ExecContext } from \"@easynet/agent-tool\";\nimport type { CoreToolHandler, CoreToolContext, CoreToolsConfig } from \"./types.js\";\nimport { runWithBuiltinContext } from \"./context.js\";\n\n/**\n * Adapter for core tools (kind=\"core\").\n * Dispatches to registered handler functions by tool name.\n *\n * Core tools are local, atomic operations (filesystem, HTTP, utilities)\n * that enforce their own security constraints (sandbox, SSRF) in addition\n * to the PolicyEngine capability gating.\n */\nexport class CoreAdapter implements ToolAdapter {\n readonly kind = \"core\" as const;\n private readonly handlers = new Map<string, CoreToolHandler>();\n private readonly config: CoreToolsConfig;\n\n constructor(config: CoreToolsConfig) {\n this.config = config;\n }\n\n /**\n * Register a handler for a specific core tool name.\n */\n registerHandler(toolName: string, handler: CoreToolHandler): void {\n this.handlers.set(toolName, handler);\n }\n\n /**\n * Unregister a handler.\n */\n unregisterHandler(toolName: string): boolean {\n return this.handlers.delete(toolName);\n }\n\n /**\n * List registered core tool names.\n */\n getRegisteredTools(): string[] {\n return Array.from(this.handlers.keys());\n }\n\n /**\n * Invoke dispatches to the appropriate handler by spec.name.\n */\n async invoke(\n spec: ToolSpec,\n args: unknown,\n ctx: ExecContext,\n ): Promise<{ result: unknown; raw?: unknown }> {\n const handler = this.handlers.get(spec.name);\n if (!handler) {\n throw new Error(\n `Core tool handler not found: ${spec.name}. Available: [${this.getRegisteredTools().join(\", \")}]`,\n );\n }\n\n const coreCtx: CoreToolContext = {\n execCtx: ctx,\n config: this.config,\n };\n\n const output = await runWithBuiltinContext(coreCtx, () =>\n handler(args as Record<string, unknown>),\n );\n\n return {\n result: output.result,\n raw: { evidence: output.evidence },\n };\n }\n}\n","import { CoreAdapter } from \"./CoreAdapter.js\";\nimport { createToolSpec, type CreateToolSpecOptions } from \"@easynet/agent-tool/core\";\nimport type { ToolRegistry } from \"@easynet/agent-tool\";\nimport type { CoreToolsConfig } from \"./types.js\";\nimport { DEFAULT_CORE_TOOLS_CONFIG } from \"./types.js\";\n\n// Handlers only (specs generated by framework from manifest)\nimport { readTextHandler } from \"./fs/readText.js\";\nimport { writeTextHandler } from \"./fs/writeText.js\";\nimport { listDirHandler } from \"./fs/listDir.js\";\nimport { searchTextHandler } from \"./fs/searchText.js\";\nimport { sha256Handler } from \"./fs/sha256.js\";\nimport { deletePathHandler } from \"./fs/deletePath.js\";\nimport { fetchTextHandler } from \"./http/fetchText.js\";\nimport { fetchJsonHandler } from \"./http/fetchJson.js\";\nimport { downloadFileHandler } from \"./http/downloadFile.js\";\nimport { headHandler } from \"./http/head.js\";\nimport { duckduckgoSearchHandler } from \"./http/duckduckgoSearch.js\";\nimport { fetchPageMainContentHandler } from \"./http/fetchPageMainContent.js\";\nimport { jsonSelectHandler } from \"./util/jsonSelect.js\";\nimport { truncateHandler } from \"./util/truncate.js\";\nimport { hashTextHandler } from \"./util/hashText.js\";\nimport { nowHandler } from \"./util/now.js\";\nimport { templateRenderHandler } from \"./util/templateRender.js\";\nimport { runCommandHandler } from \"./exec/runCommand.js\";\n\n/** Framework-generated spec options for all core tools (enables schema derivation from handler types). */\nconst CORE_TOOL_MANIFEST: CreateToolSpecOptions[] = [\n // Filesystem\n {\n name: \"core/fs.readText\",\n kind: \"core\",\n description: \"Read a UTF-8 text file from the sandbox\",\n tags: [\"filesystem\", \"read\", \"core\"],\n capabilities: [\"read:fs\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/fs.writeText\",\n kind: \"core\",\n description: \"Write UTF-8 text to a file in the sandbox\",\n tags: [\"filesystem\", \"write\", \"core\"],\n capabilities: [\"write:fs\"],\n sideEffect: \"local_write\",\n },\n {\n name: \"core/fs.listDir\",\n kind: \"core\",\n description: \"List directory contents in the sandbox\",\n tags: [\"filesystem\", \"read\", \"core\"],\n capabilities: [\"read:fs\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/fs.searchText\",\n kind: \"core\",\n description: \"Search for text patterns in files within the sandbox\",\n tags: [\"filesystem\", \"search\", \"core\"],\n capabilities: [\"read:fs\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/fs.sha256\",\n kind: \"core\",\n description: \"Compute SHA-256 hash of a file in the sandbox\",\n tags: [\"filesystem\", \"hash\", \"core\"],\n capabilities: [\"read:fs\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/fs.deletePath\",\n kind: \"core\",\n description:\n \"Delete a file or directory in the sandbox (dangerous, requires explicit confirmation)\",\n tags: [\"filesystem\", \"delete\", \"dangerous\", \"core\"],\n capabilities: [\"danger:destructive\", \"write:fs\"],\n sideEffect: \"destructive\",\n },\n // HTTP\n {\n name: \"core/http.fetchText\",\n kind: \"core\",\n description: \"Fetch a URL and return the response as text\",\n tags: [\"http\", \"network\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.fetchJson\",\n kind: \"core\",\n description: \"Fetch a URL and return the response as parsed JSON\",\n tags: [\"http\", \"network\", \"json\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.downloadFile\",\n kind: \"core\",\n description: \"Download a file from a URL to the sandbox\",\n tags: [\"http\", \"network\", \"download\", \"core\"],\n capabilities: [\"network\", \"write:fs\"],\n sideEffect: \"local_write\",\n },\n {\n name: \"core/http.head\",\n kind: \"core\",\n description: \"Send a HEAD request to get response headers without body\",\n tags: [\"http\", \"network\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.duckduckgoSearch\",\n kind: \"core\",\n description:\n \"Search DuckDuckGo via Instant Answer API (no API key). Add api.duckduckgo.com to allowedHosts.\",\n tags: [\"http\", \"search\", \"duckduckgo\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.fetchPageMainContent\",\n kind: \"core\",\n description:\n \"Fetch a URL and return only the main content (main/article/body text). Strips nav, header, footer, scripts.\",\n tags: [\"http\", \"network\", \"html\", \"main-content\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n // Utils\n {\n name: \"core/util.json.select\",\n kind: \"core\",\n description: \"Select fields from JSON data using JMESPath expressions\",\n tags: [\"util\", \"json\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n {\n name: \"core/util.text.truncate\",\n kind: \"core\",\n description: \"Truncate text to a maximum character length with a suffix marker\",\n tags: [\"util\", \"text\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n {\n name: \"core/util.hash.sha256Text\",\n kind: \"core\",\n description: \"Compute SHA-256 hash of a text string\",\n tags: [\"util\", \"hash\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n {\n name: \"core/util.time.now\",\n kind: \"core\",\n description: \"Get the current time in various formats\",\n tags: [\"util\", \"time\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n {\n name: \"core/util.template.render\",\n kind: \"core\",\n description: \"Render a Mustache template with data\",\n tags: [\"util\", \"template\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n // Exec\n {\n name: \"core/exec.runCommand\",\n kind: \"core\",\n description:\n \"Run a Linux command in the sandbox (allowlist, timeout, no shell). Command name only; args as array.\",\n tags: [\"exec\", \"shell\", \"linux\", \"core\"],\n capabilities: [\"exec\"],\n sideEffect: \"local_write\",\n },\n];\n\nconst CORE_TOOL_HANDLERS = [\n readTextHandler,\n writeTextHandler,\n listDirHandler,\n searchTextHandler,\n sha256Handler,\n deletePathHandler,\n fetchTextHandler,\n fetchJsonHandler,\n downloadFileHandler,\n headHandler,\n duckduckgoSearchHandler,\n fetchPageMainContentHandler,\n jsonSelectHandler,\n truncateHandler,\n hashTextHandler,\n nowHandler,\n templateRenderHandler,\n runCommandHandler,\n] as const;\n\n/** Specs generated from manifest (for re-export / backward compatibility). */\nexport const readTextSpec = createToolSpec(CORE_TOOL_MANIFEST[0]!);\nexport const writeTextSpec = createToolSpec(CORE_TOOL_MANIFEST[1]!);\nexport const listDirSpec = createToolSpec(CORE_TOOL_MANIFEST[2]!);\nexport const searchTextSpec = createToolSpec(CORE_TOOL_MANIFEST[3]!);\nexport const sha256Spec = createToolSpec(CORE_TOOL_MANIFEST[4]!);\nexport const deletePathSpec = createToolSpec(CORE_TOOL_MANIFEST[5]!);\nexport const fetchTextSpec = createToolSpec(CORE_TOOL_MANIFEST[6]!);\nexport const fetchJsonSpec = createToolSpec(CORE_TOOL_MANIFEST[7]!);\nexport const downloadFileSpec = createToolSpec(CORE_TOOL_MANIFEST[8]!);\nexport const headSpec = createToolSpec(CORE_TOOL_MANIFEST[9]!);\nexport const jsonSelectSpec = createToolSpec(CORE_TOOL_MANIFEST[10]!);\nexport const truncateSpec = createToolSpec(CORE_TOOL_MANIFEST[11]!);\nexport const hashTextSpec = createToolSpec(CORE_TOOL_MANIFEST[12]!);\nexport const nowSpec = createToolSpec(CORE_TOOL_MANIFEST[13]!);\nexport const templateRenderSpec = createToolSpec(CORE_TOOL_MANIFEST[14]!);\nexport const runCommandSpec = createToolSpec(CORE_TOOL_MANIFEST[15]!);\nexport const duckduckgoSearchSpec = createToolSpec(CORE_TOOL_MANIFEST[16]!);\nexport const fetchPageMainContentSpec = createToolSpec(CORE_TOOL_MANIFEST[17]!);\n\n/**\n * User-provided config for registerCoreTools.\n * `sandboxRoot` and `allowedHosts` are required; the rest have defaults.\n */\nexport type CoreToolsUserConfig = Pick<CoreToolsConfig, \"sandboxRoot\" | \"allowedHosts\"> &\n Partial<Omit<CoreToolsConfig, \"sandboxRoot\" | \"allowedHosts\">>;\n\n/** Builtin tool groups: fs, http, util, exec (name prefix core/fs., core/http., core/util., core/exec.). */\nexport type CoreToolsGroup = \"fs\" | \"http\" | \"util\" | \"exec\";\n\nconst CORE_GROUP_PREFIX: Record<CoreToolsGroup, string> = {\n fs: \"core/fs.\",\n http: \"core/http.\",\n util: \"core/util.\",\n exec: \"core/exec.\",\n};\n\nexport interface RegisterCoreToolsOptions {\n /** Restrict to these groups (e.g. [\"fs\", \"http\"]). Ignored if only is set. */\n groups?: CoreToolsGroup[];\n /** Restrict to these tool names (e.g. [\"core/fs.readText\"]). Takes precedence over groups. */\n only?: string[];\n}\n\n/**\n * Register core tools with a ToolRegistry and return the configured CoreAdapter.\n * Optionally restrict to groups or exact tool names.\n *\n * Usage:\n * ```ts\n * const coreAdapter = registerCoreTools(registry, config);\n * const coreAdapterFsOnly = registerCoreTools(registry, config, { groups: [\"fs\"] });\n * const coreAdapterNamed = registerCoreTools(registry, config, { only: [\"core/fs.readText\"] });\n * ```\n */\nexport function registerCoreTools(\n registry: ToolRegistry,\n userConfig: CoreToolsUserConfig,\n options?: RegisterCoreToolsOptions,\n): CoreAdapter {\n const config: CoreToolsConfig = {\n ...DEFAULT_CORE_TOOLS_CONFIG,\n ...userConfig,\n };\n\n const adapter = new CoreAdapter(config);\n const onlySet =\n options?.only?.length ? new Set(options.only) : null;\n const allowedPrefixes =\n !onlySet && options?.groups?.length\n ? options.groups.map((g) => CORE_GROUP_PREFIX[g])\n : null;\n\n for (let i = 0; i < CORE_TOOL_MANIFEST.length; i++) {\n const spec = createToolSpec(CORE_TOOL_MANIFEST[i]!);\n if (onlySet && !onlySet.has(spec.name)) continue;\n if (allowedPrefixes && !allowedPrefixes.some((p) => spec.name.startsWith(p))) {\n continue;\n }\n const handler = CORE_TOOL_HANDLERS[i]!;\n registry.register(spec);\n adapter.registerHandler(spec.name, handler);\n }\n\n return adapter;\n}\n","import type { ExecContext } from \"@easynet/agent-tool\";\nimport type { Evidence } from \"@easynet/agent-tool\";\n\n/**\n * Configuration for core tools runtime.\n */\nexport interface CoreToolsConfig {\n /** Absolute path. All FS operations are confined within this root. */\n sandboxRoot: string;\n /** Only these hosts may be fetched. Supports wildcard prefix (e.g. \"*.github.com\"). */\n allowedHosts: string[];\n /** Maximum bytes for fs.readText (default: 5MB) */\n maxReadBytes: number;\n /** Maximum bytes for HTTP response body (default: 5MB) */\n maxHttpBytes: number;\n /** Maximum bytes for http.downloadFile (default: 100MB) */\n maxDownloadBytes: number;\n /** CIDR ranges to block. Defaults include RFC1918 + loopback + link-local. */\n blockedCidrs: string[];\n /** Default HTTP timeout in ms (default: 15000) */\n defaultTimeoutMs: number;\n /** User-Agent header for HTTP requests */\n httpUserAgent: string;\n /** If true, large HTTP responses are auto-written to sandbox and a file ref is returned */\n enableAutoWriteLargeResponses: boolean;\n /** Allowed command names for exec.runCommand (e.g. [\"ls\", \"cat\", \"grep\"]). Empty = disabled. */\n allowedCommands: string[];\n /** Max combined stdout+stderr bytes for exec (default: 1MB) */\n maxCommandOutputBytes: number;\n /** Default timeout for exec in ms (default: 10000) */\n commandTimeoutMs: number;\n}\n\n/**\n * Default configuration values for core tools.\n */\nexport const DEFAULT_CORE_TOOLS_CONFIG: Omit<CoreToolsConfig, \"sandboxRoot\" | \"allowedHosts\"> = {\n maxReadBytes: 5 * 1024 * 1024,\n maxHttpBytes: 5 * 1024 * 1024,\n maxDownloadBytes: 100 * 1024 * 1024,\n blockedCidrs: [\n \"127.0.0.0/8\",\n \"10.0.0.0/8\",\n \"172.16.0.0/12\",\n \"192.168.0.0/16\",\n \"169.254.0.0/16\",\n \"::1/128\",\n \"fc00::/7\",\n \"fe80::/10\",\n ],\n defaultTimeoutMs: 15_000,\n httpUserAgent: \"agent-tool-core/1.0\",\n enableAutoWriteLargeResponses: false,\n allowedCommands: [\n \"cat\",\n \"echo\",\n \"env\",\n \"find\",\n \"grep\",\n \"head\",\n \"ls\",\n \"pwd\",\n \"tail\",\n \"wc\",\n \"whoami\",\n ],\n maxCommandOutputBytes: 1024 * 1024,\n commandTimeoutMs: 10_000,\n};\n\n/**\n * Context passed to each core tool handler.\n */\nexport interface CoreToolContext {\n execCtx: ExecContext;\n config: CoreToolsConfig;\n}\n\n/**\n * Structured result from a core tool handler.\n */\nexport interface CoreToolResult {\n result: unknown;\n evidence: Evidence[];\n}\n\n/**\n * A core tool handler function. Receives only args; context is injected via getBuiltinContext().\n * Uses `any` for args so handlers with specific arg types (e.g. { path: string }) are assignable.\n */\nexport type CoreToolHandler = (args: any) => Promise<CoreToolResult>;\n","import { readFile, stat } from \"node:fs/promises\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Read a UTF-8 text file from the sandbox.\n * @tool\n * @effect none\n */\nexport const readTextHandler = (async (args: {\n path: string;\n maxBytes?: number;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = args.path;\n const maxBytes = args.maxBytes ?? ctx.config.maxReadBytes;\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n\n const fileStat = await stat(resolvedPath);\n if (fileStat.size > maxBytes) {\n throw createTaggedError(\n \"FILE_TOO_LARGE\",\n `File size ${fileStat.size} bytes exceeds limit of ${maxBytes} bytes`,\n { path: resolvedPath, size: fileStat.size, limit: maxBytes },\n );\n }\n\n const text = await readFile(resolvedPath, \"utf-8\");\n\n return {\n result: {\n path: resolvedPath,\n text,\n bytes: fileStat.size,\n },\n evidence: [\n {\n type: \"file\",\n ref: resolvedPath,\n summary: `Read ${fileStat.size} bytes from ${resolvedPath}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { resolve, normalize, dirname, basename } from \"node:path\";\nimport { realpath, access } from \"node:fs/promises\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Resolve an input path to an absolute path within the sandbox.\n * Throws PATH_OUTSIDE_SANDBOX if the resolved path escapes the sandbox root.\n *\n * For existing files: uses realpath to resolve symlinks.\n * For non-existing files (write targets): resolves the parent directory.\n */\nexport async function resolveSandboxedPath(\n inputPath: string,\n sandboxRoot: string,\n): Promise<string> {\n // Resolve the sandbox root itself with realpath to handle platform symlinks\n // (e.g. macOS /var -> /private/var)\n let normalizedRoot: string;\n try {\n normalizedRoot = await realpath(resolve(sandboxRoot));\n } catch {\n normalizedRoot = normalize(resolve(sandboxRoot));\n }\n\n // Resolve against sandbox root\n const resolved = resolve(normalizedRoot, inputPath);\n\n let real: string;\n try {\n // Try to resolve symlinks for existing paths\n await access(resolved);\n real = await realpath(resolved);\n } catch {\n // Path does not exist — resolve parent to check containment\n const parentDir = dirname(resolved);\n let realParent: string;\n try {\n await access(parentDir);\n realParent = await realpath(parentDir);\n } catch {\n // Parent also doesn't exist — use normalized resolved path\n // (will fail at actual FS operation if truly invalid)\n realParent = normalize(parentDir);\n }\n real = resolve(realParent, basename(resolved));\n }\n\n if (!isWithinRoot(real, normalizedRoot)) {\n throw createTaggedError(\n \"PATH_OUTSIDE_SANDBOX\",\n `Path \"${inputPath}\" resolves to \"${real}\" which is outside sandbox \"${normalizedRoot}\"`,\n { inputPath, resolvedPath: real, sandboxRoot: normalizedRoot },\n );\n }\n\n return real;\n}\n\nfunction isWithinRoot(path: string, root: string): boolean {\n const normalizedPath = normalize(path);\n const normalizedRoot = normalize(root);\n return normalizedPath === normalizedRoot || normalizedPath.startsWith(normalizedRoot + \"/\");\n}\n","import { writeFile, mkdir } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { dirname } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\n/**\n * Write UTF-8 text to a file in the sandbox.\n * @tool\n * @effect local_write\n */\nexport const writeTextHandler = (async (args: {\n path: string;\n text: string;\n overwrite?: boolean;\n mkdirp?: boolean;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = args.path;\n const text = args.text;\n const overwrite = args.overwrite ?? false;\n const mkdirp = args.mkdirp ?? true;\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n\n // Check overwrite\n if (!overwrite) {\n const { access } = await import(\"node:fs/promises\");\n try {\n await access(resolvedPath);\n throw new Error(\n `File already exists: ${resolvedPath}. Set overwrite=true to allow overwriting.`,\n );\n } catch (err) {\n // File not found is expected — proceed\n if (err instanceof Error && !err.message.includes(\"already exists\")) {\n // access threw ENOENT — file doesn't exist, continue\n } else {\n throw err;\n }\n }\n }\n\n // Create parent directories if needed\n if (mkdirp) {\n await mkdir(dirname(resolvedPath), { recursive: true });\n }\n\n // Write file\n await writeFile(resolvedPath, text, \"utf-8\");\n\n const bytes = Buffer.byteLength(text, \"utf-8\");\n const sha256 = createHash(\"sha256\").update(text).digest(\"hex\");\n\n return {\n result: {\n path: resolvedPath,\n bytes,\n sha256,\n },\n evidence: [\n {\n type: \"file\",\n ref: resolvedPath,\n summary: `Wrote ${bytes} bytes to ${resolvedPath} (sha256: ${sha256.slice(0, 12)}...)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { readdir, stat } from \"node:fs/promises\";\nimport { resolve, join } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\ninterface DirEntry {\n name: string;\n type: \"file\" | \"directory\" | \"symlink\" | \"other\";\n size: number;\n mtime: string;\n}\n\n/**\n * List directory contents in the sandbox.\n * @tool\n * @effect none\n */\nexport const listDirHandler = (async (args: {\n path: string;\n maxEntries?: number;\n includeHidden?: boolean;\n recursive?: boolean;\n maxDepth?: number;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = args.path;\n const maxEntries = args.maxEntries ?? 2000;\n const includeHidden = args.includeHidden ?? false;\n const recursive = args.recursive ?? false;\n const maxDepth = args.maxDepth ?? 5;\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n\n const entries: DirEntry[] = [];\n let truncated = false;\n\n await walkDir(resolvedPath, \"\", entries, {\n maxEntries,\n includeHidden,\n recursive,\n maxDepth,\n currentDepth: 0,\n onTruncate: () => { truncated = true; },\n });\n\n return {\n result: {\n path: resolvedPath,\n entries,\n totalEntries: entries.length,\n truncated,\n },\n evidence: [\n {\n type: \"tool\",\n ref: `core/fs.listDir:${resolvedPath}`,\n summary: `Listed ${entries.length} entries in ${resolvedPath}${truncated ? \" (truncated)\" : \"\"}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n\ninterface WalkOptions {\n maxEntries: number;\n includeHidden: boolean;\n recursive: boolean;\n maxDepth: number;\n currentDepth: number;\n onTruncate: () => void;\n}\n\nasync function walkDir(\n basePath: string,\n relativePath: string,\n entries: DirEntry[],\n options: WalkOptions,\n): Promise<void> {\n if (entries.length >= options.maxEntries) {\n options.onTruncate();\n return;\n }\n\n const fullPath = relativePath ? resolve(basePath, relativePath) : basePath;\n const dirEntries = await readdir(fullPath, { withFileTypes: true });\n\n for (const dirent of dirEntries) {\n if (entries.length >= options.maxEntries) {\n options.onTruncate();\n return;\n }\n\n if (!options.includeHidden && dirent.name.startsWith(\".\")) {\n continue;\n }\n\n const entryPath = join(fullPath, dirent.name);\n const entryRelative = relativePath ? join(relativePath, dirent.name) : dirent.name;\n\n let entryType: DirEntry[\"type\"];\n if (dirent.isSymbolicLink()) {\n entryType = \"symlink\";\n } else if (dirent.isDirectory()) {\n entryType = \"directory\";\n } else if (dirent.isFile()) {\n entryType = \"file\";\n } else {\n entryType = \"other\";\n }\n\n let size = 0;\n let mtime = \"\";\n try {\n const entryStat = await stat(entryPath);\n size = entryStat.size;\n mtime = entryStat.mtime.toISOString();\n } catch {\n // Best effort stat\n }\n\n entries.push({\n name: entryRelative,\n type: entryType,\n size,\n mtime,\n });\n\n // Recurse into directories\n if (\n options.recursive &&\n entryType === \"directory\" &&\n options.currentDepth < options.maxDepth\n ) {\n await walkDir(basePath, entryRelative, entries, {\n ...options,\n currentDepth: options.currentDepth + 1,\n });\n }\n }\n}\n","import { readdir, stat } from \"node:fs/promises\";\nimport { createReadStream } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport { join, relative } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\ninterface SearchMatch {\n file: string;\n lineNo: number;\n excerpt: string;\n}\n\n/**\n * Search for text patterns in files within the sandbox.\n * @tool\n * @effect none\n */\nexport const searchTextHandler = (async (args: {\n root: string;\n query: string;\n glob?: string;\n maxMatches?: number;\n maxFiles?: number;\n}) => {\n const ctx = getBuiltinContext();\n const rootPath = args.root;\n const query = args.query;\n const glob = args.glob ?? \"**/*.{md,txt,log,json,ts,js,py,java,scala}\";\n const maxMatches = args.maxMatches ?? 100;\n const maxFiles = args.maxFiles ?? 500;\n\n const resolvedRoot = await resolveSandboxedPath(rootPath, ctx.config.sandboxRoot);\n\n // Build regex from query\n let regex: RegExp;\n try {\n regex = new RegExp(query, \"i\");\n } catch {\n // If not a valid regex, escape and use as literal\n regex = new RegExp(escapeRegExp(query), \"i\");\n }\n\n // Collect matching file extensions from glob\n const extensions = parseGlobExtensions(glob);\n\n // Walk directory and collect files\n const files: string[] = [];\n await collectFiles(resolvedRoot, files, { maxFiles, extensions });\n\n // Search through files\n const matches: SearchMatch[] = [];\n let filesScanned = 0;\n let truncated = false;\n\n for (const filePath of files) {\n if (matches.length >= maxMatches) {\n truncated = true;\n break;\n }\n filesScanned++;\n await searchFile(filePath, resolvedRoot, regex, matches, maxMatches);\n }\n\n if (matches.length >= maxMatches) {\n truncated = true;\n }\n\n return {\n result: {\n root: resolvedRoot,\n query,\n matches,\n totalMatches: matches.length,\n filesScanned,\n truncated,\n },\n evidence: [\n {\n type: \"tool\",\n ref: `core/fs.searchText:${resolvedRoot}`,\n summary: `Found ${matches.length} matches in ${filesScanned} files under ${resolvedRoot}${truncated ? \" (truncated)\" : \"\"}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n\nasync function collectFiles(\n dirPath: string,\n files: string[],\n options: { maxFiles: number; extensions: Set<string> },\n): Promise<void> {\n if (files.length >= options.maxFiles) return;\n\n let entries;\n try {\n entries = await readdir(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (files.length >= options.maxFiles) return;\n\n const fullPath = join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n await collectFiles(fullPath, files, options);\n } else if (entry.isFile()) {\n if (options.extensions.size > 0) {\n const ext = getExtension(entry.name);\n if (!ext || !options.extensions.has(ext)) continue;\n }\n files.push(fullPath);\n }\n }\n}\n\nasync function searchFile(\n filePath: string,\n root: string,\n regex: RegExp,\n matches: SearchMatch[],\n maxMatches: number,\n): Promise<void> {\n const fileStat = await stat(filePath).catch(() => null);\n // Skip large files (>1MB)\n if (!fileStat || fileStat.size > 1024 * 1024) return;\n\n const stream = createReadStream(filePath, { encoding: \"utf-8\" });\n const rl = createInterface({ input: stream, crlfDelay: Infinity });\n\n let lineNo = 0;\n for await (const line of rl) {\n lineNo++;\n if (matches.length >= maxMatches) {\n stream.destroy();\n break;\n }\n if (regex.test(line)) {\n matches.push({\n file: relative(root, filePath),\n lineNo,\n excerpt: line.slice(0, 200),\n });\n }\n }\n}\n\nfunction parseGlobExtensions(glob: string): Set<string> {\n const extensions = new Set<string>();\n // Match patterns like *.{ts,js,py} or *.ts\n const braceMatch = glob.match(/\\*\\.\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const ext of braceMatch[1]!.split(\",\")) {\n extensions.add(ext.trim());\n }\n } else {\n const simpleMatch = glob.match(/\\*\\.(\\w+)/);\n if (simpleMatch) {\n extensions.add(simpleMatch[1]!);\n }\n }\n return extensions;\n}\n\nfunction getExtension(filename: string): string | null {\n const dotIdx = filename.lastIndexOf(\".\");\n if (dotIdx === -1 || dotIdx === 0) return null;\n return filename.slice(dotIdx + 1);\n}\n\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { createReadStream } from \"node:fs\";\nimport { stat } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\n/**\n * Compute SHA-256 hash of a file in the sandbox.\n * @tool\n * @effect none\n */\nexport const sha256Handler = (async (args: { path: string }) => {\n const ctx = getBuiltinContext();\n const inputPath = args.path;\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n const fileStat = await stat(resolvedPath);\n\n const hash = await new Promise<string>((resolve, reject) => {\n const hasher = createHash(\"sha256\");\n const stream = createReadStream(resolvedPath);\n stream.on(\"data\", (chunk) => hasher.update(chunk));\n stream.on(\"end\", () => resolve(hasher.digest(\"hex\")));\n stream.on(\"error\", reject);\n });\n\n return {\n result: {\n sha256: hash,\n path: resolvedPath,\n bytes: fileStat.size,\n },\n evidence: [\n {\n type: \"file\",\n ref: resolvedPath,\n summary: `SHA-256 of ${resolvedPath} (${fileStat.size} bytes): ${hash.slice(0, 16)}...`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { rm, unlink, rmdir, stat } from \"node:fs/promises\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\n/**\n * Delete a file or directory in the sandbox (dangerous, requires explicit confirmation).\n * @tool\n * @effect destructive\n */\nexport const deletePathHandler = (async (args: {\n path: string;\n recursive?: boolean;\n confirm: boolean;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = args.path;\n const recursive = args.recursive ?? false;\n const confirm = args.confirm;\n\n if (!confirm) {\n throw new Error(\n \"Deletion not confirmed. Set confirm=true to proceed with deletion.\",\n );\n }\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n\n // Prevent deleting the sandbox root itself (compare resolved paths)\n let realSandboxRoot: string;\n try {\n const { realpath: rp } = await import(\"node:fs/promises\");\n realSandboxRoot = await rp(ctx.config.sandboxRoot);\n } catch {\n realSandboxRoot = ctx.config.sandboxRoot;\n }\n if (resolvedPath === realSandboxRoot) {\n throw new Error(\"Cannot delete the sandbox root directory.\");\n }\n\n const fileStat = await stat(resolvedPath);\n const isDirectory = fileStat.isDirectory();\n\n if (isDirectory) {\n if (recursive) {\n await rm(resolvedPath, { recursive: true, force: true });\n } else {\n await rmdir(resolvedPath);\n }\n } else {\n await unlink(resolvedPath);\n }\n\n return {\n result: {\n path: resolvedPath,\n deleted: true,\n type: isDirectory ? \"directory\" : \"file\",\n },\n evidence: [\n {\n type: \"file\",\n ref: resolvedPath,\n summary: `Deleted ${isDirectory ? \"directory\" : \"file\"}: ${resolvedPath}${recursive ? \" (recursive)\" : \"\"}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { lookup } from \"node:dns/promises\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Validate a URL against allowed hosts and blocked CIDRs.\n * Prevents SSRF by checking both hostname allowlist and resolved IP addresses.\n *\n * @throws HTTP_DISALLOWED_HOST if the URL is blocked\n */\nexport async function validateUrl(\n url: string,\n allowedHosts: string[],\n blockedCidrs: string[],\n): Promise<URL> {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Invalid URL: ${url}`,\n { url },\n );\n }\n\n // Only allow http/https\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,\n { url, protocol: parsed.protocol },\n );\n }\n\n const hostname = parsed.hostname;\n\n // Check allowlist\n if (!isHostAllowed(hostname, allowedHosts)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" is not in the allowed hosts list`,\n { url, hostname, allowedHosts },\n );\n }\n\n // DNS resolve and check against blocked CIDRs\n try {\n const { address } = await lookup(hostname);\n if (isIpInBlockedCidrs(address, blockedCidrs)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" resolves to blocked IP: ${address}`,\n { url, hostname, resolvedIp: address },\n );\n }\n } catch (err) {\n // Re-throw our tagged errors\n if (err instanceof Error && (err as any).kind === \"HTTP_DISALLOWED_HOST\") {\n throw err;\n }\n // DNS resolution failure — block by default\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `DNS resolution failed for host \"${hostname}\": ${err instanceof Error ? err.message : String(err)}`,\n { url, hostname },\n );\n }\n\n return parsed;\n}\n\n/**\n * Check if a hostname matches any entry in the allowed hosts list.\n * Supports wildcard prefix matching (e.g. \"*.github.com\" matches \"api.github.com\").\n */\nfunction isHostAllowed(hostname: string, allowedHosts: string[]): boolean {\n for (const pattern of allowedHosts) {\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(1); // \".github.com\"\n if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {\n return true;\n }\n } else if (hostname === pattern) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an IPv4 address falls within any blocked CIDR range.\n */\nexport function isIpInBlockedCidrs(ip: string, cidrs: string[]): boolean {\n // Handle IPv4-mapped IPv6\n const normalizedIp = normalizeIp(ip);\n if (!normalizedIp) return false;\n\n for (const cidr of cidrs) {\n if (cidr.includes(\":\")) {\n // IPv6 CIDR — skip for IPv4 addresses\n if (!ip.includes(\":\")) continue;\n if (isIpv6InCidr(ip, cidr)) return true;\n } else {\n if (isIpv4InCidr(normalizedIp, cidr)) return true;\n }\n }\n return false;\n}\n\nfunction normalizeIp(ip: string): string | null {\n // Handle IPv4-mapped IPv6 (e.g. \"::ffff:127.0.0.1\")\n if (ip.startsWith(\"::ffff:\")) {\n return ip.slice(7);\n }\n // Pure IPv4\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(ip)) {\n return ip;\n }\n return null;\n}\n\nfunction isIpv4InCidr(ip: string, cidr: string): boolean {\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;\n\n const ipNum = ipv4ToNum(ip);\n const cidrNum = ipv4ToNum(cidrIp);\n if (ipNum === null || cidrNum === null) return false;\n\n const mask = prefix === 0 ? 0 : (~0 << (32 - prefix)) >>> 0;\n return (ipNum & mask) === (cidrNum & mask);\n}\n\nfunction ipv4ToNum(ip: string): number | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n let num = 0;\n for (const part of parts) {\n const n = parseInt(part, 10);\n if (isNaN(n) || n < 0 || n > 255) return null;\n num = (num << 8) | n;\n }\n return num >>> 0;\n}\n\nfunction isIpv6InCidr(ip: string, cidr: string): boolean {\n // Simplified IPv6 CIDR matching for common cases (::1, fc00::, fe80::)\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix)) return false;\n\n const ipBytes = expandIpv6(ip);\n const cidrBytes = expandIpv6(cidrIp);\n if (!ipBytes || !cidrBytes) return false;\n\n // Compare prefix bits\n const fullBytes = Math.floor(prefix / 8);\n for (let i = 0; i < fullBytes && i < 16; i++) {\n if (ipBytes[i] !== cidrBytes[i]) return false;\n }\n\n const remainingBits = prefix % 8;\n if (remainingBits > 0 && fullBytes < 16) {\n const mask = (~0 << (8 - remainingBits)) & 0xff;\n if ((ipBytes[fullBytes]! & mask) !== (cidrBytes[fullBytes]! & mask)) return false;\n }\n\n return true;\n}\n\nfunction expandIpv6(ip: string): number[] | null {\n // Remove zone ID\n const zoneIdx = ip.indexOf(\"%\");\n if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);\n\n const parts = ip.split(\"::\");\n if (parts.length > 2) return null;\n\n const bytes: number[] = new Array(16).fill(0);\n\n const expandGroup = (group: string): number[] => {\n if (!group) return [];\n return group.split(\":\").flatMap((hex) => {\n const val = parseInt(hex || \"0\", 16);\n return [(val >> 8) & 0xff, val & 0xff];\n });\n };\n\n if (parts.length === 1) {\n const expanded = expandGroup(parts[0]!);\n if (expanded.length !== 16) return null;\n return expanded;\n }\n\n const left = expandGroup(parts[0]!);\n const right = expandGroup(parts[1]!);\n\n if (left.length + right.length > 16) return null;\n\n for (let i = 0; i < left.length; i++) bytes[i] = left[i]!;\n for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i]!;\n\n return bytes;\n}\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Fetch a URL and return the response as text.\n * @tool\n * @effect none\n */\nexport const fetchTextHandler = (async (args: {\n url: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n body?: string | null;\n timeoutMs?: number;\n maxBytes?: number;\n}) => {\n const ctx = getBuiltinContext();\n const url = args.url;\n const method = args.method ?? \"GET\";\n const headers = args.headers ?? {};\n const body = args.body ?? undefined;\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;\n\n // SSRF validation\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n if (!headers[\"User-Agent\"] && !headers[\"user-agent\"]) {\n headers[\"User-Agent\"] = ctx.config.httpUserAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body ?? undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Request to ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,\n { url, contentLength: parseInt(contentLength, 10), limit: maxBytes },\n );\n }\n\n const text = await readResponseWithLimit(response, maxBytes, url);\n const bytes = Buffer.byteLength(text, \"utf-8\");\n\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n return {\n result: {\n url,\n status: response.status,\n headers: responseHeaders,\n text,\n bytes,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `${method} ${url} → ${response.status} (${bytes} bytes)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n\nasync function readResponseWithLimit(\n response: Response,\n maxBytes: number,\n url: string,\n): Promise<string> {\n if (!response.body) {\n return response.text();\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const chunks: string[] = [];\n let totalBytes = 0;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n reader.cancel();\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response body exceeded limit of ${maxBytes} bytes while reading from ${url}`,\n { url, bytesRead: totalBytes, limit: maxBytes },\n );\n }\n\n chunks.push(decoder.decode(value, { stream: true }));\n }\n chunks.push(decoder.decode());\n } finally {\n reader.releaseLock();\n }\n\n return chunks.join(\"\");\n}\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Fetch a URL and return the response as parsed JSON.\n * @tool\n * @effect none\n */\nexport const fetchJsonHandler = (async (args: {\n url: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n body?: string | null;\n timeoutMs?: number;\n maxBytes?: number;\n}) => {\n const ctx = getBuiltinContext();\n const url = args.url;\n const method = args.method ?? \"GET\";\n const headers = args.headers ?? {};\n const body = args.body ?? undefined;\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;\n\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n if (!headers[\"Accept\"] && !headers[\"accept\"]) {\n headers[\"Accept\"] = \"application/json\";\n }\n if (!headers[\"User-Agent\"] && !headers[\"user-agent\"]) {\n headers[\"User-Agent\"] = ctx.config.httpUserAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body ?? undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Request to ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,\n { url, contentLength: parseInt(contentLength, 10), limit: maxBytes },\n );\n }\n\n const text = await response.text();\n const bytes = Buffer.byteLength(text, \"utf-8\");\n\n if (bytes > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response body ${bytes} bytes exceeds limit of ${maxBytes} bytes`,\n { url, bytes, limit: maxBytes },\n );\n }\n\n let json: unknown;\n try {\n json = JSON.parse(text);\n } catch {\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Failed to parse JSON response from ${url}: ${text.slice(0, 200)}`,\n { url, status: response.status, textPreview: text.slice(0, 500) },\n );\n }\n\n return {\n result: {\n url,\n status: response.status,\n json,\n bytes,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `${method} ${url} → ${response.status} JSON (${bytes} bytes)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { writeFile, mkdir } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { dirname } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Download a file from a URL to the sandbox.\n * @tool\n * @effect local_write\n */\nexport const downloadFileHandler = (async (args: {\n url: string;\n destPath: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n maxBytes?: number;\n overwrite?: boolean;\n}) => {\n const ctx = getBuiltinContext();\n const url = args.url;\n const destPath = args.destPath;\n const headers = args.headers ?? {};\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = args.maxBytes ?? ctx.config.maxDownloadBytes;\n const overwrite = args.overwrite ?? false;\n\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n const resolvedDest = await resolveSandboxedPath(destPath, ctx.config.sandboxRoot);\n\n if (!overwrite) {\n const { access } = await import(\"node:fs/promises\");\n try {\n await access(resolvedDest);\n throw new Error(\n `File already exists: ${resolvedDest}. Set overwrite=true to allow overwriting.`,\n );\n } catch (err) {\n if (err instanceof Error && !err.message.includes(\"already exists\")) {\n // ENOENT — file doesn't exist, proceed\n } else {\n throw err;\n }\n }\n }\n\n if (!headers[\"User-Agent\"] && !headers[\"user-agent\"]) {\n headers[\"User-Agent\"] = ctx.config.httpUserAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Download from ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Download failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Download Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,\n { url, contentLength: parseInt(contentLength, 10), limit: maxBytes },\n );\n }\n\n if (!response.body) {\n throw createTaggedError(\"UPSTREAM_ERROR\", `No response body from ${url}`, { url });\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalBytes = 0;\n const hasher = createHash(\"sha256\");\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n reader.cancel();\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Download from ${url} exceeded limit of ${maxBytes} bytes (received ${totalBytes})`,\n { url, bytesRead: totalBytes, limit: maxBytes },\n );\n }\n\n chunks.push(value);\n hasher.update(value);\n }\n } finally {\n reader.releaseLock();\n }\n\n const sha256 = hasher.digest(\"hex\");\n\n await mkdir(dirname(resolvedDest), { recursive: true });\n const buffer = Buffer.concat(chunks);\n await writeFile(resolvedDest, buffer);\n\n return {\n result: {\n destPath: resolvedDest,\n bytes: totalBytes,\n sha256,\n status: response.status,\n url,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `Downloaded ${totalBytes} bytes from ${url}`,\n createdAt: new Date().toISOString(),\n },\n {\n type: \"file\",\n ref: resolvedDest,\n summary: `Saved to ${resolvedDest} (sha256: ${sha256.slice(0, 12)}...)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Send a HEAD request to get response headers without body.\n * @tool\n * @effect none\n */\nexport const headHandler = (async (args: {\n url: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n}) => {\n const ctx = getBuiltinContext();\n const url = args.url;\n const headers = args.headers ?? {};\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n\n // SSRF validation\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n if (!headers[\"User-Agent\"] && !headers[\"user-agent\"]) {\n headers[\"User-Agent\"] = ctx.config.httpUserAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"HEAD\",\n headers,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `HEAD request to ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `HEAD request failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n return {\n result: {\n url,\n status: response.status,\n headers: responseHeaders,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `HEAD ${url} → ${response.status}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\nconst DUCKDUCKGO_API = \"https://api.duckduckgo.com/\";\n\ninterface DuckDuckGoResult {\n FirstURL?: string;\n Text?: string;\n}\n\ninterface DuckDuckGoRelatedTopic {\n Text?: string;\n FirstURL?: string;\n Result?: string;\n Icon?: { URL?: string };\n}\n\ninterface DuckDuckGoResponse {\n Abstract?: string;\n AbstractText?: string;\n AbstractURL?: string;\n AbstractSource?: string;\n RelatedTopics?: DuckDuckGoRelatedTopic[];\n Results?: DuckDuckGoResult[];\n Heading?: string;\n}\n\n/**\n * Search DuckDuckGo via the Instant Answer API (no API key).\n * Requires api.duckduckgo.com in allowedHosts.\n * @tool\n * @effect none\n */\nexport const duckduckgoSearchHandler = (async (args: {\n query: string;\n maxResults?: number;\n timeoutMs?: number;\n}) => {\n const ctx = getBuiltinContext();\n const query = args.query?.trim();\n if (!query) {\n throw createTaggedError(\"DUCKDUCKGO_INVALID\", \"query is required\", {});\n }\n\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxResults = args.maxResults ?? 10;\n\n const url = `${DUCKDUCKGO_API}?q=${encodeURIComponent(query)}&format=json`;\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers: { \"User-Agent\": ctx.config.httpUserAgent },\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `DuckDuckGo search timed out after ${timeoutMs}ms`,\n { query, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `DuckDuckGo search failed: ${err instanceof Error ? err.message : String(err)}`,\n { query },\n );\n }\n clearTimeout(timer);\n\n const maxBytes = ctx.config.maxHttpBytes;\n const text = await response.text();\n const bytes = Buffer.byteLength(text, \"utf-8\");\n if (bytes > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `DuckDuckGo response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,\n { query, bytes, limit: maxBytes },\n );\n }\n\n let raw: DuckDuckGoResponse;\n try {\n raw = JSON.parse(text) as DuckDuckGoResponse;\n } catch {\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `DuckDuckGo returned invalid JSON`,\n { query, textPreview: text.slice(0, 200) },\n );\n }\n\n const results: Array<{ url: string; title: string; snippet?: string }> = [];\n if (Array.isArray(raw.Results)) {\n for (const r of raw.Results.slice(0, maxResults)) {\n if (r.FirstURL) {\n results.push({\n url: r.FirstURL,\n title: r.Text ?? r.FirstURL,\n snippet: r.Text,\n });\n }\n }\n }\n\n const relatedTopics: Array<{ text: string; url?: string }> = [];\n if (Array.isArray(raw.RelatedTopics)) {\n for (const t of raw.RelatedTopics.slice(0, maxResults)) {\n const text = t.Text ?? t.Result;\n if (text) {\n relatedTopics.push({ text, url: t.FirstURL });\n }\n }\n }\n\n const result = {\n query,\n abstract: raw.Abstract ?? raw.AbstractText ?? undefined,\n abstractUrl: raw.AbstractURL ?? undefined,\n abstractSource: raw.AbstractSource ?? undefined,\n heading: raw.Heading ?? undefined,\n results,\n relatedTopics,\n };\n\n return {\n result,\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `DuckDuckGo search: \"${query}\" → ${results.length} results`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { parse } from \"node-html-parser\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/** Selectors tried in order for main content (HTML5 / common patterns). */\nconst MAIN_SELECTORS = [\n \"main\",\n \"article\",\n \"[role='main']\",\n \"#content\",\n \"#main\",\n \".content\",\n \".main-content\",\n \".article-body\",\n \".post-content\",\n \".entry-content\",\n];\n\n/**\n * Extract main content text from HTML: prefer main/article/role=main, else body with nav/header/footer removed.\n */\nfunction extractMainContent(html: string): { title: string; mainContent: string } {\n const root = parse(html, { comment: false });\n let title = \"\";\n const titleEl = root.querySelector(\"title\");\n if (titleEl) {\n title = (titleEl.textContent ?? \"\").trim().replace(/\\s+/g, \" \");\n }\n\n let mainEl: ReturnType<typeof root.querySelector> = null;\n for (const sel of MAIN_SELECTORS) {\n mainEl = root.querySelector(sel);\n if (mainEl) break;\n }\n\n if (!mainEl) {\n const body = root.querySelector(\"body\");\n if (body) {\n // Remove boilerplate and get text\n for (const tag of [\"script\", \"style\", \"nav\", \"header\", \"footer\", \"aside\", \"noscript\", \"iframe\"]) {\n body.querySelectorAll(tag).forEach((el) => el.remove());\n }\n mainEl = body;\n } else {\n mainEl = root;\n }\n }\n\n const text = (mainEl.textContent ?? \"\").trim().replace(/\\s+/g, \" \");\n return { title, mainContent: text };\n}\n\n/**\n * Fetch a URL and return only the main content (main/article/body text), not full HTML.\n * For HTML responses, extracts main content; for non-HTML, returns raw text.\n * @tool\n * @effect none\n */\nexport const fetchPageMainContentHandler = (async (args: {\n url: string;\n timeoutMs?: number;\n maxBytes?: number;\n}) => {\n const ctx = getBuiltinContext();\n const url = args.url;\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;\n\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers: { \"User-Agent\": ctx.config.httpUserAgent },\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Request to ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n }\n clearTimeout(timer);\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,\n { url, contentLength: parseInt(contentLength, 10), limit: maxBytes },\n );\n }\n\n const rawText = await response.text();\n const rawBytes = Buffer.byteLength(rawText, \"utf-8\");\n if (rawBytes > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response body ${rawBytes} bytes exceeds limit of ${maxBytes} bytes`,\n { url, bytes: rawBytes, limit: maxBytes },\n );\n }\n\n const contentType = (response.headers.get(\"content-type\") ?? \"\").toLowerCase();\n const isHtml = contentType.includes(\"text/html\");\n\n let title: string | undefined;\n let mainContent: string;\n\n if (isHtml && rawText.trim().length > 0) {\n try {\n const extracted = extractMainContent(rawText);\n title = extracted.title || undefined;\n mainContent = extracted.mainContent;\n } catch {\n mainContent = rawText;\n }\n } else {\n mainContent = rawText;\n }\n\n const bytes = Buffer.byteLength(mainContent, \"utf-8\");\n\n return {\n result: {\n url,\n status: response.status,\n title,\n mainContent,\n bytes,\n isHtml,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `${url} → ${response.status} main content (${bytes} bytes)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Select fields from JSON data using JMESPath expressions.\n * @tool\n * @effect none\n */\nexport const jsonSelectHandler = (async (args: {\n json: unknown;\n path: string;\n}) => {\n const json = args.json;\n const path = args.path;\n\n let jmespath: { search: (data: unknown, expression: string) => unknown };\n try {\n jmespath = await import(\"jmespath\");\n } catch {\n throw new Error(\n \"jmespath package is required for core/util.json.select. Install it with: npm install jmespath\",\n );\n }\n\n let value: unknown;\n try {\n value = jmespath.search(json, path);\n } catch (err) {\n throw new Error(\n `JMESPath expression error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return {\n result: { value },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.json.select\",\n summary: `Selected \"${path}\" from JSON → ${typeof value === \"object\" ? JSON.stringify(value).slice(0, 100) : String(value).slice(0, 100)}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Truncate text to a maximum character length with a suffix marker.\n * @tool\n * @effect none\n */\nexport const truncateHandler = (async (args: {\n text: string;\n maxChars: number;\n suffix?: string;\n}) => {\n const text = args.text;\n const maxChars = args.maxChars;\n const suffix = args.suffix ?? \"...\";\n\n const originalLength = text.length;\n\n if (text.length <= maxChars) {\n return {\n result: { text, truncated: false, originalLength },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.text.truncate\",\n summary: `Text not truncated (${originalLength} chars <= ${maxChars} max)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n }\n\n const truncatedText = text.slice(0, maxChars - suffix.length) + suffix;\n\n return {\n result: { text: truncatedText, truncated: true, originalLength },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.text.truncate\",\n summary: `Truncated ${originalLength} chars to ${truncatedText.length} chars`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { createHash } from \"node:crypto\";\nimport type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Compute SHA-256 hash of a text string.\n * @tool\n * @effect none\n */\nexport const hashTextHandler = (async (args: { text: string }) => {\n const text = args.text;\n const sha256 = createHash(\"sha256\").update(text, \"utf-8\").digest(\"hex\");\n\n return {\n result: { sha256 },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.hash.sha256Text\",\n summary: `SHA-256 of ${text.length} chars: ${sha256.slice(0, 16)}...`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Get the current time in various formats.\n * @tool\n * @effect none\n */\nexport const nowHandler = (async (args: { timezone?: string }) => {\n const timezone = args.timezone ?? \"UTC\";\n const now = new Date();\n\n let formatted: string;\n try {\n formatted = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n timeZoneName: \"short\",\n }).format(now);\n } catch {\n formatted = now.toISOString();\n }\n\n return {\n result: {\n iso: now.toISOString(),\n epochMs: now.getTime(),\n timezone,\n formatted,\n },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.time.now\",\n summary: `Current time: ${now.toISOString()} (${timezone})`,\n createdAt: now.toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Render a Mustache template with data.\n * @tool\n * @effect none\n */\nexport const templateRenderHandler = (async (args: {\n template: string;\n data: Record<string, unknown>;\n}) => {\n const template = args.template;\n const data = args.data;\n\n let renderFn: (template: string, view: unknown) => string;\n try {\n const mod = await import(\"mustache\");\n const mustache = mod.default ?? mod;\n renderFn = mustache.render.bind(mustache);\n } catch {\n throw new Error(\n \"mustache package is required for core/util.template.render. Install it with: npm install mustache\",\n );\n }\n\n let text: string;\n try {\n text = renderFn(template, data);\n } catch (err) {\n throw new Error(\n `Template rendering error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return {\n result: { text },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.template.render\",\n summary: `Rendered template (${template.length} chars) → ${text.length} chars output`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { spawn } from \"node:child_process\";\nimport { resolve as pathResolve } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Run a Linux command in the sandbox with an allowlist and timeout.\n * Uses spawn (no shell) to avoid injection; command and args are separate.\n * @tool\n * @effect local_write\n */\nexport const runCommandHandler = (async (args: {\n command: string;\n args?: string[];\n cwd?: string;\n timeoutMs?: number;\n}) => {\n const ctx = getBuiltinContext();\n const { allowedCommands, maxCommandOutputBytes, commandTimeoutMs } = ctx.config;\n\n if (!allowedCommands.length) {\n throw createTaggedError(\n \"EXEC_DISABLED\",\n \"Exec is disabled: allowedCommands is empty\",\n {},\n );\n }\n\n const rawCommand = args.command?.trim();\n if (!rawCommand) {\n throw createTaggedError(\"EXEC_INVALID\", \"command is required\", {});\n }\n\n // Only allow bare command name (no path, no shell metacharacters)\n const baseName = rawCommand.replace(/^.*\\//, \"\").trim();\n if (baseName !== rawCommand || /[;&|$`\\s]/.test(rawCommand)) {\n throw createTaggedError(\n \"EXEC_INVALID\",\n \"command must be a single executable name (no path, no shell chars)\",\n { command: rawCommand },\n );\n }\n\n if (!allowedCommands.includes(baseName)) {\n throw createTaggedError(\n \"EXEC_NOT_ALLOWED\",\n `Command \"${baseName}\" is not in allowedCommands`,\n { command: baseName, allowed: allowedCommands },\n );\n }\n\n const cmdArgs: string[] = Array.isArray(args.args) ? args.args : [];\n const timeoutMs = args.timeoutMs ?? commandTimeoutMs;\n let cwd: string = pathResolve(ctx.config.sandboxRoot);\n\n if (args.cwd != null && args.cwd !== \"\") {\n cwd = await resolveSandboxedPath(args.cwd, ctx.config.sandboxRoot);\n }\n\n return new Promise<{ result: unknown; evidence: unknown[] }>((resolvePromise, rejectPromise) => {\n const proc = spawn(baseName, cmdArgs, {\n cwd,\n shell: false,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env },\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let totalBytes = 0;\n\n const append = (chunk: string, dest: \"stdout\" | \"stderr\") => {\n const len = Buffer.byteLength(chunk, \"utf-8\");\n if (totalBytes + len > maxCommandOutputBytes) {\n proc.kill(\"SIGKILL\");\n rejectPromise(\n createTaggedError(\n \"EXEC_OUTPUT_TOO_LARGE\",\n `Command output exceeded ${maxCommandOutputBytes} bytes`,\n { maxBytes: maxCommandOutputBytes },\n ),\n );\n return;\n }\n totalBytes += len;\n if (dest === \"stdout\") stdout += chunk;\n else stderr += chunk;\n };\n\n proc.stdout?.setEncoding(\"utf-8\");\n proc.stderr?.setEncoding(\"utf-8\");\n proc.stdout?.on(\"data\", (chunk: string) => append(chunk, \"stdout\"));\n proc.stderr?.on(\"data\", (chunk: string) => append(chunk, \"stderr\"));\n\n const timeout = setTimeout(() => {\n proc.kill(\"SIGKILL\");\n resolvePromise({\n result: {\n stdout,\n stderr,\n exitCode: null,\n timedOut: true,\n signal: \"SIGKILL\",\n },\n evidence: [\n {\n type: \"exec\",\n summary: `Command \"${baseName}\" timed out after ${timeoutMs}ms`,\n createdAt: new Date().toISOString(),\n },\n ],\n });\n }, timeoutMs);\n\n proc.on(\"error\", (err) => {\n clearTimeout(timeout);\n rejectPromise(\n createTaggedError(\"EXEC_SPAWN_ERROR\", err.message, { command: baseName }),\n );\n });\n\n proc.on(\"close\", (code, signal) => {\n clearTimeout(timeout);\n resolvePromise({\n result: {\n stdout,\n stderr,\n exitCode: code,\n timedOut: false,\n signal: signal ?? undefined,\n },\n evidence: [\n {\n type: \"exec\",\n ref: baseName,\n summary: `Ran ${baseName} (exit ${code ?? signal})`,\n createdAt: new Date().toISOString(),\n },\n ],\n });\n });\n });\n}) as CoreToolHandler;\n"],"mappings":"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","names":["createTaggedError","dirname","access","dirname","stat","resolve","resolve","stat","readdir","stat","join","readdir","join","stat","createReadStream","stat","createHash","stat","resolve","createHash","createReadStream","stat","stat","createTaggedError","createTaggedError","createTaggedError","writeFile","mkdir","createHash","dirname","createTaggedError","access","createHash","mkdir","dirname","writeFile","createTaggedError","createTaggedError","text","createTaggedError","createHash","createTaggedError"]}
1
+ {"version":3,"sources":["../context.ts","../CoreAdapter.ts","../CoreToolsModule.ts","../types.ts","../fs/readText.ts","../security/sandbox.ts","../fs/writeText.ts","../fs/listDir.ts","../fs/searchText.ts","../fs/sha256.ts","../fs/deletePath.ts","../security/ssrf.ts","../http/fetchText.ts","../http/fetchJson.ts","../http/downloadFile.ts","../http/head.ts","../http/duckduckgoSearch.ts","../http/fetchPageMainContent.ts","../http/yahooFinance.ts","../util/jsonSelect.ts","../util/truncate.ts","../util/hashText.ts","../util/now.ts","../util/templateRender.ts","../exec/runCommand.ts"],"sourcesContent":["/**\n * Run context for builtin-tools: config + execCtx injected by the adapter before each invoke.\n * Handlers use getBuiltinContext() so they stay @tool-signature (args only) for scan.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { CoreToolContext } from \"./types.js\";\n\nconst storage = new AsyncLocalStorage<CoreToolContext>();\n\nexport function setBuiltinContext(ctx: CoreToolContext): void {\n storage.enterWith(ctx);\n}\n\nexport function getBuiltinContext(): CoreToolContext {\n const ctx = storage.getStore();\n if (!ctx) throw new Error(\"Builtin context not set; invoke only through CoreAdapter.\");\n return ctx;\n}\n\nexport function runWithBuiltinContext<T>(ctx: CoreToolContext, fn: () => Promise<T>): Promise<T> {\n return storage.run(ctx, fn);\n}\n","import type { ToolAdapter, ToolSpec } from \"@easynet/agent-tool\";\nimport type { ExecContext } from \"@easynet/agent-tool\";\nimport type { CoreToolHandler, CoreToolContext, CoreToolsConfig } from \"./types.js\";\nimport { runWithBuiltinContext } from \"./context.js\";\n\n/**\n * Adapter for core tools (kind=\"core\").\n * Dispatches to registered handler functions by tool name.\n *\n * Core tools are local, atomic operations (filesystem, HTTP, utilities)\n * that enforce their own security constraints (sandbox, SSRF) in addition\n * to the PolicyEngine capability gating.\n */\nexport class CoreAdapter implements ToolAdapter {\n readonly kind = \"core\" as const;\n private readonly handlers = new Map<string, CoreToolHandler>();\n private readonly config: CoreToolsConfig;\n\n constructor(config: CoreToolsConfig) {\n this.config = config;\n }\n\n /**\n * Register a handler for a specific core tool name.\n */\n registerHandler(toolName: string, handler: CoreToolHandler): void {\n this.handlers.set(toolName, handler);\n }\n\n /**\n * Unregister a handler.\n */\n unregisterHandler(toolName: string): boolean {\n return this.handlers.delete(toolName);\n }\n\n /**\n * List registered core tool names.\n */\n getRegisteredTools(): string[] {\n return Array.from(this.handlers.keys());\n }\n\n /**\n * Invoke dispatches to the appropriate handler by spec.name.\n */\n async invoke(\n spec: ToolSpec,\n args: unknown,\n ctx: ExecContext,\n ): Promise<{ result: unknown; raw?: unknown }> {\n const handler = this.handlers.get(spec.name);\n if (!handler) {\n throw new Error(\n `Core tool handler not found: ${spec.name}. Available: [${this.getRegisteredTools().join(\", \")}]`,\n );\n }\n\n const coreCtx: CoreToolContext = {\n execCtx: ctx,\n config: this.config,\n };\n\n const output = await runWithBuiltinContext(coreCtx, () =>\n handler(args as Record<string, unknown>),\n );\n\n return {\n result: output.result,\n raw: { evidence: output.evidence },\n };\n }\n}\n","import { CoreAdapter } from \"./CoreAdapter.js\";\nimport { createToolSpec, type CreateToolSpecOptions } from \"@easynet/agent-tool/core\";\nimport type { ToolRegistry } from \"@easynet/agent-tool\";\nimport type { CoreToolsConfig } from \"./types.js\";\nimport { DEFAULT_CORE_TOOLS_CONFIG } from \"./types.js\";\n\n// Handlers only (specs generated by framework from manifest)\nimport { readTextHandler } from \"./fs/readText.js\";\nimport { writeTextHandler } from \"./fs/writeText.js\";\nimport { listDirHandler } from \"./fs/listDir.js\";\nimport { searchTextHandler } from \"./fs/searchText.js\";\nimport { sha256Handler } from \"./fs/sha256.js\";\nimport { deletePathHandler } from \"./fs/deletePath.js\";\nimport { fetchTextHandler } from \"./http/fetchText.js\";\nimport { fetchJsonHandler } from \"./http/fetchJson.js\";\nimport { downloadFileHandler } from \"./http/downloadFile.js\";\nimport { headHandler } from \"./http/head.js\";\nimport { duckduckgoSearchHandler } from \"./http/duckduckgoSearch.js\";\nimport { fetchPageMainContentHandler } from \"./http/fetchPageMainContent.js\";\nimport { yahooFinanceQuoteHandler } from \"./http/yahooFinance.js\";\nimport { jsonSelectHandler } from \"./util/jsonSelect.js\";\nimport { truncateHandler } from \"./util/truncate.js\";\nimport { hashTextHandler } from \"./util/hashText.js\";\nimport { nowHandler } from \"./util/now.js\";\nimport { templateRenderHandler } from \"./util/templateRender.js\";\nimport { runCommandHandler } from \"./exec/runCommand.js\";\n\n/** Framework-generated spec options for all core tools (enables schema derivation from handler types). */\nconst CORE_TOOL_MANIFEST: CreateToolSpecOptions[] = [\n // Filesystem\n {\n name: \"core/fs.readText\",\n kind: \"core\",\n description:\n \"Read a UTF-8 text file from the sandbox. Input: path (or filePath), optional maxBytes.\",\n tags: [\"filesystem\", \"read\", \"core\"],\n capabilities: [\"read:fs\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/fs.writeText\",\n kind: \"core\",\n description:\n \"Write UTF-8 text to a file in the sandbox. Input: path (or filePath), text (or content), optional overwrite, mkdirp.\",\n tags: [\"filesystem\", \"write\", \"core\"],\n capabilities: [\"write:fs\"],\n sideEffect: \"local_write\",\n },\n {\n name: \"core/fs.listDir\",\n kind: \"core\",\n description:\n \"List directory contents in the sandbox. Input: path (or filePath, dir, directory), optional maxEntries, includeHidden, recursive, maxDepth.\",\n tags: [\"filesystem\", \"read\", \"core\"],\n capabilities: [\"read:fs\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/fs.searchText\",\n kind: \"core\",\n description:\n \"Search for text patterns in files within the sandbox. Input: root (or path, dir, directory), query (or q), optional glob, maxMatches, maxFiles.\",\n tags: [\"filesystem\", \"search\", \"core\"],\n capabilities: [\"read:fs\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/fs.sha256\",\n kind: \"core\",\n description:\n \"Compute SHA-256 hash of a file in the sandbox. Input: path (or filePath).\",\n tags: [\"filesystem\", \"hash\", \"core\"],\n capabilities: [\"read:fs\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/fs.deletePath\",\n kind: \"core\",\n description:\n \"Delete a file or directory in the sandbox (dangerous, requires explicit confirmation). Input: path (or filePath), confirm=true, optional recursive.\",\n tags: [\"filesystem\", \"delete\", \"dangerous\", \"core\"],\n capabilities: [\"danger:destructive\", \"write:fs\"],\n sideEffect: \"destructive\",\n },\n // HTTP\n {\n name: \"core/http.fetchText\",\n kind: \"core\",\n description:\n \"Fetch a URL and return the response as text. Input: url (or uri), optional method, headers, body, timeoutMs, maxBytes.\",\n tags: [\"http\", \"network\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.fetchJson\",\n kind: \"core\",\n description:\n \"Fetch a URL and return the response as parsed JSON. Input: url (or uri), optional method, headers, body, timeoutMs, maxBytes.\",\n tags: [\"http\", \"network\", \"json\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.downloadFile\",\n kind: \"core\",\n description:\n \"Download a file from a URL to the sandbox. Input: url (or uri), destPath (or destination, filePath), optional headers, timeoutMs, maxBytes, overwrite.\",\n tags: [\"http\", \"network\", \"download\", \"core\"],\n capabilities: [\"network\", \"write:fs\"],\n sideEffect: \"local_write\",\n },\n {\n name: \"core/http.head\",\n kind: \"core\",\n description:\n \"Send a HEAD request to get response headers without body. Input: url (or uri), optional headers, timeoutMs.\",\n tags: [\"http\", \"network\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.duckduckgoSearch\",\n kind: \"core\",\n description:\n \"Search DuckDuckGo via Instant Answer API (no API key). Add api.duckduckgo.com to allowedHosts. Input: use 'query' (or 'q') for the search string, optional 'maxResults'.\",\n tags: [\"http\", \"search\", \"duckduckgo\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.fetchPageMainContent\",\n kind: \"core\",\n description:\n \"Fetch a URL and return only the main content (main/article/body text). Strips nav, header, footer, scripts. Input: url (or uri), optional timeoutMs, maxBytes.\",\n tags: [\"http\", \"network\", \"html\", \"main-content\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n {\n name: \"core/http.yahooFinanceQuote\",\n kind: \"core\",\n description:\n \"Fetch stock quote(s) from Yahoo Finance chart API (no API key). Add query1.finance.yahoo.com to allowedHosts. Input: symbols (or symbol, tickers), optional range, timeoutMs.\",\n tags: [\"http\", \"finance\", \"yahoo\", \"stock\", \"quote\", \"core\"],\n capabilities: [\"network\"],\n sideEffect: \"none\",\n },\n // Utils\n {\n name: \"core/util.json.select\",\n kind: \"core\",\n description:\n \"Select fields from JSON data using JMESPath expressions. Input: json, path (or expression).\",\n tags: [\"util\", \"json\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n {\n name: \"core/util.text.truncate\",\n kind: \"core\",\n description: \"Truncate text to a maximum character length with a suffix marker\",\n tags: [\"util\", \"text\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n {\n name: \"core/util.hash.sha256Text\",\n kind: \"core\",\n description: \"Compute SHA-256 hash of a text string\",\n tags: [\"util\", \"hash\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n {\n name: \"core/util.time.now\",\n kind: \"core\",\n description: \"Get the current time in various formats\",\n tags: [\"util\", \"time\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n {\n name: \"core/util.template.render\",\n kind: \"core\",\n description: \"Render a Mustache template with data\",\n tags: [\"util\", \"template\", \"core\"],\n capabilities: [],\n sideEffect: \"none\",\n },\n // Exec\n {\n name: \"core/exec.runCommand\",\n kind: \"core\",\n description:\n \"Run a Linux command in the sandbox (allowlist, timeout, no shell). Input: command (or cmd), optional args (or arguments), cwd, timeoutMs.\",\n tags: [\"exec\", \"shell\", \"linux\", \"core\"],\n capabilities: [\"exec\"],\n sideEffect: \"local_write\",\n },\n];\n\nconst CORE_TOOL_HANDLERS = [\n readTextHandler,\n writeTextHandler,\n listDirHandler,\n searchTextHandler,\n sha256Handler,\n deletePathHandler,\n fetchTextHandler,\n fetchJsonHandler,\n downloadFileHandler,\n headHandler,\n duckduckgoSearchHandler,\n fetchPageMainContentHandler,\n yahooFinanceQuoteHandler,\n jsonSelectHandler,\n truncateHandler,\n hashTextHandler,\n nowHandler,\n templateRenderHandler,\n runCommandHandler,\n] as const;\n\n/** Specs generated from manifest (for re-export / backward compatibility). */\nexport const readTextSpec = createToolSpec(CORE_TOOL_MANIFEST[0]!);\nexport const writeTextSpec = createToolSpec(CORE_TOOL_MANIFEST[1]!);\nexport const listDirSpec = createToolSpec(CORE_TOOL_MANIFEST[2]!);\nexport const searchTextSpec = createToolSpec(CORE_TOOL_MANIFEST[3]!);\nexport const sha256Spec = createToolSpec(CORE_TOOL_MANIFEST[4]!);\nexport const deletePathSpec = createToolSpec(CORE_TOOL_MANIFEST[5]!);\nexport const fetchTextSpec = createToolSpec(CORE_TOOL_MANIFEST[6]!);\nexport const fetchJsonSpec = createToolSpec(CORE_TOOL_MANIFEST[7]!);\nexport const downloadFileSpec = createToolSpec(CORE_TOOL_MANIFEST[8]!);\nexport const headSpec = createToolSpec(CORE_TOOL_MANIFEST[9]!);\nexport const duckduckgoSearchSpec = createToolSpec(CORE_TOOL_MANIFEST[10]!);\nexport const fetchPageMainContentSpec = createToolSpec(CORE_TOOL_MANIFEST[11]!);\nexport const yahooFinanceQuoteSpec = createToolSpec(CORE_TOOL_MANIFEST[12]!);\nexport const jsonSelectSpec = createToolSpec(CORE_TOOL_MANIFEST[13]!);\nexport const truncateSpec = createToolSpec(CORE_TOOL_MANIFEST[14]!);\nexport const hashTextSpec = createToolSpec(CORE_TOOL_MANIFEST[15]!);\nexport const nowSpec = createToolSpec(CORE_TOOL_MANIFEST[16]!);\nexport const templateRenderSpec = createToolSpec(CORE_TOOL_MANIFEST[17]!);\nexport const runCommandSpec = createToolSpec(CORE_TOOL_MANIFEST[18]!);\n\n/**\n * User-provided config for registerCoreTools.\n * `sandboxRoot` and `allowedHosts` are required; the rest have defaults.\n */\nexport type CoreToolsUserConfig = Pick<CoreToolsConfig, \"sandboxRoot\" | \"allowedHosts\"> &\n Partial<Omit<CoreToolsConfig, \"sandboxRoot\" | \"allowedHosts\">>;\n\n/** Builtin tool groups: fs, http, util, exec (name prefix core/fs., core/http., core/util., core/exec.). */\nexport type CoreToolsGroup = \"fs\" | \"http\" | \"util\" | \"exec\";\n\nconst CORE_GROUP_PREFIX: Record<CoreToolsGroup, string> = {\n fs: \"core/fs.\",\n http: \"core/http.\",\n util: \"core/util.\",\n exec: \"core/exec.\",\n};\n\nexport interface RegisterCoreToolsOptions {\n /** Restrict to these groups (e.g. [\"fs\", \"http\"]). Ignored if only is set. */\n groups?: CoreToolsGroup[];\n /** Restrict to these tool names (e.g. [\"core/fs.readText\"]). Takes precedence over groups. */\n only?: string[];\n}\n\n/**\n * Register core tools with a ToolRegistry and return the configured CoreAdapter.\n * Optionally restrict to groups or exact tool names.\n *\n * Usage:\n * ```ts\n * const coreAdapter = registerCoreTools(registry, config);\n * const coreAdapterFsOnly = registerCoreTools(registry, config, { groups: [\"fs\"] });\n * const coreAdapterNamed = registerCoreTools(registry, config, { only: [\"core/fs.readText\"] });\n * ```\n */\nexport function registerCoreTools(\n registry: ToolRegistry,\n userConfig: CoreToolsUserConfig,\n options?: RegisterCoreToolsOptions,\n): CoreAdapter {\n const config: CoreToolsConfig = {\n ...DEFAULT_CORE_TOOLS_CONFIG,\n ...userConfig,\n };\n\n const adapter = new CoreAdapter(config);\n const onlySet =\n options?.only?.length ? new Set(options.only) : null;\n const allowedPrefixes =\n !onlySet && options?.groups?.length\n ? options.groups.map((g) => CORE_GROUP_PREFIX[g])\n : null;\n\n for (let i = 0; i < CORE_TOOL_MANIFEST.length; i++) {\n const spec = createToolSpec(CORE_TOOL_MANIFEST[i]!);\n if (onlySet && !onlySet.has(spec.name)) continue;\n if (allowedPrefixes && !allowedPrefixes.some((p) => spec.name.startsWith(p))) {\n continue;\n }\n const handler = CORE_TOOL_HANDLERS[i]!;\n registry.register(spec);\n adapter.registerHandler(spec.name, handler);\n }\n\n return adapter;\n}\n","import type { ExecContext } from \"@easynet/agent-tool\";\nimport type { Evidence } from \"@easynet/agent-tool\";\n\n/**\n * Configuration for core tools runtime.\n */\nexport interface CoreToolsConfig {\n /** Absolute path. All FS operations are confined within this root. */\n sandboxRoot: string;\n /** Only these hosts may be fetched. Supports wildcard prefix (e.g. \"*.github.com\"). */\n allowedHosts: string[];\n /** Maximum bytes for fs.readText (default: 5MB) */\n maxReadBytes: number;\n /** Maximum bytes for HTTP response body (default: 5MB) */\n maxHttpBytes: number;\n /** Maximum bytes for http.downloadFile (default: 100MB) */\n maxDownloadBytes: number;\n /** CIDR ranges to block. Defaults include RFC1918 + loopback + link-local. */\n blockedCidrs: string[];\n /** Default HTTP timeout in ms (default: 15000) */\n defaultTimeoutMs: number;\n /** User-Agent header for HTTP requests */\n httpUserAgent: string;\n /** If true, large HTTP responses are auto-written to sandbox and a file ref is returned */\n enableAutoWriteLargeResponses: boolean;\n /** Allowed command names for exec.runCommand (e.g. [\"ls\", \"cat\", \"grep\"]). Empty = disabled. */\n allowedCommands: string[];\n /** Max combined stdout+stderr bytes for exec (default: 1MB) */\n maxCommandOutputBytes: number;\n /** Default timeout for exec in ms (default: 10000) */\n commandTimeoutMs: number;\n}\n\n/**\n * Default configuration values for core tools.\n */\nexport const DEFAULT_CORE_TOOLS_CONFIG: Omit<CoreToolsConfig, \"sandboxRoot\" | \"allowedHosts\"> = {\n maxReadBytes: 5 * 1024 * 1024,\n maxHttpBytes: 5 * 1024 * 1024,\n maxDownloadBytes: 100 * 1024 * 1024,\n blockedCidrs: [\n \"127.0.0.0/8\",\n \"10.0.0.0/8\",\n \"172.16.0.0/12\",\n \"192.168.0.0/16\",\n \"169.254.0.0/16\",\n \"::1/128\",\n \"fc00::/7\",\n \"fe80::/10\",\n ],\n defaultTimeoutMs: 15_000,\n httpUserAgent: \"agent-tool-core/1.0\",\n enableAutoWriteLargeResponses: false,\n allowedCommands: [\n \"cat\",\n \"echo\",\n \"env\",\n \"find\",\n \"grep\",\n \"head\",\n \"ls\",\n \"pwd\",\n \"tail\",\n \"wc\",\n \"whoami\",\n ],\n maxCommandOutputBytes: 1024 * 1024,\n commandTimeoutMs: 10_000,\n};\n\n/**\n * Context passed to each core tool handler.\n */\nexport interface CoreToolContext {\n execCtx: ExecContext;\n config: CoreToolsConfig;\n}\n\n/**\n * Structured result from a core tool handler.\n */\nexport interface CoreToolResult {\n result: unknown;\n evidence: Evidence[];\n}\n\n/**\n * A core tool handler function. Receives only args; context is injected via getBuiltinContext().\n * Uses `any` for args so handlers with specific arg types (e.g. { path: string }) are assignable.\n */\nexport type CoreToolHandler = (args: any) => Promise<CoreToolResult>;\n","import { readFile, stat } from \"node:fs/promises\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Read a UTF-8 text file from the sandbox.\n * @tool\n * @effect none\n */\nexport const readTextHandler = (async (args: {\n path: string;\n /** Alias for path (accepted when agents send \"filePath\" instead of \"path\"). */\n filePath?: string;\n maxBytes?: number;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = (args.path ?? args.filePath)?.trim();\n if (!inputPath) {\n throw createTaggedError(\"FS_INVALID\", \"path is required (pass 'path' or 'filePath')\", {});\n }\n const maxBytes = args.maxBytes ?? ctx.config.maxReadBytes;\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n\n const fileStat = await stat(resolvedPath);\n if (fileStat.size > maxBytes) {\n throw createTaggedError(\n \"FILE_TOO_LARGE\",\n `File size ${fileStat.size} bytes exceeds limit of ${maxBytes} bytes`,\n { path: resolvedPath, size: fileStat.size, limit: maxBytes },\n );\n }\n\n const text = await readFile(resolvedPath, \"utf-8\");\n\n return {\n result: {\n path: resolvedPath,\n text,\n bytes: fileStat.size,\n },\n evidence: [\n {\n type: \"file\",\n ref: resolvedPath,\n summary: `Read ${fileStat.size} bytes from ${resolvedPath}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { resolve, normalize, dirname, basename } from \"node:path\";\nimport { realpath, access } from \"node:fs/promises\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Resolve an input path to an absolute path within the sandbox.\n * Throws PATH_OUTSIDE_SANDBOX if the resolved path escapes the sandbox root.\n *\n * For existing files: uses realpath to resolve symlinks.\n * For non-existing files (write targets): resolves the parent directory.\n */\nexport async function resolveSandboxedPath(\n inputPath: string,\n sandboxRoot: string,\n): Promise<string> {\n // Resolve the sandbox root itself with realpath to handle platform symlinks\n // (e.g. macOS /var -> /private/var)\n let normalizedRoot: string;\n try {\n normalizedRoot = await realpath(resolve(sandboxRoot));\n } catch {\n normalizedRoot = normalize(resolve(sandboxRoot));\n }\n\n // Resolve against sandbox root\n const resolved = resolve(normalizedRoot, inputPath);\n\n let real: string;\n try {\n // Try to resolve symlinks for existing paths\n await access(resolved);\n real = await realpath(resolved);\n } catch {\n // Path does not exist — resolve parent to check containment\n const parentDir = dirname(resolved);\n let realParent: string;\n try {\n await access(parentDir);\n realParent = await realpath(parentDir);\n } catch {\n // Parent also doesn't exist — use normalized resolved path\n // (will fail at actual FS operation if truly invalid)\n realParent = normalize(parentDir);\n }\n real = resolve(realParent, basename(resolved));\n }\n\n if (!isWithinRoot(real, normalizedRoot)) {\n throw createTaggedError(\n \"PATH_OUTSIDE_SANDBOX\",\n `Path \"${inputPath}\" resolves to \"${real}\" which is outside sandbox \"${normalizedRoot}\"`,\n { inputPath, resolvedPath: real, sandboxRoot: normalizedRoot },\n );\n }\n\n return real;\n}\n\nfunction isWithinRoot(path: string, root: string): boolean {\n const normalizedPath = normalize(path);\n const normalizedRoot = normalize(root);\n return normalizedPath === normalizedRoot || normalizedPath.startsWith(normalizedRoot + \"/\");\n}\n","import { writeFile, mkdir } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { dirname } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\n/**\n * Write UTF-8 text to a file in the sandbox.\n * @tool\n * @effect local_write\n */\nexport const writeTextHandler = (async (args: {\n path: string;\n /** Alias for path (accepted when agents send \"filePath\" instead of \"path\"). */\n filePath?: string;\n text: string;\n /** Alias for text (accepted when agents send \"content\" instead of \"text\"). */\n content?: string;\n overwrite?: boolean;\n mkdirp?: boolean;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = (args.path ?? args.filePath)?.trim();\n if (!inputPath) {\n throw new Error(\"path is required (pass 'path' or 'filePath')\");\n }\n const text = (args.text ?? args.content) ?? \"\";\n const overwrite = args.overwrite ?? false;\n const mkdirp = args.mkdirp ?? true;\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n\n // Check overwrite\n if (!overwrite) {\n const { access } = await import(\"node:fs/promises\");\n try {\n await access(resolvedPath);\n throw new Error(\n `File already exists: ${resolvedPath}. Set overwrite=true to allow overwriting.`,\n );\n } catch (err) {\n // File not found is expected — proceed\n if (err instanceof Error && !err.message.includes(\"already exists\")) {\n // access threw ENOENT — file doesn't exist, continue\n } else {\n throw err;\n }\n }\n }\n\n // Create parent directories if needed\n if (mkdirp) {\n await mkdir(dirname(resolvedPath), { recursive: true });\n }\n\n // Write file\n await writeFile(resolvedPath, text, \"utf-8\");\n\n const bytes = Buffer.byteLength(text, \"utf-8\");\n const sha256 = createHash(\"sha256\").update(text).digest(\"hex\");\n\n return {\n result: {\n path: resolvedPath,\n bytes,\n sha256,\n },\n evidence: [\n {\n type: \"file\",\n ref: resolvedPath,\n summary: `Wrote ${bytes} bytes to ${resolvedPath} (sha256: ${sha256.slice(0, 12)}...)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { readdir, stat } from \"node:fs/promises\";\nimport { resolve, join } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\ninterface DirEntry {\n name: string;\n type: \"file\" | \"directory\" | \"symlink\" | \"other\";\n size: number;\n mtime: string;\n}\n\n/**\n * List directory contents in the sandbox.\n * @tool\n * @effect none\n */\nexport const listDirHandler = (async (args: {\n path: string;\n /** Alias for path (accepted when agents send \"filePath\", \"dir\", or \"directory\"). */\n filePath?: string;\n dir?: string;\n directory?: string;\n maxEntries?: number;\n includeHidden?: boolean;\n recursive?: boolean;\n maxDepth?: number;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = (args.path ?? args.filePath ?? args.dir ?? args.directory)?.trim();\n if (!inputPath) {\n throw new Error(\"path is required (pass 'path', 'filePath', 'dir', or 'directory')\");\n }\n const maxEntries = args.maxEntries ?? 2000;\n const includeHidden = args.includeHidden ?? false;\n const recursive = args.recursive ?? false;\n const maxDepth = args.maxDepth ?? 5;\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n\n const entries: DirEntry[] = [];\n let truncated = false;\n\n await walkDir(resolvedPath, \"\", entries, {\n maxEntries,\n includeHidden,\n recursive,\n maxDepth,\n currentDepth: 0,\n onTruncate: () => { truncated = true; },\n });\n\n return {\n result: {\n path: resolvedPath,\n entries,\n totalEntries: entries.length,\n truncated,\n },\n evidence: [\n {\n type: \"tool\",\n ref: `core/fs.listDir:${resolvedPath}`,\n summary: `Listed ${entries.length} entries in ${resolvedPath}${truncated ? \" (truncated)\" : \"\"}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n\ninterface WalkOptions {\n maxEntries: number;\n includeHidden: boolean;\n recursive: boolean;\n maxDepth: number;\n currentDepth: number;\n onTruncate: () => void;\n}\n\nasync function walkDir(\n basePath: string,\n relativePath: string,\n entries: DirEntry[],\n options: WalkOptions,\n): Promise<void> {\n if (entries.length >= options.maxEntries) {\n options.onTruncate();\n return;\n }\n\n const fullPath = relativePath ? resolve(basePath, relativePath) : basePath;\n const dirEntries = await readdir(fullPath, { withFileTypes: true });\n\n for (const dirent of dirEntries) {\n if (entries.length >= options.maxEntries) {\n options.onTruncate();\n return;\n }\n\n if (!options.includeHidden && dirent.name.startsWith(\".\")) {\n continue;\n }\n\n const entryPath = join(fullPath, dirent.name);\n const entryRelative = relativePath ? join(relativePath, dirent.name) : dirent.name;\n\n let entryType: DirEntry[\"type\"];\n if (dirent.isSymbolicLink()) {\n entryType = \"symlink\";\n } else if (dirent.isDirectory()) {\n entryType = \"directory\";\n } else if (dirent.isFile()) {\n entryType = \"file\";\n } else {\n entryType = \"other\";\n }\n\n let size = 0;\n let mtime = \"\";\n try {\n const entryStat = await stat(entryPath);\n size = entryStat.size;\n mtime = entryStat.mtime.toISOString();\n } catch {\n // Best effort stat\n }\n\n entries.push({\n name: entryRelative,\n type: entryType,\n size,\n mtime,\n });\n\n // Recurse into directories\n if (\n options.recursive &&\n entryType === \"directory\" &&\n options.currentDepth < options.maxDepth\n ) {\n await walkDir(basePath, entryRelative, entries, {\n ...options,\n currentDepth: options.currentDepth + 1,\n });\n }\n }\n}\n","import { readdir, stat } from \"node:fs/promises\";\nimport { createReadStream } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport { join, relative } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\ninterface SearchMatch {\n file: string;\n lineNo: number;\n excerpt: string;\n}\n\n/**\n * Search for text patterns in files within the sandbox.\n * @tool\n * @effect none\n */\nexport const searchTextHandler = (async (args: {\n root: string;\n /** Aliases for root (path, dir, directory). */\n path?: string;\n dir?: string;\n directory?: string;\n query: string;\n /** Alias for query (accepted when agents send \"q\" instead of \"query\"). */\n q?: string;\n glob?: string;\n maxMatches?: number;\n maxFiles?: number;\n}) => {\n const ctx = getBuiltinContext();\n const rootPath = (args.root ?? args.path ?? args.dir ?? args.directory)?.trim();\n if (!rootPath) {\n throw new Error(\"root is required (pass 'root', 'path', 'dir', or 'directory')\");\n }\n const query = (args.query ?? args.q)?.trim();\n if (!query) {\n throw new Error(\"query is required (pass 'query' or 'q')\");\n }\n const glob = args.glob ?? \"**/*.{md,txt,log,json,ts,js,py,java,scala}\";\n const maxMatches = args.maxMatches ?? 100;\n const maxFiles = args.maxFiles ?? 500;\n\n const resolvedRoot = await resolveSandboxedPath(rootPath, ctx.config.sandboxRoot);\n\n // Build regex from query\n let regex: RegExp;\n try {\n regex = new RegExp(query, \"i\");\n } catch {\n // If not a valid regex, escape and use as literal\n regex = new RegExp(escapeRegExp(query), \"i\");\n }\n\n // Collect matching file extensions from glob\n const extensions = parseGlobExtensions(glob);\n\n // Walk directory and collect files\n const files: string[] = [];\n await collectFiles(resolvedRoot, files, { maxFiles, extensions });\n\n // Search through files\n const matches: SearchMatch[] = [];\n let filesScanned = 0;\n let truncated = false;\n\n for (const filePath of files) {\n if (matches.length >= maxMatches) {\n truncated = true;\n break;\n }\n filesScanned++;\n await searchFile(filePath, resolvedRoot, regex, matches, maxMatches);\n }\n\n if (matches.length >= maxMatches) {\n truncated = true;\n }\n\n return {\n result: {\n root: resolvedRoot,\n query,\n matches,\n totalMatches: matches.length,\n filesScanned,\n truncated,\n },\n evidence: [\n {\n type: \"tool\",\n ref: `core/fs.searchText:${resolvedRoot}`,\n summary: `Found ${matches.length} matches in ${filesScanned} files under ${resolvedRoot}${truncated ? \" (truncated)\" : \"\"}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n\nasync function collectFiles(\n dirPath: string,\n files: string[],\n options: { maxFiles: number; extensions: Set<string> },\n): Promise<void> {\n if (files.length >= options.maxFiles) return;\n\n let entries;\n try {\n entries = await readdir(dirPath, { withFileTypes: true });\n } catch {\n return;\n }\n\n for (const entry of entries) {\n if (files.length >= options.maxFiles) return;\n\n const fullPath = join(dirPath, entry.name);\n\n if (entry.isDirectory()) {\n if (entry.name.startsWith(\".\") || entry.name === \"node_modules\") continue;\n await collectFiles(fullPath, files, options);\n } else if (entry.isFile()) {\n if (options.extensions.size > 0) {\n const ext = getExtension(entry.name);\n if (!ext || !options.extensions.has(ext)) continue;\n }\n files.push(fullPath);\n }\n }\n}\n\nasync function searchFile(\n filePath: string,\n root: string,\n regex: RegExp,\n matches: SearchMatch[],\n maxMatches: number,\n): Promise<void> {\n const fileStat = await stat(filePath).catch(() => null);\n // Skip large files (>1MB)\n if (!fileStat || fileStat.size > 1024 * 1024) return;\n\n const stream = createReadStream(filePath, { encoding: \"utf-8\" });\n const rl = createInterface({ input: stream, crlfDelay: Infinity });\n\n let lineNo = 0;\n for await (const line of rl) {\n lineNo++;\n if (matches.length >= maxMatches) {\n stream.destroy();\n break;\n }\n if (regex.test(line)) {\n matches.push({\n file: relative(root, filePath),\n lineNo,\n excerpt: line.slice(0, 200),\n });\n }\n }\n}\n\nfunction parseGlobExtensions(glob: string): Set<string> {\n const extensions = new Set<string>();\n // Match patterns like *.{ts,js,py} or *.ts\n const braceMatch = glob.match(/\\*\\.\\{([^}]+)\\}/);\n if (braceMatch) {\n for (const ext of braceMatch[1]!.split(\",\")) {\n extensions.add(ext.trim());\n }\n } else {\n const simpleMatch = glob.match(/\\*\\.(\\w+)/);\n if (simpleMatch) {\n extensions.add(simpleMatch[1]!);\n }\n }\n return extensions;\n}\n\nfunction getExtension(filename: string): string | null {\n const dotIdx = filename.lastIndexOf(\".\");\n if (dotIdx === -1 || dotIdx === 0) return null;\n return filename.slice(dotIdx + 1);\n}\n\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n","import { createReadStream } from \"node:fs\";\nimport { stat } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Compute SHA-256 hash of a file in the sandbox.\n * @tool\n * @effect none\n */\nexport const sha256Handler = (async (args: {\n path: string;\n /** Alias for path (accepted when agents send \"filePath\" instead of \"path\"). */\n filePath?: string;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = (args.path ?? args.filePath)?.trim();\n if (!inputPath) {\n throw createTaggedError(\"FS_INVALID\", \"path is required (pass 'path' or 'filePath')\", {});\n }\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n const fileStat = await stat(resolvedPath);\n\n const hash = await new Promise<string>((resolve, reject) => {\n const hasher = createHash(\"sha256\");\n const stream = createReadStream(resolvedPath);\n stream.on(\"data\", (chunk) => hasher.update(chunk));\n stream.on(\"end\", () => resolve(hasher.digest(\"hex\")));\n stream.on(\"error\", reject);\n });\n\n return {\n result: {\n sha256: hash,\n path: resolvedPath,\n bytes: fileStat.size,\n },\n evidence: [\n {\n type: \"file\",\n ref: resolvedPath,\n summary: `SHA-256 of ${resolvedPath} (${fileStat.size} bytes): ${hash.slice(0, 16)}...`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { rm, unlink, rmdir, stat } from \"node:fs/promises\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\n\n/**\n * Delete a file or directory in the sandbox (dangerous, requires explicit confirmation).\n * @tool\n * @effect destructive\n */\nexport const deletePathHandler = (async (args: {\n path: string;\n /** Alias for path (accepted when agents send \"filePath\" instead of \"path\"). */\n filePath?: string;\n recursive?: boolean;\n confirm: boolean;\n}) => {\n const ctx = getBuiltinContext();\n const inputPath = (args.path ?? args.filePath)?.trim();\n if (!inputPath) {\n throw new Error(\"path is required (pass 'path' or 'filePath')\");\n }\n const recursive = args.recursive ?? false;\n const confirm = args.confirm;\n\n if (!confirm) {\n throw new Error(\n \"Deletion not confirmed. Set confirm=true to proceed with deletion.\",\n );\n }\n\n const resolvedPath = await resolveSandboxedPath(inputPath, ctx.config.sandboxRoot);\n\n // Prevent deleting the sandbox root itself (compare resolved paths)\n let realSandboxRoot: string;\n try {\n const { realpath: rp } = await import(\"node:fs/promises\");\n realSandboxRoot = await rp(ctx.config.sandboxRoot);\n } catch {\n realSandboxRoot = ctx.config.sandboxRoot;\n }\n if (resolvedPath === realSandboxRoot) {\n throw new Error(\"Cannot delete the sandbox root directory.\");\n }\n\n const fileStat = await stat(resolvedPath);\n const isDirectory = fileStat.isDirectory();\n\n if (isDirectory) {\n if (recursive) {\n await rm(resolvedPath, { recursive: true, force: true });\n } else {\n await rmdir(resolvedPath);\n }\n } else {\n await unlink(resolvedPath);\n }\n\n return {\n result: {\n path: resolvedPath,\n deleted: true,\n type: isDirectory ? \"directory\" : \"file\",\n },\n evidence: [\n {\n type: \"file\",\n ref: resolvedPath,\n summary: `Deleted ${isDirectory ? \"directory\" : \"file\"}: ${resolvedPath}${recursive ? \" (recursive)\" : \"\"}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { lookup } from \"node:dns/promises\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Validate a URL against allowed hosts and blocked CIDRs.\n * Prevents SSRF by checking both hostname allowlist and resolved IP addresses.\n *\n * @throws HTTP_DISALLOWED_HOST if the URL is blocked\n */\nexport async function validateUrl(\n url: string,\n allowedHosts: string[],\n blockedCidrs: string[],\n): Promise<URL> {\n let parsed: URL;\n try {\n parsed = new URL(url);\n } catch {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Invalid URL: ${url}`,\n { url },\n );\n }\n\n // Only allow http/https\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Protocol not allowed: ${parsed.protocol}. Only http: and https: are supported.`,\n { url, protocol: parsed.protocol },\n );\n }\n\n const hostname = parsed.hostname;\n\n // Check allowlist\n if (!isHostAllowed(hostname, allowedHosts)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" is not in the allowed hosts list`,\n { url, hostname, allowedHosts },\n );\n }\n\n // DNS resolve and check against blocked CIDRs\n try {\n const { address } = await lookup(hostname);\n if (isIpInBlockedCidrs(address, blockedCidrs)) {\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `Host \"${hostname}\" resolves to blocked IP: ${address}`,\n { url, hostname, resolvedIp: address },\n );\n }\n } catch (err) {\n // Re-throw our tagged errors\n if (err instanceof Error && (err as any).kind === \"HTTP_DISALLOWED_HOST\") {\n throw err;\n }\n // DNS resolution failure — block by default\n throw createTaggedError(\n \"HTTP_DISALLOWED_HOST\",\n `DNS resolution failed for host \"${hostname}\": ${err instanceof Error ? err.message : String(err)}`,\n { url, hostname },\n );\n }\n\n return parsed;\n}\n\n/**\n * Check if a hostname matches any entry in the allowed hosts list.\n * Supports wildcard prefix matching (e.g. \"*.github.com\" matches \"api.github.com\").\n */\nfunction isHostAllowed(hostname: string, allowedHosts: string[]): boolean {\n for (const pattern of allowedHosts) {\n if (pattern.startsWith(\"*.\")) {\n const suffix = pattern.slice(1); // \".github.com\"\n if (hostname.endsWith(suffix) || hostname === pattern.slice(2)) {\n return true;\n }\n } else if (hostname === pattern) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if an IPv4 address falls within any blocked CIDR range.\n */\nexport function isIpInBlockedCidrs(ip: string, cidrs: string[]): boolean {\n // Handle IPv4-mapped IPv6\n const normalizedIp = normalizeIp(ip);\n if (!normalizedIp) return false;\n\n for (const cidr of cidrs) {\n if (cidr.includes(\":\")) {\n // IPv6 CIDR — skip for IPv4 addresses\n if (!ip.includes(\":\")) continue;\n if (isIpv6InCidr(ip, cidr)) return true;\n } else {\n if (isIpv4InCidr(normalizedIp, cidr)) return true;\n }\n }\n return false;\n}\n\nfunction normalizeIp(ip: string): string | null {\n // Handle IPv4-mapped IPv6 (e.g. \"::ffff:127.0.0.1\")\n if (ip.startsWith(\"::ffff:\")) {\n return ip.slice(7);\n }\n // Pure IPv4\n if (/^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(ip)) {\n return ip;\n }\n return null;\n}\n\nfunction isIpv4InCidr(ip: string, cidr: string): boolean {\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix) || prefix < 0 || prefix > 32) return false;\n\n const ipNum = ipv4ToNum(ip);\n const cidrNum = ipv4ToNum(cidrIp);\n if (ipNum === null || cidrNum === null) return false;\n\n const mask = prefix === 0 ? 0 : (~0 << (32 - prefix)) >>> 0;\n return (ipNum & mask) === (cidrNum & mask);\n}\n\nfunction ipv4ToNum(ip: string): number | null {\n const parts = ip.split(\".\");\n if (parts.length !== 4) return null;\n let num = 0;\n for (const part of parts) {\n const n = parseInt(part, 10);\n if (isNaN(n) || n < 0 || n > 255) return null;\n num = (num << 8) | n;\n }\n return num >>> 0;\n}\n\nfunction isIpv6InCidr(ip: string, cidr: string): boolean {\n // Simplified IPv6 CIDR matching for common cases (::1, fc00::, fe80::)\n const [cidrIp, prefixStr] = cidr.split(\"/\");\n if (!cidrIp || !prefixStr) return false;\n\n const prefix = parseInt(prefixStr, 10);\n if (isNaN(prefix)) return false;\n\n const ipBytes = expandIpv6(ip);\n const cidrBytes = expandIpv6(cidrIp);\n if (!ipBytes || !cidrBytes) return false;\n\n // Compare prefix bits\n const fullBytes = Math.floor(prefix / 8);\n for (let i = 0; i < fullBytes && i < 16; i++) {\n if (ipBytes[i] !== cidrBytes[i]) return false;\n }\n\n const remainingBits = prefix % 8;\n if (remainingBits > 0 && fullBytes < 16) {\n const mask = (~0 << (8 - remainingBits)) & 0xff;\n if ((ipBytes[fullBytes]! & mask) !== (cidrBytes[fullBytes]! & mask)) return false;\n }\n\n return true;\n}\n\nfunction expandIpv6(ip: string): number[] | null {\n // Remove zone ID\n const zoneIdx = ip.indexOf(\"%\");\n if (zoneIdx !== -1) ip = ip.slice(0, zoneIdx);\n\n const parts = ip.split(\"::\");\n if (parts.length > 2) return null;\n\n const bytes: number[] = new Array(16).fill(0);\n\n const expandGroup = (group: string): number[] => {\n if (!group) return [];\n return group.split(\":\").flatMap((hex) => {\n const val = parseInt(hex || \"0\", 16);\n return [(val >> 8) & 0xff, val & 0xff];\n });\n };\n\n if (parts.length === 1) {\n const expanded = expandGroup(parts[0]!);\n if (expanded.length !== 16) return null;\n return expanded;\n }\n\n const left = expandGroup(parts[0]!);\n const right = expandGroup(parts[1]!);\n\n if (left.length + right.length > 16) return null;\n\n for (let i = 0; i < left.length; i++) bytes[i] = left[i]!;\n for (let i = 0; i < right.length; i++) bytes[16 - right.length + i] = right[i]!;\n\n return bytes;\n}\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Fetch a URL and return the response as text.\n * @tool\n * @effect none\n */\nexport const fetchTextHandler = (async (args: {\n url: string;\n /** Alias for url (accepted when agents send \"uri\" instead of \"url\"). */\n uri?: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n body?: string | null;\n timeoutMs?: number;\n maxBytes?: number;\n}) => {\n const ctx = getBuiltinContext();\n const url = (args.url ?? args.uri)?.trim();\n if (!url) {\n throw createTaggedError(\"HTTP_INVALID\", \"url is required (pass 'url' or 'uri')\", {});\n }\n const method = args.method ?? \"GET\";\n const headers = args.headers ?? {};\n const body = args.body ?? undefined;\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;\n\n // SSRF validation\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n if (!headers[\"User-Agent\"] && !headers[\"user-agent\"]) {\n headers[\"User-Agent\"] = ctx.config.httpUserAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body ?? undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Request to ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,\n { url, contentLength: parseInt(contentLength, 10), limit: maxBytes },\n );\n }\n\n const text = await readResponseWithLimit(response, maxBytes, url);\n const bytes = Buffer.byteLength(text, \"utf-8\");\n\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n return {\n result: {\n url,\n status: response.status,\n headers: responseHeaders,\n text,\n bytes,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `${method} ${url} → ${response.status} (${bytes} bytes)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n\nasync function readResponseWithLimit(\n response: Response,\n maxBytes: number,\n url: string,\n): Promise<string> {\n if (!response.body) {\n return response.text();\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const chunks: string[] = [];\n let totalBytes = 0;\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n reader.cancel();\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response body exceeded limit of ${maxBytes} bytes while reading from ${url}`,\n { url, bytesRead: totalBytes, limit: maxBytes },\n );\n }\n\n chunks.push(decoder.decode(value, { stream: true }));\n }\n chunks.push(decoder.decode());\n } finally {\n reader.releaseLock();\n }\n\n return chunks.join(\"\");\n}\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Fetch a URL and return the response as parsed JSON.\n * @tool\n * @effect none\n */\nexport const fetchJsonHandler = (async (args: {\n url: string;\n /** Alias for url (accepted when agents send \"uri\" instead of \"url\"). */\n uri?: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n body?: string | null;\n timeoutMs?: number;\n maxBytes?: number;\n}) => {\n const ctx = getBuiltinContext();\n const url = (args.url ?? args.uri)?.trim();\n if (!url) {\n throw createTaggedError(\"HTTP_INVALID\", \"url is required (pass 'url' or 'uri')\", {});\n }\n const method = args.method ?? \"GET\";\n const headers = args.headers ?? {};\n const body = args.body ?? undefined;\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;\n\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n if (!headers[\"Accept\"] && !headers[\"accept\"]) {\n headers[\"Accept\"] = \"application/json\";\n }\n if (!headers[\"User-Agent\"] && !headers[\"user-agent\"]) {\n headers[\"User-Agent\"] = ctx.config.httpUserAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method,\n headers,\n body: body ?? undefined,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Request to ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,\n { url, contentLength: parseInt(contentLength, 10), limit: maxBytes },\n );\n }\n\n const text = await response.text();\n const bytes = Buffer.byteLength(text, \"utf-8\");\n\n if (bytes > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response body ${bytes} bytes exceeds limit of ${maxBytes} bytes`,\n { url, bytes, limit: maxBytes },\n );\n }\n\n let json: unknown;\n try {\n json = JSON.parse(text);\n } catch {\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Failed to parse JSON response from ${url}: ${text.slice(0, 200)}`,\n { url, status: response.status, textPreview: text.slice(0, 500) },\n );\n }\n\n return {\n result: {\n url,\n status: response.status,\n json,\n bytes,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `${method} ${url} → ${response.status} JSON (${bytes} bytes)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { writeFile, mkdir } from \"node:fs/promises\";\nimport { createHash } from \"node:crypto\";\nimport { dirname } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Download a file from a URL to the sandbox.\n * @tool\n * @effect local_write\n */\nexport const downloadFileHandler = (async (args: {\n url: string;\n /** Alias for url (accepted when agents send \"uri\" instead of \"url\"). */\n uri?: string;\n destPath: string;\n /** Aliases for destPath (destination, filePath). */\n destination?: string;\n filePath?: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n maxBytes?: number;\n overwrite?: boolean;\n}) => {\n const ctx = getBuiltinContext();\n const url = (args.url ?? args.uri)?.trim();\n if (!url) {\n throw createTaggedError(\"HTTP_INVALID\", \"url is required (pass 'url' or 'uri')\", {});\n }\n const destPath = (args.destPath ?? args.destination ?? args.filePath)?.trim();\n if (!destPath) {\n throw createTaggedError(\"HTTP_INVALID\", \"destPath is required (pass 'destPath', 'destination', or 'filePath')\", {});\n }\n const headers = args.headers ?? {};\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = args.maxBytes ?? ctx.config.maxDownloadBytes;\n const overwrite = args.overwrite ?? false;\n\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n const resolvedDest = await resolveSandboxedPath(destPath, ctx.config.sandboxRoot);\n\n if (!overwrite) {\n const { access } = await import(\"node:fs/promises\");\n try {\n await access(resolvedDest);\n throw new Error(\n `File already exists: ${resolvedDest}. Set overwrite=true to allow overwriting.`,\n );\n } catch (err) {\n if (err instanceof Error && !err.message.includes(\"already exists\")) {\n // ENOENT — file doesn't exist, proceed\n } else {\n throw err;\n }\n }\n }\n\n if (!headers[\"User-Agent\"] && !headers[\"user-agent\"]) {\n headers[\"User-Agent\"] = ctx.config.httpUserAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Download from ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Download failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Download Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,\n { url, contentLength: parseInt(contentLength, 10), limit: maxBytes },\n );\n }\n\n if (!response.body) {\n throw createTaggedError(\"UPSTREAM_ERROR\", `No response body from ${url}`, { url });\n }\n\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let totalBytes = 0;\n const hasher = createHash(\"sha256\");\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n totalBytes += value.byteLength;\n if (totalBytes > maxBytes) {\n reader.cancel();\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Download from ${url} exceeded limit of ${maxBytes} bytes (received ${totalBytes})`,\n { url, bytesRead: totalBytes, limit: maxBytes },\n );\n }\n\n chunks.push(value);\n hasher.update(value);\n }\n } finally {\n reader.releaseLock();\n }\n\n const sha256 = hasher.digest(\"hex\");\n\n await mkdir(dirname(resolvedDest), { recursive: true });\n const buffer = Buffer.concat(chunks);\n await writeFile(resolvedDest, buffer);\n\n return {\n result: {\n destPath: resolvedDest,\n bytes: totalBytes,\n sha256,\n status: response.status,\n url,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `Downloaded ${totalBytes} bytes from ${url}`,\n createdAt: new Date().toISOString(),\n },\n {\n type: \"file\",\n ref: resolvedDest,\n summary: `Saved to ${resolvedDest} (sha256: ${sha256.slice(0, 12)}...)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Send a HEAD request to get response headers without body.\n * @tool\n * @effect none\n */\nexport const headHandler = (async (args: {\n url: string;\n /** Alias for url (accepted when agents send \"uri\" instead of \"url\"). */\n uri?: string;\n headers?: Record<string, string>;\n timeoutMs?: number;\n}) => {\n const ctx = getBuiltinContext();\n const url = (args.url ?? args.uri)?.trim();\n if (!url) {\n throw createTaggedError(\"HTTP_INVALID\", \"url is required (pass 'url' or 'uri')\", {});\n }\n const headers = args.headers ?? {};\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n\n // SSRF validation\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n if (!headers[\"User-Agent\"] && !headers[\"user-agent\"]) {\n headers[\"User-Agent\"] = ctx.config.httpUserAgent;\n }\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"HEAD\",\n headers,\n signal: controller.signal,\n });\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `HEAD request to ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `HEAD request failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n } finally {\n clearTimeout(timer);\n }\n\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n return {\n result: {\n url,\n status: response.status,\n headers: responseHeaders,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `HEAD ${url} → ${response.status}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\nconst DUCKDUCKGO_API = \"https://api.duckduckgo.com/\";\n\ninterface DuckDuckGoResult {\n FirstURL?: string;\n Text?: string;\n}\n\ninterface DuckDuckGoRelatedTopic {\n Text?: string;\n FirstURL?: string;\n Result?: string;\n Icon?: { URL?: string };\n}\n\ninterface DuckDuckGoResponse {\n Abstract?: string;\n AbstractText?: string;\n AbstractURL?: string;\n AbstractSource?: string;\n RelatedTopics?: DuckDuckGoRelatedTopic[];\n Results?: DuckDuckGoResult[];\n Heading?: string;\n}\n\n/**\n * Search DuckDuckGo via the Instant Answer API (no API key).\n * Requires api.duckduckgo.com in allowedHosts.\n * @tool\n * @effect none\n */\nexport const duckduckgoSearchHandler = (async (args: {\n /** Search query. */\n query: string;\n /** Alias for query (accepted when agents send \"q\" instead of \"query\"). */\n q?: string;\n maxResults?: number;\n timeoutMs?: number;\n}) => {\n const ctx = getBuiltinContext();\n const query = (args.query ?? args.q)?.trim();\n if (!query) {\n throw createTaggedError(\"DUCKDUCKGO_INVALID\", \"query is required (pass 'query' or 'q')\", {});\n }\n\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxResults = args.maxResults ?? 10;\n\n const url = `${DUCKDUCKGO_API}?q=${encodeURIComponent(query)}&format=json`;\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers: { \"User-Agent\": ctx.config.httpUserAgent },\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `DuckDuckGo search timed out after ${timeoutMs}ms`,\n { query, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `DuckDuckGo search failed: ${err instanceof Error ? err.message : String(err)}`,\n { query },\n );\n }\n clearTimeout(timer);\n\n const maxBytes = ctx.config.maxHttpBytes;\n const text = await response.text();\n const bytes = Buffer.byteLength(text, \"utf-8\");\n if (bytes > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `DuckDuckGo response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,\n { query, bytes, limit: maxBytes },\n );\n }\n\n let raw: DuckDuckGoResponse;\n try {\n raw = JSON.parse(text) as DuckDuckGoResponse;\n } catch {\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `DuckDuckGo returned invalid JSON`,\n { query, textPreview: text.slice(0, 200) },\n );\n }\n\n const results: Array<{ url: string; title: string; snippet?: string }> = [];\n if (Array.isArray(raw.Results)) {\n for (const r of raw.Results.slice(0, maxResults)) {\n if (r.FirstURL) {\n results.push({\n url: r.FirstURL,\n title: r.Text ?? r.FirstURL,\n snippet: r.Text,\n });\n }\n }\n }\n\n const relatedTopics: Array<{ text: string; url?: string }> = [];\n if (Array.isArray(raw.RelatedTopics)) {\n for (const t of raw.RelatedTopics.slice(0, maxResults)) {\n const text = t.Text ?? t.Result;\n if (text) {\n relatedTopics.push({ text, url: t.FirstURL });\n }\n }\n }\n\n const result = {\n query,\n abstract: raw.Abstract ?? raw.AbstractText ?? undefined,\n abstractUrl: raw.AbstractURL ?? undefined,\n abstractSource: raw.AbstractSource ?? undefined,\n heading: raw.Heading ?? undefined,\n results,\n relatedTopics,\n };\n\n return {\n result,\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `DuckDuckGo search: \"${query}\" → ${results.length} results`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { parse } from \"node-html-parser\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/** Selectors tried in order for main content (HTML5 / common patterns). */\nconst MAIN_SELECTORS = [\n \"main\",\n \"article\",\n \"[role='main']\",\n \"#content\",\n \"#main\",\n \".content\",\n \".main-content\",\n \".article-body\",\n \".post-content\",\n \".entry-content\",\n];\n\n/**\n * Extract main content text from HTML: prefer main/article/role=main, else body with nav/header/footer removed.\n */\nfunction extractMainContent(html: string): { title: string; mainContent: string } {\n const root = parse(html, { comment: false });\n let title = \"\";\n const titleEl = root.querySelector(\"title\");\n if (titleEl) {\n title = (titleEl.textContent ?? \"\").trim().replace(/\\s+/g, \" \");\n }\n\n let mainEl: ReturnType<typeof root.querySelector> = null;\n for (const sel of MAIN_SELECTORS) {\n mainEl = root.querySelector(sel);\n if (mainEl) break;\n }\n\n if (!mainEl) {\n const body = root.querySelector(\"body\");\n if (body) {\n // Remove boilerplate and get text\n for (const tag of [\"script\", \"style\", \"nav\", \"header\", \"footer\", \"aside\", \"noscript\", \"iframe\"]) {\n body.querySelectorAll(tag).forEach((el) => el.remove());\n }\n mainEl = body;\n } else {\n mainEl = root;\n }\n }\n\n const text = (mainEl.textContent ?? \"\").trim().replace(/\\s+/g, \" \");\n return { title, mainContent: text };\n}\n\n/**\n * Fetch a URL and return only the main content (main/article/body text), not full HTML.\n * For HTML responses, extracts main content; for non-HTML, returns raw text.\n * @tool\n * @effect none\n */\nexport const fetchPageMainContentHandler = (async (args: {\n url: string;\n /** Alias for url (accepted when agents send \"uri\" instead of \"url\"). */\n uri?: string;\n timeoutMs?: number;\n maxBytes?: number;\n}) => {\n const ctx = getBuiltinContext();\n const url = (args.url ?? args.uri)?.trim();\n if (!url) {\n throw createTaggedError(\"HTTP_INVALID\", \"url is required (pass 'url' or 'uri')\", {});\n }\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = args.maxBytes ?? ctx.config.maxHttpBytes;\n\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers: { \"User-Agent\": ctx.config.httpUserAgent },\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Request to ${url} timed out after ${timeoutMs}ms`,\n { url, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Fetch failed for ${url}: ${err instanceof Error ? err.message : String(err)}`,\n { url },\n );\n }\n clearTimeout(timer);\n\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && parseInt(contentLength, 10) > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response Content-Length ${contentLength} exceeds limit of ${maxBytes} bytes`,\n { url, contentLength: parseInt(contentLength, 10), limit: maxBytes },\n );\n }\n\n const rawText = await response.text();\n const rawBytes = Buffer.byteLength(rawText, \"utf-8\");\n if (rawBytes > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Response body ${rawBytes} bytes exceeds limit of ${maxBytes} bytes`,\n { url, bytes: rawBytes, limit: maxBytes },\n );\n }\n\n const contentType = (response.headers.get(\"content-type\") ?? \"\").toLowerCase();\n const isHtml = contentType.includes(\"text/html\");\n\n let title: string | undefined;\n let mainContent: string;\n\n if (isHtml && rawText.trim().length > 0) {\n try {\n const extracted = extractMainContent(rawText);\n title = extracted.title || undefined;\n mainContent = extracted.mainContent;\n } catch {\n mainContent = rawText;\n }\n } else {\n mainContent = rawText;\n }\n\n const bytes = Buffer.byteLength(mainContent, \"utf-8\");\n\n return {\n result: {\n url,\n status: response.status,\n title,\n mainContent,\n bytes,\n isHtml,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `${url} → ${response.status} main content (${bytes} bytes)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { validateUrl } from \"../security/ssrf.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\nconst YAHOO_CHART_BASE = \"https://query1.finance.yahoo.com/v8/finance/chart/\";\n\n/** Yahoo Finance chart API response (subset we use). */\ninterface YahooChartResult {\n meta?: {\n currency?: string;\n symbol?: string;\n regularMarketPrice?: number;\n previousClose?: number;\n chartPreviousClose?: number;\n };\n timestamp?: number[];\n indicators?: {\n quote?: Array<{\n open?: (number | null)[];\n high?: (number | null)[];\n low?: (number | null)[];\n close?: (number | null)[];\n volume?: (number | null)[];\n }>;\n };\n}\n\ninterface YahooChartResponse {\n chart?: {\n result?: YahooChartResult[] | null;\n error?: { code?: string; description?: string } | null;\n };\n}\n\nexport interface YahooQuoteItem {\n symbol: string;\n currency?: string;\n price?: number;\n previousClose?: number;\n change?: number;\n changePercent?: number;\n open?: number;\n high?: number;\n low?: number;\n volume?: number;\n timestamp?: number;\n}\n\n/**\n * Fetch stock quote(s) from Yahoo Finance chart API (no API key).\n * Requires query1.finance.yahoo.com in allowedHosts.\n * @tool\n * @effect none\n */\nexport const yahooFinanceQuoteHandler = (async (args: {\n symbols: string | string[];\n /** Alias for symbols (accepted when agents send \"symbol\" or \"tickers\"). */\n symbol?: string | string[];\n tickers?: string | string[];\n range?: \"1d\" | \"5d\" | \"1mo\" | \"3mo\" | \"6mo\" | \"1y\" | \"2y\" | \"5y\" | \"max\";\n timeoutMs?: number;\n}) => {\n const ctx = getBuiltinContext();\n const rawSymbols = args.symbols ?? args.symbol ?? args.tickers;\n const symbols = Array.isArray(rawSymbols)\n ? rawSymbols.map((s) => String(s).trim().toUpperCase()).filter(Boolean)\n : rawSymbols != null\n ? [String(rawSymbols).trim().toUpperCase()].filter(Boolean)\n : [];\n\n if (symbols.length === 0) {\n throw createTaggedError(\n \"YAHOO_INVALID\",\n \"At least one symbol is required\",\n {},\n );\n }\n\n const range = args.range ?? \"1d\";\n const timeoutMs = args.timeoutMs ?? ctx.config.defaultTimeoutMs;\n const maxBytes = ctx.config.maxHttpBytes;\n\n const quotes: YahooQuoteItem[] = [];\n\n for (const symbol of symbols) {\n const url = `${YAHOO_CHART_BASE}${encodeURIComponent(symbol)}?interval=1d&range=${range}`;\n await validateUrl(url, ctx.config.allowedHosts, ctx.config.blockedCidrs);\n\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: \"GET\",\n headers: {\n \"User-Agent\": ctx.config.httpUserAgent,\n Accept: \"application/json\",\n },\n signal: controller.signal,\n });\n } catch (err) {\n clearTimeout(timer);\n if (err instanceof Error && err.name === \"AbortError\") {\n throw createTaggedError(\n \"HTTP_TIMEOUT\",\n `Yahoo Finance request for ${symbol} timed out after ${timeoutMs}ms`,\n { symbol, timeoutMs },\n );\n }\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n `Yahoo Finance request failed: ${err instanceof Error ? err.message : String(err)}`,\n { symbol },\n );\n }\n clearTimeout(timer);\n\n const text = await response.text();\n const bytes = Buffer.byteLength(text, \"utf-8\");\n if (bytes > maxBytes) {\n throw createTaggedError(\n \"HTTP_TOO_LARGE\",\n `Yahoo Finance response ${bytes} bytes exceeds limit of ${maxBytes} bytes`,\n { symbol, bytes, limit: maxBytes },\n );\n }\n\n let data: YahooChartResponse;\n try {\n data = JSON.parse(text) as YahooChartResponse;\n } catch {\n throw createTaggedError(\n \"UPSTREAM_ERROR\",\n \"Yahoo Finance returned invalid JSON\",\n { symbol, textPreview: text.slice(0, 200) },\n );\n }\n\n const error = data.chart?.error;\n if (error?.description) {\n throw createTaggedError(\n \"YAHOO_ERROR\",\n `Yahoo Finance error for ${symbol}: ${error.description}`,\n { symbol, code: error.code },\n );\n }\n\n const result = data.chart?.result?.[0];\n if (!result) {\n quotes.push({ symbol });\n continue;\n }\n\n const meta = result.meta ?? {};\n const quoteArr = result.indicators?.quote?.[0];\n const lastIdx = (result.timestamp?.length ?? 1) - 1;\n const price = meta.regularMarketPrice ?? meta.previousClose ?? quoteArr?.close?.[lastIdx] ?? undefined;\n const previousClose = meta.previousClose ?? meta.chartPreviousClose ?? quoteArr?.close?.[Math.max(0, lastIdx - 1)] ?? undefined;\n const change = price != null && previousClose != null ? price - previousClose : undefined;\n const changePercent =\n change != null && previousClose != null && previousClose !== 0\n ? (change / previousClose) * 100\n : undefined;\n\n quotes.push({\n symbol: meta.symbol ?? symbol,\n currency: meta.currency,\n price: price ?? undefined,\n previousClose: previousClose ?? undefined,\n change,\n changePercent,\n open: quoteArr?.open?.[lastIdx] ?? undefined,\n high: quoteArr?.high?.[lastIdx] ?? undefined,\n low: quoteArr?.low?.[lastIdx] ?? undefined,\n volume: quoteArr?.volume?.[lastIdx] ?? undefined,\n timestamp: result.timestamp?.[lastIdx],\n });\n }\n\n const url = `${YAHOO_CHART_BASE}${encodeURIComponent(symbols[0]!)}?interval=1d&range=${range}`;\n return {\n result: {\n symbols: quotes.map((q) => q.symbol),\n quotes,\n range,\n },\n evidence: [\n {\n type: \"url\",\n ref: url,\n summary: `Yahoo Finance quote: ${symbols.join(\", \")} (${quotes.length} result(s))`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Select fields from JSON data using JMESPath expressions.\n * @tool\n * @effect none\n */\nexport const jsonSelectHandler = (async (args: {\n json: unknown;\n path: string;\n /** Alias for path (JMESPath expression; accepted when agents send \"expression\"). */\n expression?: string;\n}) => {\n const json = args.json;\n const path = (args.path ?? args.expression)?.trim();\n if (path === undefined || path === \"\") {\n throw new Error(\"path is required (pass 'path' or 'expression')\");\n }\n\n let jmespath: { search: (data: unknown, expression: string) => unknown };\n try {\n jmespath = await import(\"jmespath\");\n } catch {\n throw new Error(\n \"jmespath package is required for core/util.json.select. Install it with: npm install jmespath\",\n );\n }\n\n let value: unknown;\n try {\n value = jmespath.search(json, path);\n } catch (err) {\n throw new Error(\n `JMESPath expression error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return {\n result: { value },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.json.select\",\n summary: `Selected \"${path}\" from JSON → ${typeof value === \"object\" ? JSON.stringify(value).slice(0, 100) : String(value).slice(0, 100)}`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Truncate text to a maximum character length with a suffix marker.\n * @tool\n * @effect none\n */\nexport const truncateHandler = (async (args: {\n text: string;\n maxChars: number;\n suffix?: string;\n}) => {\n const text = args.text;\n const maxChars = args.maxChars;\n const suffix = args.suffix ?? \"...\";\n\n const originalLength = text.length;\n\n if (text.length <= maxChars) {\n return {\n result: { text, truncated: false, originalLength },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.text.truncate\",\n summary: `Text not truncated (${originalLength} chars <= ${maxChars} max)`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n }\n\n const truncatedText = text.slice(0, maxChars - suffix.length) + suffix;\n\n return {\n result: { text: truncatedText, truncated: true, originalLength },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.text.truncate\",\n summary: `Truncated ${originalLength} chars to ${truncatedText.length} chars`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { createHash } from \"node:crypto\";\nimport type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Compute SHA-256 hash of a text string.\n * @tool\n * @effect none\n */\nexport const hashTextHandler = (async (args: { text: string }) => {\n const text = args.text;\n const sha256 = createHash(\"sha256\").update(text, \"utf-8\").digest(\"hex\");\n\n return {\n result: { sha256 },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.hash.sha256Text\",\n summary: `SHA-256 of ${text.length} chars: ${sha256.slice(0, 16)}...`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Get the current time in various formats.\n * @tool\n * @effect none\n */\nexport const nowHandler = (async (args: { timezone?: string }) => {\n const timezone = args.timezone ?? \"UTC\";\n const now = new Date();\n\n let formatted: string;\n try {\n formatted = new Intl.DateTimeFormat(\"en-US\", {\n timeZone: timezone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n timeZoneName: \"short\",\n }).format(now);\n } catch {\n formatted = now.toISOString();\n }\n\n return {\n result: {\n iso: now.toISOString(),\n epochMs: now.getTime(),\n timezone,\n formatted,\n },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.time.now\",\n summary: `Current time: ${now.toISOString()} (${timezone})`,\n createdAt: now.toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import type { CoreToolHandler } from \"../types.js\";\n\n/**\n * Render a Mustache template with data.\n * @tool\n * @effect none\n */\nexport const templateRenderHandler = (async (args: {\n template: string;\n data: Record<string, unknown>;\n}) => {\n const template = args.template;\n const data = args.data;\n\n let renderFn: (template: string, view: unknown) => string;\n try {\n const mod = await import(\"mustache\");\n const mustache = mod.default ?? mod;\n renderFn = mustache.render.bind(mustache);\n } catch {\n throw new Error(\n \"mustache package is required for core/util.template.render. Install it with: npm install mustache\",\n );\n }\n\n let text: string;\n try {\n text = renderFn(template, data);\n } catch (err) {\n throw new Error(\n `Template rendering error: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n return {\n result: { text },\n evidence: [\n {\n type: \"tool\",\n ref: \"core/util.template.render\",\n summary: `Rendered template (${template.length} chars) → ${text.length} chars output`,\n createdAt: new Date().toISOString(),\n },\n ],\n };\n}) as CoreToolHandler;\n","import { spawn } from \"node:child_process\";\nimport { resolve as pathResolve } from \"node:path\";\nimport type { CoreToolHandler } from \"../types.js\";\nimport { getBuiltinContext } from \"../context.js\";\nimport { resolveSandboxedPath } from \"../security/sandbox.js\";\nimport { createTaggedError } from \"@easynet/agent-tool\";\n\n/**\n * Run a Linux command in the sandbox with an allowlist and timeout.\n * Uses spawn (no shell) to avoid injection; command and args are separate.\n * @tool\n * @effect local_write\n */\nexport const runCommandHandler = (async (args: {\n command: string;\n /** Alias for command (accepted when agents send \"cmd\" instead of \"command\"). */\n cmd?: string;\n args?: string[];\n /** Alias for args (accepted when agents send \"arguments\" instead of \"args\"). */\n arguments?: string[];\n cwd?: string;\n timeoutMs?: number;\n}) => {\n const ctx = getBuiltinContext();\n const { allowedCommands, maxCommandOutputBytes, commandTimeoutMs } = ctx.config;\n\n if (!allowedCommands.length) {\n throw createTaggedError(\n \"EXEC_DISABLED\",\n \"Exec is disabled: allowedCommands is empty\",\n {},\n );\n }\n\n const rawCommand = (args.command ?? args.cmd)?.trim();\n if (!rawCommand) {\n throw createTaggedError(\"EXEC_INVALID\", \"command is required (pass 'command' or 'cmd')\", {});\n }\n\n // Only allow bare command name (no path, no shell metacharacters)\n const baseName = rawCommand.replace(/^.*\\//, \"\").trim();\n if (baseName !== rawCommand || /[;&|$`\\s]/.test(rawCommand)) {\n throw createTaggedError(\n \"EXEC_INVALID\",\n \"command must be a single executable name (no path, no shell chars)\",\n { command: rawCommand },\n );\n }\n\n if (!allowedCommands.includes(baseName)) {\n throw createTaggedError(\n \"EXEC_NOT_ALLOWED\",\n `Command \"${baseName}\" is not in allowedCommands`,\n { command: baseName, allowed: allowedCommands },\n );\n }\n\n const cmdArgs: string[] = Array.isArray(args.args)\n ? args.args\n : Array.isArray(args.arguments)\n ? args.arguments\n : [];\n const timeoutMs = args.timeoutMs ?? commandTimeoutMs;\n let cwd: string = pathResolve(ctx.config.sandboxRoot);\n\n if (args.cwd != null && args.cwd !== \"\") {\n cwd = await resolveSandboxedPath(args.cwd, ctx.config.sandboxRoot);\n }\n\n return new Promise<{ result: unknown; evidence: unknown[] }>((resolvePromise, rejectPromise) => {\n const proc = spawn(baseName, cmdArgs, {\n cwd,\n shell: false,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env },\n });\n\n let stdout = \"\";\n let stderr = \"\";\n let totalBytes = 0;\n\n const append = (chunk: string, dest: \"stdout\" | \"stderr\") => {\n const len = Buffer.byteLength(chunk, \"utf-8\");\n if (totalBytes + len > maxCommandOutputBytes) {\n proc.kill(\"SIGKILL\");\n rejectPromise(\n createTaggedError(\n \"EXEC_OUTPUT_TOO_LARGE\",\n `Command output exceeded ${maxCommandOutputBytes} bytes`,\n { maxBytes: maxCommandOutputBytes },\n ),\n );\n return;\n }\n totalBytes += len;\n if (dest === \"stdout\") stdout += chunk;\n else stderr += chunk;\n };\n\n proc.stdout?.setEncoding(\"utf-8\");\n proc.stderr?.setEncoding(\"utf-8\");\n proc.stdout?.on(\"data\", (chunk: string) => append(chunk, \"stdout\"));\n proc.stderr?.on(\"data\", (chunk: string) => append(chunk, \"stderr\"));\n\n const timeout = setTimeout(() => {\n proc.kill(\"SIGKILL\");\n resolvePromise({\n result: {\n stdout,\n stderr,\n exitCode: null,\n timedOut: true,\n signal: \"SIGKILL\",\n },\n evidence: [\n {\n type: \"exec\",\n summary: `Command \"${baseName}\" timed out after ${timeoutMs}ms`,\n createdAt: new Date().toISOString(),\n },\n ],\n });\n }, timeoutMs);\n\n proc.on(\"error\", (err) => {\n clearTimeout(timeout);\n rejectPromise(\n createTaggedError(\"EXEC_SPAWN_ERROR\", err.message, { command: baseName }),\n );\n });\n\n proc.on(\"close\", (code, signal) => {\n clearTimeout(timeout);\n resolvePromise({\n result: {\n stdout,\n stderr,\n exitCode: code,\n timedOut: false,\n signal: signal ?? undefined,\n },\n evidence: [\n {\n type: \"exec\",\n ref: baseName,\n summary: `Ran ${baseName} (exit ${code ?? signal})`,\n createdAt: new Date().toISOString(),\n },\n ],\n });\n });\n });\n}) as CoreToolHandler;\n"],"mappings":"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","names":["createTaggedError","dirname","access","dirname","stat","resolve","resolve","stat","readdir","stat","join","readdir","join","stat","createReadStream","stat","createHash","createTaggedError","stat","resolve","createHash","createReadStream","stat","stat","createTaggedError","createTaggedError","createTaggedError","writeFile","mkdir","createHash","dirname","createTaggedError","access","createHash","mkdir","dirname","writeFile","createTaggedError","createTaggedError","text","createTaggedError","createTaggedError","url","createHash","createTaggedError"]}
@@ -1 +1 @@
1
- {"version":3,"file":"jsonSelect.d.ts","sourceRoot":"","sources":["../../util/jsonSelect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAoCxB,eAAe,CAAC"}
1
+ {"version":3,"file":"jsonSelect.d.ts","sourceRoot":"","sources":["../../util/jsonSelect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAyCxB,eAAe,CAAC"}