@juspay/neurolink 13.8.17 → 13.8.19

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 (214) hide show
  1. package/CHANGELOG.md +5 -2
  2. package/README.md +1 -1
  3. package/dist/action/actionExecutor.d.ts +33 -3
  4. package/dist/action/actionExecutor.js +71 -15
  5. package/dist/action/actionInputs.js +4 -1
  6. package/dist/action/cliVersion.d.ts +25 -0
  7. package/dist/action/cliVersion.js +26 -0
  8. package/dist/action/index.d.ts +2 -1
  9. package/dist/action/index.js +2 -1
  10. package/dist/adapters/video/directorPipeline.js +46 -36
  11. package/dist/adapters/video/ffmpegAdapter.d.ts +17 -0
  12. package/dist/adapters/video/ffmpegAdapter.js +32 -5
  13. package/dist/adapters/video/frameExtractor.js +1 -1
  14. package/dist/adapters/video/videoMerger.js +5 -2
  15. package/dist/agent/arithmeticEvaluator.d.ts +32 -0
  16. package/dist/agent/arithmeticEvaluator.js +349 -0
  17. package/dist/agent/directTools.d.ts +6 -18
  18. package/dist/agent/directTools.js +17 -56
  19. package/dist/artifacts/artifactStore.d.ts +22 -1
  20. package/dist/artifacts/artifactStore.js +66 -6
  21. package/dist/auth/anthropicOAuth.d.ts +26 -1
  22. package/dist/auth/anthropicOAuth.js +81 -5
  23. package/dist/auth/secureFiles.d.ts +37 -0
  24. package/dist/auth/secureFiles.js +95 -0
  25. package/dist/auth/tokenStore.d.ts +43 -6
  26. package/dist/auth/tokenStore.js +260 -79
  27. package/dist/avatar/providers/DIDAvatar.js +49 -45
  28. package/dist/avatar/providers/ReplicateAvatar.js +33 -40
  29. package/dist/browser/neurolink.min.js +485 -558
  30. package/dist/cli/commands/auth.js +112 -70
  31. package/dist/cli/commands/proxy.d.ts +4 -0
  32. package/dist/cli/commands/proxy.js +128 -13
  33. package/dist/cli/commands/serve.d.ts +10 -1
  34. package/dist/cli/commands/serve.js +98 -17
  35. package/dist/cli/commands/server.js +17 -5
  36. package/dist/cli/index.js +146 -5
  37. package/dist/cli/loop/optionsSchema.d.ts +1 -1
  38. package/dist/cli/utils/envManager.js +17 -3
  39. package/dist/cli/utils/serverUtils.d.ts +39 -3
  40. package/dist/cli/utils/serverUtils.js +63 -6
  41. package/dist/core/baseProvider.js +7 -1
  42. package/dist/core/modules/MessageBuilder.js +5 -0
  43. package/dist/core/modules/ToolsManager.d.ts +46 -1
  44. package/dist/core/modules/ToolsManager.js +190 -43
  45. package/dist/files/fileReferenceRegistry.d.ts +2 -23
  46. package/dist/files/fileReferenceRegistry.js +55 -5
  47. package/dist/hitl/hitlManager.js +1 -0
  48. package/dist/index.d.ts +2 -1
  49. package/dist/index.js +6 -1
  50. package/dist/mcp/auth/tokenStorage.d.ts +7 -0
  51. package/dist/mcp/auth/tokenStorage.js +23 -4
  52. package/dist/mcp/externalServerManager.d.ts +13 -3
  53. package/dist/mcp/externalServerManager.js +154 -136
  54. package/dist/mcp/index.d.ts +2 -0
  55. package/dist/mcp/index.js +3 -0
  56. package/dist/mcp/mcpClientFactory.d.ts +14 -0
  57. package/dist/mcp/mcpClientFactory.js +70 -7
  58. package/dist/mcp/projectConfigTrust.d.ts +72 -0
  59. package/dist/mcp/projectConfigTrust.js +237 -0
  60. package/dist/mcp/transportUrlPolicy.d.ts +39 -0
  61. package/dist/mcp/transportUrlPolicy.js +172 -0
  62. package/dist/music/providers/BeatovenMusic.js +35 -46
  63. package/dist/music/providers/ReplicateMusic.js +33 -40
  64. package/dist/neurolink.d.ts +16 -1
  65. package/dist/neurolink.js +64 -11
  66. package/dist/processors/archive/ArchiveProcessor.js +15 -1
  67. package/dist/processors/archive/zipEntryIndex.d.ts +22 -0
  68. package/dist/processors/archive/zipEntryIndex.js +33 -0
  69. package/dist/processors/base/BaseFileProcessor.d.ts +9 -21
  70. package/dist/processors/base/BaseFileProcessor.js +40 -111
  71. package/dist/processors/data/YamlProcessor.d.ts +13 -1
  72. package/dist/processors/data/YamlProcessor.js +93 -2
  73. package/dist/processors/document/OpenDocumentProcessor.js +7 -2
  74. package/dist/processors/document/PptxProcessor.js +12 -7
  75. package/dist/processors/media/VideoProcessor.js +93 -15
  76. package/dist/providers/openaiChatCompletionsClient.js +12 -3
  77. package/dist/proxy/accountLedger.js +6 -8
  78. package/dist/proxy/geminiFormat.d.ts +3 -11
  79. package/dist/proxy/geminiFormat.js +11 -2
  80. package/dist/proxy/inboundAuth.d.ts +89 -0
  81. package/dist/proxy/inboundAuth.js +219 -0
  82. package/dist/proxy/openaiFormat.d.ts +3 -9
  83. package/dist/proxy/openaiFormat.js +21 -15
  84. package/dist/proxy/proxyTranslationEngine.d.ts +2 -6
  85. package/dist/proxy/proxyTranslationEngine.js +25 -14
  86. package/dist/proxy/routingPolicy.d.ts +3 -1
  87. package/dist/proxy/routingPolicy.js +7 -8
  88. package/dist/proxy/tokenRefresh.d.ts +6 -0
  89. package/dist/proxy/tokenRefresh.js +13 -1
  90. package/dist/proxy/updateState.js +4 -4
  91. package/dist/rag/document/loaders.d.ts +0 -6
  92. package/dist/rag/document/loaders.js +16 -10
  93. package/dist/rag/ragIntegration.d.ts +2 -2
  94. package/dist/rag/ragIntegration.js +35 -10
  95. package/dist/rag/retrieval/vectorQueryTool.d.ts +7 -0
  96. package/dist/rag/retrieval/vectorQueryTool.js +54 -17
  97. package/dist/server/abstract/baseServerAdapter.d.ts +43 -0
  98. package/dist/server/abstract/baseServerAdapter.js +119 -6
  99. package/dist/server/adapters/expressAdapter.d.ts +3 -0
  100. package/dist/server/adapters/expressAdapter.js +78 -6
  101. package/dist/server/adapters/fastifyAdapter.d.ts +3 -0
  102. package/dist/server/adapters/fastifyAdapter.js +165 -70
  103. package/dist/server/adapters/honoAdapter.d.ts +9 -1
  104. package/dist/server/adapters/honoAdapter.js +99 -21
  105. package/dist/server/adapters/koaAdapter.d.ts +1 -0
  106. package/dist/server/adapters/koaAdapter.js +153 -74
  107. package/dist/server/index.d.ts +2 -0
  108. package/dist/server/index.js +4 -0
  109. package/dist/server/middleware/auth.js +6 -2
  110. package/dist/server/middleware/cache.js +6 -1
  111. package/dist/server/middleware/rateLimit.js +29 -4
  112. package/dist/server/routes/agentRoutes.js +24 -11
  113. package/dist/server/routes/claudeProxyRoutes.d.ts +1 -0
  114. package/dist/server/routes/claudeProxyRoutes.js +273 -84
  115. package/dist/server/routes/codexProxyRoutes.d.ts +2 -2
  116. package/dist/server/routes/codexProxyRoutes.js +125 -40
  117. package/dist/server/routes/index.d.ts +4 -0
  118. package/dist/server/routes/index.js +35 -4
  119. package/dist/server/routes/mcpRoutes.d.ts +6 -2
  120. package/dist/server/routes/mcpRoutes.js +21 -7
  121. package/dist/server/routes/memoryRoutes.js +7 -6
  122. package/dist/server/routes/toolRoutes.d.ts +12 -2
  123. package/dist/server/routes/toolRoutes.js +33 -3
  124. package/dist/server/routes/transcribeRoutes.js +60 -13
  125. package/dist/server/utils/clientAddress.d.ts +23 -0
  126. package/dist/server/utils/clientAddress.js +65 -0
  127. package/dist/server/utils/clientError.d.ts +35 -0
  128. package/dist/server/utils/clientError.js +129 -0
  129. package/dist/server/utils/pathMatch.d.ts +21 -0
  130. package/dist/server/utils/pathMatch.js +41 -0
  131. package/dist/server/utils/validation.d.ts +9 -0
  132. package/dist/server/utils/validation.js +9 -0
  133. package/dist/server/websocket/WebSocketHandler.js +22 -3
  134. package/dist/server/websocket/frameQueue.d.ts +19 -0
  135. package/dist/server/websocket/frameQueue.js +41 -3
  136. package/dist/server/websocket/transcribeWebSocket.d.ts +8 -1
  137. package/dist/server/websocket/transcribeWebSocket.js +223 -34
  138. package/dist/skills/skillStores.js +5 -0
  139. package/dist/tasks/store/fileTaskStore.d.ts +2 -0
  140. package/dist/tasks/store/fileTaskStore.js +11 -4
  141. package/dist/types/attachments.d.ts +117 -0
  142. package/dist/types/attachments.js +15 -0
  143. package/dist/types/auth.d.ts +6 -0
  144. package/dist/types/cli.d.ts +4 -0
  145. package/dist/types/config.d.ts +56 -0
  146. package/dist/types/file.d.ts +8 -0
  147. package/dist/types/hitl.d.ts +8 -0
  148. package/dist/types/index.d.ts +1 -0
  149. package/dist/types/index.js +1 -0
  150. package/dist/types/mcp.d.ts +98 -0
  151. package/dist/types/multimodal.js +0 -41
  152. package/dist/types/openaiCompatible.d.ts +1 -1
  153. package/dist/types/processor.d.ts +14 -1
  154. package/dist/types/proxy.d.ts +71 -16
  155. package/dist/types/proxyClient.d.ts +2 -0
  156. package/dist/types/rag.d.ts +9 -0
  157. package/dist/types/safeFetch.d.ts +40 -0
  158. package/dist/types/server.d.ts +206 -10
  159. package/dist/types/tools.d.ts +57 -0
  160. package/dist/types/transcribe.d.ts +6 -0
  161. package/dist/utils/attachmentPolicy.d.ts +89 -0
  162. package/dist/utils/attachmentPolicy.js +327 -0
  163. package/dist/utils/dotenvBootstrap.d.ts +48 -19
  164. package/dist/utils/dotenvBootstrap.js +172 -31
  165. package/dist/utils/fileDetector.js +115 -65
  166. package/dist/utils/json/coerce.js +11 -1
  167. package/dist/utils/logSanitize.d.ts +5 -0
  168. package/dist/utils/logSanitize.js +8 -0
  169. package/dist/utils/logger.js +73 -1
  170. package/dist/utils/messageBuilder.d.ts +2 -2
  171. package/dist/utils/messageBuilder.js +118 -105
  172. package/dist/utils/multimodalOptionsBuilder.d.ts +1 -0
  173. package/dist/utils/multimodalOptionsBuilder.js +2 -0
  174. package/dist/utils/redis.d.ts +12 -0
  175. package/dist/utils/redis.js +72 -0
  176. package/dist/utils/retryAfter.d.ts +32 -0
  177. package/dist/utils/retryAfter.js +135 -11
  178. package/dist/utils/safeFetch.d.ts +22 -1
  179. package/dist/utils/safeFetch.js +132 -38
  180. package/dist/utils/safeStoreId.d.ts +19 -0
  181. package/dist/utils/safeStoreId.js +29 -0
  182. package/dist/utils/schemaConversion.d.ts +30 -3
  183. package/dist/utils/schemaConversion.js +457 -84
  184. package/dist/utils/sizeGuard.js +2 -2
  185. package/dist/utils/ssrfGuard.d.ts +3 -3
  186. package/dist/utils/ssrfGuard.js +71 -39
  187. package/dist/voice/eval/sttEvalStore.d.ts +26 -3
  188. package/dist/voice/eval/sttEvalStore.js +77 -12
  189. package/dist/voice/livekit/agentDefinition.d.ts +18 -0
  190. package/dist/voice/livekit/agentDefinition.js +22 -0
  191. package/dist/voice/livekit/realtimeMcpTools.d.ts +1 -1
  192. package/dist/voice/livekit/realtimeMcpTools.js +8 -7
  193. package/dist/voice/livekit/realtimeVoiceAgent.d.ts +2 -4
  194. package/dist/voice/livekit/realtimeVoiceAgent.js +18 -7
  195. package/dist/voice/livekit/voiceAgent.d.ts +2 -2
  196. package/dist/voice/livekit/voiceAgent.js +2 -1
  197. package/dist/voice/livekit/xaiSessionWatch.d.ts +0 -5
  198. package/dist/voice/livekit/xaiSessionWatch.js +30 -0
  199. package/dist/voice/providers/GeminiLive.js +21 -6
  200. package/dist/voice/providers/GoogleSTT.js +8 -5
  201. package/dist/voice/transcribe.d.ts +2 -2
  202. package/dist/voice/transcribe.js +34 -18
  203. package/dist/voice/whistle/audio.js +11 -5
  204. package/dist/workflow/workflows/adaptiveWorkflow.d.ts +2 -2
  205. package/dist/workflow/workflows/adaptiveWorkflow.js +10 -10
  206. package/dist/workflow/workflows/consensusWorkflow.d.ts +4 -4
  207. package/dist/workflow/workflows/consensusWorkflow.js +12 -12
  208. package/dist/workflow/workflows/fallbackWorkflow.d.ts +3 -3
  209. package/dist/workflow/workflows/fallbackWorkflow.js +7 -7
  210. package/dist/workflow/workflows/multiJudgeWorkflow.d.ts +7 -7
  211. package/dist/workflow/workflows/multiJudgeWorkflow.js +31 -31
  212. package/docs-site/static/search-index.json +74 -52
  213. package/package.json +173 -156
  214. package/scripts/observability/import-openobserve-dashboard.mjs +11 -3
@@ -475,7 +475,7 @@
475
475
  {"objectID":"33ab5ee48608cb06f54b7febf39e926ac13ba5826c54901134eb7954eef6135d","title":"Range reads","url":"/docs/agents/ARTIFACT-BANKING#range-reads","content":"retrieve_context({ artifactId, offset, limit }) and readArtifact(id, page)\nask the backend for one window when it can produce one. ArtifactStore has\nan optional retrieveRange(id, { offset, limit }) returning\n{ content, offset, totalLength }; when a backend implements it, only the\nwindow crosses the wire and hasMore / totalSize come from totalLength,\nnever from the payload. A backend without it is read whole and sliced, exactly\nas before.\n\nUnits are characters (UTF-16 code units), the same unit offset and\nlimit always used. RedisArtifactStore records the payload's character\nlength beside its byte length and uses GETRANGE only when the two are equal\n— pure ASCII, which is what JSON tool output and logs almost always are.\nAnything else falls back to a whole read, which is slower and still correct.\nA window never starts on the wrong character.","hierarchy":{"lvl0":"Agents","lvl1":"Artifact Banking (`bankArtifact` / `readArtifact`)","lvl2":"Range reads","lvl3":""}},
476
476
  {"objectID":"7085ebf9cc51233991e0bb7d5684b0afaa26d6845f9e2a9d140fcbab1c406fd3","title":"Searching an artifact","url":"/docs/agents/ARTIFACT-BANKING#searching-an-artifact","content":"retrieve_context({ artifactId, search }) finds literal, case-insensitive text\nin an artifact and returns where it is, so the model can jump instead of\npaging to it:\n\nSnippets are bounded (about 120 characters each side of the hit) rather than\nwhole lines, because an MCP artifact is usually one compact JSON line and \"the\nmatching line\" would be the entire payload. Up to 50 matches come back per\ncall; totalMatches counts the rest and nextSearchOffset is the offset to\npass to see them. Regex metacharacters are matched literally — the model's\ninput is never compiled as a pattern — and an empty or over-long pattern is an\nexplicit error, never a silently unfiltered read.","hierarchy":{"lvl0":"Agents","lvl1":"Artifact Banking (`bankArtifact` / `readArtifact`)","lvl2":"Searching an artifact","lvl3":""}},
477
477
  {"objectID":"2861dd40f080ccdf046d8ed7779d4fa805e22593f21066888f1d6065b82e1c06","title":"Rules of thumb","url":"/docs/agents/ARTIFACT-BANKING#rules-of-thumb","content":"Bank first, summarize second. Write the payload, then decide what the\n conversation sees. Never the other way round.\nHand the model preview _and_ readBackHint together. A preview with no\n way back is just a truncation with extra steps.\nDo not raise previewChars to avoid a read-back. Past a few thousand\n characters the preview recreates the context pressure banking removes; that\n is why the cap exists.\nsizeBytes is the honest number. Show it when you show a preview, so\n \"there is more\" is visible rather than inferred.","hierarchy":{"lvl0":"Agents","lvl1":"Artifact Banking (`bankArtifact` / `readArtifact`)","lvl2":"Rules of thumb","lvl3":""}},
478
- {"objectID":"d8109a96295f93f460ef7aa2be72fb5043666f7d2024b7baff67e14c90d5584d","title":"Async Delegation (`delegate_task` / `collect_results`)","url":"/docs/agents/ASYNC-DELEGATION","content":"Async Delegation (delegate_task / collect_results)\n\nDelegation through registerAgentTool is synchronous: the supervising\nagent's loop blocks on each worker, so four investigations cost four times one\ninvestigation and the supervisor sits idle while each runs.\n\nThese tools change only when the caller waits. delegate_task returns a\nworkerId immediately and the agent keeps working; collect_results hands back\nwhichever worker finished first, which has nothing to do with which was\nspawned first.\n\nOpt-in and additive: nothing registers these tools until you ask.\n\nQuick start\n\nOr drive it from host code:\n\nThe tools\n\n| Tool | Input | Behaviour |\n| ----------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------- |\n| delegate_task | { task, scope?, context?, tools?, model? } | Starts a background worker. Returns { workerId, spawnedAt, queued, pending, ready } at once. |\n| collect_results | { mode?: \"any\" \\| \"all\", workerId?, waitMs? } | Claims finished workers in completion order, each exactly once. |\n\nA collected outcome:\n\nsummary and report are not alternatives: the summary is what the\nconversation carries, the report is where the evidence lives. The full\nreport — narrative, structured data, a tool digest, and every tool execution\nrecord in full — is banked to a file, never truncated into the conversation.\n\nOut-of-order collection\n\nwaitMs: 0 polls (whatever is ready right now); omitting it waits up to five\nminutes. timedOut means work was still outstanding when the call returned —\nthe signal to come back later, not an error.\n\nKnowing a worker landed, without polling\n\nEvery ChecklistToolResult carries delegatesPending and delegatesReady, so\na model that calls tasks_list for any reason learns that a worker finished:\n\nThat is the whole notification channel. The core generate loop is untouched —\nthere is no injection point to get wrong and nothing to poll.\n\nConcurrency, depth and cancellation\nOne pool. Concurrency uses the same process-wide delegation pool as\n registerAgentTool. maxConcurrent raises it and never lowers it — it is\n not a per-agent throttle. Spawns past capacity queue; they are never\n refused. DelegateHandle.queued says which happened.\nDepth. maxDepth defaults to 1: a background worker does not spawn\n background workers, because its delegates would outlive it with nobody left to\n collect them. At the ceiling delegate_task refuses, in the registrar's own\n wording, and names what to do instead.\nCancellation. cancelDelegates(workerId?) aborts one worker or every\n worker this instance spawned; an abortSignal passed to spawnDelegate does\n the same when the parent aborts. A cancelled worker still settles into a\n claimable outcome with ok: false and a banked report of whatever it had —\n silence would strand the supervisor waiting for a worker that is never coming.\nAn uncollected outcome is retained until claimed. Collection is what\n frees a job's registry entry; a supervisor that spawns and never collects\n accumulates settled outcomes for the life of the process. Collect what you\n spawn.\nmaxConcurrent: Infinity maps to a finite stand-in (1024) — effectively\n unbounded, without letting a non-finite number into the pool arithmetic\n (NaN once deadlocked it permanently).\n\nSessions\n\nCollection is scoped to the caller's session, resolved the same way the task\nchecklist resolves it: execution context first, then the instance's\nsetToolContext({ sessionId }), then one default per instance. Session A can\nnever collect session B's worker.\n\nA worker gets its own session (the run id), deliberately: its checklist and\nits own delegate counters must not merge into its supervisor's.\n\nHost API\n\nTypes live in src/lib/types/delegation.ts and are exported from the package\nbarrel.\n\nWhat it is built on\n\nNothing here is a second implementation of anything:\nrunIsolatedAgent — fresh session on a worker instance that shares this\n host's tool registry, so live MCP connections are reused; waste detection,\n honest stop reasons, continuation handles;\nthe delegation pool in agentToolRegistrar — one pool, raised never lowered;\nbankArtifact (N3) — the full report on disk, a pointer in the conversation;\nthe task checklist (N1) — the counters that make completion visible.\n\nTests\n\npnpm run build && pnpm run test:agent-delegation —\ntest/continuous-test-suite-agent-delegation.ts.\n\nThe timing claims are proved against a loopback chat server that answers\nDELAY:<ms> after exactly that many milliseconds, so \"which worker finished\nfirst\" is a property of the test rather than of a provider's mood. Only the live\ncase needs credentials, and it skips without them.","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"","lvl3":""}},
478
+ {"objectID":"d8109a96295f93f460ef7aa2be72fb5043666f7d2024b7baff67e14c90d5584d","title":"Async Delegation (`delegate_task` / `collect_results`)","url":"/docs/agents/ASYNC-DELEGATION","content":"Async Delegation (delegate_task / collect_results)\n\nDelegation through registerAgentTool is synchronous: the supervising\nagent's loop blocks on each worker, so four investigations cost four times one\ninvestigation and the supervisor sits idle while each runs.\n\nThese tools change only when the caller waits. delegate_task returns a\nworkerId immediately and the agent keeps working; collect_results hands back\nwhichever worker finished first, which has nothing to do with which was\nspawned first.\n\nOpt-in and additive: nothing registers these tools until you ask.\n\nQuick start\n\nOr drive it from host code:\n\nThe tools\n\n| Tool | Input | Behaviour |\n| ----------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------- |\n| delegate_task | { task, scope?, context?, tools?, model? } | Starts a background worker. Returns { workerId, spawnedAt, queued, pending, ready } at once. |\n| collect_results | { mode?: \"any\" \\| \"all\", workerId?, waitMs? } | Claims finished workers in completion order, each exactly once. |\n\nA collected outcome:\n\nsummary and report are not alternatives: the summary is what the\nconversation carries, the report is where the evidence lives. The full\nreport — narrative, structured data, a tool digest, and every tool execution\nrecord in full — is banked to a file, never truncated into the conversation.\n\nOut-of-order collection\n\nwaitMs: 0 polls (whatever is ready right now); omitting it waits up to five\nminutes. timedOut means work was still outstanding when the call returned —\nthe signal to come back later, not an error.\n\nKnowing a worker landed, without polling\n\nEvery ChecklistToolResult carries delegatesPending and delegatesReady, so\na model that calls tasks_list for any reason learns that a worker finished:\n\nThat is the whole notification channel. The core generate loop is untouched —\nthere is no injection point to get wrong and nothing to poll.\n\nConcurrency, depth and cancellation\nOne pool. Concurrency uses the same process-wide delegation pool as\n registerAgentTool. maxConcurrent raises it and never lowers it — it is\n not a per-agent throttle. Spawns past capacity queue; they are never\n refused. DelegateHandle.queued says which happened.\nDepth. maxDepth defaults to 1: a background worker does not spawn\n background workers, because its delegates would outlive it with nobody left to\n collect them. At the ceiling delegate_task refuses, in the registrar's own\n wording, and names what to do instead.\nCancellation. cancelDelegates(workerId?) aborts one worker or every\n worker this instance spawned; an abortSignal passed to spawnDelegate does\n the same when the parent aborts. A cancelled worker still settles into a\n claimable outcome with ok: false and a banked report of whatever it had —\n silence would strand the supervisor waiting for a worker that is never coming.\nAn uncollected outcome is retained until claimed. Collection is what\n frees a job's registry entry; a supervisor that spawns and never collects\n accumulates settled outcomes for the life of the process. Collect what you\n spawn.\nmaxConcurrent: Infinity maps to a finite stand-in (1024) — effectively\n unbounded, without letting a non-finite number into the pool arithmetic\n (NaN once deadlocked it permanently).\n\nSessions\n\nCollection is scoped to the caller's session, resolved the same way the task\nchecklist resolves it: execution context first, then the instance's\nsetToolContext({ sessionId }), then one default per instance. Session A can\nnever collect session B's worker.\n\nA worker gets its own session (the run id), deliberately: its checklist and\nits own delegate counters must not merge into its supervisor's.\n\nHost API\n\nTypes live in src/lib/types/delegation.ts and are exported from the package\nbarrel.\n\nWhat it is built on\n\nNothing here is a second implementation of anything:\nrunIsolatedAgent — fresh session on a worker instance that shares this\n host's tool registry, so live MCP connections are reused; waste detection,\n honest stop reasons, continuation handles;\nthe isolation is behavioural, not a security boundary. A worker\n created by createWorkerInstance() — and therefore every isolated agent\n and delegate — runs in the same process as the host, inherits the\n host's provider credentials and environment, shares its tool registry and\n HITL manager, and may only narrow the host's file-tool roots. What it\n gets fresh is conversation state: a new session, its own budget and its\n own stop reasons. A delegate's prompt can therefore reach anything the\n host's tools can reach. To run untrusted work with fewer privileges, start\n a separate process (or container) with its own credentials and point the\n host at it as an external MCP server or a remote ","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"","lvl3":""}},
479
479
  {"objectID":"afb7f7ea69e16ed38d8524c55061a475066a9e125156564d1a79fa3dbdb98523","title":"Async Delegation (delegate_task / collect_results)","url":"/docs/agents/ASYNC-DELEGATION#async-delegation-delegate_task-collect_results","content":"Delegation through registerAgentTool is synchronous: the supervising\nagent's loop blocks on each worker, so four investigations cost four times one\ninvestigation and the supervisor sits idle while each runs.\n\nThese tools change only when the caller waits. delegate_task returns a\nworkerId immediately and the agent keeps working; collect_results hands back\nwhichever worker finished first, which has nothing to do with which was\nspawned first.\n\nOpt-in and additive: nothing registers these tools until you ask.","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"Async Delegation (delegate_task / collect_results)","lvl3":""}},
480
480
  {"objectID":"205057b267b584b2c25ef4c83e0dc259ba04063e13ec9da8f71969dcc4889257","title":"Quick start","url":"/docs/agents/ASYNC-DELEGATION#quick-start","content":"Or drive it from host code:","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"Quick start","lvl3":""}},
481
481
  {"objectID":"225a13455cf22c535832c74508bf9494e67091749df9845222b58af72e63d15b","title":"The tools","url":"/docs/agents/ASYNC-DELEGATION#the-tools","content":"| Tool | Input | Behaviour |\n| ----------------- | ----------------------------------------------- | ---------------------------------------------------------------------------------------------- |\n| delegate_task | { task, scope?, context?, tools?, model? } | Starts a background worker. Returns { workerId, spawnedAt, queued, pending, ready } at once. |\n| collect_results | { mode?: \"any\" \\| \"all\", workerId?, waitMs? } | Claims finished workers in completion order, each exactly once. |\n\nA collected outcome:\n\nsummary and report are not alternatives: the summary is what the\nconversation carries, the report is where the evidence lives. The full\nreport — narrative, structured data, a tool digest, and every tool execution\nrecord in full — is banked to a file, never truncated into the conversation.","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"The tools","lvl3":""}},
@@ -484,7 +484,7 @@
484
484
  {"objectID":"63bcb00cc8a92b97f7642b1bc002685fa0bd97afc717378b8e426a107754bf2d","title":"Concurrency, depth and cancellation","url":"/docs/agents/ASYNC-DELEGATION#concurrency-depth-and-cancellation","content":"One pool. Concurrency uses the same process-wide delegation pool as\n registerAgentTool. maxConcurrent raises it and never lowers it — it is\n not a per-agent throttle. Spawns past capacity queue; they are never\n refused. DelegateHandle.queued says which happened.\nDepth. maxDepth defaults to 1: a background worker does not spawn\n background workers, because its delegates would outlive it with nobody left to\n collect them. At the ceiling delegate_task refuses, in the registrar's own\n wording, and names what to do instead.\nCancellation. cancelDelegates(workerId?) aborts one worker or every\n worker this instance spawned; an abortSignal passed to spawnDelegate does\n the same when the parent aborts. A cancelled worker still settles into a\n claimable outcome with ok: false and a banked report of whatever it had —\n silence would strand the supervisor waiting for a worker that is never coming.\nAn uncollected outcome is retained until claimed. Collection is what\n frees a job's registry entry; a supervisor that spawns and never collects\n accumulates settled outcomes for the life of the process. Collect what you\n spawn.\nmaxConcurrent: Infinity maps to a finite stand-in (1024) — effectively\n unbounded, without letting a non-finite number into the pool arithmetic\n (NaN once deadlocked it permanently).","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"Concurrency, depth and cancellation","lvl3":""}},
485
485
  {"objectID":"de8796fe6a029f9d1b2973c6aba250d1eb33fa9ba7aa4a3994a48822b27886d7","title":"Sessions","url":"/docs/agents/ASYNC-DELEGATION#sessions","content":"Collection is scoped to the caller's session, resolved the same way the task\nchecklist resolves it: execution context first, then the instance's\nsetToolContext({ sessionId }), then one default per instance. Session A can\nnever collect session B's worker.\n\nA worker gets its own session (the run id), deliberately: its checklist and\nits own delegate counters must not merge into its supervisor's.","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"Sessions","lvl3":""}},
486
486
  {"objectID":"29f6f5edb20c907e3434385f62d0389c6de8d63f088b787771d91b79cda151db","title":"Host API","url":"/docs/agents/ASYNC-DELEGATION#host-api","content":"Types live in src/lib/types/delegation.ts and are exported from the package\nbarrel.","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"Host API","lvl3":""}},
487
- {"objectID":"7687a1f43203ce2b79dbd58588c0e866de27b4c153ce4a11b20e84a6d759ac67","title":"What it is built on","url":"/docs/agents/ASYNC-DELEGATION#what-it-is-built-on","content":"Nothing here is a second implementation of anything:\nrunIsolatedAgent — fresh session on a worker instance that shares this\n host's tool registry, so live MCP connections are reused; waste detection,\n honest stop reasons, continuation handles;\nthe delegation pool in agentToolRegistrar — one pool, raised never lowered;\nbankArtifact (N3) — the full report on disk, a pointer in the conversation;\nthe task checklist (N1) — the counters that make completion visible.","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"What it is built on","lvl3":""}},
487
+ {"objectID":"7687a1f43203ce2b79dbd58588c0e866de27b4c153ce4a11b20e84a6d759ac67","title":"What it is built on","url":"/docs/agents/ASYNC-DELEGATION#what-it-is-built-on","content":"Nothing here is a second implementation of anything:\nrunIsolatedAgent — fresh session on a worker instance that shares this\n host's tool registry, so live MCP connections are reused; waste detection,\n honest stop reasons, continuation handles;\nthe isolation is behavioural, not a security boundary. A worker\n created by createWorkerInstance() — and therefore every isolated agent\n and delegate — runs in the same process as the host, inherits the\n host's provider credentials and environment, shares its tool registry and\n HITL manager, and may only narrow the host's file-tool roots. What it\n gets fresh is conversation state: a new session, its own budget and its\n own stop reasons. A delegate's prompt can therefore reach anything the\n host's tools can reach. To run untrusted work with fewer privileges, start\n a separate process (or container) with its own credentials and point the\n host at it as an external MCP server or a remote agent — do not rely on a\n worker instance for that;\nthe delegation pool in agentToolRegistrar — one pool, raised never lowered;\nbankArtifact (N3) — the full report on disk, a pointer in the conversation;\nthe task checklist (N1) — the counters that make completion visible.","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"What it is built on","lvl3":""}},
488
488
  {"objectID":"c31b7ef4deb0d5c74cf2a92930ffc893c74f78cf4a5352c088536793d327487f","title":"Tests","url":"/docs/agents/ASYNC-DELEGATION#tests","content":"pnpm run build && pnpm run test:agent-delegation —\ntest/continuous-test-suite-agent-delegation.ts.\n\nThe timing claims are proved against a loopback chat server that answers\nDELAY:<ms> after exactly that many milliseconds, so \"which worker finished\nfirst\" is a property of the test rather than of a provider's mood. Only the live\ncase needs credentials, and it skips without them.","hierarchy":{"lvl0":"Agents","lvl1":"Async Delegation (`delegate_task` / `collect_results`)","lvl2":"Tests","lvl3":""}},
489
489
  {"objectID":"49bfb17b7da8b8887501ef22f4b6e140b84c469bf5df2b06ea91ff662e47a3e5","title":"Background Commands (`run_command_bg` / `command_status` / `command_output` / `command_kill`)","url":"/docs/agents/BACKGROUND-COMMANDS","content":"Background Commands (run_command_bg / command_status / command_output / command_kill)\n\nA long-running agent has to run real commands — a build, a test suite, a linter\nwhose output is the evidence for a finding. The two obvious shapes both\nfail: bashTool blocks the loop, hands the model a shell, and truncates its own\noutput at 100 KB; a child_process call with a command string is a shell\ninjection with extra steps.\n\nThese tools keep three promises instead.\n\n| Promise | What it means |\n| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Detached | run_command_bg returns a taskId at once; the agent keeps working and asks about the command when it wants to. |\n| Nothing discarded | Both streams go straight to files as they arrive, and the COMPLETE files are banked as artifacts when the command settles. The conversation gets a bounded tail plus a read-back call. |\n| Hardened by contract | argv arrays with no shell, an exact-match executable allowlist, a realpath cwd sandbox, and a timeout that escalates SIGTERM → SIGKILL. |\n\nOpt-in and additive: nothing registers these tools until you ask, and the\npolicy is required — until one is set, every start is refused.\n\nQuick start\n\nOr drive it from host code:\n\nThe policy is the contract\nargv arrays only. spawn(argv[0], argv.slice(1), { shell: false }). There\n is no string form and no shell, ever. An argv[0] containing whitespace or a\n shell metacharacter is refused with a message saying so — because a caller\n that passed \"pnpm run lint && echo done\" believed it was writing a shell\n line, and spawning an executable with that literal name would be a worse\n answer than a refusal.\nExact-match allowlist. argv[0] must appear verbatim in\n allowedExecutables. There is deliberately no basename fallback: allowlisting\n git must never permit /tmp/evil/git. Name absolute paths when you can.\nallowlist has the final say, after the allowlist and the sandbox pass.\n Return true, or a string that becomes the refusal — so put the recovery step\n in it.\ncwd sandbox. resolveWithinRoot(cwd, cwdRoot) resolves both sides\n through the filesystem before comparing them, so a symlink inside the root\n pointing at /etc is refused rather than followed. A lexical comparison is\n not a sandbox.\nTimeout kill. SIGTERM at timeoutMs, SIGKILL five seconds later, state\n timeout. A process that ignores SIGTERM does not get to outlive its budget.\n\nenv deserves its own note: omit it and the command inherits the parent\nenvironment (what a repository's own checks normally need); pass it and it\nREPLACES the parent environment entirely — the child gets exactly those\nvariables and nothing else, which is how you keep the host's credentials out of\na third-party build.\n\nOutput: bounded previews, unbounded files\n\nBoth streams are written to\njoin(tmpdir(), \"neurolink-commands\", <taskId>)/{stdout,stderr}.log as they\narrive, and banked with bankArtifact({ kind: \"command-output\" }) when the\ncommand settles. That means:\nstatus.tailPreview is ≤ 2000 characters — orientation, never evidence.\nstatus.stdout / status.stderr are BankedArtifactRefs once settled;\n retrieve_context({ artifactId }) pages them like any other artifact.\ncommand_output({ taskId, stream, offset, limit }) reads the log file\n directly, while the command is still running as well as after. Character\n offsets, totalSize and hasMore match retrieve_context exactly, so paging\n code written for one works on the other.\n\nmaxOutputBytes is the single bound, and reaching it is loud: the command is\nkilled, the state is output-limit, and everything written up to the cap\nstays on disk in full. A capped command is a different fact from a failed one,\nand both are different from a truncated one — which is why there is a state for\nit rather than a silent cut.\n\nLearning that a command finished\n\nThe core generate loop is not modified. Completion surfaces the same way a\ndelegate's does (N2.3): counters ride along on results.\nEvery command tool result carries running / finished for the session.\nEvery ChecklistToolResult carries commandsRunning / commandsFinished, so\n a tasks_list tells the agent a build landed with no polling machinery.\n\nfinished means finished and not yet looked at. Reading a settled command's\nstatus or output clears it, so a non-zero finished always means there is\nsomething new to read. Nothing is discarded when it clears — the job, its logs\nand its artifacts stay exactly where they were.\n\nRead-only git toolset\n\nSix bounded tools — git_log, git_show, git_diff, git_blame,\ngit_m","hierarchy":{"lvl0":"Agents","lvl1":"Background Commands (`run_command_bg` / `command_status` / `command_output` / `command_kill`)","lvl2":"","lvl3":""}},
490
490
  {"objectID":"37947dabf3ae65ea803029b5512489b699d1e57f96c2f6bac290dff24545848f","title":"Background Commands (run_command_bg / command_status / command_output / command_kill)","url":"/docs/agents/BACKGROUND-COMMANDS#background-commands-run_command_bg-command_status-command_output-command_kill","content":"A long-running agent has to run real commands — a build, a test suite, a linter\nwhose output is the evidence for a finding. The two obvious shapes both\nfail: bashTool blocks the loop, hands the model a shell, and truncates its own\noutput at 100 KB; a child_process call with a command string is a shell\ninjection with extra steps.\n\nThese tools keep three promises instead.\n\n| Promise | What it means |\n| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Detached | run_command_bg returns a taskId at once; the agent keeps working and asks about the command when it wants to. |\n| Nothing discarded | Both streams go straight to files as they arrive, and the COMPLETE files are banked as artifacts when the command settles. The conversation gets a bounded tail plus a read-back call. |\n| Hardened by contract | argv arrays with no shell, an exact-match executable allowlist, a realpath cwd sandbox, and a timeout that escalates SIGTERM → SIGKILL. |\n\nOpt-in and additive: nothing registers these tools until you ask, and the\npolicy is required — until one is set, every start is refused.","hierarchy":{"lvl0":"Agents","lvl1":"Background Commands (`run_command_bg` / `command_status` / `command_output` / `command_kill`)","lvl2":"Background Commands (run_command_bg / command_status / command_output / command_kill)","lvl3":""}},
@@ -1512,7 +1512,7 @@
1512
1512
  {"objectID":"36e3959ec990bb9711fce519517797856ee468c1fd33e36f6bf7e2e1af2fbf7e","title":"Security Considerations","url":"/docs/deployment/configuration-management#security-considerations","content":"API Key Management: Store API keys securely\nBackup Encryption: Consider encrypting sensitive backups\nAccess Control: Limit config update permissions\nAudit Logging: Log all config changes","hierarchy":{"lvl0":"Deployment","lvl1":"🏗️ Enterprise Configuration Management Guide","lvl2":"Security Considerations","lvl3":""}},
1513
1513
  {"objectID":"e9a415ada65134043a5580ea06952a70e9ad8c30c1eb37735c4cfd4632d2e182","title":"Common Issues","url":"/docs/deployment/configuration-management#common-issues","content":"Config Update Fails\n\nBackup System Issues\n\nProvider Configuration Issues","hierarchy":{"lvl0":"Deployment","lvl1":"🏗️ Enterprise Configuration Management Guide","lvl2":"Common Issues","lvl3":""}},
1514
1514
  {"objectID":"516e640b602eed2c5d81f3a90cf6260fcff12fc78d397d9ad3bd5215568b9e67","title":"Support & Resources","url":"/docs/deployment/configuration-management#support-resources","content":"Documentation: See API Reference for interface details\nMigration Guide: See docs/INTERFACE-MIGRATION-GUIDE.md\nTroubleshooting: See docs/TROUBLESHOOTING.md\nGitHub Issues: Report bugs and feature requests\n\n🎯 Enterprise configuration management provides robust, reliable, and maintainable configuration handling for production NeuroLink deployments.","hierarchy":{"lvl0":"Deployment","lvl1":"🏗️ Enterprise Configuration Management Guide","lvl2":"Support & Resources","lvl3":""}},
1515
- {"objectID":"cc93459ad2879898737dd1c30f20e9f15cea76c2895e538aee06286e2920af62","title":"⚙️ NeuroLink Configuration Guide","url":"/docs/deployment/configuration","content":"⚙️ NeuroLink Configuration Guide\n\n📖 Overview\n\nThis guide covers all configuration options for NeuroLink, including AI provider setup, dynamic model configuration, MCP integration, and environment configuration.\n\nBasic Usage Examples\n\n🤖 AI Provider Configuration\n\nEnvironment Variables\n\nNeuroLink supports multiple AI providers. Set up one or more API keys:\n\n.env File Configuration\n\nCreate a .env file in your project root:\n\nProvider Selection Priority\n\nNeuroLink automatically selects the best available provider:\nGoogle AI Studio (if GOOGLE_AI_API_KEY is set)\nOpenAI (if OPENAI_API_KEY is set)\nAnthropic (if ANTHROPIC_API_KEY is set)\nOther providers in order of availability\n\nForce specific provider:\n\n🎯 Dynamic Model Configuration (v1.8.0+)\n\nOverview\n\nThe dynamic model system enables intelligent model selection, cost optimization, and runtime model configuration without code changes.\n\nEnvironment Variables\n\nModel Configuration Server\n\nStart the model configuration server to enable dynamic model features:\n\nModel Configuration File\n\nCreate or modify config/models.json to define available models:\n\nDynamic Model Usage\n\nCLI Usage\n\nSDK Usage\n\nBenefits\n✅ Runtime Updates: Add new models without code deployment\n✅ Smart Selection: Automatic model selection based on capabilities\n✅ Cost Optimization: Choose models based on price constraints\n✅ Easy Aliases: Use friendly names like \"claude-latest\", \"fastest\"\n✅ Provider Agnostic: Unified interface across all AI providers\n\n🛠️ MCP Configuration\n\nBuilt-in Tools Configuration\n\nBuilt-in tools are automatically available:\n\nTest built-in tools:\n\nExternal MCP Server Configuration\n\nExternal servers are auto-discovered from all major AI tools:\n\nAuto-Discovery Locations\n\nmacOS:\n\nLinux:\n\nWindows:\n\nManual MCP Configuration\n\nCreate .mcp-config.json in your project root:\n\nHTTP Transport Configuration\n\nFor remote MCP servers, use HTTP transport with authentication, retry, and rate limiting:\n\nHTTP Transport Options:\n\n| Option | Type | Description |\n| -------------- | -------- | --------------------------------------- |\n| transport | \"http\" | Transport type for remote servers |\n| url | string | URL of the remote MCP endpoint |\n| headers | object | HTTP headers for authentication |\n| httpOptions | object | Connection and timeout settings |\n| retryConfig | object | Retry behavior with exponential backoff |\n| rateLimiting | object | Rate limiting configuration |\n\nSee MCP HTTP Transport Guide for complete documentation.\n\nMCP Discovery Commands\n\n🖥️ CLI Configuration\n\nGlobal CLI Options\n\nCommand-line Options\n\n📊 Development Configuration\n\nTypeScript Configuration\n\nFor TypeScript projects, add to your tsconfig.json:\n\nPackage.json Scripts\n\nAdd useful scripts to your package.json:\n\nEnvironment Setup Script\n\nCreate setup-neurolink.sh:\n\nContext Compaction Configuration\n\nOverview\n\nContext compaction automatically manages conversation history to keep it within a model's context window. When the estimated input tokens exceed a configurable threshold (default: 80% of available input space), a multi-stage reduction pipeline runs before the next LLM call. The four stages, in order, are:\nTool Output Pruning -- Replace old, large tool results with compact placeholders (no LLM call)\nFile Read Deduplication -- Keep only the latest read of each file path (no LLM call)\nLLM Summarization -- Produce a structured summary of older messages (requires LLM call)\nSliding Window Truncation -- Tag the oldest messages as truncated (no LLM call)\n\nEach stage only runs if the previous stage did not bring token usage below the target. The pipeline exits early once the context fits.\n\nSDK Configuration\n\nConfigure context compaction through the contextCompaction field inside conversationMemory:\n\nField Reference:\n\n| Field | Type | Default | Description |\n| ----------------------- | --------- | ----------------------------------- | ----------------------------------------------- |\n| enabled | boolean | true (when summarization enabled) | Master switch for auto-compaction |\n| threshold | number | 0.80 | Usage ratio that triggers compaction (0.0--1.0) |\n| enablePruning | boolean | true | Enable Stage 1: tool output pruning |\n| enableDeduplication | boolean | true | Enable Stage 2: file read deduplication |\n| enableSlidingWindow | boolean | true | Enable Stage 4: sliding window truncation |\n| maxToolOutputBytes | number | 51200 | Tool output byte limit (50 KB) |\n| maxToolOutputLines | number | 2000 | Tool output line limit |\n| fileReadBudgetPercent | numb","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"","lvl3":""}},
1515
+ {"objectID":"cc93459ad2879898737dd1c30f20e9f15cea76c2895e538aee06286e2920af62","title":"⚙️ NeuroLink Configuration Guide","url":"/docs/deployment/configuration","content":"⚙️ NeuroLink Configuration Guide\n\n📖 Overview\n\nThis guide covers all configuration options for NeuroLink, including AI provider setup, dynamic model configuration, MCP integration, and environment configuration.\n\nBasic Usage Examples\n\n🤖 AI Provider Configuration\n\nEnvironment Variables\n\nNeuroLink supports multiple AI providers. Set up one or more API keys:\n\n.env File Configuration\n\nCreate a .env file in your project root:\n\nProvider Selection Priority\n\nNeuroLink automatically selects the best available provider:\nGoogle AI Studio (if GOOGLE_AI_API_KEY is set)\nOpenAI (if OPENAI_API_KEY is set)\nAnthropic (if ANTHROPIC_API_KEY is set)\nOther providers in order of availability\n\nForce specific provider:\n\n🎯 Dynamic Model Configuration (v1.8.0+)\n\nOverview\n\nThe dynamic model system enables intelligent model selection, cost optimization, and runtime model configuration without code changes.\n\nEnvironment Variables\n\nModel Configuration Server\n\nStart the model configuration server to enable dynamic model features:\n\nModel Configuration File\n\nCreate or modify config/models.json to define available models:\n\nDynamic Model Usage\n\nCLI Usage\n\nSDK Usage\n\nBenefits\n✅ Runtime Updates: Add new models without code deployment\n✅ Smart Selection: Automatic model selection based on capabilities\n✅ Cost Optimization: Choose models based on price constraints\n✅ Easy Aliases: Use friendly names like \"claude-latest\", \"fastest\"\n✅ Provider Agnostic: Unified interface across all AI providers\n\n🛠️ MCP Configuration\n\nBuilt-in Tools Configuration\n\nBuilt-in tools are automatically available:\n\nTest built-in tools:\n\nExternal MCP Server Configuration\n\nExternal servers are auto-discovered from all major AI tools:\n\nAuto-Discovery Locations\n\nmacOS:\n\nLinux:\n\nWindows:\n\nManual MCP Configuration\n\nCreate .mcp-config.json in your project root:\n\nThe file is loaded only on an explicit decision, because it names commands to run:\nSDK: new NeuroLink({ mcp: { configPath: \"./.mcp-config.json\" } }), or mcp: { trustProjectConfig: true } to load the working directory's file. Nothing is read from the working directory otherwise.\nCLI: the file is discovered, then trusted by hash — interactively with a prompt, or with --trust-mcp-config / NEUROLINK_TRUST_MCP_CONFIG=1; NEUROLINK_TRUST_MCP_CONFIG=0 runs without it. Accepted hashes live in ~/.neurolink/trusted-mcp-configs.json.\n\nPer-server options added for this: inheritParentEnv (stdio; default false — the server gets a minimal environment plus env, use \"env\": { \"X\": \"${X}\" } to pass a variable through) and allowPrivateNetwork (network transports; default false — TLS is required for non-loopback hosts and private addresses are refused). ${VAR} expands in env and args only. See MCP Integration for the full rules.\n\nHTTP Transport Configuration\n\nFor remote MCP servers, use HTTP transport with authentication, retry, and rate limiting:\n\nHTTP Transport Options:\n\n| Option | Type | Description |\n| -------------- | -------- | --------------------------------------- |\n| transport | \"http\" | Transport type for remote servers |\n| url | string | URL of the remote MCP endpoint |\n| headers | object | HTTP headers for authentication |\n| httpOptions | object | Connection and timeout settings |\n| retryConfig | object | Retry behavior with exponential backoff |\n| rateLimiting | object | Rate limiting configuration |\n\nSee MCP HTTP Transport Guide for complete documentation.\n\nMCP Discovery Commands\n\n🖥️ CLI Configuration\n\nGlobal CLI Options\n\nCommand-line Options\n\n📊 Development Configuration\n\nTypeScript Configuration\n\nFor TypeScript projects, add to your tsconfig.json:\n\nPackage.json Scripts\n\nAdd useful scripts to your package.json:\n\nEnvironment Setup Script\n\nCreate setup-neurolink.sh:\n\nContext Compaction Configuration\n\nOverview\n\nContext compaction automatically manages conversation history to keep it within a model's context window. When the estimated input tokens exceed a configurable threshold (default: 80% of available input space), a multi-stage reduction pipeline runs before the next LLM call. The four stages, in order, are:\nTool Output Pruning -- Replace old, large tool results with compact placeholders (no LLM call)\nFile Read Deduplication -- Keep only the latest read of each file path (no LLM call)\nLLM Summarization -- Produce a structured summary of older messages (requires LLM call)\nSliding Window Truncation -- Tag the oldest messages as truncated (no LLM call)\n\nEach stage only runs if the previous stage did not bring token usage below the target. The pipeline exits early once the context fits.\n\nSDK Configuration\n\nConfigure context compaction through the contextCompaction field inside conversationMemory:\n\nField Reference:\n\n| Field | Type | Default | Description |\n| ----------------------- | --------- | ----------------------------------- | ------------","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"","lvl3":""}},
1516
1516
  {"objectID":"90cfbab239ac3c2ab9a05635a2ea40e37ba74b88b1bd0fbeb25d96baf8850f03","title":"📖 Overview","url":"/docs/deployment/configuration#-overview","content":"This guide covers all configuration options for NeuroLink, including AI provider setup, dynamic model configuration, MCP integration, and environment configuration.","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"📖 Overview","lvl3":""}},
1517
1517
  {"objectID":"f6f30eb4527f05b6060bfccddf9a8bd5b4181b61a9da7ffc07d2830fd192cba3","title":"Basic Usage Examples","url":"/docs/deployment/configuration#basic-usage-examples","content":"Basic Usage Examples","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"Basic Usage Examples","lvl3":""}},
1518
1518
  {"objectID":"b37745bbe379147c780ebbf4db0f8aff5f153210084fbf50cfe97719fda1a26c","title":"Environment Variables","url":"/docs/deployment/configuration#environment-variables","content":"NeuroLink supports multiple AI providers. Set up one or more API keys:","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"Environment Variables","lvl3":""}},
@@ -1528,7 +1528,7 @@
1528
1528
  {"objectID":"087c77024205f61c94a0a1b41e99b294bab5e09d35cebf7ca16627fa4aef8e42","title":"Built-in Tools Configuration","url":"/docs/deployment/configuration#built-in-tools-configuration","content":"Built-in tools are automatically available:\n\nTest built-in tools:","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"Built-in Tools Configuration","lvl3":""}},
1529
1529
  {"objectID":"da21f4f3c06e8a8bea102200086ffc6ff163829525522f9dd1a59909fc4f5da5","title":"External MCP Server Configuration","url":"/docs/deployment/configuration#external-mcp-server-configuration","content":"External servers are auto-discovered from all major AI tools:","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"External MCP Server Configuration","lvl3":""}},
1530
1530
  {"objectID":"421585b2783af60c4f06503771128e2041a80ed004f94c7010b310e2e33da0f0","title":"Auto-Discovery Locations","url":"/docs/deployment/configuration#auto-discovery-locations","content":"macOS:\n\nLinux:\n\nWindows:","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"Auto-Discovery Locations","lvl3":""}},
1531
- {"objectID":"4f3054614379dd3e958bab99e580b0bbf5e3f5e47a65e4e90a2026f261010352","title":"Manual MCP Configuration","url":"/docs/deployment/configuration#manual-mcp-configuration","content":"Create .mcp-config.json in your project root:","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"Manual MCP Configuration","lvl3":""}},
1531
+ {"objectID":"4f3054614379dd3e958bab99e580b0bbf5e3f5e47a65e4e90a2026f261010352","title":"Manual MCP Configuration","url":"/docs/deployment/configuration#manual-mcp-configuration","content":"Create .mcp-config.json in your project root:\n\nThe file is loaded only on an explicit decision, because it names commands to run:\nSDK: new NeuroLink({ mcp: { configPath: \"./.mcp-config.json\" } }), or mcp: { trustProjectConfig: true } to load the working directory's file. Nothing is read from the working directory otherwise.\nCLI: the file is discovered, then trusted by hash — interactively with a prompt, or with --trust-mcp-config / NEUROLINK_TRUST_MCP_CONFIG=1; NEUROLINK_TRUST_MCP_CONFIG=0 runs without it. Accepted hashes live in ~/.neurolink/trusted-mcp-configs.json.\n\nPer-server options added for this: inheritParentEnv (stdio; default false — the server gets a minimal environment plus env, use \"env\": { \"X\": \"${X}\" } to pass a variable through) and allowPrivateNetwork (network transports; default false — TLS is required for non-loopback hosts and private addresses are refused). ${VAR} expands in env and args only. See MCP Integration for the full rules.","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"Manual MCP Configuration","lvl3":""}},
1532
1532
  {"objectID":"566284bd138b1bc09e1024c4edc84df965d34d5dc5e793e8cda281bdc8d77fc8","title":"HTTP Transport Configuration","url":"/docs/deployment/configuration#http-transport-configuration","content":"For remote MCP servers, use HTTP transport with authentication, retry, and rate limiting:\n\nHTTP Transport Options:\n\n| Option | Type | Description |\n| -------------- | -------- | --------------------------------------- |\n| transport | \"http\" | Transport type for remote servers |\n| url | string | URL of the remote MCP endpoint |\n| headers | object | HTTP headers for authentication |\n| httpOptions | object | Connection and timeout settings |\n| retryConfig | object | Retry behavior with exponential backoff |\n| rateLimiting | object | Rate limiting configuration |\n\nSee MCP HTTP Transport Guide for complete documentation.","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"HTTP Transport Configuration","lvl3":""}},
1533
1533
  {"objectID":"d45892a46a2ff058618f37f79bc9233458d5d3b6c87f2335abb223331cad30fb","title":"MCP Discovery Commands","url":"/docs/deployment/configuration#mcp-discovery-commands","content":"MCP Discovery Commands","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"MCP Discovery Commands","lvl3":""}},
1534
1534
  {"objectID":"93bea1701d5455e737e5db2c631d37c4b084c11ed958455a1b7f80b1b20d135b","title":"Global CLI Options","url":"/docs/deployment/configuration#global-cli-options","content":"Global CLI Options","hierarchy":{"lvl0":"Deployment","lvl1":"⚙️ NeuroLink Configuration Guide","lvl2":"Global CLI Options","lvl3":""}},
@@ -2110,6 +2110,16 @@
2110
2110
  {"objectID":"84fde65275092423ed37e9dea4196454155bd98e8c44211574a8a22daa835420","title":"Verification","url":"/docs/examples/mcp-tool-blocking-example#verification","content":"Run tests to verify the feature works correctly:","hierarchy":{"lvl0":"Examples","lvl1":"Tool Blocking Feature Example","lvl2":"Verification","lvl3":""}},
2111
2111
  {"objectID":"4063c82ce53cbddddb37aaa3f2c4e6cda3979f7c42245ab87dd1f9b32d952ebf","title":"Notes","url":"/docs/examples/mcp-tool-blocking-example#notes","content":"Blocked tools are filtered during discovery, so they won't appear in the list of available tools\nAttempts to execute blocked tools will throw an error with a clear message\nThe blockedTools array can be empty or omitted if no tools need to be blocked\nTool names are case-sensitive and must match exactly","hierarchy":{"lvl0":"Examples","lvl1":"Tool Blocking Feature Example","lvl2":"Notes","lvl3":""}},
2112
2112
  {"objectID":"5341e63ac43674fa9af2ce7263aeda1cd91585d86e51d5d3a89b1f372e615a1c","title":"Use Cases","url":"/docs/examples/use-cases","content":"This page has moved to Real-World Use Cases.","hierarchy":{"lvl0":"Examples","lvl1":"Use Cases","lvl2":"","lvl3":""}},
2113
+ {"objectID":"d6e807871128e5c589d1c08eb5d56f434341bf65824f1b103b454266e2ef7fc0","title":"Attachment Security","url":"/docs/features/attachment-security","content":"Attachment Security\n\nEvery NeuroLink call that names a file path or a URL — input.files,\ninput.images, input.pdfFiles, rag.files, transcribe({ audio }),\nDirector Mode segment images, the RAG WebLoader — turns that string into\nbytes on the host that runs the SDK. This page describes what the SDK will and\nwill not read on a caller's behalf, how to narrow it, and what changed.\n\nThe policy\n\nOne attachments option on the NeuroLink constructor governs all of those\nloaders. Every field also has an environment variable for deployments that\ncannot change constructor arguments (the CLI, containers); an explicit field\nwins over its variable.\n\n| Field | Environment variable | Default |\n| --------------------- | ---------------------------------------------------------- | ------------------------ |\n| allowedRoots | NEUROLINK_ATTACHMENT_ROOTS (:- or ;-separated paths) | unrestricted, warns once |\n| allowInsecureUrls | NEUROLINK_ATTACHMENT_ALLOW_INSECURE_URLS=1 | false |\n| allowPrivateNetwork | NEUROLINK_ATTACHMENT_ALLOW_PRIVATE_NETWORK=1 | false |\n| followRedirects | NEUROLINK_ATTACHMENT_FOLLOW_REDIRECTS=0 to disable | true |\n| maxBytes | NEUROLINK_ATTACHMENT_MAX_BYTES | each loader's own cap |\n\nURLs\n\nA URL attachment is fetched the way the HTTP server already fetched one before\nthis change: the host is resolved and every address it resolves to is checked\nagainst the private, loopback, link-local, CGNAT, multicast and cloud-metadata\nranges (IPv4 and IPv6, every encoding of an IP literal); the connection is\npinned to exactly those addresses, so a resolver that answers differently for\nthe real request gains nothing; the body is counted as it streams and refused\nthe moment it passes the cap.\nHTTPS only. An http:// URL is refused with a message that names\n attachments.allowInsecureUrls. Plain HTTP is the transport every loopback\n and link-local target answers on, and it carries any credential on the\n request in the clear.\nPublic hosts only. http://127.0.0.1/, https://169.254.169.254/,\n https://10.0.0.5/ and a host name that resolves to any of those are\n refused unless allowPrivateNetwork is set. Even then the connection is\n still pinned.\nRedirects are re-validated per hop. Each Location is checked exactly\n like the first URL, and the caller's headers (authHeaders on a processor)\n are sent to the first host only — a credential meant for one origin is never\n replayed to the one it redirects to. followRedirects: false refuses any\n 3xx outright, which is what the server's own download path does.\nCapped while streaming. transcribe() from a URL, the WebLoader, and\n every image or file URL read at most their loader's cap (or\n attachments.maxBytes, when lower) and stop the transfer there.\n\nA refused URL in input.images is dropped with a warning, as a URL that failed\nto download always was; a refused URL in input.files, rag.files or\ntranscribe({ audio }) fails the call.\n\nLocal paths\n\nA path is resolved to its real location (symlinks followed) and, when\nallowedRoots is set, refused unless that real path is inside one of the\nroots — so a symlink planted under a root cannot reach outside it. The file is\nthen opened O_NOFOLLOW on that real path (a link swapped in after the check\nis refused by the kernel), must be a regular file (no FIFOs, devices or\ndirectories), and is read under the size cap through the same descriptor that\nwas measured, so a file growing under the read is noticed rather than\nbuffered.\n\nWithout roots the SDK reads any file the process can. That is the\npre-existing behaviour, kept for backward compatibility, and the SDK says so\nonce per process:\n\nA host that forwards strings from untrusted callers must set roots. The\nHTTP server's own routes already refuse every path by default; the SDK now\ngives an embedding application the same control. A path outside the roots is\nrefused before the file system is consulted, with the same error for a missing\nfile and a forbidden one, so the refusal is not an oracle for which files\nexist.\n\nTemporary files\n\nAttachments the SDK persists for lazy reading, video frames, Whistle decode\nbuffers and Director Mode clips are written into directories created with\nmkdtemp (mode 0700) as files with mode 0600, and removed on clear() /\npipeline completion or at process exit. The local artifact store uses a\nper-user directory (neurolink-artifacts-<uid>) and refuses one that is a\nsymlink or owned by another user.\n\nArchives and YAML\nA ZIP whose central directory names the same member twice is reported, and\n only the first occurrence is read — the entry the listing described is the\n entry that is opened. With the shipped adm-zip such an archive is refused\n as corrupt.\nA YAML document whose aliases expand far past its own size (a \"billion\n laughs\" file) is parsed as shared references,","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"","lvl3":""}},
2114
+ {"objectID":"b9a64da66b3082fd997d09ec301496b9d788943917d26bbe1feb0ee9982ae22d","title":"Attachment Security","url":"/docs/features/attachment-security#attachment-security","content":"Every NeuroLink call that names a file path or a URL — input.files,\ninput.images, input.pdfFiles, rag.files, transcribe({ audio }),\nDirector Mode segment images, the RAG WebLoader — turns that string into\nbytes on the host that runs the SDK. This page describes what the SDK will and\nwill not read on a caller's behalf, how to narrow it, and what changed.","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"Attachment Security","lvl3":""}},
2115
+ {"objectID":"ddf8c24e247ee17411c89b9a493e811ec24f16764e272df5b41d7adee777de65","title":"The policy","url":"/docs/features/attachment-security#the-policy","content":"One attachments option on the NeuroLink constructor governs all of those\nloaders. Every field also has an environment variable for deployments that\ncannot change constructor arguments (the CLI, containers); an explicit field\nwins over its variable.\n\n| Field | Environment variable | Default |\n| --------------------- | ---------------------------------------------------------- | ------------------------ |\n| allowedRoots | NEUROLINK_ATTACHMENT_ROOTS (:- or ;-separated paths) | unrestricted, warns once |\n| allowInsecureUrls | NEUROLINK_ATTACHMENT_ALLOW_INSECURE_URLS=1 | false |\n| allowPrivateNetwork | NEUROLINK_ATTACHMENT_ALLOW_PRIVATE_NETWORK=1 | false |\n| followRedirects | NEUROLINK_ATTACHMENT_FOLLOW_REDIRECTS=0 to disable | true |\n| maxBytes | NEUROLINK_ATTACHMENT_MAX_BYTES | each loader's own cap |","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"The policy","lvl3":""}},
2116
+ {"objectID":"0098677d9fb7b5a9c0afd30a2c475c3f765b211923cbb527cbe90e283ccc7b73","title":"URLs","url":"/docs/features/attachment-security#urls","content":"A URL attachment is fetched the way the HTTP server already fetched one before\nthis change: the host is resolved and every address it resolves to is checked\nagainst the private, loopback, link-local, CGNAT, multicast and cloud-metadata\nranges (IPv4 and IPv6, every encoding of an IP literal); the connection is\npinned to exactly those addresses, so a resolver that answers differently for\nthe real request gains nothing; the body is counted as it streams and refused\nthe moment it passes the cap.\nHTTPS only. An http:// URL is refused with a message that names\n attachments.allowInsecureUrls. Plain HTTP is the transport every loopback\n and link-local target answers on, and it carries any credential on the\n request in the clear.\nPublic hosts only. http://127.0.0.1/, https://169.254.169.254/,\n https://10.0.0.5/ and a host name that resolves to any of those are\n refused unless allowPrivateNetwork is set. Even then the connection is\n still pinned.\nRedirects are re-validated per hop. Each Location is checked exactly\n like the first URL, and the caller's headers (authHeaders on a processor)\n are sent to the first host only — a credential meant for one origin is never\n replayed to the one it redirects to. followRedirects: false refuses any\n 3xx outright, which is what the server's own download path does.\nCapped while streaming. transcribe() from a URL, the WebLoader, and\n every image or file URL read at most their loader's cap (or\n attachments.maxBytes, when lower) and stop the transfer there.\n\nA refused URL in input.images is dropped with a warning, as a URL that failed\nto download always was; a refused URL in input.files, rag.files or\ntranscribe({ audio }) fails the call.","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"URLs","lvl3":""}},
2117
+ {"objectID":"e1244620fcf363c8d55bfa75bf9b26b01a7612f084595f4ce44e3c6634eca8a7","title":"Local paths","url":"/docs/features/attachment-security#local-paths","content":"A path is resolved to its real location (symlinks followed) and, when\nallowedRoots is set, refused unless that real path is inside one of the\nroots — so a symlink planted under a root cannot reach outside it. The file is\nthen opened O_NOFOLLOW on that real path (a link swapped in after the check\nis refused by the kernel), must be a regular file (no FIFOs, devices or\ndirectories), and is read under the size cap through the same descriptor that\nwas measured, so a file growing under the read is noticed rather than\nbuffered.\n\nWithout roots the SDK reads any file the process can. That is the\npre-existing behaviour, kept for backward compatibility, and the SDK says so\nonce per process:\n\nA host that forwards strings from untrusted callers must set roots. The\nHTTP server's own routes already refuse every path by default; the SDK now\ngives an embedding application the same control. A path outside the roots is\nrefused before the file system is consulted, with the same error for a missing\nfile and a forbidden one, so the refusal is not an oracle for which files\nexist.","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"Local paths","lvl3":""}},
2118
+ {"objectID":"eac3557771085ccc1dae3b8ca94846ac0ab93f02deb339bd2258aee6b5c73c51","title":"Temporary files","url":"/docs/features/attachment-security#temporary-files","content":"Attachments the SDK persists for lazy reading, video frames, Whistle decode\nbuffers and Director Mode clips are written into directories created with\nmkdtemp (mode 0700) as files with mode 0600, and removed on clear() /\npipeline completion or at process exit. The local artifact store uses a\nper-user directory (neurolink-artifacts-<uid>) and refuses one that is a\nsymlink or owned by another user.","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"Temporary files","lvl3":""}},
2119
+ {"objectID":"f4db56fdfca5beabc968d745f589bbb12690b0530b3584da217b706aa4abc5dd","title":"Archives and YAML","url":"/docs/features/attachment-security#archives-and-yaml","content":"A ZIP whose central directory names the same member twice is reported, and\n only the first occurrence is read — the entry the listing described is the\n entry that is opened. With the shipped adm-zip such an archive is refused\n as corrupt.\nA YAML document whose aliases expand far past its own size (a \"billion\n laughs\" file) is parsed as shared references, and its asJson rendering is\n bounded at the processor's byte limit: above it asJson is null and a\n warning says why, instead of the expansion being materialised.","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"Archives and YAML","lvl3":""}},
2120
+ {"objectID":"e8a3980979b43fb1f44642b3e7f105503e08d7cdad5c76b62e779902b0ff09e9","title":"ffmpeg","url":"/docs/features/attachment-security#ffmpeg","content":"Every ffmpeg and ffprobe invocation the SDK makes passes\n-nostdin -protocol_whitelist file,crypto,data for its inputs, so a container\nor playlist that references another URL or file cannot make the decoder fetch\nit, whatever the installed build's defaults are. A caller-supplied file name\ncontributes a temp-file suffix only when it is a known video extension, and a\nframe or subtitle extraction that times out kills the child instead of\nabandoning it.","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"ffmpeg","lvl3":""}},
2121
+ {"objectID":"8a3980a07b6f204b1e61d9fed938bdce48ba4504e3bddf487f298156d7a28647","title":"Breaking changes","url":"/docs/features/attachment-security#breaking-changes","content":"These defaults changed; each has an explicit switch.\n\n| Before | Now | Switch |\n| --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |\n| http:// URLs in input.images, input.files, transcribe, WebLoader were fetched | refused | attachments.allowInsecureUrls / NEUROLINK_ATTACHMENT_ALLOW_INSECURE_URLS=1 |\n| URLs on private, loopback or link-local hosts were fetched | refused | attachments.allowPrivateNetwork / NEUROLINK_ATTACHMENT_ALLOW_PRIVATE_NETWORK=1 |\n| Redirects were followed to any target with the caller's headers | followed only to a target the policy allows, caller headers dropped per hop | attachments.followRedirects: false refuses them altogether |\n| A local path was read silently | still read, but a one-time warning names attachments.allowedRoots | set allowedRoots to make the warning go away and the boundary real |\n| Redis session/user ids were used as given | ids containing : * ?","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"Breaking changes","lvl3":""}},
2122
+ {"objectID":"00a0620803ebc404ec51491e5de95e7a2b502f5a31efa08c604f5107b57b7949","title":"See also","url":"/docs/features/attachment-security#see-also","content":"Multimodal input — images, PDFs, CSV, video\nTranscribe — transcribe({ audio }) from a path or URL\nRAG — rag.files and the WebLoader\nVideo Director Mode — segment images\nEnvironment variables","hierarchy":{"lvl0":"Features","lvl1":"Attachment Security","lvl2":"See also","lvl3":""}},
2113
2123
  {"objectID":"663b4543baa0f126dd73ee25ad1e8111b108f06eec1f22e84f8cc195c99b00e8","title":"Audio Input & Transcription Guide","url":"/docs/features/audio-input","content":"Audio Input & Voice Conversations Guide\n\nNeuroLink provides comprehensive audio input capabilities, enabling real-time voice conversations with AI models. This guide covers currently available features, audio specifications, and upcoming enhancements.\n\nOverview\n\nCurrently Available\n\nNeuroLink supports the following audio capabilities today:\nReal-time voice conversations via Gemini Live (Google AI Studio)\nText-to-Speech (TTS) output via Google Cloud TTS, OpenAI TTS, ElevenLabs, and Azure TTS\nSpeech-to-Text (STT) via generate() and stream() options (Whisper/OpenAI STT, Google STT, Deepgram, Azure STT, ElevenLabs Scribe)\nWebSocket-based voice streaming for web applications\nBidirectional audio - speak and hear AI responses in real-time\n\nPlanned\n\nThe following features are planned for future releases:\nCLI commands: neurolink audio transcribe, neurolink audio analyze, neurolink audio summarize\nCLI commands: neurolink voice chat, neurolink voice demo\nCross-provider audio support (Anthropic, AWS Transcribe still planned)\nFile-based audio input processing\n\nProvider Support Matrix\n\n| Provider | Real-time Voice | TTS Output | Audio Transcription | Status |\n| -------------------- | --------------- | ---------- | ---------------------------- | ---------------- |\n| Google AI Studio | Yes | Yes | Yes (via Google STT) | Production Ready |\n| Google Vertex AI | Planned | Yes | Yes (via Google STT) | Available |\n| OpenAI | Planned | Yes | Yes (via Whisper/OpenAI STT) | Available |\n| Deepgram | Planned | No | Yes (speaker labels) | Available |\n| Azure | Planned | Yes | Yes (via Azure STT) | Available |\n| ElevenLabs | No | Yes | Yes (Scribe, speaker labels) | Available |\n| Self-hosted | No | No | Yes (OpenAI-compatible) | Available |\n| Anthropic | Planned | Planned | Planned | Planned |\n| AWS Bedrock | Planned | Planned | Planned | Planned |\n\nSupported Model for Real-time Voice:\n\n| Model | Provider | Capabilities |\n| ---------------------------------------------- | --------- | -------------------------------- |\n| gemini-2.5-flash-preview-native-audio-dialog | Google AI | Bidirectional audio, low latency |\n\nQuick Start: Real-Time Voice (SDK)\n\nReal-time voice conversations are available through the SDK using Gemini Live's native audio dialog model.\n\nPrerequisites\n\nBasic Real-time Voice Streaming\n\nComplete Voice Session Example\n\nQuick Start: TTS Integration\n\nNeuroLink provides Text-to-Speech output via Google Cloud TTS. TTS can be combined with any text generation.\n\nCLI Usage\n\nSDK Usage\n\nFor comprehensive TTS documentation, see the TTS Integration Guide.\n\nVoice Demo Example\n\nNeuroLink includes a complete voice demo application demonstrating real-time bidirectional audio conversations.\n\nLocation\n\nRunning the Demo\n\nThe demo will:\nStart a WebSocket server on port 5175 (or next available port)\nOpen your browser automatically to the demo interface\nAllow you to speak and receive real-time AI audio responses\n\nDemo Architecture\n\nKey Code from Voice Demo Server\n\nSpeaker Labels (Diarization)\n\nAsk for speaker labels with speakerDiarization: true (the documented alias\ndiarization: true works too). Providers that diarize: deepgram,\ngoogle-stt, elevenlabs-stt (Scribe), and any OpenAI-compatible endpoint\nthat labels its segments (see the next section). Whatever the provider,\nthe result has the same shape:\nsegments[] is a list of speaker turns: consecutive words from one\n speaker, with speaker, startTime, endTime and text.\nspeakers[] lists the distinct labels in order of first appearance.\nProviders that label words rather than segments (Deepgram, Google, Scribe)\n have their turns derived by STTProcessor, so callers never see the\n per-provider difference. A provider that returns its own speaker-labelled\n segments (the diarization sidecar) is passed through untouched.\nCLI: neurolink generate --stt --input-audio meeting.wav --stt-provider elevenlabs-stt --stt-diarize.\n\nElevenLabs Scribe (elevenlabs-stt, alias scribe) shares\nELEVENLABS_API_KEY with the TTS handler. It detects the language itself,\ntranscribes code-switched speech (Hinglish comes back romanized unless a\nlanguage: \"hi\" hint asks for Devanagari), and accepts audio or video\ncontainers. Options: model (scribe_v2 default), tagAudioEvents.\n\nSelf-hosted STT (OpenAI-compatible endpoints)\n\nThe whisper handler talks to any server that implements OpenAI's\n/audio/transcriptions — vLLM serving an ASR model such as Qwen3-ASR,\nLiteLLM, or NeuroLink's diarization sidecar (NVIDIA Nemotron-3 diarization in\nfront of a local ASR). Point it at the server and pass the model name per\n","hierarchy":{"lvl0":"Features","lvl1":"Audio Input & Transcription Guide","lvl2":"","lvl3":""}},
2114
2124
  {"objectID":"a32f77567943264cd3a10e47531543e59494110d83eacb73e06c777b325a954d","title":"Audio Input & Voice Conversations Guide","url":"/docs/features/audio-input#audio-input-voice-conversations-guide","content":"NeuroLink provides comprehensive audio input capabilities, enabling real-time voice conversations with AI models. This guide covers currently available features, audio specifications, and upcoming enhancements.","hierarchy":{"lvl0":"Features","lvl1":"Audio Input & Transcription Guide","lvl2":"Audio Input & Voice Conversations Guide","lvl3":""}},
2115
2125
  {"objectID":"e6130b0676f57a7cf79b67937961a503147a86874d2071c61df0cd0c5983606b","title":"Currently Available","url":"/docs/features/audio-input#currently-available","content":"NeuroLink supports the following audio capabilities today:\nReal-time voice conversations via Gemini Live (Google AI Studio)\nText-to-Speech (TTS) output via Google Cloud TTS, OpenAI TTS, ElevenLabs, and Azure TTS\nSpeech-to-Text (STT) via generate() and stream() options (Whisper/OpenAI STT, Google STT, Deepgram, Azure STT, ElevenLabs Scribe)\nWebSocket-based voice streaming for web applications\nBidirectional audio - speak and hear AI responses in real-time","hierarchy":{"lvl0":"Features","lvl1":"Audio Input & Transcription Guide","lvl2":"Currently Available","lvl3":""}},
@@ -2307,9 +2317,9 @@
2307
2317
  {"objectID":"04b61535b4fe39e3d24af410e19cec85df5b54fb62d12c6ae2f452247e8db4e4","title":"WHY tools are passed through in translation/fallback mode","url":"/docs/features/claude-proxy-architecture#why-tools-are-passed-through-in-translationfallback-mode","content":"When falling back to non-Anthropic providers, the proxy passes tools, thinking configuration, and conversation history through to ctx.neurolink.stream() with maxSteps: 1. This enables fallback providers to see the full request context and produce tool_use blocks if supported. The maxSteps: 1 limit prevents the proxy from running a multi-step agent loop (that is Claude Code's responsibility). Tool schemas are wrapped via NeuroLink's own jsonSchema() (src/lib/utils/tool.ts) to ensure compatibility across providers.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Architecture","lvl2":"WHY tools are passed through in translation/fallback mode","lvl3":""}},
2308
2318
  {"objectID":"cfac0f01939a0812ed5ff75837d6e7286a42e4c114a44c9f52de883bc8c047ab","title":"9. Component Diagram","url":"/docs/features/claude-proxy-architecture#9-component-diagram","content":"9. Component Diagram","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Architecture","lvl2":"9. Component Diagram","lvl3":""}},
2309
2319
  {"objectID":"e3ebba28416413ba267b0cad0694e78604986e455f3132b895229ca150c99da2","title":"10. File Reference","url":"/docs/features/claude-proxy-architecture#10-file-reference","content":"| File | Lines | Purpose |\n| -------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| src/cli/commands/proxy.ts | ~varies | CLI commands: proxy start, proxy status, proxy telemetry, proxy guard, proxy setup, proxy install, proxy uninstall |\n| src/lib/server/routes/claudeProxyRoutes.ts | ~1047 | Route handlers: /v1/messages, /v1/models, /v1/messages/count_tokens |\n| src/lib/proxy/oauthFetch.ts | ~383 | OAuth fetch wrapper with cloaking (passthrough + direct modes) |\n| src/lib/proxy/modelRouter.ts | ~57 | Model name resolution and fallback chain |\n| src/lib/proxy/claudeFormat.ts | ~varies | Claude API format parser, response serializer, SSE state machine |\n| src/lib/proxy/requestLogger.ts | ~varies | Request summaries, attempt logs, OTLP log export, debug logging, and log rotation |\n| src/lib/proxy/rawStreamCapture.ts | ~varies | Lossless raw stream capture for debugging streaming request/response IO |\n| src/lib/proxy/accountQuota.ts | ~110 | Quota header parsing (unified-5h, unified-7d) and persistence |\n| src/lib/proxy/usageStats.ts | ~60+ | In-memory per-account usage statistics","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Architecture","lvl2":"10. File Reference","lvl3":""}},
2310
- {"objectID":"61389ed610d3010d1b99ac4e092b370b182af665bf73011c8897d5863c2d27a8","title":"Claude Proxy Configuration Reference","url":"/docs/features/claude-proxy-config-reference","content":"Claude Proxy Configuration Reference\n\nThis document is the authoritative reference for every configurable aspect of the NeuroLink Claude proxy. It covers CLI flags, the YAML config file schema, environment variables, auto-configured Claude Code settings, and all file locations.\nCLI Flags\n\nneurolink proxy start\n\nStart the Claude multi-account proxy server.\n\n| Flag | Alias | Type | Default | Description |\n| ------------------- | ----- | --------- | -------------------------------- | ----------------------------------------------------------------- |\n| --port | -p | number | 55669 | Port to listen on. |\n| --share-port | | number | --port + 1 | Gate-only listener port for peer sharing (see below). |\n| --host | -H | string | 127.0.0.1 | Host/IP to bind to. Use 0.0.0.0 to listen on all interfaces. |\n| --strategy | -s | string | fill-first | Account selection strategy. Choices: fill-first, round-robin. |\n| --health-interval | | number | 30 | Health check interval in seconds. |\n| --quiet | -q | boolean | false | Suppress non-essential output (banner, status messages). |\n| --debug | -d | boolean | false | Enable debug output (stack traces on errors, verbose logging). |\n| --config | -c | string | ~/.neurolink/proxy-config.yaml | Path to proxy config file (YAML or JSON). |\n| --env-file | | string | | Path to .env file for provider API keys (overrides cwd .env). |\n| --passthrough | | boolean | false | Transparent forwarding: no retry, rotation, or polyfill. |\n\nExamples:\n\nThe share listener\n\nproxy start runs a second, gate-only listener whenever this node has at\nleast one active share grant. It serves the same routes on a different port and\nrefuses every request that carries no valid share token; the main port keeps\nserving the operator's own untokened client exactly as before.\n\nWhich port a request arrived on is decided by the accepting socket, so nothing a\nclient sends can move it across. That is the reason for a second port rather\nthan an origin check: cloudflared and every reverse proxy connect from\n127.0.0.1, so tunnelled traffic is indistinguishable from local traffic by\naddress alone.\n\n| Behaviour | Detail |\n| ------------------- | ------------------------------------------------------------------------------------------------ |\n| Port | --share-port, else NEUROLINK_PROXY_SHARE_PORT, else main port + 1 |\n| Lifecycle | Comes up on the first active grant, closes when the last is revoked — no restart on either edge |\n| Poll interval | 15s against the grant file |\n| Bind failure | Logged once and retried; never fatal. Set --share-port to move it |\n| Rolling replacement | The incoming worker loses the bind until the outgoing one drains, then takes it on the next poll |\n| Disable | NEUROLINK_PROXY_SHARE_LISTENER=0 |\n\nneurolink proxy expose picks this port automatically. Expose it, not the main\none.\n\nneurolink proxy status\n\nShow the current proxy status.\n\n| Flag | Alias | Type | Default | Description |\n| ---------- | ----- | --------- | ------- | --------------------------------------- |\n| --format | | string | text | Output format. Choices: text, json. |\n| --quiet | -q | boolean | false | Suppress non-essential output. |\n\nExamples:\n\nJSON output shape (when --format json):\n\ntotalRequests, totalSuccess, and totalErrors are final request outcomes.\ntotalAttempts, totalAttemptErrors, and the rate-limit counters describe\nupstream attempts, including retries that later recovered. Per-account\nrequests, success, and errors use the same final-outcome semantics;\nattemptErrors and the rate-limit fields remain attempt-level diagnostics.\n\nneurolink proxy telemetry <action>\n\nManage the repo-owned local OpenObserve stack and the maintained proxy dashboard.\n\n| Action | Description |\n| ------------------ | ----------------------------------------------------------------------- |\n| setup | Start OpenObserve + OTEL collector and import the maintained dashboard |\n| start | Start the local tele","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"","lvl3":""}},
2320
+ {"objectID":"61389ed610d3010d1b99ac4e092b370b182af665bf73011c8897d5863c2d27a8","title":"Claude Proxy Configuration Reference","url":"/docs/features/claude-proxy-config-reference","content":"Claude Proxy Configuration Reference\n\nThis document is the authoritative reference for every configurable aspect of the NeuroLink Claude proxy. It covers CLI flags, the YAML config file schema, environment variables, auto-configured Claude Code settings, and all file locations.\nCLI Flags\n\nneurolink proxy start\n\nStart the Claude multi-account proxy server.\n\n| Flag | Alias | Type | Default | Description |\n| ------------------------- | ----- | --------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |\n| --port | -p | number | 55669 | Port to listen on. |\n| --share-port | | number | --port + 1 | Gate-only listener port for peer sharing (see below). |\n| --host | -H | string | 127.0.0.1 | Host/IP to bind to. A non-loopback host is refused unless --inbound-token, NEUROLINK_PROXY_REQUIRE_GRANT=1 or --allow-unauthenticated is set. |\n| --inbound-token | | string | | Bearer every caller must present (x-neurolink-inbound-token or Authorization: Bearer). Also NEUROLINK_PROXY_INBOUND_TOKEN. |\n| --allow-unauthenticated | | boolean | false | Start a non-loopback listener with no inbound authentication; logs a warning. |\n| --strategy | -s | string | fill-first | Account selection strategy. Choices: fill-first, round-robin. |\n| --health-interval | | number | 30 | Health check interval in seconds. |\n| --quiet | -q | boolean | false | Suppress non-essential output (banner, status messages). |\n| --debug | -d | boolean | false | Enable debug output (stack traces on errors, verbose logging). |\n| --config | -c | string | ~/.neurolink/proxy-config.yaml | Path to proxy config file (YAML or JSON). |\n| --env-file | | string | | Path to .env file for provider API keys (overrides cwd .env). |\n| --passthrough | | boolean | false | Transparent forwarding: no retry, rotation, or polyfill. |\n\nExamples:\n\nThe share listener\n\nproxy start runs a second, gate-only listener whenever this node has at\nleast one active share grant. It serves the same routes on a different port and\nrefuses every request that carries no valid share token; the main port keeps\nserving the operator's own untokened client exactly as before.\n\nWhich port a request arrived on is decided by the accepting socket, so nothing a\nclient sends can move it across. That is the reason for a second port rather\nthan an origin check: cloudflared and every reverse proxy connect from\n127.0.0.1, so tunnelled traffic is indistinguishable from local traffic by\naddress alone.\n\n| Behaviour | Detail |\n| ------------------- | ------------------------------------------------------------------------------------------------ |\n| Port | --share-port, else NEUROLINK_PROXY_SHARE_PORT, else main port + 1 |\n| Lifecycle | Comes up on the first active grant, closes when the last is revoked — no restart on either edge |\n| Poll interval | 15s against the grant file |\n| Bind failure | Logged once and retried; never fatal. Set --share-port to move it |\n| Rolling replacement | The incoming worker loses the bind until the o","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"","lvl3":""}},
2311
2321
  {"objectID":"6a4c636d21d7795603066528f7ff242a95d59a66409ee0a0ef365357d5083a17","title":"Claude Proxy Configuration Reference","url":"/docs/features/claude-proxy-config-reference#claude-proxy-configuration-reference","content":"This document is the authoritative reference for every configurable aspect of the NeuroLink Claude proxy. It covers CLI flags, the YAML config file schema, environment variables, auto-configured Claude Code settings, and all file locations.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"Claude Proxy Configuration Reference","lvl3":""}},
2312
- {"objectID":"49b5fc78bcd03f37a7f9aa37e2e61250f2bbd2a5f90153b78338bf8742fdc635","title":"neurolink proxy start","url":"/docs/features/claude-proxy-config-reference#neurolink-proxy-start","content":"Start the Claude multi-account proxy server.\n\n| Flag | Alias | Type | Default | Description |\n| ------------------- | ----- | --------- | -------------------------------- | ----------------------------------------------------------------- |\n| --port | -p | number | 55669 | Port to listen on. |\n| --share-port | | number | --port + 1 | Gate-only listener port for peer sharing (see below). |\n| --host | -H | string | 127.0.0.1 | Host/IP to bind to. Use 0.0.0.0 to listen on all interfaces. |\n| --strategy | -s | string | fill-first | Account selection strategy. Choices: fill-first, round-robin. |\n| --health-interval | | number | 30 | Health check interval in seconds. |\n| --quiet | -q | boolean | false | Suppress non-essential output (banner, status messages). |\n| --debug | -d | boolean | false | Enable debug output (stack traces on errors, verbose logging). |\n| --config | -c | string | ~/.neurolink/proxy-config.yaml | Path to proxy config file (YAML or JSON). |\n| --env-file | | string | | Path to .env file for provider API keys (overrides cwd .env). |\n| --passthrough | | boolean | false | Transparent forwarding: no retry, rotation, or polyfill. |\n\nExamples:","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink proxy start","lvl3":""}},
2322
+ {"objectID":"49b5fc78bcd03f37a7f9aa37e2e61250f2bbd2a5f90153b78338bf8742fdc635","title":"neurolink proxy start","url":"/docs/features/claude-proxy-config-reference#neurolink-proxy-start","content":"Start the Claude multi-account proxy server.\n\n| Flag | Alias | Type | Default | Description |\n| ------------------------- | ----- | --------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |\n| --port | -p | number | 55669 | Port to listen on. |\n| --share-port | | number | --port + 1 | Gate-only listener port for peer sharing (see below). |\n| --host | -H | string | 127.0.0.1 | Host/IP to bind to. A non-loopback host is refused unless --inbound-token, NEUROLINK_PROXY_REQUIRE_GRANT=1 or --allow-unauthenticated is set. |\n| --inbound-token | | string | | Bearer every caller must present (x-neurolink-inbound-token or Authorization: Bearer). Also NEUROLINK_PROXY_INBOUND_TOKEN. |\n| --allow-unauthenticated | | boolean | false | Start a non-loopback listener with no inbound authentication; logs a warning. |\n| --strategy | -s | string | fill-first | Account selection strategy. Choices: fill-first, round-robin. |\n| --health-interval | | number | 30 | Health check interval in seconds.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink proxy start","lvl3":""}},
2313
2323
  {"objectID":"2f25895b1320d50e243cdb29c07f1671dd22bf0261de75b56416a482404ea5aa","title":"The share listener","url":"/docs/features/claude-proxy-config-reference#the-share-listener","content":"proxy start runs a second, gate-only listener whenever this node has at\nleast one active share grant. It serves the same routes on a different port and\nrefuses every request that carries no valid share token; the main port keeps\nserving the operator's own untokened client exactly as before.\n\nWhich port a request arrived on is decided by the accepting socket, so nothing a\nclient sends can move it across. That is the reason for a second port rather\nthan an origin check: cloudflared and every reverse proxy connect from\n127.0.0.1, so tunnelled traffic is indistinguishable from local traffic by\naddress alone.\n\n| Behaviour | Detail |\n| ------------------- | ------------------------------------------------------------------------------------------------ |\n| Port | --share-port, else NEUROLINK_PROXY_SHARE_PORT, else main port + 1 |\n| Lifecycle | Comes up on the first active grant, closes when the last is revoked — no restart on either edge |\n| Poll interval | 15s against the grant file |\n| Bind failure | Logged once and retried; never fatal. Set --share-port to move it |\n| Rolling replacement | The incoming worker loses the bind until the outgoing one drains, then takes it on the next poll |\n| Disable | NEUROLINK_PROXY_SHARE_LISTENER=0 |\n\nneurolink proxy expose picks this port automatically. Expose it, not the main\none.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"The share listener","lvl3":""}},
2314
2324
  {"objectID":"9f6608448998e23c21c4073a4b756a159680bd070acb2f4378b3ec28e717b1e6","title":"neurolink proxy status","url":"/docs/features/claude-proxy-config-reference#neurolink-proxy-status","content":"Show the current proxy status.\n\n| Flag | Alias | Type | Default | Description |\n| ---------- | ----- | --------- | ------- | --------------------------------------- |\n| --format | | string | text | Output format. Choices: text, json. |\n| --quiet | -q | boolean | false | Suppress non-essential output. |\n\nExamples:\n\nJSON output shape (when --format json):\n\ntotalRequests, totalSuccess, and totalErrors are final request outcomes.\ntotalAttempts, totalAttemptErrors, and the rate-limit counters describe\nupstream attempts, including retries that later recovered. Per-account\nrequests, success, and errors use the same final-outcome semantics;\nattemptErrors and the rate-limit fields remain attempt-level diagnostics.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink proxy status","lvl3":""}},
2315
2325
  {"objectID":"772a5388b7abc6e473a3f01d237478194d75d130e3d258e8b53ec27ea899e1f7","title":"neurolink proxy telemetry <action>","url":"/docs/features/claude-proxy-config-reference#neurolink-proxy-telemetry-action","content":"Manage the repo-owned local OpenObserve stack and the maintained proxy dashboard.\n\n| Action | Description |\n| ------------------ | ----------------------------------------------------------------------- |\n| setup | Start OpenObserve + OTEL collector and import the maintained dashboard |\n| start | Start the local telemetry stack without re-importing the dashboard |\n| stop | Stop the local telemetry stack |\n| status | Show local stack health and endpoint info |\n| logs | Follow OpenObserve and collector logs |\n| import-dashboard | Re-import the dashboard and dedupe older dashboards with the same title |\n\n| Flag | Alias | Type | Default | Description |\n| --------- | ----- | --------- | ------- | ------------------------------------------------- |\n| --quiet | -q | boolean | false | Suppress the local CLI spinner before delegating. |\n\nExamples:","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink proxy telemetry <action>","lvl3":""}},
@@ -2319,7 +2329,7 @@
2319
2329
  {"objectID":"cb1ebdb6de260e7c03f71a1f8e4525587db4d8b56e0bd123dc022028e05de68f","title":"neurolink proxy uninstall","url":"/docs/features/claude-proxy-config-reference#neurolink-proxy-uninstall","content":"Remove the proxy launchd background service. Unloads the service and deletes the plist file. Currently macOS-only.\n\nNo flags.\n\nExamples:","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink proxy uninstall","lvl3":""}},
2320
2330
  {"objectID":"1f9d835838d2248f601e80dc6cc4dd573956d914d45f2ad6b119df62cb479e6a","title":"neurolink auth cleanup","url":"/docs/features/claude-proxy-config-reference#neurolink-auth-cleanup","content":"Remove expired and disabled accounts from the token store.\n\n| Flag | Type | Default | Description |\n| --------- | --------- | ------- | -------------------------------------------------- |\n| --force | boolean | false | Skip confirmation when removing disabled accounts. |\n\nExamples:\n\nWhat it does:\nPrunes expired entries that have no refresh token.\nFinds permanently disabled entries (e.g., accounts that failed refresh).\nPrompts for confirmation before removing disabled accounts (unless --force).","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink auth cleanup","lvl3":""}},
2321
2331
  {"objectID":"ea946092508d02f41e596c51ea168d042419fdf95bc0dd5b4241788eedcee4aa","title":"neurolink auth enable","url":"/docs/features/claude-proxy-config-reference#neurolink-auth-enable","content":"Re-enable a previously disabled account so it can be used by the proxy pool again.\n\n| Argument | Type | Required | Description |\n| ----------- | -------- | -------- | ----------------------------------------------------- |\n| <account> | string | Yes | Account key to re-enable (e.g., anthropic:1-VjRIq). |\n\nExamples:\n\nRun neurolink auth list to see all accounts and their current status.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink auth enable","lvl3":""}},
2322
- {"objectID":"08657049d3a419bf68a12583396f7347eab685dc22e0d86603d27fbd0a94b96a","title":"neurolink auth set-primary","url":"/docs/features/claude-proxy-config-reference#neurolink-auth-set-primary","content":"Designate the proxy's primary (home) Anthropic account by email/label. Writes routing.primary-account to the proxy config YAML; a running proxy watching that exact file applies it automatically. With quota routing enabled (the default), primary is the ranking's final tiebreaker, not tried first, unless routing.prefer-primary is also set; it is tried first unconditionally only when quota routing is disabled, and under round-robin it is used as the home reference. Does not touch the encrypted token store and does not require re-OAuthing any account.\n\n| Argument | Type | Required | Description |\n| ---------- | -------- | -------- | ------------------------------------------------------------------------- |\n| <email> | string | Yes | Email/label of the Anthropic account to make primary. |\n| --config | string | No | Path to the proxy config file. Default: ~/.neurolink/proxy-config.yaml. |\n\nIf the email is not currently authenticated in the token store, the command still writes the field and prints a warning — the setting activates automatically once the account is added via auth login --add. For a running proxy, the command reports whether it watches the edited path, watches a different path, or predates hot-reload support.\n\nExamples:\n\nNote: writing YAML uses js-yaml.dump, which does not preserve comments. The command prints a warning before writing if the existing file contains comments. JSON config paths preserve everything except whitespace.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink auth set-primary","lvl3":""}},
2332
+ {"objectID":"08657049d3a419bf68a12583396f7347eab685dc22e0d86603d27fbd0a94b96a","title":"neurolink auth set-primary","url":"/docs/features/claude-proxy-config-reference#neurolink-auth-set-primary","content":"Designate the proxy's primary (home) Anthropic account by email/label. Writes routing.primary-account to the proxy config YAML; a running proxy watching that exact file applies it automatically. With quota routing enabled (the default), primary is the ranking's final tiebreaker, not tried first, unless routing.prefer-primary is also set; it is tried first unconditionally only when quota routing is disabled, and under round-robin it is used as the home reference. Does not touch the token store and does not require re-OAuthing any account.\n\n| Argument | Type | Required | Description |\n| ---------- | -------- | -------- | ------------------------------------------------------------------------- |\n| <email> | string | Yes | Email/label of the Anthropic account to make primary. |\n| --config | string | No | Path to the proxy config file. Default: ~/.neurolink/proxy-config.yaml. |\n\nIf the email is not currently authenticated in the token store, the command still writes the field and prints a warning — the setting activates automatically once the account is added via auth login --add. For a running proxy, the command reports whether it watches the edited path, watches a different path, or predates hot-reload support.\n\nExamples:\n\nNote: writing YAML uses js-yaml.dump, which does not preserve comments. The command prints a warning before writing if the existing file contains comments. JSON config paths preserve everything except whitespace.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink auth set-primary","lvl3":""}},
2323
2333
  {"objectID":"ede954ac1558ac03b0cd45df1b8a7652faab4725e387db2d0b9c24953e547a2b","title":"neurolink auth get-primary","url":"/docs/features/claude-proxy-config-reference#neurolink-auth-get-primary","content":"Show the proxy's currently configured primary account (and whether it is authenticated).\n\n| Argument | Type | Required | Description |\n| ---------- | -------- | -------- | ------------------------------------------------------------------------- |\n| --config | string | No | Path to the proxy config file. Default: ~/.neurolink/proxy-config.yaml. |\n\nExamples:\n\nOutput (when configured and authenticated):","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink auth get-primary","lvl3":""}},
2324
2334
  {"objectID":"31f976c4b2a0439660e54912877f41666002fdccfd62f9ec98275e19bd00a59b","title":"neurolink auth clear-primary","url":"/docs/features/claude-proxy-config-reference#neurolink-auth-clear-primary","content":"Remove routing.primary-account (and routing.primaryAccount) from the proxy config. A running proxy watching that file reverts to insertion-order fallback on its next valid configuration generation.\n\n| Argument | Type | Required | Description |\n| ---------- | -------- | -------- | ------------------------------------------------------------------------- |\n| --config | string | No | Path to the proxy config file. Default: ~/.neurolink/proxy-config.yaml. |\n\nExamples:\n\nIdempotent — clearing when no primary is configured prints No primary account was configured. and exits 0.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink auth clear-primary","lvl3":""}},
2325
2335
  {"objectID":"239c4644a6d6e9f2f9baf3a80814e68460e8a287e4a66f9348d51413ca4b0aba","title":"neurolink proxy share <action>","url":"/docs/features/claude-proxy-config-reference#neurolink-proxy-share-action","content":"Lender-side controls for peer sharing. Conceptual documentation lives in\nProxy peer sharing; this is the flag\nreference. Actions: create, provision, url, list, status, pause,\nresume, revoke, topup, set, link, rotate, level, note, notes,\nreceipts, delete.\n\n| Argument | Type | Description |\n| ------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| --peer | string | Borrower label, or a grant id. Required by everything but list, status, url, note and notes — the coin-note actions are issued against the node, not a peer. |\n| --preset | string | spare (default), spillover, metered, open. Fills the gate set; every field stays overridable by an explicit flag. |\n| --level | string | live (default) or complete. |\n| --ledger | string | coins or unlimited. Implied coins when --coins is given. |\n| --coins | number | Starting balance for a metered grant. With topup, the amount to add; with set, the absolute balance. |\n| --refill | string | Standing allowance, e.g. 100/week or 50/session. Applied at the first borrowed request after the period elapses, not on a timer. |\n| --max-slice | string | Ceiling as a percent of the pool: 20, or 5h=20,7d=15.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"neurolink proxy share <action>","lvl3":""}},
@@ -2337,7 +2347,7 @@
2337
2347
  {"objectID":"d9b034b736d0076ac98c315f8227b06382eafb161166a630a350add28c818ee6","title":"Cloaking Fields","url":"/docs/features/claude-proxy-config-reference#cloaking-fields","content":"| Field | Type | Default | Description |\n| -------------------------------- | ------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------ |\n| mode | \"auto\" \\| \"always\" \\| \"never\" | \"auto\" | auto applies cloaking only to OAuth accounts. always applies to all. never disables all plugins. |\n| plugins.headerScrubber | boolean | false | Strip proxy-revealing headers (x-forwarded-for, via, sec-ch-\\*, etc.). |\n| plugins.sessionIdentity | boolean | false | Generate consistent user_id/session_id per account with 1-hour TTL. |\n| plugins.systemPromptInjector | boolean | false | Inject Claude Code session context (IDE metadata, timestamps) into system prompt. OAuth accounts only. |\n| plugins.wordObfuscator.enabled | boolean | false | Insert zero-width characters into sensitive words to defeat string matching. |\n| plugins.wordObfuscator.words | string[] | [\"proxy\", \"neurolink\", ...] | Words to obfuscate. Defaults include: proxy, neurolink, load balancer, round-robin, failover, multi-account. |\n| plugins.tlsFingerprint.enabled | boolean | false | TLS fingerprint mimicry. Currently a stub/placeholder (no-op). |","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"Cloaking Fields","lvl3":""}},
2338
2348
  {"objectID":"f1d10e310dd6cdd2e1ec76e8fb228e48f343eec841772b564c22357e7ea8f64f","title":"Validation Rules","url":"/docs/features/claude-proxy-config-reference#validation-rules","content":"The config loader validates the following:\naccounts must be present and be a non-array object.\nEach provider key in accounts must map to an array.\nEach account must have a non-empty string apiKey.\nIf version is present, it must be a number.\nrouting.account-allowlist must be an array of non-empty strings when present. An explicit null counts as present and is rejected, whichever spelling carries it, including when the other spelling holds an array.\nrouting.quota-routing must be a boolean when present.\nrouting.auto-fallback must be a boolean when present.\nrouting.max-inflight-per-account must be an integer from 1 through 20 when present.\nrouting.session-soft-limit must be a number in (0, 1] when present.\nrouting.session-reset-tolerance-ms must be a positive integer when present.\nrouting.use-overage must be auto, always, or never (case-insensitive)\n when present.\nrouting.account-ranking must be expiry-first or headroom-first when\n present.\nrouting.prefer-primary must be a boolean when present.\nrouting.session-affinity must be a boolean when present.\nrouting.session-affinity-idle-ttl-ms must be an integer from 60000 through\n 86400000 when present.\nrouting.spill-inflight must be an integer from 0 through 100 when present.\nFor those five routing policy keys, an explicit null counts as present\n and is rejected, whichever spelling (kebab-case or camelCase) carries it.\nPlaintext API keys (not using ${ENV_VAR} references) trigger a warning.\n\nAn absent default config is optional. An existing config that cannot be read or\nvalidated fails proxy startup; it is never ignored in favor of unrestricted\nrouting. A value that fails any check above rejects the whole config, never\njust that key: at startup the proxy does not start, and on a hot reload the\nlast-known-good generation stays active.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"Validation Rules","lvl3":""}},
2339
2349
  {"objectID":"c8450374b1fc8e0a0f5fb47d3bef0cab242c75e17bfebe6e943ef17b22c10227","title":"Account Routing Policies","url":"/docs/features/claude-proxy-config-reference#account-routing-policies","content":"The five keys above (account-ranking, prefer-primary, session-affinity,\nsession-affinity-idle-ttl-ms, spill-inflight) all default to today's exact\nbehavior — expiry-first ranking, no affinity, no primary preference, no\nspill — and are validated and hot-reloaded through the same runtime config\nsnapshot as every other routing key.\n\nstrategy: round-robin ignores all five keys. They apply only under\nfill-first with more than one enabled account.\n\nNEUROLINK_PROXY_QUOTA_ROUTING=off disables quota-based ranking, but\nsession-affinity, prefer-primary and spill-inflight still apply.\nTurning off quota routing removes the expiry/headroom ordering step, so\naccount-ranking has no effect; it does not disable sticky sessions, the\nprimary preference or spill, which then work on the configured account\norder.\n\nPrecedence. After unusable accounts are removed, the order a request\ntries is:\nthe session's bound account, when session-affinity is on and that\n account is usable and not session-saturated;\nthe configured primary-account, when prefer-primary is on and it is\n usable and not session-saturated;\nthe remaining accounts in account-ranking order.\n\nSpill only changes which account is tried first, and only for requests\nwithout an active session-affinity binding — it never re-orders or moves a\nrequest that is already bound to an account. Its target must be usable and\nnot session-saturated, like every step above; when no account under the\nthreshold qualifies, nothing spills.\n\nBinding. A served request binds its session to the Anthropic account\nthat served it. The existing binding is kept only when that request never\ntried the bound account and the bound account is still usable and not\nsession-saturated — a request that overflowed the bound account's\nmax-inflight-per-account cap onto another account keeps the session on its\nwarm prompt cache.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"Account Routing Policies","lvl3":""}},
2340
- {"objectID":"2b5d2865be217ed908e64f9d07acbe019108e95f210f6c14f031cf8cb99ece6f","title":"3. Environment Variables","url":"/docs/features/claude-proxy-config-reference#3-environment-variables","content":"| Variable | Purpose | Used By |\n| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |\n| ANTHROPIC_API_KEY | Anthropic API key. Used as a fallback credential when no OAuth accounts are found. | Proxy routes, Anthropic provider |\n| ANTHROPIC_OAUTH_TOKEN | OAuth access token for Anthropic (alternative to stored tokens). | Anthropic provider, providerConfig |\n| CLAUDE_OAUTH_TOKEN | Alias for ANTHROPIC_OAUTH_TOKEN. Checked as a fallback.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"3. Environment Variables","lvl3":""}},
2350
+ {"objectID":"2b5d2865be217ed908e64f9d07acbe019108e95f210f6c14f031cf8cb99ece6f","title":"3. Environment Variables","url":"/docs/features/claude-proxy-config-reference#3-environment-variables","content":"| Variable | Purpose | Used By |\n| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- |\n| ANTHROPIC_API_KEY | Anthropic API key. Used as a fallback credential when no OAuth accounts are found. | Proxy routes, Anthropic provider |\n| ANTHROPIC_OAUTH_TOKEN | OAuth access token for Anthropic (alternative to stored tokens). | Anthropic provider, providerConfig |\n| CLAUDE_OAUTH_TOKEN | Alias for ANTHROPIC_OAUTH_TOKEN. Checked as a fallback.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"3. Environment Variables","lvl3":""}},
2341
2351
  {"objectID":"80c3f3761c75b9ade9789621570e067d9a631ce027171eba652da6eeb2db3dce","title":"Request body limits","url":"/docs/features/claude-proxy-config-reference#request-body-limits","content":"The proxy reads a POST body before it can parse the model or check a share token, so the body is bounded first. Each route has a request size limit, taken from its API's documentation where the API states one; a larger body is answered 413 with error.type request_too_large, before the body is parsed and before the share gate runs. Limits are binary megabytes, a little above the documented figures, so the upstream stays the one to refuse a borderline request.\n\n| Route | Limit | Source |\n| -------------------------------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| POST /v1/messages, POST /v1/messages/count_tokens, /peer/* endpoints | 32 MiB | Messages API and Token Counting API maximum request size, 32 MB: platform.claude.com/docs/en/api/errors#request-size-limits. The peer endpoints have no upstream and use the same value.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"Request body limits","lvl3":""}},
2342
2352
  {"objectID":"3f1a3fc9d7711064037deec5635e85b2dc713d3d9c019df22c659f47215812b8","title":"Proxy Env File Resolution Order","url":"/docs/features/claude-proxy-config-reference#proxy-env-file-resolution-order","content":"When the proxy starts, it loads env vars from a .env file using this priority:\n--env-file <path> CLI flag — explicit path, required to exist.\nNEUROLINK_ENV_FILE=<path> environment variable — explicit path, required to exist.\n~/.neurolink/.env — loaded automatically if the file exists (created by neurolink proxy telemetry setup).\nNothing — proxy starts without extra env vars; telemetry remains disabled unless env vars are already set in the shell, and the proxy emits a startup log explaining how to enable it unless output is suppressed.\n\nThe --env-file flag is baked into the launchd plist by proxy install, so the service always loads from the same file across reboots. The three runtime routing variables above and routing interpolation are reread transactionally; other env settings remain startup-only.\n\nPriority for Anthropic credentials (checked in order by the proxy routes):\nTokenStore compound keys -- anthropic:<label> entries in ~/.neurolink/tokens.json.\nLegacy credentials file -- ~/.neurolink/anthropic-credentials.json (only if no compound keys exist).\nANTHROPIC_API_KEY env var -- Only if no Anthropic TokenStore entries or legacy credential are present.\n\nrouting.account-allowlist filters these sources before loading or refresh. Legacy and environment fallbacks are never activated merely because existing TokenStore accounts are disabled, cooling, or unavailable.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"Proxy Env File Resolution Order","lvl3":""}},
2343
2353
  {"objectID":"80e1b4619dc934235aae772511dd334605525b9512cb0a98374bc61d27f8903a","title":"4. Claude Code Settings","url":"/docs/features/claude-proxy-config-reference#4-claude-code-settings","content":"When the proxy starts, it automatically writes to ~/.claude/settings.json:\n\n| Key | Value | Description |\n| -------------------- | ---------------------- | --------------------------------------------------------------------------- |\n| ANTHROPIC_BASE_URL | http://<host>:<port> | Tells Claude Code to route all Anthropic API requests through the proxy. |\n| ENABLE_TOOL_SEARCH | \"true\" | Enables tool search in Claude Code (required for full proxy compatibility). |\n\nLifecycle:\nOn proxy start -- Both keys are written (or merged into existing settings).\nOn proxy stop (Ctrl+C / SIGTERM) -- Both keys are removed. Other env keys in the settings file are preserved.\nFail-open guard -- A foreground proxy's detached guard removes stale settings only after confirming its parent died and no replacement is healthy. launchd-managed proxies do not spawn this cleanup guard; they use a separate updater-only worker.\nSafety -- If the ANTHROPIC_BASE_URL has been changed to a different value (e.g., another proxy), the cleanup will not overwrite it.\n\nAfter starting the proxy, restart Claude Code for the new settings to take effect.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Configuration Reference","lvl2":"4. Claude Code Settings","lvl3":""}},
@@ -2407,7 +2417,7 @@
2407
2417
  {"objectID":"82b5ea6ebad2b26819980e3c2d9236f908868af0f18e98e1f1cc3f28c0da94b0","title":"Test proxy endpoints directly","url":"/docs/features/claude-proxy-troubleshooting#test-proxy-endpoints-directly","content":"Test proxy endpoints directly","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Troubleshooting","lvl2":"Test proxy endpoints directly","lvl3":""}},
2408
2418
  {"objectID":"1891f0d140dac44c383cb93775fa43f907fac760945d11c74fae6dc65e4a8fe1","title":"Verify token validity","url":"/docs/features/claude-proxy-troubleshooting#verify-token-validity","content":"Verify token validity","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Troubleshooting","lvl2":"Verify token validity","lvl3":""}},
2409
2419
  {"objectID":"f3bcb4f502142c8c1be4a8eb8fe8e39b56453afd428b4f6c9e822818c229ba9a","title":"Architecture Notes for Debugging","url":"/docs/features/claude-proxy-troubleshooting#architecture-notes-for-debugging","content":"Understanding the proxy's architecture helps diagnose issues faster.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Troubleshooting","lvl2":"Architecture Notes for Debugging","lvl3":""}},
2410
- {"objectID":"f6f5cf5fa780160eed2a12994f0f1941bb705acbe1db249a5f89ac5b23585c98","title":"Passthrough mode (Claude to Claude)","url":"/docs/features/claude-proxy-troubleshooting#passthrough-mode-claude-to-claude","content":"Raw body forwarding. The proxy does not parse, modify, or reconstruct the request body. Only the authentication and protocol headers are set:\nAuthorization: Bearer <oauth_token> (for OAuth accounts)\nx-api-key: <key> (for API key accounts)\nBeta headers from the client request are forwarded as-is\nCloaking headers applied only for OAuth accounts (User-Agent, Stainless SDK headers, billing block)\n\nWhen to suspect passthrough issues: If the request works with one account but not another, the issue is likely account-specific (expired token, wrong permissions, billing).","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Troubleshooting","lvl2":"Passthrough mode (Claude to Claude)","lvl3":""}},
2420
+ {"objectID":"f6f5cf5fa780160eed2a12994f0f1941bb705acbe1db249a5f89ac5b23585c98","title":"Passthrough mode (Claude to Claude)","url":"/docs/features/claude-proxy-troubleshooting#passthrough-mode-claude-to-claude","content":"In --passthrough mode the proxy does not parse, modify, or reconstruct the request body and relays the caller's own Authorization / x-api-key. On the default OAuth pool path it does rewrite the body: system is normalised (a non-Claude-Code client's system prompt is relocated into the message stream behind the compiled-in billing and agent blocks), metadata.user_id is replaced with the account's Claude Code identity, and content is normalised (polyfillOAuthBody, relocateClientSystemIntoMessages). In both modes only allow-listed protocol headers travel upstream:\nAuthorization: Bearer <oauth_token> (for OAuth accounts)\nx-api-key: <key> (for API key accounts)\nanthropic-beta from the client, limited to the proxy's own beta set unless the client is Claude Code (session header and claude-cli/ user-agent)\nuser-agent, x-app, x-stainless-*, anthropic-version, accept*, content-type; everything else (x-neurolink-*, trace context, cf-*, x-forwarded-*, cookies) is dropped\nSnapshot headers applied only for OAuth accounts (User-Agent, Stainless SDK headers), captured from a genuine Claude Code client\n\nWhen to suspect passthrough issues: If the request works with one account but not another, the issue is likely account-specific (expired token, wrong permissions, billing).","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Troubleshooting","lvl2":"Passthrough mode (Claude to Claude)","lvl3":""}},
2411
2421
  {"objectID":"dc5967b6b7036c302ca7ecf3abe9138aa000090f51c6ce0289e7d43d9cfa4715","title":"Translation mode (Claude to other provider)","url":"/docs/features/claude-proxy-troubleshooting#translation-mode-claude-to-other-provider","content":"Full request parsing and format conversion through neurolink.stream(). The Claude Messages API request is converted to NeuroLink's internal format, sent to the target provider (Gemini, OpenAI, etc.), and the response is serialized back to Claude SSE format.\n\nWhen to suspect translation issues: If the error only occurs with non-Claude models or when the fallback chain activates. Check that the target provider's API key is configured and the model name is valid.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Troubleshooting","lvl2":"Translation mode (Claude to other provider)","lvl3":""}},
2412
2422
  {"objectID":"04a3520bc9da0d8211f014416da63d0404426d07301f501741e7565ea9f55858","title":"Token lifecycle","url":"/docs/features/claude-proxy-troubleshooting#token-lifecycle","content":"Token lifecycle","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Troubleshooting","lvl2":"Token lifecycle","lvl3":""}},
2413
2423
  {"objectID":"44f9341fa01636183996f6966d6a698da57d335712c3aa020dfbf6673c3e1e77","title":"Account selection (fill-first)","url":"/docs/features/claude-proxy-troubleshooting#account-selection-fill-first","content":"Account selection (fill-first)","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy Troubleshooting","lvl2":"Account selection (fill-first)","lvl3":""}},
@@ -2425,17 +2435,18 @@
2425
2435
  {"objectID":"d5e5f137807efbff5800106aa9777b782e2a973ddf98f31877f1f139acd785aa","title":"Trace And Session Context","url":"/docs/features/claude-proxy#trace-and-session-context","content":"If the caller sends W3C trace headers (traceparent, tracestate) or NeuroLink session headers (x-neurolink-session-id, x-neurolink-user-id, x-neurolink-conversation-id), the proxy links its spans to the caller trace and preserves that session/user/conversation context in proxy traces and logs.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Trace And Session Context","lvl3":""}},
2426
2436
  {"objectID":"7de815bb264918c204757a43985ee95fc50935e93e02a7b72afe0faa21978d52","title":"Token Management","url":"/docs/features/claude-proxy#token-management","content":"The proxy uses three coordinated token refresh paths:\nBackground check -- Every 30 seconds, one non-overlapping maintenance cycle checks allowed, enabled accounts.\nPre-request check -- A request refreshes an OAuth token when it is within 5 minutes of expiry.\n401 retry -- An unexpected Anthropic 401 triggers refresh and bounded retry before account rotation.\n\nRefresh calls sharing the same rotating refresh token are serialized and reuse the winning result. Credential rejection responses (400, 401, 403, or 404) disable the account until explicit login; network errors, refresh-endpoint 429s, and 5xx responses apply a bounded 30-second to 5-minute auth cooldown instead. Automatic token saves preserve an operator-disabled account's metadata.\n\nRefreshed TokenStore and legacy credentials are persisted with 0o600 permissions using serialized atomic snapshot writes.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Token Management","lvl3":""}},
2427
2437
  {"objectID":"4bbcbe771c6f38c0fe63bab3d60afebe4ece7a59ea46a41822cd364ac91d6a85","title":"Multi-Account Routing","url":"/docs/features/claude-proxy#multi-account-routing","content":"When multiple accounts are available, the proxy uses fill-first routing:\nUse the first non-cooling account for every request.\nOn a 429, classify the authoritative quota window, persist its cooldown, and try the next account.\nContinue until a request succeeds or all accounts are exhausted.\nIf all accounts are exhausted, walk the fallback chain (alternative providers).\nIf all fallbacks fail, return a 429 with a Retry-After header indicating the earliest account recovery time.\n\nIf every account has a known future cooldown, the proxy does not call any of them again. Cooldowns survive restarts in ~/.neurolink/account-cooldowns.json.\n\nAccount sources are checked in priority order:\nTokenStore compound keys (e.g., anthropic:work, anthropic:personal) -- from neurolink auth login --label\nLegacy credentials file (~/.neurolink/anthropic-credentials.json) -- only if no TokenStore accounts exist\nEnvironment variable (ANTHROPIC_API_KEY) -- only if no other accounts exist","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Multi-Account Routing","lvl3":""}},
2428
- {"objectID":"6eb147047e61e0b64fe0e6a22fcaa2149d9fbb37f65129c83f05cc95b1aef4b0","title":"Designating a primary (home) account","url":"/docs/features/claude-proxy#designating-a-primary-home-account","content":"By default the \"first\" account is the first key in token-store insertion order. To override this without re-OAuthing or editing the encrypted token store, set routing.primary-account in the proxy config. The proxy resolves the email to a stable token-store key per request, so the choice survives account additions/removals and only takes effect when that account is currently authenticated:\n\nAfter a 429 cools off, traffic returns to the configured primary (not literal index 0). When the configured account is missing or disabled, the proxy logs a warning while loading the configuration and falls back to insertion-order index 0. See the config reference for the full CLI surface (set-primary / get-primary / clear-primary).","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Designating a primary (home) account","lvl3":""}},
2438
+ {"objectID":"6eb147047e61e0b64fe0e6a22fcaa2149d9fbb37f65129c83f05cc95b1aef4b0","title":"Designating a primary (home) account","url":"/docs/features/claude-proxy#designating-a-primary-home-account","content":"By default the \"first\" account is the first key in token-store insertion order. To override this without re-OAuthing or editing the obfuscated token store (~/.neurolink/tokens.json is XOR-obfuscated, not encrypted — treat the file as a secret), set routing.primary-account in the proxy config. The proxy resolves the email to a stable token-store key per request, so the choice survives account additions/removals and only takes effect when that account is currently authenticated:\n\nAfter a 429 cools off, traffic returns to the configured primary (not literal index 0). When the configured account is missing or disabled, the proxy logs a warning while loading the configuration and falls back to insertion-order index 0. See the config reference for the full CLI surface (set-primary / get-primary / clear-primary).","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Designating a primary (home) account","lvl3":""}},
2429
2439
  {"objectID":"933173d968c19aed118ee8fcbb638aede7f1929d51f9905d95fe3579d7953b51","title":"Restricting eligible accounts","url":"/docs/features/claude-proxy#restricting-eligible-accounts","content":"primary-account controls ordering; it is not a security or isolation boundary. To ensure the proxy can use only an explicit set of Anthropic credentials, configure routing.account-allowlist:\n\nEntries accept an email/label or a full anthropic:<email-or-label> key and are matched case-insensitively. When the field is present, unlisted TokenStore accounts are excluded before token loading or refresh. The legacy credential and ANTHROPIC_API_KEY fallback are also denied unless explicitly listed as legacy-default or env, and neither hidden fallback is considered while any Anthropic TokenStore entry exists. An empty list denies all Anthropic credentials; an absent field preserves unrestricted account discovery.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Restricting eligible accounts","lvl3":""}},
2430
2440
  {"objectID":"5cc17bddecd2e132151e479016793d31d84c29fd0e547521ca9107dce6d15db9","title":"Fallback Chain","url":"/docs/features/claude-proxy#fallback-chain","content":"When all Claude accounts are rate-limited, the proxy walks the fallback chain defined in the config file. Each fallback entry specifies a provider and model:\n\nFallback requests go through NeuroLink's stream() pipeline (translation mode), which handles the format conversion to and from the target provider's API. Tools, thinking configuration, and conversation history from the original request are passed through to the fallback provider.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Fallback Chain","lvl3":""}},
2431
2441
  {"objectID":"879f5b45ba2a4ce4cb4c462d4284f9aec991aa7f9d68d89840eb8886e80ef583","title":"Proxy config file","url":"/docs/features/claude-proxy#proxy-config-file","content":"The proxy loads configuration from ~/.neurolink/proxy-config.yaml by default (override with --config). The file supports YAML or JSON format with environment variable interpolation. The running proxy watches this file and its resolved proxy env file. Valid routing edits are published atomically for new requests; in-flight requests keep their original generation. Invalid or deleted observed files are rejected and the last-known-good generation remains active.\n\nWhen routing is enabled, any requested model that starts with gemini- is treated as a Vertex target by default unless an explicit model-mappings rule overrides it.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Proxy config file","lvl3":""}},
2432
2442
  {"objectID":"1952fbc39bb1367abca1ecb0797c3e41f8d931c4de931da9b081cd95c0f96198","title":"Environment variable interpolation","url":"/docs/features/claude-proxy#environment-variable-interpolation","content":"String values in the config file support ${VAR_NAME} and ${VAR_NAME:-default} syntax:","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Environment variable interpolation","lvl3":""}},
2433
2443
  {"objectID":"52af35bc2dbc89c5f9ddc876758c59ac22e40a69a6502512d129de367ab3e801","title":"Account configuration options","url":"/docs/features/claude-proxy#account-configuration-options","content":"| Field | Type | Default | Description |\n| ----------- | ------- | ------- | ------------------------------------------ |\n| name | string | unnamed | Human-readable label for the account |\n| apiKey | string | -- | API key or token (supports ${ENV_VAR}) |\n| baseUrl | string | -- | Override the provider endpoint URL |\n| orgId | string | -- | Organization ID (e.g., for OpenAI orgs) |\n| weight | number | 1 | Weight for weighted round-robin selection |\n| enabled | boolean | true | Whether this account is active |\n| rateLimit | number | -- | Max requests per minute for this account |\n| metadata | object | -- | Arbitrary metadata attached to the account |","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Account configuration options","lvl3":""}},
2434
2444
  {"objectID":"33e969d6588960f0ea839ee1c7bb548f852ab75fc634a2bf31e46f8d72ae7367","title":"Server options","url":"/docs/features/claude-proxy#server-options","content":"| Option | Default | Description |\n| -------- | -------------------------------- | ------------------- |\n| port | 55669 | Port to listen on |\n| host | 127.0.0.1 | Host to bind to |\n| config | ~/.neurolink/proxy-config.yaml | Path to config file |","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Server options","lvl3":""}},
2445
+ {"objectID":"70c4ded5eebb724ab6c4447afac00a2154b30995cca137984121ae7be6ce8776","title":"Inbound authentication","url":"/docs/features/claude-proxy#inbound-authentication","content":"Every request the proxy serves spends one of the pooled subscriptions, so the\nproxy decides at start-up whether anything authenticates its callers:\nLoopback (127.0.0.1, localhost, ::1) binds always start. The only\n callers are processes on this machine.\nAny other --host is refused unless one of these is in place:\nan inbound token — --inbound-token <secret> or\n NEUROLINK_PROXY_INBOUND_TOKEN. Every caller must then send it as\n x-neurolink-inbound-token: <secret> or Authorization: Bearer <secret>\n (the proxy replaces Authorization upstream, so an Anthropic SDK client can\n simply use the token as its ANTHROPIC_AUTH_TOKEN). A request carrying a\n share token is judged by the share gate instead. /health stays open;\n /peer/* authenticates itself; /internal/update-control has its own\n token.\nthe share gate — NEUROLINK_PROXY_REQUIRE_GRANT=1, which refuses any\n request without a valid share token (including the operator's own client).\n--allow-unauthenticated (or NEUROLINK_PROXY_ALLOW_UNAUTHENTICATED=1),\n which records that an authenticating reverse proxy sits in front. The\n proxy starts and logs a warning.\n\nGET /limits, GET /accounts and GET /status are operator surfaces: they\nname every account (an email for an OAuth account) with its quota and spend.\nThey are refused to borrowers and, when an inbound token is configured, to any\ncaller without it.\n\nOther inbound-trust guarantees, regardless of bind address:\nOnly protocol headers travel upstream (content-type, accept*,\n anthropic-version, anthropic-beta, user-agent, x-app,\n x-stainless-*, x-claude-code-session-id, …). x-neurolink-*,\n traceparent/tracestate/baggage, cf-*, x-forwarded-*, x-real-ip,\n via, forwarded, cookies and hop-by-hop headers never reach Anthropic.\nA client may only add anthropic-beta values the proxy would send itself,\n unless it is Claude Code (both x-claude-code-session-id and a\n claude-cli/ user-agent). A rejected client-supplied beta never re-ranks the\n pool.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"Inbound authentication","lvl3":""}},
2435
2446
  {"objectID":"231993ae6fea15be881e79d7a90ff7812fed1732c66ded34408d8e407555735f","title":"neurolink proxy setup","url":"/docs/features/claude-proxy#neurolink-proxy-setup","content":"One-command onboarding: checks for existing accounts, runs OAuth login if needed, installs the proxy as a persistent service, and configures Claude Code.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy setup","lvl3":""}},
2436
- {"objectID":"8396893c0e3ca92a4fd6a3b65aef8060d1636f96864454e1baa21530559f6b3a","title":"neurolink proxy install","url":"/docs/features/claude-proxy#neurolink-proxy-install","content":"Install the proxy as a persistent macOS launchd service. The service auto-restarts on crash (5-second throttle interval) and starts on login.\n\nOptions:\n\n| Flag | Alias | Default | Description |\n| -------- | ----- | --------- | ----------------- |\n| --port | -p | 55669 | Port to listen on |\n| --host | -H | 127.0.0.1 | Host to bind to |","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy install","lvl3":""}},
2447
+ {"objectID":"8396893c0e3ca92a4fd6a3b65aef8060d1636f96864454e1baa21530559f6b3a","title":"neurolink proxy install","url":"/docs/features/claude-proxy#neurolink-proxy-install","content":"Install the proxy as a persistent macOS launchd service. The service auto-restarts on crash (5-second throttle interval) and starts on login.\n\nA non-loopback --host without --inbound-token, NEUROLINK_PROXY_REQUIRE_GRANT=1\nor --allow-unauthenticated is refused — see Inbound authentication.\nThe token is persisted into the service's environment (the plist is 0600).\n\nOptions:\n\n| Flag | Alias | Default | Description |\n| -------- | ----- | --------- | ----------------- |\n| --port | -p | 55669 | Port to listen on |\n| --host | -H | 127.0.0.1 | Host to bind to |","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy install","lvl3":""}},
2437
2448
  {"objectID":"eac87869eb201e337e5ebbfaa70913fa3be2a1394780b899fc808452de78f0f0","title":"neurolink proxy uninstall","url":"/docs/features/claude-proxy#neurolink-proxy-uninstall","content":"Remove the launchd service. Stops the proxy if it is running and deletes the launchd plist.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy uninstall","lvl3":""}},
2438
- {"objectID":"69046a17f3a7b07eb3426a13e9785df3dd33383fda7d4dee49b4e18fbdf3aecd","title":"neurolink proxy start","url":"/docs/features/claude-proxy#neurolink-proxy-start","content":"Start the proxy server.\n\nOptions:\n\n| Flag | Alias | Default | Description |\n| ------------------- | ----- | -------------------------------- | ---------------------------------------------------------- |\n| --port | -p | 55669 | Port to listen on |\n| --host | -H | 127.0.0.1 | Host to bind to |\n| --strategy | -s | fill-first | Account selection strategy (fill-first or round-robin) |\n| --health-interval | | 30 | Health check interval (seconds) |\n| --config | -c | ~/.neurolink/proxy-config.yaml | Config file path |\n| --quiet | -q | false | Suppress output |\n| --debug | -d | false | Enable debug output |\n| --passthrough | | false | Transparent forwarding (no retry, rotation, or polyfill) |\n| --env-file | | | Path to .env file for provider API keys |\n\nStrategy choices: round-robin, fill-first","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy start","lvl3":""}},
2449
+ {"objectID":"69046a17f3a7b07eb3426a13e9785df3dd33383fda7d4dee49b4e18fbdf3aecd","title":"neurolink proxy start","url":"/docs/features/claude-proxy#neurolink-proxy-start","content":"Start the proxy server.\n\nOptions:\n\n| Flag | Alias | Default | Description |\n| ------------------------- | ----- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| --port | -p | 55669 | Port to listen on |\n| --host | -H | 127.0.0.1 | Host to bind to. Non-loopback needs --inbound-token, NEUROLINK_PROXY_REQUIRE_GRANT=1 or --allow-unauthenticated |\n| --inbound-token | | | Bearer every caller must present (x-neurolink-inbound-token or Authorization: Bearer); also NEUROLINK_PROXY_INBOUND_TOKEN |\n| --allow-unauthenticated | | false | Bind a non-loopback host with no inbound authentication (an authenticating reverse proxy must sit in front) |\n| --strategy | -s | fill-first | Account selection strategy (fill-first or round-robin) |\n| --health-interval | | 30 | Health check interval (seconds) |\n| --config | -c | ~/.neurolink/proxy-config.yaml | Config file path |\n| --quiet | -q | false | Suppress output","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy start","lvl3":""}},
2439
2450
  {"objectID":"9d71d197a055694948243c62dafe139b46b7c20a2d7c9368116cd68e0d6df511","title":"neurolink proxy status","url":"/docs/features/claude-proxy#neurolink-proxy-status","content":"Show proxy status, including PID, uptime, strategy, fallback chain, and per-account usage statistics fetched from the live /status endpoint. Status output now distinguishes total upstream attempts from completed requests, so retry-heavy incidents are easier to spot.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy status","lvl3":""}},
2440
2451
  {"objectID":"dea7a210a16874eeed456ed90998f68d0819f2ae69f79b031eb066587dd58198","title":"neurolink proxy telemetry <action>","url":"/docs/features/claude-proxy#neurolink-proxy-telemetry-action","content":"Manage the local OpenObserve stack and the maintained proxy dashboard from the CLI.\n\nThese commands use the repo-owned assets under scripts/observability/ and the dashboard JSON at docs/assets/dashboards/neurolink-proxy-observability-dashboard.json.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy telemetry <action>","lvl3":""}},
2441
2452
  {"objectID":"58c3933ed4f35732252a25fe5f161f65d53f005c0acaa480e6ba536e7bbb622c","title":"neurolink proxy analyze","url":"/docs/features/claude-proxy#neurolink-proxy-analyze","content":"Read the proxy's own request and attempt logs and report what actually happened:\nper-account success and failure counts, retry-recovered requests, terminal error\ncategories, and routing decisions.\n\nReported counts are bounded by log retention. When the request and attempt\nwindows are not comparable, the command says so rather than printing a\nrecovered-after-retry figure it cannot stand behind.","hierarchy":{"lvl0":"Features","lvl1":"Claude Proxy","lvl2":"neurolink proxy analyze","lvl3":""}},
@@ -2671,15 +2682,16 @@
2671
2682
  {"objectID":"5566ca1b60d153f267dff8ba139d1a4661b60cb804fd3ec2967cf467122e4849","title":"2. Adding accounts","url":"/docs/features/codex-proxy-support#2-adding-accounts","content":"Codex login works by importing the credential the Codex CLI already holds. Log into Codex normally, then import:\n\nEach import reads ~/.codex/auth.json, decodes the account id / plan / email from the token, and stores it under a codex:<label> key in ~/.neurolink/tokens.json. If you omit --label, the account email is used.\n\nList the pool (Codex and Anthropic accounts appear together):\n\nRemove Codex accounts:\n\nOnly ChatGPT subscription login (auth_mode: \"chatgpt\") can be pooled. An API-key Codex install is rejected with a clear message.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"2. Adding accounts","lvl3":""}},
2672
2683
  {"objectID":"2c1717347ebf0ec18b9aa2738c5628682d4318c893427fdc5267caed3fe54845","title":"3. Client auto-configuration","url":"/docs/features/codex-proxy-support#3-client-auto-configuration","content":"When neurolink proxy start runs (non-dev), it configures the Codex CLI the same way it configures Claude Code and OpenCode. It appends a marker-delimited block to ~/.codex/config.toml:\n\nYour original model_provider value is snapshotted to ~/.neurolink/codex-proxy-snapshot.json and restored on shutdown, so the edit is fully reversible even if the proxy crashes. The managed block is delimited by markers and removed cleanly on clear. If ~/.codex/config.toml doesn't exist, the step is skipped silently.\n\nRestart Codex after starting the proxy for it to pick up the new provider.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"3. Client auto-configuration","lvl3":""}},
2673
2684
  {"objectID":"404cd8f6d8542fc84651326cf0b252e7c3c3098678409fecaf8c2ff1559906fd","title":"4. Quota and routing","url":"/docs/features/codex-proxy-support#4-quota-and-routing","content":"Codex reports two rate-limit windows — primary (short) and secondary (weekly) — which map onto the shared AccountQuota model as the session and weekly fields respectively. That means Codex reuses the existing cooldown, persistence, and display code rather than duplicating it.\n\nAccount ordering is fill-first and quota-aware:\nAccounts on cooldown sort last.\nWithin the same cooldown state, accounts with a rejected unified quota sort after accounts without known rejection, even when their session usage is low or unknown.\nWithin each group, accounts with no session quota measurement sort first — they get probed so they become comparable, rather than being starved.\nOtherwise, least session utilization first. Rejected accounts remain eligible after preferred accounts so stale rejection evidence cannot permanently prevent a recovery probe.\n\nCooldown reasons map to the shared vocabulary: a rejected weekly window cools until its real reset (weekly), a rejected primary window until its reset (session), and a plain burst limit gets a bounded transient cooldown (60 s floor, 15 min ceiling).\n\nQuota and cooldown state are keyed by the full codex: account key, so a Codex account and an Anthropic account that share a bare label never collide.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"4. Quota and routing","lvl3":""}},
2674
- {"objectID":"acb592d28fcb90659fa175ac4f0d1e73cfb535d0aac2b63a101f0722e538eff7","title":"5. Response headers","url":"/docs/features/codex-proxy-support#5-response-headers","content":"A response served by the Codex pool carries these attribution headers. A\nresponse served by the outbound fallback\ncarries only x-neurolink-served-by: the account, attempt and quota headers\ndescribe a Codex account, and none served that turn.\n\n| Header | Meaning |\n| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| x-neurolink-account | Which pooled account served the request |\n| x-neurolink-account-type | Always codex-oauth |\n| x-neurolink-served-by | codex, or codex-outbound-fallback:anthropic / codex-outbound-fallback:vertex when the outbound fallback served the turn |\n| x-neurolink-attempt | Which attempt succeeded (1 = first account tried) |\n| x-neurolink-quota-source | live when the backend reported quota, else none |\n| x-neurolink-quota-session-left-pct | Remaining primary-window headroom |\n| x-neurolink-quota-weekly-left-pct | Canonical remaining","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"5. Response headers","lvl3":""}},
2675
- {"objectID":"2b17d62c4d9cb65067100d6a90003bee2dce2bc06ede425f25f0b761aade359a","title":"6. Error handling","url":"/docs/features/codex-proxy-support#6-error-handling","content":"| Condition | Behaviour |\n| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| No Codex accounts configured | 401 with a message pointing at neurolink auth login codex |\n| All accounts cooling | Terminal response.failed SSE event (200, retry-after computed from the soonest recovery) instead of a bare 429, so the CLI shows a real error instead of \"Reconnecting...\" |\n| All accounts auth-cooling | The same terminal event with code server_error instead of insufficient_quota (every account is parked by an auth failure), so it is not reported as spent quota |\n| 401 / 403 from upstream | One forced token refresh and a retry; a second rejection parks the account for 60 s and rotates; a failed refresh disables the account until re-login |\n| 401 / 403 with a request-refusal code | The request ends on that account with no refresh, cooldown or rotation: a policy code answers 403, an invalid-request code keeps the upstream status (see below) |\n| 429 | Cool the account per its reported window, then rotate |\n| 5xx / network | Rotate to the next account |","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"6. Error handling","lvl3":""}},
2685
+ {"objectID":"acb592d28fcb90659fa175ac4f0d1e73cfb535d0aac2b63a101f0722e538eff7","title":"5. Response headers","url":"/docs/features/codex-proxy-support#5-response-headers","content":"A response served by the Codex pool carries these attribution headers. A\nresponse served by the outbound fallback\ncarries only x-neurolink-served-by: the account, attempt and quota headers\ndescribe a Codex account, and none served that turn.\n\n| Header | Meaning |\n| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| x-neurolink-account | Which pooled account served the request. Stripped from borrowed responses: the label is the lender's identity |\n| x-neurolink-account-type | Always codex-oauth. Stripped from borrowed responses |\n| x-neurolink-served-by | codex, or codex-outbound-fallback:anthropic / codex-outbound-fallback:vertex when the outbound fallback served the turn |\n| x-neurolink-attempt | Which attempt succeeded (1 = first account tried) |\n| x-neurolink-quota-source | live when the backend reported quota, else none |\n| x-neurolink-quota-session-left-pct | Remaining primary-window headroom |\n| x-neurolink-quota-weekly-left-pct | Canonical remaining","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"5. Response headers","lvl3":""}},
2686
+ {"objectID":"2b17d62c4d9cb65067100d6a90003bee2dce2bc06ede425f25f0b761aade359a","title":"6. Error handling","url":"/docs/features/codex-proxy-support#6-error-handling","content":"| Condition | Behaviour |\n| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| No Codex accounts configured | 401 with a message pointing at neurolink auth login codex |\n| All accounts cooling | Terminal response.failed SSE event (200, retry-after computed from the soonest recovery) instead of a bare 429, so the CLI shows a real error instead of \"Reconnecting...\" |\n| All accounts auth-cooling | The same terminal event with code server_error instead of insufficient_quota (every account is parked by an auth failure), so it is not reported as spent quota |\n| 401 / 403 from upstream | One forced token refresh and a retry; a second rejection parks the account for 60 s and rotates; a failed refresh disables the account until re-login |\n| 401 / 403 with a request-refusal code | The request ends on that account with no refresh, cooldown or rotation: a policy code answers 403, an invalid-request code keeps the upstream status (see below) |\n| 429 | Cool the account per its reported window (bounded by what the window can mean, as the Claude engine does), then rotate |\n| Any other 4xx | Upstream's verdict on the request itself (a malformed body, an unknown model): returned with the upstream status after exactly one upstream call, no rotation |\n|","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"6. Error handling","lvl3":""}},
2676
2687
  {"objectID":"9b1627d0fcff6a9e292b7f794fb47e62eb3da6b9c633e308da2b1de08a83368d","title":"7. Implementation map","url":"/docs/features/codex-proxy-support#7-implementation-map","content":"| File | Role |\n| ------------------------------------------- | ----------------------------------------------------------------------------------------- |\n| src/lib/types/codex.ts | Codex auth-file, token, and rate-limit types |\n| src/lib/auth/codexOAuth.ts | Endpoints/constants, auth.json import, token refresh, JWT decode, account-id resolution |\n| src/lib/proxy/codexAccountUsage.ts | Account enumeration, usage fetch, quota normalisation, header parsing |\n| src/lib/server/routes/codexProxyRoutes.ts | The pool engine: load → order → forward → rotate |\n| src/cli/commands/auth.ts | auth login codex, Codex rows in auth list --refresh |\n| src/cli/commands/proxy.ts | Route registration, /backend-api/* request tracking, ~/.codex/config.toml management |\n\nThe Anthropic engine in claudeProxyRoutes.ts is untouched. The Codex engine is deliberately leaner: it does pre-commit rotation but not the full transient-retry-budget or admission-lease machinery.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"7. Implementation map","lvl3":""}},
2677
- {"objectID":"c90a5222434bc717385c13b9e9f9cb865d3ce71ed7a58c077a7b5241def7d086","title":"8. Caveats","url":"/docs/features/codex-proxy-support#8-caveats","content":"Model ids matter. The ChatGPT backend rejects models that aren't available to Codex-with-a-ChatGPT-account (e.g. gpt-5-codex returns a 400). Use the model your Codex config already uses.\nTerms of service. Pooling multiple personal ChatGPT subscriptions through one client fingerprint is the kind of pattern subscription anti-abuse systems are built to detect. The originator, installation_id, user-agent, and turn-metadata headers are all correlatable. Pooling your own accounts is materially different from sharing across people — weigh the account-ban risk accordingly.\nNative browser login is not implemented. The verified path is importing an existing codex login credential. The OAuth constants (authorize URL, PKCE, scopes) are present in codexOAuth.ts for a future native flow.\nQuota-aware ordering is unverified against the live backend. The usage endpoint and the rate-limit header shape were reconstructed from a capture, not confirmed end to end. If either is wrong, fetchCodexAccountUsage returns no quota, x-neurolink-quota-source reads none, and ordering degenerates to insertion order while every 429 falls back to the 15-minute transient cooldown. Rotation still works; it is simply not quota-aware. Verify with neurolink auth list --refresh — a codex usage … error line per account means the quota path is not live.\nSSE usage-limit signals are not acted on. Only an HTTP 429 triggers a cooldown and rotation. A 200 response whose SSE stream carries usage_limit_reached (or the workspace-credit variants) is relayed to the client untouched, so the account is neither cooled nor rotated away from. HTTP-level exhaustion is handled; in-stream exhaustion is not.\nClient fingerprint is forwarded verbatim. The proxy replaces the caller's credentials but does not regenerate originator, installation_id, session-id, or turn metadata per account, so every pooled account shares the client's fingerprint. This is what makes the terms-of-service point above concrete.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"8. Caveats","lvl3":""}},
2688
+ {"objectID":"c90a5222434bc717385c13b9e9f9cb865d3ce71ed7a58c077a7b5241def7d086","title":"8. Caveats","url":"/docs/features/codex-proxy-support#8-caveats","content":"Model ids matter. The ChatGPT backend rejects models that aren't available to Codex-with-a-ChatGPT-account (e.g. gpt-5-codex returns a 400). Use the model your Codex config already uses.\nTerms of service. Pooling multiple personal ChatGPT subscriptions through one client fingerprint is the kind of pattern subscription anti-abuse systems are built to detect. The originator, installation_id, user-agent, and turn-metadata headers are all correlatable. Pooling your own accounts is materially different from sharing across people — weigh the account-ban risk accordingly.\nNative browser login is not implemented. The verified path is importing an existing codex login credential. The OAuth constants (authorize URL, PKCE, scopes) are present in codexOAuth.ts for a future native flow.\nQuota-aware ordering is unverified against the live backend. The usage endpoint and the rate-limit header shape were reconstructed from a capture, not confirmed end to end. If either is wrong, fetchCodexAccountUsage returns no quota, x-neurolink-quota-source reads none, and ordering degenerates to insertion order while every 429 falls back to the 15-minute transient cooldown. Rotation still works; it is simply not quota-aware. Verify with neurolink auth list --refresh — a codex usage … error line per account means the quota path is not live.\nSSE usage-limit signals are not acted on. Only an HTTP 429 triggers a cooldown and rotation. A 200 response whose SSE stream carries usage_limit_reached (or the workspace-credit variants) is relayed to the client untouched, so the account is neither cooled nor rotated away from. HTTP-level exhaustion is handled; in-stream exhaustion is not.\nClient fingerprint is forwarded, bounded by an allow-list.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"8. Caveats","lvl3":""}},
2689
+ {"objectID":"4fe2894f0d5c16a0b1602045b132bbebf8a239c8e36f9b7344346bd3777b7fe9","title":"Inbound trust","url":"/docs/features/codex-proxy-support#inbound-trust","content":"The Codex door is served by the same listener as /v1/messages and is governed\nby the same rules (see the Claude proxy guide's \"Inbound authentication\"):\nThe listener binds 127.0.0.1 by default and refuses any other host\n unless NEUROLINK_PROXY_INBOUND_TOKEN / --inbound-token,\n NEUROLINK_PROXY_REQUIRE_GRANT=1 or --allow-unauthenticated is set. With\n an inbound token every POST /backend-api/codex/responses and\n GET /backend-api/codex/models must carry it (x-neurolink-inbound-token\n or Authorization: Bearer); a request carrying a share token is judged by\n the share gate instead. NEUROLINK_PROXY_REQUIRE_GRANT gates this door too.\ncreateCodexProxyRoutes(basePath, runtimeConfigProvider, loopbackPort,\ninternalDispatch, inboundAuth?) applies the same token when mounted from the\n SDK, reading NEUROLINK_PROXY_INBOUND_TOKEN when no inboundAuth.token is\n given, and logs one loud warning when mounted with neither.\nBorrowed requests get no account label (x-neurolink-account* are stripped),\n cannot reference or create account-side state (previous_response_id,\n prompt_cache_key, metadata, user dropped; store forced false), and\n model discovery serves them like any other caller.\nGET /backend-api/codex/models forwards only client_version from the\n client's query and uses healthy (non-cooling) accounts only, at most the\n per-request account cap. Every call reaches upstream, because the context\n window and output ceiling it reports are recorded per model and must not be\n served stale.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"Inbound trust","lvl3":""}},
2678
2690
  {"objectID":"607b92eb2c3b89a57438267a92b6212e616ad0dd106cb1c1a6bd0514c3446cd2","title":"Model discovery","url":"/docs/features/codex-proxy-support#model-discovery","content":"The Codex CLI refreshes its model list on every invocation:\n\nThe proxy relays that upstream to chatgpt.com/backend-api/codex/models using a\npooled account, forwarding the CLI's own query parameters.\n\nIt relays rather than synthesises, unlike the Claude and OpenAI /v1/models\nroutes, which build their lists locally from the model router. Which Codex\nmodels an account can reach is a property of that account — plan tier, rollout\nstate — not something this proxy knows, so a locally-built list would be a guess\nthat reads as authoritative.\n\nTwo details matter to anyone touching it:\nclient_version is required upstream. Omit it and ChatGPT answers 400\n with a pydantic Field required on ('query', 'client_version'). The query\n is rebuilt from ctx.query; ctx.path carries no query string, and reading it\n from there drops the parameter silently.\nDiscovery is side-effect free. No cooldown is recorded and no quota is\n consumed, so the once-per-invocation refresh cannot influence routing for real\n traffic. A cooling account is still allowed to answer it — being rate-limited\n for completions does not make an account unable to say which models exist.\n\nBefore this route existed the request 404'd, and the CLI printed\nfailed to refresh available models: unexpected status 404 Not Found on every\nrun before silently falling back to a default model — quietly ignoring the model\nthe user had configured.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"Model discovery","lvl3":""}},
2679
2691
  {"objectID":"6d2395f1bb843928fffc947203d5d331fb549bb7d9403adfa777e676578b4d18","title":"Status: implemented, default OFF, request-shape verified only — see \"Live validation\" below","url":"/docs/features/codex-proxy-support#status-implemented-default-off-request-shape-verified-only-see-live-validation-below","content":"Sections 1-8 above cover the inbound direction: a Codex CLI request served\nby the Codex/ChatGPT pool engine. This section covers the opposite direction —\na native Codex /backend-api/codex/responses request that, when every Codex\naccount is exhausted or otherwise ineligible, is translated into an\nAnthropic Messages request and served by either the Anthropic OAuth pool (via\nan in-process loopback, no extra network hop to this same proxy) or a\nVertex-Claude passthrough account, then translated back into the Codex\nResponses wire shape the CLI expects. It is a third direction alongside the\ntwo-engine matrix in the rest of this document, not a replacement for either.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"Status: implemented, default OFF, request-shape verified only — see \"Live validation\" below","lvl3":""}},
2680
- {"objectID":"3c2f324de0830846bbdce959aabe14903475260a2adfabf478b669fef52ac726","title":"9.1 Enabling it","url":"/docs/features/codex-proxy-support#91-enabling-it","content":"The kill switch defaults to off. Nothing changes for an existing Codex\npool setup until you opt in:\n\nor via environment variable, which overrides the YAML key:\n\ncodex-outbound-fallback-targets is required (non-empty) for the fallback to\never fire — the kill switch alone is not enough. provider must be anthropic\nor vertex; up to 8 targets are accepted and validated at config-load time.\nWith the flag off, or with no targets configured, an exhausted Codex request\nbehaves exactly as it did before this feature existed: the same terminal\nresponse.failed SSE / 401 behaviour documented in section 6 above, byte-\nfor-byte.\n\nThe anthropic target needs the CLI proxy's in-process loopback. Dispatch\nto an anthropic target goes through an in-process loopback\n(127.0.0.1:<loopbackPort> plus an unforgeable internalDispatch marker, see\n§9.3) rather than a second network hop, and only neurolink proxy start (the\nCLI proxy command) wires that loopback through today. createAllRoutes /\nregisterAllRoutes — the generic SDK route surface in\nsrc/lib/server/routes/index.ts, used when embedding the proxy routes in your\nown server — does not thread loopbackPort/internalDispatch into\ncreateCodexProxyRoutes, so enabling this feature there with an anthropic\ntarget configured cannot actually dispatch: route creation logs one warning\nand every such request falls through to the normal Codex-exhaustion behaviour\nin section 6, indistinguishable on the wire from the feature being off. A\nvertex target has no such gap — it dispatches over executeVertexAnthropicFallback\nregardless of which route surface created the routes. If you need the\nanthropic target from the SDK route surface, run the CLI proxy alongside\nyour server, or wait for loopbackPort/internalDispatch to be threaded\nthrough CreateRoutesOptions (not yet implemented — see the doc comments on\ncreateAllRoutes and CreateRoutesOptions.runtimeConfigProvider).","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.1 Enabling it","lvl3":""}},
2681
- {"objectID":"d20a853143464660ecb4669832c8c0d5e24292564bc7ea9161354afda9a39223","title":"9.2 When it triggers","url":"/docs/features/codex-proxy-support#92-when-it-triggers","content":"attemptCodexOutboundFallback (module-private in codexProxyRoutes.ts) is\nconsulted only after every Codex account has been tried and failed, and only\nwhen all of the following hold, in this order — any one failing gate means\n\"not attempted\", and the request falls through to the normal Codex-exhaustion\nbehaviour in section 6:\nThe inbound request is not itself already a fallback leg (see loop\n prevention below).\nruntimeConfigProvider is configured (the proxy is running with the\n runtime-config feature enabled at all).\nclassifyCodexOutboundFailure judges the failure itself eligible — a total\n function, not a heuristic guess, over the terminal Codex failure class.\nThe kill switch (codexOutboundFallbackEnabled) is on.\ncodexOutboundFallbackTargets is non-empty.\nThe native Codex request body parses (parseCodexNativeRequest) — a\n request the translator cannot even parse is never a candidate.\n\nWhen the account loop runs out, the last attempt decides eligibility. A\n401/403 across the whole pool is a Codex credential failure and falls back, as\ndo 429 and 5xx. A content-policy or invalid-request error code\n(classifyProxyFailureCode), or any other 4xx, rejects the request itself and\nis returned unchanged. A pre-stream 401/403 carrying such a code never reaches\nthis point: the pool ends the request on the account that received it (see\nsection 6).\n\nThe Anthropic loopback has a 5-minute timeout that covers the connection until\nits response headers arrive. After that the stream runs as long as the turn\ndoes; a client disconnect still ends it.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.2 When it triggers","lvl3":""}},
2682
- {"objectID":"63d9622db4658e47ba8122e511162860b322d42d2b741a5c76611250fe670550","title":"9.3 Loop prevention","url":"/docs/features/codex-proxy-support#93-loop-prevention","content":"Two independent guards, so a defect in one does not remove the bound:\nMarker guard. The moment every gate above has passed and a real\n dispatch attempt is about to begin, codexProxyRoutes.ts sets\n ctx.metadata[\"neurolink.codexOutboundFallbackAttempted\"] = true on the\n request context. Gate 1 above checks this same key, so a request that has\n already crossed engines once can never be offered a second outbound-fallback\n attempt within the same client request. This is a single flag, not a\n per-target counter, because at most one crossing is ever allowed regardless\n of how many of the internal dispatch call sites reach this function.\nDepth counter (defense-in-depth). ctx.metadata[\"neurolink.fallbackHopDepth\"]\n is incremented on every engine crossing (never on a same-engine account\n rotation) and checked against MAX_ENGINE_CROSSINGS = 1, independent of the\n marker check above. The invariant this enforces: the ordered sequence of\n engines serving any one client request has length ≤ 2 with no repeat — only\n [codex], [anthropic], [codex,anthropic], [anthropic,codex] are\n possible. A leg that is itself already an inner fallback of the other engine\n can never itself fall outbound again.\n\nA request that reaches this point already carrying a forged\ncodexOutboundFallbackAttempted-shaped marker from outside is not trusted —\nthe key lives on the server-side request context (ctx.metadata), not on\nanything the client can set on the wire, so there is no client-controlled way\nto spoof past gate 1.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.3 Loop prevention","lvl3":""}},
2692
+ {"objectID":"3c2f324de0830846bbdce959aabe14903475260a2adfabf478b669fef52ac726","title":"9.1 Enabling it","url":"/docs/features/codex-proxy-support#91-enabling-it","content":"The kill switch defaults to off. Nothing changes for an existing Codex\npool setup until you opt in:\n\nor via environment variable, which overrides the YAML key:\n\ncodex-outbound-fallback-targets is required (non-empty) for the fallback to\never fire — the kill switch alone is not enough. provider must be anthropic\nor vertex; up to 8 targets are accepted and validated at config-load time.\nWith the flag off, or with no targets configured, an exhausted Codex request\nbehaves exactly as it did before this feature existed: the same terminal\nresponse.failed SSE / 401 behaviour documented in section 6 above, byte-\nfor-byte.\n\nThe anthropic target needs the CLI proxy's in-process loopback. Dispatch\nto an anthropic target goes through an in-process loopback\n(127.0.0.1:<loopbackPort>, authorised by a server-minted single-use\nx-neurolink-internal-request token — proxyActivity.ts — which is what makes\nthe crossing unforgeable; internalDispatch itself is just app.fetch, see\n§9.3) rather than a second network hop, and only neurolink proxy start (the\nCLI proxy command) wires that loopback through today. createAllRoutes /\nregisterAllRoutes — the generic SDK route surface in\nsrc/lib/server/routes/index.ts, used when embedding the proxy routes in your\nown server — does not thread loopbackPort/internalDispatch into\ncreateCodexProxyRoutes, so enabling this feature there with an anthropic\ntarget configured cannot actually dispatch: route creation logs one warning\nand every such request falls through to the normal Codex-exhaustion behaviour\nin section 6, indistinguishable on the wire from the feature being off. A\nvertex target has no such gap — it dispatches over executeVertexAnthropicFallback\nregardless of which route surface created the routes.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.1 Enabling it","lvl3":""}},
2693
+ {"objectID":"d20a853143464660ecb4669832c8c0d5e24292564bc7ea9161354afda9a39223","title":"9.2 When it triggers","url":"/docs/features/codex-proxy-support#92-when-it-triggers","content":"attemptCodexOutboundFallback (module-private in codexProxyRoutes.ts) is\nconsulted only after every Codex account has been tried and failed, and only\nwhen all of the following hold, in this order — any one failing gate means\n\"not attempted\", and the request falls through to the normal Codex-exhaustion\nbehaviour in section 6:\nThe inbound request is not itself already a fallback leg (see loop\n prevention below).\nruntimeConfigProvider is configured (the proxy is running with the\n runtime-config feature enabled at all).\nclassifyCodexOutboundFailure judges the failure itself eligible — a total\n function, not a heuristic guess, over the terminal Codex failure class.\nThe kill switch (codexOutboundFallbackEnabled) is on.\ncodexOutboundFallbackTargets is non-empty.\nThe native Codex request body parses (parseCodexNativeRequest) — a\n request the translator cannot even parse is never a candidate.\n\nWhen the account loop runs out, the last attempt decides eligibility. A\n401/403 across the whole pool is a Codex credential failure and falls back, as\ndo 429 and 5xx. A content-policy or invalid-request error code\n(classifyProxyFailureCode), or any other 4xx, rejects the request itself:\nthe pool ends the request on the account that received it, after exactly one\nupstream call, and returns the upstream status (see section 6), so such a\nrequest never reaches this point.\n\nThe Anthropic loopback has a 5-minute timeout that covers the connection until\nits response headers arrive. After that the stream runs as long as the turn\ndoes; a client disconnect still ends it.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.2 When it triggers","lvl3":""}},
2694
+ {"objectID":"63d9622db4658e47ba8122e511162860b322d42d2b741a5c76611250fe670550","title":"9.3 Loop prevention","url":"/docs/features/codex-proxy-support#93-loop-prevention","content":"Two independent guards, so a defect in one does not remove the bound:\nMarker guard. The moment every gate above has passed and a real\n dispatch attempt is about to begin, codexProxyRoutes.ts sets\n ctx.metadata[\"neurolink.codexOutboundFallbackAttempted\"] = true on the\n request context. Gate 1 above checks this same key, so a request that has\n already crossed engines once can never be offered a second outbound-fallback\n attempt within the same client request. This is a single flag, not a\n per-target counter, because at most one crossing is ever allowed regardless\n of how many of the internal dispatch call sites reach this function.\nDepth bound. MAX_ENGINE_CROSSINGS = 1 (codexOutboundFallback.ts)\n states the invariant the marker guard enforces: the ordered sequence of\n engines serving any one client request has length ≤ 2 with no repeat — only\n [codex], [anthropic], [codex,anthropic], [anthropic,codex] are\n possible. It is a documented constant, not a second runtime counter: the\n marker above is the only check that runs, and there is no\n fallbackHopDepth metadata key.\n\nA request that reaches this point already carrying a forged\ncodexOutboundFallbackAttempted-shaped marker from outside is not trusted —\nthe key lives on the server-side request context (ctx.metadata), not on\nanything the client can set on the wire, so there is no client-controlled way\nto spoof past gate 1.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.3 Loop prevention","lvl3":""}},
2683
2695
  {"objectID":"21189de88d4ffef1c2a4bbd0420442de71fe8d9fd6b9f6278867e39602e075c6","title":"9.4 What gets translated","url":"/docs/features/codex-proxy-support#94-what-gets-translated","content":"Request translation (src/lib/proxy/codexOutboundFallback.ts):\nCodex additional_tools namespaces (functions, collaboration, …) are\n flattened into one Claude tools array, preserving declaration order —\n namespace order, then tool order within each namespace — never regrouped or\n resorted by tool kind.\nA tool's kind (function vs custom) is read from the tool declaration's\n own type field, never inferred from which namespace it was declared under.\nFunction-tool JSON Schemas are dereferenced with inlineJsonSchema: plain,\n resolvable $ref/$defs (draft-07 definitions and 2020-12 $defs) are\n flattened into the inline schema and the pointer keys stripped entirely.\n A genuinely circular $ref degrades to {type: \"object\"} and is counted\n under the circular_ref_flattened degrade reason (see metrics below); a\n plain non-circular $ref is not.\nGrammar/custom tools (Lark grammar, regex format) have no JSON Schema\n equivalent, so they are wrapped as a single {input: string} parameter, with\n the response mapped back to a custom_tool_call item. This is lossy and\n explicitly flagged in code, and is the shipped behavior — see \"Sign-off\n status\" below.\nReasoning effort (minimal/low/medium/high/xhigh/max on the Codex\n side) maps to an Anthropic thinking budget via mapCodexReasoningToThinking:\n low→4096, medium→8192, high→16384, xhigh→24576, max→32768, clamped to\n [1024, max_tokens - 1024]. Thinking is left off when tool_choice is\n forced, or when the immediately preceding assistant turn called a tool.\nA non-object function_call_output/custom_tool_call_output argument falls\n back to {input: raw} in the translated history rather than failing the\n translation.\n\nResponse translation (codexResponsesFormat.ts / codexToAnthropicFallback.ts)\nconverts the Claude response — including SSE streaming — back into the Codex\nResponses wire shape the CLI expects, so a client cannot tell, from the wire\nalone, that its request was served by a different engine underneath.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.4 What gets translated","lvl3":""}},
2684
2696
  {"objectID":"4a8c83d10dbaa054203c48c374f7aed2688cb58670135943b0b2c6cd358cf129","title":"9.5 Accounting","url":"/docs/features/codex-proxy-support#95-accounting","content":"A translated request is billed and recorded exactly like any other proxied\nrequest on the serving engine — the same OTel usage record, cache/reasoning\nbuckets, and cost estimate described in Usage accounting\n(section 1) apply, attributed to the Anthropic or Vertex account that actually\nserved it, not to a Codex account. There is no separate \"fallback\" ledger; look\nat the served-by account's own usage.\n\nThe Codex route's final record names what served the turn: provider,\nmodel, account and accountType are the Claude target's, and\nrequestedModel stays the Codex model the client asked for. With the Anthropic\ntarget, the loopback's own /v1/messages record owns the usage, and the Codex\nrecord points to it through usageOwnerRequestId, so the call is counted once.\nWith Vertex there is no child record, so the Codex record carries the usage and\nis priced from the Vertex table.\n\nThe translated request marks its stable prefix with a 1-hour cache TTL. 1-hour\nwrites (usage.cache_creation.ephemeral_1h_input_tokens) are recorded as\ncacheCreation1hTokens, a subset of the cache-write total, and priced at 2x\nbase input, Anthropic's 1-hour rate on every Claude model. The rest of the\ncache writes keep the 5-minute rate (1.25x).\n\nThe token/cost metrics carry an origin attribute (ProxyRequestOrigin:\n\"native\" | \"codex-fallback\"), but only when it is not \"native\" — a\nplain Codex or Claude request emits the exact same label set it always has,\nwith no origin key at all, so existing dashboards and alerts over these\nmetrics are unaffected. Only a request actually served by this outbound-fallback\npath carries origin=\"codex-fallback\", set via\ntracer.setRequestOrigin(\"codex-fallback\") once a target has been dispatched\nand will serve the turn (both the Anthropic-loopback and Vertex targets); a\nrequest whose every target fails keeps \"native\".","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.5 Accounting","lvl3":""}},
2685
2697
  {"objectID":"efd21276881aaff463922d63ebd364e1b177ac659b6927d25c7858f7bb0a6190","title":"9.6 Metrics","url":"/docs/features/codex-proxy-support#96-metrics","content":"Two Codex-outbound-specific OTel counters, both emitted from\nsrc/lib/proxy/proxyTracer.ts:\n\n| Metric | Labels | Meaning |\n| ---------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| proxy_codex_outbound_schema_degraded_total | {reason, toolName} | A tool declaration's JSON Schema needed flattening or lost a feature on the way to a Claude tool. reason is one of circular_ref_flattened (a genuine cycle degraded to {type:\"object\"}) or strict_mode_flag_dropped (the Codex tool's strict flag has no Claude equivalent and was dropped). |\n| proxy_codex_outbound_unsupported_field_total | {field} | A Codex-outbound request field this repo cannot faithfully represent in the Claude request was dropped rather than failing the translation. |\n\nEvery other proxy metric in the existing dashboard (proxy_request_duration_ms,\nproxy_tokens_*, proxy_errors_total, proxy_fallback_attempts_total,\nproxy_fallback_success_total, proxy_fallback_failure_total, …) also fires\nfor a Codex-outbound-fallback request, on the serving engine, same as any other\nproxied call.\n\nproxy_cost_usd_total is a cumulative counter, not a gauge.","hierarchy":{"lvl0":"Features","lvl1":"Codex (ChatGPT) Support for NeuroLink Proxy","lvl2":"9.6 Metrics","lvl3":""}},
@@ -3017,7 +3029,7 @@
3017
3029
  {"objectID":"a7e9e7181f3c4e419e083e152c274ddaf929b0240ee057ece97504c909ccc8f2","title":"Best Practices","url":"/docs/features/guardrails#best-practices","content":"Name what you filter. The presets enable guardrails; your word list or filter model does the filtering.\nSet a default for every call you cannot audit. An instance or global default is applied even where a call site forgot middleware.\nPrefer specific terms or word-boundary patterns to short common words.\nTest with a real reply. Run a call that should be filtered and one that should not, and check both.\nTreat the model filter as best effort. It fails open and sees only text parts.","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Best Practices","lvl3":""}},
3018
3030
  {"objectID":"8380babcbfc88033aac779943fa372013989ce1cd79ebbc9f1803af06cf2e27e","title":"Related Features","url":"/docs/features/guardrails#related-features","content":"HITL Workflows - User approval for risky actions\nMiddleware Architecture - How the middleware chain is built\nBuilt-in Middleware - Analytics, guardrails and auto-evaluation\nGuardrails AI Integration - Pre-call evaluation and MiddlewareFactory usage","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Related Features","lvl3":""}},
3019
3031
  {"objectID":"4dcd9d3f7dd025aac5e11ee4820832266eed4420348ba5f439bac3b9035737ae","title":"Migration Notes","url":"/docs/features/guardrails#migration-notes","content":"Instance, global and environment defaults were added after guardrails were first released. They are optional: a call that passes its own middleware and sets no default behaves as it always did.","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Migration Notes","lvl3":""}},
3020
- {"objectID":"4360e3d584ae161b59c6d6c3d6c7fe074f475883b020805602930215117fd0d7","title":"Human-in-the-Loop (HITL) Workflows","url":"/docs/features/hitl","content":"Human-in-the-Loop (HITL) Workflows\n\nSince: v7.39.0 | Status: Stable | Availability: SDK\n\nOverview\n\nWhat it does: HITL pauses AI tool execution to request explicit user approval before performing risky operations like deleting files, modifying databases, or making expensive API calls.\n\nWhy use it: Prevent costly mistakes and give users control over potentially dangerous AI actions. Think of it as an \"Are you sure?\" dialog for AI assistant operations.\n\nOnly use HITL for truly risky operations. Overusing confirmation prompts degrades user experience and can lead to \"confirmation fatigue\" where users approve actions without reading them.\n\nCommon use cases:\nFile deletion or modification operations\nDatabase write/delete operations\nExpensive third-party API calls\nIrreversible actions (sending emails, posting to social media)\nOperations accessing sensitive data\n\nQuick Start\n\nSDK Example\nTool identifier used by the AI to invoke this function\nDescribes tool purpose to the LLM for proper selection\nTriggers HITL checkpoint before execution\nActual implementation only runs after user approval\n\nHandling Confirmation in Your UI\n\nHITL uses an event-based workflow where the SDK emits confirmation requests and your app responds with user decisions.\nGet the event emitter - NeuroLink is not itself an emitter, so requests and responses both go through getEventEmitter()\nSubscribe to confirmation requests - NeuroLink emits one before running a tool that needs approval\nShow your confirmation UI with the tool name, arguments and remaining time\nReply on the same emitter, echoing the request's confirmationId so the response is matched to its request\nApproval decision determines if tool executes\nOptional: Handle cases where user doesn't respond in time\n\nConfiguration\n\n| Option | Type | Default | Required | Description |\n| ---------------------- | --------- | ------- | -------- | ------------------------------------ |\n| requiresConfirmation | boolean | false | No | Mark tool as requiring user approval |\n\nTool Registration\n\nHow It Works\n\nExecution Flow\nAI requests tool execution → Tool executor checks if tool requires confirmation\nConfirmation required? → Returns USER_CONFIRMATION_REQUIRED error to LLM\nLLM asks user → \"I need to [action]. Is that okay?\"\nUser responds:\nApprove → UI sets confirmation_received = true and retries tool execution\nDeny → UI sends \"User cancelled\" message back to LLM\nTool executes → Permission flag immediately resets to false\n\nSecurity Features\nOne-time permissions: Each approval works for exactly one action\nNo reuse: AI cannot reuse old permissions for new actions\nAutomatic reset: Permission flag clears immediately after use\nFail-safe: Defaults to requiring permission when in doubt\n\nAPI Reference\n\nEvent Types\n\nAll HITL events ride the SDK emitter returned by\nneurolink.getEventEmitter(); emitter below is that object.\n\nConfirmation Request Event (hitl:confirmation-request):\n\nConfirmation Response (emit from your app):\n\nTimeout Event (hitl:timeout):\n\nTroubleshooting\n\nProblem: Tool executes without asking for permission\n\nCause: Tool not marked with requiresConfirmation: true\nSolution:\nAdd this boolean flag to any tool that performs risky operations\n\nProblem: AI keeps asking for confirmation repeatedly\n\nCause: Confirmation responses not being sent or sent with wrong confirmationId\nSolution:\nExtract confirmation ID from the request event\nAlways respond to every confirmation request\nCritical: Use the same confirmationId from the request\n\nProblem: Confirmation dialog doesn't show\n\nCause: Not listening to hitl:confirmation-request event\nSolution:\nRegister the event handler early in your application startup\nAll subsequent tool executions will trigger confirmations when needed\n\nBest Practices\n\nStore user confirmation preferences to avoid repeated prompts for the same action type. For example, if a user approves \"delete temporary files\" once, cache that preference for similar low-risk deletions in the same session.\n\nFor Developers\nMark tools conservatively - If an operation could cause problems, require confirmation\nClear prompts - Ensure users understand exactly what will happen\nTest confirmation flow - Verify it works smoothly in your UI\nLog approvals - Keep audit trail of user decisions\nHandle denials gracefully - Allow users to try alternative approaches\n\nWhat to Mark as Requiring Confirmation\n\n✅ Do require confirmation:\nFile deletions\nDatabase writes/deletes\nSending emails or messages\nMaking purchases or payments\nModifying production systems\n\n❌ Don't require confirmation:\nRead-only operations\nAnswering questions\nGenerating content\nSearching/fetching data\n\nRelated Features\nGuardrails Middleware - Content filtering and safety checks\nCustom Tools - Building your own tools with HITL\nMiddleware Architecture - Advanced request interception\n\nMigration Notes\n\nIf upgrading from versions before v7.39.0:\nReview all existing tools for risk assessment\nAdd requiresConfirmation: tr","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"","lvl3":""}},
3032
+ {"objectID":"4360e3d584ae161b59c6d6c3d6c7fe074f475883b020805602930215117fd0d7","title":"Human-in-the-Loop (HITL) Workflows","url":"/docs/features/hitl","content":"Human-in-the-Loop (HITL) Workflows\n\nSince: v7.39.0 | Status: Stable | Availability: SDK\n\nOverview\n\nWhat it does: HITL pauses AI tool execution to request explicit user approval before performing risky operations like deleting files, modifying databases, or making expensive API calls.\n\nWhy use it: Prevent costly mistakes and give users control over potentially dangerous AI actions. Think of it as an \"Are you sure?\" dialog for AI assistant operations.\n\nOnly use HITL for truly risky operations. Overusing confirmation prompts degrades user experience and can lead to \"confirmation fatigue\" where users approve actions without reading them.\n\nCommon use cases:\nFile deletion or modification operations\nDatabase write/delete operations\nExpensive third-party API calls\nIrreversible actions (sending emails, posting to social media)\nOperations accessing sensitive data\n\nQuick Start\n\nSDK Example\nTool identifier used by the AI to invoke this function\nDescribes tool purpose to the LLM for proper selection\nTriggers HITL checkpoint before execution\nActual implementation only runs after user approval\n\nHandling Confirmation in Your UI\n\nHITL uses an event-based workflow where the SDK emits confirmation requests and your app responds with user decisions.\nGet the event emitter - NeuroLink is not itself an emitter, so requests and responses both go through getEventEmitter()\nSubscribe to confirmation requests - NeuroLink emits one before running a tool that needs approval\nShow your confirmation UI with the tool name, arguments and remaining time\nReply on the same emitter, echoing the request's confirmationId so the response is matched to its request\nApproval decision determines if tool executes\nOptional: Handle cases where user doesn't respond in time\n\nConfiguration\n\n| Option | Type | Default | Required | Description |\n| ---------------------- | --------- | ------- | -------- | ------------------------------------ |\n| requiresConfirmation | boolean | false | No | Mark tool as requiring user approval |\n\nTool Registration\n\nHow It Works\n\nExecution Flow\nAI requests tool execution → Tool executor checks if tool requires confirmation\nConfirmation required? → Returns USER_CONFIRMATION_REQUIRED error to LLM\nLLM asks user → \"I need to [action]. Is that okay?\"\nUser responds:\nApprove → UI sets confirmation_received = true and retries tool execution\nDeny → UI sends \"User cancelled\" message back to LLM\nTool executes → Permission flag immediately resets to false\n\nSecurity Features\nOne-time permissions: Each approval works for exactly one action\nNo reuse: AI cannot reuse old permissions for new actions\nAutomatic reset: Permission flag clears immediately after use\nFail-safe: Defaults to requiring permission when in doubt\n\nBuilt-in tools\n\nHITL applies to the built-in tools (readFile, writeFile, listDirectory,\nanalyzeCSV, calculateMath, getCurrentTime, websearchGrounding and the\nopt-in executeBashCommand) exactly as it applies to tools you register:\ndangerousActions keywords and customRules are matched against the tool\nname on every model-driven call. Before the 2026-10 security audit fix (finding\nC3) built-in tools bypassed HITL entirely — only tools executed through the\ntool registry were gated — so a\nprompt-injected model could write files or, with the bash tool enabled, run\nshell commands with no confirmation, while the bash tool's own description\nclaimed otherwise.\n\nTwo built-ins change the machine and are confirmed on every call while HITL\nis enabled, whatever dangerousActions lists: writeFile and\nexecuteBashCommand. To gate them by keywords only, like every other tool,\nset confirmBuiltinTools: false:\n\nA denied built-in call is reported to the model as a failed tool call\n(Tool execution rejected by user: <reason>); the model sees the denial and\ncan continue without the side effect. A confirmation that returns\nmodifiedArguments runs the tool with those arguments. The confirmation\nrequest carries serverId: \"direct\" for a built-in tool.\n\nPer-call tools passed through generate({ tools }) are the host's own code\nand are not gated by HITL; wrap their execute yourself if they need it.\n\nAPI Reference\n\nEvent Types\n\nAll HITL events ride the SDK emitter returned by\nneurolink.getEventEmitter(); emitter below is that object.\n\nConfirmation Request Event (hitl:confirmation-request):\n\nConfirmation Response (emit from your app):\n\nTimeout Event (hitl:timeout):\n\nTroubleshooting\n\nProblem: Tool executes without asking for permission\n\nCause: Tool not marked with requiresConfirmation: true\nSolution:\nAdd this boolean flag to any tool that performs risky operations\n\nProblem: AI keeps asking for confirmation repeatedly\n\nCause: Confirmation responses not being sent or sent with wrong confirmationId\nSolution:\nExtract confirmation ID from the request event\nAlways respond to every confirmation request\nCritical: Use the same confirmationId from the request\n\nProblem: Confirmation dialog doesn't show\n\nCause: Not listening to hi","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"","lvl3":""}},
3021
3033
  {"objectID":"d85931f065438b4475cf5fc7e7854d68dda75d45b96963229ea7accb7f456a86","title":"Human-in-the-Loop (HITL) Workflows","url":"/docs/features/hitl#human-in-the-loop-hitl-workflows","content":"Since: v7.39.0 | Status: Stable | Availability: SDK","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Human-in-the-Loop (HITL) Workflows","lvl3":""}},
3022
3034
  {"objectID":"f1d18bf2b10a871a2c1ba24625cfdba4ced0186612c32e21ff05afa4d8c614b5","title":"Overview","url":"/docs/features/hitl#overview","content":"What it does: HITL pauses AI tool execution to request explicit user approval before performing risky operations like deleting files, modifying databases, or making expensive API calls.\n\nWhy use it: Prevent costly mistakes and give users control over potentially dangerous AI actions. Think of it as an \"Are you sure?\" dialog for AI assistant operations.\n\nOnly use HITL for truly risky operations. Overusing confirmation prompts degrades user experience and can lead to \"confirmation fatigue\" where users approve actions without reading them.\n\nCommon use cases:\nFile deletion or modification operations\nDatabase write/delete operations\nExpensive third-party API calls\nIrreversible actions (sending emails, posting to social media)\nOperations accessing sensitive data","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Overview","lvl3":""}},
3023
3035
  {"objectID":"654bf9d17ad9d1c9c4e13211c1207ecfc732fcf0ed9da7d530dab91fec0ae1fb","title":"SDK Example","url":"/docs/features/hitl#sdk-example","content":"Tool identifier used by the AI to invoke this function\nDescribes tool purpose to the LLM for proper selection\nTriggers HITL checkpoint before execution\nActual implementation only runs after user approval","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"SDK Example","lvl3":""}},
@@ -3026,6 +3038,7 @@
3026
3038
  {"objectID":"b60ffa2075bb3cd92fa381b95c086d4fcf0763098c18a2e86a4b846820bfdc2f","title":"Tool Registration","url":"/docs/features/hitl#tool-registration","content":"Tool Registration","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Tool Registration","lvl3":""}},
3027
3039
  {"objectID":"37135c25fca844145fb9e99bf6c00ce7aa59e5fce15d32037ecec0c212da1fe2","title":"Execution Flow","url":"/docs/features/hitl#execution-flow","content":"AI requests tool execution → Tool executor checks if tool requires confirmation\nConfirmation required? → Returns USER_CONFIRMATION_REQUIRED error to LLM\nLLM asks user → \"I need to [action]. Is that okay?\"\nUser responds:\nApprove → UI sets confirmation_received = true and retries tool execution\nDeny → UI sends \"User cancelled\" message back to LLM\nTool executes → Permission flag immediately resets to false","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Execution Flow","lvl3":""}},
3028
3040
  {"objectID":"4d86f092ca7e6b372a961736d886b359fa75e092f709de1fc0632865629f0e19","title":"Security Features","url":"/docs/features/hitl#security-features","content":"One-time permissions: Each approval works for exactly one action\nNo reuse: AI cannot reuse old permissions for new actions\nAutomatic reset: Permission flag clears immediately after use\nFail-safe: Defaults to requiring permission when in doubt","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Security Features","lvl3":""}},
3041
+ {"objectID":"a0bcb2831207c4628365c2a9a0c21588b0c9d3ccda0f793b63dd9bbff7d63467","title":"Built-in tools","url":"/docs/features/hitl#built-in-tools","content":"HITL applies to the built-in tools (readFile, writeFile, listDirectory,\nanalyzeCSV, calculateMath, getCurrentTime, websearchGrounding and the\nopt-in executeBashCommand) exactly as it applies to tools you register:\ndangerousActions keywords and customRules are matched against the tool\nname on every model-driven call. Before the 2026-10 security audit fix (finding\nC3) built-in tools bypassed HITL entirely — only tools executed through the\ntool registry were gated — so a\nprompt-injected model could write files or, with the bash tool enabled, run\nshell commands with no confirmation, while the bash tool's own description\nclaimed otherwise.\n\nTwo built-ins change the machine and are confirmed on every call while HITL\nis enabled, whatever dangerousActions lists: writeFile and\nexecuteBashCommand. To gate them by keywords only, like every other tool,\nset confirmBuiltinTools: false:\n\nA denied built-in call is reported to the model as a failed tool call\n(Tool execution rejected by user: <reason>); the model sees the denial and\ncan continue without the side effect. A confirmation that returns\nmodifiedArguments runs the tool with those arguments. The confirmation\nrequest carries serverId: \"direct\" for a built-in tool.\n\nPer-call tools passed through generate({ tools }) are the host's own code\nand are not gated by HITL; wrap their execute yourself if they need it.","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Built-in tools","lvl3":""}},
3029
3042
  {"objectID":"7854f3abc1202ff2f15b90ddfd8c29a88a2e6e71aa843e416f760a43ab570dfb","title":"Event Types","url":"/docs/features/hitl#event-types","content":"All HITL events ride the SDK emitter returned by\nneurolink.getEventEmitter(); emitter below is that object.\n\nConfirmation Request Event (hitl:confirmation-request):\n\nConfirmation Response (emit from your app):\n\nTimeout Event (hitl:timeout):","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Event Types","lvl3":""}},
3030
3043
  {"objectID":"5068502ff92414daee273da8919813c835390458398854e7834845b1a9b7bdef","title":"Problem: Tool executes without asking for permission","url":"/docs/features/hitl#problem-tool-executes-without-asking-for-permission","content":"Cause: Tool not marked with requiresConfirmation: true\nSolution:\nAdd this boolean flag to any tool that performs risky operations","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Problem: Tool executes without asking for permission","lvl3":""}},
3031
3044
  {"objectID":"385ab382fc18fbd69cc1e5d7da2909e9e5c70c897f97f372b61946a0273d456a","title":"Problem: AI keeps asking for confirmation repeatedly","url":"/docs/features/hitl#problem-ai-keeps-asking-for-confirmation-repeatedly","content":"Cause: Confirmation responses not being sent or sent with wrong confirmationId\nSolution:\nExtract confirmation ID from the request event\nAlways respond to every confirmation request\nCritical: Use the same confirmationId from the request","hierarchy":{"lvl0":"Features","lvl1":"Human-in-the-Loop (HITL) Workflows","lvl2":"Problem: AI keeps asking for confirmation repeatedly","lvl3":""}},
@@ -3312,7 +3325,7 @@
3312
3325
  {"objectID":"d6a663a2f913457801703cbfea385b5a2cba428988a3bdadc22decdcefb1df34","title":"Running the Test Suite","url":"/docs/features/mcp-enhancements#running-the-test-suite","content":"Running the Test Suite","hierarchy":{"lvl0":"Features","lvl1":"MCP Enhancements","lvl2":"Running the Test Suite","lvl3":""}},
3313
3326
  {"objectID":"b7897e60e94294066b1f6cc7bf6826a9775fceed2d09959e6ddfaaea03c5e278","title":"Environment Variables","url":"/docs/features/mcp-enhancements#environment-variables","content":"| Variable | Description | Default |\n| --------------- | ---------------------------------------- | ---------------------- |\n| TEST_PROVIDER | AI provider to use for integration tests | vertex |\n| TEST_MODEL | Model name override | Provider default model |","hierarchy":{"lvl0":"Features","lvl1":"MCP Enhancements","lvl2":"Environment Variables","lvl3":""}},
3314
3327
  {"objectID":"41243c9cf6b59f63bf30d887f10b3be94d6ab2926fb59964b17b25292ef90e89","title":"Test Coverage","url":"/docs/features/mcp-enhancements#test-coverage","content":"The suite contains 44 test functions with 172+ assertions organized across 9 parts:\n\n| Part | Module | Tests | Focus |\n| ---- | --------------------------------- | ----- | ----------------------------------------------------- |\n| 1 | Tool Router | 5 | Strategies, registration, affinity, health, events |\n| 2 | Tool Cache | 5 | Set/get, TTL, eviction, invalidation, stats |\n| 3 | Request Batcher | 5 | Batching, flush, drain, server grouping, events |\n| 4 | Tool Annotations | 5 | Inference, safety levels, validation, merge, filter |\n| 5 | Tool Converter | 5 | Bidirectional conversion, batch, function, sanitize |\n| 6 | Tool Integration & Middleware | 5 | Middleware chain, elicitation, timeout, retry, custom |\n| 7 | Enhanced Discovery & Multi-Server | 5 | Search, safety filter, server groups, namespacing |\n| 8 | Server Base, Exposure, Registry | 5 | Custom server, agent/workflow exposure, registry |\n| 9 | Server Capabilities & Elicitation | 4 | Resources, prompts, subscriptions, elicitation types |","hierarchy":{"lvl0":"Features","lvl1":"MCP Enhancements","lvl2":"Test Coverage","lvl3":""}},
3315
- {"objectID":"1f250cb2aa3fc19be6b69bf1883a325f5979f48d35c830dd3b09590df31fdd27","title":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","url":"/docs/features/mcp-tools-showcase","content":"MCP Tools Ecosystem: Built-in Tools + Any MCP Server\n\nSince: v7.0.0 | Status: Production Ready | MCP Version: 2024-11-05\n\nOverview\n\nNeuroLink's Model Context Protocol (MCP) integration provides a universal plugin system that transforms the SDK from a simple AI interface into a complete AI development platform. With 6 built-in core tools and the ability to connect any community MCP server (58+ cataloged in the server directory), you can extend AI capabilities to interact with filesystems, databases, APIs, cloud services, and custom enterprise systems.\n\nWhat is MCP?\n\nThe Model Context Protocol is an open standard (like USB-C for AI) that enables AI models to securely interact with external tools and data sources through a unified interface. Think of it as:\nFor Developers: A standardized way to connect AI to any external system\nFor AI Models: A tool registry with discoverable, executable functions\nFor Enterprises: A controlled, auditable way to extend AI capabilities\n\nWhy MCP Matters\n\n| Traditional Approach | MCP Approach | Benefit |\n| --------------------------------------- | --------------------------------- | ----------------------- |\n| Custom tool integrations per provider | One MCP tool works everywhere | 10x faster integration |\n| Manual tool discovery and configuration | Automatic tool registry | Zero-config tool usage |\n| Provider-specific tool formats | Universal JSON-RPC protocol | Provider portability |\n| Limited to SDK-defined tools | any community MCP server + custom | Unlimited extensibility |\n| Static tool set | Dynamic runtime addition | Adapt to changing needs |\n\nNeuroLink's Deep MCP Integration\n\nFactory-First Architecture: MCP tools work internally while users see simple factory methods:\n\nKey Features:\n99% Lighthouse Compatible: Existing MCP tools work with minimal changes\nDynamic Server Management: Add/remove MCP servers programmatically\nRich Context: 15+ fields including session, user, permissions, metadata\nPerformance Optimized: 0-11ms tool execution (target: \\<100ms)\nEnterprise Grade: Comprehensive error handling, audit logging, security\n\nQuick Start\n\nBuilt-in Core Tools (6)\n\nNeuroLink ships with 6 essential tools that require zero configuration:\ngetCurrentTime\n\nPurpose: Real-time clock with timezone support\n\nAuto-Available: Yes (always enabled)\n\nUse Cases:\nTimestamp generation\nTimezone conversions\nScheduling and reminders\nTime-based calculations\n\nExample:\n\nTool Schema:\nreadFile\n\nPurpose: Read file contents from filesystem\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nDocument analysis\nCode review\nConfiguration reading\nLog file processing\n\nExample:\n\nTool Schema:\nwriteFile\n\nPurpose: Write content to filesystem\n\nAuto-Available: Yes (with HITL approval recommended)\n\nUse Cases:\nGenerated content saving\nReport creation\nConfiguration updates\nCode generation output\n\nExample:\n\nSee the HITL guide for the approval flow.\n\nTool Schema:\nlistDirectory\n\nPurpose: List files and directories\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nProject structure analysis\nFile discovery\nDirectory traversal\nAsset inventory\n\nExample:\n\nTool Schema:\n\nFile tool roots\n\nreadFile, writeFile, listDirectory and analyzeCSV only touch paths inside their roots. By default that is the process working directory. Configure other roots per instance, and narrow them per call:\nPrecedence: per-call toolRoots, then instance tools.fileRoots, then the NEUROLINK_TOOL_ROOTS environment variable (a :-separated list; ; on Windows). A per-call root outside the instance roots is rejected, so a server that forwards caller options cannot widen file access.\nResolution: each root must be an existing directory and is resolved through symlinks once, when the request starts. A missing root rejects the call before any model request. fileRoots: [] denies all file access.\nContainment: target paths are resolved through symlinks too, and the prefix check is separator-bounded, so neither <root>/link → /etc nor a sibling such as /srv/workspace-evil gets through. A symlink that does not resolve is refused. On Linux and macOS, reads, writes and CSV parses open the checked path with O_NOFOLLOW (create mode with O_EXCL), so a link swapped in at the final path component after the check fails instead of redirecting the operation; Windows has no O_NOFOLLOW, so there only create mode carries that last-moment guarantee — the realpath check itself applies on every platform. analyzeCSV also refuses anything that is not a regular file (a FIFO, a device, a directory). listDirectory reports a symlink entry as type: \"symlink\" with the link's own metadata, never its target's. One race is not closed on any platform: a directory component swapped for a symlink between the check and the open is followed, because Node has no openat-style walk and O_NOFOLLOW covers only the final component. That needs an attacker writing","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"","lvl3":""}},
3328
+ {"objectID":"1f250cb2aa3fc19be6b69bf1883a325f5979f48d35c830dd3b09590df31fdd27","title":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","url":"/docs/features/mcp-tools-showcase","content":"MCP Tools Ecosystem: Built-in Tools + Any MCP Server\n\nSince: v7.0.0 | Status: Production Ready | MCP Version: 2024-11-05\n\nOverview\n\nNeuroLink's Model Context Protocol (MCP) integration provides a universal plugin system that transforms the SDK from a simple AI interface into a complete AI development platform. With 6 built-in core tools and the ability to connect any community MCP server (58+ cataloged in the server directory), you can extend AI capabilities to interact with filesystems, databases, APIs, cloud services, and custom enterprise systems.\n\nWhat is MCP?\n\nThe Model Context Protocol is an open standard (like USB-C for AI) that enables AI models to securely interact with external tools and data sources through a unified interface. Think of it as:\nFor Developers: A standardized way to connect AI to any external system\nFor AI Models: A tool registry with discoverable, executable functions\nFor Enterprises: A controlled, auditable way to extend AI capabilities\n\nWhy MCP Matters\n\n| Traditional Approach | MCP Approach | Benefit |\n| --------------------------------------- | --------------------------------- | ----------------------- |\n| Custom tool integrations per provider | One MCP tool works everywhere | 10x faster integration |\n| Manual tool discovery and configuration | Automatic tool registry | Zero-config tool usage |\n| Provider-specific tool formats | Universal JSON-RPC protocol | Provider portability |\n| Limited to SDK-defined tools | any community MCP server + custom | Unlimited extensibility |\n| Static tool set | Dynamic runtime addition | Adapt to changing needs |\n\nNeuroLink's Deep MCP Integration\n\nFactory-First Architecture: MCP tools work internally while users see simple factory methods:\n\nKey Features:\n99% Lighthouse Compatible: Existing MCP tools work with minimal changes\nDynamic Server Management: Add/remove MCP servers programmatically\nRich Context: 15+ fields including session, user, permissions, metadata\nPerformance Optimized: 0-11ms tool execution (target: \\<100ms)\nEnterprise Grade: Comprehensive error handling, audit logging, security\n\nQuick Start\n\nBuilt-in Core Tools (6)\n\nNeuroLink ships with 6 essential tools that require zero configuration:\ngetCurrentTime\n\nPurpose: Real-time clock with timezone support\n\nAuto-Available: Yes (always enabled)\n\nUse Cases:\nTimestamp generation\nTimezone conversions\nScheduling and reminders\nTime-based calculations\n\nExample:\n\nTool Schema:\nreadFile\n\nPurpose: Read file contents from filesystem\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nDocument analysis\nCode review\nConfiguration reading\nLog file processing\n\nExample:\n\nTool Schema:\nwriteFile\n\nPurpose: Write content to filesystem\n\nAuto-Available: Yes (confirmed on every call while HITL is enabled — see Built-in tools)\n\nUse Cases:\nGenerated content saving\nReport creation\nConfiguration updates\nCode generation output\n\nExample:\n\nSee the HITL guide for the approval flow.\n\nTool Schema:\nlistDirectory\n\nPurpose: List files and directories\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nProject structure analysis\nFile discovery\nDirectory traversal\nAsset inventory\n\nExample:\n\nTool Schema:\n\nFile tool roots\n\nreadFile, writeFile, listDirectory and analyzeCSV only touch paths inside their roots. By default that is the process working directory. Configure other roots per instance, and narrow them per call:\nPrecedence: per-call toolRoots, then instance tools.fileRoots, then the NEUROLINK_TOOL_ROOTS environment variable (a :-separated list; ; on Windows). A per-call root outside the instance roots is rejected, so a server that forwards caller options cannot widen file access.\nResolution: each root must be an existing directory and is resolved through symlinks once, when the request starts. A missing root rejects the call before any model request. fileRoots: [] denies all file access.\nContainment: target paths are resolved through symlinks too, and the prefix check is separator-bounded, so neither <root>/link → /etc nor a sibling such as /srv/workspace-evil gets through. A symlink that does not resolve is refused. On Linux and macOS, reads, writes and CSV parses open the checked path with O_NOFOLLOW (create mode with O_EXCL), so a link swapped in at the final path component after the check fails instead of redirecting the operation; Windows has no O_NOFOLLOW, so there only create mode carries that last-moment guarantee — the realpath check itself applies on every platform. analyzeCSV also refuses anything that is not a regular file (a FIFO, a device, a directory). listDirectory reports a symlink entry as type: \"symlink\" with the link's own metadata, never its target's. One race is not closed on any platform: a directory component swapped for a symlink between the check and the open is followed, because Node has no openat-style walk and O_NOFOLLOW covers only the final compo","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"","lvl3":""}},
3316
3329
  {"objectID":"d77f56e2563e08643ae18e7fea4540e640fdcdc7720690210a1b9c5c9a651cc2","title":"MCP Tools Ecosystem: Built-in Tools + Any MCP Server","url":"/docs/features/mcp-tools-showcase#mcp-tools-ecosystem-built-in-tools-any-mcp-server","content":"Since: v7.0.0 | Status: Production Ready | MCP Version: 2024-11-05","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"MCP Tools Ecosystem: Built-in Tools + Any MCP Server","lvl3":""}},
3317
3330
  {"objectID":"a2f242bd22bfb6fb857e7dc60825acc010064d863f53ef5ec236dbb81f1a6a88","title":"Overview","url":"/docs/features/mcp-tools-showcase#overview","content":"NeuroLink's Model Context Protocol (MCP) integration provides a universal plugin system that transforms the SDK from a simple AI interface into a complete AI development platform. With 6 built-in core tools and the ability to connect any community MCP server (58+ cataloged in the server directory), you can extend AI capabilities to interact with filesystems, databases, APIs, cloud services, and custom enterprise systems.","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"Overview","lvl3":""}},
3318
3331
  {"objectID":"6baec5fd689dfd70d9280b9efedecb44456fddef2a81d409f734d582aa0e856b","title":"What is MCP?","url":"/docs/features/mcp-tools-showcase#what-is-mcp","content":"The Model Context Protocol is an open standard (like USB-C for AI) that enables AI models to securely interact with external tools and data sources through a unified interface. Think of it as:\nFor Developers: A standardized way to connect AI to any external system\nFor AI Models: A tool registry with discoverable, executable functions\nFor Enterprises: A controlled, auditable way to extend AI capabilities","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"What is MCP?","lvl3":""}},
@@ -3322,10 +3335,10 @@
3322
3335
  {"objectID":"5dfaff379ed5f587fd940c02c6fef0a40290ac8c69c7a21afc28c2b4b38bf06a","title":"Built-in Core Tools (6)","url":"/docs/features/mcp-tools-showcase#built-in-core-tools-6","content":"NeuroLink ships with 6 essential tools that require zero configuration:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"Built-in Core Tools (6)","lvl3":""}},
3323
3336
  {"objectID":"ef6950cf75d93d830aa0383bb531987247e826d8de7903b4d48e5a4ab550cb86","title":"1. getCurrentTime","url":"/docs/features/mcp-tools-showcase#1-getcurrenttime","content":"Purpose: Real-time clock with timezone support\n\nAuto-Available: Yes (always enabled)\n\nUse Cases:\nTimestamp generation\nTimezone conversions\nScheduling and reminders\nTime-based calculations\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"1. getCurrentTime","lvl3":""}},
3324
3337
  {"objectID":"0415eee591ea3bb5e8bb01bdcea857d051be08a17783ada2a3f2f3e8c9abfbac","title":"2. readFile","url":"/docs/features/mcp-tools-showcase#2-readfile","content":"Purpose: Read file contents from filesystem\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nDocument analysis\nCode review\nConfiguration reading\nLog file processing\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"2. readFile","lvl3":""}},
3325
- {"objectID":"0cb0c9165418d9251e667c3cc9ffab1dc09a25dbb4360b6317d3e4fe85bae458","title":"3. writeFile","url":"/docs/features/mcp-tools-showcase#3-writefile","content":"Purpose: Write content to filesystem\n\nAuto-Available: Yes (with HITL approval recommended)\n\nUse Cases:\nGenerated content saving\nReport creation\nConfiguration updates\nCode generation output\n\nExample:\n\nSee the HITL guide for the approval flow.\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"3. writeFile","lvl3":""}},
3338
+ {"objectID":"0cb0c9165418d9251e667c3cc9ffab1dc09a25dbb4360b6317d3e4fe85bae458","title":"3. writeFile","url":"/docs/features/mcp-tools-showcase#3-writefile","content":"Purpose: Write content to filesystem\n\nAuto-Available: Yes (confirmed on every call while HITL is enabled — see Built-in tools)\n\nUse Cases:\nGenerated content saving\nReport creation\nConfiguration updates\nCode generation output\n\nExample:\n\nSee the HITL guide for the approval flow.\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"3. writeFile","lvl3":""}},
3326
3339
  {"objectID":"c27259323275ac78a5c96f275cba4c67336b351f10d6a5990acd9ecb33c015f4","title":"4. listDirectory","url":"/docs/features/mcp-tools-showcase#4-listdirectory","content":"Purpose: List files and directories\n\nAuto-Available: Yes (with filesystem access)\n\nUse Cases:\nProject structure analysis\nFile discovery\nDirectory traversal\nAsset inventory\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"4. listDirectory","lvl3":""}},
3327
3340
  {"objectID":"ea372be739ffab9dc37c0fce82830b21566da728269b630501d0755b353a2491","title":"File tool roots","url":"/docs/features/mcp-tools-showcase#file-tool-roots","content":"readFile, writeFile, listDirectory and analyzeCSV only touch paths inside their roots. By default that is the process working directory. Configure other roots per instance, and narrow them per call:\nPrecedence: per-call toolRoots, then instance tools.fileRoots, then the NEUROLINK_TOOL_ROOTS environment variable (a :-separated list; ; on Windows). A per-call root outside the instance roots is rejected, so a server that forwards caller options cannot widen file access.\nResolution: each root must be an existing directory and is resolved through symlinks once, when the request starts. A missing root rejects the call before any model request. fileRoots: [] denies all file access.\nContainment: target paths are resolved through symlinks too, and the prefix check is separator-bounded, so neither <root>/link → /etc nor a sibling such as /srv/workspace-evil gets through. A symlink that does not resolve is refused. On Linux and macOS, reads, writes and CSV parses open the checked path with O_NOFOLLOW (create mode with O_EXCL), so a link swapped in at the final path component after the check fails instead of redirecting the operation; Windows has no O_NOFOLLOW, so there only create mode carries that last-moment guarantee — the realpath check itself applies on every platform. analyzeCSV also refuses anything that is not a regular file (a FIFO, a device, a directory). listDirectory reports a symlink entry as type: \"symlink\" with the link's own metadata, never its target's. One race is not closed on any platform: a directory component swapped for a symlink between the check and the open is followed, because Node has no openat-style walk and O_NOFOLLOW covers only the final component. That needs an attacker writing into the workspace while the agent runs; if that is your threat model, isolate the process at the OS level rather than relying on this check alone. Relative paths resolve against the first root; a root of / contains every absolute path.","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"File tool roots","lvl3":""}},
3328
- {"objectID":"ad698242f08b12159d85a199152ed3aa7035bbde7fe3ba613977b8cf5371fbbd","title":"5. calculateMath","url":"/docs/features/mcp-tools-showcase#5-calculatemath","content":"Purpose: Complex mathematical calculations\n\nAuto-Available: Yes (always enabled)\n\nUse Cases:\nFinancial calculations\nStatistical analysis\nUnit conversions\nScientific computations\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"5. calculateMath","lvl3":""}},
3341
+ {"objectID":"ad698242f08b12159d85a199152ed3aa7035bbde7fe3ba613977b8cf5371fbbd","title":"5. calculateMath","url":"/docs/features/mcp-tools-showcase#5-calculatemath","content":"Purpose: Arithmetic calculations\n\nAuto-Available: Yes (always enabled)\n\nWhat it accepts: numbers, + - * / % **, parentheses, and the Math\nfunctions abs ceil floor round trunc sign sqrt cbrt pow exp log log2 log10 sin\ncos tan asin acos atan atan2 sinh cosh tanh hypot min max plus the constants\nPI E LN2 LN10 LOG2E LOG10E SQRT2 SQRT1_2, with or without the Math. prefix.\nThe expression is parsed and evaluated by a small arithmetic parser — it is\nnever run as JavaScript — so anything outside that grammar (process.exit(1),\nglobalThis, property access, assignment) is refused with an error, and a\nresult that is not a finite number (9**9**9, 1/0, sqrt(-1)) is reported\nas an error rather than as Infinity or NaN.\n\nUse Cases:\nFinancial calculations\nStatistical analysis\nUnit conversions\nScientific computations\n\nExample:\n\nTool Schema:","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"5. calculateMath","lvl3":""}},
3329
3342
  {"objectID":"143629fbd9246f9f135dab71bb41068eb3b7a1007a086298e48eadd77f4782c2","title":"6. websearchGrounding","url":"/docs/features/mcp-tools-showcase#6-websearchgrounding","content":"Purpose: Web search with result grounding\n\nAuto-Available: Only with Google Vertex AI provider\n\nUse Cases:\nReal-time information lookup\nFact verification\nCurrent events\nResearch augmentation\n\nExample:\n\nTool Schema:\n\nNote: This tool is provider-specific (Google Vertex AI only) and leverages Google's grounding capabilities.","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"6. websearchGrounding","lvl3":""}},
3330
3343
  {"objectID":"34487d043deb9df5927b3f66758bf17d6e28e070682a3d99a5f16c9628829088","title":"External MCP Servers","url":"/docs/features/mcp-tools-showcase#external-mcp-servers","content":"NeuroLink connects to the growing MCP ecosystem — any MCP-compliant server works; the server catalog lists 58+ across 6 major categories.","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"External MCP Servers","lvl3":""}},
3331
3344
  {"objectID":"e6cb3fca52d1f6935a4c7ab719365c88e7e4941b5297168480a25507d1535cff","title":"Quick Integration Example","url":"/docs/features/mcp-tools-showcase#quick-integration-example","content":"Quick Integration Example","hierarchy":{"lvl0":"Features","lvl1":"MCP Tools Ecosystem - Built-in Tools + Any MCP Server","lvl2":"Quick Integration Example","lvl3":""}},
@@ -3457,6 +3470,7 @@
3457
3470
  {"objectID":"b52c712e324d5d40df527e8a5877d9ea0ae63d2ae80bd022cfbaffc9c3c91a82","title":"Audio Input","url":"/docs/features/multimodal#audio-input","content":"| Provider | Native Audio | Transcription | Real-time | Max Duration | Notes |\n| -------------------- | ------------ | ------------- | --------- | ------------ | ----------------------------------- |\n| Google AI Studio | ✅ | ✅ | ✅ | 1 hour | Best for real-time voice |\n| Google Vertex AI | ✅ | ✅ | ✅ | 1 hour | Native Gemini audio support |\n| OpenAI | ❌ | ✅ Whisper | ❌ | 25 MB | Excellent transcription accuracy |\n| Azure OpenAI | ❌ | ✅ Whisper | ❌ | 25 MB | Via Whisper integration |\n| Anthropic | ❌ | Via fallback | ❌ | - | Uses transcription approach |\n| AWS Bedrock | ❌ | Via fallback | ❌ | - | Uses transcription approach |\n| Others | ❌ | Via fallback | ❌ | - | Audio transcribed before processing |\n\nFor comprehensive audio documentation, see the Audio Input Guide.","hierarchy":{"lvl0":"Features","lvl1":"Multimodal Capabilities Guide","lvl2":"Audio Input","lvl3":""}},
3458
3471
  {"objectID":"6c75d56315cf5bcec368645e07a84c0b2b067c8052da1028e9deb65d16aab9ee","title":"Video","url":"/docs/features/multimodal#video","content":"Two mechanisms, and which one a provider gets changes what it can answer.\n\nNative (inline) — the video file itself travels in the request. The model\nsees continuous motion and hears the audio track. Only Google's Gemini front\nends accept this today.\n\nFrame extraction — ffmpeg pulls keyframes at intervals and they are\nattached as ordinary images, alongside a metadata summary in the prompt text.\nThe model sees a handful of stills and hears nothing.\n\n| Provider | Mechanism | Inline ceiling | Audio track | Default frame budget |\n| ------------------------------------ | ---------------- | -------------- | ----------- | -------------------- |\n| Google AI Studio | Native (inline) | 14 MB | ✅ heard | 16 (fallback only) |\n| Google Vertex AI (Gemini models) | Native (inline) | 14 MB | ✅ heard | 16 (fallback only) |\n| OpenAI / Azure OpenAI | Frame extraction | – | ❌ | 8 |\n| Anthropic / AWS Bedrock | Frame extraction | – | ❌ | 8 |\n| Mistral | Frame extraction | – | ❌ | 8 |\n| LiteLLM / OpenRouter | Frame extraction | – | ❌ | 8 |\n| Ollama / llama.cpp | Frame extraction | – | ❌ | 4 |\n\nThe 14 MB ceiling is one shared source-byte budget for the whole request,\nnot a separate per-clip limit. Before a clip ships natively, its bytes are\nadded to the source bytes of every inline part already in the request, and\nthe clip is delivered only if the total stays within 14 MB. Those parts\ninclude images (keyframes among them), PDFs, audio and any clip accepted\nearlier. With nothing else attached, that reduces to the clip's own size.","hierarchy":{"lvl0":"Features","lvl1":"Multimodal Capabilities Guide","lvl2":"Video","lvl3":""}},
3459
3472
  {"objectID":"623b369433add73c32c5d31532a82b33ea81350ec9e96ead3a7dc6262db5c09f","title":"Supported containers","url":"/docs/features/multimodal#supported-containers","content":".mp4, .webm, .mov, .avi, .mkv, .mpeg, .flv, .wmv, .3gp and\nthe other formats in the detector's video registry are all accepted for frame\nextraction. Inline delivery is narrower — it is limited to the containers\nGemini reads directly (mp4, mpeg, mov, avi, flv, webm, wmv, 3gpp) — and a\ncontainer outside that set falls back to keyframes rather than being\nre-encoded. Transcoding a long recording mid-request costs minutes of CPU for\na payload that would usually breach the inline ceiling anyway.","hierarchy":{"lvl0":"Features","lvl1":"Multimodal Capabilities Guide","lvl2":"Supported containers","lvl3":""}},
3473
+ {"objectID":"534f015a043a985ba685574e5f7b8bca3e22a31c4f64c854a36eef0bcadcbc85","title":"Image Input","url":"/docs/features/multimodal#image-input","content":"Security: an image or file given as a URL is fetched only over HTTPS from\na public host, with redirects re-checked per hop; one given as a path is read\nfrom anywhere unless attachments.allowedRoots is set. Both are controlled\nby the attachments constructor option — see\nAttachment Security.","hierarchy":{"lvl0":"Features","lvl1":"Multimodal Capabilities Guide","lvl2":"Image Input","lvl3":""}},
3460
3474
  {"objectID":"0a6aa016f95cc342e4dd2a5dd050bd8ded76685337214426811889d4fdd671b7","title":"Quick Start","url":"/docs/features/multimodal#quick-start","content":"CLI:\n\nSDK:","hierarchy":{"lvl0":"Features","lvl1":"Multimodal Capabilities Guide","lvl2":"Quick Start","lvl3":""}},
3461
3475
  {"objectID":"5f31c7f6c3b80c85db3b5ac3bb71f81c22bbf21618f79f10db125106738c860d","title":"Image Formats Supported","url":"/docs/features/multimodal#image-formats-supported","content":"Accepted formats:\nJPEG (.jpg, .jpeg)\nPNG (.png)\nGIF (.gif)\nWebP (.webp)\nAVIF (.avif) - detected from content (avif/avis/avio brands) as well as extension\nBMP (.bmp), TIFF (.tif, .tiff) - detected from content\nHEIC (.heic, .heif) - detected from HEIC/HEIF content brands as well as extension; unsupported provider formats still require PNG/JPEG conversion\n\nThe MIME type is sniffed from the buffer's magic bytes, not assumed from the filename. A buffer whose bytes match no known image format is labeled application/octet-stream (with a warning) rather than silently mislabeled as JPEG.\n\nInput methods:\nBuffer objects - readFileSync() from Node.js\nLocal file paths - Relative or absolute paths\nHTTPS URLs - Remote images (auto-downloaded)","hierarchy":{"lvl0":"Features","lvl1":"Multimodal Capabilities Guide","lvl2":"Image Formats Supported","lvl3":""}},
3462
3476
  {"objectID":"61d57fa15cdce24f07122a756cd083739a35e5600ba42be04d2d147eb33a4f9d","title":"Image Alt Text (Accessibility)","url":"/docs/features/multimodal#image-alt-text-accessibility","content":"NeuroLink supports alt text for images, improving accessibility and providing additional context to AI models.\n\nAlt text best practices:\nKeep concise (under 125 characters ideal)\nFocus on key information the image conveys\nAlt text is automatically included as context in prompts","hierarchy":{"lvl0":"Features","lvl1":"Multimodal Capabilities Guide","lvl2":"Image Alt Text (Accessibility)","lvl3":""}},
@@ -3783,7 +3797,7 @@
3783
3797
  {"objectID":"00acd07b456b566352e3321cb9e1057daba22be2c7ceef57bdf7b71aa0033b5a","title":"Controlling a live share","url":"/docs/features/proxy-peer-sharing#controlling-a-live-share","content":"Every one of these takes effect on the borrower's next request — no restart.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Controlling a live share","lvl3":""}},
3784
3798
  {"objectID":"e2b45600391ae64c8daf3df738026f36e3e4072e95e3035bfd3cbd19ce06c805","title":"What the borrower sees","url":"/docs/features/proxy-peer-sharing#what-the-borrower-sees","content":"The lender answers a refusal with headers that say precisely what happened, so a\nborrower can tell \"you are out of credit\" from \"the upstream throttled me\":\n\n| Header | Meaning |\n| ----------------------------------- | ---------------------------------------------------------------------- |\n| x-neurolink-grant-status | active, paused, exhausted, revoked, expired, out-of-window |\n| x-neurolink-grant-reason | The precise refusal, e.g. slice_exhausted |\n| x-neurolink-grant-remaining-coins | Balance left on a metered grant |\n| retry-after | When coming back is worth anything |\n\nThe borrower parks a peer for a duration matched to the reason — minutes for a\ntransient problem, until the next window for an exhausted grant, a day for a\nrevoked one.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"What the borrower sees","lvl3":""}},
3785
3799
  {"objectID":"54f13127cdcf28726642c3ed1f85f99dde4942ae8b263eda2bca7f8cc9f8c875","title":"Asking before spending","url":"/docs/features/proxy-peer-sharing#asking-before-spending","content":"These routes let a borrower ask questions that cost nothing. All authenticate\nwith the share token, none touches an account, and none is subject to the\ngrant's rate or coin ceilings — they exist to ask whether spending is possible.\n\n| Route | Answers |\n| ---------------------- | -------------------------------------------------------------------------- |\n| GET /peer/handshake | Protocol version, node capabilities, and this grant's lifecycle state |\n| GET /peer/limits | Remaining coins, slice left per window, whether anything can serve you now |\n| POST /peer/heartbeat | Complete shares only: report spend, collect a refreshed lease or a stop |\n| GET /peer/receipts | Signed statements of what you were charged, ?since=<sequence> |\n| POST /peer/net | Settle one round of reciprocal netting |\n| POST /peer/note | Check a coin note, or redeem it into your balance |\n\n/peer/limits is scoped to the caller's own grant. It carries no account\nlabels and no per-account figures, so it cannot be used to describe — or count —\nthe lender's pool.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Asking before spending","lvl3":""}},
3786
- {"objectID":"13ed659f610b1cc92e63dd0001d19137d8c6417c035bd97fdefcdfd059e5d445","title":"Privacy","url":"/docs/features/proxy-peer-sharing#privacy","content":"Borrowed traffic is somebody else's conversation, so on the lender's node:\nRequest and response bodies are never captured for a borrowed request.\nx-neurolink-account and the pool counters are stripped from borrowed\n responses — that header carries the lender's account label, which for an OAuth\n account is their email address.\nGET /limits is refused for borrowed traffic. The operator view names\n every account and its quota; a borrower gets /peer/limits instead.\n/status releases account identity only to the update-control token once\n the gate is on, since a gated proxy is by definition one that may be exposed.\n\nThe borrower still receives the quota and grant headers their routing needs.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Privacy","lvl3":""}},
3800
+ {"objectID":"13ed659f610b1cc92e63dd0001d19137d8c6417c035bd97fdefcdfd059e5d445","title":"Privacy","url":"/docs/features/proxy-peer-sharing#privacy","content":"Borrowed traffic is somebody else's conversation, so on the lender's node:\nRequest and response bodies are never captured for a borrowed request.\nx-neurolink-account and the pool counters are stripped from borrowed\n responses on both the Claude and the Codex door — that header carries the\n lender's account label, which for an OAuth account is their email address.\nError messages name no account. A borrower whose request ends in a 401 or\n 403 is told how many pooled accounts need attention, never which ones.\nGET /limits and GET /accounts are refused for borrowed traffic. Both\n operator views name every account with its quota and spend, and a live\n refresh drives usage-API calls under the lender's tokens; a borrower gets\n /peer/limits instead.\n/status releases account identity only to the update-control token once\n the gate is on, since a gated proxy is by definition one that may be exposed.\n With an inbound token configured, /status is refused outright without it.\nThe borrower's own headers stay on the lender's node. Only protocol\n headers travel upstream; the share token, x-neurolink-*, trace context and\n CDN/forwarding identity (cf-connecting-ip, x-forwarded-for, …) are\n dropped, so a borrower's real address is never presented to the provider\n under the lender's identity.\nBorrowed Codex requests cannot touch account-side state.\n previous_response_id, prompt_cache_key, metadata and user are\n dropped and store is forced to false; instructions is the borrower's\n own prompt and is kept.\nBorrowed requests never write the header snapshot. The per-account\n identity snapshot is captured only from the lender's own Claude Code client.\n\nThe borrower still receives the quota and grant headers their routing needs.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Privacy","lvl3":""}},
3787
3801
  {"objectID":"ba10417b97113a48938219ff58018dc2290cebce4cf0485a7899b687cd2408ce","title":"Ordering","url":"/docs/features/proxy-peer-sharing#ordering","content":"A borrower's request falls through in this order:\nIts own accounts, in the usual quota-aware order.\nPeers, by priority — same models, same wire format, one extra hop.\nThe configured provider fallback chain (Gemini, OpenAI, …), which answers as\n a different model.\n\nA node with no accounts at all still borrows: peers are tried before the\n\"no credentials\" error is returned.\n\nA borrowed request is never forwarded on to another peer. Chaining a lend onto a\nlend would spend a third party's capacity under a grant that says nothing about\nthem.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Ordering","lvl3":""}},
3788
3802
  {"objectID":"03553aca660798a9b29c3b055eaafbe0e6205812404cdf198e7b1e11053de90e","title":"Two levels of sharing","url":"/docs/features/proxy-peer-sharing#two-levels-of-sharing","content":"Everything above describes live sharing: the borrower forwards each request\nthrough your proxy, so your gate is in the request path and your credentials\nnever leave your device. It is the default and the right choice for most people.\n\nComplete sharing trades that for availability. The borrower holds its own\ncredential on your account and calls the provider directly, so it keeps working\nwhen your laptop is shut.\n\n| | Live | Complete |\n| ---------------------------------- | ---------------------------- | -------------------------------------- |\n| Your credentials leave your device | No | Yes — a separate, independent grant |\n| Works while you are offline | No | Yes, until the lease's grace runs out |\n| Revocation | Instant, next request | Next heartbeat; grace period at worst |\n| Enforcement | Cryptographic | Cooperative, plus after-the-fact audit |\n| Extra latency | One hop | None |\n| You can see their prompts | Yes (never captured to disk) | No |","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Two levels of sharing","lvl3":""}},
3789
3803
  {"objectID":"96415489eaad02f2eb04cad449f1394938511c78a4ccccaca3864712c0ea634b","title":"Provisioning a complete share","url":"/docs/features/proxy-peer-sharing#provisioning-a-complete-share","content":"Provisioning is split: the borrower generates the PKCE verifier and you only\nauthorize. You never hold a token for the credential you just minted, so there\nis nothing for you to leak, re-send, or forget to delete.\nThe borrower asks (they must already have your share token added as a\npeer):\n\nThis generates a verifier locally, sends only its SHA-256 challenge over the\nauthenticated grant, and keeps the verifier on their machine.\nYou authorize:\n\nIt prints an authorization URL carrying their challenge. Sign in, authorize,\nand paste the code back:\nThe borrower collects:\n\nThey exchange the code with their own verifier, on their own machine, and the\ntokens land only there.\n\nThe code is single-use and expires with the request (15 minutes). Intercepting\nit buys nothing: the token endpoint will not exchange a code without the\nverifier, and the verifier never crossed the wire.\n\nThis does not copy your own tokens. Anthropic's OAuth refresh tokens rotate,\nso two devices on one refresh chain invalidate each other — and the loser gets\ndisabled. That loser could be you.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Provisioning a complete share","lvl3":""}},
@@ -3794,7 +3808,7 @@
3794
3808
  {"objectID":"59d8c63004b18fe158932e15b0bc1060bc213070c0490cea0df375e93dbfca54","title":"Receipts","url":"/docs/features/proxy-peer-sharing#receipts","content":"Until a charge is settled, the lender's word is the only record of it. A receipt\nmakes that checkable: the lender signs every settlement, and the statement\ncarries the usage it was computed from, so a borrower recomputes the charge\nrather than accepting it.\n\nThe borrower's check answers three separate questions, because they have three\ndifferent causes:\n\n| Finding | Means |\n| ---------- | -------------------------------------------------------------------- |\n| Unverified | The receipt did not come from this lender's secret |\n| Miscounted | The coin figure disagrees with the receipt's own usage block |\n| Gap | A charge was never shown to you — sequences are contiguous per grant |\n\nThe signing key is a per-grant receipt secret, minted with the grant and\ncarried in the share link after the token (#<token>.<secret>). It deliberately\nsurvives share rotate, so receipts issued under an old token stay checkable. A\npeer added by hand takes it with --receipt-secret; without one, charges are\nlisted but nothing is verified, and the CLI says so.\n\nA receipt proves authorship only to the holder of the key — it settles a dispute\nbetween the two parties to it and is worth nothing to a third. That is the cost\nof an HMAC, and it is the same trade leases make.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Receipts","lvl3":""}},
3795
3809
  {"objectID":"711f9c7297e0d4fec75353c49340d06bda141f1db122819439907ac0a60c22f8","title":"Reciprocal netting","url":"/docs/features/proxy-peer-sharing#reciprocal-netting","content":"Two nodes that lend to each other otherwise run two one-way debts that never\nmeet. Netting forgives the overlap:\n\nIf Bob has consumed 300 coins of Alice's and Alice has consumed 500 of Bob's,\n300 cancels on both sides. Positions are stated as cumulative totals, never\nas a delta, so running it twice forgives nothing the second time rather than\npaying out again. When the two sides' records of what has already been forgiven\ndisagree, the larger wins — forgiving less is the direction that cannot hand out\ncoins twice.\n\nNetting needs a grant in each direction. peer net looks for a grant you issued\nlabelled with the peer's own name; point it elsewhere with --reciprocal <label>.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Reciprocal netting","lvl3":""}},
3796
3810
  {"objectID":"8270c4f2395c857da7da0c55222fcac75f8da4e69cc2a937e9bc12dc29d0c8ae","title":"Transferable coin notes","url":"/docs/features/proxy-peer-sharing#transferable-coin-notes","content":"A grant's coins are bound to the pair that agreed them. A note is not: it is a\nbearer credit against the issuing node, redeemable once by whoever holds it.\n\nThat is A-issued, B-held, C-redeemed: the note travels out of band, and\nwhoever ends up with it redeems against A, into a grant A issued them. Marking\nspent and crediting happen under one lock, so two holders racing the same note\nproduce exactly one credit and one spent.\n\nA holder cannot verify a note offline — it is signed with a secret only the\nissuer has — so --check asks the issuer instead. That step has to exist\nregardless of the signature scheme, because a valid signature says nothing about\nwhether the note has already been spent.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Transferable coin notes","lvl3":""}},
3797
- {"objectID":"6e5f9a49dd3a55b0389b7f2a9e847f8480f4c1cd772c3da591e0e20e917ea5ed","title":"The share listener","url":"/docs/features/proxy-peer-sharing#the-share-listener","content":"A proxy that lends anything runs two listeners:\n\n| Port | Who it is for | Untokened request |\n| ---------------------- | ----------------------- | ----------------- |\n| Main (--port) | Your own client | Served, as always |\n| Share (--share-port) | Peers, through a tunnel | Refused |\n\nIt appears on its own the moment you issue the first grant and goes away when\nthe last one is revoked — no restart on either edge — and share create tells\nyou the port. Expose that one.\n\nThe split exists because the gate refuses untokened requests and your own client\nsends none. An address check could not stand in for it: cloudflared and every\nreverse proxy connect from 127.0.0.1, so tunnelled traffic is\nindistinguishable from local traffic by origin. The listener a connection was\naccepted on is not something a client can influence, which is why the decision\nis made there.\n\nNEUROLINK_PROXY_REQUIRE_GRANT=1 still exists and now means something narrower:\ngate the main port as well. Reach for it only when you bind 0.0.0.0 with\nnothing in front of it — it refuses your own client too, which is what made it\nawkward in the first place.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"The share listener","lvl3":""}},
3811
+ {"objectID":"6e5f9a49dd3a55b0389b7f2a9e847f8480f4c1cd772c3da591e0e20e917ea5ed","title":"The share listener","url":"/docs/features/proxy-peer-sharing#the-share-listener","content":"A proxy that lends anything runs two listeners:\n\n| Port | Who it is for | Untokened request |\n| ---------------------- | ----------------------- | ----------------- |\n| Main (--port) | Your own client | Served, as always |\n| Share (--share-port) | Peers, through a tunnel | Refused |\n\nIt appears on its own the moment you issue the first grant and goes away when\nthe last one is revoked — no restart on either edge — and share create tells\nyou the port. Expose that one.\n\nThe split exists because the gate refuses untokened requests and your own client\nsends none. An address check could not stand in for it: cloudflared and every\nreverse proxy connect from 127.0.0.1, so tunnelled traffic is\nindistinguishable from local traffic by origin. The listener a connection was\naccepted on is not something a client can influence, which is why the decision\nis made there.\n\nNEUROLINK_PROXY_REQUIRE_GRANT=1 still exists and now means something narrower:\ngate the main port as well. It is one of the three things that permit a\nnon-loopback bind (the others are an inbound token and an explicit\n--allow-unauthenticated; see the Claude proxy guide's \"Inbound\nauthentication\"). It refuses your own client too, which is what made it awkward\nin the first place — an inbound token is usually the better fit.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"The share listener","lvl3":""}},
3798
3812
  {"objectID":"92e5e510e92a4cf4d45a90d208c65ad705c1da31d34031543140474c70f7954f","title":"Exposure","url":"/docs/features/proxy-peer-sharing#exposure","content":"Any address a borrower can reach works — a domain you already own behind nginx or\nCaddy, a permanent named tunnel, a VPN hostname, a plain DNS record. Nothing in\nthe sharing path knows or cares how you got one.\n\nRecord it once and every link is minted against it:\n\nPoint that address at the share port, not the main one.\n\nshare url also probes that address and warns if it answers a request carrying\nno share token — the check matters more when you front the proxy yourself, since\nnothing else in your stack knows the gate is supposed to be on.\n\nneurolink proxy expose is a convenience for people who have no address yet: it\nwraps cloudflared, picks the share listener automatically, and refuses to open\na tunnel to a port that serves untokened requests. If you already have a domain,\nskip it entirely.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Exposure","lvl3":""}},
3799
3813
  {"objectID":"dc8fe9cc83072284aacc3c7ec009908282feb617037b43920cf216e3f9671eaa","title":"Exposure with cloudflared","url":"/docs/features/proxy-peer-sharing#exposure-with-cloudflared","content":"neurolink proxy expose wraps cloudflared, and refuses to open a tunnel to a\nproxy that serves untokened requests — it checks by asking the proxy, not by\nreading configuration. --force overrides that, and should only be used when\nsomething in front of the tunnel already authenticates every request.\n\nQuick tunnels get a new URL on every restart, which rots every peer's\nconfiguration. Use a named tunnel (--named <tunnel>) for a peer you expect to\nkeep.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"Exposure with cloudflared","lvl3":""}},
3800
3814
  {"objectID":"e4334c89b485facc220fc359dcd520ec9e8464dff64701db51837e14c83a4ec2","title":"What an exposed proxy still reveals","url":"/docs/features/proxy-peer-sharing#what-an-exposed-proxy-still-reveals","content":"On the share listener — or on the main port with\nNEUROLINK_PROXY_REQUIRE_GRANT=1 — /v1/messages and the Codex and\nOpenAI-compatible routes all require a share token. Two endpoints stay open on\npurpose, because a tunnel and a peer both need a liveness probe:\n/health — status, readiness, version, uptime. No account data.\n/status — counters, health and routing state, with account identity\n redacted: labels become account-1, account-2, and the primary-account\n block is blanked. A caller holding the update-control token sees the real\n values.\n\nA borrower's request reaches the same routes as yours, so image references are\nvetted for it too: on the OpenAI-compatible and Gemini routes (and on /v1/messages\nwhen a model is routed to another provider) a borrower can send data: URIs and\npublic https:// URLs, but a local path, an http:// URL or any other scheme is\nrefused with a 400 before anything is read or fetched. A borrower cannot make\nyour proxy read a file on your disk or call a service on your network.\n\nA loopback allowlist would not have worked here: cloudflared runs on the same\nmachine and connects to 127.0.0.1, so tunnelled traffic arrives from loopback\nexactly like the operator's own CLI does. Separating the two by listener is\nwhat makes the distinction real.","hierarchy":{"lvl0":"Features","lvl1":"Proxy Peer Sharing","lvl2":"What an exposed proxy still reveals","lvl3":""}},
@@ -3850,7 +3864,7 @@
3850
3864
  {"objectID":"aa0e400b06c02bd95f62a3405bb6e7476f408be8b2a0f25d35394ff73d3c99e0","title":"CLI Usage","url":"/docs/features/rag#cli-usage","content":"NeuroLink CLI provides commands for RAG operations.","hierarchy":{"lvl0":"Features","lvl1":"RAG Document Processing Guide","lvl2":"CLI Usage","lvl3":""}},
3851
3865
  {"objectID":"7553cbd6b9ad2b078a96593af5963f372bb805e4de8cd1c4867d03a0e63709b5","title":"Document Processing","url":"/docs/features/rag#document-processing","content":"Document Processing","hierarchy":{"lvl0":"Features","lvl1":"RAG Document Processing Guide","lvl2":"Document Processing","lvl3":""}},
3852
3866
  {"objectID":"742b5d9e94830c07d50459abb34ff0e30f14dc4e9899893638506ba3ec92b2c8","title":"Index Management","url":"/docs/features/rag#index-management","content":"Index Management","hierarchy":{"lvl0":"Features","lvl1":"RAG Document Processing Guide","lvl2":"Index Management","lvl3":""}},
3853
- {"objectID":"9a92de0f52e91c75fda77a3792f89a8bfa5288fe15fc3619677507aa6fb73579","title":"Simplified RAG API (rag: { files })","url":"/docs/features/rag#simplified-rag-api-rag-files-","content":"Since: v9.2.0 | Recommended for most use cases\n\nInstead of manually creating chunkers, vector stores, and tools, pass rag: { files } directly to generate() or stream(). NeuroLink handles the entire pipeline automatically.","hierarchy":{"lvl0":"Features","lvl1":"RAG Document Processing Guide","lvl2":"Simplified RAG API (rag: { files })","lvl3":""}},
3867
+ {"objectID":"9a92de0f52e91c75fda77a3792f89a8bfa5288fe15fc3619677507aa6fb73579","title":"Simplified RAG API (rag: { files })","url":"/docs/features/rag#simplified-rag-api-rag-files-","content":"Security: rag.files paths are read under the instance's\nattachments.allowedRoots (a path outside them is skipped with a warning),\neach file is capped at 50 MiB, and WebLoader fetches only HTTPS public\nhosts unless its attachmentPolicy says otherwise. See\nAttachment Security.\n\nSince: v9.2.0 | Recommended for most use cases\n\nInstead of manually creating chunkers, vector stores, and tools, pass rag: { files } directly to generate() or stream(). NeuroLink handles the entire pipeline automatically.","hierarchy":{"lvl0":"Features","lvl1":"RAG Document Processing Guide","lvl2":"Simplified RAG API (rag: { files })","lvl3":""}},
3854
3868
  {"objectID":"70b4c3bc4c6a2b9e8d2a6b3fe942a1da6ba7f9f0b1b2c990bb1ebba1fbf501cb","title":"SDK Usage","url":"/docs/features/rag#sdk-usage","content":"SDK Usage","hierarchy":{"lvl0":"Features","lvl1":"RAG Document Processing Guide","lvl2":"SDK Usage","lvl3":""}},
3855
3869
  {"objectID":"31ca80ce85490491c8164dbf2af11ee83adf19fe841468505d441381634cd08d","title":"CLI Usage","url":"/docs/features/rag#cli-usage-1","content":"CLI Usage","hierarchy":{"lvl0":"Features","lvl1":"RAG Document Processing Guide","lvl2":"CLI Usage","lvl3":""}},
3856
3870
  {"objectID":"50fb4edb089ac0e5f845990fb7d56ef102e1d7f5a6340ac4f6d28ea305db09ec","title":"CLI Flags Reference","url":"/docs/features/rag#cli-flags-reference","content":"| Flag | Type | Default | Description |\n| --------------------- | ---------- | ------------- | ------------------------------------------------------------------------------------------------------------------- |\n| --rag-files | string[] | - | File paths to load for RAG context |\n| --rag-strategy | string | auto-detected | Chunking strategy (character, recursive, sentence, token, markdown, html, json, latex, semantic, semantic-markdown) |\n| --rag-chunk-size | number | 1000 | Maximum chunk size in characters |\n| --rag-chunk-overlap | number | 200 | Overlap between adjacent chunks |\n| --rag-top-k | number | 5 | Number of top results to retrieve |","hierarchy":{"lvl0":"Features","lvl1":"RAG Document Processing Guide","lvl2":"CLI Flags Reference","lvl3":""}},
@@ -4052,9 +4066,9 @@
4052
4066
  {"objectID":"19352c9bf82d208bbd76e4303e3e35ac7d4f7497562a4f1ee006d8cf1fae5f6b","title":"The wording that made this work: a measured A/B result","url":"/docs/features/tool-routing-decision-model#the-wording-that-made-this-work-a-measured-ab-result","content":"The first phrasing tried was the obvious one: \"answering this request will\nrequire calling at least one tool from this server,\" with false meaning\n\"this server is unrelated, OR the request needs no tool at all.\" Measured\nagainst a 10-request × 5-server labelled set, it separated correctly but\nweakly — unrelated servers averaged p = 0.31 and reached as high as\n0.80, so at the 0.6 drop bar only 12 of 39 unneeded servers were\nactually dropped.\n\nThree changes fixed it: naming the server explicitly, asking in the present\ntense about what carrying out the request involves rather than what\n\"will require,\" and splitting the bundled false criterion (which was\nreally two separate claims joined by \"or\") into one single claim. That\nmoved unrelated servers to a mean of p = 0.03 with a maximum of 0.35\n— 37 of 39 dropped at the same 0.6 bar, still with zero wrong drops.\n\nThe lesson generalises past this one question: a decision model reads\nliterally, and an \"or\" in a criterion is two questions wearing one coat. Each\nhalf of a compound criterion pulls the answer toward the middle whenever\nonly one half is true, which is exactly the muddy, hard-to-gate signal the\nfirst version produced.","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"The wording that made this work: a measured A/B result","lvl3":""}},
4053
4067
  {"objectID":"9c9af1c1ff58051674501cb10c371fdcf50758c935a2dfa168df9719969bb7af","title":"What this is bad at","url":"/docs/features/tool-routing-decision-model#what-this-is-bad-at","content":"It reasons about servers, not individual tools. The unit of decision is\n a whole MCP server; a server with twenty tools where the request needs one\n is kept or dropped as a unit, not tool-by-tool.\nThe description quality bounds the question quality. A server with no\n declared description falls back to a comma-joined list of its own tool\n names, which carries much less signal than a well-written one-line\n description — the wording fix above only helps once the server's own text\n is legible to a literal reader.\nA close call still resolves to \"keep.\" There is no partial exclusion;\n anything from a coin flip up to just under 0.6 confidence is treated\n identically to a confident true.\nIt shares the base model's general limits — literal reading, no\n arithmetic, accuracy sensitive to a noisy or oversized state — all\n described in\n what decide is bad at.\nThe query is untrusted input sent as state, and this module does not\n sanitize it. The reach is deliberately bounded, not zero. Server ids are\n never read back off the wire (answers are matched by position, not by name),\n so a crafted query cannot name a tool that was not already registered, and\n the result is only a denylist appended to excludeTools. It can still steer\n a verdict: a confident false (0.6 by default) withholds that server's\n tools for the turn. Do not rely on this router as a security control; see\n the Untrusted input bullet under\n what decide is bad at.","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"What this is bad at","lvl3":""}},
4054
4068
  {"objectID":"b55a36dccb54a184ce24fa850942a8f5455cbe7f4391a23fc94f326aebeae19e","title":"See also","url":"/docs/features/tool-routing-decision-model#see-also","content":"The decide inference type\nModel routing with a decision model\nRelevance-driven compaction","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"See also","lvl3":""}},
4055
- {"objectID":"868aff1102e3175cc67c89cc4d5bc4a20b86b1666dcd8d010b976d4b16364ece","title":"The transcribe inference type","url":"/docs/features/transcribe","content":"The transcribe inference type\n\nNeuroLink has four inference types. transcribe is the one that starts from audio:\n\n| Type | Call | Produces |\n| ---------------- | --------------------------------------------------- | -------------------------------- |\n| generate | neurolink.generate() | text |\n| stream | neurolink.stream() | text, incrementally |\n| decide | neurolink.decide() | typed judgements |\n| transcribe | neurolink.transcribe() / transcribeStream() | text from audio, with timing |\n\nIt runs through any registered speech-to-text (STT) engine and adds the layers\nthat make an engine usable on real speech: a dictionary of names and\njargon, a correction pass guarded by the decision model and finished by an\nLLM rewrite, a second-opinion engine, a fallback engine for audio the\nfirst one cannot read, and client-side streaming for engines that only\ntake whole files.\n\nZero configuration. With no STT provider configured, transcribe() uses\nWhistle, the built-in local engine: it runs on this machine, needs no key\nand no network; its model files (about 18 MB) ship inside the package.\nWhistle reads English, German, French, Spanish, Italian, Dutch and Polish; for\nother languages, accents, noisy rooms or heavy jargon, configure a cloud or\nself-hosted engine, or add a dictionary and correction.\n\nSDK\n\naudio accepts bytes (Buffer, ArrayBuffer, Uint8Array), a path, a\nfile:// URL or an http(s):// URL. The container is inferred from the path\nor the bytes; pass format (\"wav\", \"mp3\", \"m4a\", \"ogg\", \"opus\",\n\"webm\", \"flac\", \"mp4\", \"pcm16\" …) for a buffer it cannot be read from.\n\nOptions\n\n| Option | Meaning |\n| ---------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| provider | STT provider name or alias. Default: NEUROLINK_STT_PROVIDER, then the first configured provider, then Whistle. |\n| model | Model of that provider. Default: NEUROLINK_STT_MODEL, only when the provider also came from the environment. |\n| language | Language code or locale, or \"auto\". Default: NEUROLINK_STT_LANGUAGE, else the engine detects it. |\n| prompt | Context prompt for engines that bias on one; dictionary terms are appended to it. |\n| diarization | Label speakers, on engines that diarize. |\n| wordTimestamps | Ask for word-level timings. |\n| dictionary | Names and jargon, see Dictionary. |\n| correction | The correction layer, see Correction. |\n| fallback | { provider, model?, when? }, see Fallback. |\n| streaming | Tuning for transcribeStream(), see Streaming. |\n| timeoutMs | Whole-call timeout. |\n| credentials | Per-call credentials; the stt slice (credentials.stt.whisper.apiKey, credentials.stt.deepgram.apiKey …) beats the env vars. |\n\nResult\n\nTranscribeResult is the engine's STTResult (text, confidence,\nlanguage, duration, words, segments, speakers, metadata) plus what\nthe layers did:\n\n| Field | Meaning |\n| ------------------ | -------------------------------------------------------------------------------------------------------- |\n| raw | The engine's text before any correction. |\n| text | The final text — the corrected text when correction changed it, else raw. |\n| corrected | Present only when correction changed the text. |\n| languageDetected | false when the engine reported a low language-detection score. |\n| languageScores | Candidate languages with the engine's own scores, where it reports them. |\n| decisions | One record per dictionary candidate: what was heard, the ter","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"","lvl3":""}},
4069
+ {"objectID":"868aff1102e3175cc67c89cc4d5bc4a20b86b1666dcd8d010b976d4b16364ece","title":"The transcribe inference type","url":"/docs/features/transcribe","content":"The transcribe inference type\n\nNeuroLink has four inference types. transcribe is the one that starts from audio:\n\n| Type | Call | Produces |\n| ---------------- | --------------------------------------------------- | -------------------------------- |\n| generate | neurolink.generate() | text |\n| stream | neurolink.stream() | text, incrementally |\n| decide | neurolink.decide() | typed judgements |\n| transcribe | neurolink.transcribe() / transcribeStream() | text from audio, with timing |\n\nIt runs through any registered speech-to-text (STT) engine and adds the layers\nthat make an engine usable on real speech: a dictionary of names and\njargon, a correction pass guarded by the decision model and finished by an\nLLM rewrite, a second-opinion engine, a fallback engine for audio the\nfirst one cannot read, and client-side streaming for engines that only\ntake whole files.\n\nZero configuration. With no STT provider configured, transcribe() uses\nWhistle, the built-in local engine: it runs on this machine, needs no key\nand no network; its model files (about 18 MB) ship inside the package.\nWhistle reads English, German, French, Spanish, Italian, Dutch and Polish; for\nother languages, accents, noisy rooms or heavy jargon, configure a cloud or\nself-hosted engine, or add a dictionary and correction.\n\nSDK\n\nSecurity: audio given as a URL must be HTTPS to a public host (set\nattachments.allowInsecureUrls / allowPrivateNetwork on the instance to\nrelax that) and is capped while it downloads; audio given as a path is\nbounded by attachments.allowedRoots when configured. See\nAttachment Security.\n\naudio accepts bytes (Buffer, ArrayBuffer, Uint8Array), a path, a\nfile:// URL or an http(s):// URL. The container is inferred from the path\nor the bytes; pass format (\"wav\", \"mp3\", \"m4a\", \"ogg\", \"opus\",\n\"webm\", \"flac\", \"mp4\", \"pcm16\" …) for a buffer it cannot be read from.\n\nOptions\n\n| Option | Meaning |\n| ---------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| provider | STT provider name or alias. Default: NEUROLINK_STT_PROVIDER, then the first configured provider, then Whistle. |\n| model | Model of that provider. Default: NEUROLINK_STT_MODEL, only when the provider also came from the environment. |\n| language | Language code or locale, or \"auto\". Default: NEUROLINK_STT_LANGUAGE, else the engine detects it. |\n| prompt | Context prompt for engines that bias on one; dictionary terms are appended to it. |\n| diarization | Label speakers, on engines that diarize. |\n| wordTimestamps | Ask for word-level timings. |\n| dictionary | Names and jargon, see Dictionary. |\n| correction | The correction layer, see Correction. |\n| fallback | { provider, model?, when? }, see Fallback. |\n| streaming | Tuning for transcribeStream(), see Streaming. |\n| timeoutMs | Whole-call timeout. |\n| credentials | Per-call credentials; the stt slice (credentials.stt.whisper.apiKey, credentials.stt.deepgram.apiKey …) beats the env vars. |\n\nResult\n\nTranscribeResult is the engine's STTResult (text, confidence,\nlanguage, duration, words, segments, speakers, metadata) plus what\nthe layers did:\n\n| Field | Meaning |\n| ------------------ | -------------------------------------------------------------------------------------------------------- |\n| raw | The engine's text before any correction. |\n| text | The final text — the corrected text when correction changed it, else raw. |\n| corrected | Present only when correction changed the text. |\n| languageDetected | false when the engine repo","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"","lvl3":""}},
4056
4070
  {"objectID":"022bf9f0cc0df8253fa229c043dc4762f656ee2c7d69e782484cb8425973befb","title":"The transcribe inference type","url":"/docs/features/transcribe#the-transcribe-inference-type","content":"NeuroLink has four inference types. transcribe is the one that starts from audio:\n\n| Type | Call | Produces |\n| ---------------- | --------------------------------------------------- | -------------------------------- |\n| generate | neurolink.generate() | text |\n| stream | neurolink.stream() | text, incrementally |\n| decide | neurolink.decide() | typed judgements |\n| transcribe | neurolink.transcribe() / transcribeStream() | text from audio, with timing |\n\nIt runs through any registered speech-to-text (STT) engine and adds the layers\nthat make an engine usable on real speech: a dictionary of names and\njargon, a correction pass guarded by the decision model and finished by an\nLLM rewrite, a second-opinion engine, a fallback engine for audio the\nfirst one cannot read, and client-side streaming for engines that only\ntake whole files.\n\nZero configuration. With no STT provider configured, transcribe() uses\nWhistle, the built-in local engine: it runs on this machine, needs no key\nand no network; its model files (about 18 MB) ship inside the package.\nWhistle reads English, German, French, Spanish, Italian, Dutch and Polish; for\nother languages, accents, noisy rooms or heavy jargon, configure a cloud or\nself-hosted engine, or add a dictionary and correction.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"The transcribe inference type","lvl3":""}},
4057
- {"objectID":"1894ce4204cb67336e3ed634535149704b8a702e2b0c6e8568f92a6868ca762a","title":"SDK","url":"/docs/features/transcribe#sdk","content":"audio accepts bytes (Buffer, ArrayBuffer, Uint8Array), a path, a\nfile:// URL or an http(s):// URL. The container is inferred from the path\nor the bytes; pass format (\"wav\", \"mp3\", \"m4a\", \"ogg\", \"opus\",\n\"webm\", \"flac\", \"mp4\", \"pcm16\" …) for a buffer it cannot be read from.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"SDK","lvl3":""}},
4071
+ {"objectID":"1894ce4204cb67336e3ed634535149704b8a702e2b0c6e8568f92a6868ca762a","title":"SDK","url":"/docs/features/transcribe#sdk","content":"Security: audio given as a URL must be HTTPS to a public host (set\nattachments.allowInsecureUrls / allowPrivateNetwork on the instance to\nrelax that) and is capped while it downloads; audio given as a path is\nbounded by attachments.allowedRoots when configured. See\nAttachment Security.\n\naudio accepts bytes (Buffer, ArrayBuffer, Uint8Array), a path, a\nfile:// URL or an http(s):// URL. The container is inferred from the path\nor the bytes; pass format (\"wav\", \"mp3\", \"m4a\", \"ogg\", \"opus\",\n\"webm\", \"flac\", \"mp4\", \"pcm16\" …) for a buffer it cannot be read from.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"SDK","lvl3":""}},
4058
4072
  {"objectID":"73fad0a7f04adcf37c338e67523cf8f11b0c64c73078bd4e477164612f62f770","title":"Options","url":"/docs/features/transcribe#options","content":"| Option | Meaning |\n| ---------------- | --------------------------------------------------------------------------------------------------------------------------------- |\n| provider | STT provider name or alias. Default: NEUROLINK_STT_PROVIDER, then the first configured provider, then Whistle. |\n| model | Model of that provider. Default: NEUROLINK_STT_MODEL, only when the provider also came from the environment. |\n| language | Language code or locale, or \"auto\". Default: NEUROLINK_STT_LANGUAGE, else the engine detects it. |\n| prompt | Context prompt for engines that bias on one; dictionary terms are appended to it. |\n| diarization | Label speakers, on engines that diarize. |\n| wordTimestamps | Ask for word-level timings. |\n| dictionary | Names and jargon, see Dictionary. |\n| correction | The correction layer, see Correction. |\n| fallback | { provider, model?, when? }, see Fallback. |\n| streaming | Tuning for transcribeStream(), see Streaming. |\n| timeoutMs | Whole-call timeout.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"Options","lvl3":""}},
4059
4073
  {"objectID":"25734eb9746d69fee91c94beaab37ba0433ce9d1bc944c78ac54b14ddaf10f83","title":"Result","url":"/docs/features/transcribe#result","content":"TranscribeResult is the engine's STTResult (text, confidence,\nlanguage, duration, words, segments, speakers, metadata) plus what\nthe layers did:\n\n| Field | Meaning |\n| ------------------ | -------------------------------------------------------------------------------------------------------- |\n| raw | The engine's text before any correction. |\n| text | The final text — the corrected text when correction changed it, else raw. |\n| corrected | Present only when correction changed the text. |\n| languageDetected | false when the engine reported a low language-detection score. |\n| languageScores | Candidate languages with the engine's own scores, where it reports them. |\n| decisions | One record per dictionary candidate: what was heard, the term, term or literal, and the probability. |\n| engine | { provider, model, fallbackUsed?, secondOpinion? }. |\n| timings | transcribeMs, secondOpinionMs, decideMs, rewriteMs, correctionMs, totalMs. |\n| steps | A readable trail: \"dictionary 2/2\", \"rewrite timed out · kept text\" … |","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"Result","lvl3":""}},
4060
4074
  {"objectID":"cfe99c9441a998e039ecbe92d247fb981326eb5e5a56e51aa7abb49fd4662663","title":"Providers and environment","url":"/docs/features/transcribe#providers-and-environment","content":"| Provider (aliases) | Configured by | Notes |\n| --------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------- |\n| whisper (openai-stt, openai-compatible) | OPENAI_STT_API_KEY or OPENAI_API_KEY; OPENAI_STT_BASE_URL for another server | Any OpenAI-compatible /audio/transcriptions endpoint. |\n| deepgram | DEEPGRAM_API_KEY | Native streaming. |\n| elevenlabs-stt (scribe, elevenlabs) | ELEVENLABS_API_KEY | |\n| google-stt | GOOGLE_API_KEY, GOOGLE_AI_API_KEY, GEMINI_API_KEY or GOOGLE_APPLICATION_CREDENTIALS | |\n| azure-stt | AZURE_SPEECH_KEY | |\n| whistle (local) | nothing | Built-in, local, always available. |\n\nThe order of that table is precedence: without provider or\nNEUROLINK_STT_PROVIDER, the first configured provider is used, and Whistle\nonly when none is.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"Providers and environment","lvl3":""}},
@@ -4083,7 +4097,7 @@
4083
4097
  {"objectID":"32a917bb7037f51d56da847c36cba9409b8d0a8951cf84aa19822c24a74b8f3f","title":"POST /v1/audio/transcriptions (OpenAI-compatible)","url":"/docs/features/transcribe#post-v1audiotranscriptions-openai-compatible","content":"multipart/form-data, the way OpenAI's API takes it, so an OpenAI client\npointed at http://<host>:<port>/v1 works unchanged:\n\n| Field | Meaning |\n| --------------------------- | ----------------------------------------------------------------------------------------------------------- |\n| file | The audio (required). Its name or type sets the container. |\n| model | <provider> or <provider>/<model>. OpenAI's own model names and auto mean the server's default engine. |\n| language, prompt | As in the SDK. |\n| response_format | json ({ \"text\" }, the default), text (plain text) or verbose_json. |\n| timestamp_granularities[] | word requests word timings. |\n| temperature | Accepted and ignored. |\n| provider | Extension: the STT provider, overriding model. |\n| diarize | Extension: true labels speakers. |\n| dictionary | Extension: the dictionary as a JSON string. |\n| correct | Extension: true runs the correction layer. |\n| fallback | Extension: fallback STT provider.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"POST /v1/audio/transcriptions (OpenAI-compatible)","lvl3":""}},
4084
4098
  {"objectID":"7f04ab4c7a4895ae38a057d50ee353f51a84b959feb713784f0779b9d0319798","title":"WebSocket /v1/audio/transcriptions/stream","url":"/docs/features/transcribe#websocket-v1audiotranscriptionsstream","content":"The route adapters do not handle WebSocket upgrades, so the streaming endpoint\nattaches to the Node HTTP server you own:\nThe first frame is text: a JSON config with the JSON route's fields\n minus the audio, plus streaming (for example { \"language\": \"auto\",\n\"streaming\": { \"sampleRate\": 16000 } }).\nThen binary frames of PCM16LE mono audio at that sample rate.\nA text frame { \"type\": \"end\" }, or closing the socket, ends the audio.\n { \"type\": \"output\", \"languages\": [\"es\", \"fr\"] } changes the output\n languages from the next utterance on; any other text frame ends the audio.\n\nThe server sends one JSON text frame per TranscribeStreamEvent and closes\nwith 1000 when the stream is done; an invalid config gets an error event and\nclose code 1008.\n\nSessions over the socket. A speaker connects to\n/v1/audio/transcriptions/stream?session=<id>&speaker=<name> and uses the\nprotocol above. A listener connects to\n/v1/audio/transcriptions/stream/subscribe?session=<id> (the\nsubscribePath option; false turns sessions off) and sends\n{ \"type\": \"subscribe\", \"languages\": [\"es\"], \"speakers\": [\"alice\"] }, again at\nany time to change them. Listeners get the speaker's events tagged with\nspeaker, and only the output events of their languages. A session lives\nwhile a speaker or a listener is connected; the same auth token guards both\npaths.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"WebSocket /v1/audio/transcriptions/stream","lvl3":""}},
4085
4099
  {"objectID":"8fbe8bc1159cfcafddcfac166492577e5e8cac318dc09634d14451b4b30b9856","title":"OpenAI Realtime transcription: /v1/realtime?intent=transcription","url":"/docs/features/transcribe#openai-realtime-transcription-v1realtimeintenttranscription","content":"The same live pipeline, behind OpenAI's Realtime transcription protocol, so a\nclient that already speaks it needs no NeuroLink adapter. With LiveKit Agents\n(livekit-plugins-openai, tested on 1.3.11):\n\nWhat the client sends:\n\n| Event | Handling |\n| -------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| session.update (session.type: \"transcription\", session.audio.input) or the beta transcription_session.update | Sets the rate (format.rate, default 24000; PCM16 only), the model (a profile), language and prompt. Answered with session.updated / transcription_session.updated. A running stream keeps the settings it started with. |\n| input_audio_buffer.append | Base64 PCM16 mono at the session's rate. |\n| input_audio_buffer.commit | Closes the open utterance. Not needed: an audio gap of 0.7 s (a muted mic) closes it too.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"OpenAI Realtime transcription: /v1/realtime?intent=transcription","lvl3":""}},
4086
- {"objectID":"a5ebafcb216e0f964c4597dd78f1616a5641819180b994f22b748870d402aa4e","title":"STT evaluation: POST /v1/evals/stt","url":"/docs/features/transcribe#stt-evaluation-post-v1evalsstt","content":"A call can run two STTs on the same audio: the one people see (primary) and\none run only to be compared (shadow). The sender posts both transcripts here\nin batches, and reads back how far apart they were per speaker. The server's\nAPI key guards it like every other route.\n\nA batch may hold up to 5,000 segments, and an empty final batch is valid.\nResends are idempotent: an id already held is replaced and counted as\nupdated. GET /v1/evals/stt lists calls, most recent first.\nGET /v1/evals/stt/:callId returns the per-speaker comparison\n(?segments=true adds the segments in time order):\n\n| Field | Meaning |\n| ------------------------------------------- | ----------------------------------------------------------------------------------------- |\n| speakers_compared[].disagreement | Word edit distance between the two STTs / the primary's words, on normalized text |\n| speakers_compared[].phonetic_disagreement | The same on phonetic word keys, so Devanagari against Latin for the same words agrees |\n| speakers_compared[].primary / .shadow | model, segments, words, languages reported, mean_latency_s (final after speech) |\n| speakers_compared[].method | full, or windowed (5-minute windows) for a speaker over 4,000 words |\n| overall | Both measures summed over every speaker |\n\nNeither side is ground truth: a disagreement says the STTs differ, not which\none is right. Calls live in memory unless NEUROLINK_STT_EVAL_DIR (or the\nevals.dir route option) names a directory, where each batch is appended to\none JSON-lines file per call and replayed on start. evals: false in the\ntranscribe route options removes the routes.\n\nLangfuse.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"STT evaluation: POST /v1/evals/stt","lvl3":""}},
4100
+ {"objectID":"a5ebafcb216e0f964c4597dd78f1616a5641819180b994f22b748870d402aa4e","title":"STT evaluation: POST /v1/evals/stt","url":"/docs/features/transcribe#stt-evaluation-post-v1evalsstt","content":"A call can run two STTs on the same audio: the one people see (primary) and\none run only to be compared (shadow). The sender posts both transcripts here\nin batches, and reads back how far apart they were per speaker. The server's\nAPI key guards it like every other route. The collector is off by default:\nit stores every transcript it is sent and reads them back to whoever asks. Mount\nit with transcribe: { evals: {} } in the route options (any\nServerSTTEvalOptions object) or NEUROLINK_STT_EVAL_ENABLED=1; evals: false\nkeeps it off whatever the environment says. Memory is bounded by evals.maxBytes\n(64 MiB of segments by default; the least recently updated calls are evicted,\nand stay on disk when a directory is set). When the server identifies callers\n(per-person authentication with carryMiddlewareState), a call belongs to the\ncaller that created it: others cannot list, read or append to it. Calls made\nunder no authentication or a shared key stay visible to every holder.\n\nA batch may hold up to 5,000 segments, and an empty final batch is valid.\nResends are idempotent: an id already held is replaced and counted as\nupdated. GET /v1/evals/stt lists calls, most recent first.","hierarchy":{"lvl0":"Features","lvl1":"The transcribe inference type","lvl2":"STT evaluation: POST /v1/evals/stt","lvl3":""}},
4087
4101
  {"objectID":"499945493bd6604fe9de0b7511127a8f248c00e05724562e9c6c1cd6bf63aa97","title":"Text-to-Speech (TTS) Integration Guide","url":"/docs/features/tts","content":"Text-to-Speech (TTS) Integration Guide\n\nNeuroLink provides integrated Text-to-Speech (TTS) capabilities, allowing you to generate high-quality audio from text prompts or AI-generated responses. This feature is perfect for voice assistants, accessibility features, narration, podcasts, and more.\n\nOverview\n\nKey Features:\nMultiple providers - Google Cloud TTS, OpenAI TTS, ElevenLabs, Azure TTS, Fish Audio, Cartesia, and 60db\nHigh-quality voices - Neural, Wavenet, Standard, and multilingual voice types\nMultiple languages - 50+ voices across 10+ languages\nFlexible audio formats - MP3, WAV, OGG/Opus\nVoice customization - Adjust speed, pitch, and volume\nTwo synthesis modes - Direct text-to-speech OR AI response synthesis\nProduction-ready - Works with Google Cloud, OpenAI, ElevenLabs, Azure, Fish Audio, Cartesia, and 60db\n\nQuick Start\n\nInstallation\n\nTTS support is built into NeuroLink. No additional installation required.\n\nEnvironment Setup\n\nSet the appropriate environment variables for your chosen TTS provider:\n\nGoogle API Key Configuration:\n\nIf using API key authentication for Google, enable both APIs in Google Cloud Console:\nNavigate to \"APIs & Services\" > \"Credentials\"\nCreate or select your API key\nUnder \"API restrictions\", enable:\nGenerative Language API (for Gemini)\nCloud Text-to-Speech API (for TTS)\n\nBasic Usage\n\nCLI:\n\nSDK:\n\nSupported Providers\n\nTTS is available through the following providers:\n\n| Provider | Authentication | Voices / Models | Notes |\n| -------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| google-ai | Service Account (GOOGLE_APPLICATION_CREDENTIALS) | 50+ voices (Neural2, Wavenet, Standard) | Same auth as vertex (TTS uses Google Cloud Text-to-Speech client) |\n| vertex | Service Account (GOOGLE_APPLICATION_CREDENTIALS) | 50+ voices (Neural2, Wavenet, Standard) | Recommended for production |\n| openai-tts | API Key (OPENAI_API_KEY) | 6 voices: alloy, echo, fable, onyx, nova, shimmer; models: tts-1, tts-1-hd | Good default quality |\n| elevenlabs | API Key (ELEVENLABS_API_KEY) | Multilingual voices; model: eleven_multilingual_v2 | High-quality multilingual synthesis |\n| azure-tts | API Key (AZURE_SPEECH_KEY + region AZURE_SPEECH_REGION) | Neural voices with SSML support | Enterprise-grade Azure Speech |\n| fish-audio | API Key (FISH_AUDIO_API_KEY) | 14 languages, voice cloning (15 s reference); models: s1 (default), speech-1.6, speech-1.5 | Low-cost, ~80% cheaper than ElevenLabs — see provider guide |\n| cartesia | API Key (CARTESIA_API_KEY) | Cartesia voice library, English-first; models: sonic-3.6 (default) | Low-latency Sonic models — see provider guide. Synchronous /tts/bytes; the WebSocket streaming flow is exposed separately via CartesiaStream in the voice server. |\n| sixtydb | Workspace API key (SIXTYDB_API_KEY) | Quality and fast workspace voice catalogs | WAV or PCM16 at 24 kHz — see ","hierarchy":{"lvl0":"Features","lvl1":"Text-to-Speech (TTS) Integration Guide","lvl2":"","lvl3":""}},
4088
4102
  {"objectID":"9384b791f5d32ea2c126e7a7a7a8852d80e56954c061aba2d9e493b0a9c25f2b","title":"Text-to-Speech (TTS) Integration Guide","url":"/docs/features/tts#text-to-speech-tts-integration-guide","content":"NeuroLink provides integrated Text-to-Speech (TTS) capabilities, allowing you to generate high-quality audio from text prompts or AI-generated responses. This feature is perfect for voice assistants, accessibility features, narration, podcasts, and more.","hierarchy":{"lvl0":"Features","lvl1":"Text-to-Speech (TTS) Integration Guide","lvl2":"Text-to-Speech (TTS) Integration Guide","lvl3":""}},
4089
4103
  {"objectID":"9cc14837132bc1ce344a44ef8c73aa1b77fe9b81356e3f5e565115a158d47618","title":"Overview","url":"/docs/features/tts#overview","content":"Key Features:\nMultiple providers - Google Cloud TTS, OpenAI TTS, ElevenLabs, Azure TTS, Fish Audio, Cartesia, and 60db\nHigh-quality voices - Neural, Wavenet, Standard, and multilingual voice types\nMultiple languages - 50+ voices across 10+ languages\nFlexible audio formats - MP3, WAV, OGG/Opus\nVoice customization - Adjust speed, pitch, and volume\nTwo synthesis modes - Direct text-to-speech OR AI response synthesis\nProduction-ready - Works with Google Cloud, OpenAI, ElevenLabs, Azure, Fish Audio, Cartesia, and 60db","hierarchy":{"lvl0":"Features","lvl1":"Text-to-Speech (TTS) Integration Guide","lvl2":"Overview","lvl3":""}},
@@ -4160,7 +4174,7 @@
4160
4174
  {"objectID":"bcf597bfbfc4c69b3359986add969199b4c122fef73c190bf66563923c5a3308","title":"Force a specific provider","url":"/docs/features/video-analysis#force-a-specific-provider","content":"Force a specific provider","hierarchy":{"lvl0":"Features","lvl1":"Video Analysis","lvl2":"Force a specific provider","lvl3":""}},
4161
4175
  {"objectID":"b0dc1b47d8cca8bb6f54649ec0f9c7cf1f307b503ee0cb955e04f32ea121d1f4","title":"Keyframe provider with more frames and the speech","url":"/docs/features/video-analysis#keyframe-provider-with-more-frames-and-the-speech","content":"Keyframe provider with more frames and the speech","hierarchy":{"lvl0":"Features","lvl1":"Video Analysis","lvl2":"Keyframe provider with more frames and the speech","lvl3":""}},
4162
4176
  {"objectID":"1f2bd84873465739c002846fe135f629903002f80a472a77931ccf676831a4dd","title":"Best Practices","url":"/docs/features/video-analysis#best-practices","content":"Prefer Gemini for anything with sound or fast motion. Only the native path sees what happens between frames and hears the audio.\nKeep clips under the ceiling. A recording that is a few megabytes at most travels whole; a longer one falls back to keyframes. Trimming to the relevant stretch, or re-encoding at a lower bitrate, keeps it on the native path. Remember the budget is shared with every other inline attachment in the same request.\nFrame depth. On the keyframe path, short videos (under 10 s) get one frame per second and long ones are sampled more sparsely. Set --video-frames to spend your frame budget evenly across a clip you care about.\nAdd a transcript only where it helps. --transcribe-audio is for providers that cannot hear the clip. It is not provider-aware, so on Gemini it only adds a redundant transcript and a speech-to-text call.\nPrompt precision. Guide the model with specific questions about the activity, and ask for the structure you want (a timeline, an action-reaction table, a verdict) in the prompt.\nFormat. The analysis is returned as text in result.content, making it easy to store, display, or pipe to other tools.","hierarchy":{"lvl0":"Features","lvl1":"Video Analysis","lvl2":"Best Practices","lvl3":""}},
4163
- {"objectID":"0af2cd2e57086d14cba79ae945f4f934c12cace5d06368f2d6846db441d467a8","title":"Video Director Mode – Multi-Clip Generation & Merging","url":"/docs/features/video-director-mode","content":"Video Director Mode\n\nDirector Mode extends NeuroLink's video generation capability to produce multi-segment videos with seamless AI-generated transitions. Instead of a single clip, you define an array of segments — each with its own prompt and image — and NeuroLink orchestrates the full pipeline: generating each clip, extracting boundary frames, producing transition videos (with individually configurable durations) using Veo 3.1's first-and-last-frame interpolation, and merging everything into one continuous video.\n\nOverview\n\nDirector Mode is triggered automatically when you supply an input.segments array to the video generation API. Each segment is a self-documenting { prompt, image } object, mapping cleanly to the pipeline concept of ordered video segments.\n\nHow It Works\nParallel clip generation – All main clips are generated concurrently (fixed concurrency of 2) via Veo 3.1's image-to-video endpoint, with a circuit breaker that trips after 2 consecutive failures to avoid wasted API calls\nFrame extraction – The last frame of clip N and first frame of clip N+1 are extracted from generated video buffers (with MP4 ftyp header validation)\nParallel transition generation – Veo 3.1 Fast's first-and-last-frame interpolation API generates transitions between each pair of adjacent clips in parallel (same concurrency limit), with individually configurable duration (4, 6, or 8 seconds each)\nSequential merge – Clips and transitions are concatenated: Clip₁ → Trans₁₋₂ → Clip₂ → Trans₂₋₃ → Clip₃ → …\nSingle output – The merged result is returned as one VideoGenerationResult buffer\n\nKey Technology: Veo First-and-Last-Frame Interpolation\n\nThe transition clips use Veo 3.1's native lastFrame parameter in the predictLongRunning API. Instead of generating from a single image, you provide two images — the first frame and the last frame — and Veo generates a video that smoothly interpolates between them:\n\nThis produces a physically coherent, AI-generated morph — far superior to simple crossfade or dissolve effects. The durationSeconds value is set independently for each transition (from the transitionDurations array), allowing shorter or longer interpolations per segment boundary.\n\nWhat You Get\nMulti-segment video – Chain any number of video segments into a single continuous output\nAI transitions – Per-transition configurable duration (4, 6, or 8 seconds each) generated by Veo 3.1 frame interpolation (not simple crossfades)\nParallel generation – Both main clips and transitions are generated concurrently (fixed concurrency of 2) with a circuit breaker for clip failures\nMixed image inputs – Each segment's image field accepts a Buffer, file path, URL, or ImageWithAltText\nConsistent settings – Resolution, aspect ratio, and audio settings apply uniformly across all segments and transitions\nPer-segment customization – Each segment is a self-contained { prompt, image } object\nBuffer validation – All video buffers are validated for MP4 ftyp headers before frame extraction and merging\nSDK only – Use programmatically via generate() (CLI not supported for Director Mode)\n\nSupported Provider & Model\n\n| Provider | Model | Interpolation Support | Transition Duration | Max Segments | Concurrency |\n| -------- | ------------------------------------------------ | --------------------- | ------------------- | ------------ | ----------- |\n| vertex | veo-3.1 (clips) / veo-3.1-fast (transitions) | First + Last Frame | 4-8s per transition | 10 | 2 (fixed) |\n\nNote: The lastFrame parameter is supported by veo-2.0-generate-001, veo-3.1-generate-001, and veo-3.1-fast-generate-001. NeuroLink uses veo-3.1-generate-001 for main clips and veo-3.1-fast-generate-001 for transition clips (faster generation with minimal quality difference for short interpolations).\n\nPrerequisites\n\nSame as Video Generation prerequisites, plus:\nSufficient quota – Director Mode generates N + (N-1) video operations (N clips + N-1 transitions). Ensure your Vertex AI project has adequate quota.\nAdequate timeout – Multi-segment generation takes proportionally longer. Set timeout accordingly (recommended: 5-10 minutes for 3+ segments).\n\nQuick Start\n\nSDK Usage\n\nUsing Image URLs\n\nMixed Input Types\n\nEach segment's image field accepts a Buffer, file path, URL, or ImageWithAltText:\n\nNote: Director Mode is SDK-only. CLI support is not available for this generation type. Use the standard --outputMode video CLI flags for single-clip video generation.\n\nComprehensive Examples\n\nExample 1: Product Commercial (3 Segments)\n\nExample 2: Social Media Story (Portrait, 4 Segments)\n\nExample 3: AI-Driven Storyboard\n\nExample 4: Batch Director Mode\n\nExample 5: Error Handling in Director Mode\n\n⚠️ Full-job retry warning: The generateWithRetry function below retries the entire neurolink.generate() call on any retriable VideoError. This means all segments and transitions are re-generated from scratch, incurring full cost each attempt ($10-60+ depending on set","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"","lvl3":""}},
4177
+ {"objectID":"0af2cd2e57086d14cba79ae945f4f934c12cace5d06368f2d6846db441d467a8","title":"Video Director Mode – Multi-Clip Generation & Merging","url":"/docs/features/video-director-mode","content":"Video Director Mode\n\nDirector Mode extends NeuroLink's video generation capability to produce multi-segment videos with seamless AI-generated transitions. Instead of a single clip, you define an array of segments — each with its own prompt and image — and NeuroLink orchestrates the full pipeline: generating each clip, extracting boundary frames, producing transition videos (with individually configurable durations) using Veo 3.1's first-and-last-frame interpolation, and merging everything into one continuous video.\n\nOverview\n\nDirector Mode is triggered automatically when you supply an input.segments array to the video generation API. Each segment is a self-documenting { prompt, image } object, mapping cleanly to the pipeline concept of ordered video segments.\n\nHow It Works\nParallel clip generation – All main clips are generated concurrently (fixed concurrency of 2) via Veo 3.1's image-to-video endpoint, with a circuit breaker that trips after 2 consecutive failures to avoid wasted API calls\nFrame extraction – The last frame of clip N and first frame of clip N+1 are extracted from generated video buffers (with MP4 ftyp header validation)\nParallel transition generation – Veo 3.1 Fast's first-and-last-frame interpolation API generates transitions between each pair of adjacent clips in parallel (same concurrency limit), with individually configurable duration (4, 6, or 8 seconds each)\nSequential merge – Clips and transitions are concatenated: Clip₁ → Trans₁₋₂ → Clip₂ → Trans₂₋₃ → Clip₃ → …\nSingle output – The merged result is returned as one VideoGenerationResult buffer\n\nKey Technology: Veo First-and-Last-Frame Interpolation\n\nThe transition clips use Veo 3.1's native lastFrame parameter in the predictLongRunning API. Instead of generating from a single image, you provide two images — the first frame and the last frame — and Veo generates a video that smoothly interpolates between them:\n\nThis produces a physically coherent, AI-generated morph — far superior to simple crossfade or dissolve effects. The durationSeconds value is set independently for each transition (from the transitionDurations array), allowing shorter or longer interpolations per segment boundary.\n\nWhat You Get\nMulti-segment video – Chain any number of video segments into a single continuous output\nAI transitions – Per-transition configurable duration (4, 6, or 8 seconds each) generated by Veo 3.1 frame interpolation (not simple crossfades)\nParallel generation – Both main clips and transitions are generated concurrently (fixed concurrency of 2) with a circuit breaker for clip failures\nMixed image inputs – Each segment's image field accepts a Buffer, file path, URL, or ImageWithAltText\nConsistent settings – Resolution, aspect ratio, and audio settings apply uniformly across all segments and transitions\nPer-segment customization – Each segment is a self-contained { prompt, image } object\nBuffer validation – All video buffers are validated for MP4 ftyp headers before frame extraction and merging\nSDK only – Use programmatically via generate() (CLI not supported for Director Mode)\n\nSupported Provider & Model\n\n| Provider | Model | Interpolation Support | Transition Duration | Max Segments | Concurrency |\n| -------- | ------------------------------------------------ | --------------------- | ------------------- | ------------ | ----------- |\n| vertex | veo-3.1 (clips) / veo-3.1-fast (transitions) | First + Last Frame | 4-8s per transition | 10 | 2 (fixed) |\n\nNote: The lastFrame parameter is supported by veo-2.0-generate-001, veo-3.1-generate-001, and veo-3.1-fast-generate-001. NeuroLink uses veo-3.1-generate-001 for main clips and veo-3.1-fast-generate-001 for transition clips (faster generation with minimal quality difference for short interpolations).\n\nPrerequisites\n\nSame as Video Generation prerequisites, plus:\nSufficient quota – Director Mode generates N + (N-1) video operations (N clips + N-1 transitions). Ensure your Vertex AI project has adequate quota.\nAdequate timeout – Multi-segment generation takes proportionally longer. Set timeout accordingly (recommended: 5-10 minutes for 3+ segments).\n\nQuick Start\n\nSDK Usage\n\nUsing Image URLs\n\nSecurity: segment image URLs are fetched only over HTTPS from public\nhosts, and segment image paths honour attachments.allowedRoots — see\nAttachment Security.\n\nMixed Input Types\n\nEach segment's image field accepts a Buffer, file path, URL, or ImageWithAltText:\n\nNote: Director Mode is SDK-only. CLI support is not available for this generation type. Use the standard --outputMode video CLI flags for single-clip video generation.\n\nComprehensive Examples\n\nExample 1: Product Commercial (3 Segments)\n\nExample 2: Social Media Story (Portrait, 4 Segments)\n\nExample 3: AI-Driven Storyboard\n\nExample 4: Batch Director Mode\n\nExample 5: Error Handling in Director Mode\n\n⚠️ Full-job retry warning: The generateWithRetry function below retries the entire neurolink.generate() cal","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"","lvl3":""}},
4164
4178
  {"objectID":"9dd83315c72382cd60863330c64a615aec84cadf693d7751bf8676806e359c94","title":"Video Director Mode","url":"/docs/features/video-director-mode#video-director-mode","content":"Director Mode extends NeuroLink's video generation capability to produce multi-segment videos with seamless AI-generated transitions. Instead of a single clip, you define an array of segments — each with its own prompt and image — and NeuroLink orchestrates the full pipeline: generating each clip, extracting boundary frames, producing transition videos (with individually configurable durations) using Veo 3.1's first-and-last-frame interpolation, and merging everything into one continuous video.","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Video Director Mode","lvl3":""}},
4165
4179
  {"objectID":"df7c4473d5ef1434c82a40e880da4d6ab470fcd00a0383199ed8c08fdca6e739","title":"Overview","url":"/docs/features/video-director-mode#overview","content":"Director Mode is triggered automatically when you supply an input.segments array to the video generation API. Each segment is a self-documenting { prompt, image } object, mapping cleanly to the pipeline concept of ordered video segments.","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Overview","lvl3":""}},
4166
4180
  {"objectID":"a6bbae377f2c9e6b146226ca01bfd6314eac4b4c9500ec854b64ab08e892b688","title":"How It Works","url":"/docs/features/video-director-mode#how-it-works","content":"Parallel clip generation – All main clips are generated concurrently (fixed concurrency of 2) via Veo 3.1's image-to-video endpoint, with a circuit breaker that trips after 2 consecutive failures to avoid wasted API calls\nFrame extraction – The last frame of clip N and first frame of clip N+1 are extracted from generated video buffers (with MP4 ftyp header validation)\nParallel transition generation – Veo 3.1 Fast's first-and-last-frame interpolation API generates transitions between each pair of adjacent clips in parallel (same concurrency limit), with individually configurable duration (4, 6, or 8 seconds each)\nSequential merge – Clips and transitions are concatenated: Clip₁ → Trans₁₋₂ → Clip₂ → Trans₂₋₃ → Clip₃ → …\nSingle output – The merged result is returned as one VideoGenerationResult buffer","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"How It Works","lvl3":""}},
@@ -4169,7 +4183,7 @@
4169
4183
  {"objectID":"8215edc84b30f32eb8e34b5237ab361c58f9c25fd9a5d45bd12f91eeefb77772","title":"Supported Provider & Model","url":"/docs/features/video-director-mode#supported-provider-model","content":"| Provider | Model | Interpolation Support | Transition Duration | Max Segments | Concurrency |\n| -------- | ------------------------------------------------ | --------------------- | ------------------- | ------------ | ----------- |\n| vertex | veo-3.1 (clips) / veo-3.1-fast (transitions) | First + Last Frame | 4-8s per transition | 10 | 2 (fixed) |\n\nNote: The lastFrame parameter is supported by veo-2.0-generate-001, veo-3.1-generate-001, and veo-3.1-fast-generate-001. NeuroLink uses veo-3.1-generate-001 for main clips and veo-3.1-fast-generate-001 for transition clips (faster generation with minimal quality difference for short interpolations).","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Supported Provider & Model","lvl3":""}},
4170
4184
  {"objectID":"219ced9abbfa7cf86f5d50ec5b6a027f6511e5708b906ee8b03290d8ba361456","title":"Prerequisites","url":"/docs/features/video-director-mode#prerequisites","content":"Same as Video Generation prerequisites, plus:\nSufficient quota – Director Mode generates N + (N-1) video operations (N clips + N-1 transitions). Ensure your Vertex AI project has adequate quota.\nAdequate timeout – Multi-segment generation takes proportionally longer. Set timeout accordingly (recommended: 5-10 minutes for 3+ segments).","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Prerequisites","lvl3":""}},
4171
4185
  {"objectID":"e2b021e42dffe633669ddca2be0f9112f6ab6c689c55c884761c31a2f23f9eb7","title":"SDK Usage","url":"/docs/features/video-director-mode#sdk-usage","content":"SDK Usage","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"SDK Usage","lvl3":""}},
4172
- {"objectID":"80bb732a4d0e7821ce58db2a3ab29bb008d61ee6589f0e09cbfd5e5bdbac49a1","title":"Using Image URLs","url":"/docs/features/video-director-mode#using-image-urls","content":"Using Image URLs","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Using Image URLs","lvl3":""}},
4186
+ {"objectID":"80bb732a4d0e7821ce58db2a3ab29bb008d61ee6589f0e09cbfd5e5bdbac49a1","title":"Using Image URLs","url":"/docs/features/video-director-mode#using-image-urls","content":"Security: segment image URLs are fetched only over HTTPS from public\nhosts, and segment image paths honour attachments.allowedRoots — see\nAttachment Security.","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Using Image URLs","lvl3":""}},
4173
4187
  {"objectID":"45df31092971d7650f10a58c8eec7186e04a6aee65c012520aae8147e143aadf","title":"Mixed Input Types","url":"/docs/features/video-director-mode#mixed-input-types","content":"Each segment's image field accepts a Buffer, file path, URL, or ImageWithAltText:\n\nNote: Director Mode is SDK-only. CLI support is not available for this generation type. Use the standard --outputMode video CLI flags for single-clip video generation.","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Mixed Input Types","lvl3":""}},
4174
4188
  {"objectID":"a6439a7b617ddd3e1f1476821f03ee4b4d77f3c4095ad2fcdb18245d35a1026a","title":"Example 1: Product Commercial (3 Segments)","url":"/docs/features/video-director-mode#example-1-product-commercial-3-segments","content":"Example 1: Product Commercial (3 Segments)","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Example 1: Product Commercial (3 Segments)","lvl3":""}},
4175
4189
  {"objectID":"c370ba733afb24a8ad54f4e20edf2273a8bd3e86ccba10b0287eed1618aabcd5","title":"Example 2: Social Media Story (Portrait, 4 Segments)","url":"/docs/features/video-director-mode#example-2-social-media-story-portrait-4-segments","content":"Example 2: Social Media Story (Portrait, 4 Segments)","hierarchy":{"lvl0":"Features","lvl1":"Video Director Mode – Multi-Clip Generation & Merging","lvl2":"Example 2: Social Media Story (Portrait, 4 Segments)","lvl3":""}},
@@ -4323,9 +4337,10 @@
4323
4337
  {"objectID":"8b922e3ee9644559addad4738b5f0c6360fe12ae2d1d0c98d678ddaac03eede9","title":"Troubleshooting","url":"/docs/features/workflow-engine#troubleshooting","content":"| Problem | Solution |\n| --------------------------------- | ---------------------------------------------------------------------------------- |\n| Workflow not found in registry | Register it with registerWorkflow() before calling generate() with workflow: |\n| All models failed | Check API keys, increase timeout, verify provider availability |\n| Judge returns neutral scores (50) | Judge response parsing failed; check judge model supports JSON output |\n| Slow execution | Reduce model count, use faster models, increase parallelism |\n| High costs | Use consensus-3-fast, chain/adaptive workflows, or set costThreshold |\n| Low consensus in multi-judge | Normal for subjective queries; increase judge count or align criteria |","hierarchy":{"lvl0":"Features","lvl1":"Workflow Engine Guide","lvl2":"Troubleshooting","lvl3":""}},
4324
4338
  {"objectID":"e9de380e8339140c2951bda58d6eaaffb28f182c85fbfda7d7679ea6f5af270e","title":"Core Exports","url":"/docs/features/workflow-engine#core-exports","content":"Execution:\nrunWorkflow(config, options) -- Execute a complete workflow\nrunWorkflowWithStreaming(config, options) -- Execute with progressive streaming\nexecuteEnsemble(options) -- Low-level parallel model execution\nexecuteModelGroups(groups, prompt, config) -- Low-level layer-based execution\nscoreEnsemble(options) -- Low-level judge scoring\nconditionResponse(options) -- Low-level response conditioning\n\nConfiguration:\ncreateWorkflowConfig(partial) -- Create config with defaults\nvalidateWorkflow(config) -- Validate workflow configuration\nvalidateForExecution(config) -- Validate for execution readiness\n\nRegistry:\nregisterWorkflow(config, options) -- Register a workflow\nunregisterWorkflow(workflowId) -- Remove a workflow\ngetWorkflow(workflowId) -- Retrieve by ID\nlistWorkflows(options) -- List with filtering\ngetRegistryStats() -- Registry statistics\nclearRegistry() -- Remove all workflows\n\nPre-built Workflows:\nCONSENSUS_3_WORKFLOW -- 3-model ensemble with judge\nCONSENSUS_3_FAST_WORKFLOW -- Fast/cheap 3-model ensemble\nBALANCED_ADAPTIVE_WORKFLOW -- 2-tier balanced adaptive\nQUALITY_MAX_WORKFLOW -- 3-tier quality-maximizing adaptive\nSPEED_FIRST_WORKFLOW -- Speed-optimized adaptive\nAGGRESSIVE_FALLBACK_WORKFLOW -- Fast + parallel premium fallback\nFAST_FALLBACK_WORKFLOW -- Sequential 3-tier fallback\nMULTI_JUDGE_3_WORKFLOW -- 3 models, 2 judges\nMULTI_JUDGE_5_WORKFLOW -- 5 models, 3 judges\n\nFactory Functions:\ncreateConsensus3WithPrompt(systemPrompt) -- Consensus-3 with custom prompt\ncreateAdaptiveWorkflow(tiers, strategy) -- Custom adaptive workflow\ncreateMultiJudgeWorkflow(modelCount, judgeCount) -- Custom multi-judge\n\nMetrics:\ncalculateModelMetrics(responses) -- Per-model metrics\ncalculateConfidence(scores) -- Confidence calculation\ncalculateConsensus(scores) -- Consensus calculation\ngenerateSummaryStats(results) -- Summary statistics\ncompareWorkflows(stats1, stats2) -- Workflow comparison\nformatMetricsForLogging(result) -- Formatted logging output\n\nTypes:\nWorkflowConfig,","hierarchy":{"lvl0":"Features","lvl1":"Workflow Engine Guide","lvl2":"Core Exports","lvl3":""}},
4325
4339
  {"objectID":"fb91715f0910d539aa3342bb53890eb88ef04121ad496d9c8c982c55d6a645d5","title":"See Also","url":"/docs/features/workflow-engine#see-also","content":"Provider Orchestration Guide -- Multi-provider configuration\nObservability Guide -- Tracing workflow executions with Langfuse\nStructured Output Guide -- JSON schema output (note: incompatible with Gemini tools)","hierarchy":{"lvl0":"Features","lvl1":"Workflow Engine Guide","lvl2":"See Also","lvl3":""}},
4326
- {"objectID":"fcc71bbb437aec3313f917118186ae468e33d960b134ccbe3a8151a55970c6a9","title":"🔧 Environment Variables Configuration Guide","url":"/docs/getting-started/environment-variables","content":"🔧 Environment Variables Configuration Guide\n\nThis guide provides comprehensive setup instructions for all AI providers supported by NeuroLink. The CLI automatically loads environment variables from .env files, making configuration seamless.\n\n🚀 Quick Setup\n\nAutomatic .env Loading ✨ NEW!\n\nNeuroLink CLI automatically loads environment variables from .env files in your project directory:\n\nManual Export (Also Supported)\n\n🏗️ Enterprise Configuration Management\n\n✨ NEW: Automatic Backup System\n\nInterface Configuration\n\nPerformance & Optimization\n\n🆕 AI Enhancement Features\n\nBasic Enhancement Configuration\n\nDescription: Configures the AI model used for response quality evaluation when --enable-evaluation flag is used. Uses Google AI's fast Gemini 2.5 Flash model for quick quality assessment.\n\nSupported Models:\ngemini-2.5-flash (default) - Fast evaluation processing\ngemini-2.5-pro - More detailed evaluation (slower)\n\nUsage:\n\n🌐 Universal Evaluation System (Advanced)\n\nPrimary Configuration\n\nNEUROLINK_EVALUATION_PROVIDER: Primary AI provider for evaluation\nOptions: google-ai, openai, anthropic, vertex, bedrock, azure, ollama, huggingface, mistral\nDefault: google-ai\nUsage: Determines which AI provider performs the quality evaluation\n\nNEUROLINK_EVALUATION_MODE: Performance vs quality trade-off\nOptions: fast (cost-effective), balanced (optimal), quality (highest accuracy)\nDefault: fast\nUsage: Selects appropriate model for the provider (e.g., gemini-2.5-flash vs gemini-2.5-pro)\n\nFallback Configuration\n\nNEUROLINK_EVALUATION_FALLBACK_ENABLED: Enable intelligent fallback system\nOptions: true, false\nDefault: true\nUsage: When enabled, automatically tries backup providers if primary fails\n\nNEUROLINK_EVALUATION_FALLBACK_PROVIDERS: Backup provider order\nFormat: Comma-separated provider names\nDefault: openai,anthropic,vertex,bedrock\nUsage: Defines the order of providers to try if primary fails\n\nPerformance Tuning\n\nPerformance Variables:\nTIMEOUT: Maximum time to wait for evaluation (prevents hanging)\nMAX_TOKENS: Limits evaluation response length (controls cost)\nTEMPERATURE: Lower values = more consistent scoring\nRETRY_ATTEMPTS: Number of retry attempts for transient failures\n\nCost Optimization\n\nNEUROLINK_EVALUATION_PREFER_CHEAP: Cost optimization preference\nOptions: true, false\nDefault: true\nUsage: When enabled, prioritizes cheaper providers and models\n\nNEUROLINK_EVALUATION_MAX_COST_PER_EVAL: Cost limit per evaluation\nFormat: Decimal number (USD)\nDefault: 0.01 ($0.01)\nUsage: Prevents expensive evaluations, switches to cheaper providers if needed\n\nComplete Universal Evaluation Example\n\nTesting Universal Evaluation\n\n🏢 Enterprise Proxy Configuration\n\nProxy Environment Variables\n\n| Variable | Description | Example |\n| ------------- | ------------------------------- | ---------------------------------- |\n| HTTPS_PROXY | Proxy server for HTTPS requests | http://proxy.company.com:8080 |\n| HTTP_PROXY | Proxy server for HTTP requests | http://proxy.company.com:8080 |\n| NO_PROXY | Domains to bypass proxy | localhost,127.0.0.1,.company.com |\n\nThe shared HTTP proxy fetch accepts comma- or whitespace-separated NO_PROXY entries. Entries are case-insensitive: * bypasses all; example.com, .example.com and *.example.com cover the host and its subdomains; example.com:8443 restricts a match to that effective port (HTTP defaults to 80, HTTPS to 443). One trailing dot is normalized for domain names. IPv4/IPv6 literals match exactly, including [::1]:8080; IPv4 CIDR entries apply only to literal IPv4 targets, and IPv6 CIDR is unsupported. Dot-only entries (. or ..) match nothing.\n\nThese rules apply to request paths that use NeuroLink's HTTP proxy fetch. Native AWS handlers, Gemini Live WebSockets and Vertex ADC token requests use separate transports/dependency rules. See Enterprise & Proxy Setup for those limits. The legacy AWS proxy selector uses a smaller comma-separated matcher; it supports exact hosts, leading-dot subdomain suffixes and *, without the full port/wildcard/CIDR syntax. It is not automatically injected into the native Bedrock constructors.\n\nAuthenticated Proxy\n\nAll NeuroLink providers automatically use proxy settings when configured.\n\nFor detailed proxy setup → See Enterprise & Proxy Setup Guide\n\n🤖 Provider Configuration\nOpenAI\n\nRequired Variables\n\nOptional Variables\n\nHow to Get OpenAI API Key\nVisit OpenAI Platform\nSign up or log in to your account\nNavigate to API Keys section\nClick Create new secret key\nCopy the key (starts with sk-proj- or sk-)\nAdd billing information if required\n\nSupported Models\n\nExamples, not the full list. The OpenAI guide lists every model the SDK names, including the GPT-6 and gpt-5.4-nano models.\ngpt-5.4 - GPT-5.4 model\ngpt-5.4-mini - Faster, cost-effective GPT-5.4 option\ngpt-4o-mini (default) - Cost-effective, fast\ngpt-4o - Previous generation multimodal model\ngpt-4-turbo - High-performance model\ngpt-3.5-turbo - Legacy cost-effective opt","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"","lvl3":""}},
4340
+ {"objectID":"fcc71bbb437aec3313f917118186ae468e33d960b134ccbe3a8151a55970c6a9","title":"🔧 Environment Variables Configuration Guide","url":"/docs/getting-started/environment-variables","content":"🔧 Environment Variables Configuration Guide\n\nThis guide provides comprehensive setup instructions for all AI providers supported by NeuroLink. The CLI automatically loads environment variables from .env files, making configuration seamless.\n\n🚀 Quick Setup\n\nAutomatic .env Loading\n\nThe CLI loads environment variables from the .env file in your current directory (or from the file named by DOTENV_CONFIG_PATH) at startup:\n\nThe SDK does not read .env when it is imported. A library must not pick up files from whatever directory the host process happens to run in — a cloned repository's .env could otherwise set ANTHROPIC_BASE_URL and send your real key to a host of its choosing. An application that wants the CLI's behaviour opts in explicitly, either way:\n\nEndpoint overrides need a trustworthy file. dotenv never overrides a variable that is already set, but it sets every one that is not — including the variables that decide where a request goes: every provider *_BASE_URL / *_ENDPOINT(S) variable, the NEUROLINK_*_DIR directories and DOTENV_CONFIG_PATH. For exactly those names the .env file must be owned by the current user and must not be group- or world-writable; otherwise they are removed again and named in a stderr line (Refused 1 endpoint override(s) from … ANTHROPIC_BASE_URL). When they are kept, a one-line notice lists them (.env at … set endpoint override(s): ANTHROPIC_BASE_URL), with a reminder when the file is outside your home directory. Export such a variable in your shell to use it regardless.\n\n| Variable | Effect |\n| -------------------- | ----------------------------------------------------------------------------------------------------------------------------- |\n| NEUROLINK_DOTENV=0 | Disable .env loading everywhere (CLI included). |\n| NEUROLINK_DOTENV=1 | Make the SDK load .env when imported. Must be set in the real environment — it cannot come from the file it enables. |\n| DOTENV_CONFIG_PATH | Load this file instead of ./.env. DOTENV_CONFIG_PATH=/dev/null is the documented way to run a test with no .env at all. |\n\nProject MCP configuration (.mcp-config.json)\n\nA project .mcp-config.json names commands to run and URLs to connect to, so it is treated like .env — a directory is not a trust boundary:\nThe SDK never loads it from the working directory on its own. Pass new NeuroLink({ mcp: { configPath: \"./.mcp-config.json\" } }) to name a file, or mcp: { trustProjectConfig: true } for a directory you control.\nThe CLI loads it only after you have trusted that exact content: the file's SHA-256 is recorded in ~/.neurolink/trusted-mcp-configs.json (mode 0600). In a terminal you are shown the servers and asked; non-interactively the command refuses with exit status 1 until you decide.\n\n| Variable / flag | Effect |\n| ------------------------------ | ------------------------------------------------------------------------------------- |\n| --trust-mcp-config | Trust the working directory's .mcp-config.json as it is now, and remember its hash. |\n| NEUROLINK_TRUST_MCP_CONFIG=1 | Same as the flag, for non-interactive runs (CI). |\n| NEUROLINK_TRUST_MCP_CONFIG=0 | Run without the project config. |\n| NEUROLINK_SKIP_MCP=true | Skip MCP initialisation entirely (built-in and external servers alike). |\n\nSee MCP Integration for what the file may contain and how ${VAR} references, the stdio environment and transport URLs are checked.\n\nManual Export (Also Supported)\n\n🏗️ Enterprise Configuration Management\n\n✨ NEW: Automatic Backup System\n\nInterface Configuration\n\nPerformance & Optimization\n\n🆕 AI Enhancement Features\n\nBasic Enhancement Configuration\n\nDescription: Configures the AI model used for response quality evaluation when --enable-evaluation flag is used. Uses Google AI's fast Gemini 2.5 Flash model for quick quality assessment.\n\nSupported Models:\ngemini-2.5-flash (default) - Fast evaluation processing\ngemini-2.5-pro - More detailed evaluation (slower)\n\nUsage:\n\n🌐 Universal Evaluation System (Advanced)\n\nPrimary Configuration\n\nNEUROLINK_EVALUATION_PROVIDER: Primary AI provider for evaluation\nOptions: google-ai, openai, anthropic, vertex, bedrock, azure, ollama, huggingface, mistral\nDefault: google-ai\nUsage: Determines which AI provider performs the quality evaluation\n\nNEUROLINK_EVALUATION_MODE: Performance vs quality trade-off\nOptions: fast (cost-effective), balanced (optimal), quality (highest accuracy)\nDefault: fast\nUsage: Selects appropriate model for the provider (e.g., gemini-2.5-flash vs gemini-2.5-pro)\n\nFallback Configuration\n\nNEUROLINK_EVALUATION_FALLBACK_ENABLED: Enable intelligent fallback ","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"","lvl3":""}},
4327
4341
  {"objectID":"c81a81fd6221fc873edf4a381a6af70939b66519ee4d4ce31acce9afec8fb5f1","title":"🔧 Environment Variables Configuration Guide","url":"/docs/getting-started/environment-variables#-environment-variables-configuration-guide","content":"This guide provides comprehensive setup instructions for all AI providers supported by NeuroLink. The CLI automatically loads environment variables from .env files, making configuration seamless.","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"🔧 Environment Variables Configuration Guide","lvl3":""}},
4328
- {"objectID":"a78ad3583ac3d28848100b6a1e832a69a5d8d6dd5538da571bcf5d184ef34789","title":"Automatic .env Loading ✨ NEW!","url":"/docs/getting-started/environment-variables#automatic-env-loading-new","content":"NeuroLink CLI automatically loads environment variables from .env files in your project directory:","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Automatic .env Loading ✨ NEW!","lvl3":""}},
4342
+ {"objectID":"efae1668bacc21e5708bb4817b48c5b5c35568780864cbfc691d90451dba4279","title":"Automatic .env Loading","url":"/docs/getting-started/environment-variables#automatic-env-loading","content":"The CLI loads environment variables from the .env file in your current directory (or from the file named by DOTENV_CONFIG_PATH) at startup:\n\nThe SDK does not read .env when it is imported. A library must not pick up files from whatever directory the host process happens to run in — a cloned repository's .env could otherwise set ANTHROPIC_BASE_URL and send your real key to a host of its choosing. An application that wants the CLI's behaviour opts in explicitly, either way:\n\nEndpoint overrides need a trustworthy file. dotenv never overrides a variable that is already set, but it sets every one that is not — including the variables that decide where a request goes: every provider *_BASE_URL / *_ENDPOINT(S) variable, the NEUROLINK_*_DIR directories and DOTENV_CONFIG_PATH. For exactly those names the .env file must be owned by the current user and must not be group- or world-writable; otherwise they are removed again and named in a stderr line (Refused 1 endpoint override(s) from … ANTHROPIC_BASE_URL). When they are kept, a one-line notice lists them (.env at … set endpoint override(s): ANTHROPIC_BASE_URL), with a reminder when the file is outside your home directory. Export such a variable in your shell to use it regardless.\n\n| Variable | Effect |\n| -------------------- | ----------------------------------------------------------------------------------------------------------------------------- |\n| NEUROLINK_DOTENV=0 | Disable .env loading everywhere (CLI included). |\n| NEUROLINK_DOTENV=1 | Make the SDK load .env when imported. Must be set in the real environment — it cannot come from the file it enables. |\n| DOTENV_CONFIG_PATH | Load this file instead of ./.env. DOTENV_CONFIG_PATH=/dev/null is the documented way to run a test with no .env at all. |","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Automatic .env Loading","lvl3":""}},
4343
+ {"objectID":"73d48e6d7ffe3a5fb44dfaf860fa52c537a139f977f7dc150b422a28a508fc03","title":"Project MCP configuration (.mcp-config.json)","url":"/docs/getting-started/environment-variables#project-mcp-configuration-mcp-configjson","content":"A project .mcp-config.json names commands to run and URLs to connect to, so it is treated like .env — a directory is not a trust boundary:\nThe SDK never loads it from the working directory on its own. Pass new NeuroLink({ mcp: { configPath: \"./.mcp-config.json\" } }) to name a file, or mcp: { trustProjectConfig: true } for a directory you control.\nThe CLI loads it only after you have trusted that exact content: the file's SHA-256 is recorded in ~/.neurolink/trusted-mcp-configs.json (mode 0600). In a terminal you are shown the servers and asked; non-interactively the command refuses with exit status 1 until you decide.\n\n| Variable / flag | Effect |\n| ------------------------------ | ------------------------------------------------------------------------------------- |\n| --trust-mcp-config | Trust the working directory's .mcp-config.json as it is now, and remember its hash. |\n| NEUROLINK_TRUST_MCP_CONFIG=1 | Same as the flag, for non-interactive runs (CI). |\n| NEUROLINK_TRUST_MCP_CONFIG=0 | Run without the project config. |\n| NEUROLINK_SKIP_MCP=true | Skip MCP initialisation entirely (built-in and external servers alike). |\n\nSee MCP Integration for what the file may contain and how ${VAR} references, the stdio environment and transport URLs are checked.","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Project MCP configuration (.mcp-config.json)","lvl3":""}},
4329
4344
  {"objectID":"4119c700a6e70a17f93d06bbe18f69a09a9c078312a9417d83d9af1ee3ebdd26","title":"Manual Export (Also Supported)","url":"/docs/getting-started/environment-variables#manual-export-also-supported","content":"Manual Export (Also Supported)","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Manual Export (Also Supported)","lvl3":""}},
4330
4345
  {"objectID":"782f9f26ea2b201cdc769485d35baa99b8e8b517fdef3cb1d85d9da7d1412a12","title":"✨ NEW: Automatic Backup System","url":"/docs/getting-started/environment-variables#-new-automatic-backup-system","content":"✨ NEW: Automatic Backup System","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"✨ NEW: Automatic Backup System","lvl3":""}},
4331
4346
  {"objectID":"5c396ee4654d8c41cd1c128436e9035eec054ebb79a7686acbeddc42880a27b1","title":"Interface Configuration","url":"/docs/getting-started/environment-variables#interface-configuration","content":"Interface Configuration","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Interface Configuration","lvl3":""}},
@@ -4443,9 +4458,11 @@
4443
4458
  {"objectID":"cd706105fb9ac4dc67aa40da22162f639f4a17eebd9deb6286e9f988c5fb278d","title":"CI/CD Configuration","url":"/docs/getting-started/environment-variables#cicd-configuration","content":"CI/CD Configuration","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"CI/CD Configuration","lvl3":""}},
4444
4459
  {"objectID":"80d22ac51f1ec7915792f88fb4d7bf1ba708bfba44992bf2e35ae053b56b821c","title":"Test All Providers","url":"/docs/getting-started/environment-variables#test-all-providers","content":"Test All Providers","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Test All Providers","lvl3":""}},
4445
4460
  {"objectID":"398b7ac6664cfd71622b79d740c6be02ee086127e030bdb1e7db43cf4d29f8fc","title":"Expected Output","url":"/docs/getting-started/environment-variables#expected-output","content":"Expected Output","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Expected Output","lvl3":""}},
4461
+ {"objectID":"288a2b72e08abd8814d103504568cfb1f80dfe930007b475b038176bd4d12cde","title":"Attachment loading (NEUROLINK_ATTACHMENT_*)","url":"/docs/getting-started/environment-variables#attachment-loading-neurolink_attachment_","content":"What the SDK may read or fetch when a call names a file path or a URL\n(input.files, input.images, rag.files, transcribe({ audio })). Each\nvariable mirrors a field of the attachments constructor option, which wins\nwhen both are set. See Attachment Security.","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Attachment loading (NEUROLINK_ATTACHMENT_*)","lvl3":""}},
4446
4462
  {"objectID":"945a1a4e8118d860ee26e1fc3e2574ccb45c6513406549fa20e4a5e36e0bce0b","title":"API Key Management","url":"/docs/getting-started/environment-variables#api-key-management","content":"✅ Use .env files for local development\n✅ Use environment variables in production\n✅ Rotate keys regularly (every 90 days)\n❌ Never commit keys to version control\n❌ Never hardcode keys in source code","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"API Key Management","lvl3":""}},
4447
4463
  {"objectID":"012c6a012c378d31363a77d4ee68cfeadd6f7a1fb36132fdeb92eca8c1ccf192","title":".gitignore Configuration","url":"/docs/getting-started/environment-variables#gitignore-configuration","content":".gitignore Configuration","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":".gitignore Configuration","lvl3":""}},
4448
4464
  {"objectID":"99decb44ca568ee3356f7dba1a59e8340cca0cab9fa9a576e98aa59636ec88e0","title":"Production Deployment","url":"/docs/getting-started/environment-variables#production-deployment","content":"Use secret management systems (AWS Secrets Manager, Azure Key Vault)\nImplement key rotation policies\nMonitor API usage and rate limits\nUse least privilege access policies","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Production Deployment","lvl3":""}},
4465
+ {"objectID":"576b77d15c571959f94b3da286da93e5ea3f75f991f1356bba2a85ae953a1266","title":"Serving over HTTP (neurolink serve)","url":"/docs/getting-started/environment-variables#serving-over-http-neurolink-serve","content":"neurolink serve listens on 127.0.0.1 unless --host says otherwise, and\nrefuses to bind a non-loopback host without an API key. These variables govern\nthe listener; see\n/docs/reference/server-configuration:","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"Serving over HTTP (neurolink serve)","lvl3":""}},
4449
4466
  {"objectID":"a3eef4d2af0af4cb92132c515f83a8fb87c7abfaa1fd2e867338f51ae4d7deac","title":"1. \"Missing API Key\" Error","url":"/docs/getting-started/environment-variables#1-missing-api-key-error","content":"1. \"Missing API Key\" Error","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"1. \"Missing API Key\" Error","lvl3":""}},
4450
4467
  {"objectID":"d8adc791030cb03648ec0203bc9a397d7947b6290b4bcece4d88ce8b4bbbfe47","title":"2. AWS Bedrock \"Not Authorized\" Error","url":"/docs/getting-started/environment-variables#2-aws-bedrock-not-authorized-error","content":"✅ Verify account has model access in Bedrock console\n✅ Use full inference profile ARN for Anthropic models\n✅ Check IAM permissions include Bedrock access","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"2. AWS Bedrock \"Not Authorized\" Error","lvl3":""}},
4451
4468
  {"objectID":"bf2d1c672dcfc8a02c17c2b9e795ca7605850fe3e46cceb22089a460a2069738","title":"3. Google Vertex AI Import Issues","url":"/docs/getting-started/environment-variables#3-google-vertex-ai-import-issues","content":"✅ Ensure Vertex AI API is enabled\n✅ Verify service account has correct permissions\n✅ Check JSON file path is absolute and accessible","hierarchy":{"lvl0":"Getting Started","lvl1":"🔧 Environment Variables Configuration Guide","lvl2":"3. Google Vertex AI Import Issues","lvl3":""}},
@@ -5284,15 +5301,15 @@
5284
5301
  {"objectID":"293d0cf78c8b91321aaea4539752c75c5d23b0f630e75d8c039fa5b10759fbd8","title":"Voice not found","url":"/docs/getting-started/providers/elevenlabs#voice-not-found","content":"You passed a voice ID that does not exist in your account. List available voices to confirm:","hierarchy":{"lvl0":"Getting Started","lvl1":"ElevenLabs Provider Guide","lvl2":"Voice not found","lvl3":""}},
5285
5302
  {"objectID":"a8f667c71e278a2fbdf507c9d16d18418a74fc97ae593129deaa675058c728f5","title":"\"Failed to get voices\"","url":"/docs/getting-started/providers/elevenlabs#failed-to-get-voices","content":"Voice discovery failed (network error or invalid key). The 5-minute cache shields against transient failures, but a hard failure at startup will propagate. Ensure ELEVENLABS_API_KEY is valid and the ElevenLabs API is reachable.","hierarchy":{"lvl0":"Getting Started","lvl1":"ElevenLabs Provider Guide","lvl2":"\"Failed to get voices\"","lvl3":""}},
5286
5303
  {"objectID":"58ee78d9a6be3099cc23a438c6255e483cabb54fdd59e63c6d9de2a3e10068ad","title":"See Also","url":"/docs/getting-started/providers/elevenlabs#see-also","content":"TTS Integration Guide — complete multi-provider TTS reference\nOpenAI TTS Provider Guide — alternative TTS provider\nAudio Input (STT) — speech-to-text counterpart\nVoice Agent Guide — building full voice assistants\n\nNeed Help? Join the GitHub Discussions or open an issue.","hierarchy":{"lvl0":"Getting Started","lvl1":"ElevenLabs Provider Guide","lvl2":"See Also","lvl3":""}},
5287
- {"objectID":"7f6bb3946274afde9ce29bfc356e888f59ea0cb8955e0c63cbd5bc3101a024af","title":"EmpirioLabs AI Provider Guide","url":"/docs/getting-started/providers/empiriolabs","content":"EmpirioLabs AI Provider Guide\n\nEmpirioLabs AI is a Tier-2 catalog provider: OpenAI-wire-compatible with no\nbehavioural quirks, so its entire integration is one JSON file\n(src/lib/providers/catalog/empiriolabs.json) rather than hand-written code.\nThat file is the source of truth for everything on this page.\n\nVerification status: docs- and roster-verified, not yet live-verified.\nThis entry was onboarded credential-free — no API key was created and no\nchat, streaming or tool-call request was ever sent. Everything below comes\nfrom the vendor's own public docs (docs.empiriolabs.ai) and an\nunauthenticated GET /v1/models call. evidence.liveMatrix is null\nin the catalog file until someone runs the live capability sweep with a\nreal key (see Live verification).\n\nKey Facts\nProvider id: empiriolabs\nProtocol: OpenAI-compatible (/v1/chat/completions) — confirmed on\n docs.empiriolabs.ai: \"Accepts the same request body as the OpenAI Chat\n Completions API.\"\nBase URL: https://api.empiriolabs.ai/v1\nDefault model: glm-5-3 (Zhipu GLM-5.3 — marked is_featured: true on\n the live roster)\nModels in catalog: 6 (curated text/chat subset of a 217-model roster\n that also spans vision, audio, video, image and 3D generation)\nStreaming: documented as a supported request parameter (stream); not\n live-probed\nTool calling: model-dependent — the roster's own features field\n marks function_calling on 97 of 217 models, not all of them\nStructured output: model-dependent per the vendor's docs\n (\"json_schema means strict schema support, json_object means JSON mode\n only... check via GET /v1/models/{modelId}\"); the default model\n (glm-5-3) documents json_object support, so the provider-level flag is\n true\nStructured output + tools together: not declared — no combined probe\n was possible without a key\nEmbeddings: not supported by this integration (the vendor does list a\n separate embedding-model family, but NeuroLink's generic OpenAI-compatible\n catalog provider does not implement embed()/embedMany())\nBilling: free-tier — pricing page: \"$0 to start... No subscription\n needed\", with several models marked \"Free\" at $0 input/output/cache cost.\n Getting-started docs also list prepaid credits as a prerequisite for\n non-free models, so budget for that before heavy use.\nKey format: keys use the sk-empiriolabs- prefix (documented)\n\nQuick Start\nGet an API key\nVisit: https://platform.empiriolabs.ai and create an account\nCreate an API key from the dashboard (keys use the sk-empiriolabs-\n prefix, up to 50 per account)\nSelected models (e.g. GLM 4.7 Flash) run at $0 cost; other models draw\n from prepaid credits topped up via the dashboard Billing page — confirm\n current pricing before heavy use\nSet EMPIRIOLABS_API_KEY in your .env file\nConfigure\nUse it\n\nPer-request credentials work as they do for every provider:\n\nModels\n\n| Model | Context | Max out | Vision | Structured output | $/M in · out (cached) | Notes |\n| ------------------------ | ------- | ------- | ------ | ----------------- | ----------------------- | ------------------------------------------------------------------------------------------------------- |\n| glm-5-3 ⭐ | 1M | 131,072 | no | json_object | $1.40 / $4.40 ($1.40) | Recommended — roster is_featured: true; reasoning, function calling, web search. |\n| glm-5-3-flash | 1M | 131,072 | yes | json_object | $0.075 / $0.25 ($0.075) | Lighter/cheaper sibling; also vision (document_understanding, video_understanding); fallback. |\n| glm-5-2 | 1M | 131,072 | no | json_object | $1.40 / $4.40 ($1.40) | Prior GLM generation; fallback. |\n| kimi-k3 | 1M | 131,072 | yes | json_schema | $3.00 / $15.00 ($3.00) | Moonshot Kimi K3 — multimodal, agentic coding; strict schema output; fallback. |\n| qwen3-7-max | 1M | 65,536 | no | json_schema | $2.50 / $7.50 ($2.50) | Alibaba flagship reasoning model with code interpreter; lower max output than the GLM family; fallback. |\n| minimax-m2-7-highspeed | 200K | 32,768 | no | json_object | $0.30 / $1.20 ($0.03) | Smallest context/output in this set; lightest/cheapest fallback. |\n\nAll context, output, pricing and structured-output values above are read\ndirectly from the unauthenticated GET https://api.empiriolabs.ai/v1/models\nresponse (2026-09-28), not invented or estimated. This 6-model set is a\ncurated subset — the full roster returned 217 ids spanning text, vision,\naudio, video, image and 3D-generation models; only text/chat-completions\nmodels with documented function_calling are catalogued here.\n\nFallback order when the default is unavailable: glm-5-3-flash →\nglm-5-2 → kimi-k3 → ","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"","lvl3":""}},
5288
- {"objectID":"9667985ea098d5b6e3f3df88e69488be9a4e8e7884becfbe54ecb70f60f262e9","title":"EmpirioLabs AI Provider Guide","url":"/docs/getting-started/providers/empiriolabs#empiriolabs-ai-provider-guide","content":"EmpirioLabs AI is a Tier-2 catalog provider: OpenAI-wire-compatible with no\nbehavioural quirks, so its entire integration is one JSON file\n(src/lib/providers/catalog/empiriolabs.json) rather than hand-written code.\nThat file is the source of truth for everything on this page.\n\nVerification status: docs- and roster-verified, not yet live-verified.\nThis entry was onboarded credential-free — no API key was created and no\nchat, streaming or tool-call request was ever sent. Everything below comes\nfrom the vendor's own public docs (docs.empiriolabs.ai) and an\nunauthenticated GET /v1/models call. evidence.liveMatrix is null\nin the catalog file until someone runs the live capability sweep with a\nreal key (see Live verification).","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"EmpirioLabs AI Provider Guide","lvl3":""}},
5304
+ {"objectID":"7f6bb3946274afde9ce29bfc356e888f59ea0cb8955e0c63cbd5bc3101a024af","title":"EmpirioLabs AI Provider Guide","url":"/docs/getting-started/providers/empiriolabs","content":"EmpirioLabs AI Provider Guide\n\nEmpirioLabs AI is a specialized AI inference and\nintegration provider. It hosts open-source models on GPU infrastructure it\nmanages, runs optimized endpoints for proprietary models, helps teams ship their\nown models, and offers on-demand GPU Cloud instances and hosted AI agents. Its\nmodel catalog spans text, image, audio, video, transcription, embedding,\nreranking, research and 3D models. API reference and guides are in the\nEmpirioLabs AI docs.\n\nIn NeuroLink, EmpirioLabs AI is a Tier-2 catalog provider: it speaks the OpenAI wire\nformat, so its entire integration is one JSON file\n(src/lib/providers/catalog/empiriolabs.json) rather than hand-written code.\nThat file is the source of truth for everything on this page.\n\nVerification status: docs- and roster-verified, not yet live-verified.\nThis entry was onboarded credential-free — no API key was created and no\nchat, streaming or tool-call request was ever sent. Everything below comes\nfrom the vendor's own public docs (docs.empiriolabs.ai) and an\nunauthenticated GET /v1/models call. evidence.liveMatrix is null\nin the catalog file until someone runs the live capability sweep with a\nreal key (see Live verification).\n\nKey Facts\nProvider id: empiriolabs\nProtocol: OpenAI-compatible (/v1/chat/completions) — confirmed on\n docs.empiriolabs.ai: \"Accepts the same request body as the OpenAI Chat\n Completions API.\"\nBase URL: https://api.empiriolabs.ai/v1\nDefault model: glm-5-3 (Zhipu GLM-5.3 — marked is_featured: true on\n the live roster)\nModels in catalog: 6 (curated text/chat subset of a 217-model roster\n that also spans vision, audio, video, image and 3D generation)\nStreaming: documented as a supported request parameter (stream); not\n live-probed\nTool calling: model-dependent — the roster's own features field\n marks function_calling on 97 of 217 models, not all of them\nStructured output: model-dependent per the vendor's docs\n (\"json_schema means strict schema support, json_object means JSON mode\n only... check via GET /v1/models/{modelId}\"); the default model\n (glm-5-3) documents json_object support, so the provider-level flag is\n true\nStructured output + tools together: not declared — no combined probe\n was possible without a key\nEmbeddings: not supported by this integration (the vendor does list a\n separate embedding-model family, but NeuroLink's generic OpenAI-compatible\n catalog provider does not implement embed()/embedMany())\nBilling: free-tier — pricing page: \"$0 to start... No subscription\n needed\", with several models marked \"Free\" at $0 input/output/cache cost.\n Getting-started docs also list prepaid credits as a prerequisite for\n non-free models, so budget for that before heavy use.\nKey format: keys use the sk-empiriolabs- prefix (documented)\n\nQuick Start\nGet an API key\nVisit: https://platform.empiriolabs.ai and create an account\nCreate an API key from the dashboard (keys use the sk-empiriolabs-\n prefix, up to 50 per account)\nSelected models (e.g. GLM 4.7 Flash) run at $0 cost; other models draw\n from prepaid credits topped up via the dashboard Billing page — confirm\n current pricing before heavy use\nSet EMPIRIOLABS_API_KEY in your .env file\nConfigure\nUse it\n\nPer-request credentials work as they do for every provider:\n\nModels\n\n| Model | Context | Max out | Vision | Structured output | $/M in · out (cached) | Notes |\n| ------------------------ | ------- | ------- | ------ | ----------------- | ----------------------- | ------------------------------------------------------------------------------------------------------- |\n| glm-5-3 ⭐ | 1M | 131,072 | no | json_object | $1.40 / $4.40 ($1.40) | Recommended — roster is_featured: true; reasoning, function calling, web search. |\n| glm-5-3-flash | 1M | 131,072 | yes | json_object | $0.075 / $0.25 ($0.075) | Lighter/cheaper sibling; also vision (document_understanding, video_understanding); fallback. |\n| glm-5-2 | 1M | 131,072 | no | json_object | $1.40 / $4.40 ($1.40) | Prior GLM generation; fallback. |\n| kimi-k3 | 1M | 131,072 | yes | json_schema | $3.00 / $15.00 ($3.00) | Moonshot Kimi K3 — multimodal, agentic coding; strict schema output; fallback. |\n| qwen3-7-max | 1M | 65,536 | no | json_schema | $2.50 / $7.50 ($2.50) | Alibaba flagship reasoning model with code interpreter; lower max output than the GLM family; fallback. |\n| minimax-m2-7-highspeed | 200K | 32,768 | no | json_object | $0.30 / $1.20 ($0.03) | Smallest context/output in this set; lightest/cheapest fallback. |\n\nAll context, output, pricing and structured-output values above a","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"","lvl3":""}},
5305
+ {"objectID":"9667985ea098d5b6e3f3df88e69488be9a4e8e7884becfbe54ecb70f60f262e9","title":"EmpirioLabs AI Provider Guide","url":"/docs/getting-started/providers/empiriolabs#empiriolabs-ai-provider-guide","content":"EmpirioLabs AI is a specialized AI inference and\nintegration provider. It hosts open-source models on GPU infrastructure it\nmanages, runs optimized endpoints for proprietary models, helps teams ship their\nown models, and offers on-demand GPU Cloud instances and hosted AI agents. Its\nmodel catalog spans text, image, audio, video, transcription, embedding,\nreranking, research and 3D models. API reference and guides are in the\nEmpirioLabs AI docs.\n\nIn NeuroLink, EmpirioLabs AI is a Tier-2 catalog provider: it speaks the OpenAI wire\nformat, so its entire integration is one JSON file\n(src/lib/providers/catalog/empiriolabs.json) rather than hand-written code.\nThat file is the source of truth for everything on this page.\n\nVerification status: docs- and roster-verified, not yet live-verified.\nThis entry was onboarded credential-free — no API key was created and no\nchat, streaming or tool-call request was ever sent. Everything below comes\nfrom the vendor's own public docs (docs.empiriolabs.ai) and an\nunauthenticated GET /v1/models call. evidence.liveMatrix is null\nin the catalog file until someone runs the live capability sweep with a\nreal key (see Live verification).","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"EmpirioLabs AI Provider Guide","lvl3":""}},
5289
5306
  {"objectID":"512dbbda3ceab0cc664df558d52aef286593d18ff49a1c718433ce16d6d8834a","title":"Key Facts","url":"/docs/getting-started/providers/empiriolabs#key-facts","content":"Provider id: empiriolabs\nProtocol: OpenAI-compatible (/v1/chat/completions) — confirmed on\n docs.empiriolabs.ai: \"Accepts the same request body as the OpenAI Chat\n Completions API.\"\nBase URL: https://api.empiriolabs.ai/v1\nDefault model: glm-5-3 (Zhipu GLM-5.3 — marked is_featured: true on\n the live roster)\nModels in catalog: 6 (curated text/chat subset of a 217-model roster\n that also spans vision, audio, video, image and 3D generation)\nStreaming: documented as a supported request parameter (stream); not\n live-probed\nTool calling: model-dependent — the roster's own features field\n marks function_calling on 97 of 217 models, not all of them\nStructured output: model-dependent per the vendor's docs\n (\"json_schema means strict schema support, json_object means JSON mode\n only... check via GET /v1/models/{modelId}\"); the default model\n (glm-5-3) documents json_object support, so the provider-level flag is\n true\nStructured output + tools together: not declared — no combined probe\n was possible without a key\nEmbeddings: not supported by this integration (the vendor does list a\n separate embedding-model family, but NeuroLink's generic OpenAI-compatible\n catalog provider does not implement embed()/embedMany())\nBilling: free-tier — pricing page: \"$0 to start... No subscription\n needed\", with several models marked \"Free\" at $0 input/output/cache cost.\n Getting-started docs also list prepaid credits as a prerequisite for\n non-free models, so budget for that before heavy use.\nKey format: keys use the sk-empiriolabs- prefix (documented)","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"Key Facts","lvl3":""}},
5290
5307
  {"objectID":"d7035afcfe6b89815711ef4af1430b377fb479254ac55cfe3d11e54e8b771ea6","title":"1. Get an API key","url":"/docs/getting-started/providers/empiriolabs#1-get-an-api-key","content":"Visit: https://platform.empiriolabs.ai and create an account\nCreate an API key from the dashboard (keys use the sk-empiriolabs-\n prefix, up to 50 per account)\nSelected models (e.g. GLM 4.7 Flash) run at $0 cost; other models draw\n from prepaid credits topped up via the dashboard Billing page — confirm\n current pricing before heavy use\nSet EMPIRIOLABS_API_KEY in your .env file","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"1. Get an API key","lvl3":""}},
5291
5308
  {"objectID":"11fe80ce183fea4b3a6867445095459a2a2f40f88d14b4feabd223d1aa6243e3","title":"2. Configure","url":"/docs/getting-started/providers/empiriolabs#2-configure","content":"2. Configure","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"2. Configure","lvl3":""}},
5292
5309
  {"objectID":"a9a581e5740730585f01ad3aa3f0f0060a8204b5c9e47a298328130654194745","title":"3. Use it","url":"/docs/getting-started/providers/empiriolabs#3-use-it","content":"Per-request credentials work as they do for every provider:","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"3. Use it","lvl3":""}},
5293
5310
  {"objectID":"47a1b4bb656a103c281c6dedea3ddfcd32893835539ee4bc50711aafb0ec5f9e","title":"Models","url":"/docs/getting-started/providers/empiriolabs#models","content":"| Model | Context | Max out | Vision | Structured output | $/M in · out (cached) | Notes |\n| ------------------------ | ------- | ------- | ------ | ----------------- | ----------------------- | ------------------------------------------------------------------------------------------------------- |\n| glm-5-3 ⭐ | 1M | 131,072 | no | json_object | $1.40 / $4.40 ($1.40) | Recommended — roster is_featured: true; reasoning, function calling, web search. |\n| glm-5-3-flash | 1M | 131,072 | yes | json_object | $0.075 / $0.25 ($0.075) | Lighter/cheaper sibling; also vision (document_understanding, video_understanding); fallback. |\n| glm-5-2 | 1M | 131,072 | no | json_object | $1.40 / $4.40 ($1.40) | Prior GLM generation; fallback. |\n| kimi-k3 | 1M | 131,072 | yes | json_schema | $3.00 / $15.00 ($3.00) | Moonshot Kimi K3 — multimodal, agentic coding; strict schema output; fallback. |\n| qwen3-7-max | 1M | 65,536 | no | json_schema | $2.50 / $7.50 ($2.50) | Alibaba flagship reasoning model with code interpreter; lower max output than the GLM family; fallback. |\n| minimax-m2-7-highspeed | 200K | 32,768 | no | json_object | $0.30 / $1.20 ($0.03) | Smallest context/output in this set; lightest/cheapest fallback. |\n\nAll context, output, pricing and structured-output values above are read\ndirectly from the unauthenticated GET https://api.empiriolabs.ai/v1/models\nresponse (2026-09-28), not invented or estimated.","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"Models","lvl3":""}},
5294
5311
  {"objectID":"b5a3aa64f768a8d7ae8598c18e71673a2abc35f1ac40547734d50eb812eb00d3","title":"Verification status","url":"/docs/getting-started/providers/empiriolabs#verification-status","content":"Tier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This is what the\ncatalog currently records for EmpirioLabs AI:\n\n| Probe | Result |\n| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Roster | unauthenticated GET /v1/models, HTTP 200, 217 models, 2026-09-28. No API key was created or used. |\n| Auth rejection | Not probed (would require a key). Documented shape only: docs.empiriolabs.ai/authentication states a missing/malformed/unknown token returns 401 Unauthorized. |\n| Wire compatibility | Documented only: docs.empiriolabs.ai/compatibility states the endpoint \"accepts the same request body as the OpenAI Chat Completions API\" and lists messages, model, stream, temperature, max_tokens, response_format as supported. |\n| Live capability sweep | Not run. evidence.liveMatrix is null. No chat, streaming, tool-call or structured-output request has been sent to this vendor.","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"Verification status","lvl3":""}},
5295
- {"objectID":"ef64365a6f8ebc4d0e7ec47fa758ca6132239036fefa1bc851c42c6e60965b17","title":"Documented quirks worth knowing (not catalog quirks)","url":"/docs/getting-started/providers/empiriolabs#documented-quirks-worth-knowing-not-catalog-quirks","content":"Implicit system prompt: EmpirioLabs docs say every chat model has a\n built-in identity message that is prepended automatically when your\n request has no system/developer role message. Supplying your own\n system message fully replaces it (no merging). This doesn't require a\n named catalog quirks entry — it only changes behavior when you omit a\n system message — but it's worth knowing if a completion reads oddly\n \"in character.\"\nresponse_format is per-model: sending a structured-output format a\n model doesn't support returns HTTP 400 per the vendor's docs. Check\n GET /v1/models/{modelId} for a given model's structured_output value\n (json_schema, json_object, or absent) before relying on it.","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"Documented quirks worth knowing (not catalog quirks)","lvl3":""}},
5312
+ {"objectID":"ef64365a6f8ebc4d0e7ec47fa758ca6132239036fefa1bc851c42c6e60965b17","title":"Documented quirks worth knowing (not catalog quirks)","url":"/docs/getting-started/providers/empiriolabs#documented-quirks-worth-knowing-not-catalog-quirks","content":"Implicit system prompt: EmpirioLabs AI docs say every chat model has a\n built-in identity message that is prepended automatically when your\n request has no system/developer role message. Supplying your own\n system message fully replaces it (no merging). This doesn't require a\n named catalog quirks entry — it only changes behavior when you omit a\n system message — but it's worth knowing if a completion reads oddly\n \"in character.\"\nresponse_format is per-model: sending a structured-output format a\n model doesn't support returns HTTP 400 per the vendor's docs. Check\n GET /v1/models/{modelId} for a given model's structured_output value\n (json_schema, json_object, or absent) before relying on it.","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"Documented quirks worth knowing (not catalog quirks)","lvl3":""}},
5296
5313
  {"objectID":"b54d9fb43ab2b37512ceae0461e6db93cefde1eca154cddbb4f1f0661e80552b","title":"Troubleshooting","url":"/docs/getting-started/providers/empiriolabs#troubleshooting","content":"| Symptom | Cause | Fix |\n| ------------------------------------------------------ | --------------------------------------------------------------------- | --------------------------------------------------------------------------------- |\n| Invalid EmpirioLabs API key | EMPIRIOLABS_API_KEY unset or wrong | Check the key at https://platform.empiriolabs.ai |\n| 401 Unauthorized | Token missing, malformed, or not found (per vendor docs) | Confirm the header is Authorization: Bearer sk-empiriolabs-... |\n| 402 Payment Required (documented, not live-verified) | Account has insufficient prepaid credits | Top up credits via the dashboard Billing page, or pick a $0 free model |\n| 429 Too Many Requests | Rate limit exceeded (new accounts: 50 RPM / 2,000,000 TPM) | Retry with exponential backoff, or email support@empiriolabs.ai for higher limits |\n| HTTP 400 on response_format | The chosen model doesn't support the requested structured-output mode | Check GET /v1/models/{modelId} for that model's structured_output value |","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
5297
5314
  {"objectID":"fb753a98000a6b9a70d1fcda483c5f68eb47882e3704a3564e99d6ffe38ca484","title":"See also","url":"/docs/getting-started/providers/empiriolabs#see-also","content":"Provider setup overview\nAll providers\nTier-2 onboarding — how this provider's JSON becomes a working integration, including the live-verification steps this entry still needs\nProvider feature compatibility","hierarchy":{"lvl0":"Getting Started","lvl1":"EmpirioLabs AI Provider Guide","lvl2":"See also","lvl3":""}},
5298
5315
  {"objectID":"ed9b509fc25930e44605e1dc0ebf6d551bef2fe83f9326bd674bab158b85ffc8","title":"Featherless AI Provider Guide","url":"/docs/getting-started/providers/featherless-ai","content":"Featherless AI Provider Guide\n\nFeatherless AI is a Tier-2 catalog provider: OpenAI-wire-compatible with no\nbehavioural quirks, so its entire integration is one JSON file\n(src/lib/providers/catalog/featherless-ai.json) rather than hand-written code.\nThat file is the source of truth for everything on this page.\n\nVerification status: this entry is docs- and roster-verified, not yet\nlive-verified. Every field below comes from Featherless's own published\ndocs and an unauthenticated GET /v1/models call — no API key was used to\nwrite this entry, so no request-response wire behavior (streaming, tool\ncalling, structured output) has actually been exercised end to end yet. See\nVerification status for exactly what was and was\nnot checked.\n\nKey Facts\nProvider id: featherless-ai\nProtocol: OpenAI-compatible (/chat/completions), per Featherless's own\n docs: \"Featherless's API is designed to be API compatible with OpenAI.\"\nBase URL: https://api.featherless.ai/v1\nDefault model: unsloth/Llama-3.3-70B-Instruct\nModels in catalog: 12 (out of a live roster of 22,060 models — see\n Models for why these 12)\nStreaming: not documented anywhere in Featherless's docs — declared\n false until confirmed live\nTool calling: model-dependent. Featherless's Tool Calling\n guide natively supports only the\n moonshotai/Kimi-K2-Instruct and Qwen 3 model families; other models need\n a prompting workaround the guide documents separately\nStructured output: not documented (no response_format/JSON-mode\n mention anywhere in the docs checked) — declared false\nEmbeddings: Featherless does document a separate POST\n/v1/embeddings endpoint for embedding-output models, but that is a distinct\n model family from the chat models in this catalog entry and is not wired\n through this provider — declared false\nBilling: no free tier. Plans start at $25/mo\nKey format: none declared by the vendor\nGated models: some roster ids are Hugging-Face-gated and return HTTP 403\n until unlocked manually in the account UI (see\n Troubleshooting)\n\nQuick Start\nGet an API key\nVisit: https://featherless.ai/register and create an account (or\n https://featherless.ai/login if you already have one)\nSubscribe to a plan — Chat ($25/mo, unlimited tokens, 32K context) or\n Developer ($50/mo in credits, billed per token, up to 256K context);\n Featherless has no free or keyless tier\nGenerate an API key from the API keys section of your account\nSet FEATHERLESS_AI_API_KEY in your .env file\nConfigure\nUse it\n\nPer-request credentials work as they do for every provider:\n\nModels\n\nFeatherless's live roster is enormous — 22,060 models as of 2026-09-28,\nspanning mainline instruction-tuned checkpoints alongside a very large number\nof community roleplay, uncensored and \"abliterated\" (safety-refusal-removed)\nfine-tunes; Featherless's own site markets these as first-class catalog\nfilters (\"LLMs for Roleplay\", \"Uncensored Models\", \"Abliterated Models\"). This\ncatalog entry lists 12 models — a bounded, verifiable slice, not the whole\nroster — chosen to include the default, its closest official counterpart, and\na representative spread of the architectures Featherless serves (Llama-3.3-70B\nfamily, QRWKV, RWKV5).\n\n| Model | Context | Vision | $/M in · out | Notes |\n| ---------------------------------------------- | ------- | ------ | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| unsloth/Llama-3.3-70B-Instruct ⭐ | 32K | no | $2.60 / $3.00 | Recommended — an ungated community re-upload of Meta's Llama 3.3 70B Instruct. Chosen as default because the official meta-llama id is gated (see below). Roster reports tool_use: true. |\n| meta-llama/Llama-3.3-70B-Instruct | 32K | no | $0.65 / $0.75 | Meta's official weights. Hugging-Face-gated on Featherless (HTTP 403 until unlocked in the account UI) — kept as a fallback, not the default. |\n| Sao10K/L3.3-70B-Euryale-v2.3 | 32K | no | $0.65 / $0.75 | Roleplay/long-form-writing Llama-3.3-70B fine-tune. Not gated; roster-listed only. |\n| EVA-UNIT-01/EVA-LLaMA-3.33-70B-v0.0 | 32K | no | $2.60 / $3.00 | Creative-writing/roleplay Llama-3.3-70B fine-tune. Not gated; roster-listed only. |\n| EVA-UNIT-01/EVA-LLaMA-3.33-70B-v0.1 | 32K | no | $2.60 / $3.00 | Later revision of the EVA-LLaMA line above. Not gated; roster-listed only. ","hierarchy":{"lvl0":"Getting Started","lvl1":"Featherless AI Provider Guide","lvl2":"","lvl3":""}},
@@ -7342,10 +7359,10 @@
7342
7359
  {"objectID":"528c131f659c227460acb3197adafd7b9a7f0d26a232d7181bf480cad9542cbe","title":"Environment Variables (Production)","url":"/docs/guides/frameworks/sveltekit#environment-variables-production","content":"Environment Variables (Production)","hierarchy":{"lvl0":"Guides","lvl1":"SvelteKit Integration Guide","lvl2":"Environment Variables (Production)","lvl3":""}},
7343
7360
  {"objectID":"a86f4915394a5106e65dd50477d31423486db347ca83c02354ed3a06df8cdc62","title":"Related Documentation","url":"/docs/guides/frameworks/sveltekit#related-documentation","content":"API Reference - NeuroLink SDK\nStreaming Guide - Real-time responses\nCompliance Guide - Security and authentication\nCost Optimization - Reduce costs\nFastify Integration - High-performance Node.js framework with schema validation","hierarchy":{"lvl0":"Guides","lvl1":"SvelteKit Integration Guide","lvl2":"Related Documentation","lvl3":""}},
7344
7361
  {"objectID":"dae99b935ff34c8fd5f10f0ac1f2f4fdffb0cd777d7bb45c7bc7f4b91059014c","title":"Additional Resources","url":"/docs/guides/frameworks/sveltekit#additional-resources","content":"SvelteKit Documentation - Official SvelteKit docs\nSvelte Tutorial - Learn Svelte\nSvelteKit Examples - Example apps\n\nNeed Help? Join our GitHub Discussions or open an issue.","hierarchy":{"lvl0":"Guides","lvl1":"SvelteKit Integration Guide","lvl2":"Additional Resources","lvl3":""}},
7345
- {"objectID":"8f31aec32f066055dee31be79a01ee297a435bbf7f901cce7785983b2e27e1eb","title":"GitHub Action Guide","url":"/docs/guides/github-action","content":"GitHub Action Guide\n\nLast Updated: January 10, 2026\nNeuroLink Version: 8.32.0\n\nRun AI-powered workflows with supported providers directly in GitHub Actions. The NeuroLink GitHub Action enables automated code review, issue triage, content generation, and more.\n\nOverview\n\nThe NeuroLink GitHub Action provides a unified interface to integrate AI capabilities into your CI/CD workflows. It supports NeuroLink provider integrations through a single, consistent configuration.\n\nKey Features:\nMulti-provider support - supported AI providers with a unified interface\nPR/Issue comments - Auto-post AI responses with intelligent comment updates\nCost tracking - Built-in analytics with usage metrics\nQuality evaluation - Response scoring and validation\nMultimodal - Support for images, PDFs, CSVs, and videos\nExtended thinking - Deep reasoning with thinking tokens\nJob summaries - Detailed execution summaries in workflow runs\n\nQuick Start\n\nBasic Usage\n\nAuto Provider Detection\n\nWhen you set provider: auto (the default), NeuroLink automatically selects the best available provider based on which API keys you provide:\n\nProvider Configuration\n\nNeuroLink supports many AI providers. Configure each by providing the required credentials as secrets.\n\nProvider Quick Reference\n\n| Provider | Required Inputs | Example Models |\n| ----------------- | ------------------------------------------------------------------ | ------------------------------------------ |\n| OpenAI | openai_api_key | gpt-4o, gpt-4o-mini, o1 |\n| Anthropic | anthropic_api_key | claude-sonnet-4-20250514, claude-3-5-haiku |\n| Google AI Studio | google_ai_api_key | gemini-2.5-pro, gemini-2.5-flash |\n| Vertex AI | google_vertex_project, google_application_credentials | gemini-\\, claude-\\ |\n| Amazon Bedrock | aws_access_key_id, aws_secret_access_key | claude-\\, titan-\\, nova-\\* |\n| Azure OpenAI | azure_openai_api_key, azure_openai_endpoint | gpt-4o, gpt-4-turbo |\n| Mistral | mistral_api_key | mistral-large, mistral-small |\n| Hugging Face | huggingface_api_key | Various open models |\n| OpenRouter | openrouter_api_key | 300+ models |\n| LiteLLM | litellm_api_key, litellm_base_url | Proxy to 100+ models |\n| Ollama | - | Local models |\n| SageMaker | aws_access_key_id, aws_secret_access_key, sagemaker_endpoint | Custom endpoints |\n| OpenAI-Compatible | openai_compatible_api_key, openai_compatible_base_url | vLLM, custom APIs |\n\nOpenAI\n\nEnvironment Variables:\nOPENAI_API_KEY - Your OpenAI API key (starts with sk-)\n\nAvailable Models:\ngpt-4o - Most capable model\ngpt-4o-mini - Fast and cost-effective\no1 - Advanced reasoning model\ngpt-4-turbo - Previous generation flagship\n\nAnthropic\n\nEnvironment Variables:\nANTHROPIC_API_KEY - Your Anthropic API key (starts with sk-ant-)\n\nAvailable Models:\nclaude-sonnet-4-20250514 - Best overall performance\nclaude-3-5-haiku - Fast and efficient\nclaude-opus-4-20250514 - Maximum capability\n\nExtended Thinking Support: Anthropic models support extended thinking for deep reasoning tasks.\n\nGoogle AI Studio\n\nEnvironment Variables:\nGOOGLE_AI_API_KEY - Your Google AI Studio API key\n\nAvailable Models:\ngemini-2.5-pro - Most capable Gemini model\ngemini-2.5-flash - Fast and cost-effective\ngemini-2.0-flash - Previous generation\n\nFree Tier: Google AI Studio offers a generous free tier (1M tokens/day).\n\nGoogle Vertex AI\n\nEnvironment Variables:\nGOOGLE_VERTEX_PROJECT - Your GCP project ID\nGOOGLE_VERTEX_LOCATION - GCP region (default: us-central1)\nGOOGLE_APPLICATION_CREDENTIALS - Base64-encoded service account JSON\n\nSetup Service Account:\n\nAmazon Bedrock\n\nEnvironment Variables:\nAWS_ACCESS_KEY_ID - AWS access key\nAWS_SECRET_ACCESS_KEY - AWS secret key\nAWS_REGION - AWS region (default: us-east-1)\nAWS_SESSION_TOKEN - Optional session token for temporary credentials\n\nAvailable Models:\nanthropic.claude-3-5-sonnet-20241022-v2:0 - Claude on Bedrock\namazon.titan-text-express-v1 - Amazon Titan\namazon.nova-pro-v1:0 - Amazon Nova\n\nOIDC Authentication (Recommended):\n\nFor better security, use GitHub OIDC instead of static credentials:\n\nAzure OpenAI\n\nEnvironment Variables:\nAZURE_OPENAI_API_KEY - Azure OpenAI API key\nAZURE_OPENAI_ENDPOIN","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"","lvl3":""}},
7362
+ {"objectID":"8f31aec32f066055dee31be79a01ee297a435bbf7f901cce7785983b2e27e1eb","title":"GitHub Action Guide","url":"/docs/guides/github-action","content":"GitHub Action Guide\n\nLast Updated: January 10, 2026\nNeuroLink Version: 8.32.0\n\nRun AI-powered workflows with supported providers directly in GitHub Actions. The NeuroLink GitHub Action enables automated code review, issue triage, content generation, and more.\n\nOverview\n\nThe NeuroLink GitHub Action provides a unified interface to integrate AI capabilities into your CI/CD workflows. It supports NeuroLink provider integrations through a single, consistent configuration.\n\nKey Features:\nMulti-provider support - supported AI providers with a unified interface\nPR/Issue comments - Auto-post AI responses with intelligent comment updates\nCost tracking - Built-in analytics with usage metrics\nQuality evaluation - Response scoring and validation\nMultimodal - Support for images, PDFs, CSVs, and videos\nExtended thinking - Deep reasoning with thinking tokens\nJob summaries - Detailed execution summaries in workflow runs\n\nQuick Start\n\nBasic Usage\n\nPinning. The examples pin the action to a full commit SHA with the release it\ncorresponds to in a comment (# v13.8.16). A tag can be moved; a SHA cannot. Dependabot's\ngithub-actions ecosystem bumps SHA pins and rewrites the comment for you. The\nCLI the action installs is pinned the same way: by default it is the exact\n@juspay/neurolink version the action was released with, installed with\n--ignore-scripts and verified with npm audit signatures; set\nneurolink_version: latest only if you accept running whatever the registry\nserves at run time.\n\nAuto Provider Detection\n\nWhen you set provider: auto (the default), NeuroLink automatically selects the best available provider based on which API keys you provide:\n\nProvider Configuration\n\nNeuroLink supports many AI providers. Configure each by providing the required credentials as secrets.\n\nProvider Quick Reference\n\n| Provider | Required Inputs | Example Models |\n| ----------------- | ------------------------------------------------------------------ | ------------------------------------------ |\n| OpenAI | openai_api_key | gpt-4o, gpt-4o-mini, o1 |\n| Anthropic | anthropic_api_key | claude-sonnet-4-20250514, claude-3-5-haiku |\n| Google AI Studio | google_ai_api_key | gemini-2.5-pro, gemini-2.5-flash |\n| Vertex AI | google_vertex_project, google_application_credentials | gemini-\\, claude-\\ |\n| Amazon Bedrock | aws_access_key_id, aws_secret_access_key | claude-\\, titan-\\, nova-\\* |\n| Azure OpenAI | azure_openai_api_key, azure_openai_endpoint | gpt-4o, gpt-4-turbo |\n| Mistral | mistral_api_key | mistral-large, mistral-small |\n| Hugging Face | huggingface_api_key | Various open models |\n| OpenRouter | openrouter_api_key | 300+ models |\n| LiteLLM | litellm_api_key, litellm_base_url | Proxy to 100+ models |\n| Ollama | - | Local models |\n| SageMaker | aws_access_key_id, aws_secret_access_key, sagemaker_endpoint | Custom endpoints |\n| OpenAI-Compatible | openai_compatible_api_key, openai_compatible_base_url | vLLM, custom APIs |\n\nOpenAI\n\nEnvironment Variables:\nOPENAI_API_KEY - Your OpenAI API key (starts with sk-)\n\nAvailable Models:\ngpt-4o - Most capable model\ngpt-4o-mini - Fast and cost-effective\no1 - Advanced reasoning model\ngpt-4-turbo - Previous generation flagship\n\nAnthropic\n\nEnvironment Variables:\nANTHROPIC_API_KEY - Your Anthropic API key (starts with sk-ant-)\n\nAvailable Models:\nclaude-sonnet-4-20250514 - Best overall performance\nclaude-3-5-haiku - Fast and efficient\nclaude-opus-4-20250514 - Maximum capability\n\nExtended Thinking Support: Anthropic models support extended thinking for deep reasoning tasks.\n\nGoogle AI Studio\n\nEnvironment Variables:\nGOOGLE_AI_API_KEY - Your Google AI Studio API key\n\nAvailable Models:\ngemini-2.5-pro - Most capable Gemini model\ngemini-2.5-flash - Fast and cost-effective\ngemini-2.0-flash - Previous generation\n\nFree Tier: Google AI Studio offers a generous free tier (1M tokens/day).\n\nGoogle Vertex AI\n\nEnvironment Variables:\nGOOGLE_VERTEX_PROJECT - Your GCP project ID\nGOOGLE_VERTEX_LOCATION - GCP region (default: us-central1)\nGOOGLE_APPLICATION_CREDENTIALS - Base64-encoded service account JSON\n\nSetup Service Account:\n\nAmazon Bedrock\n\nEnvironment Variables:\nAWS_ACC","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"","lvl3":""}},
7346
7363
  {"objectID":"7ff4c3df91e5e1c298b72c9c4582ecd6d75ff6486e6af5c4ef96766507050d2b","title":"GitHub Action Guide","url":"/docs/guides/github-action#github-action-guide","content":"Last Updated: January 10, 2026\nNeuroLink Version: 8.32.0\n\nRun AI-powered workflows with supported providers directly in GitHub Actions. The NeuroLink GitHub Action enables automated code review, issue triage, content generation, and more.","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"GitHub Action Guide","lvl3":""}},
7347
7364
  {"objectID":"33dd9029b76affe39c2b849f369b0629e6061d643568bcefd1ab923e2653bd90","title":"Overview","url":"/docs/guides/github-action#overview","content":"The NeuroLink GitHub Action provides a unified interface to integrate AI capabilities into your CI/CD workflows. It supports NeuroLink provider integrations through a single, consistent configuration.\n\nKey Features:\nMulti-provider support - supported AI providers with a unified interface\nPR/Issue comments - Auto-post AI responses with intelligent comment updates\nCost tracking - Built-in analytics with usage metrics\nQuality evaluation - Response scoring and validation\nMultimodal - Support for images, PDFs, CSVs, and videos\nExtended thinking - Deep reasoning with thinking tokens\nJob summaries - Detailed execution summaries in workflow runs","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Overview","lvl3":""}},
7348
- {"objectID":"5529eda9c4b1ee03e1083e4492f5fe163abacd64cf80ae2d1034d60fec8c1dfe","title":"Basic Usage","url":"/docs/guides/github-action#basic-usage","content":"Basic Usage","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Basic Usage","lvl3":""}},
7365
+ {"objectID":"5529eda9c4b1ee03e1083e4492f5fe163abacd64cf80ae2d1034d60fec8c1dfe","title":"Basic Usage","url":"/docs/guides/github-action#basic-usage","content":"Pinning. The examples pin the action to a full commit SHA with the release it\ncorresponds to in a comment (# v13.8.16). A tag can be moved; a SHA cannot. Dependabot's\ngithub-actions ecosystem bumps SHA pins and rewrites the comment for you. The\nCLI the action installs is pinned the same way: by default it is the exact\n@juspay/neurolink version the action was released with, installed with\n--ignore-scripts and verified with npm audit signatures; set\nneurolink_version: latest only if you accept running whatever the registry\nserves at run time.","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Basic Usage","lvl3":""}},
7349
7366
  {"objectID":"3bb997302dc433bdb7ccaa27311d8b28539d24f519d50d7777495c4477c52933","title":"Auto Provider Detection","url":"/docs/guides/github-action#auto-provider-detection","content":"When you set provider: auto (the default), NeuroLink automatically selects the best available provider based on which API keys you provide:","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Auto Provider Detection","lvl3":""}},
7350
7367
  {"objectID":"a0196ac56db4df812b123855c3b7524934cf265a63e96a8ba68334d3206c0fe1","title":"Provider Configuration","url":"/docs/guides/github-action#provider-configuration","content":"NeuroLink supports many AI providers. Configure each by providing the required credentials as secrets.","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Provider Configuration","lvl3":""}},
7351
7368
  {"objectID":"e323a8ed54e480b24ca441ae97e154de2fc279ab13289c50496ffb1c1040dbbd","title":"Provider Quick Reference","url":"/docs/guides/github-action#provider-quick-reference","content":"| Provider | Required Inputs | Example Models |\n| ----------------- | ------------------------------------------------------------------ | ------------------------------------------ |\n| OpenAI | openai_api_key | gpt-4o, gpt-4o-mini, o1 |\n| Anthropic | anthropic_api_key | claude-sonnet-4-20250514, claude-3-5-haiku |\n| Google AI Studio | google_ai_api_key | gemini-2.5-pro, gemini-2.5-flash |\n| Vertex AI | google_vertex_project, google_application_credentials | gemini-\\, claude-\\ |\n| Amazon Bedrock | aws_access_key_id, aws_secret_access_key | claude-\\, titan-\\, nova-\\* |\n| Azure OpenAI | azure_openai_api_key, azure_openai_endpoint | gpt-4o, gpt-4-turbo |\n| Mistral | mistral_api_key | mistral-large, mistral-small |\n| Hugging Face | huggingface_api_key | Various open models |\n| OpenRouter | openrouter_api_key | 300+ models |\n| LiteLLM | litellm_api_key, litellm_base_url | Proxy to 100+ models |\n| Ollama | - | Local models |\n| SageMaker | aws_access_key_id, aws_secret_access_key, sagemaker_endpoint | Custom endpoints |\n| OpenAI-Compatible | openai_compatible_api_key, openai_compatible_base_url | vLLM, custom APIs |","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Provider Quick Reference","lvl3":""}},
@@ -7375,7 +7392,7 @@
7375
7392
  {"objectID":"9d8affbdd9f3994efdf9c28aad4f9a533cdd19bf0f94f88274ce94be8b0aabce","title":"Features","url":"/docs/guides/github-action#features","content":"| Input | Description | Required | Default |\n| ------------------- | ---------------------------------------- | -------- | ------- |\n| enable_analytics | Enable usage analytics and cost tracking | No | false |\n| enable_evaluation | Enable response quality evaluation | No | false |\n| enable_tools | Enable MCP tools | No | false |\n| mcp_config_path | Path to .mcp-config.json file | No | - |","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Features","lvl3":""}},
7376
7393
  {"objectID":"cd2bc4831eac9ead30a9349143dbefcbf7d044678b8816134d2404d6eb8d9269","title":"Output Configuration","url":"/docs/guides/github-action#output-configuration","content":"| Input | Description | Required | Default |\n| --------------- | ----------------------------- | -------- | ------- |\n| output_format | Output format: text, json | No | text |\n| output_file | Output file path | No | - |","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Output Configuration","lvl3":""}},
7377
7394
  {"objectID":"657840c33610b6e0306e02ec94db225b3d461252ea0a63ea40c9d32dedbbebc8","title":"GitHub Integration","url":"/docs/guides/github-action#github-integration","content":"| Input | Description | Required | Default |\n| ------------------------- | ------------------------------------------------ | -------- | --------------------- |\n| post_comment | Post AI response as PR/issue comment | No | false |\n| update_existing_comment | Update existing NeuroLink comment instead of new | No | true |\n| comment_tag | HTML comment tag to identify NeuroLink comments | No | neurolink-action |\n| github_token | GitHub token for PR/issue operations | No | ${{ github.token }} |","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"GitHub Integration","lvl3":""}},
7378
- {"objectID":"8c441000563b8a2d5fcff3b9c86182321c27e272f5a791160316d98f8c67b26b","title":"Advanced Options","url":"/docs/guides/github-action#advanced-options","content":"| Input | Description | Required | Default |\n| ------------------- | ----------------------------------- | -------- | -------- |\n| timeout | Request timeout in seconds | No | 300 |\n| debug | Enable debug logging | No | false |\n| neurolink_version | NeuroLink CLI version to install | No | latest |\n| working_directory | Working directory for CLI execution | No | . |","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Advanced Options","lvl3":""}},
7395
+ {"objectID":"8c441000563b8a2d5fcff3b9c86182321c27e272f5a791160316d98f8c67b26b","title":"Advanced Options","url":"/docs/guides/github-action#advanced-options","content":"| Input | Description | Required | Default |\n| ------------------- | -------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- |\n| timeout | Request timeout in seconds | No | 300 |\n| debug | Enable debug logging | No | false |\n| neurolink_version | Exact CLI version to install (x.y.z); empty = the reviewed pin the action was released with; latest opts into the moving tag | No | pinned |\n| working_directory | Working directory for CLI execution | No | . |","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Advanced Options","lvl3":""}},
7379
7396
  {"objectID":"49003856c30586882dfa359d2b164c4f683bfb74722b8eb4a87ee8cf5509172f","title":"Outputs Reference","url":"/docs/guides/github-action#outputs-reference","content":"The action provides the following outputs for use in subsequent steps:\n\n| Output | Description | Example |\n| ------------------- | -------------------------------------------- | ------------------------------------ |\n| response | AI response text content | \"Here is the review...\" |\n| response_json | Full JSON response including metadata | {\"content\": \"...\", \"model\": \"...\"} |\n| provider | Provider that was used | anthropic |\n| model | Model that was used | claude-sonnet-4-20250514 |\n| tokens_used | Total tokens consumed | 1523 |\n| prompt_tokens | Input/prompt tokens | 423 |\n| completion_tokens | Output/completion tokens | 1100 |\n| cost | Estimated cost in USD (if analytics enabled) | 0.0234 |\n| execution_time | Execution time in milliseconds | 2341 |\n| evaluation_score | Quality score 0-100 (if evaluation enabled) | 87 |\n| comment_id | GitHub comment ID (if post_comment enabled) | 1234567890 |\n| error | Error message if execution failed | null |","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Outputs Reference","lvl3":""}},
7380
7397
  {"objectID":"884e734a69849c4947fe6ac29e2a8ee227d9c76904e2f764f473172bdd176a43","title":"Using Outputs","url":"/docs/guides/github-action#using-outputs","content":"Using Outputs","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Using Outputs","lvl3":""}},
7381
7398
  {"objectID":"7f91a50e08da209329e08ab0fd71ead6465593134c6766f7978c0ff9317c90ad","title":"Multimodal Processing","url":"/docs/guides/github-action#multimodal-processing","content":"Process images, PDFs, CSVs, and videos along with text prompts.","hierarchy":{"lvl0":"Guides","lvl1":"GitHub Action Guide","lvl2":"Multimodal Processing","lvl3":""}},
@@ -8286,7 +8303,7 @@
8286
8303
  {"objectID":"22a5f3178da491b1a7a95bf39833fc78514c89d9edf72155848b11c5e3f2585c","title":"Server not appearing in Claude Desktop / Cursor","url":"/docs/mcp/docs-server#server-not-appearing-in-claude-desktop-cursor","content":"Verify the config file is in the correct location (see Quick Start above)\nEnsure the JSON is valid — a trailing comma or missing bracket will silently fail\nRestart the application after saving the config\nCheck that npx is available in your PATH","hierarchy":{"lvl0":"Mcp","lvl1":"NeuroLink Docs MCP Server","lvl2":"Server not appearing in Claude Desktop / Cursor","lvl3":""}},
8287
8304
  {"objectID":"e76bac54b3b4e4ccaff39887d70984e6a9c1211cba371f01b246df7c3597d5a8","title":"Connection timeout","url":"/docs/mcp/docs-server#connection-timeout","content":"If the server takes too long to start:\nThe first run downloads @juspay/neurolink via npx — this may take 10-30 seconds\nSubsequent runs use the npm cache and start faster\nFor faster startup, install globally: npm install -g @juspay/neurolink","hierarchy":{"lvl0":"Mcp","lvl1":"NeuroLink Docs MCP Server","lvl2":"Connection timeout","lvl3":""}},
8288
8305
  {"objectID":"5c0cedc9bd31d6c3e94ee646d72afe5554d2d012fc858fcc95e48e180c7180c7","title":"Tools not returning results","url":"/docs/mcp/docs-server#tools-not-returning-results","content":"If search returns empty results:\nVerify the search index exists and is not empty\nTry broader search terms — the index uses fuzzy matching with prefix search\nUse list_sections first to see available sections, then filter with section parameter","hierarchy":{"lvl0":"Mcp","lvl1":"NeuroLink Docs MCP Server","lvl2":"Tools not returning results","lvl3":""}},
8289
- {"objectID":"84213ad5a2888d73bad41a46ff853542912c1f9e85637e029f9766360fb6a882","title":"HTTP Transport for MCP Servers","url":"/docs/mcp/http-transport","content":"HTTP Transport for MCP Servers\n\nOverview\n\nNeuroLink now supports HTTP/Streamable HTTP transport for Model Context Protocol (MCP) servers, enabling integration with remote MCP services like GitHub Copilot MCP API and custom HTTP-based MCP endpoints.\n\nThe HTTP transport implements the MCP Streamable HTTP specification, providing:\n✅ Remote MCP server connectivity\n✅ Custom header support for authentication\n✅ Session management and automatic reconnection\n✅ Firewall and proxy compatibility\n✅ Both streaming (SSE) and batch JSON responses\n\nQuick Start\n\nGitHub Copilot Integration\n\nConfiguration File\n\nAdd to .mcp-config.json:\n\nProgrammatic Usage\n\nAuthentication\n\nHTTP transport supports custom headers for authentication:\n\nBearer Token Authentication\n\nAPI Key Authentication\n\nCustom Headers\n\nOAuth 2.1 Authentication\n\nFor enterprise integrations requiring OAuth 2.1 with PKCE:\n\nOAuth Configuration Options:\n\n| Option | Type | Required | Description |\n| ------------------ | ------- | -------- | ---------------------------------------- |\n| clientId | string | Yes | OAuth client identifier |\n| clientSecret | string | No | OAuth client secret (optional with PKCE) |\n| authorizationUrl | string | Yes | Authorization endpoint URL |\n| tokenUrl | string | Yes | Token endpoint URL |\n| redirectUrl | string | Yes | OAuth callback URL |\n| scope | string | No | Space-separated OAuth scopes |\n| usePKCE | boolean | No | Enable PKCE (recommended, default: true) |\n\nAuthentication Types\n\nThe auth configuration supports three authentication types:\nOAuth 2.1 (recommended for enterprise)\nBearer Token\nAPI Key\n\nTransport Comparison\n\n| Feature | stdio | SSE | WebSocket | HTTP |\n| ------------------ | -------- | -------- | --------- | -------- |\n| Local servers | ✅ | ❌ | ❌ | ❌ |\n| Remote servers | ❌ | ✅ | ✅ | ✅ |\n| Authentication | Env vars | Headers | Headers | Headers |\n| Streaming | ✅ | ✅ | ✅ | ✅ |\n| Firewall friendly | ✅ | ✅ | ⚠️ | ✅ |\n| Session management | ❌ | ⚠️ | ⚠️ | ✅ |\n| Reconnection | ❌ | ⚠️ | ⚠️ | ✅ |\n| Specification | MCP Core | MCP Core | MCP Core | MCP 2025 |\n\nConfiguration Options\n\nRequired Fields\ntransport: Must be set to \"http\"\nurl: The HTTP endpoint URL (e.g., https://api.example.com/mcp)\ncommand: Usually same as URL for HTTP transport\n\nOptional Fields\nheaders: Object with HTTP headers for authentication and configuration\nhttpOptions: Fine-grained HTTP connection settings (see below)\nretryConfig: Automatic retry configuration with exponential backoff\nrateLimiting: Rate limiting to prevent API throttling\nauth: Authentication configuration (OAuth 2.1, Bearer, API Key)\ntimeout: Connection timeout in milliseconds (default: 10000)\nretries: Maximum retry attempts (default: 3)\nautoRestart: Whether to automatically restart on failure (default: true)\nhealthCheckInterval: Health check interval in milliseconds (default: 30000)\n\nHTTP Options Configuration\n\nFine-tune HTTP connection behavior:\n\n| Option | Type | Default | Description |\n| ------------------- | ------ | ------- | ------------------------------------ |\n| connectionTimeout | number | 30000 | Maximum time to establish connection |\n| requestTimeout | number | 60000 | Maximum time for request completion |\n| idleTimeout | number | 120000 | Time before closing idle connections |\n| keepAliveTimeout | number | 30000 | Keep-alive connection timeout |\n\nRetry Configuration\n\nAutomatic retry with exponential backoff:\n\n| Option | Type | Default | Description |\n| ------------------- | ------ | ------- | ---------------------------------- |\n| maxAttempts | number | 3 | Maximum number of retry attempts |\n| initialDelay | number | 1000 | Initial delay before first retry |\n| maxDelay | number | 30000 | Maximum delay between retries |\n| backoffMultiplier | number | 2 | Multiplier for exponential backoff |\n\nRate Limiting Configuration\n\nPrevent API throttling with token bucket rate limiting:\n\n| Option | Type | Default | Description |\n| ------------------- | ------- | ------- | ----------------------------------- |\n| requestsPerMinute | number | 60 | Maximum requests allowed per minute |\n| requestsPerHour | number | - | Maximum requests allowed per hour |\n| maxBurst | number | 10 | Maximum burst size for token bucket |\n| useTokenBucket | boolean | true | Use token bucket algorithm |\n\nExample: Complete Configuration\n\nUse Cases\nGitHub Copilot Integ","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"","lvl3":""}},
8306
+ {"objectID":"84213ad5a2888d73bad41a46ff853542912c1f9e85637e029f9766360fb6a882","title":"HTTP Transport for MCP Servers","url":"/docs/mcp/http-transport","content":"HTTP Transport for MCP Servers\n\nOverview\n\nNeuroLink now supports HTTP/Streamable HTTP transport for Model Context Protocol (MCP) servers, enabling integration with remote MCP services like GitHub Copilot MCP API and custom HTTP-based MCP endpoints.\n\nThe HTTP transport implements the MCP Streamable HTTP specification, providing:\n✅ Remote MCP server connectivity\n✅ Custom header support for authentication\n✅ Session management and automatic reconnection\n✅ Firewall and proxy compatibility\n✅ Both streaming (SSE) and batch JSON responses\n\nQuick Start\n\nGitHub Copilot Integration\n\nConfiguration File\n\nAdd to .mcp-config.json:\n\nProgrammatic Usage\n\nAuthentication\n\nHTTP transport supports custom headers for authentication:\n\nBearer Token Authentication\n\nAPI Key Authentication\n\nCustom Headers\n\nHeader values are sent exactly as written. ${VAR} references are not expanded in headers or url (a reference there would ship the variable's value to the remote host); they expand only in a server's env and args. To authenticate with a token from the environment, add the server programmatically with addExternalMCPServer() and build the header in code, or use auth: { \"type\": \"bearer\", \"token\": \"…\" } from a secrets manager. The websocket transport cannot carry headers or auth at all and fails to connect when either is configured — use http or sse.\n\nOAuth 2.1 Authentication\n\nFor enterprise integrations requiring OAuth 2.1 with PKCE:\n\nOAuth Configuration Options:\n\n| Option | Type | Required | Description |\n| ------------------ | ------- | -------- | ---------------------------------------- |\n| clientId | string | Yes | OAuth client identifier |\n| clientSecret | string | No | OAuth client secret (optional with PKCE) |\n| authorizationUrl | string | Yes | Authorization endpoint URL |\n| tokenUrl | string | Yes | Token endpoint URL |\n| redirectUrl | string | Yes | OAuth callback URL |\n| scope | string | No | Space-separated OAuth scopes |\n| usePKCE | boolean | No | Enable PKCE (recommended, default: true) |\n\nAuthentication Types\n\nThe auth configuration supports three authentication types:\nOAuth 2.1 (recommended for enterprise)\nBearer Token\nAPI Key\n\nTransport Comparison\n\n| Feature | stdio | SSE | WebSocket | HTTP |\n| ------------------ | -------- | -------- | --------- | -------- |\n| Local servers | ✅ | ❌ | ❌ | ❌ |\n| Remote servers | ❌ | ✅ | ✅ | ✅ |\n| Authentication | Env vars | Headers | ❌ (none) | Headers |\n| Streaming | ✅ | ✅ | ✅ | ✅ |\n| Firewall friendly | ✅ | ✅ | ⚠️ | ✅ |\n| Session management | ❌ | ⚠️ | ⚠️ | ✅ |\n| Reconnection | ❌ | ⚠️ | ⚠️ | ✅ |\n| Specification | MCP Core | MCP Core | MCP Core | MCP 2025 |\n\nConfiguration Options\n\nRequired Fields\ntransport: Must be set to \"http\"\nurl: The HTTP endpoint URL (e.g., https://api.example.com/mcp)\ncommand: Usually same as URL for HTTP transport\n\nOptional Fields\nheaders: Object with HTTP headers for authentication and configuration\nhttpOptions: Fine-grained HTTP connection settings (see below)\nretryConfig: Automatic retry configuration with exponential backoff\nrateLimiting: Rate limiting to prevent API throttling\nauth: Authentication configuration (OAuth 2.1, Bearer, API Key)\ntimeout: Connection timeout in milliseconds (default: 10000)\nretries: Maximum retry attempts (default: 3)\nautoRestart: Whether to automatically restart on failure (default: true)\nhealthCheckInterval: Health check interval in milliseconds (default: 30000)\n\nHTTP Options Configuration\n\nFine-tune HTTP connection behavior:\n\n| Option | Type | Default | Description |\n| ------------------- | ------ | ------- | ------------------------------------ |\n| connectionTimeout | number | 30000 | Maximum time to establish connection |\n| requestTimeout | number | 60000 | Maximum time for request completion |\n| idleTimeout | number | 120000 | Time before closing idle connections |\n| keepAliveTimeout | number | 30000 | Keep-alive connection timeout |\n\nRetry Configuration\n\nAutomatic retry with exponential backoff:\n\n| Option | Type | Default | Description |\n| ------------------- | ------ | ------- | ---------------------------------- |\n| maxAttempts | number | 3 | Maximum number of retry attempts |\n| initialDelay | number | 1000 | Initial delay before first retry |\n| maxDelay | number | 30000 | Maximum delay between retries |\n| backoffMultiplier | number | 2 | Multiplier for exponential backoff |\n\nRate Limiting Configuration\n\nPrevent API throttling with token bucket rate limitin","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"","lvl3":""}},
8290
8307
  {"objectID":"73a70d315a11430a183e2ec9e3f25537f8647bb4e7840c0bded521992537110b","title":"Overview","url":"/docs/mcp/http-transport#overview","content":"NeuroLink now supports HTTP/Streamable HTTP transport for Model Context Protocol (MCP) servers, enabling integration with remote MCP services like GitHub Copilot MCP API and custom HTTP-based MCP endpoints.\n\nThe HTTP transport implements the MCP Streamable HTTP specification, providing:\n✅ Remote MCP server connectivity\n✅ Custom header support for authentication\n✅ Session management and automatic reconnection\n✅ Firewall and proxy compatibility\n✅ Both streaming (SSE) and batch JSON responses","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Overview","lvl3":""}},
8291
8308
  {"objectID":"165fa74c6fcaa712f51204e943c7f101ad29477fd25321f7c5283b53c62b0373","title":"GitHub Copilot Integration","url":"/docs/mcp/http-transport#github-copilot-integration","content":"GitHub Copilot Integration","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"GitHub Copilot Integration","lvl3":""}},
8292
8309
  {"objectID":"51ecb5521e96f46b5a1222844ca786b897e0f464d52623bf897a9a8c26123e0f","title":"Configuration File","url":"/docs/mcp/http-transport#configuration-file","content":"Add to .mcp-config.json:","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Configuration File","lvl3":""}},
@@ -8294,10 +8311,10 @@
8294
8311
  {"objectID":"19e9b45f85dd61fde1c474f1d6ca8ed130a0373cf24696643a835ed4e712a9aa","title":"Authentication","url":"/docs/mcp/http-transport#authentication","content":"HTTP transport supports custom headers for authentication:","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Authentication","lvl3":""}},
8295
8312
  {"objectID":"f5c3e4a2a3c5f284f821a5e37310dfa02d77f9f6bb950af05616715b9127d63f","title":"Bearer Token Authentication","url":"/docs/mcp/http-transport#bearer-token-authentication","content":"Bearer Token Authentication","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Bearer Token Authentication","lvl3":""}},
8296
8313
  {"objectID":"d2f395505d6bc372bb9a1d7f54bc6584483f5a6b51174e2131fc7fd7b9f2e79c","title":"API Key Authentication","url":"/docs/mcp/http-transport#api-key-authentication","content":"API Key Authentication","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"API Key Authentication","lvl3":""}},
8297
- {"objectID":"1dbd0d01193548a372adeb10b353344e4511a887686929863019334fc7f8ab7b","title":"Custom Headers","url":"/docs/mcp/http-transport#custom-headers","content":"Custom Headers","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Custom Headers","lvl3":""}},
8314
+ {"objectID":"1dbd0d01193548a372adeb10b353344e4511a887686929863019334fc7f8ab7b","title":"Custom Headers","url":"/docs/mcp/http-transport#custom-headers","content":"Header values are sent exactly as written. ${VAR} references are not expanded in headers or url (a reference there would ship the variable's value to the remote host); they expand only in a server's env and args. To authenticate with a token from the environment, add the server programmatically with addExternalMCPServer() and build the header in code, or use auth: { \"type\": \"bearer\", \"token\": \"…\" } from a secrets manager. The websocket transport cannot carry headers or auth at all and fails to connect when either is configured — use http or sse.","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Custom Headers","lvl3":""}},
8298
8315
  {"objectID":"0796931e5e7c94b91ef50c68492dfb05101c4d4061f4dfdde167f73585132dfa","title":"OAuth 2.1 Authentication","url":"/docs/mcp/http-transport#oauth-21-authentication","content":"For enterprise integrations requiring OAuth 2.1 with PKCE:\n\nOAuth Configuration Options:\n\n| Option | Type | Required | Description |\n| ------------------ | ------- | -------- | ---------------------------------------- |\n| clientId | string | Yes | OAuth client identifier |\n| clientSecret | string | No | OAuth client secret (optional with PKCE) |\n| authorizationUrl | string | Yes | Authorization endpoint URL |\n| tokenUrl | string | Yes | Token endpoint URL |\n| redirectUrl | string | Yes | OAuth callback URL |\n| scope | string | No | Space-separated OAuth scopes |\n| usePKCE | boolean | No | Enable PKCE (recommended, default: true) |","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"OAuth 2.1 Authentication","lvl3":""}},
8299
8316
  {"objectID":"3e58d4191bac71848c310a989432b844aee1597ecf7941380eff846492a65dd1","title":"Authentication Types","url":"/docs/mcp/http-transport#authentication-types","content":"The auth configuration supports three authentication types:\nOAuth 2.1 (recommended for enterprise)\nBearer Token\nAPI Key","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Authentication Types","lvl3":""}},
8300
- {"objectID":"936eea11350ededdcd10ba0b76012bd499fa0fdbd335e41cadcf563bbd3683e2","title":"Transport Comparison","url":"/docs/mcp/http-transport#transport-comparison","content":"| Feature | stdio | SSE | WebSocket | HTTP |\n| ------------------ | -------- | -------- | --------- | -------- |\n| Local servers | ✅ | ❌ | ❌ | ❌ |\n| Remote servers | ❌ | ✅ | ✅ | ✅ |\n| Authentication | Env vars | Headers | Headers | Headers |\n| Streaming | ✅ | ✅ | ✅ | ✅ |\n| Firewall friendly | ✅ | ✅ | ⚠️ | ✅ |\n| Session management | ❌ | ⚠️ | ⚠️ | ✅ |\n| Reconnection | ❌ | ⚠️ | ⚠️ | ✅ |\n| Specification | MCP Core | MCP Core | MCP Core | MCP 2025 |","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Transport Comparison","lvl3":""}},
8317
+ {"objectID":"936eea11350ededdcd10ba0b76012bd499fa0fdbd335e41cadcf563bbd3683e2","title":"Transport Comparison","url":"/docs/mcp/http-transport#transport-comparison","content":"| Feature | stdio | SSE | WebSocket | HTTP |\n| ------------------ | -------- | -------- | --------- | -------- |\n| Local servers | ✅ | ❌ | ❌ | ❌ |\n| Remote servers | ❌ | ✅ | ✅ | ✅ |\n| Authentication | Env vars | Headers | ❌ (none) | Headers |\n| Streaming | ✅ | ✅ | ✅ | ✅ |\n| Firewall friendly | ✅ | ✅ | ⚠️ | ✅ |\n| Session management | ❌ | ⚠️ | ⚠️ | ✅ |\n| Reconnection | ❌ | ⚠️ | ⚠️ | ✅ |\n| Specification | MCP Core | MCP Core | MCP Core | MCP 2025 |","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Transport Comparison","lvl3":""}},
8301
8318
  {"objectID":"1e90749bb66b632cb05eb8de3f04338c50df84da84173ae223928285696ad19e","title":"Required Fields","url":"/docs/mcp/http-transport#required-fields","content":"transport: Must be set to \"http\"\nurl: The HTTP endpoint URL (e.g., https://api.example.com/mcp)\ncommand: Usually same as URL for HTTP transport","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Required Fields","lvl3":""}},
8302
8319
  {"objectID":"9985c6e70ff233c63e6158cafcd9429ba960e505475800c7d10100970f70ad90","title":"Optional Fields","url":"/docs/mcp/http-transport#optional-fields","content":"headers: Object with HTTP headers for authentication and configuration\nhttpOptions: Fine-grained HTTP connection settings (see below)\nretryConfig: Automatic retry configuration with exponential backoff\nrateLimiting: Rate limiting to prevent API throttling\nauth: Authentication configuration (OAuth 2.1, Bearer, API Key)\ntimeout: Connection timeout in milliseconds (default: 10000)\nretries: Maximum retry attempts (default: 3)\nautoRestart: Whether to automatically restart on failure (default: true)\nhealthCheckInterval: Health check interval in milliseconds (default: 30000)","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Optional Fields","lvl3":""}},
8303
8320
  {"objectID":"fa2d33ba610993e1b5bb1c7b130b3b6304a649c623883300af1d30cb77775b1b","title":"HTTP Options Configuration","url":"/docs/mcp/http-transport#http-options-configuration","content":"Fine-tune HTTP connection behavior:\n\n| Option | Type | Default | Description |\n| ------------------- | ------ | ------- | ------------------------------------ |\n| connectionTimeout | number | 30000 | Maximum time to establish connection |\n| requestTimeout | number | 60000 | Maximum time for request completion |\n| idleTimeout | number | 120000 | Time before closing idle connections |\n| keepAliveTimeout | number | 30000 | Keep-alive connection timeout |","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"HTTP Options Configuration","lvl3":""}},
@@ -8312,12 +8329,12 @@
8312
8329
  {"objectID":"981fff8960007b1a83ce0ac182e48c5055d6e4a56eef4277fd14e88d84240e8b","title":"Timeout Issues","url":"/docs/mcp/http-transport#timeout-issues","content":"Problem: Connection times out\n\nSolutions:\nIncrease timeout value in configuration\nCheck network connectivity\nVerify the server is running and responsive\nTest with a simple HTTP client first","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Timeout Issues","lvl3":""}},
8313
8330
  {"objectID":"6498c3d7e1959062b4a0549a78c75728f58ea95afc0ca33aaec1e5232e611b83","title":"Invalid Headers","url":"/docs/mcp/http-transport#invalid-headers","content":"Problem: Server rejects custom headers\n\nSolutions:\nCheck header names follow HTTP specification\nEnsure header values are properly formatted\nSome headers may be reserved or blocked by proxies\nTry different header names (e.g., X-API-Key instead of Api-Key)","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Invalid Headers","lvl3":""}},
8314
8331
  {"objectID":"834e1048758b90ac3d732362f318a7c7e10994aa2021f814465eb3250d38bb06","title":"Implementation","url":"/docs/mcp/http-transport#implementation","content":"HTTP transport uses the StreamableHTTPClientTransport from the @modelcontextprotocol/sdk package, which implements:\nJSON-RPC 2.0 for message protocol\nServer-Sent Events (SSE) for streaming responses\nHTTP POST for sending requests\nSession management via Mcp-Session-Id header\nAutomatic reconnection with exponential backoff","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Implementation","lvl3":""}},
8315
- {"objectID":"9f8c2485b1e6168eeb5c54987c8498918103ae18d43fa312fdd7a0f0920ab48e","title":"Security Considerations","url":"/docs/mcp/http-transport#security-considerations","content":"HTTPS Required: Always use HTTPS in production\nToken Security: Store tokens securely (environment variables, secrets management)\nHeader Sanitization: Avoid logging sensitive headers\nNetwork Security: Use VPNs or private networks for internal APIs\nRate Limiting: Implement client-side rate limiting for public APIs","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Security Considerations","lvl3":""}},
8332
+ {"objectID":"9f8c2485b1e6168eeb5c54987c8498918103ae18d43fa312fdd7a0f0920ab48e","title":"Security Considerations","url":"/docs/mcp/http-transport#security-considerations","content":"TLS is enforced: a non-loopback url must use https: (or wss:). Plaintext is accepted only for localhost, 127.0.0.0/8 and ::1.\nPrivate addresses are refused: a host that is, or resolves to, an RFC 1918, link-local (cloud metadata), CGNAT or multicast address is rejected unless that server sets \"allowPrivateNetwork\": true, which also permits plaintext to private addresses. Public hosts always need TLS.\nToken Security: Store tokens securely (environment variables, secrets management). ${VAR} is never expanded inside headers or url.\nHeader Sanitization: Avoid logging sensitive headers\nProject configs are trusted explicitly: the SDK loads .mcp-config.json only through mcp.configPath / mcp.trustProjectConfig; the CLI asks, or needs --trust-mcp-config. See MCP Integration.\nRate Limiting: Implement client-side rate limiting for public APIs","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Security Considerations","lvl3":""}},
8316
8333
  {"objectID":"0ab61437d88013b747b16a5acbffff885c0c670a544135c87db0822a503d1a4b","title":"From SSE to HTTP","url":"/docs/mcp/http-transport#from-sse-to-http","content":"If you're currently using SSE transport, migration is straightforward:\n\nBefore (SSE):\n\nAfter (HTTP):","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"From SSE to HTTP","lvl3":""}},
8317
8334
  {"objectID":"19ebb4f630ee52b89b10806243e7e76b587c1906221b730be43b12ef47292107","title":"From stdio to HTTP","url":"/docs/mcp/http-transport#from-stdio-to-http","content":"Migrating from local stdio servers to remote HTTP requires server changes:\nDeploy your MCP server as an HTTP service\nImplement authentication endpoint\nUpdate client configuration to use HTTP transport\nAdd authentication headers","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"From stdio to HTTP","lvl3":""}},
8318
8335
  {"objectID":"0eb8e8a330bba7fb5fd6188b5d9ade4b7357fe69626fd6d4db48b8ca515bd7bc","title":"Resources","url":"/docs/mcp/http-transport#resources","content":"MCP Specification - Transports\nGitHub Copilot MCP API Documentation\nNeuroLink MCP Integration Guide\nExample HTTP Transport Configurations:","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Resources","lvl3":""}},
8319
8336
  {"objectID":"0b8268811cd4fa8ff282e203734a32887cc4e0fb907292437080ee46602623c5","title":"Support","url":"/docs/mcp/http-transport#support","content":"For issues or questions:\nGitHub Issues: juspay/neurolink/issues\nDocumentation: NeuroLink Docs\nExamples: Basic Usage Examples","hierarchy":{"lvl0":"Mcp","lvl1":"HTTP Transport for MCP Servers","lvl2":"Support","lvl3":""}},
8320
- {"objectID":"276fbd370dacad8ea89d5e1e36040e179005a3ca3ff369f62e3c0ad902863861","title":"🔧 MCP (Model Context Protocol) Integration Guide","url":"/docs/mcp/integration","content":"🔧 MCP (Model Context Protocol) Integration Guide\n\nNeuroLink Universal AI Platform with External Server Connectivity\n\n📖 Overview\n\nNeuroLink now supports the Model Context Protocol (MCP) for seamless integration with external servers and tools. This enables unlimited extensibility through the growing MCP ecosystem while maintaining NeuroLink's simple interface.\n\nEnhanced MCP Integration with Factory Patterns\n\nWhat is MCP?\n\nThe Model Context Protocol is a standardized way for AI applications to connect to external tools and data sources. It enables:\n✅ External Tool Integration - Connect to filesystem, databases, APIs, and more\n✅ Standardized Communication - JSON-RPC 2.0 protocol over multiple transports\n✅ Tool Discovery - Automatic discovery of available tools and capabilities\n✅ Secure Execution - Controlled access to external resources\n✅ Ecosystem Compatibility - Works with 65+ community servers\n\n🚀 Quick Start\nInstall Popular MCP Servers\nTest Connectivity\n🆕 Programmatic Server Management\n\nNEW! Add MCP servers dynamically at runtime:\nExecute Tools (Planned)\n\nThis feature is planned for a future release.\n\n📋 MCP CLI Commands Reference\n\nServer Management\n\nInstall Popular Servers\n\nAvailable servers:\nfilesystem - File and directory operations\ngithub - GitHub repository management\npostgres - PostgreSQL database operations\nbrave-search - Web search capabilities\npuppeteer - Browser automation\n\nExample:\n\nAdd Custom Servers\n\nOptions:\n--args - Command arguments (array)\n--transport - Transport type (stdio|sse|websocket|http)\n--url - URL for SSE/WebSocket/HTTP transport\n--headers - HTTP headers for authentication (JSON)\n--env - Environment variables (JSON)\n--cwd - Working directory\n\nExamples:\n\nList Configured Servers\n\nExample output:\n\nTest Server Connectivity\n\nExample output:\n\nRemove Servers\n\n⚙️ Configuration\n\nExternal Server Configuration\n\nExternal MCP servers are configured in .mcp-config.json:\n\nEnvironment Variables\n\nSet these in your .env file for server authentication:\n\n🛠️ Available MCP Servers\n\nFilesystem Server\n\nPurpose: File and directory operations\nInstallation: neurolink mcp install filesystem\n\nAvailable Tools:\nread_file - Read file contents\nwrite_file - Create or overwrite files\nedit_file - Make line-based edits\ncreate_directory - Create directories\nlist_directory - List directory contents\ndirectory_tree - Get recursive tree view\nmove_file - Move/rename files\nsearch_files - Search for files by pattern\nget_file_info - Get file metadata\n\nGitHub Server\n\nPurpose: GitHub repository management\nInstallation: neurolink mcp install github\n\nAvailable Tools:\ncreate_repository - Create new repositories\nsearch_repositories - Search public repositories\nget_file_contents - Read repository files\ncreate_or_update_file - Modify repository files\ncreate_issue - Create GitHub issues\ncreate_pull_request - Create pull requests\nfork_repository - Fork repositories\n\nPostgreSQL Server\n\nPurpose: Database operations\nInstallation: neurolink mcp install postgres\n\nAvailable Tools:\nread-query - Execute SELECT queries\nwrite-query - Execute INSERT/UPDATE/DELETE queries\ncreate-table - Create database tables\nlist-tables - List available tables\ndescribe-table - Get table schema\n\nBrave Search Server\n\nPurpose: Web search capabilities\nInstallation: neurolink mcp install brave-search\n\nAvailable Tools:\nbrave_web_search - Search the web\nbrave_local_search - Search for local businesses\n\nPuppeteer Server\n\nPurpose: Browser automation\nInstallation: neurolink mcp install puppeteer\n\nAvailable Tools:\npuppeteer_navigate - Navigate to URLs\npuppeteer_screenshot - Take screenshots\npuppeteer_click - Click elements\npuppeteer_fill - Fill forms\npuppeteer_evaluate - Execute JavaScript\n\n🔧 Advanced Usage\n\nTransport Types\n\nSTDIO Transport (Default)\n\nBest for local servers and CLI tools:\n\nSSE Transport\n\nFor web-based servers:\n\nHTTP Transport (Streamable HTTP)\n\nFor remote MCP servers with authentication, retry, and rate limiting:\n\nConfiguration in .mcp-config.json:\n\nHTTP Transport Features:\nCustom headers for authentication (Bearer, API Key)\nConfigurable connection and request timeouts\nAutomatic retry with exponential backoff\nRate limiting with token bucket algorithm\nOAuth 2.1 support with PKCE\n\nSee MCP HTTP Transport Guide for complete documentation.\n\nServer Environment Configuration\n\nPass environment variables to servers:\n\nWorking Directory\n\nSet server working directory:\n\n🚀 Advanced MCP Features\n\nNeuroLink provides advanced MCP capabilities for production environments with multiple servers and complex tool ecosystems.\n\nTool Router\n\nIntelligent tool call routing for multi-server environments with round-robin, least-loaded, capability-based, and session affinity strategies.\n\nTool Cache\n\nCache tool results with configurable LRU, FIFO, or LFU eviction strategies, pattern-based invalidation, and cache statistics.\n\nRequest Batcher\n\nBatch multiple tool calls for efficient execution with automatic batch sizing and server-grouped batching.\n\nTool Annotations\n\nAdd safety metad","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"","lvl3":""}},
8337
+ {"objectID":"276fbd370dacad8ea89d5e1e36040e179005a3ca3ff369f62e3c0ad902863861","title":"🔧 MCP (Model Context Protocol) Integration Guide","url":"/docs/mcp/integration","content":"🔧 MCP (Model Context Protocol) Integration Guide\n\nNeuroLink Universal AI Platform with External Server Connectivity\n\n📖 Overview\n\nNeuroLink now supports the Model Context Protocol (MCP) for seamless integration with external servers and tools. This enables unlimited extensibility through the growing MCP ecosystem while maintaining NeuroLink's simple interface.\n\nEnhanced MCP Integration with Factory Patterns\n\nWhat is MCP?\n\nThe Model Context Protocol is a standardized way for AI applications to connect to external tools and data sources. It enables:\n✅ External Tool Integration - Connect to filesystem, databases, APIs, and more\n✅ Standardized Communication - JSON-RPC 2.0 protocol over multiple transports\n✅ Tool Discovery - Automatic discovery of available tools and capabilities\n✅ Secure Execution - Controlled access to external resources\n✅ Ecosystem Compatibility - Works with 65+ community servers\n\n🚀 Quick Start\nInstall Popular MCP Servers\nTest Connectivity\n🆕 Programmatic Server Management\n\nNEW! Add MCP servers dynamically at runtime:\nExecute Tools (Planned)\n\nThis feature is planned for a future release.\n\n📋 MCP CLI Commands Reference\n\nServer Management\n\nInstall Popular Servers\n\nAvailable servers:\nfilesystem - File and directory operations\ngithub - GitHub repository management\npostgres - PostgreSQL database operations\nbrave-search - Web search capabilities\npuppeteer - Browser automation\n\nExample:\n\nAdd Custom Servers\n\nOptions:\n--args - Command arguments (array)\n--transport - Transport type (stdio|sse|websocket|http)\n--url - URL for SSE/WebSocket/HTTP transport\n--headers - HTTP headers for authentication (JSON)\n--env - Environment variables (JSON)\n--cwd - Working directory\n\nExamples:\n\nList Configured Servers\n\nExample output:\n\nTest Server Connectivity\n\nExample output:\n\nRemove Servers\n\n⚙️ Configuration\n\nExternal Server Configuration\n\nExternal MCP servers are configured in .mcp-config.json:\n\nWho loads .mcp-config.json, and when\n\nA project config names commands to run and URLs to connect to, so a directory is not a trust boundary: a cloned repository's .mcp-config.json must not run its servers with your credentials just because you ran something inside it.\n\nSDK. new NeuroLink() never reads the working directory's file on its own. Name the file, or opt into the directory, in the constructor:\n\nServers added with addExternalMCPServer() / addInMemoryMCPServer() are unaffected. The legacy ProviderRegistry.setOptions({ enableManualMCP: true }) switch is now honoured too: set after construction, it re-enables the old working-directory discovery for that process.\n\nCLI. neurolink still discovers ./.mcp-config.json, but loads it only after you have trusted that exact content. The file's SHA-256 is recorded in ~/.neurolink/trusted-mcp-configs.json (0600, directory 0700); a file that changes has to be trusted again.\nIn a terminal, the first tool-enabled command shows the servers (names, commands, URLs, env key names — never values) and asks Trust this file and start these servers? [y/N].\nNon-interactively (CI, pipes), an untrusted file is refused with exit status 1 at the moment it would load, with the same summary. Decide with one of:\nneurolink generate \"…\" --trust-mcp-config or NEUROLINK_TRUST_MCP_CONFIG=1 — trust and record the hash;\nNEUROLINK_TRUST_MCP_CONFIG=0 — run without the project config;\n--disable-tools — no MCP server is needed.\nneurolink --help, --version, and any command that never initialises MCP are not affected.\n\n${VAR} references\n\n${NAME} in a server's env and args is replaced with process.env.NAME. Only names matching ^[A-Z][A-Z0-9_]*$ are expanded; anything else is left as written. ${NAME} is never expanded in headers or url — those values travel to a remote host, so a reference there would send the variable's value off the machine. A ${…} left in a header is sent literally and logged as a warning.\n\nWhat a stdio server inherits\n\nA spawned server receives the MCP SDK's minimal default environment (HOME, PATH, SHELL, TERM, USER, LOGNAME on POSIX) plus its own env. It no longer receives the whole parent process.env, so provider keys and OAuth tokens held by the host do not reach an npx -y … server unless you pass them through: \"env\": { \"OPENAI_API_KEY\": \"${OPENAI_API_KEY}\" }. A server that genuinely needs everything can set \"inheritParentEnv\": true.\n\nTransport URLs\n\nFor http, sse and websocket servers the URL must use https: / wss: unless the host is loopback (localhost, 127.0.0.0/8, ::1), and the host must not be — or resolve to — a private, link-local, CGNAT or cloud-metadata address. A server on your own network opts out per entry with \"allowPrivateNetwork\": true, which also permits plaintext http: / ws: to private addresses; public hosts always need TLS. The WebSocket transport cannot send headers or auth (the handshake carries none), so a WebSocket server configured with either fails to connect instead of connecting unauthenticated — use http or sse for authenticated servers.\n\nEnvironment Variables\n\nSet","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"","lvl3":""}},
8321
8338
  {"objectID":"75f2ab5d19e22180a60571894de6234ccf65677c1a0143ccc2bb5eeddeff9dc4","title":"🔧 MCP (Model Context Protocol) Integration Guide","url":"/docs/mcp/integration#-mcp-model-context-protocol-integration-guide","content":"NeuroLink Universal AI Platform with External Server Connectivity","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"🔧 MCP (Model Context Protocol) Integration Guide","lvl3":""}},
8322
8339
  {"objectID":"28c2227f5893d638c696fcc4eaa999f6b8d9897d60501b34fcc8879b3279db0c","title":"📖 Overview","url":"/docs/mcp/integration#-overview","content":"NeuroLink now supports the Model Context Protocol (MCP) for seamless integration with external servers and tools. This enables unlimited extensibility through the growing MCP ecosystem while maintaining NeuroLink's simple interface.","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"📖 Overview","lvl3":""}},
8323
8340
  {"objectID":"c536d621bd00c7e7c7e748e1480e1631ebd42ed876ff2a785305ae7eefb1686c","title":"Enhanced MCP Integration with Factory Patterns","url":"/docs/mcp/integration#enhanced-mcp-integration-with-factory-patterns","content":"Enhanced MCP Integration with Factory Patterns","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"Enhanced MCP Integration with Factory Patterns","lvl3":""}},
@@ -8332,7 +8349,11 @@
8332
8349
  {"objectID":"1c9d6c61b81e348c9860420cb82efd9f66d97de4d050bf4b2bc8da0c99d2d901","title":"Test Server Connectivity","url":"/docs/mcp/integration#test-server-connectivity","content":"Example output:","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"Test Server Connectivity","lvl3":""}},
8333
8350
  {"objectID":"efc21013d6c727861ddf7a6d62003457ffc17cb2001df2c5e861a74856eecea0","title":"Remove Servers","url":"/docs/mcp/integration#remove-servers","content":"Remove Servers","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"Remove Servers","lvl3":""}},
8334
8351
  {"objectID":"f1d3cb9096b4849eb8da07e391d8129e49f240243f4ab8c21e92e2aa6586ae43","title":"External Server Configuration","url":"/docs/mcp/integration#external-server-configuration","content":"External MCP servers are configured in .mcp-config.json:","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"External Server Configuration","lvl3":""}},
8335
- {"objectID":"02ca3070e051743b496cf3016eb8fd0e593ba91b53df72eff05016a7ecb1aa72","title":"Environment Variables","url":"/docs/mcp/integration#environment-variables","content":"Set these in your .env file for server authentication:","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"Environment Variables","lvl3":""}},
8352
+ {"objectID":"6f830293a15f5906932e7b87baddee6b3563923705c67e061485d15f9cedfec7","title":"Who loads .mcp-config.json, and when","url":"/docs/mcp/integration#who-loads-mcp-configjson-and-when","content":"A project config names commands to run and URLs to connect to, so a directory is not a trust boundary: a cloned repository's .mcp-config.json must not run its servers with your credentials just because you ran something inside it.\n\nSDK. new NeuroLink() never reads the working directory's file on its own. Name the file, or opt into the directory, in the constructor:\n\nServers added with addExternalMCPServer() / addInMemoryMCPServer() are unaffected. The legacy ProviderRegistry.setOptions({ enableManualMCP: true }) switch is now honoured too: set after construction, it re-enables the old working-directory discovery for that process.\n\nCLI. neurolink still discovers ./.mcp-config.json, but loads it only after you have trusted that exact content. The file's SHA-256 is recorded in ~/.neurolink/trusted-mcp-configs.json (0600, directory 0700); a file that changes has to be trusted again.\nIn a terminal, the first tool-enabled command shows the servers (names, commands, URLs, env key names — never values) and asks Trust this file and start these servers? [y/N].\nNon-interactively (CI, pipes), an untrusted file is refused with exit status 1 at the moment it would load, with the same summary. Decide with one of:\nneurolink generate \"…\" --trust-mcp-config or NEUROLINK_TRUST_MCP_CONFIG=1 — trust and record the hash;\nNEUROLINK_TRUST_MCP_CONFIG=0 — run without the project config;\n--disable-tools — no MCP server is needed.\nneurolink --help, --version, and any command that never initialises MCP are not affected.","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"Who loads .mcp-config.json, and when","lvl3":""}},
8353
+ {"objectID":"a2f6eac4268a70644c2fca9500d0233215191017fa40c23da2223f561545b71b","title":"${VAR} references","url":"/docs/mcp/integration#var-references","content":"${NAME} in a server's env and args is replaced with process.env.NAME. Only names matching ^[A-Z][A-Z0-9_]*$ are expanded; anything else is left as written. ${NAME} is never expanded in headers or url — those values travel to a remote host, so a reference there would send the variable's value off the machine. A ${…} left in a header is sent literally and logged as a warning.","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"${VAR} references","lvl3":""}},
8354
+ {"objectID":"b44daf7ba7751b27827912b3477ebb6a1a9b02f3a35fdeeadf588d8573a11a80","title":"What a stdio server inherits","url":"/docs/mcp/integration#what-a-stdio-server-inherits","content":"A spawned server receives the MCP SDK's minimal default environment (HOME, PATH, SHELL, TERM, USER, LOGNAME on POSIX) plus its own env. It no longer receives the whole parent process.env, so provider keys and OAuth tokens held by the host do not reach an npx -y … server unless you pass them through: \"env\": { \"OPENAI_API_KEY\": \"${OPENAI_API_KEY}\" }. A server that genuinely needs everything can set \"inheritParentEnv\": true.","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"What a stdio server inherits","lvl3":""}},
8355
+ {"objectID":"7514a7120a8f5f762a3afd7ae18bd7c095456b613bf525bc16767909d9cd96cc","title":"Transport URLs","url":"/docs/mcp/integration#transport-urls","content":"For http, sse and websocket servers the URL must use https: / wss: unless the host is loopback (localhost, 127.0.0.0/8, ::1), and the host must not be — or resolve to — a private, link-local, CGNAT or cloud-metadata address. A server on your own network opts out per entry with \"allowPrivateNetwork\": true, which also permits plaintext http: / ws: to private addresses; public hosts always need TLS. The WebSocket transport cannot send headers or auth (the handshake carries none), so a WebSocket server configured with either fails to connect instead of connecting unauthenticated — use http or sse for authenticated servers.","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"Transport URLs","lvl3":""}},
8356
+ {"objectID":"02ca3070e051743b496cf3016eb8fd0e593ba91b53df72eff05016a7ecb1aa72","title":"Environment Variables","url":"/docs/mcp/integration#environment-variables","content":"Set these in your .env file for server authentication (the CLI loads .env; the SDK does not — see Environment Variables):","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"Environment Variables","lvl3":""}},
8336
8357
  {"objectID":"cad70dc63bb1eac053af18efe33ebf543193cba12197a8a984acde31ac312fbe","title":"Filesystem Server","url":"/docs/mcp/integration#filesystem-server","content":"Purpose: File and directory operations\nInstallation: neurolink mcp install filesystem\n\nAvailable Tools:\nread_file - Read file contents\nwrite_file - Create or overwrite files\nedit_file - Make line-based edits\ncreate_directory - Create directories\nlist_directory - List directory contents\ndirectory_tree - Get recursive tree view\nmove_file - Move/rename files\nsearch_files - Search for files by pattern\nget_file_info - Get file metadata","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"Filesystem Server","lvl3":""}},
8337
8358
  {"objectID":"d94c75e8f3e15a3da9bc033a02e4d0183be992596954b5fa554c080146b3f36d","title":"GitHub Server","url":"/docs/mcp/integration#github-server","content":"Purpose: GitHub repository management\nInstallation: neurolink mcp install github\n\nAvailable Tools:\ncreate_repository - Create new repositories\nsearch_repositories - Search public repositories\nget_file_contents - Read repository files\ncreate_or_update_file - Modify repository files\ncreate_issue - Create GitHub issues\ncreate_pull_request - Create pull requests\nfork_repository - Fork repositories","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"GitHub Server","lvl3":""}},
8338
8359
  {"objectID":"a37d494870e626db4a8c363213b787d1b2e018e40b2317161cdffd14096188ae","title":"PostgreSQL Server","url":"/docs/mcp/integration#postgresql-server","content":"Purpose: Database operations\nInstallation: neurolink mcp install postgres\n\nAvailable Tools:\nread-query - Execute SELECT queries\nwrite-query - Execute INSERT/UPDATE/DELETE queries\ncreate-table - Create database tables\nlist-tables - List available tables\ndescribe-table - Get table schema","hierarchy":{"lvl0":"Mcp","lvl1":"🔧 MCP (Model Context Protocol) Integration Guide","lvl2":"PostgreSQL Server","lvl3":""}},
@@ -9868,21 +9889,21 @@
9868
9889
  {"objectID":"7521a69b63b695e0520c8bdda8325d29e48dd83ae908720d7f7b410883378aac","title":"Speech-to-Text (STT)","url":"/docs/reference/provider-selection#speech-to-text-stt","content":"Best accuracy: whisper (OpenAI)\n\nBest streaming: deepgram (WebSocket real-time)\n\nBest for Google Cloud users: google-stt\n\nEnterprise: azure-stt","hierarchy":{"lvl0":"Reference","lvl1":"Provider Selection Guide","lvl2":"Speech-to-Text (STT)","lvl3":""}},
9869
9890
  {"objectID":"3427711eb9150365a61d73b04412297131d3907ea8bb6702490b0a17da835969","title":"For Cost Optimization","url":"/docs/reference/provider-selection#for-cost-optimization","content":"Implement multi-provider routing - Use free/cheap providers for simple tasks, premium for complex ones.","hierarchy":{"lvl0":"Reference","lvl1":"Provider Selection Guide","lvl2":"For Cost Optimization","lvl3":""}},
9870
9891
  {"objectID":"0b16af903a7247815151028845f383f4064871833468f92ce5bb6d17dc92c895","title":"Related Resources","url":"/docs/reference/provider-selection#related-resources","content":"Provider Comparison - Detailed feature and pricing comparison\nProvider Capabilities Audit - Technical compatibility matrix\nConfiguration Reference - Environment setup for all providers\nTroubleshooting - Common issues and solutions\nMulti-Provider Fallback Cookbook - Implementation patterns\nCost Optimization Cookbook - Strategies to reduce costs\nVoice Providers Comparison - TTS, STT, and Realtime provider matrix\nVoice Providers Index - Voice provider setup cards","hierarchy":{"lvl0":"Reference","lvl1":"Provider Selection Guide","lvl2":"Related Resources","lvl3":""}},
9871
- {"objectID":"cb85ceec305e148d1d4a1107ca240b5d762fca89bbb65cf67c847a0bfa0bbbda","title":"Srvr Cofiguratio Rfrc []","url":"/docs/reference/server-configuration","content":"Server Adapter Configuration Reference\n\nThis document provides a comprehensive reference for all configuration options available in NeuroLink Server Adapters.\n\nConfiguration via CLI\n\nIn addition to programmatic configuration, NeuroLink provides CLI commands to view and manage server settings.\n\nViewing Configuration\n\nModifying Configuration\n\nConfiguration File Location\n\nCLI configuration is stored at:\nConfig file: ~/.neurolink/server-config.json\nServer state: ~/.neurolink/server-state.json\n\nCLI vs Programmatic Configuration\n\n| Aspect | CLI Config | Programmatic Config |\n| ----------- | ----------------------------- | -------------------------------- |\n| Persistence | File-based, survives restarts | In-memory, per-instance |\n| Scope | Global defaults | Per-server instance |\n| Use Case | Development, quick changes | Production, fine-grained control |\n\nRunning neurolink serve as a Service\n\nneurolink serve resolves each setting from, in order: its command-line flag, the\n--config JSON file, then the built-in default. The listen port additionally\nreads the PORT environment variable after the config file, which is what\ncontainer platforms set:\n\n| Setting | Order |\n| --------- | ----------------------------------------------------- |\n| Port | --port → config port → $PORT → 3000 |\n| Host | --host → config host → 0.0.0.0 |\n| Framework | --framework → config framework → hono |\n| Base path | --basePath → config basePath → /api |\n| CORS | --cors → config cors.enabled → enabled |\n| Rate | --rate-limit → config rateLimit.maxRequests → 100 |\n\nAPI key. Set NEUROLINK_SERVER_API_KEY to one key, or several separated by\ncommas for rotation, and every route except <basePath>/health* requires one,\nsent as Authorization: Bearer <key> or X-API-Key: <key>. Rejected requests get\n401. Without the variable the server is unauthenticated — keep it on a private\nnetwork — and the startup banner says so. neurolink server start reads the\nsame variable.\n\nContainer image. The repository's Dockerfile builds an image that runs\nneurolink serve as a non-root user, configured by environment only:\n\nUse GET /api/health/live for the liveness probe and GET /api/health/ready for\nreadiness; both stay open when an API key is set. SIGTERM drains and exits 0.\n\nThe CLI configuration provides default values that can be overridden programmatically:\n\nServerAdapterConfig\n\nThe main configuration object for server adapters.\n\nCore Options\n\n| Option | Type | Default | Description |\n| ---------------------- | --------- | ----------- | ------------------------------------------------ |\n| port | number | 3000 | Server port to listen on |\n| host | string | \"0.0.0.0\" | Server host/interface to bind |\n| basePath | string | \"/api\" | Base path prefix for all routes |\n| timeout | number | 30000 | Request timeout in milliseconds |\n| enableMetrics | boolean | true | Enable metrics endpoint |\n| enableSwagger | boolean | false | Enable OpenAPI/Swagger documentation (see below) |\n| disableBuiltInHealth | boolean | false | Disable built-in health routes |\n\nOpenAPI/Swagger Documentation (enableSwagger)\n\nWhen enableSwagger is set to true, the server exposes interactive API documentation endpoints:\n\n| Endpoint | Description |\n| ----------------------------- | ---------------------------------------- |\n| GET {basePath}/openapi.json | OpenAPI 3.1 specification in JSON format |\n| GET {basePath}/openapi.yaml | OpenAPI 3.1 specification in YAML format |\n| GET {basePath}/docs | Interactive Swagger UI documentation |\n\nExample URLs (with default basePath /api):\nhttp://localhost:3000/api/openapi.json\nhttp://localhost:3000/api/openapi.yaml\nhttp://localhost:3000/api/docs\n\nThe Swagger UI provides an interactive interface where you can:\nBrowse all available API endpoints\nView request/response schemas\nTest API calls directly from the browser\nDownload the OpenAPI specification\n\nSecurity Consideration: In production environments, consider disabling enableSwagger to prevent exposing internal API structure. Alternatively, protect the documentation endpoints with authentication middleware.\n\nExample: Basic Configuration\n\nCORS Configuration\n\n| Option | Type | Default | Description |\n| ------------- | ---------- | ------------------------------------------------------ | ---------------------------------- |\n| enabled | boolean | true ","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"","lvl3":""}},
9892
+ {"objectID":"cb85ceec305e148d1d4a1107ca240b5d762fca89bbb65cf67c847a0bfa0bbbda","title":"Srvr Cofiguratio Rfrc []","url":"/docs/reference/server-configuration","content":"Server Adapter Configuration Reference\n\nThis document provides a comprehensive reference for all configuration options available in NeuroLink Server Adapters.\n\nConfiguration via CLI\n\nIn addition to programmatic configuration, NeuroLink provides CLI commands to view and manage server settings.\n\nViewing Configuration\n\nModifying Configuration\n\nConfiguration File Location\n\nCLI configuration is stored at:\nConfig file: ~/.neurolink/server-config.json\nServer state: ~/.neurolink/server-state.json\n\nCLI vs Programmatic Configuration\n\n| Aspect | CLI Config | Programmatic Config |\n| ----------- | ----------------------------- | -------------------------------- |\n| Persistence | File-based, survives restarts | In-memory, per-instance |\n| Scope | Global defaults | Per-server instance |\n| Use Case | Development, quick changes | Production, fine-grained control |\n\nRunning neurolink serve as a Service\n\nneurolink serve resolves each setting from, in order: its command-line flag, the\n--config JSON file, then the built-in default. The listen port additionally\nreads the PORT environment variable after the config file, which is what\ncontainer platforms set:\n\n| Setting | Order |\n| --------- | ----------------------------------------------------- |\n| Port | --port → config port → $PORT → 3000 |\n| Host | --host → config host → 127.0.0.1 |\n| Framework | --framework → config framework → hono |\n| Base path | --basePath → config basePath → /api |\n| CORS | --cors → config cors.enabled → enabled |\n| Rate | --rate-limit → config rateLimit.maxRequests → 100 |\n\nLoopback by default. neurolink serve listens on 127.0.0.1 unless --host\n(or config host) names an interface. Its routes run tools, remove MCP servers\nand read conversation memory on behalf of whoever reaches the port, so a listener\nthe network can reach must be authenticated: with --host 0.0.0.0 (or any other\nnon-loopback address) and no NEUROLINK_SERVER_API_KEY, the command refuses to\nstart and exits 1. To run open on purpose — behind a reverse proxy that\nauthenticates, say — pass --allow-unauthenticated or set\nNEUROLINK_SERVER_ALLOW_UNAUTHENTICATED=1; the banner then says in so many words\nthat every route is open.\n\nAPI key. Set NEUROLINK_SERVER_API_KEY to one key, or several separated by\ncommas for rotation, and every route requires one, sent as\nAuthorization: Bearer <key> or X-API-Key: <key>, except the four probes an\norchestrator calls without credentials: <basePath>/health,\n<basePath>/health/live, <basePath>/health/ready and <basePath>/health/startup.\n<basePath>/health/detailed (runtime and MCP inventory) and <basePath>/version\nneed the key like any other route. Rejected requests get 401. neurolink server\nstart reads the same variable.\n\nBuilt-in tools. The server's registry holds none of NeuroLink's built-in\ntools (file reads and writes under the working directory among them) unless\n--enable-builtin-tools or NEUROLINK_SERVER_ENABLE_BUILTIN_TOOLS=1 is given, so\nneither POST <basePath>/tools/execute nor a model behind /agent/execute can\nreach the host's filesystem by default. MCP tools from your configuration are\nunaffected.\n\nWithout a key, tool and MCP execution answer 403. Even on loopback, a server\nwith no authentication middleware refuses POST <basePath>/tools/execute,\nPOST <basePath>/tools/:name/execute, and the MCP reconnect, remove and execute\nroutes with 403 FORBIDDEN; listing tools and servers stays open. The same\n--allow-unauthenticated / NEUROLINK_SERVER_ALLOW_UNAUTHENTICATED=1 lifts it.\n\nContainer image. The repository's Dockerfile builds an image that runs\nneurolink serve --host 0.0.0.0 as a non-root user, configured by environment\nonly. The container must therefore be given NEUROLINK_SERVER_API_KEY (or\nNEUROLINK_SERVER_ALLOW_UNAUTHENTICATED=1), or it exits at start:\n\nUse GET /api/health/live for the liveness probe and GET /api/health/ready for\nreadiness; both stay open when an API key is set. SIGTERM drains and exits 0.\n\nTranscription WebSocket. /v1/audio/transcriptions/stream takes the same key,\nas Authorization: Bearer <key> or, from a browser, as the subprotocol\nneurolink-api-key.<key> offered next to neurolink. The key in the URL\n(?token=) is refused unless NEUROLINK_SERVER_WS_ALLOW_QUERY_TOKEN=1, because a\nURL is written to access logs and Referer headers. Sockets are capped (100 in\nall, 16 per address; a further upgrade is answered 503), and mode: \"file\" on a\nnon-loopback listener needs the key. See\n/docs/features/transcribe for the protocol.\n\nThe CLI configuration provides default values that can be overridden programmatically:\n\nServerAdapterConfig\n\nThe main configuration object for server adapters.\n\nCore Options\n\n| Option | Type | Default | Description ","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"","lvl3":""}},
9872
9893
  {"objectID":"d187276d2e01714a0fd53862da97600cad53354c8e420712cda9f3af1effef79","title":"Server Adapter Configuration Reference","url":"/docs/reference/server-configuration#server-adapter-configuration-reference","content":"This document provides a comprehensive reference for all configuration options available in NeuroLink Server Adapters.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Server Adapter Configuration Reference","lvl3":""}},
9873
9894
  {"objectID":"a1610833698011b8e9f9392407beea37119d8df2cc628412a1d8ffa1c536e834","title":"Configuration via CLI","url":"/docs/reference/server-configuration#configuration-via-cli","content":"In addition to programmatic configuration, NeuroLink provides CLI commands to view and manage server settings.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Configuration via CLI","lvl3":""}},
9874
9895
  {"objectID":"1159a0fdaab76d1050b04e8f660c9b39fa4d6720261cf7a826a599293e07cb5e","title":"Viewing Configuration","url":"/docs/reference/server-configuration#viewing-configuration","content":"Viewing Configuration","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Viewing Configuration","lvl3":""}},
9875
9896
  {"objectID":"ea7d214421fbf9c3e113afbd3edcf09bc9ced22054dfdfbb2020bf8067184f2a","title":"Modifying Configuration","url":"/docs/reference/server-configuration#modifying-configuration","content":"Modifying Configuration","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Modifying Configuration","lvl3":""}},
9876
9897
  {"objectID":"0cd357f5a33e7cf878b93cbcf9aad870da227f44c99c28f4e648fdc9e6a7b360","title":"Configuration File Location","url":"/docs/reference/server-configuration#configuration-file-location","content":"CLI configuration is stored at:\nConfig file: ~/.neurolink/server-config.json\nServer state: ~/.neurolink/server-state.json","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Configuration File Location","lvl3":""}},
9877
9898
  {"objectID":"d2db092f2ae3972d7bb142238c67230664b2939eb4fa36af9d38bba749ebc5cd","title":"CLI vs Programmatic Configuration","url":"/docs/reference/server-configuration#cli-vs-programmatic-configuration","content":"| Aspect | CLI Config | Programmatic Config |\n| ----------- | ----------------------------- | -------------------------------- |\n| Persistence | File-based, survives restarts | In-memory, per-instance |\n| Scope | Global defaults | Per-server instance |\n| Use Case | Development, quick changes | Production, fine-grained control |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"CLI vs Programmatic Configuration","lvl3":""}},
9878
- {"objectID":"7879b0a9ef2756d71baef46931796ce4a195665c14dcdede04d3aedbbda30307","title":"Running neurolink serve as a Service","url":"/docs/reference/server-configuration#running-neurolink-serve-as-a-service","content":"neurolink serve resolves each setting from, in order: its command-line flag, the\n--config JSON file, then the built-in default. The listen port additionally\nreads the PORT environment variable after the config file, which is what\ncontainer platforms set:\n\n| Setting | Order |\n| --------- | ----------------------------------------------------- |\n| Port | --port → config port → $PORT → 3000 |\n| Host | --host → config host → 0.0.0.0 |\n| Framework | --framework → config framework → hono |\n| Base path | --basePath → config basePath → /api |\n| CORS | --cors → config cors.enabled → enabled |\n| Rate | --rate-limit → config rateLimit.maxRequests → 100 |\n\nAPI key. Set NEUROLINK_SERVER_API_KEY to one key, or several separated by\ncommas for rotation, and every route except <basePath>/health* requires one,\nsent as Authorization: Bearer <key> or X-API-Key: <key>. Rejected requests get\n401. Without the variable the server is unauthenticated — keep it on a private\nnetwork — and the startup banner says so. neurolink server start reads the\nsame variable.\n\nContainer image. The repository's Dockerfile builds an image that runs\nneurolink serve as a non-root user, configured by environment only:\n\nUse GET /api/health/live for the liveness probe and GET /api/health/ready for\nreadiness; both stay open when an API key is set. SIGTERM drains and exits 0.\n\nThe CLI configuration provides default values that can be overridden programmatically:","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Running neurolink serve as a Service","lvl3":""}},
9899
+ {"objectID":"7879b0a9ef2756d71baef46931796ce4a195665c14dcdede04d3aedbbda30307","title":"Running neurolink serve as a Service","url":"/docs/reference/server-configuration#running-neurolink-serve-as-a-service","content":"neurolink serve resolves each setting from, in order: its command-line flag, the\n--config JSON file, then the built-in default. The listen port additionally\nreads the PORT environment variable after the config file, which is what\ncontainer platforms set:\n\n| Setting | Order |\n| --------- | ----------------------------------------------------- |\n| Port | --port → config port → $PORT → 3000 |\n| Host | --host → config host → 127.0.0.1 |\n| Framework | --framework → config framework → hono |\n| Base path | --basePath → config basePath → /api |\n| CORS | --cors → config cors.enabled → enabled |\n| Rate | --rate-limit → config rateLimit.maxRequests → 100 |\n\nLoopback by default. neurolink serve listens on 127.0.0.1 unless --host\n(or config host) names an interface. Its routes run tools, remove MCP servers\nand read conversation memory on behalf of whoever reaches the port, so a listener\nthe network can reach must be authenticated: with --host 0.0.0.0 (or any other\nnon-loopback address) and no NEUROLINK_SERVER_API_KEY, the command refuses to\nstart and exits 1. To run open on purpose — behind a reverse proxy that\nauthenticates, say — pass --allow-unauthenticated or set\nNEUROLINK_SERVER_ALLOW_UNAUTHENTICATED=1; the banner then says in so many words\nthat every route is open.\n\nAPI key. Set NEUROLINK_SERVER_API_KEY to one key, or several separated by\ncommas for rotation, and every route requires one, sent as\nAuthorization: Bearer <key> or X-API-Key: <key>, except the four probes an\norchestrator calls without credentials: <basePath>/health,\n<basePath>/health/live, <basePath>/health/ready and <basePath>/health/startup.\n<basePath>/health/detailed (runtime and MCP inventory) and <basePath>/version\nneed the key like any other route. Rejected requests get 401. neurolink server\nstart reads the same variable.\n\nBuilt-in tools.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Running neurolink serve as a Service","lvl3":""}},
9879
9900
  {"objectID":"ebf0e8b83f1c274852b8367930f04784c3499eb3af2bf086dc5c01462975c0c2","title":"ServerAdapterConfig","url":"/docs/reference/server-configuration#serveradapterconfig","content":"The main configuration object for server adapters.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"ServerAdapterConfig","lvl3":""}},
9880
- {"objectID":"677188568d1a1f62404df0b7a4c3655f9e19f645c9918030d046d433a6429339","title":"Core Options","url":"/docs/reference/server-configuration#core-options","content":"| Option | Type | Default | Description |\n| ---------------------- | --------- | ----------- | ------------------------------------------------ |\n| port | number | 3000 | Server port to listen on |\n| host | string | \"0.0.0.0\" | Server host/interface to bind |\n| basePath | string | \"/api\" | Base path prefix for all routes |\n| timeout | number | 30000 | Request timeout in milliseconds |\n| enableMetrics | boolean | true | Enable metrics endpoint |\n| enableSwagger | boolean | false | Enable OpenAPI/Swagger documentation (see below) |\n| disableBuiltInHealth | boolean | false | Disable built-in health routes |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Core Options","lvl3":""}},
9901
+ {"objectID":"677188568d1a1f62404df0b7a4c3655f9e19f645c9918030d046d433a6429339","title":"Core Options","url":"/docs/reference/server-configuration#core-options","content":"| Option | Type | Default | Description |\n| ---------------------- | --------- | ------------- | --------------------------------------------------------------------------------------------------------------- |\n| port | number | 3000 | Server port to listen on |\n| host | string | \"127.0.0.1\" | Interface to bind; loopback by default. \"0.0.0.0\" listens on every interface — register authentication first |\n| basePath | string | \"/api\" | Base path prefix for all routes |\n| timeout | number | 30000 | Per-request timeout, on every adapter: a request past it is answered 504 REQUEST_TIMEOUT and its work aborted |\n| enableMetrics | boolean | true | Enable metrics endpoint |\n| enableSwagger | boolean | false | Enable OpenAPI/Swagger documentation (see below) |\n| disableBuiltInHealth | boolean | false | Disable built-in health routes |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Core Options","lvl3":""}},
9881
9902
  {"objectID":"679f1af42104e68e108d5e6009e16718cab67c8d2f3712b45dc516ba333b9c27","title":"OpenAPI/Swagger Documentation (enableSwagger)","url":"/docs/reference/server-configuration#openapiswagger-documentation-enableswagger","content":"When enableSwagger is set to true, the server exposes interactive API documentation endpoints:\n\n| Endpoint | Description |\n| ----------------------------- | ---------------------------------------- |\n| GET {basePath}/openapi.json | OpenAPI 3.1 specification in JSON format |\n| GET {basePath}/openapi.yaml | OpenAPI 3.1 specification in YAML format |\n| GET {basePath}/docs | Interactive Swagger UI documentation |\n\nExample URLs (with default basePath /api):\nhttp://localhost:3000/api/openapi.json\nhttp://localhost:3000/api/openapi.yaml\nhttp://localhost:3000/api/docs\n\nThe Swagger UI provides an interactive interface where you can:\nBrowse all available API endpoints\nView request/response schemas\nTest API calls directly from the browser\nDownload the OpenAPI specification\n\nSecurity Consideration: In production environments, consider disabling enableSwagger to prevent exposing internal API structure. Alternatively, protect the documentation endpoints with authentication middleware.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"OpenAPI/Swagger Documentation (enableSwagger)","lvl3":""}},
9882
9903
  {"objectID":"4521fc87cb580735f24e75ac3b75c56ddf87507e23597fbd438cb953ec71544a","title":"Example: Basic Configuration","url":"/docs/reference/server-configuration#example-basic-configuration","content":"Example: Basic Configuration","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Example: Basic Configuration","lvl3":""}},
9883
- {"objectID":"a70d025b0c2289499401bc2bc4e8071a199c148ac4483d5a3e646d713509c2ef","title":"CORS Configuration","url":"/docs/reference/server-configuration#cors-configuration","content":"| Option | Type | Default | Description |\n| ------------- | ---------- | ------------------------------------------------------ | ---------------------------------- |\n| enabled | boolean | true | Enable CORS support |\n| origins | string[] | [] | Allowed origins ([\"*\"] = any) |\n| methods | string[] | [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"] | Allowed HTTP methods |\n| headers | string[] | [\"Content-Type\", \"Authorization\"] | Allowed headers |\n| credentials | boolean | false | Allow credentials |\n| maxAge | number | 86400 | Preflight cache max age in seconds |\n\nSecurity note: With no origins listed, no web page can call the server cross-origin. List the origins you serve pages from, or set [\"*\"] explicitly to allow any domain (then also set an API key). neurolink serve --cors-origin https://myapp.com does the same from the command line.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"CORS Configuration","lvl3":""}},
9904
+ {"objectID":"a70d025b0c2289499401bc2bc4e8071a199c148ac4483d5a3e646d713509c2ef","title":"CORS Configuration","url":"/docs/reference/server-configuration#cors-configuration","content":"| Option | Type | Default | Description |\n| ------------- | ---------- | ------------------------------------------------------ | ---------------------------------- |\n| enabled | boolean | true | Enable CORS support |\n| origins | string[] | [] | Allowed origins ([\"*\"] = any) |\n| methods | string[] | [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"] | Allowed HTTP methods |\n| headers | string[] | [\"Content-Type\", \"Authorization\"] | Allowed headers |\n| credentials | boolean | false | Allow credentials |\n| maxAge | number | 86400 | Preflight cache max age in seconds |\n\nSecurity note: With no origins listed, no web page can call the server cross-origin. List the origins you serve pages from, or set [\"*\"] explicitly to allow any domain (then also set an API key). neurolink serve --cors-origin https://myapp.com does the same from the command line. The wildcard is sent as the literal * on every adapter (never the request's own Origin), and [\"*\"] together with credentials: true is refused when the server is created: a browser will not send credentials to a wildcard, and reflecting the origin to make it do so would let any page act as the user.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"CORS Configuration","lvl3":""}},
9884
9905
  {"objectID":"708cea96fded6a3d6b4ae7e87e0edd070731d631cb4d87c2684792a82addbb0c","title":"Example: Restrictive CORS","url":"/docs/reference/server-configuration#example-restrictive-cors","content":"Example: Restrictive CORS","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Example: Restrictive CORS","lvl3":""}},
9885
- {"objectID":"3706f16eed022d7b144945eae7c4e22925c2d8aa62896bbc81097cab7b4875e2","title":"Rate Limit Configuration","url":"/docs/reference/server-configuration#rate-limit-configuration","content":"| Option | Type | Default | Description |\n| -------------- | ---------- | ------------------------ | ------------------------------------------ |\n| enabled | boolean | true | Enable rate limiting |\n| windowMs | number | 900000 (15 min) | Time window in milliseconds |\n| maxRequests | number | 100 | Maximum requests per window |\n| message | string | \"Too many requests...\" | Error message when limit exceeded |\n| skipPaths | string[] | [] | Paths to exclude from rate limiting |\n| keyGenerator | function | IP-based | Custom function to generate rate limit key |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Rate Limit Configuration","lvl3":""}},
9906
+ {"objectID":"3706f16eed022d7b144945eae7c4e22925c2d8aa62896bbc81097cab7b4875e2","title":"Rate Limit Configuration","url":"/docs/reference/server-configuration#rate-limit-configuration","content":"| Option | Type | Default | Description |\n| ---------------- | ---------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| enabled | boolean | true | Enable rate limiting |\n| windowMs | number | 900000 (15 min) | Time window in milliseconds |\n| maxRequests | number | 100 | Maximum requests per window |\n| message | string | \"Too many requests...\"","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Rate Limit Configuration","lvl3":""}},
9886
9907
  {"objectID":"06f1efd322182e016ace893db5f7332ce70ca77362234b7d38a3fc3d924264b4","title":"Example: Custom Rate Limiting","url":"/docs/reference/server-configuration#example-custom-rate-limiting","content":"Example: Custom Rate Limiting","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Example: Custom Rate Limiting","lvl3":""}},
9887
9908
  {"objectID":"7787f42e969a27e990c15b1b673f04d01ad837b5f49d95006f73e61b417d91a0","title":"Body Parser Configuration","url":"/docs/reference/server-configuration#body-parser-configuration","content":"| Option | Type | Default | Description |\n| ------------ | --------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------- |\n| enabled | boolean | true | Enable body parsing |\n| maxSize | string | \"10mb\" | Maximum body size |\n| jsonLimit | string | \"10mb\" | JSON body size limit |\n| rawMaxSize | string | maxSize, else \"64mb\" | Largest raw upload (multipart/form-data, audio/*, application/octet-stream); neurolink serve --max-upload 128mb |\n| urlEncoded | boolean | true | Enable URL-encoded body parsing |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Body Parser Configuration","lvl3":""}},
9888
9909
  {"objectID":"8317d296207f703efb98d9a5476bc3fd34494aecdcada845f71f6fc775fbd343","title":"Example: Large Payload Support","url":"/docs/reference/server-configuration#example-large-payload-support","content":"Example: Large Payload Support","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Example: Large Payload Support","lvl3":""}},
@@ -9906,13 +9927,14 @@
9906
9927
  {"objectID":"d1336be8e4e01c12e9095b4cd7c96d0e899342d5eea652c007b88ff853c31b54","title":"Fastify","url":"/docs/reference/server-configuration#fastify","content":"For more details, see the Fastify Guide.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Fastify","lvl3":""}},
9907
9928
  {"objectID":"ed0fedb955902f2a425a4e21b395bf40913d52fabf7e9773f390402dbbc1172e","title":"Koa","url":"/docs/reference/server-configuration#koa","content":"For more details, see the Koa Guide.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Koa","lvl3":""}},
9908
9929
  {"objectID":"1bd94206973b2f01043042f02fa34af8d69fd36e0114648f242f77fa584c28c5","title":"Complete Configuration Example","url":"/docs/reference/server-configuration#complete-configuration-example","content":"Complete Configuration Example","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Complete Configuration Example","lvl3":""}},
9909
- {"objectID":"e6ef56bd8788b4b1f2e8540c568dd8caa7076a5fb6aeffed2f0f8a2f1a0cffb2","title":"Environment Variables","url":"/docs/reference/server-configuration#environment-variables","content":"The server adapters respect these environment variables:\n\n| Variable | Description | Default |\n| --------------------- | ------------------------------------- | ------------- |\n| PORT | Server port | 3000 |\n| HOST | Server host | 0.0.0.0 |\n| NODE_ENV | Environment mode | development |\n| npm_package_version | Package version (for health endpoint) | unknown |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Environment Variables","lvl3":""}},
9930
+ {"objectID":"e6ef56bd8788b4b1f2e8540c568dd8caa7076a5fb6aeffed2f0f8a2f1a0cffb2","title":"Environment Variables","url":"/docs/reference/server-configuration#environment-variables","content":"The server adapters respect these environment variables:\n\n| Variable | Description | Default |\n| ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |\n| PORT | Server port (neurolink serve) | 3000 |\n| NEUROLINK_SERVER_API_KEY | Comma-separated API keys; every route except the health probes needs one | unset |\n| NEUROLINK_SERVER_ALLOW_UNAUTHENTICATED | 1 lets neurolink serve bind a non-loopback host with no key, and serves the tool and MCP execution routes to unauthenticated callers (SDK too) | unset |\n| NEUROLINK_SERVER_ENABLE_BUILTIN_TOOLS | 1 keeps NeuroLink's built-in tools (filesystem among them) in neurolink serve's registry | unset |\n| NEUROLINK_SERVER_WS_ALLOW_QUERY_TOKEN | 1 lets the transcription WebSocket take the API key as ?token= | unset |\n| NEUROLINK_SERVER_TIMEOUT_MS | Per-request timeout for neurolink serve (the config file's timeout wins) | 30000 |\n| NEUROLINK_STT_EVAL_ENABLED | 1 mounts the STT evaluation collector (/v1/evals/stt), which is off by default | unset |\n| NODE_ENV | Environment mode","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Environment Variables","lvl3":""}},
9910
9931
  {"objectID":"2c3673d1b30327079ca551ff42da03e7142fc9644b9cf97e534a268be6470751","title":"Configuration Validation","url":"/docs/reference/server-configuration#configuration-validation","content":"Invalid configuration will throw errors at initialization:\n\nAlways validate your configuration in development before deploying to production.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Configuration Validation","lvl3":""}},
9911
9932
  {"objectID":"5e2e75ae58d111804af59361b2bfbadbb372c5d61c640498576bd2ea870aa922","title":"API Endpoints","url":"/docs/reference/server-configuration#api-endpoints","content":"The server adapters expose the following endpoints (all prefixed with basePath, default /api):","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"API Endpoints","lvl3":""}},
9912
9933
  {"objectID":"058b0d65053e90409a9fb95b4a7f33a46c90b2281f9f23bec2e616cf25c2c8e3","title":"Health Endpoints","url":"/docs/reference/server-configuration#health-endpoints","content":"| Method | Endpoint | Description |\n| ------ | ---------- | ------------------- |\n| GET | /health | Basic health check |\n| GET | /ready | Readiness probe |\n| GET | /live | Liveness probe |\n| GET | /version | Version information |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Health Endpoints","lvl3":""}},
9913
9934
  {"objectID":"a729ac442aae6a2921608402e3611ab5e40e5509b58d14a65dbd9dc75694c715","title":"Agent Endpoints","url":"/docs/reference/server-configuration#agent-endpoints","content":"| Method | Endpoint | Description |\n| ------ | ---------------- | ------------------------ |\n| POST | /agent/execute | Execute agent with input |\n| POST | /agent/stream | Stream agent response |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Agent Endpoints","lvl3":""}},
9914
- {"objectID":"1da101ce6be59ea621ea1fd153a744a4ccd6b9b0fd43cc5131ce046b3e921c21","title":"Tool Endpoints","url":"/docs/reference/server-configuration#tool-endpoints","content":"| Method | Endpoint | Description |\n| ------ | -------------- | ----------------------- |\n| GET | /tools | List available tools |\n| POST | /tools/:name | Execute a specific tool |\n| GET | /tools/:name | Get tool metadata |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Tool Endpoints","lvl3":""}},
9915
- {"objectID":"f5104e97ba804ea037bb1aefbcee375dd9e91b06585716e312910a0559d1fa16","title":"MCP Endpoints","url":"/docs/reference/server-configuration#mcp-endpoints","content":"| Method | Endpoint | Description |\n| ------ | -------------- | -------------------------- |\n| GET | /mcp/servers | List MCP servers |\n| POST | /mcp/execute | Execute MCP tool |\n| GET | /mcp/health | MCP subsystem health check |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"MCP Endpoints","lvl3":""}},
9935
+ {"objectID":"1da101ce6be59ea621ea1fd153a744a4ccd6b9b0fd43cc5131ce046b3e921c21","title":"Tool Endpoints","url":"/docs/reference/server-configuration#tool-endpoints","content":"| Method | Endpoint | Description |\n| ------ | ---------------------- | -------------------------------------------- |\n| GET | /tools | List available tools |\n| GET | /tools/search | Search tools by name or description |\n| POST | /tools/execute | Execute a tool named in the body (see below) |\n| POST | /tools/:name/execute | Execute a specific tool (see below) |\n| GET | /tools/:name | Get tool metadata |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Tool Endpoints","lvl3":""}},
9936
+ {"objectID":"f5104e97ba804ea037bb1aefbcee375dd9e91b06585716e312910a0559d1fa16","title":"MCP Endpoints","url":"/docs/reference/server-configuration#mcp-endpoints","content":"| Method | Endpoint | Description |\n| ------ | -------------------------------------------- | --------------------------------- |\n| GET | /mcp/servers | List MCP servers |\n| GET | /mcp/servers/:name | One server's status |\n| POST | /mcp/servers/:name/reconnect | Reconnect a server (see below) |\n| DELETE | /mcp/servers/:name | Remove a server (see below) |\n| GET | /mcp/servers/:name/tools | One server's tools |\n| POST | /mcp/servers/:name/tools/:toolName/execute | Execute one server's tool (below) |\n| GET | /mcp/health | MCP subsystem health check |\n\nExecution routes refuse an unauthenticated server. The routes marked \"see\nbelow\" act on the host. When the server has no middleware marked\nauthenticates: true (the built-in createAuthMiddleware,\ncreateBearerAuthMiddleware and the CLI's API-key middleware mark themselves),\nthey answer 403 FORBIDDEN on every request. registerAllRoutes() wires the\ncheck; createAllRoutes() applies it only when given hasAuthentication. Opt\nout with registerAllRoutes(server, \"/api\", { allowUnauthenticated: true }) or\nNEUROLINK_SERVER_ALLOW_UNAUTHENTICATED=1, or leave the tool routes out\naltogether with { tools: false }. Set authenticates: true on your own\nauthentication middleware so the routes recognise it.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"MCP Endpoints","lvl3":""}},
9937
+ {"objectID":"70113d407c6503754f0e3695933621d958664518b0d02fda4c64ff680e8a57f2","title":"Error responses","url":"/docs/reference/server-configuration#error-responses","content":"A failed request answers with a fixed message for its category and the request\nid, never the exception's text, which stays in the server log under that id:\n\n| Code | Status | When |\n| ------------------------- | ------ | ---------------------------------------------------------- |\n| VALIDATION_ERROR etc. | 4xx | A message this server composed about the request |\n| PROVIDER_NOT_CONFIGURED | 503 | A provider refused the server's credentials or has none |\n| UPSTREAM_RATE_LIMITED | 503 | A provider is rate limiting the server |\n| REQUEST_TIMEOUT | 504 | The request ran past timeout; its generation was aborted |\n| INTERNAL_ERROR | 500 | Anything else |\n\nSSE error events on /agent/stream carry the same code, message and\nrequestId.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Error responses","lvl3":""}},
9916
9938
  {"objectID":"59df95a6c22094185142a56ac760329296dfc9b7da69008274f4793ae71e4f81","title":"Memory Endpoints","url":"/docs/reference/server-configuration#memory-endpoints","content":"| Method | Endpoint | Description |\n| ------ | ---------------------- | ----------------------------- |\n| GET | /memory/sessions | List memory sessions |\n| GET | /memory/sessions/:id | Get session details |\n| DELETE | /memory/sessions/:id | Delete a session |\n| DELETE | /memory/sessions | Clear all sessions |\n| GET | /memory/health | Memory subsystem health check |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Memory Endpoints","lvl3":""}},
9917
9939
  {"objectID":"718cd66a21c0c346acec1061a2dfff7d330e83f9c1826bd1fef67ec672e9e726","title":"OpenAPI Endpoints (when enableSwagger: true)","url":"/docs/reference/server-configuration#openapi-endpoints-when-enableswagger-true","content":"| Method | Endpoint | Description |\n| ------ | --------------- | ----------------------- |\n| GET | /openapi.json | OpenAPI 3.1 spec (JSON) |\n| GET | /openapi.yaml | OpenAPI 3.1 spec (YAML) |\n| GET | /docs | Swagger UI |","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"OpenAPI Endpoints (when enableSwagger: true)","lvl3":""}},
9918
9940
  {"objectID":"94803bb1b1e623b1ae33fdafcd43cc8bb41403c0fb042f7859360f39a924bbde","title":"Lifecycle Management","url":"/docs/reference/server-configuration#lifecycle-management","content":"Server adapters implement a comprehensive lifecycle management system that enables graceful startup, connection tracking, and orderly shutdown. Understanding the lifecycle is essential for production deployments.","hierarchy":{"lvl0":"Reference","lvl1":"Srvr Cofiguratio Rfrc []","lvl2":"Lifecycle Management","lvl3":""}},