@juspay/neurolink 11.2.3 → 11.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/browser/neurolink.min.js +396 -396
- package/dist/core/handlerRegistry.d.ts +29 -0
- package/dist/core/handlerRegistry.js +61 -0
- package/dist/core/loopEngine.d.ts +23 -0
- package/dist/core/loopEngine.js +245 -0
- package/dist/core/nativeToolFormat.d.ts +33 -0
- package/dist/core/nativeToolFormat.js +30 -0
- package/dist/core/streamChannel.d.ts +10 -0
- package/dist/core/streamChannel.js +76 -0
- package/dist/factories/providerRegistry.d.ts +4 -16
- package/dist/factories/providerRegistry.js +4 -56
- package/dist/lib/core/handlerRegistry.d.ts +29 -0
- package/dist/lib/core/handlerRegistry.js +62 -0
- package/dist/lib/core/loopEngine.d.ts +23 -0
- package/dist/lib/core/loopEngine.js +246 -0
- package/dist/lib/core/nativeToolFormat.d.ts +33 -0
- package/dist/lib/core/nativeToolFormat.js +31 -0
- package/dist/lib/core/streamChannel.d.ts +10 -0
- package/dist/lib/core/streamChannel.js +77 -0
- package/dist/lib/factories/providerRegistry.d.ts +4 -16
- package/dist/lib/factories/providerRegistry.js +4 -56
- package/dist/lib/providers/anthropic/cacheControl.d.ts +12 -0
- package/dist/lib/providers/anthropic/cacheControl.js +15 -0
- package/dist/lib/providers/anthropic/client.js +12 -45
- package/dist/lib/providers/googleAiStudio/client.js +7 -5
- package/dist/lib/providers/googleNativeGemini3/utils.d.ts +4 -11
- package/dist/lib/providers/googleNativeGemini3/utils.js +1 -75
- package/dist/lib/providers/googleVertex/client.js +28 -30
- package/dist/lib/providers/openaiChatCompletionsBase.js +10 -12
- package/dist/lib/providers/openaiChatCompletionsClient.d.ts +1 -5
- package/dist/lib/providers/openaiChatCompletionsClient.js +0 -26
- package/dist/lib/types/index.d.ts +3 -0
- package/dist/lib/types/index.js +3 -0
- package/dist/lib/types/loopEngine.d.ts +78 -0
- package/dist/lib/types/loopEngine.js +2 -0
- package/dist/lib/types/nativeTools.d.ts +16 -0
- package/dist/lib/types/nativeTools.js +2 -0
- package/dist/lib/types/openaiCompatible.d.ts +2 -2
- package/dist/lib/types/providers.d.ts +0 -13
- package/dist/lib/types/streaming.d.ts +15 -0
- package/dist/lib/types/streaming.js +2 -0
- package/dist/lib/utils/avatarProcessor.d.ts +5 -1
- package/dist/lib/utils/avatarProcessor.js +13 -18
- package/dist/lib/utils/musicProcessor.d.ts +5 -1
- package/dist/lib/utils/musicProcessor.js +13 -18
- package/dist/lib/utils/sttProcessor.d.ts +10 -2
- package/dist/lib/utils/sttProcessor.js +22 -18
- package/dist/lib/utils/ttsProcessor.d.ts +10 -2
- package/dist/lib/utils/ttsProcessor.js +22 -18
- package/dist/lib/utils/videoProcessor.d.ts +5 -1
- package/dist/lib/utils/videoProcessor.js +13 -18
- package/dist/lib/voice/RealtimeVoiceAPI.d.ts +1 -1
- package/dist/lib/voice/RealtimeVoiceAPI.js +17 -28
- package/dist/providers/anthropic/cacheControl.d.ts +12 -0
- package/dist/providers/anthropic/cacheControl.js +14 -0
- package/dist/providers/anthropic/client.js +12 -45
- package/dist/providers/googleAiStudio/client.js +7 -5
- package/dist/providers/googleNativeGemini3/utils.d.ts +4 -11
- package/dist/providers/googleNativeGemini3/utils.js +1 -75
- package/dist/providers/googleVertex/client.js +28 -30
- package/dist/providers/openaiChatCompletionsBase.js +10 -12
- package/dist/providers/openaiChatCompletionsClient.d.ts +1 -5
- package/dist/providers/openaiChatCompletionsClient.js +0 -26
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.js +3 -0
- package/dist/types/loopEngine.d.ts +78 -0
- package/dist/types/loopEngine.js +1 -0
- package/dist/types/nativeTools.d.ts +16 -0
- package/dist/types/nativeTools.js +1 -0
- package/dist/types/openaiCompatible.d.ts +2 -2
- package/dist/types/providers.d.ts +0 -13
- package/dist/types/streaming.d.ts +15 -0
- package/dist/types/streaming.js +1 -0
- package/dist/utils/avatarProcessor.d.ts +5 -1
- package/dist/utils/avatarProcessor.js +13 -18
- package/dist/utils/musicProcessor.d.ts +5 -1
- package/dist/utils/musicProcessor.js +13 -18
- package/dist/utils/sttProcessor.d.ts +10 -2
- package/dist/utils/sttProcessor.js +22 -18
- package/dist/utils/ttsProcessor.d.ts +10 -2
- package/dist/utils/ttsProcessor.js +22 -18
- package/dist/utils/videoProcessor.d.ts +5 -1
- package/dist/utils/videoProcessor.js +13 -18
- package/dist/voice/RealtimeVoiceAPI.d.ts +1 -1
- package/dist/voice/RealtimeVoiceAPI.js +17 -28
- package/package.json +9 -1
|
@@ -36,7 +36,8 @@ import { resolveToolChoice } from "../utils/toolChoice.js";
|
|
|
36
36
|
import { transformToolExecutions } from "../utils/transformationUtils.js";
|
|
37
37
|
import { withProviderRetry } from "../utils/providerRetry.js";
|
|
38
38
|
import { resolveDeferredTool } from "../tools/toolDiscovery.js";
|
|
39
|
-
import { buildAPIError, buildBody, buildToolsForOpenAI, buildWireToolNameMaps,
|
|
39
|
+
import { buildAPIError, buildBody, buildToolsForOpenAI, buildWireToolNameMaps, createDeferredAnalytics, ensureJsonWordInBody, estimateWireTokens, mapNeuroLinkToolChoice, mergeUsage, messageBuilderToOpenAI, parseSSEStream, stringifyToolOutput, stripTrailingSlash, v3ResponseFormatToOpenAI, v3ToolChoiceToOpenAI, v3ToolsToOpenAI, } from "./openaiChatCompletionsClient.js";
|
|
40
|
+
import { createStreamChannel } from "../core/streamChannel.js";
|
|
40
41
|
/**
|
|
41
42
|
* Safety margin (tokens) when fitting `max_tokens` to a runtime-discovered
|
|
42
43
|
* context window: the char-based input estimate and the backend's own prompt
|
|
@@ -647,7 +648,7 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
647
648
|
const toolsUsed = [];
|
|
648
649
|
const toolExecutionSummaries = [];
|
|
649
650
|
const { usagePromise, finishPromise, resolveUsage, resolveFinish } = createDeferredAnalytics();
|
|
650
|
-
const
|
|
651
|
+
const channel = createStreamChannel();
|
|
651
652
|
// Per-provider lifecycle hook (e.g. OTel span wrap for LiteLLM).
|
|
652
653
|
const lifecycle = this.onStreamStart(modelId);
|
|
653
654
|
const loopPromise = this.runStreamLoop({
|
|
@@ -665,7 +666,8 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
665
666
|
emitter,
|
|
666
667
|
toolsUsed,
|
|
667
668
|
toolExecutionSummaries,
|
|
668
|
-
pushChunk,
|
|
669
|
+
pushChunk: channel.push,
|
|
670
|
+
closeChannel: channel.close,
|
|
669
671
|
resolveUsage,
|
|
670
672
|
resolveFinish,
|
|
671
673
|
});
|
|
@@ -695,11 +697,7 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
695
697
|
const transformedStream = async function* () {
|
|
696
698
|
let contentYielded = 0;
|
|
697
699
|
try {
|
|
698
|
-
for (
|
|
699
|
-
const chunk = await nextChunk();
|
|
700
|
-
if ("done" in chunk) {
|
|
701
|
-
break;
|
|
702
|
-
}
|
|
700
|
+
for await (const chunk of channel.iterable) {
|
|
703
701
|
if ("content" in chunk &&
|
|
704
702
|
typeof chunk.content === "string" &&
|
|
705
703
|
chunk.content.length > 0) {
|
|
@@ -707,7 +705,7 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
707
705
|
}
|
|
708
706
|
yield chunk;
|
|
709
707
|
}
|
|
710
|
-
// Surface any error that the loop threw after we drained the
|
|
708
|
+
// Surface any error that the loop threw after we drained the channel.
|
|
711
709
|
await loopPromise;
|
|
712
710
|
// No-output path: stream completed normally but yielded zero text.
|
|
713
711
|
// Build an enriched sentinel + stamp the active OTel span so
|
|
@@ -782,7 +780,7 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
782
780
|
return result;
|
|
783
781
|
}
|
|
784
782
|
async runStreamLoop(args) {
|
|
785
|
-
const { maxSteps, modelId, url, fetchImpl, abortSignal, options, conversation, openAITools, openAIToolChoice, toolsRecord, toolNameFromWire, emitter, toolsUsed, toolExecutionSummaries, pushChunk, resolveUsage, resolveFinish, } = args;
|
|
783
|
+
const { maxSteps, modelId, url, fetchImpl, abortSignal, options, conversation, openAITools, openAIToolChoice, toolsRecord, toolNameFromWire, emitter, toolsUsed, toolExecutionSummaries, pushChunk, closeChannel, resolveUsage, resolveFinish, } = args;
|
|
786
784
|
// Hoisted above the try so the catch can resolve the usage accumulated
|
|
787
785
|
// by steps that completed BEFORE the failure — those steps were billed.
|
|
788
786
|
let stepFinish = null;
|
|
@@ -905,7 +903,7 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
905
903
|
}
|
|
906
904
|
resolveUsage(toDeferredUsage());
|
|
907
905
|
resolveFinish(stepFinish ?? "stop");
|
|
908
|
-
|
|
906
|
+
closeChannel();
|
|
909
907
|
return {
|
|
910
908
|
finishReason: stepFinish ?? "stop",
|
|
911
909
|
usage: stepUsage,
|
|
@@ -919,7 +917,7 @@ export class OpenAIChatCompletionsProvider extends BaseProvider {
|
|
|
919
917
|
// instead of zeroing the whole turn.
|
|
920
918
|
resolveUsage(toDeferredUsage());
|
|
921
919
|
resolveFinish("error");
|
|
922
|
-
|
|
920
|
+
closeChannel();
|
|
923
921
|
throw err;
|
|
924
922
|
}
|
|
925
923
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* Nothing here imports from "ai" or "@ai-sdk/*". The whole point of this
|
|
14
14
|
* module is to be the native replacement for the AI SDK's OpenAI wrapper.
|
|
15
15
|
*/
|
|
16
|
-
import type { OpenAICompatBuildBodyArgs, OpenAICompatChatMessage, OpenAICompatChatRequest, OpenAICompatChatTool, OpenAICompatMessage, OpenAICompatMessageContent, OpenAICompatResponseFormat, OpenAICompatSSEResult,
|
|
16
|
+
import type { OpenAICompatBuildBodyArgs, OpenAICompatChatMessage, OpenAICompatChatRequest, OpenAICompatChatTool, OpenAICompatMessage, OpenAICompatMessageContent, OpenAICompatResponseFormat, OpenAICompatSSEResult, OpenAICompatToolChoiceWire, OpenAICompatUsage, OpenAICompatV3CallToolChoice, OpenAICompatV3CallTools, DeferredUsage, Tool } from "../types/index.js";
|
|
17
17
|
export declare const stripTrailingSlash: (s: string) => string;
|
|
18
18
|
/**
|
|
19
19
|
* Build a bijective original ↔ wire tool-name map. Returns undefined when
|
|
@@ -67,8 +67,4 @@ export declare const createDeferredAnalytics: () => {
|
|
|
67
67
|
resolveUsage: (u: DeferredUsage) => void;
|
|
68
68
|
resolveFinish: (reason: string) => void;
|
|
69
69
|
};
|
|
70
|
-
export declare const createChunkQueue: () => {
|
|
71
|
-
pushChunk: (c: OpenAICompatStreamChunk) => void;
|
|
72
|
-
nextChunk: () => Promise<OpenAICompatStreamChunk>;
|
|
73
|
-
};
|
|
74
70
|
export declare const mergeUsage: (a: OpenAICompatUsage | undefined, b: OpenAICompatUsage | undefined) => OpenAICompatUsage | undefined;
|
|
@@ -649,32 +649,6 @@ export const createDeferredAnalytics = () => {
|
|
|
649
649
|
});
|
|
650
650
|
return { usagePromise, finishPromise, resolveUsage, resolveFinish };
|
|
651
651
|
};
|
|
652
|
-
// Single-producer / single-consumer chunk queue. The streaming loop pushes
|
|
653
|
-
// `{content}` deltas as they arrive from SSE and a final `{done:true}` when
|
|
654
|
-
// it finishes; the consumer's AsyncIterable pulls from `nextChunk()`.
|
|
655
|
-
export const createChunkQueue = () => {
|
|
656
|
-
const chunkQueue = [];
|
|
657
|
-
let pendingResolve;
|
|
658
|
-
const pushChunk = (c) => {
|
|
659
|
-
if (pendingResolve) {
|
|
660
|
-
const r = pendingResolve;
|
|
661
|
-
pendingResolve = undefined;
|
|
662
|
-
r(c);
|
|
663
|
-
}
|
|
664
|
-
else {
|
|
665
|
-
chunkQueue.push(c);
|
|
666
|
-
}
|
|
667
|
-
};
|
|
668
|
-
const nextChunk = () => new Promise((resolve) => {
|
|
669
|
-
if (chunkQueue.length > 0) {
|
|
670
|
-
resolve(chunkQueue.shift());
|
|
671
|
-
}
|
|
672
|
-
else {
|
|
673
|
-
pendingResolve = resolve;
|
|
674
|
-
}
|
|
675
|
-
});
|
|
676
|
-
return { pushChunk, nextChunk };
|
|
677
|
-
};
|
|
678
652
|
export const mergeUsage = (a, b) => {
|
|
679
653
|
if (!a) {
|
|
680
654
|
return b;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -32,12 +32,14 @@ export * from "./hitl.js";
|
|
|
32
32
|
export * from "./isolatedAgent.js";
|
|
33
33
|
export * from "./knowledge.js";
|
|
34
34
|
export * from "./livekit.js";
|
|
35
|
+
export * from "./loopEngine.js";
|
|
35
36
|
export * from "./mcp.js";
|
|
36
37
|
export * from "./mcpOutput.js";
|
|
37
38
|
export * from "./memory.js";
|
|
38
39
|
export * from "./middleware.js";
|
|
39
40
|
export * from "./model.js";
|
|
40
41
|
export * from "./multimodal.js";
|
|
42
|
+
export * from "./nativeTools.js";
|
|
41
43
|
export * from "./observability.js";
|
|
42
44
|
export * from "./openaiCompatible.js";
|
|
43
45
|
export * from "./ppt.js";
|
|
@@ -51,6 +53,7 @@ export * from "./server.js";
|
|
|
51
53
|
export * from "./service.js";
|
|
52
54
|
export * from "./skills.js";
|
|
53
55
|
export * from "./stream.js";
|
|
56
|
+
export * from "./streaming.js";
|
|
54
57
|
export * from "./subscription.js";
|
|
55
58
|
export * from "./task.js";
|
|
56
59
|
export * from "./taskClassification.js";
|
package/dist/types/index.js
CHANGED
|
@@ -33,12 +33,14 @@ export * from "./hitl.js";
|
|
|
33
33
|
export * from "./isolatedAgent.js";
|
|
34
34
|
export * from "./knowledge.js";
|
|
35
35
|
export * from "./livekit.js";
|
|
36
|
+
export * from "./loopEngine.js";
|
|
36
37
|
export * from "./mcp.js";
|
|
37
38
|
export * from "./mcpOutput.js";
|
|
38
39
|
export * from "./memory.js";
|
|
39
40
|
export * from "./middleware.js";
|
|
40
41
|
export * from "./model.js";
|
|
41
42
|
export * from "./multimodal.js";
|
|
43
|
+
export * from "./nativeTools.js";
|
|
42
44
|
export * from "./observability.js";
|
|
43
45
|
export * from "./openaiCompatible.js";
|
|
44
46
|
export * from "./ppt.js";
|
|
@@ -52,6 +54,7 @@ export * from "./server.js";
|
|
|
52
54
|
export * from "./service.js";
|
|
53
55
|
export * from "./skills.js";
|
|
54
56
|
export * from "./stream.js";
|
|
57
|
+
export * from "./streaming.js";
|
|
55
58
|
export * from "./subscription.js";
|
|
56
59
|
export * from "./task.js";
|
|
57
60
|
export * from "./taskClassification.js";
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export type AgenticLoopToolCall = {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
args: Record<string, unknown>;
|
|
5
|
+
};
|
|
6
|
+
export type AgenticLoopUsage = {
|
|
7
|
+
inputTokens: number;
|
|
8
|
+
outputTokens: number;
|
|
9
|
+
cacheReadTokens?: number;
|
|
10
|
+
cacheWriteTokens?: number;
|
|
11
|
+
reasoningTokens?: number;
|
|
12
|
+
};
|
|
13
|
+
export type AgenticLoopStepResult<TRaw = unknown> = {
|
|
14
|
+
text: string;
|
|
15
|
+
reasoning?: string;
|
|
16
|
+
toolCalls: AgenticLoopToolCall[];
|
|
17
|
+
usage: AgenticLoopUsage;
|
|
18
|
+
/** Provider's own raw stop/finish-reason string, e.g. "tool_use", "MAX_TOKENS" */
|
|
19
|
+
rawStopReason: string | undefined;
|
|
20
|
+
/** Adapter-private accumulated response data needed by buildToolResultMessages
|
|
21
|
+
* (e.g. Anthropic's ordered content blocks, Gemini's rawResponseParts). */
|
|
22
|
+
raw: TRaw;
|
|
23
|
+
};
|
|
24
|
+
export type AgenticLoopToolCallResult = AgenticLoopToolCall & {
|
|
25
|
+
output: unknown;
|
|
26
|
+
error?: string;
|
|
27
|
+
permanentlyFailed?: boolean;
|
|
28
|
+
};
|
|
29
|
+
export type AgenticLoopStepRequest = {
|
|
30
|
+
raw: unknown;
|
|
31
|
+
};
|
|
32
|
+
export type AgenticLoopReclaimResult<TConversation> = {
|
|
33
|
+
conversation: TConversation;
|
|
34
|
+
};
|
|
35
|
+
export type AgenticLoopToolFailureBreaker = {
|
|
36
|
+
maxRetries: number;
|
|
37
|
+
};
|
|
38
|
+
export type AgenticLoopAdapter<TConversation = unknown, TRaw = unknown> = {
|
|
39
|
+
readonly providerLabel: string;
|
|
40
|
+
readonly maxSteps: number;
|
|
41
|
+
/** Pre-existing per-family flat timeout, used as createTurnClock's deadline default. */
|
|
42
|
+
readonly defaultTurnTimeoutMs?: number;
|
|
43
|
+
readonly stallTimeoutMs?: number;
|
|
44
|
+
/** Set only for adapter instances whose client has the TOOL_NOT_FOUND strike breaker today: both Gemini adapters (AI Studio, Vertex+Gemini) AND the Vertex+Claude call to createAnthropicLoopAdapter — NOT the native-Anthropic call to that same factory, and not Bedrock. See Verified Fact 4. */
|
|
45
|
+
readonly toolFailureBreaker?: AgenticLoopToolFailureBreaker;
|
|
46
|
+
buildStepRequest(conversation: TConversation, step: number): AgenticLoopStepRequest;
|
|
47
|
+
executeStep(request: AgenticLoopStepRequest, channel: {
|
|
48
|
+
push(chunk: {
|
|
49
|
+
content: string;
|
|
50
|
+
}): void;
|
|
51
|
+
}, signal: AbortSignal): Promise<AgenticLoopStepResult<TRaw>>;
|
|
52
|
+
buildToolResultMessages(conversation: TConversation, stepResult: AgenticLoopStepResult<TRaw>, toolResults: AgenticLoopToolCallResult[]): TConversation;
|
|
53
|
+
mapFinishReason(rawStopReason: string | undefined, hadToolCalls: boolean): string;
|
|
54
|
+
/** Optional: in-turn context-budget reclaim, called once per step before buildStepRequest. */
|
|
55
|
+
planReclaim?(conversation: TConversation, step: number): AgenticLoopReclaimResult<TConversation> | undefined;
|
|
56
|
+
/** Optional: Vertex+Gemini-only single-retry-on-malformed-call. */
|
|
57
|
+
isMalformedStep?(stepResult: AgenticLoopStepResult<TRaw>): boolean;
|
|
58
|
+
buildMalformedRetryNote?(conversation: TConversation): TConversation;
|
|
59
|
+
};
|
|
60
|
+
export type AgenticLoopOptions = {
|
|
61
|
+
tools?: Record<string, {
|
|
62
|
+
execute?: (args: Record<string, unknown>, opts: unknown) => Promise<unknown>;
|
|
63
|
+
}>;
|
|
64
|
+
abortSignal?: AbortSignal;
|
|
65
|
+
};
|
|
66
|
+
export type AgenticLoopResult<TConversation> = {
|
|
67
|
+
text: string;
|
|
68
|
+
toolCalls: AgenticLoopToolCall[];
|
|
69
|
+
toolExecutions: Array<{
|
|
70
|
+
name: string;
|
|
71
|
+
input: Record<string, unknown>;
|
|
72
|
+
output: unknown;
|
|
73
|
+
}>;
|
|
74
|
+
usage: AgenticLoopUsage;
|
|
75
|
+
finishReason: string;
|
|
76
|
+
rawStopReason: string | undefined;
|
|
77
|
+
conversation: TConversation;
|
|
78
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire formats accepted by `toNativeToolDeclarations` (src/lib/core/nativeToolFormat.ts).
|
|
3
|
+
* `"input_schema"` is Anthropic's native Messages-API tool shape;
|
|
4
|
+
* `"functionDeclarations"` is the @google/genai SDK shape shared by the
|
|
5
|
+
* Gemini-family native providers (Google AI Studio, Vertex+Gemini).
|
|
6
|
+
*/
|
|
7
|
+
export type NativeToolFormat = "input_schema" | "functionDeclarations";
|
|
8
|
+
/** A single tool declaration in Anthropic's native `input_schema` wire format. */
|
|
9
|
+
export type NativeAnthropicToolDeclaration = {
|
|
10
|
+
name: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
input_schema: Record<string, unknown>;
|
|
13
|
+
cache_control?: {
|
|
14
|
+
type: "ephemeral";
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -203,8 +203,6 @@ export type OpenAICompatSSEResult = {
|
|
|
203
203
|
export type OpenAICompatStreamChunk = {
|
|
204
204
|
content: string;
|
|
205
205
|
reasoning?: string;
|
|
206
|
-
} | {
|
|
207
|
-
done: true;
|
|
208
206
|
};
|
|
209
207
|
export type ToolExecutionSummaryInternal = {
|
|
210
208
|
toolCallId: string;
|
|
@@ -232,6 +230,8 @@ export type StreamLoopArgs = {
|
|
|
232
230
|
toolsUsed: string[];
|
|
233
231
|
toolExecutionSummaries: ToolExecutionSummaryInternal[];
|
|
234
232
|
pushChunk: (chunk: OpenAICompatStreamChunk) => void;
|
|
233
|
+
/** Signals the channel that no further chunks will arrive (success or error path alike). */
|
|
234
|
+
closeChannel: () => void;
|
|
235
235
|
resolveUsage: (u: {
|
|
236
236
|
promptTokens: number;
|
|
237
237
|
completionTokens: number;
|
|
@@ -1740,19 +1740,6 @@ export type CollectedChunkResult = {
|
|
|
1740
1740
|
*/
|
|
1741
1741
|
reasoningTokens?: number;
|
|
1742
1742
|
};
|
|
1743
|
-
/** Push-based text channel for incremental streaming. */
|
|
1744
|
-
export type TextChannel = {
|
|
1745
|
-
/** Push a text chunk to the consumer. */
|
|
1746
|
-
push: (text: string) => void;
|
|
1747
|
-
/** Signal that no more chunks will arrive. */
|
|
1748
|
-
close: () => void;
|
|
1749
|
-
/** Signal that the producer encountered a fatal error. */
|
|
1750
|
-
error: (err: unknown) => void;
|
|
1751
|
-
/** Async iterable consumed by the StreamResult. */
|
|
1752
|
-
iterable: AsyncIterable<{
|
|
1753
|
-
content: string;
|
|
1754
|
-
}>;
|
|
1755
|
-
};
|
|
1756
1743
|
/** Language model object shape (LanguageModelV2/V3). */
|
|
1757
1744
|
export type LanguageModelObject = {
|
|
1758
1745
|
readonly modelId: string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared push-based channel bridging a background producer (an agentic
|
|
3
|
+
* tool-calling loop) with an async-iterable consumer. Replaces the two
|
|
4
|
+
* independently-invented primitives this type unifies: the OpenAI-family
|
|
5
|
+
* `createChunkQueue` (pull-based, in-band `{done:true}` sentinel) and the
|
|
6
|
+
* Gemini-family `createTextChannel` (push-based, out-of-band close/error).
|
|
7
|
+
*/
|
|
8
|
+
export type StreamChannel<T = {
|
|
9
|
+
content: string;
|
|
10
|
+
}> = {
|
|
11
|
+
push(value: T): void;
|
|
12
|
+
close(): void;
|
|
13
|
+
error(err: unknown): void;
|
|
14
|
+
readonly iterable: AsyncIterable<T>;
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -43,7 +43,7 @@ export declare class AvatarError extends NeuroLinkError {
|
|
|
43
43
|
* Static processor managing the avatar handler registry.
|
|
44
44
|
*/
|
|
45
45
|
export declare class AvatarProcessor {
|
|
46
|
-
private static readonly
|
|
46
|
+
private static readonly registry;
|
|
47
47
|
/**
|
|
48
48
|
* Register an avatar handler for a specific provider.
|
|
49
49
|
*/
|
|
@@ -63,6 +63,10 @@ export declare class AvatarProcessor {
|
|
|
63
63
|
* already-registered primary handler when backfilling its aliases.
|
|
64
64
|
*/
|
|
65
65
|
static getHandler(providerName: string): AvatarHandler | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Clear all registered handlers (for testing).
|
|
68
|
+
*/
|
|
69
|
+
static clearHandlers(): void;
|
|
66
70
|
private static buildSpanAttributes;
|
|
67
71
|
/**
|
|
68
72
|
* Generate an avatar video via the registered handler.
|
|
@@ -13,6 +13,7 @@ import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
|
13
13
|
import { SpanSerializer, SpanStatus, SpanType, getMetricsAggregator, } from "../observability/index.js";
|
|
14
14
|
import { NeuroLinkError } from "./errorHandling.js";
|
|
15
15
|
import { logger } from "./logger.js";
|
|
16
|
+
import { HandlerRegistry } from "../core/handlerRegistry.js";
|
|
16
17
|
/**
|
|
17
18
|
* Avatar-specific error codes.
|
|
18
19
|
*/
|
|
@@ -47,38 +48,26 @@ export class AvatarError extends NeuroLinkError {
|
|
|
47
48
|
* Static processor managing the avatar handler registry.
|
|
48
49
|
*/
|
|
49
50
|
export class AvatarProcessor {
|
|
50
|
-
static
|
|
51
|
+
static registry = new HandlerRegistry("AvatarProcessor");
|
|
51
52
|
/**
|
|
52
53
|
* Register an avatar handler for a specific provider.
|
|
53
54
|
*/
|
|
54
55
|
static registerHandler(providerName, handler) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
if (!handler) {
|
|
59
|
-
throw new Error("Handler is required");
|
|
60
|
-
}
|
|
61
|
-
const key = providerName.toLowerCase();
|
|
62
|
-
if (this.handlers.has(key)) {
|
|
63
|
-
logger.warn(`[AvatarProcessor] Overwriting existing handler for provider: ${key}`);
|
|
64
|
-
}
|
|
65
|
-
this.handlers.set(key, handler);
|
|
56
|
+
const key = providerName ? providerName.toLowerCase() : providerName;
|
|
57
|
+
this.registry.register(providerName, handler);
|
|
66
58
|
logger.debug(`[AvatarProcessor] Registered avatar handler: ${key}`);
|
|
67
59
|
}
|
|
68
60
|
/**
|
|
69
61
|
* Check if a provider has a registered avatar handler.
|
|
70
62
|
*/
|
|
71
63
|
static supports(providerName) {
|
|
72
|
-
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
return this.handlers.has(providerName.toLowerCase());
|
|
64
|
+
return this.registry.supports(providerName);
|
|
76
65
|
}
|
|
77
66
|
/**
|
|
78
67
|
* List the names of all registered providers.
|
|
79
68
|
*/
|
|
80
69
|
static listProviders() {
|
|
81
|
-
return
|
|
70
|
+
return this.registry.list();
|
|
82
71
|
}
|
|
83
72
|
/**
|
|
84
73
|
* Get a registered avatar handler by provider name.
|
|
@@ -87,7 +76,13 @@ export class AvatarProcessor {
|
|
|
87
76
|
* already-registered primary handler when backfilling its aliases.
|
|
88
77
|
*/
|
|
89
78
|
static getHandler(providerName) {
|
|
90
|
-
return this.
|
|
79
|
+
return this.registry.get(providerName);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Clear all registered handlers (for testing).
|
|
83
|
+
*/
|
|
84
|
+
static clearHandlers() {
|
|
85
|
+
this.registry.clear();
|
|
91
86
|
}
|
|
92
87
|
static buildSpanAttributes(provider, options) {
|
|
93
88
|
return {
|
|
@@ -42,7 +42,7 @@ export declare class MusicError extends NeuroLinkError {
|
|
|
42
42
|
* Static processor managing the music handler registry.
|
|
43
43
|
*/
|
|
44
44
|
export declare class MusicProcessor {
|
|
45
|
-
private static readonly
|
|
45
|
+
private static readonly registry;
|
|
46
46
|
/**
|
|
47
47
|
* Register a music handler for a specific provider.
|
|
48
48
|
*/
|
|
@@ -62,6 +62,10 @@ export declare class MusicProcessor {
|
|
|
62
62
|
* already-registered primary handler when backfilling its aliases.
|
|
63
63
|
*/
|
|
64
64
|
static getHandler(providerName: string): MusicHandler | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Clear all registered handlers (for testing).
|
|
67
|
+
*/
|
|
68
|
+
static clearHandlers(): void;
|
|
65
69
|
private static buildSpanAttributes;
|
|
66
70
|
/**
|
|
67
71
|
* Generate a music track via the registered handler.
|
|
@@ -13,6 +13,7 @@ import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
|
13
13
|
import { SpanSerializer, SpanStatus, SpanType, getMetricsAggregator, } from "../observability/index.js";
|
|
14
14
|
import { NeuroLinkError } from "./errorHandling.js";
|
|
15
15
|
import { logger } from "./logger.js";
|
|
16
|
+
import { HandlerRegistry } from "../core/handlerRegistry.js";
|
|
16
17
|
/**
|
|
17
18
|
* Music-specific error codes.
|
|
18
19
|
*/
|
|
@@ -46,38 +47,26 @@ export class MusicError extends NeuroLinkError {
|
|
|
46
47
|
* Static processor managing the music handler registry.
|
|
47
48
|
*/
|
|
48
49
|
export class MusicProcessor {
|
|
49
|
-
static
|
|
50
|
+
static registry = new HandlerRegistry("MusicProcessor");
|
|
50
51
|
/**
|
|
51
52
|
* Register a music handler for a specific provider.
|
|
52
53
|
*/
|
|
53
54
|
static registerHandler(providerName, handler) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
if (!handler) {
|
|
58
|
-
throw new Error("Handler is required");
|
|
59
|
-
}
|
|
60
|
-
const key = providerName.toLowerCase();
|
|
61
|
-
if (this.handlers.has(key)) {
|
|
62
|
-
logger.warn(`[MusicProcessor] Overwriting existing handler for provider: ${key}`);
|
|
63
|
-
}
|
|
64
|
-
this.handlers.set(key, handler);
|
|
55
|
+
const key = providerName ? providerName.toLowerCase() : providerName;
|
|
56
|
+
this.registry.register(providerName, handler);
|
|
65
57
|
logger.debug(`[MusicProcessor] Registered music handler: ${key}`);
|
|
66
58
|
}
|
|
67
59
|
/**
|
|
68
60
|
* Check if a provider has a registered music handler.
|
|
69
61
|
*/
|
|
70
62
|
static supports(providerName) {
|
|
71
|
-
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
return this.handlers.has(providerName.toLowerCase());
|
|
63
|
+
return this.registry.supports(providerName);
|
|
75
64
|
}
|
|
76
65
|
/**
|
|
77
66
|
* List the names of all registered providers.
|
|
78
67
|
*/
|
|
79
68
|
static listProviders() {
|
|
80
|
-
return
|
|
69
|
+
return this.registry.list();
|
|
81
70
|
}
|
|
82
71
|
/**
|
|
83
72
|
* Get a registered music handler by provider name.
|
|
@@ -86,7 +75,13 @@ export class MusicProcessor {
|
|
|
86
75
|
* already-registered primary handler when backfilling its aliases.
|
|
87
76
|
*/
|
|
88
77
|
static getHandler(providerName) {
|
|
89
|
-
return this.
|
|
78
|
+
return this.registry.get(providerName);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Clear all registered handlers (for testing).
|
|
82
|
+
*/
|
|
83
|
+
static clearHandlers() {
|
|
84
|
+
this.registry.clear();
|
|
90
85
|
}
|
|
91
86
|
static buildSpanAttributes(provider, options) {
|
|
92
87
|
return {
|
|
@@ -27,11 +27,10 @@ import type { STTOptions, STTResult, STTHandler } from "../types/index.js";
|
|
|
27
27
|
export declare class STTProcessor {
|
|
28
28
|
/**
|
|
29
29
|
* Handler registry mapping provider names to STT handlers
|
|
30
|
-
* Uses Map for O(1) lookups and better type safety
|
|
31
30
|
*
|
|
32
31
|
* @private
|
|
33
32
|
*/
|
|
34
|
-
private static readonly
|
|
33
|
+
private static readonly registry;
|
|
35
34
|
/**
|
|
36
35
|
* Default maximum audio duration for STT transcription (in seconds)
|
|
37
36
|
*
|
|
@@ -72,6 +71,15 @@ export declare class STTProcessor {
|
|
|
72
71
|
* @returns Handler instance or undefined if not registered
|
|
73
72
|
*/
|
|
74
73
|
static getHandler(providerName: string): STTHandler | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* List the names of all registered providers.
|
|
76
|
+
*/
|
|
77
|
+
static listProviders(): string[];
|
|
78
|
+
/**
|
|
79
|
+
* Removes every registered STT handler. Primarily for test isolation —
|
|
80
|
+
* production code should not need to call this.
|
|
81
|
+
*/
|
|
82
|
+
static clearHandlers(): void;
|
|
75
83
|
/**
|
|
76
84
|
* Check if a provider is supported (has a registered STT handler)
|
|
77
85
|
*
|
|
@@ -10,6 +10,7 @@ import { logger } from "./logger.js";
|
|
|
10
10
|
import { STT_ERROR_CODES } from "../types/index.js";
|
|
11
11
|
import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
12
12
|
import { STTError } from "../voice/errors.js";
|
|
13
|
+
import { HandlerRegistry } from "../core/handlerRegistry.js";
|
|
13
14
|
import { SpanSerializer, SpanType, SpanStatus, getMetricsAggregator, } from "../observability/index.js";
|
|
14
15
|
/**
|
|
15
16
|
* STT processor class for orchestrating speech-to-text operations
|
|
@@ -31,11 +32,10 @@ import { SpanSerializer, SpanType, SpanStatus, getMetricsAggregator, } from "../
|
|
|
31
32
|
export class STTProcessor {
|
|
32
33
|
/**
|
|
33
34
|
* Handler registry mapping provider names to STT handlers
|
|
34
|
-
* Uses Map for O(1) lookups and better type safety
|
|
35
35
|
*
|
|
36
36
|
* @private
|
|
37
37
|
*/
|
|
38
|
-
static
|
|
38
|
+
static registry = new HandlerRegistry("STTProcessor");
|
|
39
39
|
/**
|
|
40
40
|
* Default maximum audio duration for STT transcription (in seconds)
|
|
41
41
|
*
|
|
@@ -66,17 +66,10 @@ export class STTProcessor {
|
|
|
66
66
|
* ```
|
|
67
67
|
*/
|
|
68
68
|
static registerHandler(providerName, handler) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
throw new Error("Handler is required");
|
|
74
|
-
}
|
|
75
|
-
const normalizedName = providerName.toLowerCase();
|
|
76
|
-
if (this.handlers.has(normalizedName)) {
|
|
77
|
-
logger.warn(`[STTProcessor] Overwriting existing handler for provider: ${normalizedName}`);
|
|
78
|
-
}
|
|
79
|
-
this.handlers.set(normalizedName, handler);
|
|
69
|
+
const normalizedName = providerName
|
|
70
|
+
? providerName.toLowerCase()
|
|
71
|
+
: providerName;
|
|
72
|
+
this.registry.register(providerName, handler);
|
|
80
73
|
logger.debug(`[STTProcessor] Registered STT handler for provider: ${normalizedName}`);
|
|
81
74
|
}
|
|
82
75
|
/**
|
|
@@ -89,8 +82,20 @@ export class STTProcessor {
|
|
|
89
82
|
* @returns Handler instance or undefined if not registered
|
|
90
83
|
*/
|
|
91
84
|
static getHandler(providerName) {
|
|
92
|
-
|
|
93
|
-
|
|
85
|
+
return this.registry.get(providerName);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* List the names of all registered providers.
|
|
89
|
+
*/
|
|
90
|
+
static listProviders() {
|
|
91
|
+
return this.registry.list();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Removes every registered STT handler. Primarily for test isolation —
|
|
95
|
+
* production code should not need to call this.
|
|
96
|
+
*/
|
|
97
|
+
static clearHandlers() {
|
|
98
|
+
this.registry.clear();
|
|
94
99
|
}
|
|
95
100
|
/**
|
|
96
101
|
* Check if a provider is supported (has a registered STT handler)
|
|
@@ -110,8 +115,7 @@ export class STTProcessor {
|
|
|
110
115
|
logger.error("[STTProcessor] Provider name is required for supports check");
|
|
111
116
|
return false;
|
|
112
117
|
}
|
|
113
|
-
const
|
|
114
|
-
const isSupported = this.handlers.has(normalizedName);
|
|
118
|
+
const isSupported = this.registry.supports(providerName);
|
|
115
119
|
if (!isSupported) {
|
|
116
120
|
logger.debug(`[STTProcessor] Provider ${providerName} is not supported`);
|
|
117
121
|
}
|
|
@@ -192,7 +196,7 @@ export class STTProcessor {
|
|
|
192
196
|
retriable: false,
|
|
193
197
|
context: {
|
|
194
198
|
provider,
|
|
195
|
-
availableProviders:
|
|
199
|
+
availableProviders: this.registry.list(),
|
|
196
200
|
},
|
|
197
201
|
});
|
|
198
202
|
}
|
|
@@ -54,11 +54,10 @@ export declare class TTSError extends NeuroLinkError {
|
|
|
54
54
|
export declare class TTSProcessor {
|
|
55
55
|
/**
|
|
56
56
|
* Handler registry mapping provider names to TTS handlers
|
|
57
|
-
* Uses Map for O(1) lookups and better type safety
|
|
58
57
|
*
|
|
59
58
|
* @private
|
|
60
59
|
*/
|
|
61
|
-
private static readonly
|
|
60
|
+
private static readonly registry;
|
|
62
61
|
/**
|
|
63
62
|
* Default maximum text length for TTS synthesis (in bytes)
|
|
64
63
|
*
|
|
@@ -100,6 +99,15 @@ export declare class TTSProcessor {
|
|
|
100
99
|
* @returns Handler instance or undefined if not registered
|
|
101
100
|
*/
|
|
102
101
|
static getHandler(providerName: string): TTSHandler | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* List the names of all registered providers.
|
|
104
|
+
*/
|
|
105
|
+
static listProviders(): string[];
|
|
106
|
+
/**
|
|
107
|
+
* Removes every registered TTS handler. Primarily for test isolation —
|
|
108
|
+
* production code should not need to call this.
|
|
109
|
+
*/
|
|
110
|
+
static clearHandlers(): void;
|
|
103
111
|
/**
|
|
104
112
|
* Check if a provider is supported (has a registered TTS handler)
|
|
105
113
|
*
|