@better-agent/plugins 0.1.0-beta.1 → 0.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/shared/json.ts","../src/auth/responses.ts","../src/shared/validation.ts","../src/auth/validate.ts","../src/auth/plugin.ts","../src/ip-allowlist/ip.ts","../src/ip-allowlist/cidr.ts","../src/ip-allowlist/responses.ts","../src/ip-allowlist/validate.ts","../src/ip-allowlist/plugin.ts","../src/logging/format.ts","../src/logging/redact.ts","../src/logging/validate.ts","../src/logging/plugin.ts","../src/rate-limit/bucket.ts","../src/rate-limit/memory-store.ts","../src/rate-limit/responses.ts","../src/rate-limit/validate.ts","../src/rate-limit/plugin.ts"],"sourcesContent":["/** Creates a JSON response with a default content type. */\nexport function jsonResponse(body: unknown, init?: ResponseInit): Response {\n const headers = new Headers(init?.headers);\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n\n return new Response(JSON.stringify(body), {\n ...init,\n headers,\n });\n}\n","import { jsonResponse } from \"../shared/json\";\n\n/** Creates the default unauthorized response. */\nexport function createUnauthorizedResponse(): Response {\n return jsonResponse(\n {\n error: \"unauthorized\",\n message: \"Invalid API key.\",\n },\n { status: 401 },\n );\n}\n","import { BetterAgentError } from \"@better-agent/shared/errors\";\n\n/** Creates a plugin validation error. */\nexport function createValidationError(message: string, at: string): BetterAgentError {\n return BetterAgentError.fromCode(\"VALIDATION_FAILED\", message, {\n trace: [{ at }],\n });\n}\n\n/** Requires a positive finite number. */\nexport function requirePositiveNumber(value: number, name: string, at: string): void {\n if (!Number.isFinite(value) || value <= 0) {\n throw createValidationError(`\\`${name}\\` must be a positive number.`, at);\n }\n}\n\n/** Requires a non-empty array. */\nexport function requireNonEmptyArray<T>(\n value: readonly T[] | undefined,\n name: string,\n at: string,\n): asserts value is readonly T[] {\n if (!value || value.length === 0) {\n throw createValidationError(`\\`${name}\\` must contain at least one value.`, at);\n }\n}\n","import { createValidationError } from \"../shared/validation\";\nimport type { AuthPluginConfig } from \"./types\";\n\n/** Validates `authPlugin` configuration. */\nexport function validateAuthPluginConfig(config: AuthPluginConfig): void {\n if (!config.validate && (!config.apiKeys || config.apiKeys.length === 0)) {\n throw createValidationError(\n \"`authPlugin` requires either `apiKeys` or `validate`.\",\n \"plugins.authPlugin\",\n );\n }\n\n if (config.header !== undefined && config.header.trim().length === 0) {\n throw createValidationError(\n \"`authPlugin` requires `header` to be a non-empty string when provided.\",\n \"plugins.authPlugin\",\n );\n }\n\n if (config.apiKeys) {\n const normalized = config.apiKeys\n .filter((key): key is string => typeof key === \"string\")\n .map((key) => key.trim())\n .filter((key) => key.length > 0);\n\n if (normalized.length === 0 && !config.validate) {\n throw createValidationError(\n \"`authPlugin` requires `apiKeys` to contain at least one non-empty key.\",\n \"plugins.authPlugin\",\n );\n }\n }\n}\n","import type { Plugin } from \"@better-agent/core\";\nimport { createUnauthorizedResponse } from \"./responses\";\nimport type { AuthPluginConfig } from \"./types\";\nimport { validateAuthPluginConfig } from \"./validate\";\n\n/**\n * Creates an API-key auth plugin.\n *\n * Provide either `apiKeys` or `validate`.\n *\n * @example\n * ```ts\n * const plugin = authPlugin({\n * apiKeys: [\"dev-key\"],\n * });\n * ```\n */\nexport const authPlugin = (config: AuthPluginConfig): Plugin => {\n validateAuthPluginConfig(config);\n\n const header = config.header?.trim() || \"x-api-key\";\n const apiKeys = new Set((config.apiKeys ?? []).map((key) => key.trim()).filter(Boolean));\n\n return {\n id: config.id ?? \"auth\",\n guards: [\n async (ctx) => {\n const keyValue = config.getKey\n ? await config.getKey({\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : ctx.request.headers.get(header);\n\n const key =\n typeof keyValue === \"string\" && keyValue.trim().length > 0 ? keyValue : null;\n\n const valid = config.validate\n ? await config.validate({\n key,\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : key !== null && apiKeys.has(key);\n\n if (valid) {\n return null;\n }\n\n return config.onUnauthorized\n ? await config.onUnauthorized({\n key,\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : createUnauthorizedResponse();\n },\n ],\n };\n};\n","/** Parsed IP value. */\ntype ParsedIp = {\n /** IP family. */\n kind: \"ipv4\" | \"ipv6\";\n /** Numeric IP value. */\n value: bigint;\n /** Bit width for the IP family. */\n bits: number;\n /** Normalized string form. */\n normalized: string;\n};\n\n/** Parses an IPv4 string. */\nfunction parseIpv4(input: string): ParsedIp | null {\n const parts = input.split(\".\");\n if (parts.length !== 4) return null;\n\n let value = 0n;\n for (const part of parts) {\n if (!/^\\d+$/.test(part)) return null;\n const octet = Number(part);\n if (octet < 0 || octet > 255) return null;\n value = (value << 8n) | BigInt(octet);\n }\n\n return {\n kind: \"ipv4\",\n value,\n bits: 32,\n normalized: parts.join(\".\"),\n };\n}\n\n/** Expands an IPv6 string into eight normalized segments. */\nfunction expandIpv6Segments(input: string): string[] | null {\n const zoneIndex = input.indexOf(\"%\");\n const value = zoneIndex >= 0 ? input.slice(0, zoneIndex) : input;\n if (value.length === 0) return null;\n\n const doubleColonCount = value.split(\"::\").length - 1;\n if (doubleColonCount > 1) return null;\n\n const [leftRaw = \"\", rightRaw = \"\"] = value.split(\"::\");\n const left = leftRaw.length > 0 ? leftRaw.split(\":\") : [];\n const right = rightRaw.length > 0 ? rightRaw.split(\":\") : [];\n\n const normalizedRight = [...right];\n if (normalizedRight.length > 0) {\n const last = normalizedRight[normalizedRight.length - 1];\n if (last?.includes(\".\")) {\n const ipv4 = parseIpv4(last);\n if (!ipv4) return null;\n normalizedRight.splice(\n normalizedRight.length - 1,\n 1,\n Number((ipv4.value >> 16n) & 0xffffn).toString(16),\n Number(ipv4.value & 0xffffn).toString(16),\n );\n }\n }\n\n const normalizedLeft = [...left];\n if (normalizedLeft.length > 0) {\n const last = normalizedLeft[normalizedLeft.length - 1];\n if (last?.includes(\".\")) {\n const ipv4 = parseIpv4(last);\n if (!ipv4) return null;\n normalizedLeft.splice(\n normalizedLeft.length - 1,\n 1,\n Number((ipv4.value >> 16n) & 0xffffn).toString(16),\n Number(ipv4.value & 0xffffn).toString(16),\n );\n }\n }\n\n const totalSegments = normalizedLeft.length + normalizedRight.length;\n if (doubleColonCount === 0 && totalSegments !== 8) return null;\n if (doubleColonCount === 1 && totalSegments >= 8) return null;\n\n const missing = doubleColonCount === 1 ? 8 - totalSegments : 0;\n const segments = [\n ...normalizedLeft,\n ...Array.from({ length: missing }, () => \"0\"),\n ...normalizedRight,\n ];\n\n if (segments.length !== 8) return null;\n if (segments.some((segment) => !/^[0-9a-fA-F]{1,4}$/.test(segment))) return null;\n\n return segments.map((segment) => segment.toLowerCase());\n}\n\n/** Parses an IPv6 string. */\nfunction parseIpv6(input: string): ParsedIp | null {\n const segments = expandIpv6Segments(input);\n if (!segments) return null;\n\n let value = 0n;\n for (const segment of segments) {\n value = (value << 16n) | BigInt(Number.parseInt(segment, 16));\n }\n\n return {\n kind: \"ipv6\",\n value,\n bits: 128,\n normalized: segments.join(\":\"),\n };\n}\n\n/** Parses an IPv4 or IPv6 string. */\nexport function parseIp(input: string): ParsedIp | null {\n const value = input.trim();\n if (value.length === 0) return null;\n return parseIpv4(value) ?? parseIpv6(value);\n}\n\n/** Normalizes an IP string. */\nexport function normalizeIp(input: string): string | null {\n return parseIp(input)?.normalized ?? null;\n}\n\nexport type { ParsedIp };\n","import { type ParsedIp, parseIp } from \"./ip\";\n\n/** Matcher for one allowed IP entry. */\nexport type IpMatcher = {\n /** Original allowlist entry. */\n raw: string;\n /** Returns true when the IP matches this entry. */\n matches: (ip: ParsedIp) => boolean;\n};\n\n/** Creates a network mask for the given prefix. */\nfunction createMask(bits: number, prefix: number): bigint {\n if (prefix === 0) return 0n;\n return ((1n << BigInt(prefix)) - 1n) << BigInt(bits - prefix);\n}\n\n/** Parses one allowlist IP or CIDR entry. */\nexport function parseAllowEntry(input: string): IpMatcher | null {\n const raw = input.trim();\n if (raw.length === 0) return null;\n\n const slashIndex = raw.indexOf(\"/\");\n if (slashIndex === -1) {\n const parsed = parseIp(raw);\n if (!parsed) return null;\n return {\n raw,\n matches: (ip) => ip.kind === parsed.kind && ip.value === parsed.value,\n };\n }\n\n const addressPart = raw.slice(0, slashIndex).trim();\n const prefixPart = raw.slice(slashIndex + 1).trim();\n if (!/^\\d+$/.test(prefixPart)) return null;\n\n const parsed = parseIp(addressPart);\n if (!parsed) return null;\n\n const prefix = Number(prefixPart);\n if (prefix < 0 || prefix > parsed.bits) return null;\n\n const mask = createMask(parsed.bits, prefix);\n const network = parsed.value & mask;\n\n return {\n raw,\n matches: (ip) => ip.kind === parsed.kind && (ip.value & mask) === network,\n };\n}\n","import { jsonResponse } from \"../shared/json\";\n\n/** Creates the default IP denied response. */\nexport function createIpDeniedResponse(): Response {\n return jsonResponse(\n {\n error: \"forbidden\",\n message: \"IP address is not allowed.\",\n },\n { status: 403 },\n );\n}\n","import { createValidationError, requireNonEmptyArray } from \"../shared/validation\";\nimport { parseAllowEntry } from \"./cidr\";\nimport type { IpAllowlistPluginConfig } from \"./types\";\n\n/** Validates `ipAllowlistPlugin` configuration. */\nexport function validateIpAllowlistPluginConfig(config: IpAllowlistPluginConfig): void {\n requireNonEmptyArray(config.allow, \"allow\", \"plugins.ipAllowlistPlugin\");\n\n for (const entry of config.allow) {\n if (typeof entry !== \"string\" || !parseAllowEntry(entry)) {\n throw createValidationError(\n `\\`ipAllowlistPlugin\\` received an invalid allow entry: '${String(entry)}'.`,\n \"plugins.ipAllowlistPlugin\",\n );\n }\n }\n}\n","import type { Plugin } from \"@better-agent/core\";\nimport { parseAllowEntry } from \"./cidr\";\nimport { normalizeIp, parseIp } from \"./ip\";\nimport { createIpDeniedResponse } from \"./responses\";\nimport type { IpAllowlistPluginConfig } from \"./types\";\nimport { validateIpAllowlistPluginConfig } from \"./validate\";\n\n/** Reads the first valid forwarded IP. */\nfunction getProxyIp(request: Request): string | null {\n const forwardedFor = request.headers.get(\"x-forwarded-for\");\n if (!forwardedFor) return null;\n\n for (const part of forwardedFor.split(\",\")) {\n const normalized = normalizeIp(part.trim());\n if (normalized) {\n return normalized;\n }\n }\n\n return null;\n}\n\n/** Reads a direct client IP from common proxy headers. */\nfunction getDirectIp(request: Request): string | null {\n const candidates = [\n request.headers.get(\"x-real-ip\"),\n request.headers.get(\"cf-connecting-ip\"),\n request.headers.get(\"fly-client-ip\"),\n request.headers.get(\"fastly-client-ip\"),\n request.headers.get(\"x-client-ip\"),\n ];\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const normalized = normalizeIp(candidate);\n if (normalized) {\n return normalized;\n }\n }\n\n return null;\n}\n\n/**\n * Creates an IP allowlist plugin.\n *\n * @example\n * ```ts\n * const plugin = ipAllowlistPlugin({\n * allow: [\"127.0.0.1\", \"10.0.0.0/8\"],\n * });\n * ```\n */\nexport const ipAllowlistPlugin = (config: IpAllowlistPluginConfig): Plugin => {\n validateIpAllowlistPluginConfig(config);\n\n const matchers = config.allow.map((entry) => {\n const matcher = parseAllowEntry(entry);\n if (!matcher) {\n throw new Error(`Invalid allowlist entry: ${entry}`);\n }\n return matcher;\n });\n\n return {\n id: config.id ?? \"ip-allowlist\",\n guards: [\n async (ctx) => {\n const resolvedIp = config.getIp\n ? await config.getIp({\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : config.trustProxy\n ? getProxyIp(ctx.request)\n : getDirectIp(ctx.request);\n\n const normalizedIp =\n typeof resolvedIp === \"string\" && resolvedIp.trim().length > 0\n ? normalizeIp(resolvedIp)\n : null;\n const parsedIp = normalizedIp ? parseIp(normalizedIp) : null;\n\n if (parsedIp && matchers.some((matcher) => matcher.matches(parsedIp))) {\n return null;\n }\n\n return config.onDenied\n ? await config.onDenied({\n ip: normalizedIp,\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : createIpDeniedResponse();\n },\n ],\n };\n};\n","import type { LogEntry, LoggingPluginConfig } from \"./types\";\n\nconst order: Record<LogEntry[\"level\"], number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\n/** Returns true when the entry should be logged at the current level. */\nexport function shouldLog(\n currentLevel: NonNullable<LoggingPluginConfig[\"level\"]>,\n entry: LogEntry,\n): boolean {\n return order[entry.level] >= order[currentLevel];\n}\n","const DEFAULT_REDACT_HEADERS = [\"authorization\", \"cookie\", \"set-cookie\", \"x-api-key\"] as const;\n\n/** Redacts sensitive headers. */\nexport function redactHeaders(\n headers: Headers,\n extraHeaders?: readonly string[],\n): Record<string, string> {\n const redactSet = new Set(\n [...DEFAULT_REDACT_HEADERS, ...(extraHeaders ?? [])].map((value) => value.toLowerCase()),\n );\n const result: Record<string, string> = {};\n\n headers.forEach((value, key) => {\n result[key] = redactSet.has(key.toLowerCase()) ? \"[REDACTED]\" : value;\n });\n\n return result;\n}\n","import type { LoggingPluginConfig } from \"./types\";\n\n/** Validates `loggingPlugin` configuration. */\nexport function validateLoggingPluginConfig(_config: LoggingPluginConfig): void {}\n","import type { Plugin } from \"@better-agent/core\";\nimport type { PluginOnStepContext, PluginSaveContext } from \"@better-agent/core\";\nimport type { Event } from \"@better-agent/core/events\";\nimport { shouldLog } from \"./format\";\nimport { redactHeaders } from \"./redact\";\nimport type { LogEntry, LoggingPluginConfig } from \"./types\";\nimport { validateLoggingPluginConfig } from \"./validate\";\n\nfunction safeInvoke(fn: ((...args: unknown[]) => void) | undefined, payload: unknown): void {\n if (!fn) return;\n try {\n fn(payload);\n } catch {\n // Logging must never affect runtime execution.\n }\n}\n\n/** Resolves the logger methods for the configured sink. */\nfunction getLoggerMethods(config: LoggingPluginConfig) {\n return {\n debug: config.logger?.debug ?? console.debug,\n info: config.logger?.info ?? console.info,\n warn: config.logger?.warn ?? console.warn,\n error: config.logger?.error ?? console.error,\n };\n}\n\n/** Emits one log entry. */\nfunction emitLog(config: LoggingPluginConfig, entry: LogEntry): void {\n const level = config.level ?? \"info\";\n if (!shouldLog(level, entry)) return;\n\n const output = config.format ? config.format(entry) : entry;\n const logger = getLoggerMethods(config);\n safeInvoke(logger[entry.level], output);\n}\n\n/** Maps one runtime event to a log level. */\nfunction getEventLevel(event: Event): LogEntry[\"level\"] {\n if (event.type.endsWith(\"_ERROR\")) return \"error\";\n return \"info\";\n}\n\n/** Creates request log data. */\nfunction createRequestData(ctx: Parameters<NonNullable<Plugin[\"guards\"]>[number]>[0]) {\n return {\n mode: ctx.mode,\n url: ctx.request.url,\n method: ctx.request.method,\n headers: redactHeaders(ctx.request.headers),\n input: ctx.input,\n };\n}\n\n/** Creates step log data. */\nfunction createStepData(ctx: PluginOnStepContext) {\n return {\n stepIndex: ctx.stepIndex,\n maxSteps: ctx.maxSteps,\n messageCount: ctx.messages.length,\n };\n}\n\n/** Creates save log data. */\nfunction createSaveData(ctx: PluginSaveContext) {\n const messageCount = ctx.items.filter((item) => item.type === \"message\").length;\n\n return {\n itemCount: ctx.items.length,\n messageCount,\n };\n}\n\n/**\n * Creates a logging plugin.\n *\n * @example\n * ```ts\n * const plugin = loggingPlugin({\n * level: \"info\",\n * include: { requests: true, toolCalls: true },\n * });\n * ```\n */\nexport const loggingPlugin = (config: LoggingPluginConfig = {}): Plugin => {\n validateLoggingPluginConfig(config);\n\n const include = {\n requests: config.include?.requests ?? true,\n events: config.include?.events ?? true,\n steps: config.include?.steps ?? true,\n modelCalls: config.include?.modelCalls ?? true,\n toolCalls: config.include?.toolCalls ?? true,\n saves: config.include?.saves ?? false,\n errors: config.include?.errors ?? true,\n };\n\n const plugin: Plugin = {\n id: config.id ?? \"logging\",\n };\n\n if (include.requests) {\n plugin.guards = [\n async (ctx) => {\n const body = config.redactBody\n ? config.redactBody({ body: ctx.input, phase: \"request\" })\n : ctx.input;\n\n emitLog(config, {\n level: \"info\",\n event: \"request.received\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n data: {\n ...createRequestData(ctx),\n input: body,\n },\n });\n\n return null;\n },\n ];\n }\n\n if (include.events) {\n plugin.onEvent = async (event, ctx) => {\n const level = getEventLevel(event);\n if (level === \"error\" && !include.errors) return;\n\n emitLog(config, {\n level,\n event: \"run.event\",\n timestamp: new Date(event.timestamp).toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n type: event.type,\n },\n });\n };\n }\n\n if (include.steps) {\n plugin.onStep = async (ctx) => {\n emitLog(config, {\n level: \"info\",\n event: \"step.start\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: createStepData(ctx),\n });\n };\n }\n\n if (include.modelCalls) {\n plugin.onBeforeModelCall = async (ctx) => {\n emitLog(config, {\n level: \"debug\",\n event: \"model.before\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n stepIndex: ctx.stepIndex,\n inputCount: ctx.input.length,\n toolCount: ctx.tools.length,\n toolChoice: ctx.toolChoice,\n },\n });\n };\n\n plugin.onAfterModelCall = async (ctx) => {\n emitLog(config, {\n level: \"debug\",\n event: \"model.after\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n stepIndex: ctx.stepIndex,\n response: config.redactBody\n ? config.redactBody({ body: ctx.response, phase: \"response\" })\n : ctx.response,\n },\n });\n };\n }\n\n if (include.toolCalls) {\n plugin.onBeforeToolCall = async (ctx) => {\n emitLog(config, {\n level: \"info\",\n event: \"tool.before\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n toolName: ctx.toolName,\n toolCallId: ctx.toolCallId,\n args: config.redactBody\n ? config.redactBody({ body: ctx.args, phase: \"tool_args\" })\n : ctx.args,\n },\n });\n return undefined;\n };\n\n plugin.onAfterToolCall = async (ctx) => {\n emitLog(config, {\n level: ctx.error ? \"error\" : \"info\",\n event: \"tool.after\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n toolName: ctx.toolName,\n toolCallId: ctx.toolCallId,\n error: ctx.error,\n result: config.redactBody\n ? config.redactBody({ body: ctx.result, phase: \"tool_result\" })\n : ctx.result,\n },\n });\n };\n }\n\n if (include.saves) {\n plugin.onBeforeSave = async (ctx) => {\n emitLog(config, {\n level: \"debug\",\n event: \"save.before\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n ...createSaveData(ctx),\n items: config.redactBody\n ? config.redactBody({ body: ctx.items, phase: \"save\" })\n : ctx.items,\n },\n });\n };\n }\n\n return plugin;\n};\n","import type { RateLimitBucket } from \"./types\";\n\n/** Creates a rate-limit bucket for the current window. */\nexport function createBucket(params: {\n key: string;\n now: Date;\n windowMs: number;\n}): RateLimitBucket {\n const nowMs = params.now.getTime();\n const windowStartMs = Math.floor(nowMs / params.windowMs) * params.windowMs;\n\n return {\n id: `${windowStartMs}:${params.key}`,\n key: params.key,\n now: params.now,\n windowStart: new Date(windowStartMs),\n windowEnd: new Date(windowStartMs + params.windowMs),\n };\n}\n","import type { RateLimitPluginConfig, RateLimitStorageState } from \"./types\";\n\n/** Creates an in-memory CAS store for rate limiting. */\nexport function createMemoryStore(): NonNullable<RateLimitPluginConfig[\"storage\"]> {\n const rows = new Map<string, RateLimitStorageState>();\n\n return {\n read: async ({ bucket }) => rows.get(bucket.id) ?? null,\n write: async ({ bucket, prevVersion, next }) => {\n const current = rows.get(bucket.id) ?? null;\n if (prevVersion === null) {\n if (current) return false;\n rows.set(bucket.id, next);\n return true;\n }\n\n if (!current || current.version !== prevVersion) {\n return false;\n }\n\n rows.set(bucket.id, next);\n return true;\n },\n };\n}\n","import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport { jsonResponse } from \"../shared/json\";\nimport type { RateLimitBucket } from \"./types\";\n\n/** Creates the default rate-limited response. */\nexport function createRateLimitedResponse(params: {\n bucket: RateLimitBucket;\n nowMs: number;\n key: string;\n max: number;\n}): Response {\n const retryAfter = Math.max(\n 1,\n Math.ceil((params.bucket.windowEnd.getTime() - params.nowMs) / 1000),\n );\n\n return jsonResponse(\n {\n error: \"rate_limited\",\n message: \"Too many requests.\",\n key: params.key,\n limit: params.max,\n remaining: 0,\n resetAt: params.bucket.windowEnd.toISOString(),\n },\n {\n status: 429,\n headers: {\n \"retry-after\": String(retryAfter),\n \"x-ratelimit-limit\": String(params.max),\n \"x-ratelimit-remaining\": \"0\",\n \"x-ratelimit-reset\": String(Math.floor(params.bucket.windowEnd.getTime() / 1000)),\n },\n },\n );\n}\n\n/** Creates the default storage unavailable response. */\nexport function createRateLimitStorageUnavailableResponse(): Response {\n return jsonResponse(\n {\n error: \"service_unavailable\",\n message: \"Rate limit storage is unavailable.\",\n },\n { status: 503 },\n );\n}\n\n/** Creates the CAS retries exceeded error. */\nexport function createCasRetriesExceededError(): BetterAgentError {\n return BetterAgentError.fromCode(\"INTERNAL\", \"Rate limit write failed after CAS retries.\", {\n trace: [{ at: \"plugins.rateLimitPlugin\" }],\n });\n}\n","import { requirePositiveNumber } from \"../shared/validation\";\nimport type { RateLimitPluginConfig } from \"./types\";\n\n/** Validates `rateLimitPlugin` configuration. */\nexport function validateRateLimitPluginConfig(config: RateLimitPluginConfig): void {\n requirePositiveNumber(config.windowMs, \"windowMs\", \"plugins.rateLimitPlugin\");\n requirePositiveNumber(config.max, \"max\", \"plugins.rateLimitPlugin\");\n requirePositiveNumber(config.casRetries ?? 8, \"casRetries\", \"plugins.rateLimitPlugin\");\n}\n","import type { Plugin } from \"@better-agent/core\";\nimport { createBucket } from \"./bucket\";\nimport { createMemoryStore } from \"./memory-store\";\nimport {\n createCasRetriesExceededError,\n createRateLimitStorageUnavailableResponse,\n createRateLimitedResponse,\n} from \"./responses\";\nimport type { RateLimitPluginConfig, RateLimitStorageState } from \"./types\";\nimport { validateRateLimitPluginConfig } from \"./validate\";\n\n/**\n * Creates a rate-limit plugin.\n *\n * Uses an in-memory store by default.\n *\n * @example\n * ```ts\n * const plugin = rateLimitPlugin({\n * windowMs: 60_000,\n * max: 30,\n * });\n * ```\n */\nexport const rateLimitPlugin = (config: RateLimitPluginConfig): Plugin => {\n validateRateLimitPluginConfig(config);\n\n const casRetries = config.casRetries ?? 8;\n const storage = config.storage ?? createMemoryStore();\n\n return {\n id: config.id ?? \"rate-limit\",\n guards: [\n async (ctx) => {\n const request = {\n mode: ctx.mode,\n agentName: ctx.agentName,\n request: ctx.request,\n };\n\n const now = new Date();\n const nowMs = now.getTime();\n const keyFromConfig = config.key\n ? await config.key(request)\n : `${ctx.agentName}:global`;\n const key =\n typeof keyFromConfig === \"string\" && keyFromConfig.trim().length > 0\n ? keyFromConfig.trim()\n : `${ctx.agentName}:global`;\n const bucket = createBucket({\n key,\n now,\n windowMs: config.windowMs,\n });\n\n const handleStoreError = async (error: unknown): Promise<Response | null> => {\n const action = config.onStoreError\n ? await config.onStoreError({ error, bucket, request })\n : \"allow\";\n\n if (action instanceof Response) return action;\n if (action === \"deny\") {\n return createRateLimitStorageUnavailableResponse();\n }\n\n return null;\n };\n\n for (let attempt = 0; attempt < casRetries; attempt += 1) {\n let state: RateLimitStorageState | null = null;\n try {\n state = await storage.read({ bucket, request });\n } catch (error) {\n return handleStoreError(error);\n }\n\n if (state && state.count >= config.max) {\n return createRateLimitedResponse({\n bucket,\n nowMs,\n key,\n max: config.max,\n });\n }\n\n try {\n const written = await storage.write({\n bucket,\n request,\n prevVersion: state?.version ?? null,\n next: {\n count: (state?.count ?? 0) + 1,\n version: (state?.version ?? 0) + 1,\n },\n });\n\n if (written) return null;\n } catch (error) {\n return handleStoreError(error);\n }\n }\n\n return handleStoreError(createCasRetriesExceededError());\n },\n ],\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["createValidationError","createValidationError","createValidationError","removeUndefined","createValidationError"],"sources":["../src/shared/json.ts","../src/auth/responses.ts","../src/shared/validation.ts","../src/auth/validate.ts","../src/auth/plugin.ts","../src/ip-allowlist/ip.ts","../src/ip-allowlist/cidr.ts","../src/ip-allowlist/responses.ts","../src/ip-allowlist/validate.ts","../src/ip-allowlist/plugin.ts","../src/logging/format.ts","../src/logging/redact.ts","../src/logging/validate.ts","../src/logging/plugin.ts","../src/rate-limit/bucket.ts","../src/rate-limit/memory-store.ts","../src/rate-limit/responses.ts","../src/rate-limit/validate.ts","../src/rate-limit/plugin.ts","../src/sandbox/daytona.ts","../src/sandbox/e2b.ts","../src/sandbox/memory-store.ts","../src/sandbox/validate.ts","../src/sandbox/plugin.ts"],"sourcesContent":["/** Creates a JSON response with a default content type. */\nexport function jsonResponse(body: unknown, init?: ResponseInit): Response {\n const headers = new Headers(init?.headers);\n if (!headers.has(\"content-type\")) {\n headers.set(\"content-type\", \"application/json\");\n }\n\n return new Response(JSON.stringify(body), {\n ...init,\n headers,\n });\n}\n","import { jsonResponse } from \"../shared/json\";\n\n/** Creates the default unauthorized response. */\nexport function createUnauthorizedResponse(): Response {\n return jsonResponse(\n {\n error: \"unauthorized\",\n message: \"Invalid API key.\",\n },\n { status: 401 },\n );\n}\n","import { BetterAgentError } from \"@better-agent/shared/errors\";\n\n/** Creates a plugin validation error. */\nexport function createValidationError(message: string, at: string): BetterAgentError {\n return BetterAgentError.fromCode(\"VALIDATION_FAILED\", message, {\n trace: [{ at }],\n });\n}\n\n/** Requires a positive finite number. */\nexport function requirePositiveNumber(value: number, name: string, at: string): void {\n if (!Number.isFinite(value) || value <= 0) {\n throw createValidationError(`\\`${name}\\` must be a positive number.`, at);\n }\n}\n\n/** Requires a non-empty array. */\nexport function requireNonEmptyArray<T>(\n value: readonly T[] | undefined,\n name: string,\n at: string,\n): asserts value is readonly T[] {\n if (!value || value.length === 0) {\n throw createValidationError(`\\`${name}\\` must contain at least one value.`, at);\n }\n}\n","import { createValidationError } from \"../shared/validation\";\nimport type { AuthPluginConfig } from \"./types\";\n\n/** Validates `authPlugin` configuration. */\nexport function validateAuthPluginConfig(config: AuthPluginConfig): void {\n if (!config.validate && (!config.apiKeys || config.apiKeys.length === 0)) {\n throw createValidationError(\n \"`authPlugin` requires either `apiKeys` or `validate`.\",\n \"plugins.authPlugin\",\n );\n }\n\n if (config.header !== undefined && config.header.trim().length === 0) {\n throw createValidationError(\n \"`authPlugin` requires `header` to be a non-empty string when provided.\",\n \"plugins.authPlugin\",\n );\n }\n\n if (config.apiKeys) {\n const normalized = config.apiKeys\n .filter((key): key is string => typeof key === \"string\")\n .map((key) => key.trim())\n .filter((key) => key.length > 0);\n\n if (normalized.length === 0 && !config.validate) {\n throw createValidationError(\n \"`authPlugin` requires `apiKeys` to contain at least one non-empty key.\",\n \"plugins.authPlugin\",\n );\n }\n }\n}\n","import type { Plugin } from \"@better-agent/core\";\nimport { createUnauthorizedResponse } from \"./responses\";\nimport type { AuthPluginConfig } from \"./types\";\nimport { validateAuthPluginConfig } from \"./validate\";\n\n/**\n * Creates an API-key auth plugin.\n *\n * Provide either `apiKeys` or `validate`.\n *\n * @example\n * ```ts\n * const plugin = authPlugin({\n * apiKeys: [\"dev-key\"],\n * });\n * ```\n */\nexport const authPlugin = (config: AuthPluginConfig): Plugin => {\n validateAuthPluginConfig(config);\n\n const header = config.header?.trim() || \"x-api-key\";\n const apiKeys = new Set((config.apiKeys ?? []).map((key) => key.trim()).filter(Boolean));\n\n return {\n id: config.id ?? \"auth\",\n guards: [\n async (ctx) => {\n const keyValue = config.getKey\n ? await config.getKey({\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : ctx.request.headers.get(header);\n\n const key =\n typeof keyValue === \"string\" && keyValue.trim().length > 0 ? keyValue : null;\n\n const valid = config.validate\n ? await config.validate({\n key,\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : key !== null && apiKeys.has(key);\n\n if (valid) {\n return null;\n }\n\n return config.onUnauthorized\n ? await config.onUnauthorized({\n key,\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : createUnauthorizedResponse();\n },\n ],\n };\n};\n","/** Parsed IP value. */\ntype ParsedIp = {\n /** IP family. */\n kind: \"ipv4\" | \"ipv6\";\n /** Numeric IP value. */\n value: bigint;\n /** Bit width for the IP family. */\n bits: number;\n /** Normalized string form. */\n normalized: string;\n};\n\n/** Parses an IPv4 string. */\nfunction parseIpv4(input: string): ParsedIp | null {\n const parts = input.split(\".\");\n if (parts.length !== 4) return null;\n\n let value = 0n;\n for (const part of parts) {\n if (!/^\\d+$/.test(part)) return null;\n const octet = Number(part);\n if (octet < 0 || octet > 255) return null;\n value = (value << 8n) | BigInt(octet);\n }\n\n return {\n kind: \"ipv4\",\n value,\n bits: 32,\n normalized: parts.join(\".\"),\n };\n}\n\n/** Expands an IPv6 string into eight normalized segments. */\nfunction expandIpv6Segments(input: string): string[] | null {\n const zoneIndex = input.indexOf(\"%\");\n const value = zoneIndex >= 0 ? input.slice(0, zoneIndex) : input;\n if (value.length === 0) return null;\n\n const doubleColonCount = value.split(\"::\").length - 1;\n if (doubleColonCount > 1) return null;\n\n const [leftRaw = \"\", rightRaw = \"\"] = value.split(\"::\");\n const left = leftRaw.length > 0 ? leftRaw.split(\":\") : [];\n const right = rightRaw.length > 0 ? rightRaw.split(\":\") : [];\n\n const normalizedRight = [...right];\n if (normalizedRight.length > 0) {\n const last = normalizedRight[normalizedRight.length - 1];\n if (last?.includes(\".\")) {\n const ipv4 = parseIpv4(last);\n if (!ipv4) return null;\n normalizedRight.splice(\n normalizedRight.length - 1,\n 1,\n Number((ipv4.value >> 16n) & 0xffffn).toString(16),\n Number(ipv4.value & 0xffffn).toString(16),\n );\n }\n }\n\n const normalizedLeft = [...left];\n if (normalizedLeft.length > 0) {\n const last = normalizedLeft[normalizedLeft.length - 1];\n if (last?.includes(\".\")) {\n const ipv4 = parseIpv4(last);\n if (!ipv4) return null;\n normalizedLeft.splice(\n normalizedLeft.length - 1,\n 1,\n Number((ipv4.value >> 16n) & 0xffffn).toString(16),\n Number(ipv4.value & 0xffffn).toString(16),\n );\n }\n }\n\n const totalSegments = normalizedLeft.length + normalizedRight.length;\n if (doubleColonCount === 0 && totalSegments !== 8) return null;\n if (doubleColonCount === 1 && totalSegments >= 8) return null;\n\n const missing = doubleColonCount === 1 ? 8 - totalSegments : 0;\n const segments = [\n ...normalizedLeft,\n ...Array.from({ length: missing }, () => \"0\"),\n ...normalizedRight,\n ];\n\n if (segments.length !== 8) return null;\n if (segments.some((segment) => !/^[0-9a-fA-F]{1,4}$/.test(segment))) return null;\n\n return segments.map((segment) => segment.toLowerCase());\n}\n\n/** Parses an IPv6 string. */\nfunction parseIpv6(input: string): ParsedIp | null {\n const segments = expandIpv6Segments(input);\n if (!segments) return null;\n\n let value = 0n;\n for (const segment of segments) {\n value = (value << 16n) | BigInt(Number.parseInt(segment, 16));\n }\n\n return {\n kind: \"ipv6\",\n value,\n bits: 128,\n normalized: segments.join(\":\"),\n };\n}\n\n/** Parses an IPv4 or IPv6 string. */\nexport function parseIp(input: string): ParsedIp | null {\n const value = input.trim();\n if (value.length === 0) return null;\n return parseIpv4(value) ?? parseIpv6(value);\n}\n\n/** Normalizes an IP string. */\nexport function normalizeIp(input: string): string | null {\n return parseIp(input)?.normalized ?? null;\n}\n\nexport type { ParsedIp };\n","import { type ParsedIp, parseIp } from \"./ip\";\n\n/** Matcher for one allowed IP entry. */\nexport type IpMatcher = {\n /** Original allowlist entry. */\n raw: string;\n /** Returns true when the IP matches this entry. */\n matches: (ip: ParsedIp) => boolean;\n};\n\n/** Creates a network mask for the given prefix. */\nfunction createMask(bits: number, prefix: number): bigint {\n if (prefix === 0) return 0n;\n return ((1n << BigInt(prefix)) - 1n) << BigInt(bits - prefix);\n}\n\n/** Parses one allowlist IP or CIDR entry. */\nexport function parseAllowEntry(input: string): IpMatcher | null {\n const raw = input.trim();\n if (raw.length === 0) return null;\n\n const slashIndex = raw.indexOf(\"/\");\n if (slashIndex === -1) {\n const parsed = parseIp(raw);\n if (!parsed) return null;\n return {\n raw,\n matches: (ip) => ip.kind === parsed.kind && ip.value === parsed.value,\n };\n }\n\n const addressPart = raw.slice(0, slashIndex).trim();\n const prefixPart = raw.slice(slashIndex + 1).trim();\n if (!/^\\d+$/.test(prefixPart)) return null;\n\n const parsed = parseIp(addressPart);\n if (!parsed) return null;\n\n const prefix = Number(prefixPart);\n if (prefix < 0 || prefix > parsed.bits) return null;\n\n const mask = createMask(parsed.bits, prefix);\n const network = parsed.value & mask;\n\n return {\n raw,\n matches: (ip) => ip.kind === parsed.kind && (ip.value & mask) === network,\n };\n}\n","import { jsonResponse } from \"../shared/json\";\n\n/** Creates the default IP denied response. */\nexport function createIpDeniedResponse(): Response {\n return jsonResponse(\n {\n error: \"forbidden\",\n message: \"IP address is not allowed.\",\n },\n { status: 403 },\n );\n}\n","import { createValidationError, requireNonEmptyArray } from \"../shared/validation\";\nimport { parseAllowEntry } from \"./cidr\";\nimport type { IpAllowlistPluginConfig } from \"./types\";\n\n/** Validates `ipAllowlistPlugin` configuration. */\nexport function validateIpAllowlistPluginConfig(config: IpAllowlistPluginConfig): void {\n requireNonEmptyArray(config.allow, \"allow\", \"plugins.ipAllowlistPlugin\");\n\n for (const entry of config.allow) {\n if (typeof entry !== \"string\" || !parseAllowEntry(entry)) {\n throw createValidationError(\n `\\`ipAllowlistPlugin\\` received an invalid allow entry: '${String(entry)}'.`,\n \"plugins.ipAllowlistPlugin\",\n );\n }\n }\n}\n","import type { Plugin } from \"@better-agent/core\";\nimport { parseAllowEntry } from \"./cidr\";\nimport { normalizeIp, parseIp } from \"./ip\";\nimport { createIpDeniedResponse } from \"./responses\";\nimport type { IpAllowlistPluginConfig } from \"./types\";\nimport { validateIpAllowlistPluginConfig } from \"./validate\";\n\n/** Reads the first valid forwarded IP. */\nfunction getProxyIp(request: Request): string | null {\n const forwardedFor = request.headers.get(\"x-forwarded-for\");\n if (!forwardedFor) return null;\n\n for (const part of forwardedFor.split(\",\")) {\n const normalized = normalizeIp(part.trim());\n if (normalized) {\n return normalized;\n }\n }\n\n return null;\n}\n\n/** Reads a direct client IP from common proxy headers. */\nfunction getDirectIp(request: Request): string | null {\n const candidates = [\n request.headers.get(\"x-real-ip\"),\n request.headers.get(\"cf-connecting-ip\"),\n request.headers.get(\"fly-client-ip\"),\n request.headers.get(\"fastly-client-ip\"),\n request.headers.get(\"x-client-ip\"),\n ];\n\n for (const candidate of candidates) {\n if (!candidate) continue;\n const normalized = normalizeIp(candidate);\n if (normalized) {\n return normalized;\n }\n }\n\n return null;\n}\n\n/**\n * Creates an IP allowlist plugin.\n *\n * @example\n * ```ts\n * const plugin = ipAllowlistPlugin({\n * allow: [\"127.0.0.1\", \"10.0.0.0/8\"],\n * });\n * ```\n */\nexport const ipAllowlistPlugin = (config: IpAllowlistPluginConfig): Plugin => {\n validateIpAllowlistPluginConfig(config);\n\n const matchers = config.allow.map((entry) => {\n const matcher = parseAllowEntry(entry);\n if (!matcher) {\n throw new Error(`Invalid allowlist entry: ${entry}`);\n }\n return matcher;\n });\n\n return {\n id: config.id ?? \"ip-allowlist\",\n guards: [\n async (ctx) => {\n const resolvedIp = config.getIp\n ? await config.getIp({\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : config.trustProxy\n ? getProxyIp(ctx.request)\n : getDirectIp(ctx.request);\n\n const normalizedIp =\n typeof resolvedIp === \"string\" && resolvedIp.trim().length > 0\n ? normalizeIp(resolvedIp)\n : null;\n const parsedIp = normalizedIp ? parseIp(normalizedIp) : null;\n\n if (parsedIp && matchers.some((matcher) => matcher.matches(parsedIp))) {\n return null;\n }\n\n return config.onDenied\n ? await config.onDenied({\n ip: normalizedIp,\n agentName: ctx.agentName,\n mode: ctx.mode,\n request: ctx.request,\n })\n : createIpDeniedResponse();\n },\n ],\n };\n};\n","import type { LogEntry, LoggingPluginConfig } from \"./types\";\n\nconst order: Record<LogEntry[\"level\"], number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\n/** Returns true when the entry should be logged at the current level. */\nexport function shouldLog(\n currentLevel: NonNullable<LoggingPluginConfig[\"level\"]>,\n entry: LogEntry,\n): boolean {\n return order[entry.level] >= order[currentLevel];\n}\n","const DEFAULT_REDACT_HEADERS = [\"authorization\", \"cookie\", \"set-cookie\", \"x-api-key\"] as const;\n\n/** Redacts sensitive headers. */\nexport function redactHeaders(\n headers: Headers,\n extraHeaders?: readonly string[],\n): Record<string, string> {\n const redactSet = new Set(\n [...DEFAULT_REDACT_HEADERS, ...(extraHeaders ?? [])].map((value) => value.toLowerCase()),\n );\n const result: Record<string, string> = {};\n\n headers.forEach((value, key) => {\n result[key] = redactSet.has(key.toLowerCase()) ? \"[REDACTED]\" : value;\n });\n\n return result;\n}\n","import type { LoggingPluginConfig } from \"./types\";\n\n/** Validates `loggingPlugin` configuration. */\nexport function validateLoggingPluginConfig(_config: LoggingPluginConfig): void {}\n","import type { Plugin } from \"@better-agent/core\";\nimport type { PluginOnStepContext, PluginSaveContext } from \"@better-agent/core\";\nimport type { Event } from \"@better-agent/core/events\";\nimport { shouldLog } from \"./format\";\nimport { redactHeaders } from \"./redact\";\nimport type { LogEntry, LoggingPluginConfig } from \"./types\";\nimport { validateLoggingPluginConfig } from \"./validate\";\n\nfunction safeInvoke(fn: ((...args: unknown[]) => void) | undefined, payload: unknown): void {\n if (!fn) return;\n try {\n fn(payload);\n } catch {\n // Logging must never affect runtime execution.\n }\n}\n\n/** Resolves the logger methods for the configured sink. */\nfunction getLoggerMethods(config: LoggingPluginConfig) {\n return {\n debug: config.logger?.debug ?? console.debug,\n info: config.logger?.info ?? console.info,\n warn: config.logger?.warn ?? console.warn,\n error: config.logger?.error ?? console.error,\n };\n}\n\n/** Emits one log entry. */\nfunction emitLog(config: LoggingPluginConfig, entry: LogEntry): void {\n const level = config.level ?? \"info\";\n if (!shouldLog(level, entry)) return;\n\n const output = config.format ? config.format(entry) : entry;\n const logger = getLoggerMethods(config);\n safeInvoke(logger[entry.level], output);\n}\n\n/** Maps one runtime event to a log level. */\nfunction getEventLevel(event: Event): LogEntry[\"level\"] {\n if (event.type.endsWith(\"_ERROR\")) return \"error\";\n return \"info\";\n}\n\n/** Creates request log data. */\nfunction createRequestData(ctx: Parameters<NonNullable<Plugin[\"guards\"]>[number]>[0]) {\n return {\n mode: ctx.mode,\n url: ctx.request.url,\n method: ctx.request.method,\n headers: redactHeaders(ctx.request.headers),\n input: ctx.input,\n };\n}\n\n/** Creates step log data. */\nfunction createStepData(ctx: PluginOnStepContext) {\n return {\n stepIndex: ctx.stepIndex,\n maxSteps: ctx.maxSteps,\n messageCount: ctx.messages.length,\n };\n}\n\n/** Creates save log data. */\nfunction createSaveData(ctx: PluginSaveContext) {\n const messageCount = ctx.items.filter((item) => item.type === \"message\").length;\n\n return {\n itemCount: ctx.items.length,\n messageCount,\n };\n}\n\n/**\n * Creates a logging plugin.\n *\n * @example\n * ```ts\n * const plugin = loggingPlugin({\n * level: \"info\",\n * include: { requests: true, toolCalls: true },\n * });\n * ```\n */\nexport const loggingPlugin = (config: LoggingPluginConfig = {}): Plugin => {\n validateLoggingPluginConfig(config);\n\n const include = {\n requests: config.include?.requests ?? true,\n events: config.include?.events ?? true,\n steps: config.include?.steps ?? true,\n modelCalls: config.include?.modelCalls ?? true,\n toolCalls: config.include?.toolCalls ?? true,\n saves: config.include?.saves ?? false,\n errors: config.include?.errors ?? true,\n };\n\n const plugin: Plugin = {\n id: config.id ?? \"logging\",\n };\n\n if (include.requests) {\n plugin.guards = [\n async (ctx) => {\n const body = config.redactBody\n ? config.redactBody({ body: ctx.input, phase: \"request\" })\n : ctx.input;\n\n emitLog(config, {\n level: \"info\",\n event: \"request.received\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n data: {\n ...createRequestData(ctx),\n input: body,\n },\n });\n\n return null;\n },\n ];\n }\n\n if (include.events) {\n plugin.onEvent = async (event, ctx) => {\n const level = getEventLevel(event);\n if (level === \"error\" && !include.errors) return;\n\n emitLog(config, {\n level,\n event: \"run.event\",\n timestamp: new Date(event.timestamp).toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n type: event.type,\n },\n });\n };\n }\n\n if (include.steps) {\n plugin.onStep = async (ctx) => {\n emitLog(config, {\n level: \"info\",\n event: \"step.start\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: createStepData(ctx),\n });\n };\n }\n\n if (include.modelCalls) {\n plugin.onBeforeModelCall = async (ctx) => {\n emitLog(config, {\n level: \"debug\",\n event: \"model.before\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n stepIndex: ctx.stepIndex,\n inputCount: ctx.input.length,\n toolCount: ctx.tools.length,\n toolChoice: ctx.toolChoice,\n },\n });\n };\n\n plugin.onAfterModelCall = async (ctx) => {\n emitLog(config, {\n level: \"debug\",\n event: \"model.after\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n stepIndex: ctx.stepIndex,\n response: config.redactBody\n ? config.redactBody({ body: ctx.response, phase: \"response\" })\n : ctx.response,\n },\n });\n };\n }\n\n if (include.toolCalls) {\n plugin.onBeforeToolCall = async (ctx) => {\n emitLog(config, {\n level: \"info\",\n event: \"tool.before\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n toolName: ctx.toolName,\n toolCallId: ctx.toolCallId,\n args: config.redactBody\n ? config.redactBody({ body: ctx.args, phase: \"tool_args\" })\n : ctx.args,\n },\n });\n return undefined;\n };\n\n plugin.onAfterToolCall = async (ctx) => {\n emitLog(config, {\n level: ctx.error ? \"error\" : \"info\",\n event: \"tool.after\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n toolName: ctx.toolName,\n toolCallId: ctx.toolCallId,\n error: ctx.error,\n result: config.redactBody\n ? config.redactBody({ body: ctx.result, phase: \"tool_result\" })\n : ctx.result,\n },\n });\n };\n }\n\n if (include.saves) {\n plugin.onBeforeSave = async (ctx) => {\n emitLog(config, {\n level: \"debug\",\n event: \"save.before\",\n timestamp: new Date().toISOString(),\n agentName: ctx.agentName,\n runId: ctx.runId,\n conversationId: ctx.conversationId,\n data: {\n ...createSaveData(ctx),\n items: config.redactBody\n ? config.redactBody({ body: ctx.items, phase: \"save\" })\n : ctx.items,\n },\n });\n };\n }\n\n return plugin;\n};\n","import type { RateLimitBucket } from \"./types\";\n\n/** Creates a rate-limit bucket for the current window. */\nexport function createBucket(params: {\n key: string;\n now: Date;\n windowMs: number;\n}): RateLimitBucket {\n const nowMs = params.now.getTime();\n const windowStartMs = Math.floor(nowMs / params.windowMs) * params.windowMs;\n\n return {\n id: `${windowStartMs}:${params.key}`,\n key: params.key,\n now: params.now,\n windowStart: new Date(windowStartMs),\n windowEnd: new Date(windowStartMs + params.windowMs),\n };\n}\n","import type { RateLimitPluginConfig, RateLimitStorageState } from \"./types\";\n\n/** Creates an in-memory CAS store for rate limiting. */\nexport function createMemoryStore(): NonNullable<RateLimitPluginConfig[\"storage\"]> {\n const rows = new Map<string, RateLimitStorageState>();\n\n return {\n read: async ({ bucket }) => rows.get(bucket.id) ?? null,\n write: async ({ bucket, prevVersion, next }) => {\n const current = rows.get(bucket.id) ?? null;\n if (prevVersion === null) {\n if (current) return false;\n rows.set(bucket.id, next);\n return true;\n }\n\n if (!current || current.version !== prevVersion) {\n return false;\n }\n\n rows.set(bucket.id, next);\n return true;\n },\n };\n}\n","import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport { jsonResponse } from \"../shared/json\";\nimport type { RateLimitBucket } from \"./types\";\n\n/** Creates the default rate-limited response. */\nexport function createRateLimitedResponse(params: {\n bucket: RateLimitBucket;\n nowMs: number;\n key: string;\n max: number;\n}): Response {\n const retryAfter = Math.max(\n 1,\n Math.ceil((params.bucket.windowEnd.getTime() - params.nowMs) / 1000),\n );\n\n return jsonResponse(\n {\n error: \"rate_limited\",\n message: \"Too many requests.\",\n key: params.key,\n limit: params.max,\n remaining: 0,\n resetAt: params.bucket.windowEnd.toISOString(),\n },\n {\n status: 429,\n headers: {\n \"retry-after\": String(retryAfter),\n \"x-ratelimit-limit\": String(params.max),\n \"x-ratelimit-remaining\": \"0\",\n \"x-ratelimit-reset\": String(Math.floor(params.bucket.windowEnd.getTime() / 1000)),\n },\n },\n );\n}\n\n/** Creates the default storage unavailable response. */\nexport function createRateLimitStorageUnavailableResponse(): Response {\n return jsonResponse(\n {\n error: \"service_unavailable\",\n message: \"Rate limit storage is unavailable.\",\n },\n { status: 503 },\n );\n}\n\n/** Creates the CAS retries exceeded error. */\nexport function createCasRetriesExceededError(): BetterAgentError {\n return BetterAgentError.fromCode(\"INTERNAL\", \"Rate limit write failed after CAS retries.\", {\n trace: [{ at: \"plugins.rateLimitPlugin\" }],\n });\n}\n","import { requirePositiveNumber } from \"../shared/validation\";\nimport type { RateLimitPluginConfig } from \"./types\";\n\n/** Validates `rateLimitPlugin` configuration. */\nexport function validateRateLimitPluginConfig(config: RateLimitPluginConfig): void {\n requirePositiveNumber(config.windowMs, \"windowMs\", \"plugins.rateLimitPlugin\");\n requirePositiveNumber(config.max, \"max\", \"plugins.rateLimitPlugin\");\n requirePositiveNumber(config.casRetries ?? 8, \"casRetries\", \"plugins.rateLimitPlugin\");\n}\n","import type { Plugin } from \"@better-agent/core\";\nimport { createBucket } from \"./bucket\";\nimport { createMemoryStore } from \"./memory-store\";\nimport {\n createCasRetriesExceededError,\n createRateLimitStorageUnavailableResponse,\n createRateLimitedResponse,\n} from \"./responses\";\nimport type { RateLimitPluginConfig, RateLimitStorageState } from \"./types\";\nimport { validateRateLimitPluginConfig } from \"./validate\";\n\n/**\n * Creates a rate-limit plugin.\n *\n * Uses an in-memory store by default.\n *\n * @example\n * ```ts\n * const plugin = rateLimitPlugin({\n * windowMs: 60_000,\n * max: 30,\n * });\n * ```\n */\nexport const rateLimitPlugin = (config: RateLimitPluginConfig): Plugin => {\n validateRateLimitPluginConfig(config);\n\n const casRetries = config.casRetries ?? 8;\n const storage = config.storage ?? createMemoryStore();\n\n return {\n id: config.id ?? \"rate-limit\",\n guards: [\n async (ctx) => {\n const request = {\n mode: ctx.mode,\n agentName: ctx.agentName,\n request: ctx.request,\n };\n\n const now = new Date();\n const nowMs = now.getTime();\n const keyFromConfig = config.key\n ? await config.key(request)\n : `${ctx.agentName}:global`;\n const key =\n typeof keyFromConfig === \"string\" && keyFromConfig.trim().length > 0\n ? keyFromConfig.trim()\n : `${ctx.agentName}:global`;\n const bucket = createBucket({\n key,\n now,\n windowMs: config.windowMs,\n });\n\n const handleStoreError = async (error: unknown): Promise<Response | null> => {\n const action = config.onStoreError\n ? await config.onStoreError({ error, bucket, request })\n : \"allow\";\n\n if (action instanceof Response) return action;\n if (action === \"deny\") {\n return createRateLimitStorageUnavailableResponse();\n }\n\n return null;\n };\n\n for (let attempt = 0; attempt < casRetries; attempt += 1) {\n let state: RateLimitStorageState | null = null;\n try {\n state = await storage.read({ bucket, request });\n } catch (error) {\n return handleStoreError(error);\n }\n\n if (state && state.count >= config.max) {\n return createRateLimitedResponse({\n bucket,\n nowMs,\n key,\n max: config.max,\n });\n }\n\n try {\n const written = await storage.write({\n bucket,\n request,\n prevVersion: state?.version ?? null,\n next: {\n count: (state?.count ?? 0) + 1,\n version: (state?.version ?? 0) + 1,\n },\n });\n\n if (written) return null;\n } catch (error) {\n return handleStoreError(error);\n }\n }\n\n return handleStoreError(createCasRetriesExceededError());\n },\n ],\n };\n};\n","import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport type {\n DaytonaSandboxClientConfig,\n SandboxClient,\n SandboxCommandResult,\n SandboxFileEntry,\n SandboxPreviewInfo,\n} from \"./types\";\n\ntype DaytonaModule = {\n Daytona: new (config?: Record<string, unknown>) => DaytonaClientInstance;\n};\n\ntype DaytonaClientInstance = {\n create: (\n params?: Record<string, unknown>,\n options?: {\n timeout?: number;\n onSnapshotCreateLogs?: (chunk: string) => void;\n },\n ) => Promise<DaytonaSandboxInstance>;\n get: (sandboxIdOrName: string) => Promise<DaytonaSandboxInstance>;\n start?: (sandbox: DaytonaSandboxInstance, timeout?: number) => Promise<void>;\n stop?: (sandbox: DaytonaSandboxInstance) => Promise<void>;\n delete?: (sandbox: DaytonaSandboxInstance, timeout?: number) => Promise<void>;\n};\n\ntype DaytonaSandboxInstance = {\n id: string;\n process: {\n executeCommand: (\n command: string,\n cwd?: string,\n envVars?: Record<string, string>,\n timeout?: number,\n ) => Promise<{\n result?: string;\n exitCode?: number;\n }>;\n };\n fs: {\n downloadFile: (remotePath: string, timeout?: number) => Promise<Uint8Array | string>;\n uploadFile: (\n file: Uint8Array | string,\n remotePath: string,\n timeout?: number,\n ) => Promise<void>;\n listFiles: (path: string) => Promise<DaytonaFileInfo[]>;\n createFolder: (path: string, mode: string) => Promise<void>;\n deleteFile: (path: string, recursive?: boolean) => Promise<void>;\n };\n getPreviewLink: (port: number) => Promise<SandboxPreviewInfo>;\n start?: (timeout?: number) => Promise<void>;\n stop?: (timeout?: number) => Promise<void>;\n archive?: () => Promise<void>;\n delete?: (timeout?: number) => Promise<void>;\n};\n\ntype DaytonaFileInfo = {\n name?: string;\n path?: string;\n isDir?: boolean;\n type?: string;\n};\n\nconst loadDaytona = async (): Promise<DaytonaModule> => {\n try {\n const moduleName = \"@daytonaio/sdk\";\n return (await import(moduleName)) as DaytonaModule;\n } catch (error) {\n throw BetterAgentError.fromCode(\n \"INTERNAL\",\n \"The Daytona sandbox client requires the `@daytonaio/sdk` package to be installed in the host app.\",\n {\n cause: error,\n trace: [{ at: \"plugins.sandbox.createDaytonaSandboxClient.loadDaytona\" }],\n },\n );\n }\n};\n\nconst removeUndefined = (value: Record<string, unknown>) =>\n Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));\n\nconst toSeconds = (value: number | undefined): number | undefined =>\n value === undefined ? undefined : Math.max(1, Math.ceil(value / 1000));\n\nconst toUtf8 = (value: Uint8Array | string): string =>\n typeof value === \"string\" ? value : new TextDecoder().decode(value);\n\nconst normalizeFileEntries = (files: DaytonaFileInfo[]): SandboxFileEntry[] =>\n files.map((entry) => ({\n name: entry.name ?? entry.path?.split(\"/\").filter(Boolean).at(-1) ?? \"\",\n path: entry.path ?? entry.name ?? \"\",\n type: entry.type ?? (entry.isDir ? \"directory\" : \"file\"),\n }));\n\n/** Creates a sandbox client backed by the Daytona SDK. */\nexport function createDaytonaSandboxClient(config: DaytonaSandboxClientConfig = {}): SandboxClient {\n const clientConfig = removeUndefined({\n apiKey: config.apiKey,\n apiUrl: config.apiUrl,\n target: config.target,\n });\n\n const buildCreateParams = (overrides?: {\n template?: string;\n envs?: Record<string, string>;\n metadata?: Record<string, string>;\n }) => {\n const template = overrides?.template ?? config.template;\n const templateKind = config.templateKind ?? \"snapshot\";\n\n return removeUndefined({\n language: config.language,\n envVars: overrides?.envs ?? config.envs,\n labels: overrides?.metadata ?? config.metadata,\n public: config.public,\n autoStopInterval: config.autoStopInterval,\n autoArchiveInterval: config.autoArchiveInterval,\n autoDeleteInterval: config.autoDeleteInterval,\n ...(template !== undefined\n ? templateKind === \"image\"\n ? { image: template }\n : { snapshot: template }\n : {}),\n ...(config.snapshot !== undefined ? { snapshot: config.snapshot } : {}),\n ...(config.image !== undefined ? { image: config.image } : {}),\n });\n };\n\n const getClient = async (): Promise<DaytonaClientInstance> => {\n const { Daytona } = await loadDaytona();\n return new Daytona(clientConfig);\n };\n\n const getSandbox = async (\n sandboxId: string,\n ): Promise<{\n client: DaytonaClientInstance;\n sandbox: DaytonaSandboxInstance;\n }> => {\n const client = await getClient();\n return {\n sandbox: await client.get(sandboxId),\n client,\n };\n };\n\n const toCommandResult = (response: {\n result?: string;\n exitCode?: number;\n }): SandboxCommandResult => ({\n exitCode: response.exitCode,\n stdout: response.result,\n });\n\n return {\n provider: \"daytona\",\n capabilities: {\n commands: true,\n filesystem: true,\n preview: true,\n pty: true,\n desktop: true,\n git: true,\n snapshots: true,\n volumes: true,\n lifecycle: {\n start: true,\n stop: true,\n archive: true,\n resume: true,\n },\n },\n\n async createSandbox(params) {\n const client = await getClient();\n const timeout = toSeconds(params?.timeoutMs ?? config.timeoutMs);\n const sandbox = await client.create(buildCreateParams(params), {\n ...(timeout !== undefined ? { timeout } : {}),\n });\n\n return { sandboxId: sandbox.id };\n },\n\n async runCommand(params) {\n const { sandbox } = await getSandbox(params.sandboxId);\n return toCommandResult(\n await sandbox.process.executeCommand(\n params.cmd,\n params.cwd,\n params.envs,\n toSeconds(params.timeoutMs),\n ),\n );\n },\n\n async readFile(params) {\n const { sandbox } = await getSandbox(params.sandboxId);\n return toUtf8(await sandbox.fs.downloadFile(params.path));\n },\n\n async writeFile(params) {\n const { sandbox } = await getSandbox(params.sandboxId);\n await sandbox.fs.uploadFile(Buffer.from(params.content), params.path);\n return { path: params.path };\n },\n\n async listFiles(params) {\n const { sandbox } = await getSandbox(params.sandboxId);\n return normalizeFileEntries(await sandbox.fs.listFiles(params.path));\n },\n\n async makeDir(params) {\n const { sandbox } = await getSandbox(params.sandboxId);\n await sandbox.fs.createFolder(params.path, \"755\");\n return { created: true };\n },\n\n async removePath(params) {\n const { sandbox } = await getSandbox(params.sandboxId);\n await sandbox.fs.deleteFile(params.path, true);\n },\n\n async getHost(params) {\n const { sandbox } = await getSandbox(params.sandboxId);\n return await sandbox.getPreviewLink(params.port);\n },\n\n async killSandbox(params) {\n const { client, sandbox } = await getSandbox(params.sandboxId);\n if (typeof sandbox.delete === \"function\") {\n await sandbox.delete(60);\n return;\n }\n\n if (typeof client.delete === \"function\") {\n await client.delete(sandbox, 60);\n return;\n }\n\n throw BetterAgentError.fromCode(\n \"NOT_IMPLEMENTED\",\n \"The active Daytona SDK instance does not expose sandbox deletion.\",\n {\n context: { sandboxId: params.sandboxId },\n trace: [{ at: \"plugins.sandbox.createDaytonaSandboxClient.killSandbox\" }],\n },\n );\n },\n\n lifecycle: {\n async startSandbox(params) {\n const { client, sandbox } = await getSandbox(params.sandboxId);\n const timeout = toSeconds(params.timeoutMs);\n\n if (typeof sandbox.start === \"function\") {\n await sandbox.start(timeout);\n return;\n }\n\n if (typeof client.start === \"function\") {\n await client.start(sandbox, timeout);\n }\n },\n\n async stopSandbox(params) {\n const { client, sandbox } = await getSandbox(params.sandboxId);\n\n if (typeof sandbox.stop === \"function\") {\n await sandbox.stop(toSeconds(params.timeoutMs));\n return;\n }\n\n if (typeof client.stop === \"function\") {\n await client.stop(sandbox);\n }\n },\n\n async archiveSandbox(params) {\n const { sandbox } = await getSandbox(params.sandboxId);\n if (typeof sandbox.archive === \"function\") {\n await sandbox.archive();\n return;\n }\n\n throw BetterAgentError.fromCode(\n \"NOT_IMPLEMENTED\",\n \"The active Daytona SDK instance does not expose sandbox archiving.\",\n {\n context: { sandboxId: params.sandboxId },\n trace: [\n { at: \"plugins.sandbox.createDaytonaSandboxClient.archiveSandbox\" },\n ],\n },\n );\n },\n },\n };\n}\n","import { BetterAgentError } from \"@better-agent/shared/errors\";\nimport type {\n E2BSandboxClientConfig,\n SandboxClient,\n SandboxCommandParams,\n SandboxCommandResult,\n SandboxFileEntry,\n} from \"./types\";\n\ntype E2BSandboxModule = {\n Sandbox: {\n create: (\n templateOrOptions?: string | Record<string, unknown>,\n options?: Record<string, unknown>,\n ) => Promise<E2BSandboxInstance>;\n connect: (\n sandboxId: string,\n options?: Record<string, unknown>,\n ) => Promise<E2BSandboxInstance>;\n };\n};\n\ntype E2BSandboxInstance = {\n sandboxId: string;\n commands: {\n run: (\n cmd: string,\n options?: Record<string, unknown>,\n ) => Promise<{\n exitCode?: number;\n stdout?: string;\n stderr?: string;\n pid?: number;\n }>;\n };\n files: {\n read: (path: string, options?: Record<string, unknown>) => Promise<string>;\n write: (\n path: string,\n data: string,\n options?: Record<string, unknown>,\n ) => Promise<{ path?: string }>;\n list: (path: string, options?: Record<string, unknown>) => Promise<SandboxFileEntry[]>;\n makeDir: (path: string, options?: Record<string, unknown>) => Promise<boolean>;\n remove: (path: string, options?: Record<string, unknown>) => Promise<void>;\n };\n getHost: (port: number) => string;\n kill: (options?: Record<string, unknown>) => Promise<void>;\n};\n\nconst removeUndefined = (value: Record<string, unknown>) =>\n Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined));\n\nconst loadE2B = async (): Promise<E2BSandboxModule> => {\n try {\n const moduleName = \"e2b\";\n return (await import(moduleName)) as E2BSandboxModule;\n } catch (error) {\n throw BetterAgentError.fromCode(\n \"INTERNAL\",\n \"The built-in E2B sandbox client requires the `e2b` package to be installed in the host app.\",\n {\n cause: error,\n trace: [{ at: \"plugins.sandbox.createE2BSandboxClient.loadE2B\" }],\n },\n );\n }\n};\n\n/** Creates a sandbox client backed by the E2B SDK. */\nexport function createE2BSandboxClient(config: E2BSandboxClientConfig = {}): SandboxClient {\n const connectionOptions = removeUndefined({\n apiKey: config.apiKey,\n accessToken: config.accessToken,\n domain: config.domain,\n requestTimeoutMs: config.requestTimeoutMs,\n });\n\n const toCreateOptions = (overrides?: {\n template?: string;\n timeoutMs?: number;\n envs?: Record<string, string>;\n metadata?: Record<string, string>;\n }) =>\n removeUndefined({\n ...connectionOptions,\n timeoutMs: overrides?.timeoutMs ?? config.timeoutMs,\n envs: overrides?.envs ?? config.envs,\n metadata: overrides?.metadata ?? config.metadata,\n });\n\n const connectSandbox = async (sandboxId: string): Promise<E2BSandboxInstance> => {\n const { Sandbox } = await loadE2B();\n return await Sandbox.connect(sandboxId, connectionOptions);\n };\n\n const mapCommandResult = (\n result: Awaited<ReturnType<E2BSandboxInstance[\"commands\"][\"run\"]>>,\n ): SandboxCommandResult => ({\n exitCode: result.exitCode,\n stdout: result.stdout,\n stderr: result.stderr,\n pid: result.pid,\n });\n\n return {\n provider: \"e2b\",\n capabilities: {\n commands: true,\n filesystem: true,\n preview: true,\n mcp: true,\n pty: true,\n desktop: true,\n },\n async createSandbox(params) {\n const { Sandbox } = await loadE2B();\n const template = params?.template ?? config.template;\n const options = toCreateOptions(params);\n\n const sandbox =\n template !== undefined\n ? await Sandbox.create(template, options)\n : await Sandbox.create(options);\n\n return { sandboxId: sandbox.sandboxId };\n },\n\n async runCommand(params: SandboxCommandParams) {\n const sandbox = await connectSandbox(params.sandboxId);\n return mapCommandResult(\n await sandbox.commands.run(\n params.cmd,\n removeUndefined({\n cwd: params.cwd,\n envs: params.envs,\n timeoutMs: params.timeoutMs,\n }),\n ),\n );\n },\n\n async readFile(params) {\n const sandbox = await connectSandbox(params.sandboxId);\n return await sandbox.files.read(params.path);\n },\n\n async writeFile(params) {\n const sandbox = await connectSandbox(params.sandboxId);\n const result = await sandbox.files.write(params.path, params.content);\n return { path: result.path ?? params.path };\n },\n\n async listFiles(params) {\n const sandbox = await connectSandbox(params.sandboxId);\n return await sandbox.files.list(params.path);\n },\n\n async makeDir(params) {\n const sandbox = await connectSandbox(params.sandboxId);\n return {\n created: await sandbox.files.makeDir(params.path),\n };\n },\n\n async removePath(params) {\n const sandbox = await connectSandbox(params.sandboxId);\n await sandbox.files.remove(params.path);\n },\n\n async getHost(params) {\n const sandbox = await connectSandbox(params.sandboxId);\n return sandbox.getHost(params.port);\n },\n\n async killSandbox(params) {\n const sandbox = await connectSandbox(params.sandboxId);\n await sandbox.kill();\n },\n };\n}\n","import type { SandboxSessionStore } from \"./types\";\n\n/** Creates an in-memory sandbox session store. */\nexport function createMemorySandboxSessionStore(): SandboxSessionStore {\n const sessions = new Map<string, string>();\n\n return {\n async get(key) {\n return sessions.get(key) ?? null;\n },\n async set(key, sandboxId) {\n sessions.set(key, sandboxId);\n },\n async delete(key) {\n sessions.delete(key);\n },\n };\n}\n","import { createValidationError } from \"../shared/validation\";\nimport type { SandboxPluginConfig } from \"./types\";\n\n/** Validates `sandboxPlugin` configuration. */\nexport function validateSandboxPluginConfig(config: SandboxPluginConfig): void {\n const client = config.client;\n\n if (!client || typeof client !== \"object\") {\n throw createValidationError(\n \"`sandboxPlugin` requires a `client`.\",\n \"plugins.sandboxPlugin\",\n );\n }\n\n if (config.prefix !== undefined && config.prefix.trim().length === 0) {\n throw createValidationError(\n \"`sandboxPlugin` requires `prefix` to be a non-empty string when provided.\",\n \"plugins.sandboxPlugin\",\n );\n }\n}\n","import { type Plugin, type ToolRunContext, defineTool } from \"@better-agent/core\";\nimport { BetterAgentError } from \"@better-agent/shared/errors\";\nimport { createMemorySandboxSessionStore } from \"./memory-store\";\nimport type { SandboxCreateParams, SandboxPluginConfig } from \"./types\";\nimport { validateSandboxPluginConfig } from \"./validate\";\n\nconst trimToUndefined = (value: string | undefined): string | undefined => {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n};\n\nconst normalizeHostUrl = (value: string): string =>\n /^[a-z][a-z0-9+.-]*:\\/\\//i.test(value) ? value : `https://${value}`;\n\nconst createValidationError = (message: string, at: string, context?: Record<string, unknown>) =>\n BetterAgentError.fromCode(\"VALIDATION_FAILED\", message, {\n ...(context !== undefined ? { context } : {}),\n trace: [{ at }],\n });\n\ntype ResolvedSandboxRef = {\n sandboxId: string;\n sessionKey?: string;\n created: boolean;\n};\n\ntype SessionPolicy =\n | {\n kind: \"managed\";\n sessionKey: string;\n }\n | {\n kind: \"disabled\";\n };\n\n/**\n * Adds sandbox tools.\n *\n * By default, the plugin reuses one sandbox per `conversationId`.\n * Use `sessionKey` to customize reuse, or return `null`/`undefined`\n * to disable reuse for a specific tool call.\n *\n * Uses an in-memory store by default.\n *\n * @example\n * ```ts\n * import { sandboxPlugin, createE2BSandboxClient } from \"@better-agent/plugins\";\n *\n * const plugin = sandboxPlugin({\n * client: createE2BSandboxClient({\n * apiKey: process.env.E2B_API_KEY,\n * }),\n * defaults: {\n * template: \"base\",\n * timeoutMs: 10 * 60_000,\n * },\n * });\n * ```\n */\nexport const sandboxPlugin = (config: SandboxPluginConfig): Plugin => {\n validateSandboxPluginConfig(config);\n\n const sandboxClient = config.client;\n const store = config.store ?? createMemorySandboxSessionStore();\n const prefix = trimToUndefined(config.prefix) ?? \"sandbox\";\n const nameFor = (suffix: string) => `${prefix}_${suffix}`;\n\n const getSessionPolicy = (ctx: ToolRunContext, toolName: string): SessionPolicy => {\n if (config.sessionKey) {\n const custom = trimToUndefined(\n config.sessionKey({\n runId: ctx.runId,\n agentName: ctx.agentName,\n ...(ctx.conversationId !== undefined\n ? { conversationId: ctx.conversationId }\n : {}),\n toolName,\n }) ?? undefined,\n );\n\n return custom !== undefined\n ? { kind: \"managed\", sessionKey: custom }\n : { kind: \"disabled\" };\n }\n\n return ctx.conversationId\n ? { kind: \"managed\", sessionKey: `conversation:${ctx.conversationId}` }\n : { kind: \"disabled\" };\n };\n\n const getExplicitSandboxId = (value: string | undefined): string | undefined => {\n if (value === undefined) {\n return undefined;\n }\n\n const trimmed = value.trim();\n if (!trimmed) {\n throw createValidationError(\n \"`sandboxId` must be a non-empty string when provided.\",\n \"plugins.sandboxPlugin.sandboxId\",\n );\n }\n\n return trimmed;\n };\n\n const createSandbox = async (\n params: SandboxCreateParams | undefined,\n ctx: ToolRunContext,\n toolName: string,\n ): Promise<ResolvedSandboxRef> => {\n const sessionPolicy = getSessionPolicy(ctx, toolName);\n const created = await sandboxClient.createSandbox({\n template: params?.template ?? config.defaults?.template,\n timeoutMs: params?.timeoutMs ?? config.defaults?.timeoutMs,\n envs: params?.envs ?? config.defaults?.envs,\n metadata: params?.metadata ?? config.defaults?.metadata,\n });\n\n if (sessionPolicy.kind === \"managed\") {\n await store.set(sessionPolicy.sessionKey, created.sandboxId);\n }\n\n return {\n sandboxId: created.sandboxId,\n ...(sessionPolicy.kind === \"managed\" ? { sessionKey: sessionPolicy.sessionKey } : {}),\n created: true,\n };\n };\n\n const resolveSandbox = async (params: {\n sandboxId?: string;\n createIfMissing: boolean;\n createParams?: SandboxCreateParams;\n ctx: ToolRunContext;\n toolName: string;\n }): Promise<ResolvedSandboxRef> => {\n const explicitSandboxId = getExplicitSandboxId(params.sandboxId);\n if (explicitSandboxId) {\n return { sandboxId: explicitSandboxId, created: false };\n }\n\n const sessionPolicy = getSessionPolicy(params.ctx, params.toolName);\n if (sessionPolicy.kind === \"managed\") {\n const existing = trimToUndefined(\n (await store.get(sessionPolicy.sessionKey)) ?? undefined,\n );\n if (existing) {\n return {\n sandboxId: existing,\n sessionKey: sessionPolicy.sessionKey,\n created: false,\n };\n }\n }\n\n if (!params.createIfMissing) {\n throw createValidationError(\n `No sandbox is available for this ${params.ctx.conversationId ? \"conversation\" : \"run\"}. Create one first with '${nameFor(\"create\")}' or pass a sandboxId explicitly.`,\n \"plugins.sandboxPlugin.resolveSandbox.missing\",\n {\n runId: params.ctx.runId,\n agentName: params.ctx.agentName,\n conversationId: params.ctx.conversationId,\n toolName: params.toolName,\n },\n );\n }\n\n return await createSandbox(params.createParams, params.ctx, params.toolName);\n };\n\n const clearManagedSessionIfMatches = async (\n ctx: ToolRunContext,\n toolName: string,\n sandboxId: string,\n ): Promise<string | undefined> => {\n const sessionPolicy = getSessionPolicy(ctx, toolName);\n if (sessionPolicy.kind !== \"managed\") {\n return undefined;\n }\n\n const current = await store.get(sessionPolicy.sessionKey);\n if (current === sandboxId) {\n await store.delete(sessionPolicy.sessionKey);\n return sessionPolicy.sessionKey;\n }\n\n return undefined;\n };\n\n const createSchema = {\n type: \"object\",\n properties: {\n forceNew: { type: \"boolean\" },\n template: { type: \"string\" },\n timeoutMs: { type: \"number\", exclusiveMinimum: 0 },\n envs: {\n type: \"object\",\n additionalProperties: { type: \"string\" },\n },\n metadata: {\n type: \"object\",\n additionalProperties: { type: \"string\" },\n },\n },\n additionalProperties: false,\n } as const;\n\n const sandboxIdSchema = {\n type: \"string\",\n } as const;\n\n const pathSchema = {\n type: \"string\",\n minLength: 1,\n } as const;\n\n const envsSchema = {\n type: \"object\",\n additionalProperties: { type: \"string\" },\n } as const;\n\n const createTool = defineTool({\n name: nameFor(\"create\"),\n description:\n \"Create a sandbox, or reuse the current conversation sandbox unless forceNew is true.\",\n schema: createSchema,\n }).server(async (input, ctx) => {\n if (!input.forceNew) {\n const sessionPolicy = getSessionPolicy(ctx, nameFor(\"create\"));\n if (sessionPolicy.kind === \"managed\") {\n const existing = trimToUndefined(\n (await store.get(sessionPolicy.sessionKey)) ?? undefined,\n );\n if (existing) {\n return {\n sandboxId: existing,\n reused: true,\n created: false,\n sessionKey: sessionPolicy.sessionKey,\n };\n }\n }\n }\n\n const resolved = await createSandbox(\n {\n template: input.template,\n timeoutMs: input.timeoutMs,\n envs: input.envs,\n metadata: input.metadata,\n },\n ctx,\n nameFor(\"create\"),\n );\n\n return {\n sandboxId: resolved.sandboxId,\n reused: false,\n created: true,\n ...(resolved.sessionKey !== undefined ? { sessionKey: resolved.sessionKey } : {}),\n };\n });\n\n const execTool = defineTool({\n name: nameFor(\"exec\"),\n description:\n \"Run one shell command inside a sandbox. Creates a sandbox automatically when none exists for the conversation.\",\n schema: {\n type: \"object\",\n properties: {\n sandboxId: sandboxIdSchema,\n cmd: { type: \"string\", minLength: 1 },\n cwd: { type: \"string\" },\n timeoutMs: { type: \"number\", exclusiveMinimum: 0 },\n envs: envsSchema,\n },\n required: [\"cmd\"],\n additionalProperties: false,\n } as const,\n approval: config.approvals?.exec,\n }).server(async (input, ctx) => {\n const resolved = await resolveSandbox({\n sandboxId: input.sandboxId,\n createIfMissing: true,\n ctx,\n toolName: nameFor(\"exec\"),\n });\n const result = await sandboxClient.runCommand({\n sandboxId: resolved.sandboxId,\n cmd: input.cmd,\n cwd: input.cwd,\n timeoutMs: input.timeoutMs,\n envs: input.envs,\n });\n\n return {\n sandboxId: resolved.sandboxId,\n createdSandbox: resolved.created,\n ...result,\n };\n });\n\n const readFileTool = defineTool({\n name: nameFor(\"read_file\"),\n description:\n \"Read one text file from a sandbox. Creates a sandbox automatically when none exists for the conversation.\",\n schema: {\n type: \"object\",\n properties: {\n sandboxId: sandboxIdSchema,\n path: pathSchema,\n },\n required: [\"path\"],\n additionalProperties: false,\n } as const,\n }).server(async (input, ctx) => {\n const resolved = await resolveSandbox({\n sandboxId: input.sandboxId,\n createIfMissing: true,\n ctx,\n toolName: nameFor(\"read_file\"),\n });\n\n return {\n sandboxId: resolved.sandboxId,\n path: input.path,\n content: await sandboxClient.readFile({\n sandboxId: resolved.sandboxId,\n path: input.path,\n }),\n };\n });\n\n const writeFileTool = defineTool({\n name: nameFor(\"write_file\"),\n description:\n \"Write one text file into a sandbox. Creates a sandbox automatically when none exists for the conversation.\",\n schema: {\n type: \"object\",\n properties: {\n sandboxId: sandboxIdSchema,\n path: pathSchema,\n content: { type: \"string\" },\n },\n required: [\"path\", \"content\"],\n additionalProperties: false,\n } as const,\n approval: config.approvals?.writeFile,\n }).server(async (input, ctx) => {\n const resolved = await resolveSandbox({\n sandboxId: input.sandboxId,\n createIfMissing: true,\n ctx,\n toolName: nameFor(\"write_file\"),\n });\n const result = await sandboxClient.writeFile({\n sandboxId: resolved.sandboxId,\n path: input.path,\n content: input.content,\n });\n\n return {\n sandboxId: resolved.sandboxId,\n createdSandbox: resolved.created,\n path: result.path,\n };\n });\n\n const listFilesTool = defineTool({\n name: nameFor(\"list_files\"),\n description:\n \"List directory entries inside a sandbox. Creates a sandbox automatically when none exists for the conversation.\",\n schema: {\n type: \"object\",\n properties: {\n sandboxId: sandboxIdSchema,\n path: pathSchema,\n },\n required: [\"path\"],\n additionalProperties: false,\n } as const,\n }).server(async (input, ctx) => {\n const resolved = await resolveSandbox({\n sandboxId: input.sandboxId,\n createIfMissing: true,\n ctx,\n toolName: nameFor(\"list_files\"),\n });\n\n return {\n sandboxId: resolved.sandboxId,\n path: input.path,\n entries: await sandboxClient.listFiles({\n sandboxId: resolved.sandboxId,\n path: input.path,\n }),\n };\n });\n\n const makeDirTool = defineTool({\n name: nameFor(\"make_dir\"),\n description:\n \"Create a directory inside a sandbox. Creates a sandbox automatically when none exists for the conversation.\",\n schema: {\n type: \"object\",\n properties: {\n sandboxId: sandboxIdSchema,\n path: pathSchema,\n },\n required: [\"path\"],\n additionalProperties: false,\n } as const,\n }).server(async (input, ctx) => {\n const resolved = await resolveSandbox({\n sandboxId: input.sandboxId,\n createIfMissing: true,\n ctx,\n toolName: nameFor(\"make_dir\"),\n });\n const result = await sandboxClient.makeDir({\n sandboxId: resolved.sandboxId,\n path: input.path,\n });\n\n return {\n sandboxId: resolved.sandboxId,\n path: input.path,\n created: result.created,\n };\n });\n\n const removePathTool = defineTool({\n name: nameFor(\"remove_path\"),\n description: \"Remove a file or directory from a sandbox.\",\n schema: {\n type: \"object\",\n properties: {\n sandboxId: sandboxIdSchema,\n path: pathSchema,\n },\n required: [\"path\"],\n additionalProperties: false,\n } as const,\n approval: config.approvals?.removePath,\n }).server(async (input, ctx) => {\n const resolved = await resolveSandbox({\n sandboxId: input.sandboxId,\n createIfMissing: false,\n ctx,\n toolName: nameFor(\"remove_path\"),\n });\n await sandboxClient.removePath({\n sandboxId: resolved.sandboxId,\n path: input.path,\n });\n\n return {\n sandboxId: resolved.sandboxId,\n removed: true,\n path: input.path,\n };\n });\n\n const getHostTool = defineTool({\n name: nameFor(\"get_host\"),\n description:\n \"Expose one sandbox port as a host URL so callers can reach an app running inside the sandbox.\",\n schema: {\n type: \"object\",\n properties: {\n sandboxId: sandboxIdSchema,\n port: { type: \"number\", minimum: 1, maximum: 65535 },\n },\n required: [\"port\"],\n additionalProperties: false,\n } as const,\n }).server(async (input, ctx) => {\n const resolved = await resolveSandbox({\n sandboxId: input.sandboxId,\n createIfMissing: false,\n ctx,\n toolName: nameFor(\"get_host\"),\n });\n const hostResult = await sandboxClient.getHost({\n sandboxId: resolved.sandboxId,\n port: input.port,\n });\n const preview = typeof hostResult === \"string\" ? undefined : hostResult;\n const host = normalizeHostUrl(typeof hostResult === \"string\" ? hostResult : hostResult.url);\n\n return {\n sandboxId: resolved.sandboxId,\n port: input.port,\n host,\n ...(preview?.token !== undefined ? { token: preview.token } : {}),\n };\n });\n\n const killTool = defineTool({\n name: nameFor(\"kill\"),\n description:\n \"Terminate a sandbox and clear the current conversation sandbox when applicable.\",\n schema: {\n type: \"object\",\n properties: {\n sandboxId: sandboxIdSchema,\n },\n additionalProperties: false,\n } as const,\n approval: config.approvals?.killSandbox,\n }).server(async (input, ctx) => {\n const resolved = await resolveSandbox({\n sandboxId: input.sandboxId,\n createIfMissing: false,\n ctx,\n toolName: nameFor(\"kill\"),\n });\n\n await sandboxClient.killSandbox({\n sandboxId: resolved.sandboxId,\n });\n\n const clearedSessionKey = await clearManagedSessionIfMatches(\n ctx,\n nameFor(\"kill\"),\n resolved.sandboxId,\n );\n\n return {\n sandboxId: resolved.sandboxId,\n killed: true,\n ...(clearedSessionKey !== undefined ? { clearedSessionKey } : {}),\n };\n });\n\n // @ts-ignore\n const tools = [\n createTool,\n execTool,\n readFileTool,\n writeFileTool,\n listFilesTool,\n makeDirTool,\n removePathTool,\n getHostTool,\n killTool,\n ];\n\n const plugin: Plugin = {\n id: config.id ?? \"sandbox\",\n tools,\n };\n\n return plugin;\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-agent/plugins",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.2",
4
4
  "description": "Better Agent plugins TypeScript library",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -36,13 +36,15 @@
36
36
  "access": "public"
37
37
  },
38
38
  "dependencies": {
39
- "@better-agent/shared": "0.1.0-canary.2"
39
+ "@better-agent/shared": "0.1.0-beta.2"
40
40
  },
41
41
  "devDependencies": {
42
+ "@daytonaio/sdk": "^0.161.0",
42
43
  "@types/bun": "^1.2.18",
43
- "@types/node": "^22.15.30"
44
+ "@types/node": "^22.15.30",
45
+ "e2b": "^2.19.0"
44
46
  },
45
47
  "peerDependencies": {
46
- "@better-agent/core": "0.1.0-canary.2"
48
+ "@better-agent/core": "0.1.0-beta.2"
47
49
  }
48
50
  }