@juspay/neurolink 13.8.14 โ†’ 13.8.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/dist/browser/neurolink.min.js +398 -398
  3. package/dist/cli/utils/serverUtils.d.ts +4 -0
  4. package/dist/cli/utils/serverUtils.js +5 -1
  5. package/dist/core/conversationMemoryFactory.d.ts +2 -2
  6. package/dist/core/conversationMemoryFactory.js +2 -2
  7. package/dist/core/conversationMemoryInitializer.d.ts +2 -2
  8. package/dist/core/conversationMemoryInitializer.js +2 -2
  9. package/dist/core/redisConversationMemoryManager.d.ts +13 -2
  10. package/dist/core/redisConversationMemoryManager.js +31 -1
  11. package/dist/neurolink.js +1 -1
  12. package/dist/server/abstract/baseServerAdapter.d.ts +30 -1
  13. package/dist/server/abstract/baseServerAdapter.js +71 -0
  14. package/dist/server/adapters/expressAdapter.js +5 -0
  15. package/dist/server/adapters/fastifyAdapter.d.ts +1 -0
  16. package/dist/server/adapters/fastifyAdapter.js +16 -3
  17. package/dist/server/adapters/honoAdapter.d.ts +6 -0
  18. package/dist/server/adapters/honoAdapter.js +67 -16
  19. package/dist/server/adapters/koaAdapter.js +5 -0
  20. package/dist/server/middleware/auth.js +3 -0
  21. package/dist/server/routes/agentRoutes.d.ts +42 -1
  22. package/dist/server/routes/agentRoutes.js +140 -31
  23. package/dist/server/routes/index.d.ts +9 -0
  24. package/dist/server/routes/index.js +15 -1
  25. package/dist/server/utils/carriedContextMark.d.ts +28 -0
  26. package/dist/server/utils/carriedContextMark.js +32 -0
  27. package/dist/types/common.d.ts +2 -1
  28. package/dist/types/conversation.d.ts +12 -0
  29. package/dist/types/server.d.ts +140 -2
  30. package/docs-site/static/search-index.json +10 -6
  31. package/package.json +2 -1
@@ -7640,7 +7640,7 @@
7640
7640
  {"objectID":"ad29fcad00b9d73eacff3f9ca6c0adb18b19c60ff1e6f3aa93b80e38865394a9","title":"createServer(neurolink, options?)","url":"/docs/guides/server-adapters/api-reference#createserverneurolink-options","content":"Convenience function that creates a server adapter from a NeuroLink instance.","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"createServer(neurolink, options?)","lvl3":""}},
7641
7641
  {"objectID":"8cc46647ccb6a0e9d912da7efa7b1827b1c6e4ef762dbb5b88baa676d6841a8a","title":"ServerAdapterFactory","url":"/docs/guides/server-adapters/api-reference#serveradapterfactory","content":"Static factory class for creating adapters. Supports dynamic imports so unused frameworks are never bundled.\n\n| Method | Signature | Description |\n| ------------------------- | ---------------------------------------------------------------------- | --------------------------------- |\n| create | (options: ServerAdapterFactoryOptions) => Promise<BaseServerAdapter> | Create adapter by framework name |\n| createHono | (neurolink, config?) => Promise<BaseServerAdapter> | Shortcut for Hono |\n| createExpress | (neurolink, config?) => Promise<BaseServerAdapter> | Shortcut for Express |\n| createFastify | (neurolink, config?) => Promise<BaseServerAdapter> | Shortcut for Fastify |\n| createKoa | (neurolink, config?) => Promise<BaseServerAdapter> | Shortcut for Koa |\n| registerAdapter | (framework, adapterClass) => void | Register a custom adapter class |\n| isSupported | (framework: string) => boolean | Check if a framework is supported |\n| getSupportedFrameworks | () => Array<{framework, status, description}> | List all supported frameworks |\n| getRecommendedFramework | () => ServerFramework | Returns \"hono\" |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ServerAdapterFactory","lvl3":""}},
7642
7642
  {"objectID":"84823b5000a24fb8b2d82aead2e94a037d9bdea5be7ed0587f8feb198974d1c7","title":"BaseServerAdapter","url":"/docs/guides/server-adapters/api-reference#baseserveradapter","content":"Abstract base class that all framework adapters extend. Extends EventEmitter.\n\n| Method | Signature | Description |\n| -------------------------- | -------------------------------------------- | --------------------------------------------- |\n| initialize | () => Promise<void> | Initialize routes, middleware, framework |\n| start | () => Promise<void> | Start listening (abstract) |\n| stop | () => Promise<void> | Stop server with graceful shutdown (abstract) |\n| registerRoute | (route: RouteDefinition) => void | Register a single route |\n| registerRouteGroup | (group: RouteGroup) => void | Register a route group with prefix |\n| registerMiddleware | (middleware: MiddlewareDefinition) => void | Register middleware |\n| getStatus | () => ServerStatus | Get running status, uptime, route count |\n| listRoutes | () => RouteDefinition[] | List all registered routes |\n| getConfig | () => RequiredServerAdapterConfig | Get resolved configuration |\n| getLifecycleState | () => ServerLifecycleState | Get current lifecycle state |\n| getActiveConnectionCount | () => number | Number of active connections |\n| getFrameworkInstance | () => unknown | Get underlying framework instance (abstract) |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"BaseServerAdapter","lvl3":""}},
7643
- {"objectID":"8147853e8b9b9e7fc31c0480161f56665f741cd53ccbeb50aeed5c67242ed3b3","title":"ServerAdapterConfig","url":"/docs/guides/server-adapters/api-reference#serveradapterconfig","content":"All fields are optional; defaults are applied by the base class.\n\n| Field | Type | Default | Description |\n| ---------------------- | ------------------ | ------------------------ | --------------------------------- |\n| port | number | 3000 | Server port |\n| host | string | \"0.0.0.0\" | Server host |\n| basePath | string | \"/api\" | Base path for all routes |\n| cors | CORSConfig | enabled, origins [\"*\"] | CORS settings |\n| rateLimit | RateLimitConfig | enabled, 100 req/15 min | Rate limiting |\n| bodyParser | BodyParserConfig | enabled, 10 MB limit | Body parsing |\n| logging | LoggingConfig | enabled, level \"info\" | Request logging |\n| timeout | number | 30000 | Request timeout (ms) |\n| enableMetrics | boolean | true | Expose /api/metrics |\n| enableSwagger | boolean | false | Enable OpenAPI docs |\n| disableBuiltInHealth | boolean | false | Skip built-in /health, /ready |\n| redaction | RedactionConfig | disabled | Stream redaction settings |\n| shutdown | ShutdownConfig | 30s shutdown, 15s drain | Graceful shutdown behavior |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ServerAdapterConfig","lvl3":""}},
7643
+ {"objectID":"8147853e8b9b9e7fc31c0480161f56665f741cd53ccbeb50aeed5c67242ed3b3","title":"ServerAdapterConfig","url":"/docs/guides/server-adapters/api-reference#serveradapterconfig","content":"All fields are optional; defaults are applied by the base class.\n\n| Field | Type | Default | Description |\n| ---------------------- | ------------------ | ------------------------ | --------------------------------- |\n| port | number | 3000 | Server port |\n| host | string | \"0.0.0.0\" | Server host |\n| basePath | string | \"/api\" | Base path for all routes |\n| cors | CORSConfig | enabled, origins [\"*\"] | CORS settings |\n| rateLimit | RateLimitConfig | enabled, 100 req/15 min | Rate limiting |\n| bodyParser | BodyParserConfig | enabled, 10 MB limit | Body parsing |\n| logging | LoggingConfig | enabled, level \"info\" | Request logging |\n| timeout | number | 30000 | Request timeout (ms) |\n| enableMetrics | boolean | true | Expose /api/metrics |\n| enableSwagger | boolean | false | Enable OpenAPI docs |\n| disableBuiltInHealth | boolean | false | Skip built-in /health, /ready |\n| redaction | RedactionConfig | disabled | Stream redaction settings |\n| shutdown | ShutdownConfig | 30s shutdown, 15s drain | Graceful shutdown behavior |\n| carryMiddlewareState | boolean | false | Carry middleware state (opt-in) |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ServerAdapterConfig","lvl3":""}},
7644
7644
  {"objectID":"b9b51bfed21ee76f61c6b63bb94df2c91a354520e27a7b4bd1a18092fd42fe93","title":"ShutdownConfig","url":"/docs/guides/server-adapters/api-reference#shutdownconfig","content":"| Field | Type | Default | Description |\n| --------------------------- | --------- | ------- | ----------------------------- |\n| gracefulShutdownTimeoutMs | number | 30000 | Max time for entire shutdown |\n| drainTimeoutMs | number | 15000 | Max time to drain connections |\n| forceClose | boolean | true | Force-close after timeout |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ShutdownConfig","lvl3":""}},
