@juspay/neurolink 12.34.1 → 12.34.3
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 +3 -3
- package/dist/browser/neurolink.min.js +393 -393
- package/dist/providers/openaiChatCompletionsBase.js +20 -0
- package/dist/services/server/ai/observability/instrumentation.d.ts +5 -0
- package/dist/services/server/ai/observability/instrumentation.js +31 -0
- package/package.json +1 -1
|
@@ -1812,6 +1812,20 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
1812
1812
|
// `loopPromise` is undefined when a middleware blocked the request
|
|
1813
1813
|
// before `doStream` ran, in which case there is no loop to surface.
|
|
1814
1814
|
await loopPromise;
|
|
1815
|
+
// Record the terminal finish reason on the metadata object this
|
|
1816
|
+
// provider returns by reference (`result.metadata`). A rejected
|
|
1817
|
+
// `loopPromise` throws out of this `await` straight into the `catch`
|
|
1818
|
+
// below, so reaching this line means `runStreamLoop` returned
|
|
1819
|
+
// normally and already called `resolveFinish` with the wire value —
|
|
1820
|
+
// `finishPromise` is settled, not pending.
|
|
1821
|
+
//
|
|
1822
|
+
// `rawFinishReason` is the verbatim vendor value (e.g. "stop",
|
|
1823
|
+
// "length", "tool_calls", "content_filter") and is accurate the
|
|
1824
|
+
// moment the wire stream itself finished, independent of whatever
|
|
1825
|
+
// post-stream work follows. The graded `finishReason` is set later,
|
|
1826
|
+
// once that post-stream work (the structured-output re-ask below)
|
|
1827
|
+
// has actually succeeded — see the assignment after that block.
|
|
1828
|
+
streamMetadata.rawFinishReason = await finishPromise;
|
|
1815
1829
|
// Structured output for a `stream({ schema })` turn. Runs HERE —
|
|
1816
1830
|
// after the stream is fully drained — so a tool-free re-ask (when the
|
|
1817
1831
|
// streamed answer isn't already schema-valid) never reaches
|
|
@@ -1853,6 +1867,12 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
1853
1867
|
});
|
|
1854
1868
|
}
|
|
1855
1869
|
}
|
|
1870
|
+
// Only reached once the structured-output re-ask above (when there
|
|
1871
|
+
// was one) has resolved without throwing. A caller abort during that
|
|
1872
|
+
// re-ask rejects `resolveStreamStructuredData` and skips this line
|
|
1873
|
+
// entirely, so `metadata.finishReason` never claims "stop" for a
|
|
1874
|
+
// turn that actually failed after the wire stream itself finished.
|
|
1875
|
+
streamMetadata.finishReason = "stop";
|
|
1856
1876
|
// No-output path: stream completed normally but yielded zero text.
|
|
1857
1877
|
// Build an enriched sentinel + stamp the active OTel span so
|
|
1858
1878
|
// Pipeline B (ContextEnricher) surfaces a WARNING-level Langfuse
|
|
@@ -51,6 +51,11 @@ export declare function initializeOpenTelemetry(config: LangfuseConfig): Promise
|
|
|
51
51
|
export declare function flushOpenTelemetry(): Promise<void>;
|
|
52
52
|
/**
|
|
53
53
|
* Shutdown OpenTelemetry and Langfuse span processor
|
|
54
|
+
*
|
|
55
|
+
* Concurrent callers share one in-flight teardown, the same way concurrent
|
|
56
|
+
* initializers share one in-flight `initializeOpenTelemetry`: a second
|
|
57
|
+
* shutdown call joins the first instead of tearing down the same provider
|
|
58
|
+
* instances a second time.
|
|
54
59
|
*/
|
|
55
60
|
export declare function shutdownOpenTelemetry(): Promise<void>;
|
|
56
61
|
/**
|
|
@@ -106,6 +106,7 @@ let loggerProvider = null;
|
|
|
106
106
|
let langfuseProcessor = null;
|
|
107
107
|
let isInitialized = false;
|
|
108
108
|
let initializationPromise = null;
|
|
109
|
+
let shutdownPromise = null;
|
|
109
110
|
let isCredentialsValid = false;
|
|
110
111
|
let currentConfig = null;
|
|
111
112
|
let usingExternalProvider = false;
|
|
@@ -841,6 +842,15 @@ async function initializeStandaloneOpenTelemetryMode(config, resource, otlpEndpo
|
|
|
841
842
|
* flush or shutdown wait for the same initialization before touching providers.
|
|
842
843
|
*/
|
|
843
844
|
export async function initializeOpenTelemetry(config) {
|
|
845
|
+
if (shutdownPromise) {
|
|
846
|
+
// A shutdown already in flight is what made isInitialized/
|
|
847
|
+
// initializationPromise true or null in the first place; either reading
|
|
848
|
+
// is stale until it actually finishes. Waiting here means this call sees
|
|
849
|
+
// the settled post-teardown state — nothing initialized, nothing
|
|
850
|
+
// pending — and falls through to build fresh providers, rather than
|
|
851
|
+
// returning early on a flag that is about to flip out from under it.
|
|
852
|
+
await shutdownPromise;
|
|
853
|
+
}
|
|
844
854
|
if (isInitialized) {
|
|
845
855
|
currentConfig = config;
|
|
846
856
|
logger.debug(`${LOG_PREFIX} Already initialized, config updated`, {
|
|
@@ -991,8 +1001,29 @@ export async function flushOpenTelemetry() {
|
|
|
991
1001
|
}
|
|
992
1002
|
/**
|
|
993
1003
|
* Shutdown OpenTelemetry and Langfuse span processor
|
|
1004
|
+
*
|
|
1005
|
+
* Concurrent callers share one in-flight teardown, the same way concurrent
|
|
1006
|
+
* initializers share one in-flight `initializeOpenTelemetry`: a second
|
|
1007
|
+
* shutdown call joins the first instead of tearing down the same provider
|
|
1008
|
+
* instances a second time.
|
|
994
1009
|
*/
|
|
995
1010
|
export async function shutdownOpenTelemetry() {
|
|
1011
|
+
if (shutdownPromise) {
|
|
1012
|
+
await shutdownPromise;
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
const pending = shutdownOpenTelemetryOnce();
|
|
1016
|
+
shutdownPromise = pending;
|
|
1017
|
+
try {
|
|
1018
|
+
await pending;
|
|
1019
|
+
}
|
|
1020
|
+
finally {
|
|
1021
|
+
if (shutdownPromise === pending) {
|
|
1022
|
+
shutdownPromise = null;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
async function shutdownOpenTelemetryOnce() {
|
|
996
1027
|
if (initializationPromise) {
|
|
997
1028
|
try {
|
|
998
1029
|
await initializationPromise;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.34.
|
|
3
|
+
"version": "12.34.3",
|
|
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": {
|