trusera-sdk 0.2.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/events.ts","../src/interceptor.ts","../src/standalone.ts","../src/cedar.ts","../src/integrations/langchain.ts"],"sourcesContent":["/**\n * Trusera SDK - TypeScript SDK for monitoring AI agents\n *\n * @packageDocumentation\n */\n\nexport { TruseraClient } from \"./client.js\";\nexport type { TruseraClientOptions } from \"./client.js\";\n\nexport { TruseraInterceptor } from \"./interceptor.js\";\nexport type { InterceptorOptions, EnforcementMode } from \"./interceptor.js\";\n\nexport { StandaloneInterceptor } from \"./standalone.js\";\nexport type { StandaloneInterceptorOptions, StandaloneEnforcementMode } from \"./standalone.js\";\n\nexport { CedarEvaluator } from \"./cedar.js\";\nexport type { PolicyContext, PolicyDecision } from \"./cedar.js\";\n\nexport { EventType, createEvent, isValidEvent } from \"./events.js\";\nexport type { Event } from \"./events.js\";\n\nexport { TruseraLangChainHandler } from \"./integrations/langchain.js\";\nexport type { LangChainHandlerOptions } from \"./integrations/langchain.js\";\n","import type { Event } from \"./events.js\";\n\n/**\n * Configuration options for TruseraClient.\n */\nexport interface TruseraClientOptions {\n /** API key for authenticating with Trusera backend (tsk_xxx) */\n apiKey: string;\n /** Base URL for Trusera API (defaults to production) */\n baseUrl?: string;\n /** Agent identifier (auto-registered if not provided) */\n agentId?: string;\n /** Interval in ms to auto-flush events (default: 5000) */\n flushInterval?: number;\n /** Max events per batch (default: 100) */\n batchSize?: number;\n /** Enable debug logging to console */\n debug?: boolean;\n}\n\n/**\n * Response from agent registration endpoint.\n */\ninterface RegisterAgentResponse {\n agent_id: string;\n name: string;\n created_at: string;\n}\n\n/**\n * Core client for tracking AI agent events and sending them to Trusera.\n * Handles batching, automatic flushing, and agent registration.\n *\n * @example\n * ```typescript\n * const client = new TruseraClient({\n * apiKey: \"tsk_your_key_here\",\n * agentId: \"my-agent-123\"\n * });\n *\n * client.track(createEvent(EventType.TOOL_CALL, \"github.search\", { query: \"AI\" }));\n * await client.close(); // Flush remaining events and cleanup\n * ```\n */\nexport class TruseraClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly batchSize: number;\n private readonly flushInterval: number;\n private readonly debug: boolean;\n\n private agentId: string | undefined;\n private eventQueue: Event[] = [];\n private flushTimer: NodeJS.Timeout | undefined;\n private isClosed = false;\n\n constructor(options: TruseraClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://api.trusera.io\";\n this.agentId = options.agentId;\n this.batchSize = options.batchSize ?? 100;\n this.flushInterval = options.flushInterval ?? 5000;\n this.debug = options.debug ?? false;\n\n if (!this.apiKey.startsWith(\"tsk_\")) {\n throw new Error(\"Invalid API key format. Must start with 'tsk_'\");\n }\n\n // Start auto-flush timer\n this.startFlushTimer();\n this.log(\"TruseraClient initialized\", { baseUrl: this.baseUrl, batchSize: this.batchSize });\n }\n\n /**\n * Registers a new agent with Trusera backend.\n * Returns the assigned agent_id which should be stored for future use.\n *\n * @param name - Human-readable agent name\n * @param framework - Framework identifier (e.g., \"langchain\", \"autogen\", \"custom\")\n * @returns Agent ID string\n */\n async registerAgent(name: string, framework: string): Promise<string> {\n this.log(\"Registering agent\", { name, framework });\n\n const response = await fetch(`${this.baseUrl}/api/v1/agents/register`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n name,\n framework,\n metadata: {\n sdk_version: \"0.1.0\",\n runtime: \"node\",\n node_version: process.version,\n },\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to register agent: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as RegisterAgentResponse;\n this.agentId = data.agent_id;\n this.log(\"Agent registered\", { agentId: this.agentId });\n return this.agentId;\n }\n\n /**\n * Queues an event for transmission.\n * Events are batched and sent automatically based on flushInterval and batchSize.\n *\n * @param event - Event to track\n */\n track(event: Event): void {\n if (this.isClosed) {\n throw new Error(\"Cannot track events on closed client\");\n }\n\n // Enrich metadata with agent context\n const enrichedEvent: Event = {\n ...event,\n metadata: {\n ...event.metadata,\n agent_id: this.agentId,\n sdk_version: \"0.1.0\",\n },\n };\n\n this.eventQueue.push(enrichedEvent);\n this.log(\"Event tracked\", { type: event.type, name: event.name, queueSize: this.eventQueue.length });\n\n // Auto-flush if batch size reached\n if (this.eventQueue.length >= this.batchSize) {\n void this.flush();\n }\n }\n\n /**\n * Immediately sends all queued events to Trusera backend.\n * Called automatically by flush timer or when batch size is reached.\n *\n * @returns Promise that resolves when events are sent\n */\n async flush(): Promise<void> {\n if (this.eventQueue.length === 0) {\n return;\n }\n\n const batch = this.eventQueue.splice(0, this.batchSize);\n this.log(\"Flushing events\", { count: batch.length });\n\n try {\n const response = await fetch(`${this.baseUrl}/api/v1/events/batch`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({ events: batch }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n console.error(`[Trusera] Failed to send events: ${response.status} ${error}`);\n // Re-queue failed events for retry\n this.eventQueue.unshift(...batch);\n } else {\n this.log(\"Events flushed successfully\", { count: batch.length });\n }\n } catch (error) {\n console.error(\"[Trusera] Network error sending events:\", error);\n // Re-queue failed events\n this.eventQueue.unshift(...batch);\n }\n }\n\n /**\n * Gracefully shuts down the client.\n * Flushes all remaining events and stops the auto-flush timer.\n *\n * @returns Promise that resolves when shutdown is complete\n */\n async close(): Promise<void> {\n this.log(\"Closing client\");\n this.isClosed = true;\n this.stopFlushTimer();\n await this.flush();\n this.log(\"Client closed\");\n }\n\n /**\n * Returns current queue size (useful for monitoring/debugging).\n */\n getQueueSize(): number {\n return this.eventQueue.length;\n }\n\n /**\n * Returns the current agent ID (if registered).\n */\n getAgentId(): string | undefined {\n return this.agentId;\n }\n\n private startFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.flushInterval);\n\n // Don't keep process alive for flush timer\n if (this.flushTimer.unref) {\n this.flushTimer.unref();\n }\n }\n\n private stopFlushTimer(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n }\n\n private log(message: string, data?: Record<string, unknown>): void {\n if (this.debug) {\n console.log(`[Trusera] ${message}`, data ?? \"\");\n }\n }\n}\n","/**\n * Event types tracked by the Trusera SDK.\n * These align with the core observability primitives for AI agent monitoring.\n */\nexport enum EventType {\n /** Tool or function call by the agent */\n TOOL_CALL = \"tool_call\",\n /** LLM inference invocation */\n LLM_INVOKE = \"llm_invoke\",\n /** Data access operation (read/write) */\n DATA_ACCESS = \"data_access\",\n /** Outbound HTTP API call */\n API_CALL = \"api_call\",\n /** File write operation */\n FILE_WRITE = \"file_write\",\n /** Decision point or chain step */\n DECISION = \"decision\",\n}\n\n/**\n * Core event structure for all Trusera tracking.\n * Events are immutable once created and queued for batch transmission.\n */\nexport interface Event {\n /** Unique event identifier (UUIDv4) */\n id: string;\n /** Event type discriminator */\n type: EventType;\n /** Human-readable event name (e.g., \"openai.chat.completions\", \"github.api.repos\") */\n name: string;\n /** Event-specific structured data */\n payload: Record<string, unknown>;\n /** Additional context (agent_id, session_id, tags, etc.) */\n metadata: Record<string, unknown>;\n /** ISO 8601 timestamp */\n timestamp: string;\n}\n\n/**\n * Creates a well-formed Event with automatic ID and timestamp generation.\n *\n * @param type - Event type from EventType enum\n * @param name - Descriptive event name (use dotted notation: \"service.resource.action\")\n * @param payload - Event-specific data (request, response, errors, etc.)\n * @param metadata - Optional metadata (merged with default agent context)\n * @returns Fully populated Event ready for tracking\n *\n * @example\n * ```typescript\n * const event = createEvent(\n * EventType.API_CALL,\n * \"openai.chat.completions\",\n * { model: \"gpt-4\", tokens: 150 },\n * { session_id: \"abc-123\" }\n * );\n * client.track(event);\n * ```\n */\nexport function createEvent(\n type: EventType,\n name: string,\n payload: Record<string, unknown> = {},\n metadata: Record<string, unknown> = {}\n): Event {\n return {\n id: crypto.randomUUID(),\n type,\n name,\n payload: { ...payload },\n metadata: { ...metadata },\n timestamp: new Date().toISOString(),\n };\n}\n\n/**\n * Type guard to validate if an object is a valid Event.\n * Useful for runtime validation before transmission.\n */\nexport function isValidEvent(obj: unknown): obj is Event {\n if (typeof obj !== \"object\" || obj === null) return false;\n const e = obj as Partial<Event>;\n return (\n typeof e.id === \"string\" &&\n typeof e.type === \"string\" &&\n Object.values(EventType).includes(e.type as EventType) &&\n typeof e.name === \"string\" &&\n typeof e.payload === \"object\" &&\n e.payload !== null &&\n typeof e.metadata === \"object\" &&\n e.metadata !== null &&\n typeof e.timestamp === \"string\"\n );\n}\n","import type { TruseraClient } from \"./client.js\";\nimport { EventType, createEvent } from \"./events.js\";\n\n/**\n * Enforcement modes for policy violations.\n */\nexport type EnforcementMode = \"block\" | \"warn\" | \"log\";\n\n/**\n * Configuration for the HTTP interceptor.\n */\nexport interface InterceptorOptions {\n /** How to handle policy violations (default: \"log\") */\n enforcement?: EnforcementMode;\n /** Cedar policy service URL for runtime policy checks */\n policyUrl?: string;\n /** URL patterns to exclude from interception (regex strings) */\n excludePatterns?: string[];\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Policy evaluation request sent to Cedar policy service.\n */\ninterface PolicyEvaluationRequest {\n principal: string;\n action: string;\n resource: string;\n context: Record<string, unknown>;\n}\n\n/**\n * Policy evaluation response from Cedar service.\n */\ninterface PolicyEvaluationResponse {\n decision: \"Allow\" | \"Deny\";\n reasons?: string[];\n}\n\n/**\n * Global interceptor singleton state.\n * Only one interceptor can be active at a time.\n */\nlet activeInterceptor: TruseraInterceptor | null = null;\nlet originalFetch: typeof globalThis.fetch | null = null;\n\n/**\n * Safely require an optional dependency.\n * Returns null if the module is not installed.\n */\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nfunction tryRequire(moduleName: string): any { // eslint-disable-line @typescript-eslint/no-explicit-any\n try {\n return require(moduleName);\n } catch {\n return null;\n }\n}\n\n/**\n * HTTP interceptor for AI agent outbound traffic.\n * Monkey-patches globalThis.fetch, axios, and undici to intercept all HTTP calls,\n * evaluate them against Cedar policies, and track events.\n *\n * @example\n * ```typescript\n * const client = new TruseraClient({ apiKey: \"tsk_xxx\" });\n * const interceptor = new TruseraInterceptor();\n *\n * interceptor.install(client, {\n * enforcement: \"block\",\n * policyUrl: \"https://policy.trusera.io/evaluate\",\n * excludePatterns: [\"^https://api\\\\.trusera\\\\.io/.*\"]\n * });\n *\n * // All fetch/axios/undici calls are now intercepted\n * await fetch(\"https://api.github.com/repos/test\"); // Tracked + policy-checked\n *\n * interceptor.uninstall(); // Restore originals\n * ```\n */\nexport class TruseraInterceptor {\n private client: TruseraClient | null = null;\n private options: Required<InterceptorOptions> = {\n enforcement: \"log\",\n policyUrl: \"\",\n excludePatterns: [],\n debug: false,\n };\n private excludeRegexes: RegExp[] = [];\n private isInstalled = false;\n\n // Axios interception state\n private axiosDefault: any = null; // eslint-disable-line @typescript-eslint/no-explicit-any\n private axiosRequestId: number | null = null;\n private axiosResponseId: number | null = null;\n\n // Undici interception state\n private undiciMod: any = null; // eslint-disable-line @typescript-eslint/no-explicit-any\n private origUndiciRequest: ((...args: any[]) => any) | null = null; // eslint-disable-line @typescript-eslint/no-explicit-any\n private origUndiciFetch: ((...args: any[]) => any) | null = null; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n /**\n * Installs the HTTP interceptor by patching globalThis.fetch, axios, and undici.\n * Only one interceptor can be active at a time.\n *\n * @param client - TruseraClient instance for event tracking\n * @param options - Interceptor configuration\n * @throws Error if another interceptor is already installed\n */\n install(client: TruseraClient, options: InterceptorOptions = {}): void {\n if (activeInterceptor !== null && activeInterceptor !== this) {\n throw new Error(\"Another TruseraInterceptor is already installed. Call uninstall() first.\");\n }\n\n if (this.isInstalled) {\n this.log(\"Interceptor already installed\");\n return;\n }\n\n this.client = client;\n this.options = {\n enforcement: options.enforcement ?? \"log\",\n policyUrl: options.policyUrl ?? \"\",\n excludePatterns: options.excludePatterns ?? [],\n debug: options.debug ?? false,\n };\n\n // Compile exclude patterns to regexes\n this.excludeRegexes = this.options.excludePatterns.map((pattern) => new RegExp(pattern));\n\n // Save original fetch and install interceptor\n if (originalFetch === null) {\n originalFetch = globalThis.fetch;\n }\n\n globalThis.fetch = this.createInterceptedFetch();\n activeInterceptor = this;\n this.isInstalled = true;\n\n // Install optional library interceptors (graceful skip if not available)\n this._installAxios();\n this._installUndici();\n\n this.log(\"Interceptor installed\", {\n enforcement: this.options.enforcement,\n policyUrl: this.options.policyUrl,\n excludePatterns: this.options.excludePatterns.length,\n });\n }\n\n /**\n * Uninstalls the interceptor and restores original fetch, axios, and undici.\n */\n uninstall(): void {\n if (!this.isInstalled) {\n return;\n }\n\n if (originalFetch !== null) {\n globalThis.fetch = originalFetch;\n originalFetch = null; // Reset for next install\n }\n\n this._uninstallAxios();\n this._uninstallUndici();\n\n activeInterceptor = null;\n this.isInstalled = false;\n this.client = null;\n\n this.log(\"Interceptor uninstalled\");\n }\n\n // ─── Shared evaluation + tracking ───────────────────────────────────\n\n /**\n * Shared pre-request evaluation: checks excludes, evaluates Cedar policy,\n * tracks API_CALL event, and returns whether the request should be blocked.\n * Used by fetch, axios, and undici interceptors.\n */\n private async _evaluateAndTrack(\n url: string,\n method: string,\n headers: Record<string, string>\n ): Promise<{ blocked: boolean; reasons: string[] }> {\n if (this.shouldExclude(url)) {\n return { blocked: false, reasons: [] };\n }\n\n const eventName = this.generateEventName(url, method);\n\n const event = createEvent(\n EventType.API_CALL,\n eventName,\n { method, url, headers },\n { interception_mode: this.options.enforcement }\n );\n\n // Evaluate policy if configured\n if (this.options.policyUrl) {\n const policyDecision = await this.evaluatePolicy(url, method, { headers, body: null });\n\n if (policyDecision.decision === \"Deny\") {\n this.log(\"Policy violation detected\", { url, reasons: policyDecision.reasons });\n\n const violationEvent = createEvent(\n EventType.API_CALL,\n `${eventName}.policy_violation`,\n {\n ...event.payload,\n policy_decision: \"Deny\",\n policy_reasons: policyDecision.reasons,\n }\n );\n this.client?.track(violationEvent);\n\n if (this.options.enforcement === \"block\") {\n return { blocked: true, reasons: policyDecision.reasons ?? [] };\n } else if (this.options.enforcement === \"warn\") {\n console.warn(\n `[Trusera] Policy violation (allowed): ${policyDecision.reasons?.join(\", \") ?? \"Request denied\"}`\n );\n }\n }\n }\n\n this.client?.track(event);\n return { blocked: false, reasons: [] };\n }\n\n // ─── Axios interceptor ─────────────────────────────────────────────\n\n private _installAxios(): void {\n const axios = tryRequire(\"axios\");\n if (!axios?.interceptors) return;\n\n this.axiosDefault = axios;\n const self = this;\n\n this.axiosRequestId = axios.interceptors.request.use(\n async (config: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any\n const url = self._resolveAxiosUrl(config);\n const method = ((config.method as string | undefined) ?? \"get\").toUpperCase();\n const headers = self._flattenHeaders(config.headers);\n\n const { blocked, reasons } = await self._evaluateAndTrack(url, method, headers);\n if (blocked) {\n throw new Error(\n `[Trusera] Policy violation: ${reasons.join(\", \") || \"Request denied\"}`\n );\n }\n return config;\n }\n );\n\n this.axiosResponseId = axios.interceptors.response.use(\n (response: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any\n const url = self._resolveAxiosUrl(response.config);\n const method = ((response.config?.method as string | undefined) ?? \"get\").toUpperCase();\n\n if (!self.shouldExclude(url)) {\n const event = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.response`,\n { method, url, status: response.status, status_text: response.statusText }\n );\n self.client?.track(event);\n }\n return response;\n },\n (error: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any\n const config = error?.config;\n if (config) {\n const url = self._resolveAxiosUrl(config);\n const method = ((config.method as string | undefined) ?? \"get\").toUpperCase();\n\n if (!self.shouldExclude(url)) {\n const event = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.error`,\n { method, url, error: (error as Error).message }\n );\n self.client?.track(event);\n }\n }\n return Promise.reject(error as Error);\n }\n );\n\n this.log(\"Axios interceptor installed\");\n }\n\n private _uninstallAxios(): void {\n if (this.axiosDefault) {\n if (this.axiosRequestId !== null) {\n this.axiosDefault.interceptors.request.eject(this.axiosRequestId);\n this.axiosRequestId = null;\n }\n if (this.axiosResponseId !== null) {\n this.axiosDefault.interceptors.response.eject(this.axiosResponseId);\n this.axiosResponseId = null;\n }\n this.axiosDefault = null;\n }\n }\n\n private _resolveAxiosUrl(config: any): string { // eslint-disable-line @typescript-eslint/no-explicit-any\n if (!config) return \"\";\n const base: string = (config.baseURL as string | undefined) ?? \"\";\n const url: string = (config.url as string | undefined) ?? \"\";\n if (url.startsWith(\"http\")) return url;\n return base ? `${base.replace(/\\/$/, \"\")}/${url.replace(/^\\//, \"\")}` : url;\n }\n\n private _flattenHeaders(headers: any): Record<string, string> { // eslint-disable-line @typescript-eslint/no-explicit-any\n if (!headers) return {};\n if (typeof headers.toJSON === \"function\") {\n return headers.toJSON() as Record<string, string>;\n }\n const result: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (typeof v === \"string\") result[k] = v;\n }\n return result;\n }\n\n // ─── Undici interceptor ─────────────────────────────────────────────\n\n private _installUndici(): void {\n const undici = tryRequire(\"undici\");\n if (!undici) return;\n\n this.undiciMod = undici;\n const self = this;\n\n // Patch undici.request\n if (typeof undici.request === \"function\") {\n this.origUndiciRequest = undici.request;\n undici.request = async function interceptedUndiciRequest(\n url: string | URL,\n options?: Record<string, unknown>\n ): Promise<unknown> {\n const urlStr = typeof url === \"string\" ? url : url.href;\n const method = ((options?.method as string | undefined) ?? \"GET\").toUpperCase();\n const headers = self._flattenHeaders(options?.headers);\n\n const { blocked, reasons } = await self._evaluateAndTrack(urlStr, method, headers);\n if (blocked) {\n throw new Error(\n `[Trusera] Policy violation: ${reasons.join(\", \") || \"Request denied\"}`\n );\n }\n\n const result: any = await self.origUndiciRequest!.call(undici, url, options); // eslint-disable-line @typescript-eslint/no-explicit-any\n\n if (!self.shouldExclude(urlStr)) {\n const event = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(urlStr, method)}.response`,\n { method, url: urlStr, status: result.statusCode }\n );\n self.client?.track(event);\n }\n\n return result;\n };\n }\n\n // Patch undici.fetch\n if (typeof undici.fetch === \"function\") {\n this.origUndiciFetch = undici.fetch;\n undici.fetch = async function interceptedUndiciFetch(\n input: string | URL | Request,\n init?: RequestInit\n ): Promise<Response> {\n const url = typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n const method = (init?.method ?? \"GET\").toUpperCase();\n\n if (self.shouldExclude(url)) {\n return self.origUndiciFetch!.call(undici, input, init) as Promise<Response>;\n }\n\n const { blocked, reasons } = await self._evaluateAndTrack(url, method, {});\n if (blocked) {\n throw new Error(\n `[Trusera] Policy violation: ${reasons.join(\", \") || \"Request denied\"}`\n );\n }\n\n const response = await self.origUndiciFetch!.call(undici, input, init) as Response;\n\n const event = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.response`,\n { method, url, status: response.status }\n );\n self.client?.track(event);\n\n return response;\n };\n }\n\n this.log(\"Undici interceptor installed\");\n }\n\n private _uninstallUndici(): void {\n if (this.undiciMod) {\n if (this.origUndiciRequest) {\n this.undiciMod.request = this.origUndiciRequest;\n this.origUndiciRequest = null;\n }\n if (this.origUndiciFetch) {\n this.undiciMod.fetch = this.origUndiciFetch;\n this.origUndiciFetch = null;\n }\n this.undiciMod = null;\n }\n }\n\n // ─── Fetch interceptor (core) ───────────────────────────────────────\n\n /**\n * Creates the intercepted fetch function.\n * This is the core of the interception logic.\n */\n private createInterceptedFetch(): typeof globalThis.fetch {\n const self = this;\n\n return async function interceptedFetch(\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n // Ensure we have original fetch to fall back to\n if (originalFetch === null) {\n throw new Error(\"Original fetch not available\");\n }\n\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n const method = init?.method ?? \"GET\";\n\n // Check if URL should be excluded\n if (self.shouldExclude(url)) {\n self.log(\"Skipping excluded URL\", { url });\n return originalFetch(input, init);\n }\n\n self.log(\"Intercepting request\", { method, url });\n\n // Extract request details\n const requestData = await self.extractRequestData(input, init);\n\n // Create tracking event\n const event = createEvent(\n EventType.API_CALL,\n self.generateEventName(url, method),\n {\n method,\n url,\n headers: requestData.headers,\n body: requestData.body,\n },\n {\n interception_mode: self.options.enforcement,\n }\n );\n\n // Evaluate policy if configured\n if (self.options.policyUrl) {\n const policyDecision = await self.evaluatePolicy(url, method, requestData);\n\n if (policyDecision.decision === \"Deny\") {\n self.log(\"Policy violation detected\", { url, reasons: policyDecision.reasons });\n\n // Track violation event\n const violationEvent = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.policy_violation`,\n {\n ...event.payload,\n policy_decision: \"Deny\",\n policy_reasons: policyDecision.reasons,\n }\n );\n\n self.client?.track(violationEvent);\n\n // Handle based on enforcement mode\n if (self.options.enforcement === \"block\") {\n throw new Error(\n `[Trusera] Policy violation: ${policyDecision.reasons?.join(\", \") ?? \"Request denied\"}`\n );\n } else if (self.options.enforcement === \"warn\") {\n console.warn(\n `[Trusera] Policy violation (allowed): ${policyDecision.reasons?.join(\", \") ?? \"Request denied\"}`\n );\n }\n } else {\n self.log(\"Policy check passed\", { url });\n }\n }\n\n // Track the API call event\n self.client?.track(event);\n\n // Execute the actual request\n const startTime = Date.now();\n let response: Response;\n let error: Error | undefined;\n\n try {\n response = await originalFetch(input, init);\n } catch (err) {\n error = err as Error;\n self.log(\"Request failed\", { url, error: error.message });\n\n // Track error event\n const errorEvent = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.error`,\n {\n ...event.payload,\n error: error.message,\n duration_ms: Date.now() - startTime,\n }\n );\n self.client?.track(errorEvent);\n\n throw error;\n }\n\n // Track response\n const responseEvent = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.response`,\n {\n ...event.payload,\n status: response.status,\n status_text: response.statusText,\n duration_ms: Date.now() - startTime,\n response_headers: (() => { const h: Record<string, string> = {}; response.headers.forEach((v, k) => { h[k] = v; }); return h; })(),\n }\n );\n self.client?.track(responseEvent);\n\n return response;\n };\n }\n\n // ─── Shared utilities ───────────────────────────────────────────────\n\n /**\n * Checks if a URL should be excluded from interception.\n */\n private shouldExclude(url: string): boolean {\n return this.excludeRegexes.some((regex) => regex.test(url));\n }\n\n /**\n * Extracts request data for policy evaluation and tracking.\n */\n private async extractRequestData(\n _input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<{ headers: Record<string, string>; body: string | null }> {\n const headers: Record<string, string> = {};\n\n // Extract headers\n if (init?.headers) {\n if (init.headers instanceof Headers) {\n init.headers.forEach((value, key) => {\n headers[key] = value;\n });\n } else if (Array.isArray(init.headers)) {\n for (const [key, value] of init.headers) {\n headers[key] = value;\n }\n } else {\n Object.assign(headers, init.headers);\n }\n }\n\n // Extract body (if present and serializable)\n let body: string | null = null;\n if (init?.body) {\n if (typeof init.body === \"string\") {\n body = init.body;\n } else if (init.body instanceof URLSearchParams) {\n body = init.body.toString();\n } else if (init.body instanceof FormData) {\n body = \"[FormData]\";\n } else {\n body = \"[Binary data]\";\n }\n }\n\n return { headers, body };\n }\n\n /**\n * Evaluates request against Cedar policies.\n */\n private async evaluatePolicy(\n url: string,\n method: string,\n requestData: { headers: Record<string, string>; body: string | null }\n ): Promise<PolicyEvaluationResponse> {\n if (!this.options.policyUrl || !originalFetch) {\n return { decision: \"Allow\" };\n }\n\n try {\n const evaluationRequest: PolicyEvaluationRequest = {\n principal: this.client?.getAgentId() ?? \"unknown-agent\",\n action: `http.${method.toLowerCase()}`,\n resource: url,\n context: {\n headers: requestData.headers,\n body_present: requestData.body !== null,\n timestamp: new Date().toISOString(),\n },\n };\n\n const response = await originalFetch(this.options.policyUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(evaluationRequest),\n });\n\n if (!response.ok) {\n console.error(`[Trusera] Policy evaluation failed: ${response.status}`);\n return { decision: \"Allow\" }; // Fail open\n }\n\n return (await response.json()) as PolicyEvaluationResponse;\n } catch (error) {\n console.error(\"[Trusera] Policy evaluation error:\", error);\n return { decision: \"Allow\" }; // Fail open on error\n }\n }\n\n /**\n * Generates a structured event name from URL and method.\n */\n private generateEventName(url: string, method: string): string {\n try {\n const urlObj = new URL(url);\n const hostname = urlObj.hostname.replace(/\\./g, \"_\");\n const path = urlObj.pathname.split(\"/\").filter(Boolean).join(\"_\") || \"root\";\n return `http.${method.toLowerCase()}.${hostname}.${path}`;\n } catch {\n return `http.${method.toLowerCase()}.invalid_url`;\n }\n }\n\n private log(message: string, data?: Record<string, unknown>): void {\n if (this.options.debug) {\n console.log(`[Trusera Interceptor] ${message}`, data ?? \"\");\n }\n }\n}\n","/**\n * Standalone interceptor for Trusera SDK.\n *\n * Works WITHOUT any API key or platform connection.\n * Evaluates requests against local Cedar policies and logs events to disk.\n *\n * @example\n * ```typescript\n * import { StandaloneInterceptor } from \"trusera-sdk\";\n *\n * const interceptor = new StandaloneInterceptor({\n * policyFile: \".cedar/ai-policy.cedar\",\n * enforcement: \"block\",\n * logFile: \"agent-events.jsonl\",\n * excludePatterns: [\"api\\\\.trusera\\\\.\"],\n * debug: false\n * });\n *\n * interceptor.install();\n *\n * // All fetch calls are now monitored\n * await fetch(\"https://api.github.com/repos/test\");\n *\n * interceptor.uninstall();\n * ```\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CedarEvaluator } from \"./cedar.js\";\nimport type { PolicyDecision } from \"./cedar.js\";\n\n/**\n * Enforcement modes for policy violations.\n */\nexport type StandaloneEnforcementMode = \"block\" | \"warn\" | \"log\";\n\n/**\n * Configuration for the standalone interceptor.\n */\nexport interface StandaloneInterceptorOptions {\n /** Path to Cedar policy file (optional) */\n policyFile?: string;\n /** How to handle policy violations (default: \"log\") */\n enforcement?: StandaloneEnforcementMode;\n /** Path to JSONL log file for events (optional) */\n logFile?: string;\n /** URL patterns to exclude from interception (regex strings) */\n excludePatterns?: string[];\n /** Enable debug logging to console */\n debug?: boolean;\n}\n\n/**\n * Event logged to JSONL file.\n */\ninterface LoggedEvent {\n timestamp: string;\n method: string;\n url: string;\n status?: number;\n duration_ms?: number;\n policy_decision: \"Allow\" | \"Deny\";\n policy_reasons?: string[];\n enforcement_action: \"allowed\" | \"blocked\" | \"warned\";\n error?: string;\n}\n\n/**\n * Global singleton state for standalone interceptor.\n */\nlet activeStandaloneInterceptor: StandaloneInterceptor | null = null;\nlet originalFetch: typeof globalThis.fetch | null = null;\n\n/**\n * Standalone HTTP interceptor that works without Trusera platform.\n *\n * Evaluates requests against local Cedar policies and logs events to disk.\n * Suitable for local development, testing, and air-gapped environments.\n *\n * Only one interceptor can be active at a time.\n */\nexport class StandaloneInterceptor {\n private options: Required<StandaloneInterceptorOptions>;\n private excludeRegexes: RegExp[] = [];\n private isInstalled = false;\n private policyEvaluator: CedarEvaluator | null = null;\n private logFileHandle: number | null = null;\n\n constructor(options: StandaloneInterceptorOptions = {}) {\n this.options = {\n policyFile: options.policyFile ?? \"\",\n enforcement: options.enforcement ?? \"log\",\n logFile: options.logFile ?? \"\",\n excludePatterns: options.excludePatterns ?? [],\n debug: options.debug ?? false,\n };\n\n // Compile exclude patterns\n this.excludeRegexes = this.options.excludePatterns.map(\n (pattern) => new RegExp(pattern)\n );\n }\n\n /**\n * Installs the standalone interceptor.\n * Loads Cedar policy (if configured) and monkey-patches globalThis.fetch.\n *\n * @throws Error if another interceptor is already installed\n */\n install(): void {\n if (activeStandaloneInterceptor !== null && activeStandaloneInterceptor !== this) {\n throw new Error(\n \"Another StandaloneInterceptor is already installed. Call uninstall() first.\"\n );\n }\n\n if (this.isInstalled) {\n this.log(\"Interceptor already installed\");\n return;\n }\n\n // Load Cedar policy if configured\n if (this.options.policyFile) {\n this.loadPolicy(this.options.policyFile);\n }\n\n // Open log file if configured\n if (this.options.logFile) {\n this.openLogFile(this.options.logFile);\n }\n\n // Save original fetch and install interceptor\n if (originalFetch === null) {\n originalFetch = globalThis.fetch;\n }\n\n globalThis.fetch = this.createInterceptedFetch();\n activeStandaloneInterceptor = this;\n this.isInstalled = true;\n\n this.log(\"Standalone interceptor installed\", {\n policyFile: this.options.policyFile,\n policyRules: this.policyEvaluator?.getRuleCount() ?? 0,\n enforcement: this.options.enforcement,\n logFile: this.options.logFile,\n excludePatterns: this.options.excludePatterns.length,\n });\n }\n\n /**\n * Uninstalls the interceptor and restores original fetch.\n * Closes log file if open.\n */\n uninstall(): void {\n if (!this.isInstalled) {\n return;\n }\n\n if (originalFetch !== null) {\n globalThis.fetch = originalFetch;\n originalFetch = null; // Reset for next install\n }\n\n // Close log file\n if (this.logFileHandle !== null) {\n try {\n fs.closeSync(this.logFileHandle);\n } catch (error) {\n console.error(\"[Trusera Standalone] Error closing log file:\", error);\n }\n this.logFileHandle = null;\n }\n\n activeStandaloneInterceptor = null;\n this.isInstalled = false;\n\n this.log(\"Standalone interceptor uninstalled\");\n }\n\n /**\n * Loads Cedar policy from file.\n */\n private loadPolicy(policyPath: string): void {\n try {\n const absolutePath = path.resolve(policyPath);\n const policyText = fs.readFileSync(absolutePath, \"utf-8\");\n this.policyEvaluator = new CedarEvaluator(policyText);\n\n this.log(\"Loaded Cedar policy\", {\n path: absolutePath,\n rules: this.policyEvaluator.getRuleCount(),\n });\n } catch (error) {\n const err = error as Error;\n console.error(\n `[Trusera Standalone] Failed to load policy file ${policyPath}:`,\n err.message\n );\n // Continue without policy\n this.policyEvaluator = null;\n }\n }\n\n /**\n * Opens log file for appending.\n */\n private openLogFile(logPath: string): void {\n try {\n const absolutePath = path.resolve(logPath);\n\n // Ensure directory exists\n const dir = path.dirname(absolutePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Open file for appending\n this.logFileHandle = fs.openSync(absolutePath, \"a\");\n\n this.log(\"Opened log file\", { path: absolutePath });\n } catch (error) {\n const err = error as Error;\n console.error(\n `[Trusera Standalone] Failed to open log file ${logPath}:`,\n err.message\n );\n this.logFileHandle = null;\n }\n }\n\n /**\n * Creates the intercepted fetch function.\n */\n private createInterceptedFetch(): typeof globalThis.fetch {\n const self = this;\n\n return async function interceptedFetch(\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n if (originalFetch === null) {\n throw new Error(\"Original fetch not available\");\n }\n\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n const method = init?.method ?? \"GET\";\n\n // Check if URL should be excluded\n if (self.shouldExclude(url)) {\n self.log(\"Skipping excluded URL\", { url });\n return originalFetch(input, init);\n }\n\n self.log(\"Intercepting request\", { method, url });\n\n // Extract hostname and path for policy evaluation\n let hostname = \"\";\n let pathname = \"\";\n try {\n const urlObj = new URL(url);\n hostname = urlObj.hostname;\n pathname = urlObj.pathname;\n } catch {\n // Invalid URL, skip policy check\n self.log(\"Invalid URL, skipping policy check\", { url });\n return originalFetch(input, init);\n }\n\n // Evaluate policy if loaded\n let policyDecision: PolicyDecision = { decision: \"Allow\", reasons: [] };\n if (self.policyEvaluator) {\n policyDecision = self.policyEvaluator.evaluate({\n url,\n method,\n hostname,\n path: pathname,\n });\n\n if (policyDecision.decision === \"Deny\") {\n self.log(\"Policy violation detected\", {\n url,\n reasons: policyDecision.reasons,\n });\n\n // Log the violation event\n self.logEvent({\n timestamp: new Date().toISOString(),\n method,\n url,\n policy_decision: \"Deny\",\n policy_reasons: policyDecision.reasons,\n enforcement_action: self.options.enforcement === \"block\" ? \"blocked\" : \"warned\",\n });\n\n // Handle based on enforcement mode\n if (self.options.enforcement === \"block\") {\n throw new Error(\n `[Trusera] Policy violation: ${policyDecision.reasons.join(\", \")}`\n );\n } else if (self.options.enforcement === \"warn\") {\n console.warn(\n `[Trusera] Policy violation (allowed): ${policyDecision.reasons.join(\", \")}`\n );\n }\n } else {\n self.log(\"Policy check passed\", { url });\n }\n }\n\n // Execute the actual request\n const startTime = Date.now();\n let response: Response;\n let error: Error | undefined;\n\n try {\n response = await originalFetch(input, init);\n } catch (err) {\n error = err as Error;\n self.log(\"Request failed\", { url, error: error.message });\n\n // Log error event\n const errorEvent: LoggedEvent = {\n timestamp: new Date().toISOString(),\n method,\n url,\n duration_ms: Date.now() - startTime,\n policy_decision: policyDecision.decision,\n enforcement_action: \"allowed\",\n error: error.message,\n };\n if (policyDecision.reasons.length > 0) {\n errorEvent.policy_reasons = policyDecision.reasons;\n }\n self.logEvent(errorEvent);\n\n throw error;\n }\n\n // Log successful response\n const successEvent: LoggedEvent = {\n timestamp: new Date().toISOString(),\n method,\n url,\n status: response.status,\n duration_ms: Date.now() - startTime,\n policy_decision: policyDecision.decision,\n enforcement_action: \"allowed\",\n };\n if (policyDecision.reasons.length > 0) {\n successEvent.policy_reasons = policyDecision.reasons;\n }\n self.logEvent(successEvent);\n\n return response;\n };\n }\n\n /**\n * Checks if a URL should be excluded from interception.\n */\n private shouldExclude(url: string): boolean {\n return this.excludeRegexes.some((regex) => regex.test(url));\n }\n\n /**\n * Logs an event to the JSONL file.\n */\n private logEvent(event: LoggedEvent): void {\n if (this.logFileHandle === null) {\n return;\n }\n\n try {\n const line = JSON.stringify(event) + \"\\n\";\n fs.writeSync(this.logFileHandle, line);\n } catch (error) {\n const err = error as Error;\n console.error(\"[Trusera Standalone] Error writing to log file:\", err.message);\n }\n }\n\n /**\n * Debug logging.\n */\n private log(message: string, data?: Record<string, unknown>): void {\n if (this.options.debug) {\n console.log(`[Trusera Standalone] ${message}`, data ?? \"\");\n }\n }\n}\n","/**\n * Cedar-like policy evaluator for TypeScript.\n *\n * Evaluates simplified Cedar policy rules against HTTP request contexts.\n * Supports forbid/permit rules with conditions on URL, method, hostname, path.\n *\n * @example\n * ```typescript\n * const policy = `\n * forbid (principal, action == Action::\"http.get\", resource)\n * when { resource.hostname == \"malicious.com\" };\n * `;\n *\n * const evaluator = new CedarEvaluator(policy);\n * const result = evaluator.evaluate({\n * url: \"https://malicious.com/api\",\n * method: \"GET\",\n * hostname: \"malicious.com\"\n * });\n *\n * console.log(result.decision); // \"Deny\"\n * console.log(result.reasons); // [\"Policy violation: hostname == malicious.com\"]\n * ```\n */\n\n/**\n * Request context for policy evaluation.\n */\nexport interface PolicyContext {\n /** Full URL being accessed */\n url: string;\n /** HTTP method (GET, POST, etc.) */\n method: string;\n /** Hostname extracted from URL */\n hostname: string;\n /** Path extracted from URL */\n path?: string;\n /** Custom context fields */\n [key: string]: unknown;\n}\n\n/**\n * Policy evaluation result.\n */\nexport interface PolicyDecision {\n /** Allow or Deny */\n decision: \"Allow\" | \"Deny\";\n /** Reasons for the decision (policy rules that matched) */\n reasons: string[];\n}\n\n/**\n * Parsed policy rule.\n */\ninterface PolicyRule {\n /** forbid or permit */\n effect: \"forbid\" | \"permit\";\n /** Action pattern (e.g., \"http.get\", \"*\") */\n action: string;\n /** Field name being checked (e.g., \"hostname\", \"path\") */\n field: string;\n /** Comparison operator (==, !=, contains, startsWith, etc.) */\n operator: string;\n /** Value to compare against */\n value: string;\n /** Raw rule text for debugging */\n raw: string;\n}\n\n/**\n * Cedar-like policy evaluator.\n *\n * Parses and evaluates simplified Cedar policies for HTTP requests.\n * Supports basic forbid/permit rules with string matching conditions.\n */\nexport class CedarEvaluator {\n private rules: PolicyRule[] = [];\n\n /**\n * Creates a new Cedar evaluator with the given policy text.\n *\n * @param policyText - Cedar-like policy rules\n */\n constructor(policyText: string) {\n this.rules = this.parsePolicy(policyText);\n }\n\n /**\n * Evaluates a request context against loaded policies.\n *\n * @param context - Request context to evaluate\n * @returns Policy decision with reasons\n */\n evaluate(context: PolicyContext): PolicyDecision {\n const matchedRules: PolicyRule[] = [];\n\n for (const rule of this.rules) {\n if (this.evaluateRule(rule, context)) {\n matchedRules.push(rule);\n }\n }\n\n // If any forbid rules matched, deny the request\n const forbidMatches = matchedRules.filter((r) => r.effect === \"forbid\");\n if (forbidMatches.length > 0) {\n return {\n decision: \"Deny\",\n reasons: forbidMatches.map(\n (r) => `Policy violation: ${r.field} ${r.operator} ${r.value}`\n ),\n };\n }\n\n // Otherwise allow\n return {\n decision: \"Allow\",\n reasons: [],\n };\n }\n\n /**\n * Parses Cedar-like policy text into rule objects.\n *\n * Supported syntax:\n * ```\n * forbid (principal, action == Action::\"http.get\", resource)\n * when { resource.hostname == \"malicious.com\" };\n *\n * forbid (principal, action == Action::\"*\", resource)\n * when { resource.url contains \"blocked-domain.com\" };\n * ```\n */\n private parsePolicy(policyText: string): PolicyRule[] {\n const rules: PolicyRule[] = [];\n\n // Strip comments (// style)\n const cleaned = policyText.replace(/\\/\\/[^\\n]*/g, \"\");\n\n // Regex to match forbid/permit rules\n // Matches: (forbid|permit) ( ... ) when { resource.field operator \"value\" };\n const rulePattern = /\\b(forbid|permit)\\s*\\(\\s*principal\\s*,\\s*action\\s*==\\s*Action::\"([^\"]+)\"\\s*,\\s*resource\\s*\\)\\s*when\\s*\\{([^}]+)\\}\\s*;/gim;\n\n let match;\n while ((match = rulePattern.exec(cleaned)) !== null) {\n const effect = match[1]?.toLowerCase() as \"forbid\" | \"permit\";\n const action = match[2];\n const conditionBody = match[3];\n\n if (!effect || !action || !conditionBody) {\n continue;\n }\n\n // Parse condition (resource.field operator value)\n const conditionPattern = /resource\\.(\\w+)\\s*(==|!=|contains|startsWith|endsWith)\\s*\"([^\"]+)\"/gi;\n let condMatch;\n while ((condMatch = conditionPattern.exec(conditionBody)) !== null) {\n const field = condMatch[1];\n const operator = condMatch[2];\n const value = condMatch[3];\n\n if (!field || !operator || !value) {\n continue;\n }\n\n rules.push({\n effect,\n action,\n field,\n operator,\n value,\n raw: match[0] ?? \"\",\n });\n }\n }\n\n return rules;\n }\n\n /**\n * Evaluates a single rule against a context.\n */\n private evaluateRule(rule: PolicyRule, context: PolicyContext): boolean {\n // Check if action matches\n if (!this.matchesAction(rule.action, context.method)) {\n return false;\n }\n\n // Get the field value from context\n const fieldValue = this.getFieldValue(rule.field, context);\n if (fieldValue === undefined) {\n return false;\n }\n\n // Evaluate the condition\n return this.evaluateCondition(\n String(fieldValue),\n rule.operator,\n rule.value\n );\n }\n\n /**\n * Checks if an action pattern matches the HTTP method.\n */\n private matchesAction(actionPattern: string, method: string): boolean {\n if (actionPattern === \"*\") {\n return true;\n }\n\n // Action format: \"http.get\", \"http.post\", etc.\n const normalizedPattern = actionPattern.toLowerCase();\n const normalizedMethod = method.toLowerCase();\n\n if (normalizedPattern === `http.${normalizedMethod}`) {\n return true;\n }\n\n // Check for wildcard patterns\n if (normalizedPattern.endsWith(\"*\")) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedMethod.startsWith(prefix);\n }\n\n return false;\n }\n\n /**\n * Extracts a field value from the context.\n */\n private getFieldValue(field: string, context: PolicyContext): unknown {\n // Direct context access\n if (field in context) {\n return context[field];\n }\n\n // Special handling for common fields\n if (field === \"hostname\") {\n return context.hostname;\n }\n\n if (field === \"path\") {\n if (context.path !== undefined) {\n return context.path;\n }\n // Try to extract from URL\n try {\n const url = new URL(context.url);\n return url.pathname;\n } catch {\n return undefined;\n }\n }\n\n if (field === \"method\") {\n return context.method;\n }\n\n if (field === \"url\") {\n return context.url;\n }\n\n return undefined;\n }\n\n /**\n * Evaluates a condition operator.\n */\n private evaluateCondition(\n actual: string,\n operator: string,\n expected: string\n ): boolean {\n const actualLower = actual.toLowerCase();\n const expectedLower = expected.toLowerCase();\n\n switch (operator.toLowerCase()) {\n case \"==\":\n return actualLower === expectedLower;\n case \"!=\":\n return actualLower !== expectedLower;\n case \"contains\":\n return actualLower.includes(expectedLower);\n case \"startswith\":\n return actualLower.startsWith(expectedLower);\n case \"endswith\":\n return actualLower.endsWith(expectedLower);\n default:\n return false;\n }\n }\n\n /**\n * Returns the number of loaded rules.\n */\n getRuleCount(): number {\n return this.rules.length;\n }\n}\n","import type { TruseraClient } from \"../client.js\";\nimport { EventType, createEvent, type Event } from \"../events.js\";\nimport type { EnforcementMode } from \"../interceptor.js\";\nimport type { CedarEvaluator } from \"../cedar.js\";\n\n/**\n * Options for configuring the LangChain handler with policy enforcement.\n */\nexport interface LangChainHandlerOptions {\n /** Enforcement mode for policy violations (default: none/passive tracking only) */\n enforcement?: EnforcementMode;\n /** Cedar policy evaluator for local policy checks */\n cedarEvaluator?: CedarEvaluator;\n}\n\n/**\n * LangChain.js callback handler for Trusera integration.\n * Implements the BaseCallbackHandler interface to track LLM calls,\n * tool executions, and chain steps.\n *\n * Supports optional Cedar policy enforcement: block throws, warn logs, log is silent.\n * Without options, operates in passive tracking mode (full backward compatibility).\n *\n * Note: This uses structural typing to avoid requiring langchain as a dependency.\n * If langchain types change, this will need updating.\n *\n * @example\n * ```typescript\n * import { ChatOpenAI } from \"langchain/chat_models/openai\";\n * import { TruseraClient, TruseraLangChainHandler, CedarEvaluator } from \"trusera-sdk\";\n *\n * const client = new TruseraClient({ apiKey: \"tsk_xxx\" });\n *\n * // Passive tracking (no enforcement)\n * const handler = new TruseraLangChainHandler(client);\n *\n * // With Cedar policy enforcement\n * const evaluator = new CedarEvaluator(policyText);\n * const enforcedHandler = new TruseraLangChainHandler(client, {\n * enforcement: \"block\",\n * cedarEvaluator: evaluator\n * });\n *\n * const model = new ChatOpenAI({ callbacks: [enforcedHandler] });\n * await model.invoke(\"What is AI safety?\");\n *\n * await client.close();\n * ```\n */\nexport class TruseraLangChainHandler {\n private readonly client: TruseraClient;\n private readonly pendingEvents = new Map<string, Event>();\n private readonly enforcement: EnforcementMode | undefined;\n private readonly cedarEvaluator: CedarEvaluator | undefined;\n\n constructor(client: TruseraClient, options?: LangChainHandlerOptions) {\n this.client = client;\n this.enforcement = options?.enforcement;\n this.cedarEvaluator = options?.cedarEvaluator;\n }\n\n /**\n * Called when an LLM starts running.\n */\n handleLLMStart(\n llm: { name: string },\n prompts: string[],\n runId: string,\n parentRunId?: string,\n extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>\n ): void {\n // Evaluate policy if enforcement is configured\n if (this.enforcement && this.cedarEvaluator) {\n const decision = this.cedarEvaluator.evaluate({\n url: `langchain://llm/${llm.name}`,\n method: \"INVOKE\",\n hostname: \"langchain\",\n path: `/llm/${llm.name}`,\n });\n\n if (decision.decision === \"Deny\") {\n this._handleViolation(\n `langchain.llm.${llm.name}`,\n EventType.LLM_INVOKE,\n decision.reasons,\n runId\n );\n\n if (this.enforcement === \"block\") {\n throw new Error(\n `[Trusera] Policy violation: LLM ${llm.name} denied - ${decision.reasons.join(\", \")}`\n );\n }\n }\n }\n\n const event = createEvent(\n EventType.LLM_INVOKE,\n `langchain.llm.${llm.name}`,\n {\n prompts,\n prompt_count: prompts.length,\n invocation_params: extraParams ?? {},\n },\n {\n run_id: runId,\n parent_run_id: parentRunId,\n tags: tags ?? [],\n ...metadata,\n }\n );\n\n this.pendingEvents.set(runId, event);\n this.client.track(event);\n }\n\n /**\n * Called when an LLM finishes running.\n */\n handleLLMEnd(\n output: { generations: Array<Array<{ text: string }>> },\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const texts = output.generations.flatMap((gen) => gen.map((g) => g.text));\n\n const event = createEvent(\n EventType.LLM_INVOKE,\n `${startEvent.name}.completed`,\n {\n ...startEvent.payload,\n outputs: texts,\n output_count: texts.length,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when an LLM encounters an error.\n */\n handleLLMError(\n error: Error,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.LLM_INVOKE,\n `${startEvent.name}.error`,\n {\n ...startEvent.payload,\n error: error.message,\n error_type: error.name,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when a tool starts running.\n */\n handleToolStart(\n tool: { name: string },\n input: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>\n ): void {\n // Evaluate policy if enforcement is configured\n if (this.enforcement && this.cedarEvaluator) {\n const decision = this.cedarEvaluator.evaluate({\n url: `langchain://tool/${tool.name}`,\n method: \"EXECUTE\",\n hostname: \"langchain\",\n path: `/tool/${tool.name}`,\n });\n\n if (decision.decision === \"Deny\") {\n this._handleViolation(\n `langchain.tool.${tool.name}`,\n EventType.TOOL_CALL,\n decision.reasons,\n runId\n );\n\n if (this.enforcement === \"block\") {\n throw new Error(\n `[Trusera] Policy violation: tool ${tool.name} denied - ${decision.reasons.join(\", \")}`\n );\n }\n }\n }\n\n const event = createEvent(\n EventType.TOOL_CALL,\n `langchain.tool.${tool.name}`,\n {\n input,\n input_length: input.length,\n },\n {\n run_id: runId,\n parent_run_id: parentRunId,\n tags: tags ?? [],\n ...metadata,\n }\n );\n\n this.pendingEvents.set(runId, event);\n this.client.track(event);\n }\n\n /**\n * Called when a tool finishes running.\n */\n handleToolEnd(\n output: string,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.TOOL_CALL,\n `${startEvent.name}.completed`,\n {\n ...startEvent.payload,\n output,\n output_length: output.length,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when a tool encounters an error.\n */\n handleToolError(\n error: Error,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.TOOL_CALL,\n `${startEvent.name}.error`,\n {\n ...startEvent.payload,\n error: error.message,\n error_type: error.name,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when a chain starts running.\n */\n handleChainStart(\n chain: { name: string },\n inputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>\n ): void {\n const event = createEvent(\n EventType.DECISION,\n `langchain.chain.${chain.name}`,\n {\n inputs,\n input_keys: Object.keys(inputs),\n },\n {\n run_id: runId,\n parent_run_id: parentRunId,\n tags: tags ?? [],\n ...metadata,\n }\n );\n\n this.pendingEvents.set(runId, event);\n this.client.track(event);\n }\n\n /**\n * Called when a chain finishes running.\n */\n handleChainEnd(\n outputs: Record<string, unknown>,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.DECISION,\n `${startEvent.name}.completed`,\n {\n ...startEvent.payload,\n outputs,\n output_keys: Object.keys(outputs),\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when a chain encounters an error.\n */\n handleChainError(\n error: Error,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.DECISION,\n `${startEvent.name}.error`,\n {\n ...startEvent.payload,\n error: error.message,\n error_type: error.name,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Returns the number of pending (incomplete) events.\n * Useful for testing and debugging.\n */\n getPendingEventCount(): number {\n return this.pendingEvents.size;\n }\n\n /**\n * Clears all pending events.\n * Should only be used in testing or error recovery.\n */\n clearPendingEvents(): void {\n this.pendingEvents.clear();\n }\n\n /**\n * Handle a policy violation: track POLICY_VIOLATION event and warn if needed.\n */\n private _handleViolation(\n name: string,\n eventType: EventType,\n reasons: string[],\n runId: string\n ): void {\n const violationEvent = createEvent(\n eventType,\n `${name}.policy_violation`,\n {\n policy_decision: \"Deny\",\n policy_reasons: reasons,\n },\n { run_id: runId }\n );\n this.client.track(violationEvent);\n\n if (this.enforcement === \"warn\") {\n console.warn(\n `[Trusera] Policy violation (allowed): ${reasons.join(\", \")}`\n );\n }\n }\n}\n"],"mappings":"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","names":["EventType","path","originalFetch"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client.ts","../src/events.ts","../src/interceptor.ts","../src/standalone.ts","../src/cedar.ts","../src/integrations/langchain.ts"],"sourcesContent":["/**\n * Trusera SDK - TypeScript SDK for monitoring AI agents\n *\n * @packageDocumentation\n */\n\nexport { TruseraClient } from \"./client.js\";\nexport type { TruseraClientOptions } from \"./client.js\";\n\nexport { TruseraInterceptor } from \"./interceptor.js\";\nexport type { InterceptorOptions, EnforcementMode } from \"./interceptor.js\";\n\nexport { StandaloneInterceptor } from \"./standalone.js\";\nexport type { StandaloneInterceptorOptions, StandaloneEnforcementMode } from \"./standalone.js\";\n\nexport { CedarEvaluator } from \"./cedar.js\";\nexport type { PolicyContext, PolicyDecision } from \"./cedar.js\";\n\nexport { EventType, createEvent, isValidEvent } from \"./events.js\";\nexport type { Event } from \"./events.js\";\n\nexport { TruseraLangChainHandler } from \"./integrations/langchain.js\";\nexport type { LangChainHandlerOptions } from \"./integrations/langchain.js\";\n","import type { Event } from \"./events.js\";\n\nconst SDK_VERSION = \"1.0.0\";\n\n/**\n * Configuration options for TruseraClient.\n */\nexport interface TruseraClientOptions {\n /** API key for authenticating with Trusera backend (tsk_xxx) */\n apiKey: string;\n /** Base URL for Trusera API (defaults to production) */\n baseUrl?: string;\n /** Agent identifier (auto-registered if not provided) */\n agentId?: string;\n /** Interval in ms to auto-flush events (default: 5000) */\n flushInterval?: number;\n /** Max events per batch (default: 100) */\n batchSize?: number;\n /** Enable debug logging to console */\n debug?: boolean;\n /** Auto-register with fleet discovery on startup (default: false).\n * Overridden by TRUSERA_AUTO_REGISTER env var. */\n autoRegister?: boolean;\n /** Agent name for fleet registration (defaults to os.hostname()) */\n agentName?: string;\n /** Agent type for fleet registration (e.g. \"langchain\") */\n agentType?: string;\n /** Deployment environment for fleet registration */\n environment?: string;\n /** Heartbeat interval in ms (default: 60000).\n * Overridden by TRUSERA_HEARTBEAT_INTERVAL env var. */\n heartbeatInterval?: number;\n}\n\n/**\n * Response from agent registration endpoint.\n */\ninterface RegisterAgentResponse {\n agent_id: string;\n name: string;\n created_at: string;\n}\n\n/**\n * Core client for tracking AI agent events and sending them to Trusera.\n * Handles batching, automatic flushing, and agent registration.\n *\n * @example\n * ```typescript\n * const client = new TruseraClient({\n * apiKey: \"tsk_your_key_here\",\n * agentId: \"my-agent-123\"\n * });\n *\n * client.track(createEvent(EventType.TOOL_CALL, \"github.search\", { query: \"AI\" }));\n * await client.close(); // Flush remaining events and cleanup\n * ```\n */\nexport class TruseraClient {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly batchSize: number;\n private readonly flushInterval: number;\n private readonly debug: boolean;\n\n private agentId: string | undefined;\n private eventQueue: Event[] = [];\n private flushTimer: NodeJS.Timeout | undefined;\n private isClosed = false;\n\n // Fleet auto-registration\n private readonly autoRegister: boolean;\n private readonly agentName: string;\n private readonly agentType: string;\n private readonly environment: string;\n private readonly heartbeatInterval: number;\n private fleetAgentId: string | undefined;\n private heartbeatTimer: NodeJS.Timeout | undefined;\n\n constructor(options: TruseraClientOptions) {\n this.apiKey = options.apiKey;\n this.baseUrl = options.baseUrl ?? \"https://api.trusera.io\";\n this.agentId = options.agentId;\n this.batchSize = options.batchSize ?? 100;\n this.flushInterval = options.flushInterval ?? 5000;\n this.debug = options.debug ?? false;\n\n // Fleet config with env var overrides\n const envAuto = (typeof process !== \"undefined\" ? process.env?.TRUSERA_AUTO_REGISTER : undefined) ?? \"\";\n if (envAuto.toLowerCase() === \"true\" || envAuto === \"1\") {\n this.autoRegister = true;\n } else if (envAuto.toLowerCase() === \"false\" || envAuto === \"0\") {\n this.autoRegister = false;\n } else {\n this.autoRegister = options.autoRegister ?? false;\n }\n\n const hostname = typeof process !== \"undefined\" && process.env?.HOSTNAME\n ? process.env.HOSTNAME\n : typeof globalThis !== \"undefined\" && \"navigator\" in globalThis\n ? \"browser\"\n : \"unknown\";\n this.agentName = options.agentName ?? (typeof process !== \"undefined\" ? process.env?.TRUSERA_AGENT_NAME : undefined) ?? hostname;\n this.agentType = options.agentType ?? (typeof process !== \"undefined\" ? process.env?.TRUSERA_AGENT_TYPE : undefined) ?? \"\";\n this.environment = options.environment ?? (typeof process !== \"undefined\" ? process.env?.TRUSERA_ENVIRONMENT : undefined) ?? \"\";\n const envHb = typeof process !== \"undefined\" ? process.env?.TRUSERA_HEARTBEAT_INTERVAL : undefined;\n this.heartbeatInterval = envHb ? parseInt(envHb, 10) * 1000 : (options.heartbeatInterval ?? 60000);\n\n if (!this.apiKey.startsWith(\"tsk_\")) {\n throw new Error(\"Invalid API key format. Must start with 'tsk_'\");\n }\n\n // Start auto-flush timer\n this.startFlushTimer();\n\n // Fleet auto-registration\n if (this.autoRegister) {\n void this.registerWithFleet();\n }\n\n this.log(\"TruseraClient initialized\", { baseUrl: this.baseUrl, batchSize: this.batchSize, autoRegister: this.autoRegister });\n }\n\n /**\n * Registers a new agent with Trusera backend.\n * Returns the assigned agent_id which should be stored for future use.\n *\n * @param name - Human-readable agent name\n * @param framework - Framework identifier (e.g., \"langchain\", \"autogen\", \"custom\")\n * @returns Agent ID string\n */\n async registerAgent(name: string, framework: string): Promise<string> {\n this.log(\"Registering agent\", { name, framework });\n\n const response = await fetch(`${this.baseUrl}/api/v1/agents/register`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({\n name,\n framework,\n metadata: {\n sdk_version: \"0.1.0\",\n runtime: \"node\",\n node_version: process.version,\n },\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Failed to register agent: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as RegisterAgentResponse;\n this.agentId = data.agent_id;\n this.log(\"Agent registered\", { agentId: this.agentId });\n return this.agentId;\n }\n\n /**\n * Queues an event for transmission.\n * Events are batched and sent automatically based on flushInterval and batchSize.\n *\n * @param event - Event to track\n */\n track(event: Event): void {\n if (this.isClosed) {\n throw new Error(\"Cannot track events on closed client\");\n }\n\n // Enrich metadata with agent context\n const enrichedEvent: Event = {\n ...event,\n metadata: {\n ...event.metadata,\n agent_id: this.agentId,\n sdk_version: \"0.1.0\",\n },\n };\n\n this.eventQueue.push(enrichedEvent);\n this.log(\"Event tracked\", { type: event.type, name: event.name, queueSize: this.eventQueue.length });\n\n // Auto-flush if batch size reached\n if (this.eventQueue.length >= this.batchSize) {\n void this.flush();\n }\n }\n\n /**\n * Immediately sends all queued events to Trusera backend.\n * Called automatically by flush timer or when batch size is reached.\n *\n * @returns Promise that resolves when events are sent\n */\n async flush(): Promise<void> {\n if (this.eventQueue.length === 0) {\n return;\n }\n\n const batch = this.eventQueue.splice(0, this.batchSize);\n this.log(\"Flushing events\", { count: batch.length });\n\n try {\n const response = await fetch(`${this.baseUrl}/api/v1/events/batch`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify({ events: batch }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n console.error(`[Trusera] Failed to send events: ${response.status} ${error}`);\n // Re-queue failed events for retry\n this.eventQueue.unshift(...batch);\n } else {\n this.log(\"Events flushed successfully\", { count: batch.length });\n }\n } catch (error) {\n console.error(\"[Trusera] Network error sending events:\", error);\n // Re-queue failed events\n this.eventQueue.unshift(...batch);\n }\n }\n\n /**\n * Gracefully shuts down the client.\n * Flushes all remaining events and stops the auto-flush timer.\n *\n * @returns Promise that resolves when shutdown is complete\n */\n async close(): Promise<void> {\n this.log(\"Closing client\");\n this.isClosed = true;\n this.stopFlushTimer();\n this.stopHeartbeat();\n await this.flush();\n this.log(\"Client closed\");\n }\n\n /**\n * Returns current queue size (useful for monitoring/debugging).\n */\n getQueueSize(): number {\n return this.eventQueue.length;\n }\n\n /**\n * Returns the current agent ID (if registered).\n */\n getAgentId(): string | undefined {\n return this.agentId;\n }\n\n // -- Fleet auto-registration --\n\n private getProcessInfo(): Record<string, unknown> {\n if (typeof process === \"undefined\") return {};\n return {\n pid: process.pid,\n argv: process.argv?.slice(0, 10),\n node_version: process.version,\n platform: process.platform,\n arch: process.arch,\n };\n }\n\n private getNetworkInfo(): Record<string, unknown> {\n const info: Record<string, unknown> = {};\n if (typeof process !== \"undefined\") {\n try {\n const os = require(\"os\");\n info.hostname = os.hostname?.();\n } catch {\n info.hostname = process.env?.HOSTNAME ?? \"unknown\";\n }\n }\n return info;\n }\n\n private async registerWithFleet(): Promise<void> {\n const payload: Record<string, unknown> = {\n name: this.agentName,\n discovery_method: \"sdk\",\n sdk_version: SDK_VERSION,\n hostname: this.agentName,\n process_info: this.getProcessInfo(),\n network_info: this.getNetworkInfo(),\n };\n if (this.agentType) payload.framework = this.agentType;\n if (this.environment) payload.environment = this.environment;\n\n try {\n const response = await fetch(`${this.baseUrl}/api/v1/fleet/register`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n this.log(\"Fleet auto-register failed\", { status: response.status });\n return;\n }\n\n const data = await response.json() as { data?: { id?: string }; id?: string };\n const agentData = data.data ?? data;\n const fleetId = agentData.id;\n if (fleetId) {\n this.fleetAgentId = String(fleetId);\n this.startHeartbeat();\n this.log(\"Fleet auto-register succeeded\", { fleetAgentId: this.fleetAgentId });\n }\n } catch (err) {\n this.log(\"Fleet auto-register error (continuing without)\", { error: String(err) });\n }\n }\n\n private startHeartbeat(): void {\n this.heartbeatTimer = setInterval(() => {\n void this.sendHeartbeat();\n }, this.heartbeatInterval);\n\n if (this.heartbeatTimer.unref) {\n this.heartbeatTimer.unref();\n }\n }\n\n private stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = undefined;\n }\n }\n\n private async sendHeartbeat(): Promise<void> {\n if (!this.fleetAgentId) return;\n try {\n const payload = {\n process_info: this.getProcessInfo(),\n network_info: this.getNetworkInfo(),\n };\n const response = await fetch(`${this.baseUrl}/api/v1/fleet/${this.fleetAgentId}/heartbeat`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(payload),\n });\n if (!response.ok) {\n this.log(\"Fleet heartbeat failed\", { status: response.status });\n }\n } catch (err) {\n this.log(\"Fleet heartbeat error\", { error: String(err) });\n }\n }\n\n // -- Timers --\n\n private startFlushTimer(): void {\n this.flushTimer = setInterval(() => {\n void this.flush();\n }, this.flushInterval);\n\n // Don't keep process alive for flush timer\n if (this.flushTimer.unref) {\n this.flushTimer.unref();\n }\n }\n\n private stopFlushTimer(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = undefined;\n }\n }\n\n private log(message: string, data?: Record<string, unknown>): void {\n if (this.debug) {\n console.log(`[Trusera] ${message}`, data ?? \"\");\n }\n }\n}\n","/**\n * Event types tracked by the Trusera SDK.\n * These align with the core observability primitives for AI agent monitoring.\n */\nexport enum EventType {\n /** Tool or function call by the agent */\n TOOL_CALL = \"tool_call\",\n /** LLM inference invocation */\n LLM_INVOKE = \"llm_invoke\",\n /** Data access operation (read/write) */\n DATA_ACCESS = \"data_access\",\n /** Outbound HTTP API call */\n API_CALL = \"api_call\",\n /** File write operation */\n FILE_WRITE = \"file_write\",\n /** Decision point or chain step */\n DECISION = \"decision\",\n}\n\n/**\n * Core event structure for all Trusera tracking.\n * Events are immutable once created and queued for batch transmission.\n */\nexport interface Event {\n /** Unique event identifier (UUIDv4) */\n id: string;\n /** Event type discriminator */\n type: EventType;\n /** Human-readable event name (e.g., \"openai.chat.completions\", \"github.api.repos\") */\n name: string;\n /** Event-specific structured data */\n payload: Record<string, unknown>;\n /** Additional context (agent_id, session_id, tags, etc.) */\n metadata: Record<string, unknown>;\n /** ISO 8601 timestamp */\n timestamp: string;\n}\n\n/**\n * Creates a well-formed Event with automatic ID and timestamp generation.\n *\n * @param type - Event type from EventType enum\n * @param name - Descriptive event name (use dotted notation: \"service.resource.action\")\n * @param payload - Event-specific data (request, response, errors, etc.)\n * @param metadata - Optional metadata (merged with default agent context)\n * @returns Fully populated Event ready for tracking\n *\n * @example\n * ```typescript\n * const event = createEvent(\n * EventType.API_CALL,\n * \"openai.chat.completions\",\n * { model: \"gpt-4\", tokens: 150 },\n * { session_id: \"abc-123\" }\n * );\n * client.track(event);\n * ```\n */\nexport function createEvent(\n type: EventType,\n name: string,\n payload: Record<string, unknown> = {},\n metadata: Record<string, unknown> = {}\n): Event {\n return {\n id: crypto.randomUUID(),\n type,\n name,\n payload: { ...payload },\n metadata: { ...metadata },\n timestamp: new Date().toISOString(),\n };\n}\n\n/**\n * Type guard to validate if an object is a valid Event.\n * Useful for runtime validation before transmission.\n */\nexport function isValidEvent(obj: unknown): obj is Event {\n if (typeof obj !== \"object\" || obj === null) return false;\n const e = obj as Partial<Event>;\n return (\n typeof e.id === \"string\" &&\n typeof e.type === \"string\" &&\n Object.values(EventType).includes(e.type as EventType) &&\n typeof e.name === \"string\" &&\n typeof e.payload === \"object\" &&\n e.payload !== null &&\n typeof e.metadata === \"object\" &&\n e.metadata !== null &&\n typeof e.timestamp === \"string\"\n );\n}\n","import type { TruseraClient } from \"./client.js\";\nimport { EventType, createEvent } from \"./events.js\";\n\n/**\n * Enforcement modes for policy violations.\n */\nexport type EnforcementMode = \"block\" | \"warn\" | \"log\";\n\n/**\n * Configuration for the HTTP interceptor.\n */\nexport interface InterceptorOptions {\n /** How to handle policy violations (default: \"log\") */\n enforcement?: EnforcementMode;\n /** Cedar policy service URL for runtime policy checks */\n policyUrl?: string;\n /** URL patterns to exclude from interception (regex strings) */\n excludePatterns?: string[];\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Policy evaluation request sent to Cedar policy service.\n */\ninterface PolicyEvaluationRequest {\n principal: string;\n action: string;\n resource: string;\n context: Record<string, unknown>;\n}\n\n/**\n * Policy evaluation response from Cedar service.\n */\ninterface PolicyEvaluationResponse {\n decision: \"Allow\" | \"Deny\";\n reasons?: string[];\n}\n\n/**\n * Global interceptor singleton state.\n * Only one interceptor can be active at a time.\n */\nlet activeInterceptor: TruseraInterceptor | null = null;\nlet originalFetch: typeof globalThis.fetch | null = null;\n\n/**\n * Safely require an optional dependency.\n * Returns null if the module is not installed.\n */\n// eslint-disable-next-line @typescript-eslint/no-require-imports\nfunction tryRequire(moduleName: string): any { // eslint-disable-line @typescript-eslint/no-explicit-any\n try {\n return require(moduleName);\n } catch {\n return null;\n }\n}\n\n/**\n * HTTP interceptor for AI agent outbound traffic.\n * Monkey-patches globalThis.fetch, axios, and undici to intercept all HTTP calls,\n * evaluate them against Cedar policies, and track events.\n *\n * @example\n * ```typescript\n * const client = new TruseraClient({ apiKey: \"tsk_xxx\" });\n * const interceptor = new TruseraInterceptor();\n *\n * interceptor.install(client, {\n * enforcement: \"block\",\n * policyUrl: \"https://policy.trusera.io/evaluate\",\n * excludePatterns: [\"^https://api\\\\.trusera\\\\.io/.*\"]\n * });\n *\n * // All fetch/axios/undici calls are now intercepted\n * await fetch(\"https://api.github.com/repos/test\"); // Tracked + policy-checked\n *\n * interceptor.uninstall(); // Restore originals\n * ```\n */\nexport class TruseraInterceptor {\n private client: TruseraClient | null = null;\n private options: Required<InterceptorOptions> = {\n enforcement: \"log\",\n policyUrl: \"\",\n excludePatterns: [],\n debug: false,\n };\n private excludeRegexes: RegExp[] = [];\n private isInstalled = false;\n\n // Axios interception state\n private axiosDefault: any = null; // eslint-disable-line @typescript-eslint/no-explicit-any\n private axiosRequestId: number | null = null;\n private axiosResponseId: number | null = null;\n\n // Undici interception state\n private undiciMod: any = null; // eslint-disable-line @typescript-eslint/no-explicit-any\n private origUndiciRequest: ((...args: any[]) => any) | null = null; // eslint-disable-line @typescript-eslint/no-explicit-any\n private origUndiciFetch: ((...args: any[]) => any) | null = null; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n /**\n * Installs the HTTP interceptor by patching globalThis.fetch, axios, and undici.\n * Only one interceptor can be active at a time.\n *\n * @param client - TruseraClient instance for event tracking\n * @param options - Interceptor configuration\n * @throws Error if another interceptor is already installed\n */\n install(client: TruseraClient, options: InterceptorOptions = {}): void {\n if (activeInterceptor !== null && activeInterceptor !== this) {\n throw new Error(\"Another TruseraInterceptor is already installed. Call uninstall() first.\");\n }\n\n if (this.isInstalled) {\n this.log(\"Interceptor already installed\");\n return;\n }\n\n this.client = client;\n this.options = {\n enforcement: options.enforcement ?? \"log\",\n policyUrl: options.policyUrl ?? \"\",\n excludePatterns: options.excludePatterns ?? [],\n debug: options.debug ?? false,\n };\n\n // Compile exclude patterns to regexes\n this.excludeRegexes = this.options.excludePatterns.map((pattern) => new RegExp(pattern));\n\n // Save original fetch and install interceptor\n if (originalFetch === null) {\n originalFetch = globalThis.fetch;\n }\n\n globalThis.fetch = this.createInterceptedFetch();\n activeInterceptor = this;\n this.isInstalled = true;\n\n // Install optional library interceptors (graceful skip if not available)\n this._installAxios();\n this._installUndici();\n\n this.log(\"Interceptor installed\", {\n enforcement: this.options.enforcement,\n policyUrl: this.options.policyUrl,\n excludePatterns: this.options.excludePatterns.length,\n });\n }\n\n /**\n * Uninstalls the interceptor and restores original fetch, axios, and undici.\n */\n uninstall(): void {\n if (!this.isInstalled) {\n return;\n }\n\n if (originalFetch !== null) {\n globalThis.fetch = originalFetch;\n originalFetch = null; // Reset for next install\n }\n\n this._uninstallAxios();\n this._uninstallUndici();\n\n activeInterceptor = null;\n this.isInstalled = false;\n this.client = null;\n\n this.log(\"Interceptor uninstalled\");\n }\n\n // ─── Shared evaluation + tracking ───────────────────────────────────\n\n /**\n * Shared pre-request evaluation: checks excludes, evaluates Cedar policy,\n * tracks API_CALL event, and returns whether the request should be blocked.\n * Used by fetch, axios, and undici interceptors.\n */\n private async _evaluateAndTrack(\n url: string,\n method: string,\n headers: Record<string, string>\n ): Promise<{ blocked: boolean; reasons: string[] }> {\n if (this.shouldExclude(url)) {\n return { blocked: false, reasons: [] };\n }\n\n const eventName = this.generateEventName(url, method);\n\n const event = createEvent(\n EventType.API_CALL,\n eventName,\n { method, url, headers },\n { interception_mode: this.options.enforcement }\n );\n\n // Evaluate policy if configured\n if (this.options.policyUrl) {\n const policyDecision = await this.evaluatePolicy(url, method, { headers, body: null });\n\n if (policyDecision.decision === \"Deny\") {\n this.log(\"Policy violation detected\", { url, reasons: policyDecision.reasons });\n\n const violationEvent = createEvent(\n EventType.API_CALL,\n `${eventName}.policy_violation`,\n {\n ...event.payload,\n policy_decision: \"Deny\",\n policy_reasons: policyDecision.reasons,\n }\n );\n this.client?.track(violationEvent);\n\n if (this.options.enforcement === \"block\") {\n return { blocked: true, reasons: policyDecision.reasons ?? [] };\n } else if (this.options.enforcement === \"warn\") {\n console.warn(\n `[Trusera] Policy violation (allowed): ${policyDecision.reasons?.join(\", \") ?? \"Request denied\"}`\n );\n }\n }\n }\n\n this.client?.track(event);\n return { blocked: false, reasons: [] };\n }\n\n // ─── Axios interceptor ─────────────────────────────────────────────\n\n private _installAxios(): void {\n const axios = tryRequire(\"axios\");\n if (!axios?.interceptors) return;\n\n this.axiosDefault = axios;\n const self = this;\n\n this.axiosRequestId = axios.interceptors.request.use(\n async (config: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any\n const url = self._resolveAxiosUrl(config);\n const method = ((config.method as string | undefined) ?? \"get\").toUpperCase();\n const headers = self._flattenHeaders(config.headers);\n\n const { blocked, reasons } = await self._evaluateAndTrack(url, method, headers);\n if (blocked) {\n throw new Error(\n `[Trusera] Policy violation: ${reasons.join(\", \") || \"Request denied\"}`\n );\n }\n return config;\n }\n );\n\n this.axiosResponseId = axios.interceptors.response.use(\n (response: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any\n const url = self._resolveAxiosUrl(response.config);\n const method = ((response.config?.method as string | undefined) ?? \"get\").toUpperCase();\n\n if (!self.shouldExclude(url)) {\n const event = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.response`,\n { method, url, status: response.status, status_text: response.statusText }\n );\n self.client?.track(event);\n }\n return response;\n },\n (error: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any\n const config = error?.config;\n if (config) {\n const url = self._resolveAxiosUrl(config);\n const method = ((config.method as string | undefined) ?? \"get\").toUpperCase();\n\n if (!self.shouldExclude(url)) {\n const event = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.error`,\n { method, url, error: (error as Error).message }\n );\n self.client?.track(event);\n }\n }\n return Promise.reject(error as Error);\n }\n );\n\n this.log(\"Axios interceptor installed\");\n }\n\n private _uninstallAxios(): void {\n if (this.axiosDefault) {\n if (this.axiosRequestId !== null) {\n this.axiosDefault.interceptors.request.eject(this.axiosRequestId);\n this.axiosRequestId = null;\n }\n if (this.axiosResponseId !== null) {\n this.axiosDefault.interceptors.response.eject(this.axiosResponseId);\n this.axiosResponseId = null;\n }\n this.axiosDefault = null;\n }\n }\n\n private _resolveAxiosUrl(config: any): string { // eslint-disable-line @typescript-eslint/no-explicit-any\n if (!config) return \"\";\n const base: string = (config.baseURL as string | undefined) ?? \"\";\n const url: string = (config.url as string | undefined) ?? \"\";\n if (url.startsWith(\"http\")) return url;\n return base ? `${base.replace(/\\/$/, \"\")}/${url.replace(/^\\//, \"\")}` : url;\n }\n\n private _flattenHeaders(headers: any): Record<string, string> { // eslint-disable-line @typescript-eslint/no-explicit-any\n if (!headers) return {};\n if (typeof headers.toJSON === \"function\") {\n return headers.toJSON() as Record<string, string>;\n }\n const result: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) {\n if (typeof v === \"string\") result[k] = v;\n }\n return result;\n }\n\n // ─── Undici interceptor ─────────────────────────────────────────────\n\n private _installUndici(): void {\n const undici = tryRequire(\"undici\");\n if (!undici) return;\n\n this.undiciMod = undici;\n const self = this;\n\n // Patch undici.request\n if (typeof undici.request === \"function\") {\n this.origUndiciRequest = undici.request;\n undici.request = async function interceptedUndiciRequest(\n url: string | URL,\n options?: Record<string, unknown>\n ): Promise<unknown> {\n const urlStr = typeof url === \"string\" ? url : url.href;\n const method = ((options?.method as string | undefined) ?? \"GET\").toUpperCase();\n const headers = self._flattenHeaders(options?.headers);\n\n const { blocked, reasons } = await self._evaluateAndTrack(urlStr, method, headers);\n if (blocked) {\n throw new Error(\n `[Trusera] Policy violation: ${reasons.join(\", \") || \"Request denied\"}`\n );\n }\n\n const result: any = await self.origUndiciRequest!.call(undici, url, options); // eslint-disable-line @typescript-eslint/no-explicit-any\n\n if (!self.shouldExclude(urlStr)) {\n const event = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(urlStr, method)}.response`,\n { method, url: urlStr, status: result.statusCode }\n );\n self.client?.track(event);\n }\n\n return result;\n };\n }\n\n // Patch undici.fetch\n if (typeof undici.fetch === \"function\") {\n this.origUndiciFetch = undici.fetch;\n undici.fetch = async function interceptedUndiciFetch(\n input: string | URL | Request,\n init?: RequestInit\n ): Promise<Response> {\n const url = typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n const method = (init?.method ?? \"GET\").toUpperCase();\n\n if (self.shouldExclude(url)) {\n return self.origUndiciFetch!.call(undici, input, init) as Promise<Response>;\n }\n\n const { blocked, reasons } = await self._evaluateAndTrack(url, method, {});\n if (blocked) {\n throw new Error(\n `[Trusera] Policy violation: ${reasons.join(\", \") || \"Request denied\"}`\n );\n }\n\n const response = await self.origUndiciFetch!.call(undici, input, init) as Response;\n\n const event = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.response`,\n { method, url, status: response.status }\n );\n self.client?.track(event);\n\n return response;\n };\n }\n\n this.log(\"Undici interceptor installed\");\n }\n\n private _uninstallUndici(): void {\n if (this.undiciMod) {\n if (this.origUndiciRequest) {\n this.undiciMod.request = this.origUndiciRequest;\n this.origUndiciRequest = null;\n }\n if (this.origUndiciFetch) {\n this.undiciMod.fetch = this.origUndiciFetch;\n this.origUndiciFetch = null;\n }\n this.undiciMod = null;\n }\n }\n\n // ─── Fetch interceptor (core) ───────────────────────────────────────\n\n /**\n * Creates the intercepted fetch function.\n * This is the core of the interception logic.\n */\n private createInterceptedFetch(): typeof globalThis.fetch {\n const self = this;\n\n return async function interceptedFetch(\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n // Ensure we have original fetch to fall back to\n if (originalFetch === null) {\n throw new Error(\"Original fetch not available\");\n }\n\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n const method = init?.method ?? \"GET\";\n\n // Check if URL should be excluded\n if (self.shouldExclude(url)) {\n self.log(\"Skipping excluded URL\", { url });\n return originalFetch(input, init);\n }\n\n self.log(\"Intercepting request\", { method, url });\n\n // Extract request details\n const requestData = await self.extractRequestData(input, init);\n\n // Create tracking event\n const event = createEvent(\n EventType.API_CALL,\n self.generateEventName(url, method),\n {\n method,\n url,\n headers: requestData.headers,\n body: requestData.body,\n },\n {\n interception_mode: self.options.enforcement,\n }\n );\n\n // Evaluate policy if configured\n if (self.options.policyUrl) {\n const policyDecision = await self.evaluatePolicy(url, method, requestData);\n\n if (policyDecision.decision === \"Deny\") {\n self.log(\"Policy violation detected\", { url, reasons: policyDecision.reasons });\n\n // Track violation event\n const violationEvent = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.policy_violation`,\n {\n ...event.payload,\n policy_decision: \"Deny\",\n policy_reasons: policyDecision.reasons,\n }\n );\n\n self.client?.track(violationEvent);\n\n // Handle based on enforcement mode\n if (self.options.enforcement === \"block\") {\n throw new Error(\n `[Trusera] Policy violation: ${policyDecision.reasons?.join(\", \") ?? \"Request denied\"}`\n );\n } else if (self.options.enforcement === \"warn\") {\n console.warn(\n `[Trusera] Policy violation (allowed): ${policyDecision.reasons?.join(\", \") ?? \"Request denied\"}`\n );\n }\n } else {\n self.log(\"Policy check passed\", { url });\n }\n }\n\n // Track the API call event\n self.client?.track(event);\n\n // Execute the actual request\n const startTime = Date.now();\n let response: Response;\n let error: Error | undefined;\n\n try {\n response = await originalFetch(input, init);\n } catch (err) {\n error = err as Error;\n self.log(\"Request failed\", { url, error: error.message });\n\n // Track error event\n const errorEvent = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.error`,\n {\n ...event.payload,\n error: error.message,\n duration_ms: Date.now() - startTime,\n }\n );\n self.client?.track(errorEvent);\n\n throw error;\n }\n\n // Track response\n const responseEvent = createEvent(\n EventType.API_CALL,\n `${self.generateEventName(url, method)}.response`,\n {\n ...event.payload,\n status: response.status,\n status_text: response.statusText,\n duration_ms: Date.now() - startTime,\n response_headers: (() => { const h: Record<string, string> = {}; response.headers.forEach((v, k) => { h[k] = v; }); return h; })(),\n }\n );\n self.client?.track(responseEvent);\n\n return response;\n };\n }\n\n // ─── Shared utilities ───────────────────────────────────────────────\n\n /**\n * Checks if a URL should be excluded from interception.\n */\n private shouldExclude(url: string): boolean {\n return this.excludeRegexes.some((regex) => regex.test(url));\n }\n\n /**\n * Extracts request data for policy evaluation and tracking.\n */\n private async extractRequestData(\n _input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<{ headers: Record<string, string>; body: string | null }> {\n const headers: Record<string, string> = {};\n\n // Extract headers\n if (init?.headers) {\n if (init.headers instanceof Headers) {\n init.headers.forEach((value, key) => {\n headers[key] = value;\n });\n } else if (Array.isArray(init.headers)) {\n for (const [key, value] of init.headers) {\n headers[key] = value;\n }\n } else {\n Object.assign(headers, init.headers);\n }\n }\n\n // Extract body (if present and serializable)\n let body: string | null = null;\n if (init?.body) {\n if (typeof init.body === \"string\") {\n body = init.body;\n } else if (init.body instanceof URLSearchParams) {\n body = init.body.toString();\n } else if (init.body instanceof FormData) {\n body = \"[FormData]\";\n } else {\n body = \"[Binary data]\";\n }\n }\n\n return { headers, body };\n }\n\n /**\n * Evaluates request against Cedar policies.\n */\n private async evaluatePolicy(\n url: string,\n method: string,\n requestData: { headers: Record<string, string>; body: string | null }\n ): Promise<PolicyEvaluationResponse> {\n if (!this.options.policyUrl || !originalFetch) {\n return { decision: \"Allow\" };\n }\n\n try {\n const evaluationRequest: PolicyEvaluationRequest = {\n principal: this.client?.getAgentId() ?? \"unknown-agent\",\n action: `http.${method.toLowerCase()}`,\n resource: url,\n context: {\n headers: requestData.headers,\n body_present: requestData.body !== null,\n timestamp: new Date().toISOString(),\n },\n };\n\n const response = await originalFetch(this.options.policyUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(evaluationRequest),\n });\n\n if (!response.ok) {\n console.error(`[Trusera] Policy evaluation failed: ${response.status}`);\n return { decision: \"Allow\" }; // Fail open\n }\n\n return (await response.json()) as PolicyEvaluationResponse;\n } catch (error) {\n console.error(\"[Trusera] Policy evaluation error:\", error);\n return { decision: \"Allow\" }; // Fail open on error\n }\n }\n\n /**\n * Generates a structured event name from URL and method.\n */\n private generateEventName(url: string, method: string): string {\n try {\n const urlObj = new URL(url);\n const hostname = urlObj.hostname.replace(/\\./g, \"_\");\n const path = urlObj.pathname.split(\"/\").filter(Boolean).join(\"_\") || \"root\";\n return `http.${method.toLowerCase()}.${hostname}.${path}`;\n } catch {\n return `http.${method.toLowerCase()}.invalid_url`;\n }\n }\n\n private log(message: string, data?: Record<string, unknown>): void {\n if (this.options.debug) {\n console.log(`[Trusera Interceptor] ${message}`, data ?? \"\");\n }\n }\n}\n","/**\n * Standalone interceptor for Trusera SDK.\n *\n * Works WITHOUT any API key or platform connection.\n * Evaluates requests against local Cedar policies and logs events to disk.\n *\n * @example\n * ```typescript\n * import { StandaloneInterceptor } from \"trusera-sdk\";\n *\n * const interceptor = new StandaloneInterceptor({\n * policyFile: \".cedar/ai-policy.cedar\",\n * enforcement: \"block\",\n * logFile: \"agent-events.jsonl\",\n * excludePatterns: [\"api\\\\.trusera\\\\.\"],\n * debug: false\n * });\n *\n * interceptor.install();\n *\n * // All fetch calls are now monitored\n * await fetch(\"https://api.github.com/repos/test\");\n *\n * interceptor.uninstall();\n * ```\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { CedarEvaluator } from \"./cedar.js\";\nimport type { PolicyDecision } from \"./cedar.js\";\n\n/**\n * Enforcement modes for policy violations.\n */\nexport type StandaloneEnforcementMode = \"block\" | \"warn\" | \"log\";\n\n/**\n * Configuration for the standalone interceptor.\n */\nexport interface StandaloneInterceptorOptions {\n /** Path to Cedar policy file (optional) */\n policyFile?: string;\n /** How to handle policy violations (default: \"log\") */\n enforcement?: StandaloneEnforcementMode;\n /** Path to JSONL log file for events (optional) */\n logFile?: string;\n /** URL patterns to exclude from interception (regex strings) */\n excludePatterns?: string[];\n /** Enable debug logging to console */\n debug?: boolean;\n}\n\n/**\n * Event logged to JSONL file.\n */\ninterface LoggedEvent {\n timestamp: string;\n method: string;\n url: string;\n status?: number;\n duration_ms?: number;\n policy_decision: \"Allow\" | \"Deny\";\n policy_reasons?: string[];\n enforcement_action: \"allowed\" | \"blocked\" | \"warned\";\n error?: string;\n}\n\n/**\n * Global singleton state for standalone interceptor.\n */\nlet activeStandaloneInterceptor: StandaloneInterceptor | null = null;\nlet originalFetch: typeof globalThis.fetch | null = null;\n\n/**\n * Standalone HTTP interceptor that works without Trusera platform.\n *\n * Evaluates requests against local Cedar policies and logs events to disk.\n * Suitable for local development, testing, and air-gapped environments.\n *\n * Only one interceptor can be active at a time.\n */\nexport class StandaloneInterceptor {\n private options: Required<StandaloneInterceptorOptions>;\n private excludeRegexes: RegExp[] = [];\n private isInstalled = false;\n private policyEvaluator: CedarEvaluator | null = null;\n private logFileHandle: number | null = null;\n\n constructor(options: StandaloneInterceptorOptions = {}) {\n this.options = {\n policyFile: options.policyFile ?? \"\",\n enforcement: options.enforcement ?? \"log\",\n logFile: options.logFile ?? \"\",\n excludePatterns: options.excludePatterns ?? [],\n debug: options.debug ?? false,\n };\n\n // Compile exclude patterns\n this.excludeRegexes = this.options.excludePatterns.map(\n (pattern) => new RegExp(pattern)\n );\n }\n\n /**\n * Installs the standalone interceptor.\n * Loads Cedar policy (if configured) and monkey-patches globalThis.fetch.\n *\n * @throws Error if another interceptor is already installed\n */\n install(): void {\n if (activeStandaloneInterceptor !== null && activeStandaloneInterceptor !== this) {\n throw new Error(\n \"Another StandaloneInterceptor is already installed. Call uninstall() first.\"\n );\n }\n\n if (this.isInstalled) {\n this.log(\"Interceptor already installed\");\n return;\n }\n\n // Load Cedar policy if configured\n if (this.options.policyFile) {\n this.loadPolicy(this.options.policyFile);\n }\n\n // Open log file if configured\n if (this.options.logFile) {\n this.openLogFile(this.options.logFile);\n }\n\n // Save original fetch and install interceptor\n if (originalFetch === null) {\n originalFetch = globalThis.fetch;\n }\n\n globalThis.fetch = this.createInterceptedFetch();\n activeStandaloneInterceptor = this;\n this.isInstalled = true;\n\n this.log(\"Standalone interceptor installed\", {\n policyFile: this.options.policyFile,\n policyRules: this.policyEvaluator?.getRuleCount() ?? 0,\n enforcement: this.options.enforcement,\n logFile: this.options.logFile,\n excludePatterns: this.options.excludePatterns.length,\n });\n }\n\n /**\n * Uninstalls the interceptor and restores original fetch.\n * Closes log file if open.\n */\n uninstall(): void {\n if (!this.isInstalled) {\n return;\n }\n\n if (originalFetch !== null) {\n globalThis.fetch = originalFetch;\n originalFetch = null; // Reset for next install\n }\n\n // Close log file\n if (this.logFileHandle !== null) {\n try {\n fs.closeSync(this.logFileHandle);\n } catch (error) {\n console.error(\"[Trusera Standalone] Error closing log file:\", error);\n }\n this.logFileHandle = null;\n }\n\n activeStandaloneInterceptor = null;\n this.isInstalled = false;\n\n this.log(\"Standalone interceptor uninstalled\");\n }\n\n /**\n * Loads Cedar policy from file.\n */\n private loadPolicy(policyPath: string): void {\n try {\n const absolutePath = path.resolve(policyPath);\n const policyText = fs.readFileSync(absolutePath, \"utf-8\");\n this.policyEvaluator = new CedarEvaluator(policyText);\n\n this.log(\"Loaded Cedar policy\", {\n path: absolutePath,\n rules: this.policyEvaluator.getRuleCount(),\n });\n } catch (error) {\n const err = error as Error;\n console.error(\n `[Trusera Standalone] Failed to load policy file ${policyPath}:`,\n err.message\n );\n // Continue without policy\n this.policyEvaluator = null;\n }\n }\n\n /**\n * Opens log file for appending.\n */\n private openLogFile(logPath: string): void {\n try {\n const absolutePath = path.resolve(logPath);\n\n // Ensure directory exists\n const dir = path.dirname(absolutePath);\n if (!fs.existsSync(dir)) {\n fs.mkdirSync(dir, { recursive: true });\n }\n\n // Open file for appending\n this.logFileHandle = fs.openSync(absolutePath, \"a\");\n\n this.log(\"Opened log file\", { path: absolutePath });\n } catch (error) {\n const err = error as Error;\n console.error(\n `[Trusera Standalone] Failed to open log file ${logPath}:`,\n err.message\n );\n this.logFileHandle = null;\n }\n }\n\n /**\n * Creates the intercepted fetch function.\n */\n private createInterceptedFetch(): typeof globalThis.fetch {\n const self = this;\n\n return async function interceptedFetch(\n input: RequestInfo | URL,\n init?: RequestInit\n ): Promise<Response> {\n if (originalFetch === null) {\n throw new Error(\"Original fetch not available\");\n }\n\n const url = typeof input === \"string\" ? input : input instanceof URL ? input.href : input.url;\n const method = init?.method ?? \"GET\";\n\n // Check if URL should be excluded\n if (self.shouldExclude(url)) {\n self.log(\"Skipping excluded URL\", { url });\n return originalFetch(input, init);\n }\n\n self.log(\"Intercepting request\", { method, url });\n\n // Extract hostname and path for policy evaluation\n let hostname = \"\";\n let pathname = \"\";\n try {\n const urlObj = new URL(url);\n hostname = urlObj.hostname;\n pathname = urlObj.pathname;\n } catch {\n // Invalid URL, skip policy check\n self.log(\"Invalid URL, skipping policy check\", { url });\n return originalFetch(input, init);\n }\n\n // Evaluate policy if loaded\n let policyDecision: PolicyDecision = { decision: \"Allow\", reasons: [] };\n if (self.policyEvaluator) {\n policyDecision = self.policyEvaluator.evaluate({\n url,\n method,\n hostname,\n path: pathname,\n });\n\n if (policyDecision.decision === \"Deny\") {\n self.log(\"Policy violation detected\", {\n url,\n reasons: policyDecision.reasons,\n });\n\n // Log the violation event\n self.logEvent({\n timestamp: new Date().toISOString(),\n method,\n url,\n policy_decision: \"Deny\",\n policy_reasons: policyDecision.reasons,\n enforcement_action: self.options.enforcement === \"block\" ? \"blocked\" : \"warned\",\n });\n\n // Handle based on enforcement mode\n if (self.options.enforcement === \"block\") {\n throw new Error(\n `[Trusera] Policy violation: ${policyDecision.reasons.join(\", \")}`\n );\n } else if (self.options.enforcement === \"warn\") {\n console.warn(\n `[Trusera] Policy violation (allowed): ${policyDecision.reasons.join(\", \")}`\n );\n }\n } else {\n self.log(\"Policy check passed\", { url });\n }\n }\n\n // Execute the actual request\n const startTime = Date.now();\n let response: Response;\n let error: Error | undefined;\n\n try {\n response = await originalFetch(input, init);\n } catch (err) {\n error = err as Error;\n self.log(\"Request failed\", { url, error: error.message });\n\n // Log error event\n const errorEvent: LoggedEvent = {\n timestamp: new Date().toISOString(),\n method,\n url,\n duration_ms: Date.now() - startTime,\n policy_decision: policyDecision.decision,\n enforcement_action: \"allowed\",\n error: error.message,\n };\n if (policyDecision.reasons.length > 0) {\n errorEvent.policy_reasons = policyDecision.reasons;\n }\n self.logEvent(errorEvent);\n\n throw error;\n }\n\n // Log successful response\n const successEvent: LoggedEvent = {\n timestamp: new Date().toISOString(),\n method,\n url,\n status: response.status,\n duration_ms: Date.now() - startTime,\n policy_decision: policyDecision.decision,\n enforcement_action: \"allowed\",\n };\n if (policyDecision.reasons.length > 0) {\n successEvent.policy_reasons = policyDecision.reasons;\n }\n self.logEvent(successEvent);\n\n return response;\n };\n }\n\n /**\n * Checks if a URL should be excluded from interception.\n */\n private shouldExclude(url: string): boolean {\n return this.excludeRegexes.some((regex) => regex.test(url));\n }\n\n /**\n * Logs an event to the JSONL file.\n */\n private logEvent(event: LoggedEvent): void {\n if (this.logFileHandle === null) {\n return;\n }\n\n try {\n const line = JSON.stringify(event) + \"\\n\";\n fs.writeSync(this.logFileHandle, line);\n } catch (error) {\n const err = error as Error;\n console.error(\"[Trusera Standalone] Error writing to log file:\", err.message);\n }\n }\n\n /**\n * Debug logging.\n */\n private log(message: string, data?: Record<string, unknown>): void {\n if (this.options.debug) {\n console.log(`[Trusera Standalone] ${message}`, data ?? \"\");\n }\n }\n}\n","/**\n * Cedar-like policy evaluator for TypeScript.\n *\n * Evaluates simplified Cedar policy rules against HTTP request contexts.\n * Supports forbid/permit rules with conditions on URL, method, hostname, path.\n *\n * @example\n * ```typescript\n * const policy = `\n * forbid (principal, action == Action::\"http.get\", resource)\n * when { resource.hostname == \"malicious.com\" };\n * `;\n *\n * const evaluator = new CedarEvaluator(policy);\n * const result = evaluator.evaluate({\n * url: \"https://malicious.com/api\",\n * method: \"GET\",\n * hostname: \"malicious.com\"\n * });\n *\n * console.log(result.decision); // \"Deny\"\n * console.log(result.reasons); // [\"Policy violation: hostname == malicious.com\"]\n * ```\n */\n\n/**\n * Request context for policy evaluation.\n */\nexport interface PolicyContext {\n /** Full URL being accessed */\n url: string;\n /** HTTP method (GET, POST, etc.) */\n method: string;\n /** Hostname extracted from URL */\n hostname: string;\n /** Path extracted from URL */\n path?: string;\n /** Custom context fields */\n [key: string]: unknown;\n}\n\n/**\n * Policy evaluation result.\n */\nexport interface PolicyDecision {\n /** Allow or Deny */\n decision: \"Allow\" | \"Deny\";\n /** Reasons for the decision (policy rules that matched) */\n reasons: string[];\n}\n\n/**\n * Parsed policy rule.\n */\ninterface PolicyRule {\n /** forbid or permit */\n effect: \"forbid\" | \"permit\";\n /** Action pattern (e.g., \"http.get\", \"*\") */\n action: string;\n /** Field name being checked (e.g., \"hostname\", \"path\") */\n field: string;\n /** Comparison operator (==, !=, contains, startsWith, etc.) */\n operator: string;\n /** Value to compare against */\n value: string;\n /** Raw rule text for debugging */\n raw: string;\n}\n\n/**\n * Cedar-like policy evaluator.\n *\n * Parses and evaluates simplified Cedar policies for HTTP requests.\n * Supports basic forbid/permit rules with string matching conditions.\n */\nexport class CedarEvaluator {\n private rules: PolicyRule[] = [];\n\n /**\n * Creates a new Cedar evaluator with the given policy text.\n *\n * @param policyText - Cedar-like policy rules\n */\n constructor(policyText: string) {\n this.rules = this.parsePolicy(policyText);\n }\n\n /**\n * Evaluates a request context against loaded policies.\n *\n * @param context - Request context to evaluate\n * @returns Policy decision with reasons\n */\n evaluate(context: PolicyContext): PolicyDecision {\n const matchedRules: PolicyRule[] = [];\n\n for (const rule of this.rules) {\n if (this.evaluateRule(rule, context)) {\n matchedRules.push(rule);\n }\n }\n\n // If any forbid rules matched, deny the request\n const forbidMatches = matchedRules.filter((r) => r.effect === \"forbid\");\n if (forbidMatches.length > 0) {\n return {\n decision: \"Deny\",\n reasons: forbidMatches.map(\n (r) => `Policy violation: ${r.field} ${r.operator} ${r.value}`\n ),\n };\n }\n\n // Otherwise allow\n return {\n decision: \"Allow\",\n reasons: [],\n };\n }\n\n /**\n * Parses Cedar-like policy text into rule objects.\n *\n * Supported syntax:\n * ```\n * forbid (principal, action == Action::\"http.get\", resource)\n * when { resource.hostname == \"malicious.com\" };\n *\n * forbid (principal, action == Action::\"*\", resource)\n * when { resource.url contains \"blocked-domain.com\" };\n * ```\n */\n private parsePolicy(policyText: string): PolicyRule[] {\n const rules: PolicyRule[] = [];\n\n // Strip comments (// style)\n const cleaned = policyText.replace(/\\/\\/[^\\n]*/g, \"\");\n\n // Regex to match forbid/permit rules\n // Matches: (forbid|permit) ( ... ) when { resource.field operator \"value\" };\n const rulePattern = /\\b(forbid|permit)\\s*\\(\\s*principal\\s*,\\s*action\\s*==\\s*Action::\"([^\"]+)\"\\s*,\\s*resource\\s*\\)\\s*when\\s*\\{([^}]+)\\}\\s*;/gim;\n\n let match;\n while ((match = rulePattern.exec(cleaned)) !== null) {\n const effect = match[1]?.toLowerCase() as \"forbid\" | \"permit\";\n const action = match[2];\n const conditionBody = match[3];\n\n if (!effect || !action || !conditionBody) {\n continue;\n }\n\n // Parse condition (resource.field operator value)\n const conditionPattern = /resource\\.(\\w+)\\s*(==|!=|contains|startsWith|endsWith)\\s*\"([^\"]+)\"/gi;\n let condMatch;\n while ((condMatch = conditionPattern.exec(conditionBody)) !== null) {\n const field = condMatch[1];\n const operator = condMatch[2];\n const value = condMatch[3];\n\n if (!field || !operator || !value) {\n continue;\n }\n\n rules.push({\n effect,\n action,\n field,\n operator,\n value,\n raw: match[0] ?? \"\",\n });\n }\n }\n\n return rules;\n }\n\n /**\n * Evaluates a single rule against a context.\n */\n private evaluateRule(rule: PolicyRule, context: PolicyContext): boolean {\n // Check if action matches\n if (!this.matchesAction(rule.action, context.method)) {\n return false;\n }\n\n // Get the field value from context\n const fieldValue = this.getFieldValue(rule.field, context);\n if (fieldValue === undefined) {\n return false;\n }\n\n // Evaluate the condition\n return this.evaluateCondition(\n String(fieldValue),\n rule.operator,\n rule.value\n );\n }\n\n /**\n * Checks if an action pattern matches the HTTP method.\n */\n private matchesAction(actionPattern: string, method: string): boolean {\n if (actionPattern === \"*\") {\n return true;\n }\n\n // Action format: \"http.get\", \"http.post\", etc.\n const normalizedPattern = actionPattern.toLowerCase();\n const normalizedMethod = method.toLowerCase();\n\n if (normalizedPattern === `http.${normalizedMethod}`) {\n return true;\n }\n\n // Check for wildcard patterns\n if (normalizedPattern.endsWith(\"*\")) {\n const prefix = normalizedPattern.slice(0, -1);\n return normalizedMethod.startsWith(prefix);\n }\n\n return false;\n }\n\n /**\n * Extracts a field value from the context.\n */\n private getFieldValue(field: string, context: PolicyContext): unknown {\n // Direct context access\n if (field in context) {\n return context[field];\n }\n\n // Special handling for common fields\n if (field === \"hostname\") {\n return context.hostname;\n }\n\n if (field === \"path\") {\n if (context.path !== undefined) {\n return context.path;\n }\n // Try to extract from URL\n try {\n const url = new URL(context.url);\n return url.pathname;\n } catch {\n return undefined;\n }\n }\n\n if (field === \"method\") {\n return context.method;\n }\n\n if (field === \"url\") {\n return context.url;\n }\n\n return undefined;\n }\n\n /**\n * Evaluates a condition operator.\n */\n private evaluateCondition(\n actual: string,\n operator: string,\n expected: string\n ): boolean {\n const actualLower = actual.toLowerCase();\n const expectedLower = expected.toLowerCase();\n\n switch (operator.toLowerCase()) {\n case \"==\":\n return actualLower === expectedLower;\n case \"!=\":\n return actualLower !== expectedLower;\n case \"contains\":\n return actualLower.includes(expectedLower);\n case \"startswith\":\n return actualLower.startsWith(expectedLower);\n case \"endswith\":\n return actualLower.endsWith(expectedLower);\n default:\n return false;\n }\n }\n\n /**\n * Returns the number of loaded rules.\n */\n getRuleCount(): number {\n return this.rules.length;\n }\n}\n","import type { TruseraClient } from \"../client.js\";\nimport { EventType, createEvent, type Event } from \"../events.js\";\nimport type { EnforcementMode } from \"../interceptor.js\";\nimport type { CedarEvaluator } from \"../cedar.js\";\n\n/**\n * Options for configuring the LangChain handler with policy enforcement.\n */\nexport interface LangChainHandlerOptions {\n /** Enforcement mode for policy violations (default: none/passive tracking only) */\n enforcement?: EnforcementMode;\n /** Cedar policy evaluator for local policy checks */\n cedarEvaluator?: CedarEvaluator;\n}\n\n/**\n * LangChain.js callback handler for Trusera integration.\n * Implements the BaseCallbackHandler interface to track LLM calls,\n * tool executions, and chain steps.\n *\n * Supports optional Cedar policy enforcement: block throws, warn logs, log is silent.\n * Without options, operates in passive tracking mode (full backward compatibility).\n *\n * Note: This uses structural typing to avoid requiring langchain as a dependency.\n * If langchain types change, this will need updating.\n *\n * @example\n * ```typescript\n * import { ChatOpenAI } from \"langchain/chat_models/openai\";\n * import { TruseraClient, TruseraLangChainHandler, CedarEvaluator } from \"trusera-sdk\";\n *\n * const client = new TruseraClient({ apiKey: \"tsk_xxx\" });\n *\n * // Passive tracking (no enforcement)\n * const handler = new TruseraLangChainHandler(client);\n *\n * // With Cedar policy enforcement\n * const evaluator = new CedarEvaluator(policyText);\n * const enforcedHandler = new TruseraLangChainHandler(client, {\n * enforcement: \"block\",\n * cedarEvaluator: evaluator\n * });\n *\n * const model = new ChatOpenAI({ callbacks: [enforcedHandler] });\n * await model.invoke(\"What is AI safety?\");\n *\n * await client.close();\n * ```\n */\nexport class TruseraLangChainHandler {\n private readonly client: TruseraClient;\n private readonly pendingEvents = new Map<string, Event>();\n private readonly enforcement: EnforcementMode | undefined;\n private readonly cedarEvaluator: CedarEvaluator | undefined;\n\n constructor(client: TruseraClient, options?: LangChainHandlerOptions) {\n this.client = client;\n this.enforcement = options?.enforcement;\n this.cedarEvaluator = options?.cedarEvaluator;\n }\n\n /**\n * Called when an LLM starts running.\n */\n handleLLMStart(\n llm: { name: string },\n prompts: string[],\n runId: string,\n parentRunId?: string,\n extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>\n ): void {\n // Evaluate policy if enforcement is configured\n if (this.enforcement && this.cedarEvaluator) {\n const decision = this.cedarEvaluator.evaluate({\n url: `langchain://llm/${llm.name}`,\n method: \"INVOKE\",\n hostname: \"langchain\",\n path: `/llm/${llm.name}`,\n });\n\n if (decision.decision === \"Deny\") {\n this._handleViolation(\n `langchain.llm.${llm.name}`,\n EventType.LLM_INVOKE,\n decision.reasons,\n runId\n );\n\n if (this.enforcement === \"block\") {\n throw new Error(\n `[Trusera] Policy violation: LLM ${llm.name} denied - ${decision.reasons.join(\", \")}`\n );\n }\n }\n }\n\n const event = createEvent(\n EventType.LLM_INVOKE,\n `langchain.llm.${llm.name}`,\n {\n prompts,\n prompt_count: prompts.length,\n invocation_params: extraParams ?? {},\n },\n {\n run_id: runId,\n parent_run_id: parentRunId,\n tags: tags ?? [],\n ...metadata,\n }\n );\n\n this.pendingEvents.set(runId, event);\n this.client.track(event);\n }\n\n /**\n * Called when an LLM finishes running.\n */\n handleLLMEnd(\n output: { generations: Array<Array<{ text: string }>> },\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const texts = output.generations.flatMap((gen) => gen.map((g) => g.text));\n\n const event = createEvent(\n EventType.LLM_INVOKE,\n `${startEvent.name}.completed`,\n {\n ...startEvent.payload,\n outputs: texts,\n output_count: texts.length,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when an LLM encounters an error.\n */\n handleLLMError(\n error: Error,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.LLM_INVOKE,\n `${startEvent.name}.error`,\n {\n ...startEvent.payload,\n error: error.message,\n error_type: error.name,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when a tool starts running.\n */\n handleToolStart(\n tool: { name: string },\n input: string,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>\n ): void {\n // Evaluate policy if enforcement is configured\n if (this.enforcement && this.cedarEvaluator) {\n const decision = this.cedarEvaluator.evaluate({\n url: `langchain://tool/${tool.name}`,\n method: \"EXECUTE\",\n hostname: \"langchain\",\n path: `/tool/${tool.name}`,\n });\n\n if (decision.decision === \"Deny\") {\n this._handleViolation(\n `langchain.tool.${tool.name}`,\n EventType.TOOL_CALL,\n decision.reasons,\n runId\n );\n\n if (this.enforcement === \"block\") {\n throw new Error(\n `[Trusera] Policy violation: tool ${tool.name} denied - ${decision.reasons.join(\", \")}`\n );\n }\n }\n }\n\n const event = createEvent(\n EventType.TOOL_CALL,\n `langchain.tool.${tool.name}`,\n {\n input,\n input_length: input.length,\n },\n {\n run_id: runId,\n parent_run_id: parentRunId,\n tags: tags ?? [],\n ...metadata,\n }\n );\n\n this.pendingEvents.set(runId, event);\n this.client.track(event);\n }\n\n /**\n * Called when a tool finishes running.\n */\n handleToolEnd(\n output: string,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.TOOL_CALL,\n `${startEvent.name}.completed`,\n {\n ...startEvent.payload,\n output,\n output_length: output.length,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when a tool encounters an error.\n */\n handleToolError(\n error: Error,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.TOOL_CALL,\n `${startEvent.name}.error`,\n {\n ...startEvent.payload,\n error: error.message,\n error_type: error.name,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when a chain starts running.\n */\n handleChainStart(\n chain: { name: string },\n inputs: Record<string, unknown>,\n runId: string,\n parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>\n ): void {\n const event = createEvent(\n EventType.DECISION,\n `langchain.chain.${chain.name}`,\n {\n inputs,\n input_keys: Object.keys(inputs),\n },\n {\n run_id: runId,\n parent_run_id: parentRunId,\n tags: tags ?? [],\n ...metadata,\n }\n );\n\n this.pendingEvents.set(runId, event);\n this.client.track(event);\n }\n\n /**\n * Called when a chain finishes running.\n */\n handleChainEnd(\n outputs: Record<string, unknown>,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.DECISION,\n `${startEvent.name}.completed`,\n {\n ...startEvent.payload,\n outputs,\n output_keys: Object.keys(outputs),\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Called when a chain encounters an error.\n */\n handleChainError(\n error: Error,\n runId: string\n ): void {\n const startEvent = this.pendingEvents.get(runId);\n if (!startEvent) return;\n\n const event = createEvent(\n EventType.DECISION,\n `${startEvent.name}.error`,\n {\n ...startEvent.payload,\n error: error.message,\n error_type: error.name,\n },\n startEvent.metadata\n );\n\n this.client.track(event);\n this.pendingEvents.delete(runId);\n }\n\n /**\n * Returns the number of pending (incomplete) events.\n * Useful for testing and debugging.\n */\n getPendingEventCount(): number {\n return this.pendingEvents.size;\n }\n\n /**\n * Clears all pending events.\n * Should only be used in testing or error recovery.\n */\n clearPendingEvents(): void {\n this.pendingEvents.clear();\n }\n\n /**\n * Handle a policy violation: track POLICY_VIOLATION event and warn if needed.\n */\n private _handleViolation(\n name: string,\n eventType: EventType,\n reasons: string[],\n runId: string\n ): void {\n const violationEvent = createEvent(\n eventType,\n `${name}.policy_violation`,\n {\n policy_decision: \"Deny\",\n policy_reasons: reasons,\n },\n { run_id: runId }\n );\n this.client.track(violationEvent);\n\n if (this.enforcement === \"warn\") {\n console.warn(\n `[Trusera] Policy violation (allowed): ${reasons.join(\", \")}`\n );\n }\n }\n}\n"],"mappings":"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","names":["EventType","path","originalFetch"]}
package/dist/index.d.cts CHANGED
@@ -24,6 +24,11 @@ interface TruseraClientOptions {
24
24
  flushInterval?: number;
25
25
  batchSize?: number;
26
26
  debug?: boolean;
27
+ autoRegister?: boolean;
28
+ agentName?: string;
29
+ agentType?: string;
30
+ environment?: string;
31
+ heartbeatInterval?: number;
27
32
  }