7645
7645
  {"objectID":"20dfcebcadaaeeffe2c27254dd2d227fabc2307718987ac56dba6ec74ce8deaa","title":"Server Lifecycle States","url":"/docs/guides/server-adapters/api-reference#server-lifecycle-states","content":"\"uninitialized\" | \"initializing\" | \"initialized\" | \"starting\" | \"running\" | \"draining\" | \"stopping\" | \"stopped\" | \"error\"","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Server Lifecycle States","lvl3":""}},
7646
7646
  {"objectID":"b4f54c24b5274a577a9050cb268ff0e8254297ba5f2c865ca5343f9b8d9b2ca9","title":"Events (ServerAdapterEvents)","url":"/docs/guides/server-adapters/api-reference#events-serveradapterevents","content":"| Event | Payload |\n| ------------- | ------------------------------------------------ |\n| initialized | { config, routeCount, middlewareCount } |\n| started | { port, host, timestamp } |\n| stopped | { uptime, timestamp } |\n| request | { requestId, method, path, timestamp } |\n| response | { requestId, statusCode, duration, timestamp } |\n| error | { requestId?, error, timestamp } |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Events (ServerAdapterEvents)","lvl3":""}},
@@ -7719,7 +7719,7 @@
7719
7719
  {"objectID":"1aba31d0169a6255c13c0834ddf34f5e433ad08bd11d3f4f8d77e52d2aac5178","title":"Route and Middleware Types","url":"/docs/guides/server-adapters/api-reference#route-and-middleware-types","content":"| Type | Description |\n| ---------------------- | ----------------------------------------------------------------------------------- |\n| HttpMethod | \"GET\" \\| \"POST\" \\| \"PUT\" \\| \"DELETE\" \\| \"PATCH\" \\| \"OPTIONS\" |\n| RouteDefinition | Full route definition |\n| RouteGroup | Group of routes with prefix and optional middleware |\n| RouteHandler<T> | (ctx: ServerContext) => Promise<T \\| ServerResponse<T> \\| AsyncIterable<unknown>> |\n| MiddlewareDefinition | Middleware definition with name, order, handler, paths |\n| MiddlewareHandler | (ctx, next) => Promise<unknown> |\n| CreateRoutesOptions | Options for createAllRoutes |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Route and Middleware Types","lvl3":""}},
7720
7720
  {"objectID":"a4daff1325a8b89a05cc217c671de5a359fdcd820d52991fdedf7265940eb257","title":"Factory Types","url":"/docs/guides/server-adapters/api-reference#factory-types","content":"| Type | Description |\n| ----------------------------- | ------------------------------------------- |\n| ServerFramework | \"hono\" \\| \"express\" \\| \"fastify\" \\| \"koa\" |\n| ServerAdapterFactoryOptions | { framework, neurolink, config? } |\n| ServerStatus | Server status snapshot |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Factory Types","lvl3":""}},
7721
7721
  {"objectID":"4f2b202faec0c6c8bdbf6913438e0809776d019ac03be6082db1cd3a6cc9cc20","title":"Streaming Types","url":"/docs/guides/server-adapters/api-reference#streaming-types","content":"| Type | Description |\n| ---------------------------------------------------- | --------------------------------- |\n| DataStreamWriter | Writer interface for data streams |\n| DataStreamEventType | Event type union |\n| DataStreamEvent | Base event |\n| TextStartEvent / TextDeltaEvent / TextEndEvent | Text streaming events |\n| ToolCallEvent / ToolResultEvent | Tool events |\n| DataEvent / ErrorEvent / FinishEvent | Utility events |\n| DataStreamWriterConfig | Writer factory config |\n| DataStreamResponseConfig | Response factory config |\n| SSEEventOptions | SSE formatting options |\n| SSEWriteOptions | SSE write options |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Streaming Types","lvl3":""}},
7722
- {"objectID":"f3b123615ba16d79e4f558be441599b7fa3adb19657e4f75e3035e79ba7c936a","title":"WebSocket Types","url":"/docs/guides/server-adapters/api-reference#websocket-types","content":"| Type | Description |\n| ---------------------- | --------------------------------------------------------------------- |\n| WebSocketConfig | WebSocket server settings |\n| WebSocketConnection | Connection object |\n| WebSocketHandler | Event handler interface (onOpen, onMessage, onClose, onError) |\n| WebSocketMessage | Message object |\n| WebSocketMessageType | \"text\" \\| \"binary\" \\| \"ping\" \\| \"pong\" \\| \"close\" |\n| WebSocketAuthConfig | Auth config for WebSocket (same shape as AuthConfig from types) |\n| AuthenticatedUser | User object with id, email, name, roles, permissions, metadata |\n| AuthStrategy | \"bearer\" \\| \"apiKey\" \\| \"basic\" \\| \"custom\" \\| \"none\" |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"WebSocket Types","lvl3":""}},
7722
+ {"objectID":"f3b123615ba16d79e4f558be441599b7fa3adb19657e4f75e3035e79ba7c936a","title":"WebSocket Types","url":"/docs/guides/server-adapters/api-reference#websocket-types","content":"| Type | Description |\n| ---------------------- | --------------------------------------------------------------------- |\n| WebSocketConfig | WebSocket server settings |\n| WebSocketConnection | Connection object |\n| WebSocketHandler | Event handler interface (onOpen, onMessage, onClose, onError) |\n| WebSocketMessage | Message object |\n| WebSocketMessageType | \"text\" \\| \"binary\" \\| \"ping\" \\| \"pong\" \\| \"close\" |\n| WebSocketAuthConfig | Auth config for WebSocket (same shape as AuthConfig from types) |\n| AuthenticatedUser | User object: id, shared, email, name, roles, permissions, metadata |\n| AuthStrategy | \"bearer\" \\| \"apiKey\" \\| \"basic\" \\| \"custom\" \\| \"none\" |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"WebSocket Types","lvl3":""}},
7723
7723
  {"objectID":"75ac5dd684dae3c078a954801e7d8c39e4a7ab6eefb4c4e13140af491da67cd3","title":"Error Types","url":"/docs/guides/server-adapters/api-reference#error-types","content":"| Type | Description |\n| ---------------------------- | ------------------------------------- |\n| ErrorCategoryType | Error category union |\n| ErrorSeverityType | Error severity union |\n| ServerAdapterErrorCodeType | Error code union |\n| ServerAdapterErrorContext | Context object for error construction |","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"Error Types","lvl3":""}},
7724
7724
  {"objectID":"9930ededc5ccfc16a496b95cde993bfd1fdff5dae26b819e6e6a7b11de933418","title":"ErrorCategory","url":"/docs/guides/server-adapters/api-reference#errorcategory","content":"ErrorCategory","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ErrorCategory","lvl3":""}},
7725
7725
  {"objectID":"81be0bf7c25a87d9ade845c9461d764b1851de541c9182f00c87b86d6d98e4d2","title":"ErrorSeverity","url":"/docs/guides/server-adapters/api-reference#errorseverity","content":"ErrorSeverity","hierarchy":{"lvl0":"Guides","lvl1":"Server Adapters API Reference","lvl2":"ErrorSeverity","lvl3":""}},
@@ -7993,7 +7993,7 @@
7993
7993
  {"objectID":"20b4b9bfe4f6987d7c88692d17430396985fe8533056d76bd16efcc0af7c8e74","title":"Custom Rate Limit Store (Redis)","url":"/docs/guides/server-adapters/middleware#custom-rate-limit-store-redis","content":"Custom Rate Limit Store (Redis)","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Custom Rate Limit Store (Redis)","lvl3":""}},
7994
7994
  {"objectID":"7826f375db586c8004183275c0715b410e96f673701874419ba565b6ff3dd214","title":"When to Use","url":"/docs/guides/server-adapters/middleware#when-to-use-9","content":"API abuse prevention\nFair usage enforcement\nCost control for expensive operations\nProtection against DDoS attacks","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"When to Use","lvl3":""}},
7995
7995
  {"objectID":"ce6af8a97b716420a9742ad3d965d5cb0aa5912e3d52d961814c83e9e1abaa19","title":"Authentication Middleware","url":"/docs/guides/server-adapters/middleware#authentication-middleware","content":"Provides flexible authentication support with multiple strategies.","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Authentication Middleware","lvl3":""}},
7996
- {"objectID":"39ede52482e2c4efd166bd94c8fa1ea4a6957b2528e2bca5c058208e4f293b81","title":"Configuration","url":"/docs/guides/server-adapters/middleware#configuration-8","content":"Configuration","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Configuration","lvl3":""}},
7996
+ {"objectID":"39ede52482e2c4efd166bd94c8fa1ea4a6957b2528e2bca5c058208e4f293b81","title":"Configuration","url":"/docs/guides/server-adapters/middleware#configuration-8","content":"The authenticated user is set on ctx.user. On the built-in adapters (Hono,\nExpress, Fastify and Koa) it reaches later middleware and the route handler on\nevery request only when the server is created with carryMiddlewareState: true.\nBy default Express, Fastify and Koa, and Hono when the client sent no\nX-Request-ID of its own, hand each middleware step and the handler a fresh\ncontext, so a role guard registered after authentication refuses everyone there;\nonly Hono with a client X-Request-ID shares the context. The option does not\napply to a context you build yourself: a custom adapter, or a route handler you\ncall directly, can supply a context that already has ctx.user set. See\nCarrying middleware state\nin the security guide. Whether the agent routes treat ctx.user as the caller is\na separate choice: see perUserAuth in the\nsecurity guide.","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Configuration","lvl3":""}},
7997
7997
  {"objectID":"51fb1cc8c6e28634044df5ad09ea7250e2d1520cade26f2996bf81c174b30aa9","title":"Usage","url":"/docs/guides/server-adapters/middleware#usage-10","content":"Usage","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Usage","lvl3":""}},
