@juspay/neurolink 13.4.5 → 13.4.6

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.
package/CHANGELOG.md CHANGED
@@ -1,8 +1,8 @@
1
- ## [13.4.5](https://github.com/juspay/neurolink/compare/v13.4.4...v13.4.5) (2026-10-18)
1
+ ## [13.4.6](https://github.com/juspay/neurolink/compare/v13.4.5...v13.4.6) (2026-10-18)
2
2
 
3
3
  ### Bug Fixes
4
4
 
5
- - **(xor):** send decisions to /v1/decisions with the xor-latest and xor-omni models ([5ef74c4](https://github.com/juspay/neurolink/commit/5ef74c42a8e6422641ff39743b65061c5c5c1385))
5
+ - **(voice):** refuse a cleartext xAI realtime URL to another host unless opted in ([b58347d](https://github.com/juspay/neurolink/commit/b58347d9a6df84cd979a78d8b5676169f10c4e8c))
6
6
 
7
7
  ## [11.2.3](https://github.com/juspay/neurolink/compare/v11.2.2...v11.2.3) (2026-08-19)
8
8
 
@@ -502,7 +502,7 @@ export type RealtimeVoiceAgentConfig = {
502
502
  location?: string;
503
503
  model?: string;
504
504
  voice?: string;
505
- /** xai only: WebSocket base URL of the realtime endpoint. */
505
+ /** xai only: WebSocket base URL of the realtime endpoint. A `ws://` URL to a host other than localhost, 127.0.0.0/8 or [::1] is refused unless `XAI_REALTIME_ALLOW_INSECURE=true`, because the xAI key would cross the network unencrypted. */
506
506
  xaiBaseURL?: string;
507
507
  responseModality?: string;
508
508
  systemPrompt?: string;
@@ -23,6 +23,15 @@ export declare function resolveLiveKitServerConfig(): LiveKitServerConfig;
23
23
  * `VOICE_LLM_MODEL`.
24
24
  */
25
25
  export declare function resolveBrainDefaults(): LiveKitBrainDefaults;
26
+ /**
27
+ * Refuse a `ws://` URL to a host other than loopback unless
28
+ * `XAI_REALTIME_ALLOW_INSECURE=true`: the xAI plugin sends `XAI_API_KEY` to the
29
+ * URL it is given, and `ws://` sends it unencrypted. Anything else passes,
30
+ * including a value that is not a ws or wss URL, which is for the caller's own
31
+ * check. The error names the setting and the opt-in and does not repeat the
32
+ * value.
33
+ */
34
+ export declare function requireNoCleartextCrossHost(value: string, name: string): void;
26
35
  /**
27
36
  * Resolve the realtime (speech-to-speech) voice configuration from the
28
37
  * environment.
@@ -31,7 +40,10 @@ export declare function resolveBrainDefaults(): LiveKitBrainDefaults;
31
40
  * env at all. `VOICE_REALTIME_BACKEND` picks the model family (`gemini`, the
32
41
  * default, or `xai`); `backend` here overrides it and then the environment's
33
42
  * value is not read. A non-blank `xaiBaseURL` here likewise replaces
34
- * `XAI_REALTIME_BASE_URL` after the same ws or wss check.
43
+ * `XAI_REALTIME_BASE_URL` after the same ws or wss check. Either URL is
44
+ * checked whatever the backend. A `ws://` URL to a host other than `localhost`,
45
+ * `127.0.0.0/8` or `[::1]` is refused unless `XAI_REALTIME_ALLOW_INSECURE=true`,
46
+ * because the xAI plugin sends `XAI_API_KEY` to it unencrypted.
35
47
  * `VOICE_LIVE_MODEL` overrides the backend's default model.
36
48
  * Vertex `project` is resolved from `VERTEX_PROJECT`, then the service-account
37
49
  * project (`GOOGLE_AUTH_BREEZE_PROJECT_ID`), then `GOOGLE_CLOUD_PROJECT_ID`;
@@ -77,6 +77,7 @@ const DEFAULT_SYSTEM_PROMPT = "You are a concise voice assistant for a merchant
77
77
  const DEFAULT_GREETING = "Briefly greet the merchant and ask how you can help with their store today.";
78
78
  const DEFAULT_LIGHTHOUSE_URL = "http://localhost:5173";
79
79
  const DEFAULT_MCP_PATH = "/ai/mcp/v2";
80
+ const ALLOW_INSECURE_ENV = "XAI_REALTIME_ALLOW_INSECURE";
80
81
  /**
81
82
  * The backend named by `VOICE_REALTIME_BACKEND`: `gemini` or `xai`, matched
82
83
  * case-insensitively, with blank or absent meaning `gemini`. The error names the
@@ -100,20 +101,53 @@ function requireKnownBackend(value) {
100
101
  }
101
102
  throw new Error('The realtime voice backend must be "gemini" or "xai"');
102
103
  }
103
- function isWebSocketUrl(value) {
104
+ function parseWebSocketUrl(value) {
104
105
  try {
105
- const { protocol } = new URL(value);
106
- return protocol === "ws:" || protocol === "wss:";
106
+ const url = new URL(value);
107
+ return url.protocol === "ws:" || url.protocol === "wss:" ? url : undefined;
107
108
  }
108
109
  catch {
109
- return false;
110
+ return undefined;
110
111
  }
111
112
  }
112
- /** A ws or wss URL. The error names the setting and does not repeat the value. */
113
+ /**
114
+ * Whether a WHATWG-parsed hostname is `localhost`, an address in `127.0.0.0/8`
115
+ * or `[::1]`. The parser has already lowercased the name and reduced shorthand
116
+ * IPv4 forms (`127.1`, `0x7f.1`) to dotted decimal, and a userinfo prefix such
117
+ * as `localhost@host` never reaches `hostname`, so neither can pass for a
118
+ * loopback host.
119
+ */
120
+ function isLoopbackHost(hostname) {
121
+ if (hostname === "localhost" || hostname === "[::1]") {
122
+ return true;
123
+ }
124
+ const octets = hostname.split(".");
125
+ return (octets.length === 4 &&
126
+ octets[0] === "127" &&
127
+ octets.every((octet) => /^\d{1,3}$/.test(octet) && Number(octet) <= 255));
128
+ }
129
+ /**
130
+ * Refuse a `ws://` URL to a host other than loopback unless
131
+ * `XAI_REALTIME_ALLOW_INSECURE=true`: the xAI plugin sends `XAI_API_KEY` to the
132
+ * URL it is given, and `ws://` sends it unencrypted. Anything else passes,
133
+ * including a value that is not a ws or wss URL, which is for the caller's own
134
+ * check. The error names the setting and the opt-in and does not repeat the
135
+ * value.
136
+ */
137
+ export function requireNoCleartextCrossHost(value, name) {
138
+ const url = parseWebSocketUrl(value);
139
+ if (url?.protocol === "ws:" &&
140
+ !isLoopbackHost(url.hostname) &&
141
+ readEnv(ALLOW_INSECURE_ENV, "").toLowerCase() !== "true") {
142
+ throw new Error(`${name} is a ws:// URL to a host other than localhost, 127.0.0.0/8 or [::1], which would send XAI_API_KEY unencrypted. Use wss://, or set ${ALLOW_INSECURE_ENV}=true to accept that`);
143
+ }
144
+ }
145
+ /** A ws or wss URL that passes `requireNoCleartextCrossHost`. The error names the setting and does not repeat the value. */
113
146
  function requireWebSocketUrl(value, name) {
114
- if (!isWebSocketUrl(value)) {
147
+ if (parseWebSocketUrl(value) === undefined) {
115
148
  throw new Error(`${name} must be a ws:// or wss:// URL`);
116
149
  }
150
+ requireNoCleartextCrossHost(value, name);
117
151
  return value;
118
152
  }
119
153
  /** `XAI_REALTIME_BASE_URL`, which must be a ws or wss URL when set. */
@@ -136,7 +170,10 @@ function resolveXaiBaseUrl(override) {
136
170
  * env at all. `VOICE_REALTIME_BACKEND` picks the model family (`gemini`, the
137
171
  * default, or `xai`); `backend` here overrides it and then the environment's
138
172
  * value is not read. A non-blank `xaiBaseURL` here likewise replaces
139
- * `XAI_REALTIME_BASE_URL` after the same ws or wss check.
173
+ * `XAI_REALTIME_BASE_URL` after the same ws or wss check. Either URL is
174
+ * checked whatever the backend. A `ws://` URL to a host other than `localhost`,
175
+ * `127.0.0.0/8` or `[::1]` is refused unless `XAI_REALTIME_ALLOW_INSECURE=true`,
176
+ * because the xAI plugin sends `XAI_API_KEY` to it unencrypted.
140
177
  * `VOICE_LIVE_MODEL` overrides the backend's default model.
141
178
  * Vertex `project` is resolved from `VERTEX_PROJECT`, then the service-account
142
179
  * project (`GOOGLE_AUTH_BREEZE_PROJECT_ID`), then `GOOGLE_CLOUD_PROJECT_ID`;
@@ -28,6 +28,8 @@ export declare function requireXaiApiKey(): void;
28
28
  * The gemini branch builds exactly what the agent has always built: Vertex AI,
29
29
  * the configured model, transcripts of both sides, and project, location,
30
30
  * voice and modality when set. The xai branch needs `XAI_API_KEY` in the
31
- * environment and throws before touching the plugin when it is missing.
31
+ * environment and throws before touching the plugin when it is missing. It also
32
+ * throws before touching the plugin for a `ws://` base URL to a host other than
33
+ * loopback, unless `XAI_REALTIME_ALLOW_INSECURE=true`, as config resolution does.
32
34
  */
33
35
  export declare function createRealtimeLlm(cfg: RealtimeVoiceConfig): Promise<RealtimeLlm>;
@@ -13,6 +13,7 @@
13
13
  *
14
14
  * See docs/features/livekit-voice-agent.md.
15
15
  */
16
+ import { requireNoCleartextCrossHost } from "./config.js";
16
17
  /**
17
18
  * Fail early, naming the variable, when `XAI_API_KEY` is blank or absent.
18
19
  *
@@ -53,6 +54,11 @@ async function createGeminiRealtimeLlm(cfg) {
53
54
  }
54
55
  async function createXaiRealtimeLlm(cfg) {
55
56
  requireXaiApiKey();
57
+ // `cfg` can be built by hand, without `resolveRealtimeVoiceConfig`, so the
58
+ // key-leak check runs here as well as there.
59
+ if (cfg.xaiBaseURL) {
60
+ requireNoCleartextCrossHost(cfg.xaiBaseURL, "xaiBaseURL");
61
+ }
56
62
  const xai = await import("@livekit/agents-plugin-xai");
57
63
  // Keys are added only when set. The plugin spreads these options over its
58
64
  // own defaults, so a key holding `undefined` would erase the default: a
@@ -75,7 +81,9 @@ async function createXaiRealtimeLlm(cfg) {
75
81
  * The gemini branch builds exactly what the agent has always built: Vertex AI,
76
82
  * the configured model, transcripts of both sides, and project, location,
77
83
  * voice and modality when set. The xai branch needs `XAI_API_KEY` in the
78
- * environment and throws before touching the plugin when it is missing.
84
+ * environment and throws before touching the plugin when it is missing. It also
85
+ * throws before touching the plugin for a `ws://` base URL to a host other than
86
+ * loopback, unless `XAI_REALTIME_ALLOW_INSECURE=true`, as config resolution does.
79
87
  */
80
88
  export async function createRealtimeLlm(cfg) {
81
89
  switch (cfg.backend) {
@@ -3678,12 +3678,12 @@
3678
3678
  {"objectID":"e6ef692117fe2ad968f2bb5bd1692e50783a069a189d3dbfd6ac49f71ef84c73","title":"Remembering a realtime call in the user's own conversation","url":"/docs/features/livekit-voice-agent#remembering-a-realtime-call-in-the-users-own-conversation","content":"A speech-to-speech call (defineRealtimeVoiceAgent) never goes through\nstream() or generate(), so by default nothing it says is stored. Opt in with\nmemory and the call's turns are written, through\nNeuroLink.recordConversationTurn, to the same conversation memory typed chat\nuses, appended to the conversation the person already has open. The model is\nalso seeded with that conversation's recent history when the call starts, so it\nknows what was said before.\n\nWhose conversation is never taken from the client. The host that creates\nthe room signs a binding and puts it in the room metadata next to authToken\nand mcpContext. The worker stores nothing unless it verifies.\nThe signature is HMAC-SHA256 over [\"neurolink.voice.memory.v1\", room,\nuserId, sessionId, exp] (a JSON array, so no choice of values can make two\n bindings collide), base64url-encoded. It covers the room name, so a binding\n copied into another room does not verify. exp is Unix seconds; the default\n lifetime is two hours, the cap 24 hours.\nThe shared secret is at least 16 characters, read from\n NEUROLINK_VOICE_MEMORY_SECRET unless memory.secret is set on the worker.\nsessionId matches ^[A-Za-z0-9_-]{1,128}$ (no :, which is part of the\n stored key). userId is 1 to 256 characters with no whitespace or control\n characters; : is allowed because chat user ids contain it.\nFail closed. No secret, no binding, a malformed or expired binding, or a\n bad signature: the call runs normally, nothing is stored, and a warning\n names the reason (never the ids).\nA client may name the conversation to append to. The host accepts the name\n only when neurolink.conversationExists({ sessionId, userId }) is true for\n the verified user. Otherwise it mints a new voice-<uuid>.\n\nWhat is stored. Each finished exchange becomes a user message and an\nassistant message with the ids ${turnId}:user and ${turnId}:assistant, where\nturnId is the realtime session's assistant message id, and\nmetadata.modality: \"voice\".","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Remembering a realtime call in the user's own conversation","lvl3":""}},
3679
3679
  {"objectID":"2b5f572d39aad7e08324d267d06f5dcbc4e90af9c0c31f1d536c84cc4243c5c1","title":"Realtime Speech-to-Speech Backends (Gemini Live and xAI Grok Voice)","url":"/docs/features/livekit-voice-agent#realtime-speech-to-speech-backends-gemini-live-and-xai-grok-voice","content":"defineRealtimeVoiceAgent runs one realtime model that does speech-to-text,\nreasoning, text-to-speech and turn detection over a single connection. Gemini\nLive on Vertex is the default. xAI's Grok Voice is a second backend, reached\nthrough LiveKit's xAI plugin.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Realtime Speech-to-Speech Backends (Gemini Live and xAI Grok Voice)","lvl3":""}},
3680
3680
  {"objectID":"3ea0de3512723dda2eba65763b09a6e3eff2ded8a4d0aa2fa41581d46b88e6c7","title":"Status","url":"/docs/features/livekit-voice-agent#status","content":"Tested against a stub WebSocket server only. The stub listens on\n 127.0.0.1. It shows what the LiveKit xAI plugin sends to whatever it is\n pointed at, and how this package reads the OpenAI-style events it is given.\n It shows nothing about how xAI answers.\nNo request has been made to xAI by this project. No xAI key was available\n when the backend was written.\nNot established here: behaviour against the live service, latency,\n accuracy, and every xAI benchmark. Nothing in this section says the xai\n backend works with the real service. Treat it as untested against xAI until\n someone runs a call with a real key.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Status","lvl3":""}},
3681
- {"objectID":"6676179c44d375115fe98161f9377ba40357b82eebf4a99b7b330ede9721e8c3","title":"Choosing the backend","url":"/docs/features/livekit-voice-agent#choosing-the-backend","content":"| Variable | Backend | Meaning |\n| --------------------------------------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| VOICE_REALTIME_BACKEND | both | gemini or xai. Any other value throws at startup, naming the variable and the two choices and repeating nothing from the environment. |\n| VOICE_LIVE_MODEL | both | Realtime model id. Default gemini-live-2.5-flash for gemini, grok-voice-3.0 for xai. |\n| VOICE_S2S_VOICE | both | Voice name.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Choosing the backend","lvl3":""}},
3681
+ {"objectID":"6676179c44d375115fe98161f9377ba40357b82eebf4a99b7b330ede9721e8c3","title":"Choosing the backend","url":"/docs/features/livekit-voice-agent#choosing-the-backend","content":"| Variable | Backend | Meaning |\n| --------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| VOICE_REALTIME_BACKEND | both | gemini or xai. Any other value throws at startup, naming the variable and the two choices and repeating nothing from the environment.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Choosing the backend","lvl3":""}},
3682
3682
  {"objectID":"632f3752058fa7c7c6d48b02af1e8d5212b7daa55001e8cc931227404009278f","title":"Dependencies","url":"/docs/features/livekit-voice-agent#dependencies","content":"The xai backend needs @livekit/agents-plugin-xai and\n@livekit/agents-plugin-openai. Both are optional dependencies of this package,\nso they are installed with its other optional dependencies (an install that\nomits optional dependencies has to add them by hand), and both resolved to\n1.4.6 in its lockfile. The xAI plugin asks for @livekit/agents 1.4.6 exactly,\nwhich is why that package moved from 1.4.5 to 1.4.6 with it. The options the\nGemini backend builds are unchanged by the move, but no live Gemini call was\nrun after it.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Dependencies","lvl3":""}},
3683
3683
  {"objectID":"a890643483526cae888fdc083535c83d5313ddef29c4a24f6d2771e94dcf3f71","title":"What the xai backend does","url":"/docs/features/livekit-voice-agent#what-the-xai-backend-does","content":"The LiveKit xAI plugin extends the OpenAI realtime model. Against a stub it\nconnects to <base URL>/realtime?model=<id> with Authorization: Bearer\n<XAI_API_KEY> (the key is never put in the URL) and its first event is a\nsession.update that carries the model, the voice, output_modalities:\n[\"audio\"], server-side voice-activity detection (threshold 0.5, 300 ms prefix\npadding, 200 ms silence, response creation and interruption on) and an input\ntranscription setting. The plugin's default endpoint is wss://api.x.ai/v1.\n\nTwo things in that list are the plugin's and are not verified against xAI:\nthe plugin sends gpt-4o-mini-transcribe, an OpenAI model name, as the input\n transcription model;\nthe plugin's own default model is grok-voice-think-fast-1.0. NeuroLink\n defaults to grok-voice-3.0, the flagship id xAI's documentation lists\n (together with the alias grok-voice-latest and a deprecated\n grok-voice-2.0). The plugin passes the id through; whether the service\n accepts it through the plugin has not been tested.\n\nA missing key stops the call before it connects. If XAI_API_KEY is unset\nthe plugin falls back to OPENAI_API_KEY, and a stub server showed that\nfallback sending the OpenAI key as the Bearer token to the configured xAI URL.\n(An empty value does not fall back: the plugin throws its own OpenAI API key is\nrequired error. A whitespace-only value is sent as the key.) NeuroLink\ntherefore refuses an unset, empty or whitespace-only key: it throws\nXAI_API_KEY is not set ... when the agent starts and again in\ncreateRealtimeLlm, and no connection is made.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"What the xai backend does","lvl3":""}},
3684
3684
  {"objectID":"b4b0a14667e072deb333f9771c062361a617e33da9a0142087c0ba9502d3e4f7","title":"How each part of the agent behaves on xai","url":"/docs/features/livekit-voice-agent#how-each-part-of-the-agent-behaves-on-xai","content":"| Part | On xai |\n| ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Vertex ADC and GEMINI_API_KEY clearing | Not run. The xai backend never touches the Gemini environment. |\n| Data-channel event bridge, HITL, room context | Unchanged. They work on the LiveKit room and the agent session, not on a model. |\n| Session events (user transcript, assistant text, turn done, usage) | Unchanged code. Against a stub, OpenAI-style transcript and usage events reach the shapes the agent reads. |\n| MCP tool bridge and schema sanitizer | Unchanged. The sanitizer produces plain JSON Schema (the OpenAI-style API takes full JSON Schema), and the plugin forwards it as is. Keeping it is the safer choice: it drops $ref and unions that xAI has not been tried with. |\n| Conversation memory (recording and seeding) | Recording is shared by both backends.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"How each part of the agent behaves on xai","lvl3":""}},
3685
3685
  {"objectID":"f2c4f00431a110b4ec6b67653e157a21d79cc3d52751253260a13758eec90e66","title":"Still unknown without a real key","url":"/docs/features/livekit-voice-agent#still-unknown-without-a-real-key","content":"Whether xAI accepts the model ids above through the plugin; whether it accepts\nthe input transcription setting; whether it accepts the sanitized tool schemas\nand underscore tool names; the event names and ordering xAI really sends (the\nplugin line pinned here, 1.4.6, predates later xAI-specific handling in newer\nplugin releases); whether the seeded history is accepted; and how interruption,\ntruncation and tool calls behave. A live smoke test with a key supplied by the\nowner is the missing step.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Still unknown without a real key","lvl3":""}},
3686
- {"objectID":"9eb38592a55bd3da33ee8a936b4648d18645a49909579f1fccb19844c8263ac7","title":"Troubleshooting","url":"/docs/features/livekit-voice-agent#troubleshooting","content":"VOICE_REALTIME_BACKEND must be \"gemini\" or \"xai\": fix the value, or unset it\n for gemini.\nXAI_API_KEY is not set: set it in the worker's environment. The check also\n rejects a whitespace-only value.\nXAI_REALTIME_BASE_URL must be a ws:// or wss:// URL: use a WebSocket URL,\n not an https:// one.\nA call that will not start on the xai backend: confirm that VOICE_LIVE_MODEL\n and VOICE_S2S_VOICE hold xAI values and not leftover Gemini ones, since both\n variables are shared.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Troubleshooting","lvl3":""}},
3686
+ {"objectID":"9eb38592a55bd3da33ee8a936b4648d18645a49909579f1fccb19844c8263ac7","title":"Troubleshooting","url":"/docs/features/livekit-voice-agent#troubleshooting","content":"VOICE_REALTIME_BACKEND must be \"gemini\" or \"xai\": fix the value, or unset it\n for gemini.\nXAI_API_KEY is not set: set it in the worker's environment. The check also\n rejects a whitespace-only value.\nXAI_REALTIME_BASE_URL must be a ws:// or wss:// URL: use a WebSocket URL,\n not an https:// one.\nXAI_REALTIME_BASE_URL is a ws:// URL to a host other than localhost, ... (or\n the same for xaiBaseURL): the URL would send XAI_API_KEY unencrypted to a\n host that is not loopback. Use a wss:// URL. Only if the path to that host is\n one you trust, set XAI_REALTIME_ALLOW_INSECURE=true, knowing the key then\n travels in cleartext.\nA call that will not start on the xai backend: confirm that VOICE_LIVE_MODEL\n and VOICE_S2S_VOICE hold xAI values and not leftover Gemini ones, since both\n variables are shared.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Troubleshooting","lvl3":""}},
3687
3687
  {"objectID":"7ffe7e32a7c2baea6c491d743617448eb70eeb4afe439960050efdc3ead18c48","title":"Implementation Plan","url":"/docs/features/livekit-voice-agent#implementation-plan","content":"The integration is built and validated in phases. Each phase is independently testable.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Implementation Plan","lvl3":""}},
3688
3688
  {"objectID":"d4c9885eea3272e250fa1a0dbc1af9503b1a24f0217a82dd0c30d93bf6c5df31","title":"Phase 0 — Console-mode spike (no infrastructure)","url":"/docs/features/livekit-voice-agent#phase-0-console-mode-spike-no-infrastructure","content":"Build a minimal agent (Silero VAD + Deepgram STT + ElevenLabs TTS + llmNode → neurolink.stream()) and run it in console mode using the host machine's mic/speakers. Validates the NeuroLink brain loop, conversationId history, and a tool call — with no LiveKit server and no browser. Requires only STT/TTS and LLM credentials.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Phase 0 — Console-mode spike (no infrastructure)","lvl3":""}},