28
33
  declare class TruseraClient {
29
34
  private readonly apiKey;
@@ -35,6 +40,13 @@ declare class TruseraClient {
35
40
  private eventQueue;
36
41
  private flushTimer;
37
42
  private isClosed;
43
+ private readonly autoRegister;
44
+ private readonly agentName;
45
+ private readonly agentType;
46
+ private readonly environment;
47
+ private readonly heartbeatInterval;
48
+ private fleetAgentId;
49
+ private heartbeatTimer;
38
50
  constructor(options: TruseraClientOptions);
39
51
  registerAgent(name: string, framework: string): Promise<string>;
40
52
  track(event: Event): void;
@@ -42,6 +54,12 @@ declare class TruseraClient {
42
54
  close(): Promise<void>;
43
55
  getQueueSize(): number;
44
56
  getAgentId(): string | undefined;
57
+ private getProcessInfo;
58
+ private getNetworkInfo;
59
+ private registerWithFleet;
60
+ private startHeartbeat;
61
+ private stopHeartbeat;
62
+ private sendHeartbeat;
45
63
  private startFlushTimer;
46
64
  private stopFlushTimer;
47
65
  private log;
package/dist/index.d.ts CHANGED
@@ -24,6 +24,11 @@ interface TruseraClientOptions {
24
24
  flushInterval?: number;
25
25
  batchSize?: number;
26
26
  debug?: boolean;
27
+ autoRegister?: boolean;
28
+ agentName?: string;
29
+ agentType?: string;
30
+ environment?: string;
31
+ heartbeatInterval?: number;
27
32
  }
28
33
  declare class TruseraClient {
29
34
  private readonly apiKey;
@@ -35,6 +40,13 @@ declare class TruseraClient {
35
40
  private eventQueue;
36
41
  private flushTimer;
37
42
  private isClosed;
43
+ private readonly autoRegister;
44
+ private readonly agentName;
45
+ private readonly agentType;
46
+ private readonly environment;
47
+ private readonly heartbeatInterval;
48
+ private fleetAgentId;
49
+ private heartbeatTimer;
38
50
  constructor(options: TruseraClientOptions);
39
51
  registerAgent(name: string, framework: string): Promise<string>;
40
52
  track(event: Event): void;
@@ -42,6 +54,12 @@ declare class TruseraClient {
42
54
  close(): Promise<void>;
43
55
  getQueueSize(): number;
44
56
  getAgentId(): string | undefined;
57
+ private getProcessInfo;
58
+ private getNetworkInfo;
59
+ private registerWithFleet;
60
+ private startHeartbeat;
61
+ private stopHeartbeat;
62
+ private sendHeartbeat;
45
63
  private startFlushTimer;
46
64
  private stopFlushTimer;
47
65
  private log;