7998
7998
  {"objectID":"dc019f0ad08d89054d4f68945d6855bbc6d74da0b3f8082e35f56fa5f731ec51","title":"Headers Read","url":"/docs/guides/server-adapters/middleware#headers-read","content":"| Header | Auth Type | Description |\n| --------------- | ------------- | ------------------------------------ |\n| Authorization | bearer, basic | Bearer <token> or Basic <base64> |\n| X-API-Key | api-key | Raw API key value |","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Headers Read","lvl3":""}},
7999
7999
  {"objectID":"43776c9da774387f221eb7918931d5a4a59b42c949ef248c30c7afb5512ee7ea","title":"Dev Playground Support","url":"/docs/guides/server-adapters/middleware#dev-playground-support","content":"Requests with an X-NeuroLink-Dev-Playground: true (or X-NeuroLink-Playground: true) header bypass authentication and receive a default developer user context (id: \"playground\", roles: [\"developer\"]), but only when NODE_ENV is exactly development. The variable is read on every request.\n\nWith NODE_ENV unset, production, test, staging or any other value, the header is ignored and the request must carry a valid credential. The bypass is therefore off by default in a deployment that never sets NODE_ENV. Pass skipDevPlayground: false to refuse the header even in development.","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Dev Playground Support","lvl3":""}},
@@ -8011,13 +8011,15 @@
8011
8011
  {"objectID":"75f9986be54ffb5b39930d9b1514e6a696e982fe41bbc2a600033e3254bad57b","title":"When to Use","url":"/docs/guides/server-adapters/middleware#when-to-use-12","content":"Expensive operations (database queries, AI generation)\nFrequently requested static data\nRate limit budget optimization\nReducing latency for repeated requests","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"When to Use","lvl3":""}},
8012
8012
  {"objectID":"3e522465420d38d5c0e20166dfc374452a7c8366d592ff2cf3a9cb9afadc3b7d","title":"Composing Middleware","url":"/docs/guides/server-adapters/middleware#composing-middleware","content":"Middleware are executed in order based on their order property. Here's a recommended production setup:","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Composing Middleware","lvl3":""}},
8013
8013
  {"objectID":"293ec2d6d2933e2f370ee73b87ee9684f64143acd21d8bbb5e7e48640ec0d2bb","title":"Next Steps","url":"/docs/guides/server-adapters/middleware#next-steps","content":"Configuration Reference - Full server configuration options\nSecurity Best Practices - Authentication and authorization patterns\nDeployment Guide - Production deployment strategies\nExpress Adapter - Express-specific middleware integration\nFastify Adapter - Fastify-specific hooks and plugins","hierarchy":{"lvl0":"Guides","lvl1":"Middleware Reference","lvl2":"Next Steps","lvl3":""}},