3689
3689
  {"objectID":"9dddf98f952af643b5357bdefbcb5554a3ff2d9c33a16b0c432243fd68db5569","title":"Phase 1 — NeuroLink LiveKit module","url":"/docs/features/livekit-voice-agent#phase-1-neurolink-livekit-module","content":"Implement brain.ts, voiceAgent.ts, voiceAgentWorker.ts, tokens.ts, config.ts; add the @juspay/neurolink/livekit export and optional/peer dependencies. The worker factory accepts an external NeuroLink instance so a host application's registered tools are available. Wire abort-on-interrupt. Verify build, type-check, and lint.","hierarchy":{"lvl0":"Features","lvl1":"LiveKit Voice Agent — Real-Time Voice over WebRTC","lvl2":"Phase 1 — NeuroLink LiveKit module","lvl3":""}},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "13.4.5",
3
+ "version": "13.4.6",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
6
6
  "author": {
@@ -563,14 +563,14 @@
563
563
  "@koa/cors": "^5.0.0",
564
564
  "@koa/router": "^15.3.1",
565
565
  "@livekit/agents": "^1.4.6",
566
- "@livekit/agents-plugin-cartesia": "^1.4.5",
567
- "@livekit/agents-plugin-deepgram": "^1.4.5",
568
- "@livekit/agents-plugin-elevenlabs": "^1.4.5",
569
- "@livekit/agents-plugin-google": "^1.4.5",
570
- "@livekit/agents-plugin-livekit": "^1.4.5",
566
+ "@livekit/agents-plugin-cartesia": "^1.4.6",
567
+ "@livekit/agents-plugin-deepgram": "^1.4.6",
568
+ "@livekit/agents-plugin-elevenlabs": "^1.4.6",
569
+ "@livekit/agents-plugin-google": "^1.4.6",
570
+ "@livekit/agents-plugin-livekit": "^1.4.6",
571
571
  "@livekit/agents-plugin-openai": "^1.4.6",
572
- "@livekit/agents-plugin-silero": "^1.4.5",
573
- "@livekit/agents-plugin-soniox": "^1.4.5",
572
+ "@livekit/agents-plugin-silero": "^1.4.6",
573
+ "@livekit/agents-plugin-soniox": "^1.4.6",
574
574
  "@livekit/agents-plugin-xai": "^1.4.6",
575
575
  "@livekit/rtc-node": "^0.13.29",
576
576
  "@picovoice/cobra-node": "^3.0.2",