@supyagent/sdk 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/cache.ts","../src/core/tool-converter.ts","../src/core/http-executor.ts","../src/core/skill-parser.ts","../src/tools/skills.ts","../src/core/client.ts","../src/tools/bash.ts","../src/tools/view-image.ts"],"sourcesContent":["export { supyagent } from \"./core/client.js\";\nexport type {\n SupyagentOptions,\n SupyagentClient,\n ScopedClient,\n ToolFilterOptions,\n ToolMetadata,\n OpenAITool,\n ToolsResponse,\n SkillsOptions,\n SkillsResult,\n ParsedSkill,\n ParsedSkillsDocument,\n MeOptions,\n MeResponse,\n // Connected accounts\n ConnectedAccount,\n ConnectedAccountWithIntegrations,\n AccountIntegration,\n AccountIntegrationDetail,\n CreateAccountOptions,\n UpdateAccountOptions,\n ListAccountsOptions,\n ListAccountsResponse,\n ConnectOptions,\n ConnectSession,\n ConnectSessionStatus,\n AccountsClient,\n} from \"./core/types.js\";\nexport { createBashTool } from \"./tools/bash.js\";\nexport type { BashToolOptions, BashToolResult } from \"./tools/bash.js\";\nexport { createViewImageTool } from \"./tools/view-image.js\";\nexport type { ViewImageToolOptions, ViewImageToolResult } from \"./tools/view-image.js\";\nexport { parseSkillsMarkdown, buildSkillsSystemPrompt, findSkill } from \"./core/skill-parser.js\";\nexport { createLoadSkillTool, createApiCallTool } from \"./tools/skills.js\";\n","interface CacheEntry<T> {\n data: T;\n expiresAt: number;\n}\n\nexport class TTLCache<T> {\n private store = new Map<string, CacheEntry<T>>();\n\n get(key: string): T | undefined {\n const entry = this.store.get(key);\n if (!entry) return undefined;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return undefined;\n }\n return entry.data;\n }\n\n set(key: string, data: T, ttlSeconds: number): void {\n this.store.set(key, {\n data,\n expiresAt: Date.now() + ttlSeconds * 1000,\n });\n }\n\n clear(): void {\n this.store.clear();\n }\n}\n","import { tool, jsonSchema } from \"ai\";\nimport type { OpenAITool } from \"./types.js\";\nimport { createExecutor } from \"./http-executor.js\";\n\n/**\n * Converts an array of OpenAI-format tools from the supyagent API\n * into a Record of AI SDK tool() instances ready for streamText/generateText.\n */\nexport function convertTools(\n tools: OpenAITool[],\n baseUrl: string,\n apiKey: string,\n accountId?: string,\n): Record<string, import(\"ai\").Tool> {\n const result: Record<string, import(\"ai\").Tool> = {};\n\n for (const t of tools) {\n const { name, description, parameters } = t.function;\n const metadata = t.metadata;\n\n result[name] = tool({\n description,\n inputSchema: jsonSchema(parameters as Parameters<typeof jsonSchema>[0]),\n execute: async (args) => createExecutor(metadata, baseUrl, apiKey, accountId)(args as Record<string, unknown>),\n });\n }\n\n return result;\n}\n\n/**\n * Filter tools by provider, service, or tool name.\n */\nexport function filterTools(\n tools: OpenAITool[],\n options: { only?: string[]; except?: string[] }\n): OpenAITool[] {\n let filtered = tools;\n\n if (options.only && options.only.length > 0) {\n const onlySet = new Set(options.only.map((s) => s.toLowerCase()));\n filtered = filtered.filter((t) => {\n const name = t.function.name.toLowerCase();\n const provider = t.metadata.provider.toLowerCase();\n const service = t.metadata.service.toLowerCase();\n return onlySet.has(name) || onlySet.has(provider) || onlySet.has(service);\n });\n }\n\n if (options.except && options.except.length > 0) {\n const exceptSet = new Set(options.except.map((s) => s.toLowerCase()));\n filtered = filtered.filter((t) => {\n const name = t.function.name.toLowerCase();\n const provider = t.metadata.provider.toLowerCase();\n const service = t.metadata.service.toLowerCase();\n return (\n !exceptSet.has(name) &&\n !exceptSet.has(provider) &&\n !exceptSet.has(service)\n );\n });\n }\n\n return filtered;\n}\n","import type { ToolMetadata } from \"./types.js\";\n\n/**\n * Creates an execute function for a tool that calls the supyagent API.\n *\n * Handles:\n * - Path parameter substitution (e.g., {messageId} in /api/v1/gmail/messages/{messageId})\n * - GET/DELETE: remaining args → query string\n * - POST/PUT/PATCH: merge bodyDefaults + remaining args → JSON body\n */\nexport function createExecutor(\n metadata: ToolMetadata,\n baseUrl: string,\n apiKey: string,\n accountId?: string,\n): (args: Record<string, unknown>) => Promise<unknown> {\n return async (args: Record<string, unknown>) => {\n const { method, path, bodyDefaults } = metadata;\n\n // Extract path parameters and substitute into the path\n const remainingArgs = { ...args };\n let resolvedPath = path;\n\n const pathParams = path.match(/\\{(\\w+)\\}/g);\n if (pathParams) {\n for (const param of pathParams) {\n const paramName = param.slice(1, -1);\n if (paramName in remainingArgs) {\n resolvedPath = resolvedPath.replace(\n param,\n encodeURIComponent(String(remainingArgs[paramName]))\n );\n delete remainingArgs[paramName];\n }\n }\n\n // Fallback: LLMs often send { id } instead of { messageId }, { eventId }, etc.\n // because list responses return objects with an `id` field.\n // For any unresolved {fooId} param, try `id` from the args (once only).\n if (\"id\" in remainingArgs && resolvedPath.includes(\"{\")) {\n const unresolved = resolvedPath.match(/\\{(\\w+)\\}/g);\n if (unresolved) {\n for (const param of unresolved) {\n const paramName = param.slice(1, -1);\n if (paramName.toLowerCase().endsWith(\"id\")) {\n resolvedPath = resolvedPath.replace(\n param,\n encodeURIComponent(String(remainingArgs.id))\n );\n delete remainingArgs.id;\n break; // consume `id` only once\n }\n }\n }\n }\n }\n\n let url = `${baseUrl}${resolvedPath}`;\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n ...(accountId ? { \"X-Account-Id\": accountId } : {}),\n },\n };\n\n if (method === \"GET\" || method === \"DELETE\") {\n // Remaining args go as query parameters\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(remainingArgs)) {\n if (value !== undefined && value !== null) {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n } else {\n // POST/PUT/PATCH: merge bodyDefaults with remaining args\n const body = { ...bodyDefaults, ...remainingArgs };\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n const data = await response.json();\n return data;\n };\n}\n","import type { ParsedSkill, ParsedSkillsDocument } from \"./types.js\";\n\n/**\n * Parse YAML frontmatter from the beginning of a markdown document.\n */\nfunction parseFrontmatter(markdown: string): {\n frontmatter: { name: string; description: string };\n body: string;\n} {\n const match = markdown.match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/);\n if (!match) {\n return {\n frontmatter: { name: \"supyagent-skills\", description: \"\" },\n body: markdown,\n };\n }\n\n const [, yamlBlock, body] = match;\n const fields: Record<string, string> = {};\n for (const line of yamlBlock!.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex > 0) {\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n fields[key] = value;\n }\n }\n\n return {\n frontmatter: {\n name: fields.name || \"supyagent-skills\",\n description: fields.description || \"\",\n },\n body: body!,\n };\n}\n\n/**\n * Extract the skill name from a section starting with `# Name`.\n */\nfunction extractSkillName(section: string): string {\n const match = section.match(/^#\\s+(.+)/m);\n return match ? match[1].trim() : \"Unknown\";\n}\n\n/**\n * Parse the aggregated skills markdown into structured sections.\n */\nexport function parseSkillsMarkdown(markdown: string): ParsedSkillsDocument {\n const { frontmatter, body } = parseFrontmatter(markdown);\n\n // Split body on \\n---\\n (the section separator)\n const parts = body.split(/\\n---\\n/);\n\n // First part is the preamble (general header info)\n const preamble = (parts[0] || \"\").trim();\n\n // Remaining parts are individual skill sections\n const skills: ParsedSkill[] = [];\n for (let i = 1; i < parts.length; i++) {\n const content = parts[i]!.trim();\n if (!content) continue;\n const name = extractSkillName(content);\n skills.push({ name, content });\n }\n\n return { frontmatter, preamble, skills };\n}\n\n/**\n * Build a concise system prompt from parsed skills.\n * Lists available skills with one-line summaries, not full docs.\n */\nexport function buildSkillsSystemPrompt(\n doc: ParsedSkillsDocument,\n): string {\n if (doc.skills.length === 0) {\n return \"No skills are currently available. The user has no connected integrations.\";\n }\n\n const skillList = doc.skills.map((s) => `- **${s.name}**`).join(\"\\n\");\n\n return `You have access to the following skills via Supyagent:\n\n${skillList}\n\nTo use a skill:\n1. Call \\`loadSkill\\` with the skill name to get detailed API documentation\n2. Call \\`apiCall\\` to make authenticated HTTP requests to the API endpoints described in the skill docs\n\nAvailable skill names: ${doc.skills.map((s) => s.name).join(\", \")}`;\n}\n\n/**\n * Find a skill by name (case-insensitive).\n */\nexport function findSkill(\n skills: ParsedSkill[],\n name: string,\n): ParsedSkill | null {\n const normalized = name.toLowerCase().trim();\n return (\n skills.find((s) => s.name.toLowerCase() === normalized) ??\n skills.find((s) => s.name.toLowerCase().includes(normalized)) ??\n null\n );\n}\n","import { tool, jsonSchema } from \"ai\";\nimport type { ParsedSkill } from \"../core/types.js\";\nimport { findSkill } from \"../core/skill-parser.js\";\n\n/**\n * Create the loadSkill tool.\n * Returns detailed documentation for a specific skill.\n */\nexport function createLoadSkillTool(skills: ParsedSkill[]) {\n const availableNames = skills.map((s) => s.name).join(\", \");\n\n return tool({\n description: `Load detailed API documentation for a specific skill. Available skills: ${availableNames}. Call this before using apiCall to understand the available endpoints, parameters, and examples.`,\n inputSchema: jsonSchema({\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description: `The skill name to load. Available: ${availableNames}`,\n },\n },\n required: [\"name\"],\n } as Parameters<typeof jsonSchema>[0]),\n execute: async (args) => {\n const { name } = args as { name: string };\n const skill = findSkill(skills, name);\n\n if (!skill) {\n return {\n error: `Skill \"${name}\" not found. Available skills: ${availableNames}`,\n };\n }\n\n return {\n name: skill.name,\n documentation: skill.content,\n };\n },\n });\n}\n\nconst VALID_METHODS = new Set([\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"]);\n\n/**\n * Create the apiCall tool.\n * Makes authenticated HTTP requests to the Supyagent API.\n */\nexport function createApiCallTool(baseUrl: string, apiKey: string, accountId?: string) {\n return tool({\n description:\n \"Make an authenticated HTTP request to the Supyagent API. Use loadSkill first to understand available endpoints. The authorization header and base URL are handled automatically — only provide the path (e.g., /api/v1/google/gmail/messages).\",\n inputSchema: jsonSchema({\n type: \"object\",\n properties: {\n method: {\n type: \"string\",\n enum: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"],\n description: \"HTTP method\",\n },\n path: {\n type: \"string\",\n description:\n 'API path starting with /api/v1/ (e.g., \"/api/v1/google/gmail/messages\")',\n },\n body: {\n type: \"object\",\n description: \"Request body for POST/PUT/PATCH requests\",\n additionalProperties: true,\n },\n params: {\n type: \"object\",\n description: \"Query parameters\",\n additionalProperties: true,\n },\n },\n required: [\"method\", \"path\"],\n } as Parameters<typeof jsonSchema>[0]),\n execute: async (args) => {\n const {\n method: rawMethod,\n path,\n body,\n params,\n } = args as {\n method: string;\n path: string;\n body?: Record<string, unknown>;\n params?: Record<string, unknown>;\n };\n\n const method = rawMethod.toUpperCase();\n\n if (!VALID_METHODS.has(method)) {\n return { error: `Invalid HTTP method: ${method}` };\n }\n\n if (!path.startsWith(\"/api/v1/\")) {\n return { error: `Path must start with /api/v1/. Got: ${path}` };\n }\n\n let url = `${baseUrl}${path}`;\n\n if (params && Object.keys(params).length > 0) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.set(key, String(value));\n }\n }\n const qs = searchParams.toString();\n if (qs) url += `?${qs}`;\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n ...(accountId ? { \"X-Account-Id\": accountId } : {}),\n },\n };\n\n if (body && method !== \"GET\" && method !== \"DELETE\") {\n fetchOptions.body = JSON.stringify(body);\n }\n\n try {\n const response = await fetch(url, fetchOptions);\n const data = await response.json();\n\n if (!response.ok) {\n return { error: `API returned ${response.status}`, details: data };\n }\n\n return data;\n } catch (err) {\n return {\n error: `Request failed: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n },\n });\n}\n","import type {\n SupyagentOptions,\n SupyagentClient,\n ScopedClient,\n ToolFilterOptions,\n ToolsResponse,\n SkillsOptions,\n SkillsResult,\n ParsedSkillsDocument,\n MeOptions,\n MeResponse,\n AccountsClient,\n ConnectedAccount,\n ConnectedAccountWithIntegrations,\n ListAccountsResponse,\n ConnectSession,\n ConnectSessionStatus,\n AccountIntegrationDetail,\n CreateAccountOptions,\n UpdateAccountOptions,\n ListAccountsOptions,\n ConnectOptions,\n} from \"./types.js\";\nimport { TTLCache } from \"./cache.js\";\nimport { convertTools, filterTools } from \"./tool-converter.js\";\nimport { parseSkillsMarkdown, buildSkillsSystemPrompt } from \"./skill-parser.js\";\nimport { createLoadSkillTool, createApiCallTool } from \"../tools/skills.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.supyagent.com\";\nconst CACHE_KEY = \"tools\";\n\ntype Fetcher = (path: string, init?: RequestInit) => Promise<Response>;\n\nfunction createFetcher(baseUrl: string, apiKey: string, accountId?: string): Fetcher {\n return async function fetcher(path: string, init?: RequestInit) {\n const res = await fetch(`${baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n ...(accountId ? { \"X-Account-Id\": accountId } : {}),\n ...((init?.headers as Record<string, string>) ?? {}),\n },\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Supyagent API error (${res.status}): ${text}`);\n }\n return res;\n };\n}\n\nfunction createDataPlane(\n fetcher: Fetcher,\n baseUrl: string,\n apiKey: string,\n accountId?: string,\n) {\n const toolsCache = new TTLCache<ToolsResponse>();\n const skillsCache = new TTLCache<ParsedSkillsDocument>();\n const meCache = new TTLCache<MeResponse>();\n\n return {\n async tools(filterOptions?: ToolFilterOptions) {\n const cacheTTL = resolveCacheTTL(filterOptions?.cache);\n\n // Check cache\n let response = cacheTTL > 0 ? toolsCache.get(CACHE_KEY) : undefined;\n\n if (!response) {\n // Fetch from API\n const res = await fetcher(\"/api/v1/tools\", {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n const json = await res.json();\n // API wraps response in { ok, data: { tools, base_url, total } }\n response = (json.data ?? json) as ToolsResponse;\n\n // Store in cache if TTL > 0\n if (cacheTTL > 0) {\n toolsCache.set(CACHE_KEY, response, cacheTTL);\n }\n }\n\n // Use API-reported base_url for tool execution\n const toolBaseUrl = response.base_url || baseUrl;\n\n // Guard against non-array tools (e.g., API returns empty or unexpected shape)\n const toolsArray = Array.isArray(response.tools) ? response.tools : [];\n\n // Filter\n const filtered = filterTools(toolsArray, {\n only: filterOptions?.only,\n except: filterOptions?.except,\n });\n\n // Convert to AI SDK tools\n return convertTools(filtered, toolBaseUrl, apiKey, accountId);\n },\n\n async skills(options?: SkillsOptions): Promise<SkillsResult> {\n const cacheTTL = resolveCacheTTL(options?.cache);\n\n let parsed = cacheTTL > 0 ? skillsCache.get(\"skills\") : undefined;\n\n if (!parsed) {\n const res = await fetcher(\"/api/v1/skills\");\n\n parsed = parseSkillsMarkdown(await res.text());\n\n if (cacheTTL > 0) {\n skillsCache.set(\"skills\", parsed, cacheTTL);\n }\n }\n\n return {\n systemPrompt: buildSkillsSystemPrompt(parsed),\n tools: {\n loadSkill: createLoadSkillTool(parsed.skills),\n apiCall: createApiCallTool(baseUrl, apiKey, accountId),\n },\n };\n },\n\n async me(options?: MeOptions): Promise<MeResponse> {\n const cacheTTL = resolveCacheTTL(options?.cache);\n\n let response = cacheTTL > 0 ? meCache.get(\"me\") : undefined;\n\n if (!response) {\n const res = await fetcher(\"/api/v1/me\");\n\n const json = await res.json();\n response = (json.data ?? json) as MeResponse;\n\n if (cacheTTL > 0) {\n meCache.set(\"me\", response, cacheTTL);\n }\n }\n\n return response;\n },\n };\n}\n\n/**\n * Create a supyagent client for fetching and converting tools.\n *\n * @example\n * ```ts\n * import { supyagent } from '@supyagent/sdk';\n *\n * const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });\n * const tools = await client.tools({ cache: 300 });\n * ```\n */\nexport function supyagent(options: SupyagentOptions): SupyagentClient {\n const { apiKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const fetcher = createFetcher(baseUrl, apiKey);\n const dataPlane = createDataPlane(fetcher, baseUrl, apiKey);\n\n async function apiCall<T>(\n method: string,\n path: string,\n body?: Record<string, unknown>,\n ): Promise<T> {\n const res = await fetcher(path, {\n method,\n ...(body ? { headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify(body) } : {}),\n });\n\n const json = await res.json();\n return (json.data ?? json) as T;\n }\n\n return {\n ...dataPlane,\n accounts: createAccountsClient(apiCall),\n asAccount(externalId: string): ScopedClient {\n const scopedFetcher = createFetcher(baseUrl, apiKey, externalId);\n const scopedDataPlane = createDataPlane(scopedFetcher, baseUrl, apiKey, externalId);\n return {\n accountId: externalId,\n ...scopedDataPlane,\n };\n },\n };\n}\n\nfunction createAccountsClient(\n apiCall: <T>(method: string, path: string, body?: Record<string, unknown>) => Promise<T>,\n): AccountsClient {\n function toAccount(raw: Record<string, unknown>): ConnectedAccount {\n return {\n id: raw.id as string,\n externalId: raw.external_id as string,\n displayName: (raw.display_name as string | null) ?? null,\n metadata: (raw.metadata as Record<string, unknown>) ?? {},\n createdAt: raw.created_at as string,\n };\n }\n\n function toIntegration(raw: Record<string, unknown>): {\n id: string;\n provider: string;\n status: string;\n connectedAt: string;\n } {\n return {\n id: raw.id as string,\n provider: raw.provider as string,\n status: raw.status as string,\n connectedAt: raw.connected_at as string,\n };\n }\n\n function toIntegrationDetail(raw: Record<string, unknown>): AccountIntegrationDetail {\n const services = (raw.enabled_services as Array<Record<string, unknown>>) ?? [];\n return {\n ...toIntegration(raw),\n enabledServices: services.map((s) => ({\n serviceName: s.service_name as string,\n isEnabled: s.is_enabled as boolean,\n })),\n };\n }\n\n return {\n async create(opts: CreateAccountOptions): Promise<ConnectedAccount> {\n const raw = await apiCall<Record<string, unknown>>(\"POST\", \"/api/v1/accounts\", {\n external_id: opts.externalId,\n ...(opts.displayName != null ? { display_name: opts.displayName } : {}),\n ...(opts.metadata != null ? { metadata: opts.metadata } : {}),\n });\n return toAccount(raw);\n },\n\n async list(opts?: ListAccountsOptions): Promise<ListAccountsResponse> {\n const params = new URLSearchParams();\n if (opts?.limit != null) params.set(\"limit\", String(opts.limit));\n if (opts?.offset != null) params.set(\"offset\", String(opts.offset));\n const qs = params.toString();\n const raw = await apiCall<Record<string, unknown>>(\n \"GET\",\n `/api/v1/accounts${qs ? `?${qs}` : \"\"}`,\n );\n return {\n accounts: ((raw.accounts as Array<Record<string, unknown>>) ?? []).map(toAccount),\n total: raw.total as number,\n limit: raw.limit as number,\n offset: raw.offset as number,\n };\n },\n\n async get(id: string): Promise<ConnectedAccountWithIntegrations> {\n const raw = await apiCall<Record<string, unknown>>(\"GET\", `/api/v1/accounts/${id}`);\n return {\n ...toAccount(raw),\n integrations: ((raw.integrations as Array<Record<string, unknown>>) ?? []).map(\n toIntegration,\n ),\n };\n },\n\n async update(id: string, opts: UpdateAccountOptions): Promise<ConnectedAccount> {\n const body: Record<string, unknown> = {};\n if (opts.displayName !== undefined) body.display_name = opts.displayName;\n if (opts.metadata !== undefined) body.metadata = opts.metadata;\n const raw = await apiCall<Record<string, unknown>>(\"PATCH\", `/api/v1/accounts/${id}`, body);\n return toAccount(raw);\n },\n\n async delete(id: string): Promise<{ deleted: true }> {\n return apiCall<{ deleted: true }>(\"DELETE\", `/api/v1/accounts/${id}`);\n },\n\n async connect(id: string, opts: ConnectOptions): Promise<ConnectSession> {\n const raw = await apiCall<Record<string, unknown>>(\n \"POST\",\n `/api/v1/accounts/${id}/connect`,\n {\n provider: opts.provider,\n redirect_url: opts.redirectUrl,\n ...(opts.scopes ? { scopes: opts.scopes } : {}),\n },\n );\n return {\n connectUrl: raw.connect_url as string,\n sessionId: raw.session_id as string,\n expiresAt: raw.expires_at as string,\n };\n },\n\n async getSession(id: string, sessionId: string): Promise<ConnectSessionStatus> {\n const raw = await apiCall<Record<string, unknown>>(\n \"GET\",\n `/api/v1/accounts/${id}/connect/${sessionId}`,\n );\n return {\n sessionId: raw.session_id as string,\n provider: raw.provider as string,\n status: raw.status as string,\n ...(raw.error ? { error: raw.error as string } : {}),\n createdAt: raw.created_at as string,\n expiresAt: raw.expires_at as string,\n };\n },\n\n async integrations(id: string): Promise<AccountIntegrationDetail[]> {\n const raw = await apiCall<Record<string, unknown>>(\n \"GET\",\n `/api/v1/accounts/${id}/integrations`,\n );\n return ((raw.integrations as Array<Record<string, unknown>>) ?? []).map(\n toIntegrationDetail,\n );\n },\n\n async disconnect(id: string, provider: string): Promise<{ deleted: true; provider: string }> {\n return apiCall<{ deleted: true; provider: string }>(\n \"DELETE\",\n `/api/v1/accounts/${id}/integrations/${provider}`,\n );\n },\n };\n}\n\nfunction resolveCacheTTL(cache?: boolean | number): number {\n if (cache === true) return 60;\n if (typeof cache === \"number\") return cache;\n return 0;\n}\n","import { tool, jsonSchema } from \"ai\";\nimport { exec, type ExecException } from \"node:child_process\";\n\nconst MAX_OUTPUT = 30_000;\nconst DEFAULT_TIMEOUT = 30_000; // 30 seconds\n\n// ── Environment sanitization ────────────────────────────────────────────────\n\nconst SECRET_PATTERNS = [\n /key/i, /secret/i, /token/i, /password/i, /credential/i,\n /auth/i, /private/i, /api_key/i, /apikey/i,\n /^AWS_/i, /^AZURE_/i, /^GCP_/i, /^GITHUB_/i,\n /^DATABASE_URL$/i, /^ENCRYPTION_/i, /^SUPABASE_/i,\n];\n\nconst SAFE_VARS = new Set([\n \"PATH\", \"HOME\", \"USER\", \"SHELL\", \"LANG\", \"LC_ALL\", \"LC_CTYPE\",\n \"TERM\", \"EDITOR\", \"VISUAL\", \"TMPDIR\", \"TMP\", \"TEMP\",\n \"NODE_ENV\", \"NODE_PATH\", \"NODE_OPTIONS\",\n \"NPM_CONFIG_PREFIX\", \"NVM_DIR\", \"NVM_BIN\", \"NVM_INC\",\n \"XDG_CONFIG_HOME\", \"XDG_DATA_HOME\", \"XDG_CACHE_HOME\",\n \"COLORTERM\", \"FORCE_COLOR\", \"NO_COLOR\",\n \"COLUMNS\", \"LINES\", \"SHLVL\", \"PWD\", \"OLDPWD\", \"LOGNAME\",\n \"HOSTNAME\", \"HOSTTYPE\", \"OSTYPE\", \"MACHTYPE\",\n]);\n\nfunction sanitizeEnv(\n env: NodeJS.ProcessEnv,\n opts?: { include?: string[]; exclude?: string[] }\n): Record<string, string> {\n const result: Record<string, string> = {};\n const includeSet = opts?.include ? new Set(opts.include) : null;\n const excludeSet = opts?.exclude ? new Set(opts.exclude) : null;\n\n for (const [key, value] of Object.entries(env)) {\n if (value === undefined) continue;\n if (excludeSet?.has(key)) continue;\n if (includeSet?.has(key)) { result[key] = value; continue; }\n if (SAFE_VARS.has(key)) { result[key] = value; continue; }\n if (SECRET_PATTERNS.some(p => p.test(key))) continue;\n result[key] = value;\n }\n\n result.TERM = \"dumb\";\n return result;\n}\n\nfunction buildEnv(\n policy: BashToolOptions[\"env\"],\n opts?: BashToolOptions\n): Record<string, string> {\n if (typeof policy === \"object\" && policy !== null) {\n return { ...policy, TERM: \"dumb\" };\n }\n switch (policy) {\n case \"inherit\":\n return { ...process.env, TERM: \"dumb\" } as Record<string, string>;\n case \"none\":\n return {\n PATH: process.env.PATH ?? \"/usr/local/bin:/usr/bin:/bin\",\n HOME: process.env.HOME ?? \"/tmp\",\n TERM: \"dumb\",\n };\n case \"safe\":\n default:\n return sanitizeEnv(process.env, {\n include: opts?.envInclude,\n exclude: opts?.envExclude,\n });\n }\n}\n\n// ── Command safety ──────────────────────────────────────────────────────────\n\ntype CommandSafety = \"safe\" | \"dangerous\" | \"unknown\";\n\nconst SAFE_COMMANDS = new Set([\n \"cat\", \"cd\", \"cut\", \"echo\", \"expr\", \"false\", \"grep\", \"egrep\", \"fgrep\",\n \"head\", \"id\", \"ls\", \"nl\", \"paste\", \"pwd\", \"rev\", \"seq\", \"stat\",\n \"tail\", \"tr\", \"true\", \"uname\", \"uniq\", \"wc\", \"which\", \"whoami\",\n \"date\", \"env\", \"printenv\", \"hostname\", \"df\", \"du\", \"file\",\n \"find\", \"rg\", \"tree\", \"less\", \"more\", \"sort\",\n \"diff\", \"md5sum\", \"sha256sum\", \"base64\", \"xxd\", \"hexdump\",\n \"man\", \"help\", \"type\", \"command\", \"test\", \"basename\", \"dirname\",\n \"realpath\", \"readlink\", \"tee\", \"xargs\", \"jq\", \"yq\",\n]);\n\nconst SAFE_GIT_SUBCOMMANDS = new Set([\n \"status\", \"log\", \"diff\", \"show\", \"branch\", \"tag\", \"remote\",\n \"stash\", \"describe\", \"shortlog\", \"blame\", \"reflog\", \"rev-parse\",\n \"ls-files\", \"ls-tree\", \"cat-file\", \"rev-list\", \"name-rev\",\n]);\n\nconst DANGEROUS_PATTERNS = [\n /rm\\s+(-[^\\s]*f|-[^\\s]*r|--force|--recursive).*\\//,\n /:\\(\\)\\s*\\{\\s*:\\|:&\\s*\\};:/,\n />\\s*\\/dev\\/sd/,\n /mkfs\\./,\n /dd\\s+.*of=\\/dev\\//,\n /shutdown|reboot|halt|poweroff/,\n /chmod\\s+777\\s+\\//,\n /curl.*\\|\\s*(ba)?sh/,\n /wget.*\\|\\s*(ba)?sh/,\n];\n\nfunction classifyCommand(\n command: string,\n extraSafe?: Set<string>,\n extraDeny?: RegExp[],\n): CommandSafety {\n const trimmed = command.trim();\n\n // Check dangerous patterns first\n if (DANGEROUS_PATTERNS.some(p => p.test(trimmed))) return \"dangerous\";\n if (extraDeny?.some(p => p.test(trimmed))) return \"dangerous\";\n\n // Extract base command (strip leading env var assignments)\n const stripped = trimmed.replace(/^(\\w+=\\S+\\s+)*/, \"\");\n const parts = stripped.split(/\\s+/);\n const base = parts[0]?.replace(/^.*\\//, \"\"); // strip path prefix\n\n if (!base) return \"unknown\";\n\n // Check git subcommands\n if (base === \"git\") {\n const sub = parts[1];\n if (sub && SAFE_GIT_SUBCOMMANDS.has(sub)) return \"safe\";\n return \"unknown\";\n }\n\n if (SAFE_COMMANDS.has(base)) return \"safe\";\n if (extraSafe?.has(base)) return \"safe\";\n\n return \"unknown\";\n}\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\nexport interface BashToolOptions {\n /** Working directory for commands. Defaults to `process.cwd()`. */\n cwd?: string;\n /** Command timeout in milliseconds. Defaults to 30000 (30s). Max 600000 (10m). */\n timeout?: number;\n /** Maximum output length in characters. Defaults to 30000. */\n maxOutput?: number;\n\n /**\n * Command approval policy. Default: \"auto\".\n * - `\"auto\"`: Safe read-only commands (ls, cat, grep...) auto-execute; others require user approval\n * - `\"always\"`: Every command requires user approval before execution\n * - `\"never\"`: No approval required (use only in trusted environments)\n * - `function`: Custom approval logic — return `true` to require approval\n */\n approval?: \"auto\" | \"always\" | \"never\" | ((command: string) => boolean | Promise<boolean>);\n\n /**\n * Environment variable policy. Default: \"safe\".\n * - `\"safe\"`: Strip vars matching secret patterns (KEY, TOKEN, SECRET, PASSWORD, etc.)\n * - `\"inherit\"`: Pass full process.env (NOT recommended for production)\n * - `\"none\"`: Minimal env (PATH, HOME, TERM only)\n * - `Record<string,string>`: Explicit env vars to use\n */\n env?: \"safe\" | \"inherit\" | \"none\" | Record<string, string>;\n\n /** Extra env vars to include even if they match secret patterns. Only used with `env: \"safe\"`. */\n envInclude?: string[];\n /** Extra env vars to exclude beyond default secret patterns. Only used with `env: \"safe\"`. */\n envExclude?: string[];\n\n /** Additional commands to treat as safe (auto-execute without approval in \"auto\" mode). */\n allowCommands?: string[];\n /** Additional patterns to block (never execute, even if approved). */\n denyPatterns?: RegExp[];\n}\n\nexport interface BashToolResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n durationMs: number;\n timedOut?: boolean;\n}\n\n// ── Tool factory ────────────────────────────────────────────────────────────\n\n/**\n * Create a bash tool that executes shell commands on the server.\n *\n * By default, uses \"auto\" approval (safe commands run immediately, others\n * require user approval) and \"safe\" env isolation (strips secret-like\n * environment variables).\n *\n * @example\n * ```ts\n * import { supyagent, createBashTool } from '@supyagent/sdk';\n *\n * const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });\n * const supyagentTools = await client.tools({ cache: 300 });\n *\n * const tools = {\n * ...supyagentTools,\n * bash: createBashTool({ cwd: '/path/to/project' }),\n * };\n * ```\n */\nexport function createBashTool(options?: BashToolOptions) {\n const cwd = options?.cwd ?? process.cwd();\n const timeout = Math.min(options?.timeout ?? DEFAULT_TIMEOUT, 600_000);\n const maxOutput = options?.maxOutput ?? MAX_OUTPUT;\n const approvalPolicy = options?.approval ?? \"auto\";\n\n const extraSafe = options?.allowCommands ? new Set(options.allowCommands) : undefined;\n const extraDeny = options?.denyPatterns;\n\n const execEnv = buildEnv(options?.env ?? \"safe\", options);\n\n const schema = {\n type: \"object\" as const,\n properties: {\n command: {\n type: \"string\",\n description: \"The bash command to execute\",\n },\n },\n required: [\"command\"],\n };\n\n // Resolve needsApproval based on policy\n const needsApproval =\n approvalPolicy === \"always\"\n ? true\n : approvalPolicy === \"never\"\n ? false\n : async (args: unknown) => {\n const { command } = args as { command: string };\n if (typeof approvalPolicy === \"function\") {\n return approvalPolicy(command);\n }\n // \"auto\" mode — safe commands pass, everything else needs approval\n const safety = classifyCommand(command, extraSafe, extraDeny);\n return safety !== \"safe\";\n };\n\n return tool({\n description:\n \"Execute a bash command on the server. Use this for running shell commands, scripts, package managers, git operations, file manipulation, and system tasks. Returns stdout, stderr, and exit code.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n needsApproval,\n execute: async (args): Promise<BashToolResult> => {\n const { command } = args as { command: string };\n\n // Block dangerous commands even if somehow approved\n if (\n DANGEROUS_PATTERNS.some(p => p.test(command)) ||\n extraDeny?.some(p => p.test(command))\n ) {\n return {\n stdout: \"\",\n stderr: \"Command blocked by safety policy\",\n exitCode: 126,\n durationMs: 0,\n };\n }\n\n const start = Date.now();\n\n return new Promise<BashToolResult>((resolve) => {\n const child = exec(\n command,\n {\n cwd,\n timeout,\n shell: \"/bin/bash\",\n maxBuffer: 10 * 1024 * 1024,\n env: execEnv,\n },\n (error: ExecException | null, stdout: string, stderr: string) => {\n const durationMs = Date.now() - start;\n const timedOut = error?.killed === true;\n const exitCode = timedOut\n ? 124\n : typeof error?.code === \"number\"\n ? error.code\n : error\n ? 1\n : 0;\n\n resolve({\n stdout: truncate(stdout, maxOutput),\n stderr: truncate(stderr, maxOutput),\n exitCode,\n durationMs,\n ...(timedOut ? { timedOut: true } : {}),\n });\n }\n );\n\n child.on(\"error\", () => {\n resolve({\n stdout: \"\",\n stderr: \"Failed to start process\",\n exitCode: 127,\n durationMs: Date.now() - start,\n });\n });\n });\n },\n });\n}\n\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n const half = Math.floor(max / 2) - 50;\n return (\n str.slice(0, half) +\n `\\n\\n... (${str.length - max} characters truncated) ...\\n\\n` +\n str.slice(-half)\n );\n}\n","import { tool, jsonSchema } from \"ai\";\n\nexport interface ViewImageToolOptions {\n /**\n * Custom description for the tool.\n * @default \"Display an image in the chat. Use this when you want to show the user an image from a URL.\"\n */\n description?: string;\n}\n\nexport interface ViewImageToolResult {\n url: string;\n displayed: true;\n}\n\n/**\n * Create a viewImage tool that the agent can call to display an image in the chat.\n *\n * On the client side, pair this with the `useViewImageEffect` hook (or equivalent logic)\n * to inject the image as a `FileUIPart` into the conversation. This ensures the image\n * is visible to both the user (rendered as `<img>`) and the model (via `convertToModelMessages`).\n */\nexport function createViewImageTool(options?: ViewImageToolOptions) {\n const schema = {\n type: \"object\" as const,\n properties: {\n url: {\n type: \"string\",\n description: \"The URL of the image to display\",\n },\n },\n required: [\"url\"],\n };\n\n return tool({\n description:\n options?.description ??\n \"Display an image in the chat. Use this when you want to show the user an image from a URL.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n execute: async (args): Promise<ViewImageToolResult> => {\n const { url } = args as { url: string };\n return { url, displayed: true };\n },\n });\n}\n"],"mappings":"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","names":["import_ai","import_ai","import_ai"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/cache.ts","../src/core/tool-converter.ts","../src/core/http-executor.ts","../src/core/skill-parser.ts","../src/tools/skills.ts","../src/core/client.ts","../src/tools/bash.ts","../src/tools/view-image.ts","../src/tools/edit-file.ts","../src/tools/grep.ts","../src/tools/find.ts","../src/tools/read-file-range.ts","../src/tools/append-file.ts","../src/tools/http-request.ts"],"sourcesContent":["export { supyagent } from \"./core/client.js\";\nexport type {\n SupyagentOptions,\n SupyagentClient,\n ScopedClient,\n ToolFilterOptions,\n ToolMetadata,\n OpenAITool,\n ToolsResponse,\n SkillsOptions,\n SkillsResult,\n ParsedSkill,\n ParsedSkillsDocument,\n MeOptions,\n MeResponse,\n // Tool discovery\n ScoredTool,\n ToolSearchResponse,\n ToolListResponse,\n // Connected accounts\n ConnectedAccount,\n ConnectedAccountWithIntegrations,\n AccountIntegration,\n AccountIntegrationDetail,\n CreateAccountOptions,\n UpdateAccountOptions,\n ListAccountsOptions,\n ListAccountsResponse,\n ConnectOptions,\n ConnectSession,\n ConnectSessionStatus,\n AccountsClient,\n} from \"./core/types.js\";\nexport { createBashTool } from \"./tools/bash.js\";\nexport type { BashToolOptions, BashToolResult } from \"./tools/bash.js\";\nexport { createViewImageTool } from \"./tools/view-image.js\";\nexport type { ViewImageToolOptions, ViewImageToolResult } from \"./tools/view-image.js\";\nexport { parseSkillsMarkdown, buildSkillsSystemPrompt, findSkill } from \"./core/skill-parser.js\";\nexport { createLoadSkillTool, createApiCallTool } from \"./tools/skills.js\";\nexport { createEditFileTool } from \"./tools/edit-file.js\";\nexport type { EditFileToolOptions, EditFileToolResult } from \"./tools/edit-file.js\";\nexport { createGrepTool } from \"./tools/grep.js\";\nexport type { GrepToolOptions, GrepToolResult } from \"./tools/grep.js\";\nexport { createFindTool } from \"./tools/find.js\";\nexport type { FindToolOptions, FindToolResult } from \"./tools/find.js\";\nexport { createReadFileRangeTool } from \"./tools/read-file-range.js\";\nexport type { ReadFileRangeToolOptions, ReadFileRangeToolResult } from \"./tools/read-file-range.js\";\nexport { createAppendFileTool } from \"./tools/append-file.js\";\nexport type { AppendFileToolOptions, AppendFileToolResult } from \"./tools/append-file.js\";\nexport { createHttpRequestTool } from \"./tools/http-request.js\";\nexport type { HttpRequestToolOptions, HttpRequestToolResult } from \"./tools/http-request.js\";\n","interface CacheEntry<T> {\n data: T;\n expiresAt: number;\n}\n\nexport class TTLCache<T> {\n private store = new Map<string, CacheEntry<T>>();\n\n get(key: string): T | undefined {\n const entry = this.store.get(key);\n if (!entry) return undefined;\n if (Date.now() > entry.expiresAt) {\n this.store.delete(key);\n return undefined;\n }\n return entry.data;\n }\n\n set(key: string, data: T, ttlSeconds: number): void {\n this.store.set(key, {\n data,\n expiresAt: Date.now() + ttlSeconds * 1000,\n });\n }\n\n clear(): void {\n this.store.clear();\n }\n}\n","import { tool, jsonSchema } from \"ai\";\nimport type { OpenAITool } from \"./types.js\";\nimport { createExecutor } from \"./http-executor.js\";\n\n/**\n * Converts an array of OpenAI-format tools from the supyagent API\n * into a Record of AI SDK tool() instances ready for streamText/generateText.\n */\nexport function convertTools(\n tools: OpenAITool[],\n baseUrl: string,\n apiKey: string,\n accountId?: string,\n): Record<string, import(\"ai\").Tool> {\n const result: Record<string, import(\"ai\").Tool> = {};\n\n for (const t of tools) {\n const { name, description, parameters } = t.function;\n const metadata = t.metadata;\n\n result[name] = tool({\n description,\n inputSchema: jsonSchema(parameters as Parameters<typeof jsonSchema>[0]),\n execute: async (args) => createExecutor(metadata, baseUrl, apiKey, accountId)(args as Record<string, unknown>),\n });\n }\n\n return result;\n}\n\n/**\n * Filter tools by provider, service, or tool name.\n */\nexport function filterTools(\n tools: OpenAITool[],\n options: { only?: string[]; except?: string[] }\n): OpenAITool[] {\n let filtered = tools;\n\n if (options.only && options.only.length > 0) {\n const onlySet = new Set(options.only.map((s) => s.toLowerCase()));\n filtered = filtered.filter((t) => {\n const name = t.function.name.toLowerCase();\n const provider = t.metadata.provider.toLowerCase();\n const service = t.metadata.service.toLowerCase();\n return onlySet.has(name) || onlySet.has(provider) || onlySet.has(service);\n });\n }\n\n if (options.except && options.except.length > 0) {\n const exceptSet = new Set(options.except.map((s) => s.toLowerCase()));\n filtered = filtered.filter((t) => {\n const name = t.function.name.toLowerCase();\n const provider = t.metadata.provider.toLowerCase();\n const service = t.metadata.service.toLowerCase();\n return (\n !exceptSet.has(name) &&\n !exceptSet.has(provider) &&\n !exceptSet.has(service)\n );\n });\n }\n\n return filtered;\n}\n","import type { ToolMetadata } from \"./types.js\";\n\n/**\n * Creates an execute function for a tool that calls the supyagent API.\n *\n * Handles:\n * - Path parameter substitution (e.g., {messageId} in /api/v1/gmail/messages/{messageId})\n * - GET/DELETE: remaining args → query string\n * - POST/PUT/PATCH: merge bodyDefaults + remaining args → JSON body\n */\nexport function createExecutor(\n metadata: ToolMetadata,\n baseUrl: string,\n apiKey: string,\n accountId?: string,\n): (args: Record<string, unknown>) => Promise<unknown> {\n return async (args: Record<string, unknown>) => {\n const { method, path, bodyDefaults } = metadata;\n\n // Extract path parameters and substitute into the path\n const remainingArgs = { ...args };\n let resolvedPath = path;\n\n const pathParams = path.match(/\\{(\\w+)\\}/g);\n if (pathParams) {\n for (const param of pathParams) {\n const paramName = param.slice(1, -1);\n if (paramName in remainingArgs) {\n resolvedPath = resolvedPath.replace(\n param,\n encodeURIComponent(String(remainingArgs[paramName]))\n );\n delete remainingArgs[paramName];\n }\n }\n\n // Fallback: LLMs often send { id } instead of { messageId }, { eventId }, etc.\n // because list responses return objects with an `id` field.\n // For any unresolved {fooId} param, try `id` from the args (once only).\n if (\"id\" in remainingArgs && resolvedPath.includes(\"{\")) {\n const unresolved = resolvedPath.match(/\\{(\\w+)\\}/g);\n if (unresolved) {\n for (const param of unresolved) {\n const paramName = param.slice(1, -1);\n if (paramName.toLowerCase().endsWith(\"id\")) {\n resolvedPath = resolvedPath.replace(\n param,\n encodeURIComponent(String(remainingArgs.id))\n );\n delete remainingArgs.id;\n break; // consume `id` only once\n }\n }\n }\n }\n }\n\n let url = `${baseUrl}${resolvedPath}`;\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n ...(accountId ? { \"X-Account-Id\": accountId } : {}),\n },\n };\n\n if (method === \"GET\" || method === \"DELETE\") {\n // Remaining args go as query parameters\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(remainingArgs)) {\n if (value !== undefined && value !== null) {\n params.set(key, String(value));\n }\n }\n const qs = params.toString();\n if (qs) url += `?${qs}`;\n } else {\n // POST/PUT/PATCH: merge bodyDefaults with remaining args\n const body = { ...bodyDefaults, ...remainingArgs };\n fetchOptions.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, fetchOptions);\n const data = await response.json();\n return data;\n };\n}\n","import type { ParsedSkill, ParsedSkillsDocument } from \"./types.js\";\n\n/**\n * Parse YAML frontmatter from the beginning of a markdown document.\n */\nfunction parseFrontmatter(markdown: string): {\n frontmatter: { name: string; description: string };\n body: string;\n} {\n const match = markdown.match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/);\n if (!match) {\n return {\n frontmatter: { name: \"supyagent-skills\", description: \"\" },\n body: markdown,\n };\n }\n\n const [, yamlBlock, body] = match;\n const fields: Record<string, string> = {};\n for (const line of yamlBlock!.split(\"\\n\")) {\n const colonIndex = line.indexOf(\":\");\n if (colonIndex > 0) {\n const key = line.slice(0, colonIndex).trim();\n const value = line.slice(colonIndex + 1).trim();\n fields[key] = value;\n }\n }\n\n return {\n frontmatter: {\n name: fields.name || \"supyagent-skills\",\n description: fields.description || \"\",\n },\n body: body!,\n };\n}\n\n/**\n * Extract the skill name from a section starting with `# Name`.\n */\nfunction extractSkillName(section: string): string {\n const match = section.match(/^#\\s+(.+)/m);\n return match ? match[1].trim() : \"Unknown\";\n}\n\n/**\n * Parse the aggregated skills markdown into structured sections.\n */\nexport function parseSkillsMarkdown(markdown: string): ParsedSkillsDocument {\n const { frontmatter, body } = parseFrontmatter(markdown);\n\n // Split body on \\n---\\n (the section separator)\n const parts = body.split(/\\n---\\n/);\n\n // First part is the preamble (general header info)\n const preamble = (parts[0] || \"\").trim();\n\n // Remaining parts are individual skill sections\n const skills: ParsedSkill[] = [];\n for (let i = 1; i < parts.length; i++) {\n const content = parts[i]!.trim();\n if (!content) continue;\n const name = extractSkillName(content);\n skills.push({ name, content });\n }\n\n return { frontmatter, preamble, skills };\n}\n\n/**\n * Build a concise system prompt from parsed skills.\n * Lists available skills with one-line summaries, not full docs.\n */\nexport function buildSkillsSystemPrompt(\n doc: ParsedSkillsDocument,\n): string {\n if (doc.skills.length === 0) {\n return \"No skills are currently available. The user has no connected integrations.\";\n }\n\n const skillList = doc.skills.map((s) => `- **${s.name}**`).join(\"\\n\");\n\n return `You have access to the following skills via Supyagent:\n\n${skillList}\n\nTo use a skill:\n1. Call \\`loadSkill\\` with the skill name to get detailed API documentation\n2. Call \\`apiCall\\` to make authenticated HTTP requests to the API endpoints described in the skill docs\n\nAvailable skill names: ${doc.skills.map((s) => s.name).join(\", \")}`;\n}\n\n/**\n * Find a skill by name (case-insensitive).\n */\nexport function findSkill(\n skills: ParsedSkill[],\n name: string,\n): ParsedSkill | null {\n const normalized = name.toLowerCase().trim();\n return (\n skills.find((s) => s.name.toLowerCase() === normalized) ??\n skills.find((s) => s.name.toLowerCase().includes(normalized)) ??\n null\n );\n}\n","import { tool, jsonSchema } from \"ai\";\nimport type { ParsedSkill } from \"../core/types.js\";\nimport { findSkill } from \"../core/skill-parser.js\";\n\n/**\n * Create the loadSkill tool.\n * Returns detailed documentation for a specific skill.\n */\nexport function createLoadSkillTool(skills: ParsedSkill[]) {\n const availableNames = skills.map((s) => s.name).join(\", \");\n\n return tool({\n description: `Load detailed API documentation for a specific skill. Available skills: ${availableNames}. Call this before using apiCall to understand the available endpoints, parameters, and examples.`,\n inputSchema: jsonSchema({\n type: \"object\",\n properties: {\n name: {\n type: \"string\",\n description: `The skill name to load. Available: ${availableNames}`,\n },\n },\n required: [\"name\"],\n } as Parameters<typeof jsonSchema>[0]),\n execute: async (args) => {\n const { name } = args as { name: string };\n const skill = findSkill(skills, name);\n\n if (!skill) {\n return {\n error: `Skill \"${name}\" not found. Available skills: ${availableNames}`,\n };\n }\n\n return {\n name: skill.name,\n documentation: skill.content,\n };\n },\n });\n}\n\nconst VALID_METHODS = new Set([\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"]);\n\n/**\n * Create the apiCall tool.\n * Makes authenticated HTTP requests to the Supyagent API.\n */\nexport function createApiCallTool(baseUrl: string, apiKey: string, accountId?: string) {\n return tool({\n description:\n \"Make an authenticated HTTP request to the Supyagent API. Use loadSkill first to understand available endpoints. The authorization header and base URL are handled automatically — only provide the path (e.g., /api/v1/google/gmail/messages).\",\n inputSchema: jsonSchema({\n type: \"object\",\n properties: {\n method: {\n type: \"string\",\n enum: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\"],\n description: \"HTTP method\",\n },\n path: {\n type: \"string\",\n description:\n 'API path starting with /api/v1/ (e.g., \"/api/v1/google/gmail/messages\")',\n },\n body: {\n type: \"object\",\n description: \"Request body for POST/PUT/PATCH requests\",\n additionalProperties: true,\n },\n params: {\n type: \"object\",\n description: \"Query parameters\",\n additionalProperties: true,\n },\n },\n required: [\"method\", \"path\"],\n } as Parameters<typeof jsonSchema>[0]),\n execute: async (args) => {\n const {\n method: rawMethod,\n path,\n body,\n params,\n } = args as {\n method: string;\n path: string;\n body?: Record<string, unknown>;\n params?: Record<string, unknown>;\n };\n\n const method = rawMethod.toUpperCase();\n\n if (!VALID_METHODS.has(method)) {\n return { error: `Invalid HTTP method: ${method}` };\n }\n\n if (!path.startsWith(\"/api/v1/\")) {\n return { error: `Path must start with /api/v1/. Got: ${path}` };\n }\n\n let url = `${baseUrl}${path}`;\n\n if (params && Object.keys(params).length > 0) {\n const searchParams = new URLSearchParams();\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n searchParams.set(key, String(value));\n }\n }\n const qs = searchParams.toString();\n if (qs) url += `?${qs}`;\n }\n\n const fetchOptions: RequestInit = {\n method,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n ...(accountId ? { \"X-Account-Id\": accountId } : {}),\n },\n };\n\n if (body && method !== \"GET\" && method !== \"DELETE\") {\n fetchOptions.body = JSON.stringify(body);\n }\n\n try {\n const response = await fetch(url, fetchOptions);\n const data = await response.json();\n\n if (!response.ok) {\n return { error: `API returned ${response.status}`, details: data };\n }\n\n return data;\n } catch (err) {\n return {\n error: `Request failed: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n },\n });\n}\n","import type {\n SupyagentOptions,\n SupyagentClient,\n ScopedClient,\n ToolFilterOptions,\n ToolsResponse,\n ToolSearchResponse,\n ToolListResponse,\n SkillsOptions,\n SkillsResult,\n ParsedSkillsDocument,\n MeOptions,\n MeResponse,\n AccountsClient,\n ConnectedAccount,\n ConnectedAccountWithIntegrations,\n ListAccountsResponse,\n ConnectSession,\n ConnectSessionStatus,\n AccountIntegrationDetail,\n CreateAccountOptions,\n UpdateAccountOptions,\n ListAccountsOptions,\n ConnectOptions,\n} from \"./types.js\";\nimport { TTLCache } from \"./cache.js\";\nimport { convertTools, filterTools } from \"./tool-converter.js\";\nimport { parseSkillsMarkdown, buildSkillsSystemPrompt } from \"./skill-parser.js\";\nimport { createLoadSkillTool, createApiCallTool } from \"../tools/skills.js\";\n\nconst DEFAULT_BASE_URL = \"https://app.supyagent.com\";\nconst CACHE_KEY = \"tools\";\n\ntype Fetcher = (path: string, init?: RequestInit) => Promise<Response>;\n\nfunction createFetcher(baseUrl: string, apiKey: string, accountId?: string): Fetcher {\n return async function fetcher(path: string, init?: RequestInit) {\n const res = await fetch(`${baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n ...(accountId ? { \"X-Account-Id\": accountId } : {}),\n ...((init?.headers as Record<string, string>) ?? {}),\n },\n });\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Supyagent API error (${res.status}): ${text}`);\n }\n return res;\n };\n}\n\nfunction createDataPlane(\n fetcher: Fetcher,\n baseUrl: string,\n apiKey: string,\n accountId?: string,\n) {\n const toolsCache = new TTLCache<ToolsResponse>();\n const skillsCache = new TTLCache<ParsedSkillsDocument>();\n const meCache = new TTLCache<MeResponse>();\n\n return {\n async tools(filterOptions?: ToolFilterOptions) {\n const cacheTTL = resolveCacheTTL(filterOptions?.cache);\n\n // Check cache\n let response = cacheTTL > 0 ? toolsCache.get(CACHE_KEY) : undefined;\n\n if (!response) {\n // Fetch from API\n const res = await fetcher(\"/api/v1/tools\", {\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n const json = await res.json();\n // API wraps response in { ok, data: { tools, base_url, total } }\n response = (json.data ?? json) as ToolsResponse;\n\n // Store in cache if TTL > 0\n if (cacheTTL > 0) {\n toolsCache.set(CACHE_KEY, response, cacheTTL);\n }\n }\n\n // Use API-reported base_url for tool execution\n const toolBaseUrl = response.base_url || baseUrl;\n\n // Guard against non-array tools (e.g., API returns empty or unexpected shape)\n const toolsArray = Array.isArray(response.tools) ? response.tools : [];\n\n // Filter\n const filtered = filterTools(toolsArray, {\n only: filterOptions?.only,\n except: filterOptions?.except,\n });\n\n // Convert to AI SDK tools\n return convertTools(filtered, toolBaseUrl, apiKey, accountId);\n },\n\n async skills(options?: SkillsOptions): Promise<SkillsResult> {\n const cacheTTL = resolveCacheTTL(options?.cache);\n\n let parsed = cacheTTL > 0 ? skillsCache.get(\"skills\") : undefined;\n\n if (!parsed) {\n const res = await fetcher(\"/api/v1/skills\");\n\n parsed = parseSkillsMarkdown(await res.text());\n\n if (cacheTTL > 0) {\n skillsCache.set(\"skills\", parsed, cacheTTL);\n }\n }\n\n return {\n systemPrompt: buildSkillsSystemPrompt(parsed),\n tools: {\n loadSkill: createLoadSkillTool(parsed.skills),\n apiCall: createApiCallTool(baseUrl, apiKey, accountId),\n },\n };\n },\n\n async me(options?: MeOptions): Promise<MeResponse> {\n const cacheTTL = resolveCacheTTL(options?.cache);\n\n let response = cacheTTL > 0 ? meCache.get(\"me\") : undefined;\n\n if (!response) {\n const res = await fetcher(\"/api/v1/me\");\n\n const json = await res.json();\n response = (json.data ?? json) as MeResponse;\n\n if (cacheTTL > 0) {\n meCache.set(\"me\", response, cacheTTL);\n }\n }\n\n return response;\n },\n\n async searchTools(query: string): Promise<ToolSearchResponse> {\n const res = await fetcher(`/api/v1/tools/search/${encodeURIComponent(query)}`);\n const json = await res.json();\n const data = (json.data ?? json) as ToolSearchResponse;\n return {\n tools: Array.isArray(data.tools) ? data.tools : [],\n total: data.total ?? 0,\n };\n },\n\n async toolsByProvider(provider: string): Promise<ToolListResponse> {\n const res = await fetcher(`/api/v1/tools/provider/${encodeURIComponent(provider)}`);\n const json = await res.json();\n const data = (json.data ?? json) as ToolListResponse;\n return {\n tools: Array.isArray(data.tools) ? data.tools : [],\n total: data.total ?? 0,\n };\n },\n\n async toolsByService(service: string): Promise<ToolListResponse> {\n const res = await fetcher(`/api/v1/tools/service/${encodeURIComponent(service)}`);\n const json = await res.json();\n const data = (json.data ?? json) as ToolListResponse;\n return {\n tools: Array.isArray(data.tools) ? data.tools : [],\n total: data.total ?? 0,\n };\n },\n };\n}\n\n/**\n * Create a supyagent client for fetching and converting tools.\n *\n * @example\n * ```ts\n * import { supyagent } from '@supyagent/sdk';\n *\n * const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });\n * const tools = await client.tools({ cache: 300 });\n * ```\n */\nexport function supyagent(options: SupyagentOptions): SupyagentClient {\n const { apiKey, baseUrl = DEFAULT_BASE_URL } = options;\n\n const fetcher = createFetcher(baseUrl, apiKey);\n const dataPlane = createDataPlane(fetcher, baseUrl, apiKey);\n\n async function apiCall<T>(\n method: string,\n path: string,\n body?: Record<string, unknown>,\n ): Promise<T> {\n const res = await fetcher(path, {\n method,\n ...(body ? { headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify(body) } : {}),\n });\n\n const json = await res.json();\n return (json.data ?? json) as T;\n }\n\n return {\n ...dataPlane,\n accounts: createAccountsClient(apiCall),\n asAccount(externalId: string): ScopedClient {\n const scopedFetcher = createFetcher(baseUrl, apiKey, externalId);\n const scopedDataPlane = createDataPlane(scopedFetcher, baseUrl, apiKey, externalId);\n return {\n accountId: externalId,\n ...scopedDataPlane,\n };\n },\n };\n}\n\nfunction createAccountsClient(\n apiCall: <T>(method: string, path: string, body?: Record<string, unknown>) => Promise<T>,\n): AccountsClient {\n function toAccount(raw: Record<string, unknown>): ConnectedAccount {\n return {\n id: raw.id as string,\n externalId: raw.external_id as string,\n displayName: (raw.display_name as string | null) ?? null,\n metadata: (raw.metadata as Record<string, unknown>) ?? {},\n createdAt: raw.created_at as string,\n };\n }\n\n function toIntegration(raw: Record<string, unknown>): {\n id: string;\n provider: string;\n status: string;\n connectedAt: string;\n } {\n return {\n id: raw.id as string,\n provider: raw.provider as string,\n status: raw.status as string,\n connectedAt: raw.connected_at as string,\n };\n }\n\n function toIntegrationDetail(raw: Record<string, unknown>): AccountIntegrationDetail {\n const services = (raw.enabled_services as Array<Record<string, unknown>>) ?? [];\n return {\n ...toIntegration(raw),\n enabledServices: services.map((s) => ({\n serviceName: s.service_name as string,\n isEnabled: s.is_enabled as boolean,\n })),\n };\n }\n\n return {\n async create(opts: CreateAccountOptions): Promise<ConnectedAccount> {\n const raw = await apiCall<Record<string, unknown>>(\"POST\", \"/api/v1/accounts\", {\n external_id: opts.externalId,\n ...(opts.displayName != null ? { display_name: opts.displayName } : {}),\n ...(opts.metadata != null ? { metadata: opts.metadata } : {}),\n });\n return toAccount(raw);\n },\n\n async list(opts?: ListAccountsOptions): Promise<ListAccountsResponse> {\n const params = new URLSearchParams();\n if (opts?.limit != null) params.set(\"limit\", String(opts.limit));\n if (opts?.offset != null) params.set(\"offset\", String(opts.offset));\n const qs = params.toString();\n const raw = await apiCall<Record<string, unknown>>(\n \"GET\",\n `/api/v1/accounts${qs ? `?${qs}` : \"\"}`,\n );\n return {\n accounts: ((raw.accounts as Array<Record<string, unknown>>) ?? []).map(toAccount),\n total: raw.total as number,\n limit: raw.limit as number,\n offset: raw.offset as number,\n };\n },\n\n async get(id: string): Promise<ConnectedAccountWithIntegrations> {\n const raw = await apiCall<Record<string, unknown>>(\"GET\", `/api/v1/accounts/${id}`);\n return {\n ...toAccount(raw),\n integrations: ((raw.integrations as Array<Record<string, unknown>>) ?? []).map(\n toIntegration,\n ),\n };\n },\n\n async update(id: string, opts: UpdateAccountOptions): Promise<ConnectedAccount> {\n const body: Record<string, unknown> = {};\n if (opts.displayName !== undefined) body.display_name = opts.displayName;\n if (opts.metadata !== undefined) body.metadata = opts.metadata;\n const raw = await apiCall<Record<string, unknown>>(\"PATCH\", `/api/v1/accounts/${id}`, body);\n return toAccount(raw);\n },\n\n async delete(id: string): Promise<{ deleted: true }> {\n return apiCall<{ deleted: true }>(\"DELETE\", `/api/v1/accounts/${id}`);\n },\n\n async connect(id: string, opts: ConnectOptions): Promise<ConnectSession> {\n const raw = await apiCall<Record<string, unknown>>(\n \"POST\",\n `/api/v1/accounts/${id}/connect`,\n {\n provider: opts.provider,\n redirect_url: opts.redirectUrl,\n ...(opts.scopes ? { scopes: opts.scopes } : {}),\n },\n );\n return {\n connectUrl: raw.connect_url as string,\n sessionId: raw.session_id as string,\n expiresAt: raw.expires_at as string,\n };\n },\n\n async getSession(id: string, sessionId: string): Promise<ConnectSessionStatus> {\n const raw = await apiCall<Record<string, unknown>>(\n \"GET\",\n `/api/v1/accounts/${id}/connect/${sessionId}`,\n );\n return {\n sessionId: raw.session_id as string,\n provider: raw.provider as string,\n status: raw.status as string,\n ...(raw.error ? { error: raw.error as string } : {}),\n createdAt: raw.created_at as string,\n expiresAt: raw.expires_at as string,\n };\n },\n\n async integrations(id: string): Promise<AccountIntegrationDetail[]> {\n const raw = await apiCall<Record<string, unknown>>(\n \"GET\",\n `/api/v1/accounts/${id}/integrations`,\n );\n return ((raw.integrations as Array<Record<string, unknown>>) ?? []).map(\n toIntegrationDetail,\n );\n },\n\n async disconnect(id: string, provider: string): Promise<{ deleted: true; provider: string }> {\n return apiCall<{ deleted: true; provider: string }>(\n \"DELETE\",\n `/api/v1/accounts/${id}/integrations/${provider}`,\n );\n },\n };\n}\n\nfunction resolveCacheTTL(cache?: boolean | number): number {\n if (cache === true) return 60;\n if (typeof cache === \"number\") return cache;\n return 0;\n}\n","import { tool, jsonSchema } from \"ai\";\nimport { exec, type ExecException } from \"node:child_process\";\n\nconst MAX_OUTPUT = 30_000;\nconst DEFAULT_TIMEOUT = 30_000; // 30 seconds\n\n// ── Environment sanitization ────────────────────────────────────────────────\n\nconst SECRET_PATTERNS = [\n /key/i, /secret/i, /token/i, /password/i, /credential/i,\n /auth/i, /private/i, /api_key/i, /apikey/i,\n /^AWS_/i, /^AZURE_/i, /^GCP_/i, /^GITHUB_/i,\n /^DATABASE_URL$/i, /^ENCRYPTION_/i, /^SUPABASE_/i,\n];\n\nconst SAFE_VARS = new Set([\n \"PATH\", \"HOME\", \"USER\", \"SHELL\", \"LANG\", \"LC_ALL\", \"LC_CTYPE\",\n \"TERM\", \"EDITOR\", \"VISUAL\", \"TMPDIR\", \"TMP\", \"TEMP\",\n \"NODE_ENV\", \"NODE_PATH\", \"NODE_OPTIONS\",\n \"NPM_CONFIG_PREFIX\", \"NVM_DIR\", \"NVM_BIN\", \"NVM_INC\",\n \"XDG_CONFIG_HOME\", \"XDG_DATA_HOME\", \"XDG_CACHE_HOME\",\n \"COLORTERM\", \"FORCE_COLOR\", \"NO_COLOR\",\n \"COLUMNS\", \"LINES\", \"SHLVL\", \"PWD\", \"OLDPWD\", \"LOGNAME\",\n \"HOSTNAME\", \"HOSTTYPE\", \"OSTYPE\", \"MACHTYPE\",\n]);\n\nfunction sanitizeEnv(\n env: NodeJS.ProcessEnv,\n opts?: { include?: string[]; exclude?: string[] }\n): Record<string, string> {\n const result: Record<string, string> = {};\n const includeSet = opts?.include ? new Set(opts.include) : null;\n const excludeSet = opts?.exclude ? new Set(opts.exclude) : null;\n\n for (const [key, value] of Object.entries(env)) {\n if (value === undefined) continue;\n if (excludeSet?.has(key)) continue;\n if (includeSet?.has(key)) { result[key] = value; continue; }\n if (SAFE_VARS.has(key)) { result[key] = value; continue; }\n if (SECRET_PATTERNS.some(p => p.test(key))) continue;\n result[key] = value;\n }\n\n result.TERM = \"dumb\";\n return result;\n}\n\nfunction buildEnv(\n policy: BashToolOptions[\"env\"],\n opts?: BashToolOptions\n): Record<string, string> {\n if (typeof policy === \"object\" && policy !== null) {\n return { ...policy, TERM: \"dumb\" };\n }\n switch (policy) {\n case \"inherit\":\n return { ...process.env, TERM: \"dumb\" } as Record<string, string>;\n case \"none\":\n return {\n PATH: process.env.PATH ?? \"/usr/local/bin:/usr/bin:/bin\",\n HOME: process.env.HOME ?? \"/tmp\",\n TERM: \"dumb\",\n };\n case \"safe\":\n default:\n return sanitizeEnv(process.env, {\n include: opts?.envInclude,\n exclude: opts?.envExclude,\n });\n }\n}\n\n// ── Command safety ──────────────────────────────────────────────────────────\n\ntype CommandSafety = \"safe\" | \"dangerous\" | \"unknown\";\n\nconst SAFE_COMMANDS = new Set([\n \"cat\", \"cd\", \"cut\", \"echo\", \"expr\", \"false\", \"grep\", \"egrep\", \"fgrep\",\n \"head\", \"id\", \"ls\", \"nl\", \"paste\", \"pwd\", \"rev\", \"seq\", \"stat\",\n \"tail\", \"tr\", \"true\", \"uname\", \"uniq\", \"wc\", \"which\", \"whoami\",\n \"date\", \"env\", \"printenv\", \"hostname\", \"df\", \"du\", \"file\",\n \"find\", \"rg\", \"tree\", \"less\", \"more\", \"sort\",\n \"diff\", \"md5sum\", \"sha256sum\", \"base64\", \"xxd\", \"hexdump\",\n \"man\", \"help\", \"type\", \"command\", \"test\", \"basename\", \"dirname\",\n \"realpath\", \"readlink\", \"tee\", \"xargs\", \"jq\", \"yq\",\n]);\n\nconst SAFE_GIT_SUBCOMMANDS = new Set([\n \"status\", \"log\", \"diff\", \"show\", \"branch\", \"tag\", \"remote\",\n \"stash\", \"describe\", \"shortlog\", \"blame\", \"reflog\", \"rev-parse\",\n \"ls-files\", \"ls-tree\", \"cat-file\", \"rev-list\", \"name-rev\",\n]);\n\nconst DANGEROUS_PATTERNS = [\n /rm\\s+(-[^\\s]*f|-[^\\s]*r|--force|--recursive).*\\//,\n /:\\(\\)\\s*\\{\\s*:\\|:&\\s*\\};:/,\n />\\s*\\/dev\\/sd/,\n /mkfs\\./,\n /dd\\s+.*of=\\/dev\\//,\n /shutdown|reboot|halt|poweroff/,\n /chmod\\s+777\\s+\\//,\n /curl.*\\|\\s*(ba)?sh/,\n /wget.*\\|\\s*(ba)?sh/,\n];\n\nfunction classifyCommand(\n command: string,\n extraSafe?: Set<string>,\n extraDeny?: RegExp[],\n): CommandSafety {\n const trimmed = command.trim();\n\n // Check dangerous patterns first\n if (DANGEROUS_PATTERNS.some(p => p.test(trimmed))) return \"dangerous\";\n if (extraDeny?.some(p => p.test(trimmed))) return \"dangerous\";\n\n // Extract base command (strip leading env var assignments)\n const stripped = trimmed.replace(/^(\\w+=\\S+\\s+)*/, \"\");\n const parts = stripped.split(/\\s+/);\n const base = parts[0]?.replace(/^.*\\//, \"\"); // strip path prefix\n\n if (!base) return \"unknown\";\n\n // Check git subcommands\n if (base === \"git\") {\n const sub = parts[1];\n if (sub && SAFE_GIT_SUBCOMMANDS.has(sub)) return \"safe\";\n return \"unknown\";\n }\n\n if (SAFE_COMMANDS.has(base)) return \"safe\";\n if (extraSafe?.has(base)) return \"safe\";\n\n return \"unknown\";\n}\n\n// ── Types ───────────────────────────────────────────────────────────────────\n\nexport interface BashToolOptions {\n /** Working directory for commands. Defaults to `process.cwd()`. */\n cwd?: string;\n /** Command timeout in milliseconds. Defaults to 30000 (30s). Max 600000 (10m). */\n timeout?: number;\n /** Maximum output length in characters. Defaults to 30000. */\n maxOutput?: number;\n\n /**\n * Command approval policy. Default: \"auto\".\n * - `\"auto\"`: Safe read-only commands (ls, cat, grep...) auto-execute; others require user approval\n * - `\"always\"`: Every command requires user approval before execution\n * - `\"never\"`: No approval required (use only in trusted environments)\n * - `function`: Custom approval logic — return `true` to require approval\n */\n approval?: \"auto\" | \"always\" | \"never\" | ((command: string) => boolean | Promise<boolean>);\n\n /**\n * Environment variable policy. Default: \"safe\".\n * - `\"safe\"`: Strip vars matching secret patterns (KEY, TOKEN, SECRET, PASSWORD, etc.)\n * - `\"inherit\"`: Pass full process.env (NOT recommended for production)\n * - `\"none\"`: Minimal env (PATH, HOME, TERM only)\n * - `Record<string,string>`: Explicit env vars to use\n */\n env?: \"safe\" | \"inherit\" | \"none\" | Record<string, string>;\n\n /** Extra env vars to include even if they match secret patterns. Only used with `env: \"safe\"`. */\n envInclude?: string[];\n /** Extra env vars to exclude beyond default secret patterns. Only used with `env: \"safe\"`. */\n envExclude?: string[];\n\n /** Additional commands to treat as safe (auto-execute without approval in \"auto\" mode). */\n allowCommands?: string[];\n /** Additional patterns to block (never execute, even if approved). */\n denyPatterns?: RegExp[];\n}\n\nexport interface BashToolResult {\n stdout: string;\n stderr: string;\n exitCode: number;\n durationMs: number;\n timedOut?: boolean;\n}\n\n// ── Tool factory ────────────────────────────────────────────────────────────\n\n/**\n * Create a bash tool that executes shell commands on the server.\n *\n * By default, uses \"auto\" approval (safe commands run immediately, others\n * require user approval) and \"safe\" env isolation (strips secret-like\n * environment variables).\n *\n * @example\n * ```ts\n * import { supyagent, createBashTool } from '@supyagent/sdk';\n *\n * const client = supyagent({ apiKey: process.env.SUPYAGENT_API_KEY! });\n * const supyagentTools = await client.tools({ cache: 300 });\n *\n * const tools = {\n * ...supyagentTools,\n * bash: createBashTool({ cwd: '/path/to/project' }),\n * };\n * ```\n */\nexport function createBashTool(options?: BashToolOptions) {\n const cwd = options?.cwd ?? process.cwd();\n const timeout = Math.min(options?.timeout ?? DEFAULT_TIMEOUT, 600_000);\n const maxOutput = options?.maxOutput ?? MAX_OUTPUT;\n const approvalPolicy = options?.approval ?? \"auto\";\n\n const extraSafe = options?.allowCommands ? new Set(options.allowCommands) : undefined;\n const extraDeny = options?.denyPatterns;\n\n const execEnv = buildEnv(options?.env ?? \"safe\", options);\n\n const schema = {\n type: \"object\" as const,\n properties: {\n command: {\n type: \"string\",\n description: \"The bash command to execute\",\n },\n },\n required: [\"command\"],\n };\n\n // Resolve needsApproval based on policy\n const needsApproval =\n approvalPolicy === \"always\"\n ? true\n : approvalPolicy === \"never\"\n ? false\n : async (args: unknown) => {\n const { command } = args as { command: string };\n if (typeof approvalPolicy === \"function\") {\n return approvalPolicy(command);\n }\n // \"auto\" mode — safe commands pass, everything else needs approval\n const safety = classifyCommand(command, extraSafe, extraDeny);\n return safety !== \"safe\";\n };\n\n return tool({\n description:\n \"Execute a bash command on the server. Use this for running shell commands, scripts, package managers, git operations, file manipulation, and system tasks. Returns stdout, stderr, and exit code.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n needsApproval,\n execute: async (args): Promise<BashToolResult> => {\n const { command } = args as { command: string };\n\n // Block dangerous commands even if somehow approved\n if (\n DANGEROUS_PATTERNS.some(p => p.test(command)) ||\n extraDeny?.some(p => p.test(command))\n ) {\n return {\n stdout: \"\",\n stderr: \"Command blocked by safety policy\",\n exitCode: 126,\n durationMs: 0,\n };\n }\n\n const start = Date.now();\n\n return new Promise<BashToolResult>((resolve) => {\n const child = exec(\n command,\n {\n cwd,\n timeout,\n shell: \"/bin/bash\",\n maxBuffer: 10 * 1024 * 1024,\n env: execEnv,\n },\n (error: ExecException | null, stdout: string, stderr: string) => {\n const durationMs = Date.now() - start;\n const timedOut = error?.killed === true;\n const exitCode = timedOut\n ? 124\n : typeof error?.code === \"number\"\n ? error.code\n : error\n ? 1\n : 0;\n\n resolve({\n stdout: truncate(stdout, maxOutput),\n stderr: truncate(stderr, maxOutput),\n exitCode,\n durationMs,\n ...(timedOut ? { timedOut: true } : {}),\n });\n }\n );\n\n child.on(\"error\", () => {\n resolve({\n stdout: \"\",\n stderr: \"Failed to start process\",\n exitCode: 127,\n durationMs: Date.now() - start,\n });\n });\n });\n },\n });\n}\n\nfunction truncate(str: string, max: number): string {\n if (str.length <= max) return str;\n const half = Math.floor(max / 2) - 50;\n return (\n str.slice(0, half) +\n `\\n\\n... (${str.length - max} characters truncated) ...\\n\\n` +\n str.slice(-half)\n );\n}\n","import { tool, jsonSchema } from \"ai\";\n\nexport interface ViewImageToolOptions {\n /**\n * Custom description for the tool.\n * @default \"Display an image in the chat. Use this when you want to show the user an image from a URL.\"\n */\n description?: string;\n}\n\nexport interface ViewImageToolResult {\n url: string;\n displayed: true;\n}\n\n/**\n * Create a viewImage tool that the agent can call to display an image in the chat.\n *\n * On the client side, pair this with the `useViewImageEffect` hook (or equivalent logic)\n * to inject the image as a `FileUIPart` into the conversation. This ensures the image\n * is visible to both the user (rendered as `<img>`) and the model (via `convertToModelMessages`).\n */\nexport function createViewImageTool(options?: ViewImageToolOptions) {\n const schema = {\n type: \"object\" as const,\n properties: {\n url: {\n type: \"string\",\n description: \"The URL of the image to display\",\n },\n },\n required: [\"url\"],\n };\n\n return tool({\n description:\n options?.description ??\n \"Display an image in the chat. Use this when you want to show the user an image from a URL.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n execute: async (args): Promise<ViewImageToolResult> => {\n const { url } = args as { url: string };\n return { url, displayed: true };\n },\n });\n}\n","import { tool, jsonSchema } from \"ai\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nexport interface EditFileToolOptions {\n /** Base directory for resolving relative paths. Defaults to `process.cwd()`. */\n cwd?: string;\n /** Maximum file size in bytes that can be edited. Defaults to 1MB. */\n maxFileSize?: number;\n}\n\nexport interface EditFileToolResult {\n path: string;\n replacements: number;\n}\n\n/**\n * Create an editFile tool that patches files using search-and-replace.\n *\n * Unlike a full-file write, this lets the LLM send only the changed sections,\n * saving tokens and reducing the risk of accidentally dropping content.\n *\n * @example\n * ```ts\n * import { createEditFileTool } from '@supyagent/sdk';\n *\n * const tools = {\n * editFile: createEditFileTool({ cwd: '/path/to/project' }),\n * };\n * ```\n */\nexport function createEditFileTool(options?: EditFileToolOptions) {\n const cwd = options?.cwd ?? process.cwd();\n const maxFileSize = options?.maxFileSize ?? 1_048_576;\n\n const schema = {\n type: \"object\" as const,\n properties: {\n path: {\n type: \"string\",\n description:\n \"File path to edit (absolute or relative to working directory)\",\n },\n edits: {\n type: \"array\",\n description:\n \"Array of search-and-replace operations applied sequentially. Each edit replaces the first occurrence of oldText with newText.\",\n items: {\n type: \"object\",\n properties: {\n oldText: {\n type: \"string\",\n description: \"The exact text to find in the file\",\n },\n newText: {\n type: \"string\",\n description: \"The replacement text\",\n },\n },\n required: [\"oldText\", \"newText\"],\n },\n },\n },\n required: [\"path\", \"edits\"],\n };\n\n return tool({\n description:\n \"Edit a file by applying one or more search-and-replace operations. Each edit replaces the first occurrence of oldText with newText. More efficient than rewriting entire files — only send the changed parts. Returns an error with the current file content if any oldText is not found.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n execute: async (args): Promise<EditFileToolResult | { error: string; currentContent?: string }> => {\n const { path: filePath, edits } = args as {\n path: string;\n edits: Array<{ oldText: string; newText: string }>;\n };\n\n const fullPath = resolve(cwd, filePath);\n\n let content: string;\n try {\n const buf = await readFile(fullPath);\n if (buf.length > maxFileSize) {\n return { error: `File too large (${buf.length} bytes). Max: ${maxFileSize} bytes.` };\n }\n content = buf.toString(\"utf-8\");\n } catch (err: unknown) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n return { error: `File not found: ${filePath}` };\n }\n return { error: `Failed to read file: ${(err as Error).message}` };\n }\n\n let replacements = 0;\n for (const edit of edits) {\n const idx = content.indexOf(edit.oldText);\n if (idx === -1) {\n return {\n error: `oldText not found in file — it may have been modified. Re-read the file and retry.\\n\\nSearched for:\\n${edit.oldText}`,\n currentContent: content,\n };\n }\n content = content.slice(0, idx) + edit.newText + content.slice(idx + edit.oldText.length);\n replacements++;\n }\n\n await writeFile(fullPath, content, \"utf-8\");\n return { path: filePath, replacements };\n },\n });\n}\n","import { tool, jsonSchema } from \"ai\";\nimport { exec } from \"node:child_process\";\nimport { resolve } from \"node:path\";\n\nconst MAX_OUTPUT = 30_000;\nconst DEFAULT_TIMEOUT = 15_000;\n\nexport interface GrepToolOptions {\n /** Base directory for searching. Defaults to `process.cwd()`. */\n cwd?: string;\n /** Timeout in milliseconds. Defaults to 15000 (15s). */\n timeout?: number;\n /** Maximum output length in characters. Defaults to 30000. */\n maxOutput?: number;\n}\n\nexport interface GrepToolResult {\n matches: string;\n matchCount: number;\n truncated: boolean;\n}\n\n/**\n * Create a grep tool for searching file contents by pattern.\n *\n * Uses `grep -rn` (or `rg` if available) under the hood.\n * Returns matching lines with file paths and line numbers.\n *\n * @example\n * ```ts\n * import { createGrepTool } from '@supyagent/sdk';\n *\n * const tools = {\n * grep: createGrepTool({ cwd: '/path/to/project' }),\n * };\n * ```\n */\nexport function createGrepTool(options?: GrepToolOptions) {\n const cwd = options?.cwd ?? process.cwd();\n const timeout = options?.timeout ?? DEFAULT_TIMEOUT;\n const maxOutput = options?.maxOutput ?? MAX_OUTPUT;\n\n const schema = {\n type: \"object\" as const,\n properties: {\n pattern: {\n type: \"string\",\n description: \"Search pattern (regular expression)\",\n },\n path: {\n type: \"string\",\n description:\n \"File or directory to search in (relative to working directory). Defaults to current directory.\",\n },\n include: {\n type: \"string\",\n description:\n 'Glob pattern to filter files, e.g. \"*.ts\", \"*.{js,jsx}\". Only matching files are searched.',\n },\n ignoreCase: {\n type: \"boolean\",\n description: \"Case-insensitive search. Defaults to false.\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of matching lines to return. Defaults to 100.\",\n },\n },\n required: [\"pattern\"],\n };\n\n return tool({\n description:\n \"Search file contents for a pattern (regular expression). Returns matching lines with file paths and line numbers. Useful for finding function definitions, usages, imports, config values, and more.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n execute: async (args): Promise<GrepToolResult | { error: string }> => {\n const {\n pattern,\n path: searchPath,\n include,\n ignoreCase,\n maxResults,\n } = args as {\n pattern: string;\n path?: string;\n include?: string;\n ignoreCase?: boolean;\n maxResults?: number;\n };\n\n const target = resolve(cwd, searchPath ?? \".\");\n const limit = maxResults ?? 100;\n\n // Build command — prefer rg if available, fallback to grep\n const rgArgs = [\n \"--no-heading\",\n \"--line-number\",\n \"--color=never\",\n `-m ${limit}`,\n ];\n if (ignoreCase) rgArgs.push(\"-i\");\n if (include) rgArgs.push(`--glob '${include}'`);\n\n const grepArgs = [\n \"-rn\",\n \"--color=never\",\n `-m ${limit}`,\n ];\n if (ignoreCase) grepArgs.push(\"-i\");\n if (include) grepArgs.push(`--include='${include}'`);\n\n // Escape pattern for shell\n const escaped = pattern.replace(/'/g, \"'\\\\''\");\n\n const command =\n `rg ${rgArgs.join(\" \")} '${escaped}' '${target}' 2>/dev/null || ` +\n `grep ${grepArgs.join(\" \")} '${escaped}' '${target}' 2>/dev/null`;\n\n return new Promise<GrepToolResult | { error: string }>((resolvePromise) => {\n exec(\n command,\n {\n cwd,\n timeout,\n maxBuffer: 10 * 1024 * 1024,\n env: { ...process.env, TERM: \"dumb\" },\n },\n (error, stdout) => {\n // grep exits 1 when no matches — that's fine\n if (error && error.code !== 1 && !error.killed) {\n resolvePromise({ error: `Search failed: ${error.message}` });\n return;\n }\n\n if (error?.killed) {\n resolvePromise({ error: \"Search timed out\" });\n return;\n }\n\n const output = stdout.trim();\n if (!output) {\n resolvePromise({ matches: \"\", matchCount: 0, truncated: false });\n return;\n }\n\n const truncated = output.length > maxOutput;\n const matches = truncated ? output.slice(0, maxOutput) + \"\\n... (truncated)\" : output;\n const matchCount = matches.split(\"\\n\").filter(Boolean).length;\n\n resolvePromise({ matches, matchCount, truncated });\n }\n );\n });\n },\n });\n}\n","import { tool, jsonSchema } from \"ai\";\nimport { exec } from \"node:child_process\";\nimport { resolve } from \"node:path\";\n\nconst DEFAULT_TIMEOUT = 15_000;\nconst MAX_OUTPUT = 30_000;\n\nexport interface FindToolOptions {\n /** Base directory for searching. Defaults to `process.cwd()`. */\n cwd?: string;\n /** Timeout in milliseconds. Defaults to 15000 (15s). */\n timeout?: number;\n /** Maximum output length in characters. Defaults to 30000. */\n maxOutput?: number;\n}\n\nexport interface FindToolResult {\n files: string[];\n count: number;\n truncated: boolean;\n}\n\n/**\n * Create a find tool for discovering files by name or glob pattern.\n *\n * Uses `find` under the hood with common ignore patterns\n * (node_modules, .git, dist, etc.) pre-configured.\n *\n * @example\n * ```ts\n * import { createFindTool } from '@supyagent/sdk';\n *\n * const tools = {\n * find: createFindTool({ cwd: '/path/to/project' }),\n * };\n * ```\n */\nexport function createFindTool(options?: FindToolOptions) {\n const cwd = options?.cwd ?? process.cwd();\n const timeout = options?.timeout ?? DEFAULT_TIMEOUT;\n const maxOutput = options?.maxOutput ?? MAX_OUTPUT;\n\n const schema = {\n type: \"object\" as const,\n properties: {\n pattern: {\n type: \"string\",\n description:\n 'File name or glob pattern to search for, e.g. \"*.ts\", \"config.json\", \"README*\"',\n },\n path: {\n type: \"string\",\n description:\n \"Directory to search in (relative to working directory). Defaults to current directory.\",\n },\n type: {\n type: \"string\",\n description:\n 'Filter by type: \"f\" for files only, \"d\" for directories only. Defaults to both.',\n enum: [\"f\", \"d\"],\n },\n maxDepth: {\n type: \"number\",\n description: \"Maximum directory depth to search. Defaults to no limit.\",\n },\n maxResults: {\n type: \"number\",\n description: \"Maximum number of results to return. Defaults to 200.\",\n },\n },\n required: [\"pattern\"],\n };\n\n const IGNORE_DIRS = [\n \"node_modules\", \".git\", \"dist\", \"build\", \".next\", \"__pycache__\",\n \".venv\", \"venv\", \".cache\", \"coverage\", \".turbo\",\n ];\n\n return tool({\n description:\n \"Find files and directories by name or glob pattern. Returns matching paths relative to the working directory. Automatically ignores common directories (node_modules, .git, dist, etc.).\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n execute: async (args): Promise<FindToolResult | { error: string }> => {\n const {\n pattern,\n path: searchPath,\n type: fileType,\n maxDepth,\n maxResults,\n } = args as {\n pattern: string;\n path?: string;\n type?: \"f\" | \"d\";\n maxDepth?: number;\n maxResults?: number;\n };\n\n const target = resolve(cwd, searchPath ?? \".\");\n const limit = maxResults ?? 200;\n\n // Build find command with ignore patterns\n const pruneExpr = IGNORE_DIRS\n .map(d => `-name '${d}' -prune`)\n .join(\" -o \");\n\n const parts = [\n `find '${target}'`,\n `\\\\( ${pruneExpr} \\\\)`,\n `-o -name '${pattern.replace(/'/g, \"'\\\\''\")}'`,\n ];\n\n if (fileType) parts.push(`-type ${fileType}`);\n parts.push(\"-print\");\n parts.push(`| head -n ${limit}`);\n\n if (maxDepth !== undefined) {\n // Insert maxdepth right after the target path\n parts.splice(1, 0, `-maxdepth ${maxDepth}`);\n }\n\n const command = parts.join(\" \");\n\n return new Promise<FindToolResult | { error: string }>((resolvePromise) => {\n exec(\n command,\n {\n cwd,\n timeout,\n maxBuffer: 10 * 1024 * 1024,\n env: { ...process.env, TERM: \"dumb\" },\n },\n (error, stdout) => {\n if (error?.killed) {\n resolvePromise({ error: \"Search timed out\" });\n return;\n }\n\n // find may return non-zero with permission errors — still return results\n const output = stdout.trim();\n if (!output) {\n resolvePromise({ files: [], count: 0, truncated: false });\n return;\n }\n\n const truncated = output.length > maxOutput;\n const raw = truncated ? output.slice(0, maxOutput) : output;\n const files = raw.split(\"\\n\").filter(Boolean);\n\n resolvePromise({\n files,\n count: files.length,\n truncated: truncated || files.length >= limit,\n });\n }\n );\n });\n },\n });\n}\n","import { tool, jsonSchema } from \"ai\";\nimport { open } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nconst DEFAULT_MAX_LINES = 200;\n\nexport interface ReadFileRangeToolOptions {\n /** Base directory for resolving relative paths. Defaults to `process.cwd()`. */\n cwd?: string;\n /** Maximum number of lines that can be requested at once. Defaults to 200. */\n maxLines?: number;\n}\n\nexport interface ReadFileRangeToolResult {\n path: string;\n content: string;\n startLine: number;\n endLine: number;\n totalLines: number;\n}\n\n/**\n * Create a readFileRange tool that reads specific line ranges from files.\n *\n * More token-efficient than reading entire files — especially useful\n * after a grep to read context around a match.\n *\n * @example\n * ```ts\n * import { createReadFileRangeTool } from '@supyagent/sdk';\n *\n * const tools = {\n * readFileRange: createReadFileRangeTool({ cwd: '/path/to/project' }),\n * };\n * ```\n */\nexport function createReadFileRangeTool(options?: ReadFileRangeToolOptions) {\n const cwd = options?.cwd ?? process.cwd();\n const maxLines = options?.maxLines ?? DEFAULT_MAX_LINES;\n\n const schema = {\n type: \"object\" as const,\n properties: {\n path: {\n type: \"string\",\n description:\n \"File path to read (absolute or relative to working directory)\",\n },\n startLine: {\n type: \"number\",\n description: \"First line to read (1-based, inclusive). Defaults to 1.\",\n },\n endLine: {\n type: \"number\",\n description:\n \"Last line to read (1-based, inclusive). Defaults to startLine + 200.\",\n },\n },\n required: [\"path\"],\n };\n\n return tool({\n description:\n \"Read a specific range of lines from a file, with line numbers. More efficient than reading entire files — use this after grep to read context around matches, or to inspect specific sections of large files.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n execute: async (\n args,\n ): Promise<ReadFileRangeToolResult | { error: string }> => {\n const { path: filePath, startLine, endLine } = args as {\n path: string;\n startLine?: number;\n endLine?: number;\n };\n\n const fullPath = resolve(cwd, filePath);\n const start = Math.max(1, startLine ?? 1);\n const requestedEnd = endLine ?? start + maxLines - 1;\n const end = Math.min(requestedEnd, start + maxLines - 1);\n\n let fh;\n try {\n fh = await open(fullPath, \"r\");\n } catch (err: unknown) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") {\n return { error: `File not found: ${filePath}` };\n }\n return { error: `Failed to open file: ${(err as Error).message}` };\n }\n\n try {\n const lines: string[] = [];\n let lineNum = 0;\n\n for await (const line of fh.readLines()) {\n lineNum++;\n if (lineNum > end) break;\n if (lineNum >= start) {\n lines.push(`${lineNum}\\t${line}`);\n }\n }\n\n if (lines.length === 0 && start > 1) {\n return {\n error: `File only has ${lineNum} lines. Requested start line: ${start}.`,\n };\n }\n\n return {\n path: filePath,\n content: lines.join(\"\\n\"),\n startLine: start,\n endLine: Math.min(end, lineNum),\n totalLines: lineNum,\n };\n } finally {\n await fh.close();\n }\n },\n });\n}\n","import { tool, jsonSchema } from \"ai\";\nimport { appendFile as fsAppendFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nexport interface AppendFileToolOptions {\n /** Base directory for resolving relative paths. Defaults to `process.cwd()`. */\n cwd?: string;\n}\n\nexport interface AppendFileToolResult {\n path: string;\n bytesAppended: number;\n}\n\n/**\n * Create an appendFile tool that appends content to existing files.\n *\n * More token-efficient than read-concat-write for incremental file building\n * (logs, CSVs, reports). Creates the file if it doesn't exist.\n *\n * @example\n * ```ts\n * import { createAppendFileTool } from '@supyagent/sdk';\n *\n * const tools = {\n * appendFile: createAppendFileTool({ cwd: '/path/to/project' }),\n * };\n * ```\n */\nexport function createAppendFileTool(options?: AppendFileToolOptions) {\n const cwd = options?.cwd ?? process.cwd();\n\n const schema = {\n type: \"object\" as const,\n properties: {\n path: {\n type: \"string\",\n description:\n \"File path to append to (absolute or relative to working directory). Created if it doesn't exist.\",\n },\n content: {\n type: \"string\",\n description:\n \"Content to append to the end of the file. Include a leading newline if you want separation from existing content.\",\n },\n },\n required: [\"path\", \"content\"],\n };\n\n return tool({\n description:\n \"Append content to the end of a file. Creates the file if it doesn't exist. More efficient than reading a file and rewriting it — use this for building up logs, CSVs, reports, or any file where you only need to add content.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n execute: async (args): Promise<AppendFileToolResult | { error: string }> => {\n const { path: filePath, content } = args as {\n path: string;\n content: string;\n };\n\n const fullPath = resolve(cwd, filePath);\n\n try {\n await fsAppendFile(fullPath, content, \"utf-8\");\n return {\n path: filePath,\n bytesAppended: Buffer.byteLength(content, \"utf-8\"),\n };\n } catch (err: unknown) {\n return { error: `Failed to append to file: ${(err as Error).message}` };\n }\n },\n });\n}\n","import { tool, jsonSchema } from \"ai\";\n\nconst DEFAULT_TIMEOUT = 30_000;\nconst MAX_RESPONSE_SIZE = 100_000;\n\nexport interface HttpRequestToolOptions {\n /** Default timeout in milliseconds. Defaults to 30000 (30s). */\n timeout?: number;\n /** Maximum response body size in characters. Defaults to 100000. */\n maxResponseSize?: number;\n /** Default headers to include in every request. */\n defaultHeaders?: Record<string, string>;\n}\n\nexport interface HttpRequestToolResult {\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body: string;\n durationMs: number;\n truncated: boolean;\n}\n\n/**\n * Create an httpRequest tool for making HTTP requests.\n *\n * Supports GET, POST, PUT, PATCH, DELETE with headers, body, and\n * parsed JSON responses. Cleaner than composing curl commands via bash.\n *\n * @example\n * ```ts\n * import { createHttpRequestTool } from '@supyagent/sdk';\n *\n * const tools = {\n * httpRequest: createHttpRequestTool({\n * defaultHeaders: { 'Authorization': 'Bearer ...' },\n * }),\n * };\n * ```\n */\nexport function createHttpRequestTool(options?: HttpRequestToolOptions) {\n const defaultTimeout = options?.timeout ?? DEFAULT_TIMEOUT;\n const maxResponseSize = options?.maxResponseSize ?? MAX_RESPONSE_SIZE;\n const defaultHeaders = options?.defaultHeaders ?? {};\n\n const schema = {\n type: \"object\" as const,\n properties: {\n url: {\n type: \"string\",\n description: \"The URL to request (must include protocol, e.g. https://)\",\n },\n method: {\n type: \"string\",\n description: \"HTTP method. Defaults to GET.\",\n enum: [\"GET\", \"POST\", \"PUT\", \"PATCH\", \"DELETE\", \"HEAD\"],\n },\n headers: {\n type: \"object\",\n description:\n \"Request headers as key-value pairs, e.g. { \\\"Content-Type\\\": \\\"application/json\\\" }\",\n additionalProperties: { type: \"string\" },\n },\n body: {\n type: \"string\",\n description:\n \"Request body as a string. For JSON, stringify the object first.\",\n },\n timeout: {\n type: \"number\",\n description: \"Request timeout in milliseconds. Defaults to 30000.\",\n },\n },\n required: [\"url\"],\n };\n\n return tool({\n description:\n \"Make an HTTP request to any URL. Supports GET, POST, PUT, PATCH, DELETE with custom headers and body. Returns status code, headers, and response body. Use this for calling APIs, checking endpoints, fetching data, or sending webhooks.\",\n inputSchema: jsonSchema(schema as Parameters<typeof jsonSchema>[0]),\n execute: async (args): Promise<HttpRequestToolResult | { error: string }> => {\n const {\n url,\n method,\n headers,\n body,\n timeout: reqTimeout,\n } = args as {\n url: string;\n method?: string;\n headers?: Record<string, string>;\n body?: string;\n timeout?: number;\n };\n\n const effectiveTimeout = reqTimeout ?? defaultTimeout;\n\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), effectiveTimeout);\n\n const start = Date.now();\n\n const response = await fetch(url, {\n method: method ?? \"GET\",\n headers: { ...defaultHeaders, ...headers },\n body: body ?? undefined,\n signal: controller.signal,\n });\n\n const durationMs = Date.now() - start;\n clearTimeout(timer);\n\n // Extract response headers as plain object\n const responseHeaders: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n // Read body as text\n let responseBody = await response.text();\n const truncated = responseBody.length > maxResponseSize;\n if (truncated) {\n responseBody = responseBody.slice(0, maxResponseSize) + \"\\n... (truncated)\";\n }\n\n return {\n status: response.status,\n statusText: response.statusText,\n headers: responseHeaders,\n body: responseBody,\n durationMs,\n truncated,\n };\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return { error: `Request timed out after ${effectiveTimeout}ms` };\n }\n return { error: `Request failed: ${(err as Error).message}` };\n }\n },\n });\n}\n"],"mappings":"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","names":["import_ai","import_ai","resolve","import_ai","import_ai","import_ai","import_node_child_process","import_node_path","MAX_OUTPUT","DEFAULT_TIMEOUT","import_ai","import_node_child_process","import_node_path","DEFAULT_TIMEOUT","MAX_OUTPUT","import_ai","import_promises","import_node_path","import_ai","import_promises","import_node_path","fsAppendFile","import_ai","DEFAULT_TIMEOUT"]}
package/dist/index.d.cts CHANGED
@@ -10,6 +10,8 @@ interface ToolMetadata {
10
10
  bodyDefaults?: Record<string, string>;
11
11
  category?: string;
12
12
  tags?: string[];
13
+ /** Whether the user has the required integration connected. Present on all tool discovery endpoints. */
14
+ connected?: boolean;
13
15
  }
14
16
  /** A single tool as returned by the /api/v1/tools endpoint */
15
17
  interface OpenAITool {
@@ -96,6 +98,20 @@ interface SkillsResult {
96
98
  /** Tool objects: loadSkill and apiCall */
97
99
  tools: Record<string, ai.Tool>;
98
100
  }
101
+ /** A tool with a relevance score, returned by search endpoints */
102
+ interface ScoredTool extends OpenAITool {
103
+ score: number;
104
+ }
105
+ /** Response from search endpoints (/tools/search, /tools/names) */
106
+ interface ToolSearchResponse {
107
+ tools: ScoredTool[];
108
+ total: number;
109
+ }
110
+ /** Response from filter endpoints (/tools/provider, /tools/service) */
111
+ interface ToolListResponse {
112
+ tools: OpenAITool[];
113
+ total: number;
114
+ }
99
115
  /** A connected account (end-user of the partner) */
100
116
  interface ConnectedAccount {
101
117
  id: string;
@@ -190,12 +206,24 @@ interface ScopedClient {
190
206
  tools(options?: ToolFilterOptions): Promise<Record<string, ai.Tool>>;
191
207
  skills(options?: SkillsOptions): Promise<SkillsResult>;
192
208
  me(options?: MeOptions): Promise<MeResponse>;
209
+ /** Fuzzy search across tool names and descriptions. Returns scored results. */
210
+ searchTools(query: string): Promise<ToolSearchResponse>;
211
+ /** Get all tools for a specific provider (e.g. "google", "slack"). */
212
+ toolsByProvider(provider: string): Promise<ToolListResponse>;
213
+ /** Get all tools for a specific service (e.g. "gmail", "calendar"). */
214
+ toolsByService(service: string): Promise<ToolListResponse>;
193
215
  }
194
216
  /** The supyagent client interface */
195
217
  interface SupyagentClient {
196
218
  tools(options?: ToolFilterOptions): Promise<Record<string, ai.Tool>>;
197
219
  skills(options?: SkillsOptions): Promise<SkillsResult>;
198
220
  me(options?: MeOptions): Promise<MeResponse>;
221
+ /** Fuzzy search across tool names and descriptions. Returns scored results. */
222
+ searchTools(query: string): Promise<ToolSearchResponse>;
223
+ /** Get all tools for a specific provider (e.g. "google", "slack"). */
224
+ toolsByProvider(provider: string): Promise<ToolListResponse>;
225
+ /** Get all tools for a specific service (e.g. "gmail", "calendar"). */
226
+ toolsByService(service: string): Promise<ToolListResponse>;
199
227
  accounts: AccountsClient;
200
228
  /** Returns a client scoped to a connected account. All requests include X-Account-Id. */
201
229
  asAccount(externalId: string): ScopedClient;
@@ -328,4 +356,194 @@ declare function createLoadSkillTool(skills: ParsedSkill[]): ai.Tool<unknown, {
328
356
  */
329
357
  declare function createApiCallTool(baseUrl: string, apiKey: string, accountId?: string): ai.Tool<unknown, any>;
330
358
 
331
- export { type AccountIntegration, type AccountIntegrationDetail, type AccountsClient, type BashToolOptions, type BashToolResult, type ConnectOptions, type ConnectSession, type ConnectSessionStatus, type ConnectedAccount, type ConnectedAccountWithIntegrations, type CreateAccountOptions, type ListAccountsOptions, type ListAccountsResponse, type MeOptions, type MeResponse, type OpenAITool, type ParsedSkill, type ParsedSkillsDocument, type ScopedClient, type SkillsOptions, type SkillsResult, type SupyagentClient, type SupyagentOptions, type ToolFilterOptions, type ToolMetadata, type ToolsResponse, type UpdateAccountOptions, type ViewImageToolOptions, type ViewImageToolResult, buildSkillsSystemPrompt, createApiCallTool, createBashTool, createLoadSkillTool, createViewImageTool, findSkill, parseSkillsMarkdown, supyagent };
359
+ interface EditFileToolOptions {
360
+ /** Base directory for resolving relative paths. Defaults to `process.cwd()`. */
361
+ cwd?: string;
362
+ /** Maximum file size in bytes that can be edited. Defaults to 1MB. */
363
+ maxFileSize?: number;
364
+ }
365
+ interface EditFileToolResult {
366
+ path: string;
367
+ replacements: number;
368
+ }
369
+ /**
370
+ * Create an editFile tool that patches files using search-and-replace.
371
+ *
372
+ * Unlike a full-file write, this lets the LLM send only the changed sections,
373
+ * saving tokens and reducing the risk of accidentally dropping content.
374
+ *
375
+ * @example
376
+ * ```ts
377
+ * import { createEditFileTool } from '@supyagent/sdk';
378
+ *
379
+ * const tools = {
380
+ * editFile: createEditFileTool({ cwd: '/path/to/project' }),
381
+ * };
382
+ * ```
383
+ */
384
+ declare function createEditFileTool(options?: EditFileToolOptions): ai.Tool<unknown, EditFileToolResult | {
385
+ error: string;
386
+ currentContent?: string;
387
+ }>;
388
+
389
+ interface GrepToolOptions {
390
+ /** Base directory for searching. Defaults to `process.cwd()`. */
391
+ cwd?: string;
392
+ /** Timeout in milliseconds. Defaults to 15000 (15s). */
393
+ timeout?: number;
394
+ /** Maximum output length in characters. Defaults to 30000. */
395
+ maxOutput?: number;
396
+ }
397
+ interface GrepToolResult {
398
+ matches: string;
399
+ matchCount: number;
400
+ truncated: boolean;
401
+ }
402
+ /**
403
+ * Create a grep tool for searching file contents by pattern.
404
+ *
405
+ * Uses `grep -rn` (or `rg` if available) under the hood.
406
+ * Returns matching lines with file paths and line numbers.
407
+ *
408
+ * @example
409
+ * ```ts
410
+ * import { createGrepTool } from '@supyagent/sdk';
411
+ *
412
+ * const tools = {
413
+ * grep: createGrepTool({ cwd: '/path/to/project' }),
414
+ * };
415
+ * ```
416
+ */
417
+ declare function createGrepTool(options?: GrepToolOptions): ai.Tool<unknown, GrepToolResult | {
418
+ error: string;
419
+ }>;
420
+
421
+ interface FindToolOptions {
422
+ /** Base directory for searching. Defaults to `process.cwd()`. */
423
+ cwd?: string;
424
+ /** Timeout in milliseconds. Defaults to 15000 (15s). */
425
+ timeout?: number;
426
+ /** Maximum output length in characters. Defaults to 30000. */
427
+ maxOutput?: number;
428
+ }
429
+ interface FindToolResult {
430
+ files: string[];
431
+ count: number;
432
+ truncated: boolean;
433
+ }
434
+ /**
435
+ * Create a find tool for discovering files by name or glob pattern.
436
+ *
437
+ * Uses `find` under the hood with common ignore patterns
438
+ * (node_modules, .git, dist, etc.) pre-configured.
439
+ *
440
+ * @example
441
+ * ```ts
442
+ * import { createFindTool } from '@supyagent/sdk';
443
+ *
444
+ * const tools = {
445
+ * find: createFindTool({ cwd: '/path/to/project' }),
446
+ * };
447
+ * ```
448
+ */
449
+ declare function createFindTool(options?: FindToolOptions): ai.Tool<unknown, FindToolResult | {
450
+ error: string;
451
+ }>;
452
+
453
+ interface ReadFileRangeToolOptions {
454
+ /** Base directory for resolving relative paths. Defaults to `process.cwd()`. */
455
+ cwd?: string;
456
+ /** Maximum number of lines that can be requested at once. Defaults to 200. */
457
+ maxLines?: number;
458
+ }
459
+ interface ReadFileRangeToolResult {
460
+ path: string;
461
+ content: string;
462
+ startLine: number;
463
+ endLine: number;
464
+ totalLines: number;
465
+ }
466
+ /**
467
+ * Create a readFileRange tool that reads specific line ranges from files.
468
+ *
469
+ * More token-efficient than reading entire files — especially useful
470
+ * after a grep to read context around a match.
471
+ *
472
+ * @example
473
+ * ```ts
474
+ * import { createReadFileRangeTool } from '@supyagent/sdk';
475
+ *
476
+ * const tools = {
477
+ * readFileRange: createReadFileRangeTool({ cwd: '/path/to/project' }),
478
+ * };
479
+ * ```
480
+ */
481
+ declare function createReadFileRangeTool(options?: ReadFileRangeToolOptions): ai.Tool<unknown, ReadFileRangeToolResult | {
482
+ error: string;
483
+ }>;
484
+
485
+ interface AppendFileToolOptions {
486
+ /** Base directory for resolving relative paths. Defaults to `process.cwd()`. */
487
+ cwd?: string;
488
+ }
489
+ interface AppendFileToolResult {
490
+ path: string;
491
+ bytesAppended: number;
492
+ }
493
+ /**
494
+ * Create an appendFile tool that appends content to existing files.
495
+ *
496
+ * More token-efficient than read-concat-write for incremental file building
497
+ * (logs, CSVs, reports). Creates the file if it doesn't exist.
498
+ *
499
+ * @example
500
+ * ```ts
501
+ * import { createAppendFileTool } from '@supyagent/sdk';
502
+ *
503
+ * const tools = {
504
+ * appendFile: createAppendFileTool({ cwd: '/path/to/project' }),
505
+ * };
506
+ * ```
507
+ */
508
+ declare function createAppendFileTool(options?: AppendFileToolOptions): ai.Tool<unknown, AppendFileToolResult | {
509
+ error: string;
510
+ }>;
511
+
512
+ interface HttpRequestToolOptions {
513
+ /** Default timeout in milliseconds. Defaults to 30000 (30s). */
514
+ timeout?: number;
515
+ /** Maximum response body size in characters. Defaults to 100000. */
516
+ maxResponseSize?: number;
517
+ /** Default headers to include in every request. */
518
+ defaultHeaders?: Record<string, string>;
519
+ }
520
+ interface HttpRequestToolResult {
521
+ status: number;
522
+ statusText: string;
523
+ headers: Record<string, string>;
524
+ body: string;
525
+ durationMs: number;
526
+ truncated: boolean;
527
+ }
528
+ /**
529
+ * Create an httpRequest tool for making HTTP requests.
530
+ *
531
+ * Supports GET, POST, PUT, PATCH, DELETE with headers, body, and
532
+ * parsed JSON responses. Cleaner than composing curl commands via bash.
533
+ *
534
+ * @example
535
+ * ```ts
536
+ * import { createHttpRequestTool } from '@supyagent/sdk';
537
+ *
538
+ * const tools = {
539
+ * httpRequest: createHttpRequestTool({
540
+ * defaultHeaders: { 'Authorization': 'Bearer ...' },
541
+ * }),
542
+ * };
543
+ * ```
544
+ */
545
+ declare function createHttpRequestTool(options?: HttpRequestToolOptions): ai.Tool<unknown, HttpRequestToolResult | {
546
+ error: string;
547
+ }>;
548
+
549
+ export { type AccountIntegration, type AccountIntegrationDetail, type AccountsClient, type AppendFileToolOptions, type AppendFileToolResult, type BashToolOptions, type BashToolResult, type ConnectOptions, type ConnectSession, type ConnectSessionStatus, type ConnectedAccount, type ConnectedAccountWithIntegrations, type CreateAccountOptions, type EditFileToolOptions, type EditFileToolResult, type FindToolOptions, type FindToolResult, type GrepToolOptions, type GrepToolResult, type HttpRequestToolOptions, type HttpRequestToolResult, type ListAccountsOptions, type ListAccountsResponse, type MeOptions, type MeResponse, type OpenAITool, type ParsedSkill, type ParsedSkillsDocument, type ReadFileRangeToolOptions, type ReadFileRangeToolResult, type ScopedClient, type ScoredTool, type SkillsOptions, type SkillsResult, type SupyagentClient, type SupyagentOptions, type ToolFilterOptions, type ToolListResponse, type ToolMetadata, type ToolSearchResponse, type ToolsResponse, type UpdateAccountOptions, type ViewImageToolOptions, type ViewImageToolResult, buildSkillsSystemPrompt, createApiCallTool, createAppendFileTool, createBashTool, createEditFileTool, createFindTool, createGrepTool, createHttpRequestTool, createLoadSkillTool, createReadFileRangeTool, createViewImageTool, findSkill, parseSkillsMarkdown, supyagent };