8014
- {"objectID":"3f8ed2c1cc0b9c59fe231fb08fe10302270284784b912664350299fe0a5de458","title":"Security Best Practices","url":"/docs/guides/server-adapters/security","content":"Security Best Practices\n\nProtect your AI APIs with comprehensive security measures\n\nThis guide covers authentication, authorization, rate limiting, and other security best practices for deploying NeuroLink server adapters in production.\n\nAuthentication\n\nNeuroLink server adapters support multiple authentication strategies out of the box.\n\nBearer Token Authentication\n\nBearer tokens (JWT, OAuth tokens) are the most common authentication method for APIs:\n\nAPI Key Authentication\n\nFor service-to-service communication or simple API access:\n\nBasic Authentication\n\nFor simple username/password authentication:\n\nCustom Authentication\n\nFor OAuth 2.0, OIDC, or custom schemes:\n\nSkip Paths Configuration\n\nCertain endpoints should bypass authentication:\n\nRate Limiting\n\nProtect your API from abuse with configurable rate limiting.\n\nBasic Configuration\n\nPer-IP Rate Limiting\n\nThe default behavior limits requests by client IP:\n\nPer-User Rate Limiting\n\nLimit based on authenticated user:\n\nPer-API-Key Rate Limiting\n\nDifferent limits for different API keys:\n\nSliding Window Rate Limiting\n\nFor smoother rate limiting that prevents burst-and-wait patterns:\n\nRate Limit Headers\n\nRate limit middleware automatically adds headers to responses:\n\nRate Limit Response Headers\n\nWhen a request exceeds the rate limit, the server returns HTTP 429 (Too Many Requests) with these headers:\n\n| Header | Description | Example |\n| ----------------------- | -------------------------------- | ------------ |\n| X-RateLimit-Limit | Maximum requests per window | 100 |\n| X-RateLimit-Remaining | Requests remaining in window | 0 |\n| X-RateLimit-Reset | Unix timestamp when limit resets | 1706745660 |\n| Retry-After | Seconds to wait before retrying | 60 |\n\nClients should respect the Retry-After header to avoid unnecessary requests.\n\nStream Redaction\n\nProtect sensitive data in streaming responses. Redaction is disabled by default and must be explicitly enabled.\n\nWhy Disabled by Default?\n\nStream redaction is disabled by default because:\nIt adds processing overhead to every stream chunk\nDevelopers should consciously decide what to redact\nOverly aggressive redaction can break functionality\n\nEnabling Stream Redaction\n\nCustom Redaction Configuration\n\nProgrammatic Redaction\n\nFor custom streaming routes:\n\nCORS Configuration\n\nProperly configure Cross-Origin Resource Sharing:\n\nDynamic CORS Origins\n\nFor multi-tenant applications:\n\nSecurity Headers\n\nAdd essential security headers to all responses. NeuroLink provides a built-in createSecurityHeadersMiddleware that works with all server adapters (Hono, Express, Fastify, Koa).\n\nUsing NeuroLink Security Headers Middleware (All Adapters)\n\nThe recommended approach is to use NeuroLink's built-in security headers middleware, which works consistently across all frameworks:\n\nConfiguration Options\n\n| Option | Type | Default | Description |\n| ----------------------- | --------------------------------- | ----------------------------------- | ------------------------------ |\n| contentSecurityPolicy | string | undefined | Content-Security-Policy header |\n| frameOptions | \"DENY\" \\| \"SAMEORIGIN\" \\| false | \"DENY\" | X-Frame-Options header |\n| contentTypeOptions | \"nosniff\" \\| false | \"nosniff\" | X-Content-Type-Options header |\n| hstsMaxAge | number \\| false | 31536000 (1 year) | HSTS max-age in seconds |\n| referrerPolicy | string \\| false | \"strict-origin-when-cross-origin\" | Referrer-Policy header |\n| customHeaders | Record<string, string> | {} | Additional custom headers |\n\nHeaders Set by the Middleware\n\nThe middleware automatically sets these security headers:\n\n| Header | Default Value | Purpose |\n| --------------------------- | ------------------------------------- | ----------------------------- |\n| X-Frame-Options | DENY | Prevents clickjacking attacks |\n| X-Content-Type-Options | nosniff | Prevents MIME type sniffing |\n| Strict-Transport-Security | max-age=31536000; includeSubDomains | Enforces HTTPS connections |\n| Referrer-Policy | strict-origin-when-cross-origin | Controls referrer information |\n| X-XSS-Protection | 1; mode=block | XSS filter for older browsers |\n| Content-Security-Policy | (only if configured) | Controls resource loading |\n\nExpress Example\n\nFastify Example\n\nKoa Example\n\nHono Example\n\nDisabling Specific Headers\n\nSet any option to false to disable that header:\n\nFramew","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"","lvl3":""}},
8014
+ {"objectID":"3f8ed2c1cc0b9c59fe231fb08fe10302270284784b912664350299fe0a5de458","title":"Security Best Practices","url":"/docs/guides/server-adapters/security","content":"Security Best Practices\n\nProtect your AI APIs with comprehensive security measures\n\nThis guide covers authentication, authorization, rate limiting, and other security best practices for deploying NeuroLink server adapters in production.\n\nAuthentication\n\nNeuroLink server adapters support multiple authentication strategies out of the box.\n\nBearer Token Authentication\n\nBearer tokens (JWT, OAuth tokens) are the most common authentication method for APIs:\n\nAPI Key Authentication\n\nFor service-to-service communication or simple API access:\n\nBasic Authentication\n\nFor simple username/password authentication:\n\nCustom Authentication\n\nFor OAuth 2.0, OIDC, or custom schemes:\n\nCarrying middleware state to guards and handlers (carryMiddlewareState)\n\nAuthentication middleware sets ctx.user. On the built-in adapters, whether the\nmiddleware that runs after it, and the route handler, see it depends on the\nadapter and on carryMiddlewareState, which is off by default: each adapter\nthen propagates context as it always did. Express, Fastify and Koa build a fresh\ncontext for every middleware step and for the handler and carry only the\nresponse headers; Hono shares one context between the steps and the handler only\nwhen the client sent its own X-Request-ID.\n\nThe option does not apply to a context you build yourself: a custom adapter, or a\nroute handler you call directly, can supply a context that already has ctx.user\nset.\n\nSo by default a role guard (createRoleMiddleware) registered after\ncreateAuthMiddleware sees the user on one request shape only. Measured: it\nanswers 401 to every request on Express, Fastify and Koa, and on Hono without a\nclient X-Request-ID, even for a user holding the required role, and a\nrate-limit keyGenerator reads ctx.user as undefined there. Set the option on\nthe server to carry ctx.user, ctx.session, ctx.metadata and the abort\nsignal to later middleware and the handler on every built-in adapter:\n\nWith it on, the role guard admits a user holding the role (200) and refuses one\nwithout it (403), and a keyGenerator sees ctx.user, on every built-in adapter. A key\ngenerator that keys on the user id then does what it says, so make it ignore a\nshared identity (ctx.user.shared), or every holder of one API key falls into a\nsingle bucket; the rate-limit examples below do. Turning the option on does not\nchange whose identity the agent routes trust, and registerAllRoutes turns it\non by itself when given perUserAuth, as the next section says.\n\nWho the agent routes treat as the user (perUserAuth)\n\nWhether the agent routes (/agent/execute, /agent/stream, and the skill\nmutation routes' requestedBy) trust ctx.user as a person is a separate\nchoice from whether the server carries it: a single shared API key sets the same\nctx.user for every caller, and taking it as the user would give every client\none userId and no conversation memory.\n\nSo without an opt-in the agent routes resolve identity as they always have:\nOn Express, Fastify and Koa, and on Hono when the client sent no\n X-Request-ID, userId and sessionId come from the request body.\n ctx.user and ctx.session are ignored (they are not in the handler's\n context at all unless the server carries middleware state), and the skill\n routes use the body's requestedBy.\nOn Hono, when the client sent its own X-Request-ID header, an authenticated\n ctx.user wins over the body (and ctx.session over the body's\n sessionId), as it did before. Hono kept the middleware's context under that\n header, so the handler found it. That is the only built-in combination where\n the default ever guarded userId.\nA context the built-in adapters did not hand the carry to keeps the same\n rule, an authenticated ctx.user wins: an adapter you wrote that sets\n ctx.user itself, or a route handler you call directly with a context you\n built (a test harness, for one).\n\nSet perUserAuth: true when your middleware identifies individual people (one\ncredential per person). Only this option, with carryMiddlewareState on, makes the agent routes take\nthe user from ctx.user, and ignore the body's userId, on every built-in\nadapter and for every request:\n\nregisterAllRoutes also turns on carryMiddlewareState for the server, because\nthe routes can only take identity from ctx.user if the adapter hands it to the\nhandler. With carryMiddlewareState on, a perUserAuth request that your middleware\nauthenticated reaches the handler with that user on every built-in adapter. A\nrequest that no middleware authenticated (optional authentication) runs as\nanonymous, with no userId and no session.\n\nIf you register the agent routes yourself with\ncreateAgentRoutes(\"/api\", { perUserAuth: true }), create the server with\ncarryMiddlewareState: true. Without it, whether a perUserAuth request has a\nuser depends on the adapter and the request:\nHono, when the client sent its own X-Request-ID header: an authenticated\n request has its user and session. Hono hands the handler the middleware's context for such\n a request whether or not carryM","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"","lvl3":""}},
8015
8015
  {"objectID":"7cdb3cd74c088f4b197de4db297c2eb3b47c353b41ce1a84ed2e12548147b408","title":"Security Best Practices","url":"/docs/guides/server-adapters/security#security-best-practices","content":"Protect your AI APIs with comprehensive security measures\n\nThis guide covers authentication, authorization, rate limiting, and other security best practices for deploying NeuroLink server adapters in production.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Security Best Practices","lvl3":""}},
8016
8016
  {"objectID":"7165b0d19a27c31d8ca81ea15e5a79ad56fd20234c80f3c955a1c579a669e84f","title":"Authentication","url":"/docs/guides/server-adapters/security#authentication","content":"NeuroLink server adapters support multiple authentication strategies out of the box.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Authentication","lvl3":""}},
8017
8017
  {"objectID":"9b83e309c15f0ef505257e6ef1750da7d26183f6b598bcd24996ad199df910cc","title":"Bearer Token Authentication","url":"/docs/guides/server-adapters/security#bearer-token-authentication","content":"Bearer tokens (JWT, OAuth tokens) are the most common authentication method for APIs:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Bearer Token Authentication","lvl3":""}},
8018
8018
  {"objectID":"9447de8730cba3e8d7100e35f3edc53f5d838fed4aab12473ba0d154a63ee127","title":"API Key Authentication","url":"/docs/guides/server-adapters/security#api-key-authentication","content":"For service-to-service communication or simple API access:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"API Key Authentication","lvl3":""}},
8019
8019
  {"objectID":"55486c9aed152083800f7142accdefaf2750be560161e53b51e4e7f076e78783","title":"Basic Authentication","url":"/docs/guides/server-adapters/security#basic-authentication","content":"For simple username/password authentication:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Basic Authentication","lvl3":""}},
8020
8020
  {"objectID":"3975b5affef7749530f0c88db91dccfe9ae500ea616d9ae756de09c501e74e09","title":"Custom Authentication","url":"/docs/guides/server-adapters/security#custom-authentication","content":"For OAuth 2.0, OIDC, or custom schemes:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Custom Authentication","lvl3":""}},
