@juspay/neurolink 12.14.16 → 12.14.18
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.
|
@@ -264,14 +264,30 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
264
264
|
provider: this.getProviderName(),
|
|
265
265
|
...(finishReason !== undefined && { finishReason }),
|
|
266
266
|
...(rawFinishReason !== undefined && { rawFinishReason }),
|
|
267
|
-
toolsUsed
|
|
267
|
+
// `toolsUsed` means RAN, not "was asked for". `runAgenticLoop` records
|
|
268
|
+
// every dispatch it performed, including the ones that never reached a
|
|
269
|
+
// tool: a name the model invented (TOOL_NOT_FOUND), one the breaker had
|
|
270
|
+
// already given up on (TOOL_PERMANENTLY_FAILED), and one that threw.
|
|
271
|
+
// Exactly those carry `error`; a call that reached the tool and got a
|
|
272
|
+
// value back does not. That is the same line `nativeGenerateLoop` draws
|
|
273
|
+
// — its `toolsUsed.push(name)` sits inside the try, after the guarded
|
|
274
|
+
// call returns — so filtering here makes Bedrock's generate path report
|
|
275
|
+
// what every other generate path reports, instead of inflating
|
|
276
|
+
// analytics, cost attribution and audit with calls that never ran.
|
|
277
|
+
//
|
|
278
|
+
// `toolCalls` and `toolExecutions` stay complete on purpose: they are
|
|
279
|
+
// the record of what the turn ATTEMPTED, and a failed attempt is
|
|
280
|
+
// precisely what a caller debugging a turn needs to see.
|
|
281
|
+
toolsUsed: toolExecutions
|
|
282
|
+
.filter((execution) => execution.error === undefined)
|
|
283
|
+
.map((execution) => execution.name),
|
|
268
284
|
toolCalls: toolExecutions.map((execution) => ({
|
|
269
285
|
toolCallId: execution.id,
|
|
270
286
|
toolName: execution.name,
|
|
271
287
|
args: execution.input,
|
|
272
288
|
})),
|
|
273
289
|
toolExecutions: resolveToolExecutionRecords(options, transformToolExecutions(toolExecutions)),
|
|
274
|
-
enhancedWithTools: toolExecutions.
|
|
290
|
+
enhancedWithTools: toolExecutions.some((execution) => execution.error === undefined),
|
|
275
291
|
};
|
|
276
292
|
}
|
|
277
293
|
async conversationLoop(options) {
|
|
@@ -983,7 +999,15 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
983
999
|
// alone left every streamed Bedrock turn reporting no tool calls,
|
|
984
1000
|
// however many it made.
|
|
985
1001
|
toolExecutions: outcome.result?.toolExecutions ?? [],
|
|
986
|
-
|
|
1002
|
+
// Same "ran, not asked for" rule as the generate path above.
|
|
1003
|
+
// `toolCallCount` still derives from the unfiltered
|
|
1004
|
+
// `toolExecutions`, which is correct — a dispatch that failed was
|
|
1005
|
+
// still a call — so this list is a fallback today rather than an
|
|
1006
|
+
// observable surface. It is filtered anyway so that the moment
|
|
1007
|
+
// anything does surface it, it is not surfacing the same lie.
|
|
1008
|
+
toolsUsed: (outcome.result?.toolExecutions ?? [])
|
|
1009
|
+
.filter((execution) => execution.error === undefined)
|
|
1010
|
+
.map((execution) => execution.name),
|
|
987
1011
|
}, Date.now() - startTime, {
|
|
988
1012
|
requestId: `bedrock-stream-${Date.now()}`,
|
|
989
1013
|
streamingMode: true,
|
|
@@ -25,17 +25,40 @@ function asNonEmptyString(value) {
|
|
|
25
25
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
26
26
|
}
|
|
27
27
|
function buildSystemInstructions(body) {
|
|
28
|
+
const instructions = [];
|
|
28
29
|
if (typeof body.system === "string") {
|
|
29
|
-
|
|
30
|
+
if (body.system) {
|
|
31
|
+
instructions.push(body.system);
|
|
32
|
+
}
|
|
30
33
|
}
|
|
31
|
-
if (Array.isArray(body.system)) {
|
|
34
|
+
else if (Array.isArray(body.system)) {
|
|
32
35
|
const text = body.system
|
|
33
36
|
.map((block) => (typeof block.text === "string" ? block.text : ""))
|
|
34
37
|
.filter(Boolean)
|
|
35
38
|
.join("\n\n");
|
|
36
|
-
|
|
39
|
+
if (text) {
|
|
40
|
+
instructions.push(text);
|
|
41
|
+
}
|
|
37
42
|
}
|
|
38
|
-
|
|
43
|
+
for (const message of body.messages) {
|
|
44
|
+
// Claude's public Messages type restricts message roles to user/assistant,
|
|
45
|
+
// but Claude Code can emit an inline system message for context-management
|
|
46
|
+
// edits. Preserve its text as instructions instead of sending a non-leading
|
|
47
|
+
// system item to the Codex conversation input.
|
|
48
|
+
if (message.role !== "system") {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const text = typeof message.content === "string"
|
|
52
|
+
? message.content
|
|
53
|
+
: message.content
|
|
54
|
+
.map((block) => (block.type === "text" ? block.text : ""))
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
.join("\n");
|
|
57
|
+
if (text) {
|
|
58
|
+
instructions.push(text);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return instructions.length > 0 ? instructions.join("\n\n") : undefined;
|
|
39
62
|
}
|
|
40
63
|
function imageUrlForBlock(block) {
|
|
41
64
|
if (block.source.type === "url" && block.source.url) {
|
|
@@ -126,14 +149,26 @@ function convertClaudeMessage(role, content) {
|
|
|
126
149
|
});
|
|
127
150
|
continue;
|
|
128
151
|
}
|
|
129
|
-
|
|
152
|
+
// Claude Code context-management messages can contain `tool_addition`
|
|
153
|
+
// blocks. The live tool definitions are already carried by `body.tools`;
|
|
154
|
+
// these history markers must not become undefined array entries because
|
|
155
|
+
// JSON encodes array undefined values as null and Codex rejects them.
|
|
156
|
+
if (block.type === "tool_addition") {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const contentPart = toCodexContentPart(block, role);
|
|
160
|
+
if (contentPart) {
|
|
161
|
+
messageContent.push(contentPart);
|
|
162
|
+
}
|
|
130
163
|
}
|
|
131
164
|
flushMessage();
|
|
132
165
|
return input;
|
|
133
166
|
}
|
|
134
167
|
/** Convert a Claude Messages request into the ChatGPT Codex Responses shape. */
|
|
135
168
|
export function convertClaudeRequestToCodex(body, model, reasoningEffort) {
|
|
136
|
-
const input = body.messages.flatMap((message) =>
|
|
169
|
+
const input = body.messages.flatMap((message) => message.role === "system"
|
|
170
|
+
? []
|
|
171
|
+
: convertClaudeMessage(message.role, message.content));
|
|
137
172
|
const request = {
|
|
138
173
|
model,
|
|
139
174
|
input,
|
package/dist/types/config.d.ts
CHANGED
|
@@ -510,11 +510,16 @@ export type CreateThinkingConfigOptions = {
|
|
|
510
510
|
* Native SDK thinkingConfig structure for Gemini native SDK.
|
|
511
511
|
*
|
|
512
512
|
* `thinkingLevel` and `thinkingBudget` are mutually exclusive on the wire:
|
|
513
|
-
* Gemini 3 models accept `thinkingLevel`; Gemini 2.5
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
513
|
+
* Gemini 3 models accept `thinkingLevel`; Gemini 2.5 models reject it outright
|
|
514
|
+
* with INVALID_ARGUMENT "thinking_level not supported by this model" and
|
|
515
|
+
* require the numeric `thinkingBudget` instead. Gemini 2.5 is also the only
|
|
516
|
+
* family `createNativeThinkingConfig` emits a budget for:
|
|
517
|
+
* `getGemini25ThinkingBudgetRange` has no verified range for anything earlier,
|
|
518
|
+
* so those models get no `thinkingConfig` at all — and a one-time WARN —
|
|
519
|
+
* rather than a guessed shape that might itself 400.
|
|
520
|
+
*
|
|
521
|
+
* Both fields are optional here so a single type can represent either shape —
|
|
522
|
+
* callers building the request pick whichever field the target model accepts.
|
|
518
523
|
*/
|
|
519
524
|
export type NativeThinkingConfig = {
|
|
520
525
|
includeThoughts: boolean;
|