@juspay/neurolink 11.2.4 → 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 +5 -1
- package/dist/browser/neurolink.min.js +391 -391
- 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/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/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/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/package.json +3 -1
|
@@ -639,80 +639,6 @@ export async function collectStreamChunks(stream) {
|
|
|
639
639
|
reasoningTokens,
|
|
640
640
|
};
|
|
641
641
|
}
|
|
642
|
-
/**
|
|
643
|
-
* Create a push-based text channel that bridges a background producer
|
|
644
|
-
* (the agentic tool-calling loop) with an async-iterable consumer.
|
|
645
|
-
*
|
|
646
|
-
* This enables truly incremental streaming: text parts are yielded to the
|
|
647
|
-
* caller as they arrive from the network, rather than being buffered until
|
|
648
|
-
* the model finishes generating.
|
|
649
|
-
*/
|
|
650
|
-
export function createTextChannel() {
|
|
651
|
-
const queue = [];
|
|
652
|
-
let done = false;
|
|
653
|
-
let fatalError = undefined;
|
|
654
|
-
// Resolve the current "wait for data" promise when new data arrives
|
|
655
|
-
let notify = null;
|
|
656
|
-
function wake() {
|
|
657
|
-
if (notify) {
|
|
658
|
-
const fn = notify;
|
|
659
|
-
notify = null;
|
|
660
|
-
fn();
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
function push(text) {
|
|
664
|
-
if (done) {
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
667
|
-
queue.push({ content: text });
|
|
668
|
-
wake();
|
|
669
|
-
}
|
|
670
|
-
function close() {
|
|
671
|
-
done = true;
|
|
672
|
-
wake();
|
|
673
|
-
}
|
|
674
|
-
function error(err) {
|
|
675
|
-
done = true;
|
|
676
|
-
fatalError = err;
|
|
677
|
-
wake();
|
|
678
|
-
}
|
|
679
|
-
let readIndex = 0;
|
|
680
|
-
async function* iterable() {
|
|
681
|
-
try {
|
|
682
|
-
while (true) {
|
|
683
|
-
if (readIndex < queue.length) {
|
|
684
|
-
yield queue[readIndex++];
|
|
685
|
-
// Periodically compact consumed chunks to avoid unbounded retention
|
|
686
|
-
if (readIndex > 1024 && readIndex * 2 >= queue.length) {
|
|
687
|
-
queue.splice(0, readIndex);
|
|
688
|
-
readIndex = 0;
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
else if (done) {
|
|
692
|
-
if (fatalError !== undefined) {
|
|
693
|
-
throw fatalError instanceof Error
|
|
694
|
-
? fatalError
|
|
695
|
-
: new Error(String(fatalError));
|
|
696
|
-
}
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
else {
|
|
700
|
-
// Wait until the producer pushes data or signals completion
|
|
701
|
-
await new Promise((resolve) => {
|
|
702
|
-
notify = resolve;
|
|
703
|
-
});
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
finally {
|
|
708
|
-
// Consumer stopped reading (e.g. disconnect/cancel): stop buffering.
|
|
709
|
-
done = true;
|
|
710
|
-
queue.length = 0;
|
|
711
|
-
notify?.();
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
return { push, close, error, iterable: iterable() };
|
|
715
|
-
}
|
|
716
642
|
/**
|
|
717
643
|
* Iterate a single stream step incrementally, pushing text parts to `channel`
|
|
718
644
|
* as they arrive from the network while simultaneously accumulating the full
|
|
@@ -741,7 +667,7 @@ export async function collectStreamChunksIncremental(stream, channel) {
|
|
|
741
667
|
rawResponseParts.push(part);
|
|
742
668
|
// Forward text parts to the consumer immediately
|
|
743
669
|
if (typeof part.text === "string" && part.text.length > 0) {
|
|
744
|
-
channel.push(part.text);
|
|
670
|
+
channel.push({ content: part.text });
|
|
745
671
|
}
|
|
746
672
|
}
|
|
747
673
|
}
|
|
@@ -29,7 +29,9 @@ import { convertZodToJsonSchema, inlineJsonSchema, ensureNestedSchemaTypes, } fr
|
|
|
29
29
|
import { createNativeThinkingConfig } from "../../utils/thinkingConfig.js";
|
|
30
30
|
import { TimeoutError, raceWithAbort, withTimeout, } from "../../utils/async/index.js";
|
|
31
31
|
import { parseTimeout } from "../../utils/timeout.js";
|
|
32
|
-
import { appendStepText, buildAbortedTurnMessage, buildContextCapMessage, buildToolLoopCapMessage, buildTurnStalledMessage, buildTurnTimeoutMessage, buildWrapupNudgeText, createContextGuard,
|
|
32
|
+
import { appendStepText, buildAbortedTurnMessage, buildContextCapMessage, buildToolLoopCapMessage, buildTurnStalledMessage, buildTurnTimeoutMessage, buildWrapupNudgeText, createContextGuard, createTurnClock, extractThoughtSignature, isAbortError, mapGeminiFinishReason, prependConversationMessages, resolveTurnStopReason, DedupExecuteMap, } from "../googleNativeGemini3/index.js";
|
|
33
|
+
import { createStreamChannel } from "../../core/streamChannel.js";
|
|
34
|
+
import { toNativeToolDeclarations } from "../../core/nativeToolFormat.js";
|
|
33
35
|
import { getAvailableInputTokens, getContextWindowSize, } from "../../constants/contextWindows.js";
|
|
34
36
|
import { resolveLiveTool } from "../../tools/toolDiscovery.js";
|
|
35
37
|
import { ATTR, LANGFUSE_ATTR, spanJsonAttribute, tracers, withClientSpan, withClientStreamSpan, withSpan, } from "../../telemetry/index.js";
|
|
@@ -1145,17 +1147,14 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
1145
1147
|
if (options.tools &&
|
|
1146
1148
|
Object.keys(options.tools).length > 0 &&
|
|
1147
1149
|
!options.disableTools) {
|
|
1148
|
-
const
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
executeMap.set(name, tool.execute);
|
|
1153
|
-
}
|
|
1150
|
+
const declared = toNativeToolDeclarations(options.tools, "functionDeclarations");
|
|
1151
|
+
tools = declared.toolsConfig;
|
|
1152
|
+
for (const [name, execute] of declared.executeMap) {
|
|
1153
|
+
executeMap.set(name, execute);
|
|
1154
1154
|
}
|
|
1155
|
-
tools = [{ functionDeclarations }];
|
|
1156
1155
|
logger.debug("[GoogleVertex] Converted tools for native SDK", {
|
|
1157
|
-
toolCount: functionDeclarations.length,
|
|
1158
|
-
toolNames: functionDeclarations.map((t) => t.name),
|
|
1156
|
+
toolCount: declared.toolsConfig[0].functionDeclarations.length,
|
|
1157
|
+
toolNames: declared.toolsConfig[0].functionDeclarations.map((t) => t.name),
|
|
1159
1158
|
});
|
|
1160
1159
|
}
|
|
1161
1160
|
// Check if we need to use the final_result tool pattern for structured output with tools
|
|
@@ -2154,17 +2153,14 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
2154
2153
|
let tools;
|
|
2155
2154
|
const executeMap = new DedupExecuteMap();
|
|
2156
2155
|
if (Object.keys(combinedTools).length > 0) {
|
|
2157
|
-
const
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
executeMap.set(name, tool.execute);
|
|
2162
|
-
}
|
|
2156
|
+
const declared = toNativeToolDeclarations(combinedTools, "functionDeclarations");
|
|
2157
|
+
tools = declared.toolsConfig;
|
|
2158
|
+
for (const [name, execute] of declared.executeMap) {
|
|
2159
|
+
executeMap.set(name, execute);
|
|
2163
2160
|
}
|
|
2164
|
-
tools = [{ functionDeclarations }];
|
|
2165
2161
|
logger.debug("[GoogleVertex] Converted tools for native SDK generate", {
|
|
2166
|
-
toolCount: functionDeclarations.length,
|
|
2167
|
-
toolNames: functionDeclarations.map((t) => t.name),
|
|
2162
|
+
toolCount: declared.toolsConfig[0].functionDeclarations.length,
|
|
2163
|
+
toolNames: declared.toolsConfig[0].functionDeclarations.map((t) => t.name),
|
|
2168
2164
|
});
|
|
2169
2165
|
}
|
|
2170
2166
|
// Check if we need to use the final_result tool pattern for structured output with tools
|
|
@@ -3374,7 +3370,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
3374
3370
|
: maxSteps;
|
|
3375
3371
|
const allToolCalls = [];
|
|
3376
3372
|
const toolExecutions = [];
|
|
3377
|
-
const channel =
|
|
3373
|
+
const channel = createStreamChannel();
|
|
3378
3374
|
// Mutable holders the StreamResult references. Background loop updates
|
|
3379
3375
|
// these as state progresses; consumer reads them after iterating the
|
|
3380
3376
|
// stream to completion (channel.close() is called AFTER mutations).
|
|
@@ -3593,7 +3589,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
3593
3589
|
firstDeltaSeen = true;
|
|
3594
3590
|
generationSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_COMPLETION_START_TIME, new Date().toISOString());
|
|
3595
3591
|
}
|
|
3596
|
-
channel.push(delta);
|
|
3592
|
+
channel.push({ content: delta });
|
|
3597
3593
|
liveTextPushedLength += delta.length;
|
|
3598
3594
|
}
|
|
3599
3595
|
});
|
|
@@ -3694,7 +3690,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
3694
3690
|
const finalResultCall = toolUseBlocks.find((block) => block.name === "final_result");
|
|
3695
3691
|
if (finalResultCall) {
|
|
3696
3692
|
structuredOutputRef.value = finalResultCall.input;
|
|
3697
|
-
channel.push(JSON.stringify(finalResultCall.input));
|
|
3693
|
+
channel.push({ content: JSON.stringify(finalResultCall.input) });
|
|
3698
3694
|
modelFinished = true;
|
|
3699
3695
|
logger.debug("[GoogleVertex] Extracted structured output from final_result tool (stream)", { keys: Object.keys(finalResultCall.input) });
|
|
3700
3696
|
break;
|
|
@@ -4052,7 +4048,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4052
4048
|
maxSteps,
|
|
4053
4049
|
toolCallCount: externalToolCallCount,
|
|
4054
4050
|
});
|
|
4055
|
-
channel.push(exitMessage);
|
|
4051
|
+
channel.push({ content: exitMessage });
|
|
4056
4052
|
aggregatedTurnText = exitMessage;
|
|
4057
4053
|
}
|
|
4058
4054
|
}
|
|
@@ -4117,7 +4113,9 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4117
4113
|
const forcedFinalResult = response.content.find((block) => block.type === "tool_use" && block.name === "final_result");
|
|
4118
4114
|
if (forcedFinalResult) {
|
|
4119
4115
|
structuredOutputRef.value = forcedFinalResult.input;
|
|
4120
|
-
channel.push(
|
|
4116
|
+
channel.push({
|
|
4117
|
+
content: JSON.stringify(forcedFinalResult.input),
|
|
4118
|
+
});
|
|
4121
4119
|
synthesizedFinalAnswer = true;
|
|
4122
4120
|
logger.debug("[GoogleVertex] Forced finalization returned structured output (stream)", { keys: Object.keys(forcedFinalResult.input) });
|
|
4123
4121
|
}
|
|
@@ -4125,7 +4123,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4125
4123
|
const capMessage = hitContextLimit
|
|
4126
4124
|
? buildContextCapMessage(externalToolCallCount)
|
|
4127
4125
|
: buildToolLoopCapMessage(maxSteps, externalToolCallCount);
|
|
4128
|
-
channel.push(capMessage);
|
|
4126
|
+
channel.push({ content: capMessage });
|
|
4129
4127
|
aggregatedTurnText += capMessage;
|
|
4130
4128
|
}
|
|
4131
4129
|
}
|
|
@@ -4151,7 +4149,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4151
4149
|
maxSteps,
|
|
4152
4150
|
toolCallCount: externalToolCallCount,
|
|
4153
4151
|
});
|
|
4154
|
-
channel.push(exitMessage);
|
|
4152
|
+
channel.push({ content: exitMessage });
|
|
4155
4153
|
aggregatedTurnText += exitMessage;
|
|
4156
4154
|
}
|
|
4157
4155
|
}
|
|
@@ -4222,14 +4220,14 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4222
4220
|
.join("");
|
|
4223
4221
|
if (backstopText) {
|
|
4224
4222
|
synthesizedFinalAnswer = true;
|
|
4225
|
-
channel.push(backstopText);
|
|
4223
|
+
channel.push({ content: backstopText });
|
|
4226
4224
|
aggregatedTurnText = backstopText;
|
|
4227
4225
|
}
|
|
4228
4226
|
else {
|
|
4229
4227
|
const capMessage = hitContextLimit
|
|
4230
4228
|
? buildContextCapMessage(externalToolCallCount)
|
|
4231
4229
|
: buildToolLoopCapMessage(maxSteps, externalToolCallCount);
|
|
4232
|
-
channel.push(capMessage);
|
|
4230
|
+
channel.push({ content: capMessage });
|
|
4233
4231
|
aggregatedTurnText = capMessage;
|
|
4234
4232
|
}
|
|
4235
4233
|
}
|
|
@@ -4255,7 +4253,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4255
4253
|
maxSteps,
|
|
4256
4254
|
toolCallCount: externalToolCallCount,
|
|
4257
4255
|
});
|
|
4258
|
-
channel.push(exitMessage);
|
|
4256
|
+
channel.push({ content: exitMessage });
|
|
4259
4257
|
aggregatedTurnText = exitMessage;
|
|
4260
4258
|
}
|
|
4261
4259
|
}
|
|
@@ -4281,7 +4279,7 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
4281
4279
|
maxSteps,
|
|
4282
4280
|
toolCallCount: externalToolCallTotal,
|
|
4283
4281
|
});
|
|
4284
|
-
channel.push(exitMessage);
|
|
4282
|
+
channel.push({ content: exitMessage });
|
|
4285
4283
|
aggregatedTurnText = exitMessage;
|
|
4286
4284
|
}
|
|
4287
4285
|
// Honest finish reason (same mapping as the generate twin): "length"
|
|
@@ -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;
|
|
@@ -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/lib/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,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
|
+
};
|
|
@@ -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,12 @@
|
|
|
1
|
+
import type Anthropic from "@anthropic-ai/sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Read an Anthropic cache breakpoint from a message/part/tool carrier.
|
|
4
|
+
* MessageBuilder marks system messages (and GenerationHandler marks the last
|
|
5
|
+
* tool definition) with `providerOptions.anthropic.cacheControl` — the
|
|
6
|
+
* AI-SDK-era prompt-caching contract this native path must keep honoring.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from anthropic/client.ts so `src/lib/core/nativeToolFormat.ts`
|
|
9
|
+
* can share it without importing the provider client (which would create a
|
|
10
|
+
* circular import: client.ts -> core/nativeToolFormat.ts -> client.ts).
|
|
11
|
+
*/
|
|
12
|
+
export declare const cacheControlOf: (carrier: unknown) => Anthropic.Messages.CacheControlEphemeral | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read an Anthropic cache breakpoint from a message/part/tool carrier.
|
|
3
|
+
* MessageBuilder marks system messages (and GenerationHandler marks the last
|
|
4
|
+
* tool definition) with `providerOptions.anthropic.cacheControl` — the
|
|
5
|
+
* AI-SDK-era prompt-caching contract this native path must keep honoring.
|
|
6
|
+
*
|
|
7
|
+
* Extracted from anthropic/client.ts so `src/lib/core/nativeToolFormat.ts`
|
|
8
|
+
* can share it without importing the provider client (which would create a
|
|
9
|
+
* circular import: client.ts -> core/nativeToolFormat.ts -> client.ts).
|
|
10
|
+
*/
|
|
11
|
+
export const cacheControlOf = (carrier) => {
|
|
12
|
+
const cc = carrier?.providerOptions?.anthropic?.cacheControl;
|
|
13
|
+
return cc?.type === "ephemeral" ? { type: "ephemeral" } : undefined;
|
|
14
|
+
};
|