8021
+ {"objectID":"6c5ba88d8c7484db5bcd476fabfca5763fad609f689edee826a37f9360219610","title":"Carrying middleware state to guards and handlers (carryMiddlewareState)","url":"/docs/guides/server-adapters/security#carrying-middleware-state-to-guards-and-handlers-carrymiddlewarestate","content":"Authentication middleware sets ctx.user. On the built-in adapters, whether the\nmiddleware that runs after it, and the route handler, see it depends on the\nadapter and on carryMiddlewareState, which is off by default: each adapter\nthen propagates context as it always did. Express, Fastify and Koa build a fresh\ncontext for every middleware step and for the handler and carry only the\nresponse headers; Hono shares one context between the steps and the handler only\nwhen the client sent its own X-Request-ID.\n\nThe option does not apply to a context you build yourself: a custom adapter, or a\nroute handler you call directly, can supply a context that already has ctx.user\nset.\n\nSo by default a role guard (createRoleMiddleware) registered after\ncreateAuthMiddleware sees the user on one request shape only. Measured: it\nanswers 401 to every request on Express, Fastify and Koa, and on Hono without a\nclient X-Request-ID, even for a user holding the required role, and a\nrate-limit keyGenerator reads ctx.user as undefined there. Set the option on\nthe server to carry ctx.user, ctx.session, ctx.metadata and the abort\nsignal to later middleware and the handler on every built-in adapter:\n\nWith it on, the role guard admits a user holding the role (200) and refuses one\nwithout it (403), and a keyGenerator sees ctx.user, on every built-in adapter. A key\ngenerator that keys on the user id then does what it says, so make it ignore a\nshared identity (ctx.user.shared), or every holder of one API key falls into a\nsingle bucket; the rate-limit examples below do. Turning the option on does not\nchange whose identity the agent routes trust, and registerAllRoutes turns it\non by itself when given perUserAuth, as the next section says.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Carrying middleware state to guards and handlers (carryMiddlewareState)","lvl3":""}},
8022
+ {"objectID":"f4407e53fe643ff19343687ebdafae3eaf56adc6a7cafc61834a490cc90bffd1","title":"Who the agent routes treat as the user (perUserAuth)","url":"/docs/guides/server-adapters/security#who-the-agent-routes-treat-as-the-user-peruserauth","content":"Whether the agent routes (/agent/execute, /agent/stream, and the skill\nmutation routes' requestedBy) trust ctx.user as a person is a separate\nchoice from whether the server carries it: a single shared API key sets the same\nctx.user for every caller, and taking it as the user would give every client\none userId and no conversation memory.\n\nSo without an opt-in the agent routes resolve identity as they always have:\nOn Express, Fastify and Koa, and on Hono when the client sent no\n X-Request-ID, userId and sessionId come from the request body.\n ctx.user and ctx.session are ignored (they are not in the handler's\n context at all unless the server carries middleware state), and the skill\n routes use the body's requestedBy.\nOn Hono, when the client sent its own X-Request-ID header, an authenticated\n ctx.user wins over the body (and ctx.session over the body's\n sessionId), as it did before. Hono kept the middleware's context under that\n header, so the handler found it. That is the only built-in combination where\n the default ever guarded userId.\nA context the built-in adapters did not hand the carry to keeps the same\n rule, an authenticated ctx.user wins: an adapter you wrote that sets\n ctx.user itself, or a route handler you call directly with a context you\n built (a test harness, for one).\n\nSet perUserAuth: true when your middleware identifies individual people (one\ncredential per person). Only this option, with carryMiddlewareState on, makes the agent routes take\nthe user from ctx.user, and ignore the body's userId, on every built-in\nadapter and for every request:\n\nregisterAllRoutes also turns on carryMiddlewareState for the server, because\nthe routes can only take identity from ctx.user if the adapter hands it to the\nhandler. With carryMiddlewareState on, a perUserAuth request that your middleware\nauthenticated reaches the handler with that user on every built-in adapter.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Who the agent routes treat as the user (perUserAuth)","lvl3":""}},
8021
8023
  {"objectID":"0eb6912fafa8a4ab0aa683215da36521df010f267a7e6fa07e5b36117285fbd7","title":"Skip Paths Configuration","url":"/docs/guides/server-adapters/security#skip-paths-configuration","content":"Certain endpoints should bypass authentication:","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Skip Paths Configuration","lvl3":""}},
8022
8024
  {"objectID":"9e51a77be4d03e43ee3f36b8d0011c07bc65e43fe63401529fc309117cc8f14d","title":"Rate Limiting","url":"/docs/guides/server-adapters/security#rate-limiting","content":"Protect your API from abuse with configurable rate limiting.","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Rate Limiting","lvl3":""}},
8023
8025
  {"objectID":"c6e767ba1ce5b5628ab9d303d199a6fb4947a70e2e43358a5d7f89a96534c74e","title":"Basic Configuration","url":"/docs/guides/server-adapters/security#basic-configuration","content":"Basic Configuration","hierarchy":{"lvl0":"Guides","lvl1":"Security Best Practices","lvl2":"Basic Configuration","lvl3":""}},
@@ -8464,15 +8466,16 @@
8464
8466
  {"objectID":"156003cd4819e4dbb7f346be7120ea605e8ad136ca867e2f736327744c48c281","title":"2. Best Practices","url":"/docs/mcp/testing#2-best-practices","content":"Use TypeScript for full type safety\nValidate inputs with Zod schemas\nHandle errors gracefully in tools\nLog execution for debugging\nTest thoroughly before deployment","hierarchy":{"lvl0":"Mcp","lvl1":"๐Ÿงช MCP Foundation Testing Guide","lvl2":"2. Best Practices","lvl3":""}},
8465
8467
  {"objectID":"e772b5dca6bea98f96f9043b173ee610272e201d08879869318c2d8070425ffc","title":"3. Performance Monitoring","url":"/docs/mcp/testing#3-performance-monitoring","content":"3. Performance Monitoring","hierarchy":{"lvl0":"Mcp","lvl1":"๐Ÿงช MCP Foundation Testing Guide","lvl2":"3. Performance Monitoring","lvl3":""}},
8466
8468
  {"objectID":"82c7cc03c75290cac4197443132e907f9796ad297a7a81df29ac6e5ae9c42734","title":"๐Ÿš€ Next Steps","url":"/docs/mcp/testing#-next-steps","content":"โœ… Test Current Implementation - Use programmatic testing examples\n๐Ÿ”ง Add CLI Integration - Implement MCP CLI commands\n๐Ÿ—๏ธ Create Custom Servers - Build domain-specific tool servers\n๐Ÿ“Š Monitor Performance - Track tool execution and usage\n๐Ÿ”„ Iterate and Improve - Enhance based on real usage\n\nMCP Foundation is production-ready and waiting for your custom tools! ๐ŸŽ‰","hierarchy":{"lvl0":"Mcp","lvl1":"๐Ÿงช MCP Foundation Testing Guide","lvl2":"๐Ÿš€ Next Steps","lvl3":""}},
8467
- {"objectID":"d287e2ebab877225d0b71aafb45118dd2b1d04914f8cf4cd8b2c82b12aba80b8","title":"Conversation Memory","url":"/docs/memory/conversation","content":"Conversation Memory\n\nNeuroLink's Conversation Memory feature enables AI models to maintain context across multiple turns within a session, creating more natural and coherent conversations.\n\n๐Ÿง  Overview\n\nThe conversation memory system provides:\nSession-based memory: Each conversation session maintains its own context\nTurn-by-turn persistence: AI remembers previous messages within a session\nAutomatic cleanup: Configurable limits to prevent memory bloat\nSession isolation: Different sessions don't interfere with each other\nIn-memory storage: Fast, lightweight storage for conversation history\nUniversal Method Support: Works seamlessly with both generate() and stream() methods\nStream Integration: Full conversation memory support for streaming responses\n\nโš™๏ธ Configuration\n\nEnvironment Variables\n\nProgrammatic Configuration\n\n๐Ÿš€ Usage Examples\n\nBasic Usage with Session ID\n\nStreaming Support\n\nThe conversation memory system now fully supports streaming responses with the same memory persistence:\n\nMixed Generate/Stream Conversations\n\nYou can seamlessly mix generate() and stream() calls within the same conversation:\n\nSession Isolation Example\n\n๐Ÿ“Š Memory Management\n\nTurn Limits\n\nWhen the number of conversation turns exceeds maxTurnsPerSession, older messages are automatically removed:\n\nSession Limits\n\nWhen the number of active sessions exceeds maxSessions, the least recently used sessions are removed:\n\n๐Ÿ”Œ API Reference\n\nMemory Statistics\n\nSession Management\n\n๐Ÿงช Test Results\n\nThe conversation memory system has been thoroughly tested and validated:\n\nโœ… Test Suite Results\n\n| Test Case | Status | Description |\n| --------------------- | ------- | ----------------------------------------------- |\n| Basic Memory | โœ… PASS | AI correctly remembers information across turns |\n| Session Isolation | โœ… PASS | Sessions remain completely separate |\n| Turn Limits | โœ… PASS | Automatic cleanup when limits exceeded |\n| Session Limits | โœ… PASS | LRU eviction of old sessions |\n| API Functions | โœ… PASS | Clear operations work correctly |\n\nExample Test Output\n\n๐Ÿ’ก Best Practices\nSession ID Strategy\nMemory Limits\nError Handling\n\n๐Ÿ”ง Technical Implementation\n\nArchitecture\n\nMessage Format\n\n๐Ÿ” Troubleshooting\n\nCommon Issues\n\nMemory not persisting between calls\nEnsure sessionId is consistent across calls\nVerify conversationMemory.enabled is true\nCheck that sessionId is a valid string\n\nPerformance issues with large conversations\nReduce maxTurnsPerSession limit\nImplement session cleanup strategies\nMonitor memory usage statistics\n\nSession isolation not working\nVerify different sessionId values are being used\nCheck for session ID conflicts or duplicates\n\nDebug Logging\n\n๐Ÿ”— Related Documentation\nRedis Conversation Export - Export session history as JSON for analytics\nAPI Reference - Complete SDK documentation\nConfiguration - Environment setup guide\nExamples - More usage examples\nTesting Guide - How to test conversation memory\n\n๐Ÿ“ˆ Performance Characteristics\nMemory Usage: ~1KB per conversation turn\nLookup Time: O(1) for session retrieval\nCleanup Time: O(n) for session limit enforcement\nConcurrency: Thread-safe in-memory operations\n\nThe conversation memory system is designed for production use with efficient memory management and robust error handling.","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"","lvl3":""}},
8469
+ {"objectID":"d287e2ebab877225d0b71aafb45118dd2b1d04914f8cf4cd8b2c82b12aba80b8","title":"Conversation Memory","url":"/docs/memory/conversation","content":"Conversation Memory\n\nNeuroLink's Conversation Memory feature enables AI models to maintain context across multiple turns within a session, creating more natural and coherent conversations.\n\n๐Ÿง  Overview\n\nThe conversation memory system provides:\nSession-based memory: Each conversation session maintains its own context\nTurn-by-turn persistence: AI remembers previous messages within a session\nAutomatic cleanup: Configurable limits to prevent memory bloat\nSession isolation: Different sessions don't interfere with each other\nIn-memory storage: Fast, lightweight storage for conversation history\nUniversal Method Support: Works seamlessly with both generate() and stream() methods\nStream Integration: Full conversation memory support for streaming responses\nTitle Generation Events: Redis-backed conversations get an AI-generated title, announced with a conversation:titleGenerated event\n\nโš™๏ธ Configuration\n\nEnvironment Variables\n\nProgrammatic Configuration\n\n๐Ÿš€ Usage Examples\n\nBasic Usage with Session ID\n\nStreaming Support\n\nThe conversation memory system now fully supports streaming responses with the same memory persistence:\n\nMixed Generate/Stream Conversations\n\nYou can seamlessly mix generate() and stream() calls within the same conversation:\n\nSession Isolation Example\n\n๐Ÿท๏ธ Title Generation Events {#title-generation-events}\n\nWhen a Redis-backed conversation stores its first turn, NeuroLink generates a title for it in the background and saves it on the session (listSessions() reports it). Once the title is stored, the SDK's event emitter fires conversation:titleGenerated.\n\nPayload (ConversationTitleGeneratedEvent):\n\n| Property | Type | Description |\n| ----------- | -------- | ---------------------------------------------------- |\n| sessionId | string | Session the title belongs to |\n| userId | string | User that owns the session (randomUser when unset) |\n| title | string | The title that was stored |\n| timestamp | number | Unix epoch milliseconds when the title was stored |\n\nNotes:\nThe event fires once per conversation, on the first turn, not on later turns.\nOnly Redis-backed memory generates titles; in-memory storage lists sessions by session ID.\nIf the summarization provider cannot answer, the stored title falls back to the first 30 characters of the message plus ..., and the event carries that fallback.\nSet NEUROLINK_TITLE_PROMPT to customize the title prompt. ${userMessage} is replaced with the user's message.\n\n๐Ÿ“Š Memory Management\n\nTurn Limits\n\nWhen the number of conversation turns exceeds maxTurnsPerSession, older messages are automatically removed:\n\nSession Limits\n\nWhen the number of active sessions exceeds maxSessions, the least recently used sessions are removed:\n\n๐Ÿ”Œ API Reference\n\nMemory Statistics\n\nSession Management\n\n๐Ÿงช Test Results\n\nThe conversation memory system has been thoroughly tested and validated:\n\nโœ… Test Suite Results\n\n| Test Case | Status | Description |\n| --------------------- | ------- | ----------------------------------------------- |\n| Basic Memory | โœ… PASS | AI correctly remembers information across turns |\n| Session Isolation | โœ… PASS | Sessions remain completely separate |\n| Turn Limits | โœ… PASS | Automatic cleanup when limits exceeded |\n| Session Limits | โœ… PASS | LRU eviction of old sessions |\n| API Functions | โœ… PASS | Clear operations work correctly |\n\nExample Test Output\n\n๐Ÿ’ก Best Practices\nSession ID Strategy\nMemory Limits\nError Handling\n\n๐Ÿ”ง Technical Implementation\n\nArchitecture\n\nMessage Format\n\n๐Ÿ” Troubleshooting\n\nCommon Issues\n\nMemory not persisting between calls\nEnsure sessionId is consistent across calls\nVerify conversationMemory.enabled is true\nCheck that sessionId is a valid string\n\nPerformance issues with large conversations\nReduce maxTurnsPerSession limit\nImplement session cleanup strategies\nMonitor memory usage statistics\n\nSession isolation not working\nVerify different sessionId values are being used\nCheck for session ID conflicts or duplicates\n\nDebug Logging\n\n๐Ÿ”— Related Documentation\nRedis Conversation Export - Export session history as JSON for analytics\nAPI Reference - Complete SDK documentation\nConfiguration - Environment setup guide\nExamples - More usage examples\nTesting Guide - How to test conversation memory\n\n๐Ÿ“ˆ Performance Characteristics\nMemory Usage: ~1KB per conversation turn\nLookup Time: O(1) for session retrieval\nCleanup Time: O(n) for session limit enforcement\nConcurrency: Thread-safe in-memory operations\n\nThe conversation memory system is designed for production use with efficient memory management and robust error handling.","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"","lvl3":""}},
8468
8470
  {"objectID":"c5ecb284a686db95e36732c07ddc3b49949d9113b826193e1f6feabf1ae48784","title":"Conversation Memory","url":"/docs/memory/conversation#conversation-memory","content":"NeuroLink's Conversation Memory feature enables AI models to maintain context across multiple turns within a session, creating more natural and coherent conversations.","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Conversation Memory","lvl3":""}},
8469
- {"objectID":"5eb7e9215a286dcd5f45287f758f7c7aa08263f946d3b58182bd9ae2ea029d98","title":"๐Ÿง  Overview","url":"/docs/memory/conversation#-overview","content":"The conversation memory system provides:\nSession-based memory: Each conversation session maintains its own context\nTurn-by-turn persistence: AI remembers previous messages within a session\nAutomatic cleanup: Configurable limits to prevent memory bloat\nSession isolation: Different sessions don't interfere with each other\nIn-memory storage: Fast, lightweight storage for conversation history\nUniversal Method Support: Works seamlessly with both generate() and stream() methods\nStream Integration: Full conversation memory support for streaming responses","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"๐Ÿง  Overview","lvl3":""}},
8471
+ {"objectID":"5eb7e9215a286dcd5f45287f758f7c7aa08263f946d3b58182bd9ae2ea029d98","title":"๐Ÿง  Overview","url":"/docs/memory/conversation#-overview","content":"The conversation memory system provides:\nSession-based memory: Each conversation session maintains its own context\nTurn-by-turn persistence: AI remembers previous messages within a session\nAutomatic cleanup: Configurable limits to prevent memory bloat\nSession isolation: Different sessions don't interfere with each other\nIn-memory storage: Fast, lightweight storage for conversation history\nUniversal Method Support: Works seamlessly with both generate() and stream() methods\nStream Integration: Full conversation memory support for streaming responses\nTitle Generation Events: Redis-backed conversations get an AI-generated title, announced with a conversation:titleGenerated event","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"๐Ÿง  Overview","lvl3":""}},
8470
8472
  {"objectID":"d2eb5a1a0caa1a4c9a75e15f0cf37e5cd1f37e00d9ef168bac48c0db9cb40ffd","title":"Environment Variables","url":"/docs/memory/conversation#environment-variables","content":"Environment Variables","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Environment Variables","lvl3":""}},
8471
8473
  {"objectID":"520e090e02894dc26d3732e6e5710332a0c681ebd3f9648f421d48e01c991d65","title":"Programmatic Configuration","url":"/docs/memory/conversation#programmatic-configuration","content":"Programmatic Configuration","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Programmatic Configuration","lvl3":""}},
8472
8474
  {"objectID":"75f91f33db6fd6704adb0d78885dafb7f3d33a0e36ac5edd543ed070cacd2329","title":"Basic Usage with Session ID","url":"/docs/memory/conversation#basic-usage-with-session-id","content":"Basic Usage with Session ID","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Basic Usage with Session ID","lvl3":""}},
8473
8475
  {"objectID":"5d65f1e509ac96cb91a4a3027345c19b33198f0e3dd51442e5f3ef4d5e6bf8ba","title":"Streaming Support","url":"/docs/memory/conversation#streaming-support","content":"The conversation memory system now fully supports streaming responses with the same memory persistence:","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Streaming Support","lvl3":""}},
8474
8476
  {"objectID":"b104538f38fc8e518c4b440d352a6888ccbc0e3fe334446b317e81ef2815ef69","title":"Mixed Generate/Stream Conversations","url":"/docs/memory/conversation#mixed-generatestream-conversations","content":"You can seamlessly mix generate() and stream() calls within the same conversation:","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Mixed Generate/Stream Conversations","lvl3":""}},
8475
8477
  {"objectID":"3d44a6a1ef6c03c6f48aabb0c9516e1f05d660eac1d51829bfaf2e8506bd9c2e","title":"Session Isolation Example","url":"/docs/memory/conversation#session-isolation-example","content":"Session Isolation Example","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Session Isolation Example","lvl3":""}},
8478
+ {"objectID":"778e79ba226a658a91d70c69514a873920f93d560c695eb75e1d9b6a735567a8","title":"๐Ÿท๏ธ Title Generation Events","url":"/docs/memory/conversation#title-generation-events","content":"When a Redis-backed conversation stores its first turn, NeuroLink generates a title for it in the background and saves it on the session (listSessions() reports it). Once the title is stored, the SDK's event emitter fires conversation:titleGenerated.\n\nPayload (ConversationTitleGeneratedEvent):\n\n| Property | Type | Description |\n| ----------- | -------- | ---------------------------------------------------- |\n| sessionId | string | Session the title belongs to |\n| userId | string | User that owns the session (randomUser when unset) |\n| title | string | The title that was stored |\n| timestamp | number | Unix epoch milliseconds when the title was stored |\n\nNotes:\nThe event fires once per conversation, on the first turn, not on later turns.\nOnly Redis-backed memory generates titles; in-memory storage lists sessions by session ID.\nIf the summarization provider cannot answer, the stored title falls back to the first 30 characters of the message plus ..., and the event carries that fallback.\nSet NEUROLINK_TITLE_PROMPT to customize the title prompt. ${userMessage} is replaced with the user's message.","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"๐Ÿท๏ธ Title Generation Events","lvl3":""}},
8476
8479
  {"objectID":"63f2feb8c208abf16abfab0606af7eb1d9d51bcbc584182610a3d692a41ef777","title":"Turn Limits","url":"/docs/memory/conversation#turn-limits","content":"When the number of conversation turns exceeds maxTurnsPerSession, older messages are automatically removed:","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Turn Limits","lvl3":""}},
8477
8480
  {"objectID":"211814691635003dcae6fae6c3c3e7cb5b400ba93b6f4ad45fdec9423659ec0c","title":"Session Limits","url":"/docs/memory/conversation#session-limits","content":"When the number of active sessions exceeds maxSessions, the least recently used sessions are removed:","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Session Limits","lvl3":""}},
8478
8481
  {"objectID":"11e00a73bb57324fcdab4d4130bf0f98bb4cb3b754b4e558e2feb4474e73a1d3","title":"Memory Statistics","url":"/docs/memory/conversation#memory-statistics","content":"Memory Statistics","hierarchy":{"lvl0":"Memory","lvl1":"Conversation Memory","lvl2":"Memory Statistics","lvl3":""}},
@@ -10347,6 +10350,7 @@
10347
10350
  {"objectID":"d79631a303031924a7185daa0471458026c9d9ef6bee4a13e49d9ce0610262b9","title":"Event System","url":"/docs/sdk/api-reference#event-system","content":"NeuroLink emits events throughout the generation and streaming lifecycle through a TypedEventEmitter. NeuroLink does not extend EventEmitter itself, so there is no neurolink.on(): get the emitter with getEventEmitter(), subscribe with on() and unsubscribe with off().","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Event System","lvl3":""}},
10348
10351
  {"objectID":"357bbb718f458d764e00524826a1d42a64da83167df93a52c04d9ddec3651764","title":"Core Events","url":"/docs/sdk/api-reference#core-events","content":"| Event | Emitted When |\n| ------------------ | ------------------------------------ |\n| generation:start | A generate() call begins |\n| generation:end | A generate() call completes |\n| stream:start | A stream() call begins |\n| stream:chunk | A new chunk arrives during streaming |\n| stream:end | Streaming completes normally |\n| stream:complete | Stream fully consumed |\n| stream:error | An error occurs during streaming |\n| tool:start | A tool execution begins |\n| tool:end | A tool execution completes |\n| response:start | A provider response begins |\n| response:end | A provider response completes |","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Core Events","lvl3":""}},
10349
10352
  {"objectID":"efcf19aa651c13dbc72ef4b3d0f83986ee180008a076c0db030509880e4d4b1a","title":"MCP Server Events","url":"/docs/sdk/api-reference#mcp-server-events","content":"| Event | Emitted When |\n| -------------------------------- | ----------------------------------------- |\n| externalMCP:serverConnected | An external MCP server connects |\n| externalMCP:serverDisconnected | An external MCP server disconnects |\n| externalMCP:serverFailed | An external MCP server connection fails |\n| externalMCP:toolDiscovered | A new tool is discovered on an MCP server |\n| externalMCP:toolRemoved | A tool is removed from an MCP server |\n| externalMCP:serverAdded | A new MCP server registration is added |\n| externalMCP:serverRemoved | An MCP server registration is removed |","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"MCP Server Events","lvl3":""}},
10353
+ {"objectID":"e6691df9653e15f2a7a988af6dbe15f86784234b7aa7030fa74880e053d1e262","title":"Conversation Memory Events","url":"/docs/sdk/api-reference#conversation-memory-events","content":"| Event | Emitted When |\n| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |\n| conversation:titleGenerated | A new Redis-backed conversation's title is stored (see Conversation Memory) |","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Conversation Memory Events","lvl3":""}},
10350
10354
  {"objectID":"c4d157804d0d96f1d8571e6aabeff4305aca0c07c151894dee3804d611331de6","title":"Other Events","url":"/docs/sdk/api-reference#other-events","content":"| Event | Emitted When |\n| ---------------------- | ----------------------------------- |\n| tools-register:start | Tool registration process begins |\n| tools-register:end | Tool registration process completes |\n| connected | Connection established |\n| message | General message event |\n| error | An error occurs |\n| log | A log message is emitted |\n| log-event | A structured log event is emitted |\n\nTypedEventEmitter Interface:","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Other Events","lvl3":""}},
10351
10355
  {"objectID":"7ff1b31f163c4928ce88a79da3c279d1c1c6351ccf3cc5ad2464d2a03174f308","title":"Related Features","url":"/docs/sdk/api-reference#related-features","content":"Human-in-the-Loop (HITL) - Mark tools with requiresConfirmation: true\nGuardrails Middleware - Set middleware per call, in new NeuroLink({ middleware }) or with configureGlobalMiddleware(); add badWords or modelFilter to filter\nConversation History - Use getConversationHistory() method\nMultimodal Chat - Use images array in generate() options\nAuto Evaluation - Enable with enableEvaluation: true\nCLI Loop Sessions - Interactive mode with persistent state\nProvider Orchestration - Set enableOrchestration: true\nRegional Streaming - Use region parameter in generate()\nOffice Documents - Use the files array (or --file) for DOCX, PPTX, XLSX\nPDF Support - Use pdfFiles array for PDF documents\nCSV Support - Use csvFiles array for spreadsheet data\nCLI Commands Reference - CLI equivalents for all SDK methods\nConfiguration Guide - Environment variables and config files\nTroubleshooting - Common SDK issues and solutions\n\nBack to Main README | Next: Visual Demos","hierarchy":{"lvl0":"Sdk","lvl1":"API Reference","lvl2":"Related Features","lvl3":""}},
10352
10356
  {"objectID":"72ff7213f71cd3e590c196c5a1a39a7ab2af152776936e1a647f228cae34de6e","title":"๐Ÿ”ง SDK Custom Tools Guide","url":"/docs/sdk/custom-tools-guide","content":"๐Ÿ”ง SDK Custom Tools Guide\n\nBuild powerful AI applications by extending NeuroLink with your own custom tools.\n\n๐Ÿ“‹ Overview\n\nNeuroLink's SDK allows you to register custom tools programmatically, giving your AI assistants access to any functionality you need. All registered tools work seamlessly with the built-in tool system across all supported providers.\n\nKey Features\nโœ… Type-Safe: Full TypeScript support with Zod schema validation\nโœ… Provider Agnostic: Works with all providers that support tools\nโœ… Easy Integration: Simple API for tool registration\nโœ… Async Support: All tools run asynchronously\nโœ… Error Handling: Graceful error handling built-in\n\n๐Ÿš€ Quick Start\n\nBasic Tool Registration\n\nโš ๏ธ Common Mistakes\n\nโŒ Using schema instead of parameters\n\nโŒ Using plain JSON schema as parameters\n\nโœ… Correct Zod Schema Format\n\n๐Ÿ“– SimpleTool Interface\n\nAll custom tools implement the SimpleTool interface:\n\nInterface Components\ndescription: Clear, actionable description that helps the AI understand when to use the tool\nparameters: Optional Zod schema for validating inputs (highly recommended)\nexecute: Async function that implements the tool's logic\n\n๐Ÿ› ๏ธ Registration Methods\n\nRegister Single Tool\n\nRegister Multiple Tools\n\nGet Custom Tools\n\n๐Ÿ’ก Common Use Cases\nAPI Integration\nDatabase Operations\nData Processing\nFile Operations\nExternal Service Integration\n\n๐ŸŽฏ Best Practices\nClear Descriptions\n\nMake tool descriptions specific and actionable:\nParameter Validation\n\nAlways use Zod schemas for type safety:\nError Handling\n\nHandle errors gracefully:\n\nA returned error is classified as a failure everywhere the SDK reports one,\nexactly as a thrown error is. A result is error-shaped when it carries\nisError: true (the MCP convention), a non-null error field ({ error:\n\"User not found\" }), or a status of \"error\" / \"failed\" / \"failure\" /\n\"fail\". Such a call emits tool:end with success: false and the error\ntext, is stored in session memory as success: false, replays on later turns\nas [called <tool> โ†’ error], and is reported with isError: true in\nresult.toolExecutions. The model still receives the full object you\nreturned โ€” classification only affects telemetry and memory, never what the\nmodel sees.\nAsync Operations\n\nAll execute functions must return promises:\nTool Naming\n\nUse clear, consistent naming:\n\n๐Ÿงช Testing Your Tools\n\nUnit Testing\n\nIntegration Testing\n\n๐Ÿ” Debugging Tools\n\nEnable Debug Mode\n\nLog Tool Execution\n\n๐Ÿš€ Advanced Patterns\n\nTool Composition\n\nTool Middleware\n\nDynamic Tool Registration\n\nForcing a Tool Call\n\ntoolChoice tells the model whether it must call a tool on a step:\n\n| Value | Effect |\n| --------------------------------- | ------------------------------------------------ |\n| \"auto\" (default) | The model decides whether and which tool to call |\n| \"none\" | No tool calls on any step |\n| \"required\" | The model must call at least one tool |\n| { type: \"tool\", toolName: \"x\" } | The model must call the named tool |\n\nA forced choice (\"required\" or a named tool) is applied only to the first\ntoolChoiceSteps steps of the tool loop โ€” default 1 โ€” after which the\nmodel is free to answer. Holding a forced choice on every step would compel\na tool call on every step, and the turn could only end when maxSteps ran\nout. \"auto\" and \"none\" are applied unchanged on every step.\n\nFor anything finer, prepareStep runs before every step and may return a\ntoolChoice for that step, which takes precedence over toolChoiceSteps:\n\nprepareStep receives { stepNumber, steps, maxSteps, model }, where steps\nholds one record per completed step (its text, tool calls โ€” with input\nalready parsed into an object โ€” tool results, finish reason and usage,\nincluding prompt-cache tokens where the provider reports them). Only the\nreturned toolChoice is honoured; the legacy model and\nexperimental_activeTools / activeTools fields are accepted for source\ncompatibility but ignored, and their presence is logged once as a warning โ€”\nuse toolFilter / excludeTools to scope tools. A hook that throws is\nlogged and that step falls back to the toolChoice / toolChoiceSteps rule;\na hook still pending when the turn is aborted or times out is released with\nthe abort. Both toolChoice and prepareStep apply to stream() as well.\n\nVertex, Google AI Studio and Bedrock do not honour toolChoice at all today.\nSageMaker honours tools, toolChoice and prepareStep on generate()\nonly: its stream() sends the prompt without tools.\n\n๐Ÿ“Š Performance Considerations\nTimeout Handling\nCaching\nBatch Operations\n\n๐Ÿ”’ Security Considerations\n\nInput Sanitization\n\nPermission Checking\n\nRate Limiting\n\n๐ŸŽ‰ Complete Example\n\nHere's a complete example combining multiple concepts:\n\n๐ŸŒ MCP Server Integration\n\nBeyond simple tool registration, NeuroLink SDK supports adding complete MCP (Model Context Protocol) servers for more complex tool ecosystems.\n\nAdding I","hierarchy":{"lvl0":"Sdk","lvl1":"๐Ÿ”ง SDK Custom Tools Guide","lvl2":"","lvl3":""}},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "13.8.14",
3
+ "version": "13.8.16",
4
4
  "packageManager": "pnpm@10.28.2",
5
5
  "description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types โ€” generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI ยท Anthropic ยท Gemini ยท Bedrock ยท Azure ยท Ollama ยท TypeSafe Jev and more.",
6
6
  "author": {
@@ -214,6 +214,7 @@
214
214
  "test:server-boundaries": "pnpm exec tsx test/continuous-test-suite-server-boundaries.ts",
215
215
  "test:agent-input-guard": "pnpm exec tsx test/continuous-test-suite-agent-input-guard.ts",
216
216
  "test:body-limits": "pnpm exec tsx test/continuous-test-suite-body-limits.ts",
217
+ "test:adapter-request-context": "pnpm exec tsx test/continuous-test-suite-adapter-request-context.ts",
217
218
  "test:websocket-agent-handler": "pnpm exec tsx test/continuous-test-suite-websocket-agent-handler.ts",
218
219
  "test:tool-reliability": "pnpm exec tsx test/continuous-test-suite-tool-reliability.ts",
219
220
  "test:video-abort": "pnpm exec tsx test/continuous-test-suite-video-abort.ts",