@juspay/neurolink 12.14.15 → 12.14.16
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 -2
- package/dist/browser/neurolink.min.js +382 -382
- package/dist/core/baseProvider.js +34 -6
- package/dist/models/manifests/vertex.js +6 -2
- package/dist/neurolink.js +39 -9
- package/dist/providers/anthropic/loopAdapter.js +13 -0
- package/dist/providers/googleNativeGemini3/utils.d.ts +5 -1
- package/dist/providers/googleNativeGemini3/utils.js +9 -2
- package/dist/providers/googleVertex/client.d.ts +48 -0
- package/dist/providers/googleVertex/client.js +221 -17
- package/dist/types/config.d.ts +12 -2
- package/dist/types/generate.d.ts +18 -9
- package/dist/utils/modelDetection.d.ts +10 -0
- package/dist/utils/modelDetection.js +38 -0
- package/dist/utils/streamResultAccessors.d.ts +38 -0
- package/dist/utils/streamResultAccessors.js +55 -0
- package/dist/utils/thinkingConfig.d.ts +21 -2
- package/dist/utils/thinkingConfig.js +62 -3
- package/package.json +5 -1
|
@@ -31,7 +31,7 @@ import { attachStreamCancel, cancelStream, releaseIterator, } from "../utils/str
|
|
|
31
31
|
import { TimeoutError as AsyncTimeoutError, withTimeoutFn, } from "../utils/async/withTimeout.js";
|
|
32
32
|
import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
33
33
|
import { shouldDisableBuiltinTools } from "../utils/toolUtils.js";
|
|
34
|
-
import { getKeyCount, getKeysAsString } from "../utils/transformationUtils.js";
|
|
34
|
+
import { getKeyCount, getKeysAsString, transformToolExecutions, } from "../utils/transformationUtils.js";
|
|
35
35
|
import { ToolExecutionRecorder } from "./toolExecutionRecorder.js";
|
|
36
36
|
import { TTS_ERROR_CODES, TTSProcessor } from "../utils/ttsProcessor.js";
|
|
37
37
|
import { executeVideoAnalysis, hasVideoFrames, } from "../utils/videoAnalysisProcessor.js";
|
|
@@ -48,6 +48,7 @@ import { Utilities } from "./modules/Utilities.js";
|
|
|
48
48
|
import { generateOnceNative } from "../utils/nativeSingleShot.js";
|
|
49
49
|
import { validateExecutionControl } from "../utils/parameterValidation.js";
|
|
50
50
|
import { extractTokenUsage } from "../utils/tokenUtils.js";
|
|
51
|
+
import { preserveLiveStreamAccessors } from "../utils/streamResultAccessors.js";
|
|
51
52
|
/**
|
|
52
53
|
* Read the consumer-facing lifecycle callbacks buried inside a request's
|
|
53
54
|
* middleware blob. The parameter is `unknown` on purpose: request options
|
|
@@ -523,10 +524,14 @@ export class BaseProvider {
|
|
|
523
524
|
cancelStream(activeStream);
|
|
524
525
|
releaseIterator(activeIterator);
|
|
525
526
|
});
|
|
526
|
-
|
|
527
|
+
// A naked spread reads (and thereby snapshots) every enumerable getter
|
|
528
|
+
// on `result` — including a provider's lazily-populated `toolsUsed` /
|
|
529
|
+
// `toolExecutions` — before the consumer has pulled a single chunk.
|
|
530
|
+
// Re-applying the original accessor descriptors keeps those fields live.
|
|
531
|
+
return preserveLiveStreamAccessors(result, {
|
|
527
532
|
...result,
|
|
528
533
|
stream: wrapped,
|
|
529
|
-
};
|
|
534
|
+
});
|
|
530
535
|
}
|
|
531
536
|
/**
|
|
532
537
|
* The eager half of the retired-model stream fallback, for providers whose
|
|
@@ -688,7 +693,12 @@ export class BaseProvider {
|
|
|
688
693
|
cancelStream(originalStream);
|
|
689
694
|
releaseIterator(upstreamIterator);
|
|
690
695
|
});
|
|
691
|
-
|
|
696
|
+
// See the comment in withStreamModelFallback above: this spread must not
|
|
697
|
+
// be allowed to freeze a provider's lazy toolsUsed/toolExecutions getters.
|
|
698
|
+
return preserveLiveStreamAccessors(result, {
|
|
699
|
+
...result,
|
|
700
|
+
stream: wrappedStream,
|
|
701
|
+
});
|
|
692
702
|
}
|
|
693
703
|
/**
|
|
694
704
|
* Fire the consumer-supplied onError callback before throwing. Used in
|
|
@@ -891,7 +901,19 @@ export class BaseProvider {
|
|
|
891
901
|
}
|
|
892
902
|
: undefined;
|
|
893
903
|
// Create a synthetic stream from the generate result that simulates progressive delivery
|
|
894
|
-
|
|
904
|
+
//
|
|
905
|
+
// toolsUsed/toolExecutions: generate()'s result carries both once the
|
|
906
|
+
// tool round trip settles, but a plain field list (like every other
|
|
907
|
+
// field above) would silently drop them from the fake-streaming
|
|
908
|
+
// StreamResult. toolsUsed overlaps generate()'s and StreamResult's
|
|
909
|
+
// declared types exactly, so it is assigned directly; toolExecutions
|
|
910
|
+
// does not (GenerateResult carries ToolExecutionRecord[], StreamResult
|
|
911
|
+
// declares ToolExecutionSummary[] but every other live producer of this
|
|
912
|
+
// field actually returns transformToolExecutions()'s
|
|
913
|
+
// {name,input,output,duration} shape) — attached via defineProperty,
|
|
914
|
+
// the same bypass `createMCPStream()` uses, rather than a literal that
|
|
915
|
+
// would fail the structural check or need a banned double-cast.
|
|
916
|
+
return Object.defineProperty({
|
|
895
917
|
stream: this.createFakeStreamingOutput(result, options, onTTSComplete),
|
|
896
918
|
usage: result?.usage,
|
|
897
919
|
provider: result?.provider,
|
|
@@ -916,7 +938,13 @@ export class BaseProvider {
|
|
|
916
938
|
evaluation: result?.evaluation,
|
|
917
939
|
audio,
|
|
918
940
|
ttsMetadata,
|
|
919
|
-
|
|
941
|
+
toolsUsed: result?.toolsUsed,
|
|
942
|
+
}, "toolExecutions", {
|
|
943
|
+
value: transformToolExecutions(result?.toolExecutions),
|
|
944
|
+
enumerable: true,
|
|
945
|
+
configurable: true,
|
|
946
|
+
writable: true,
|
|
947
|
+
});
|
|
920
948
|
}
|
|
921
949
|
catch (error) {
|
|
922
950
|
logger.error(`Fake streaming fallback failed for ${this.providerName}:`, error);
|
|
@@ -11,8 +11,12 @@ export const vertexManifest = {
|
|
|
11
11
|
aliases: [],
|
|
12
12
|
contextWindow: 1048576,
|
|
13
13
|
maxOutputTokens: 64000,
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
// Measured against live Vertex, every served model in this project —
|
|
15
|
+
// gemini-2.5-flash / -pro / -flash-lite, claude-sonnet-4-6 and
|
|
16
|
+
// claude-sonnet-4-5@20250929 — accepted image and PDF input and
|
|
17
|
+
// returned tool calls. Declaring false here contradicted the wire.
|
|
18
|
+
vision: true,
|
|
19
|
+
functionCalling: true,
|
|
16
20
|
},
|
|
17
21
|
},
|
|
18
22
|
};
|
package/dist/neurolink.js
CHANGED
|
@@ -82,6 +82,7 @@ import { hasLifecycleErrorFired, markLifecycleErrorFired, } from "./utils/lifecy
|
|
|
82
82
|
import { interleaveTTSStream } from "./utils/ttsStream.js";
|
|
83
83
|
import { resolveLifecycleTimeoutMs } from "./utils/lifecycleTimeout.js";
|
|
84
84
|
import { cloneOptionsForCallIsolation } from "./utils/cloneOptions.js";
|
|
85
|
+
import { pickLiveStreamDescriptors, preserveLiveStreamAccessors, } from "./utils/streamResultAccessors.js";
|
|
85
86
|
import { coerceJsonToSchema, recoverScalarRoot, schemaAccepts, } from "./utils/json/coerce.js";
|
|
86
87
|
// Factory processing imports
|
|
87
88
|
import { createCleanStreamOptions, enhanceTextGenerationOptions, processFactoryOptions, processStreamingFactoryOptions, validateFactoryConfig, } from "./utils/factoryProcessing.js";
|
|
@@ -6873,10 +6874,17 @@ Current user's request: ${currentInput}`;
|
|
|
6873
6874
|
// the inner loop. We only get here if the loop didn't return.
|
|
6874
6875
|
throw new Error(`[NeuroLink.stream] iteration fallback exhausted ${maxAttempts} attempts`);
|
|
6875
6876
|
})();
|
|
6876
|
-
|
|
6877
|
+
// `result`'s toolsUsed/toolExecutions may be live getters (openai-compat
|
|
6878
|
+
// providers back them with a getter over an array still being populated
|
|
6879
|
+
// by a background loop) — a naked spread here would read them once, now,
|
|
6880
|
+
// and freeze whatever they held at that instant. preserveLiveStreamAccessors
|
|
6881
|
+
// re-applies the original getter descriptors onto the rebuilt object, the
|
|
6882
|
+
// same fix already applied to withStreamModelFallback/
|
|
6883
|
+
// wrapStreamWithLifecycleCallbacks in baseProvider.ts.
|
|
6884
|
+
return preserveLiveStreamAccessors(result, {
|
|
6877
6885
|
...result,
|
|
6878
6886
|
stream: wrappedStream,
|
|
6879
|
-
};
|
|
6887
|
+
});
|
|
6880
6888
|
}
|
|
6881
6889
|
async executeStreamRequest(options) {
|
|
6882
6890
|
// Dynamic argument resolution — resolve any function-valued options before downstream use
|
|
@@ -7567,7 +7575,12 @@ Current user's request: ${currentInput}`;
|
|
|
7567
7575
|
factoryResult,
|
|
7568
7576
|
sessionId: enhancedOptions.context?.sessionId,
|
|
7569
7577
|
});
|
|
7570
|
-
|
|
7578
|
+
// Kept whole (not just destructured) so its toolsUsed/toolExecutions
|
|
7579
|
+
// descriptors can be re-applied onto the final StreamResult near the
|
|
7580
|
+
// bottom of this method, without ever reading — and thereby freezing —
|
|
7581
|
+
// a getter-based provider's value here.
|
|
7582
|
+
const mcpStreamOutcome = await this.createMCPStream(enhancedOptions);
|
|
7583
|
+
const { stream: mcpStream, provider: providerName, usage: streamUsage, model: streamModel, finishReason: streamFinishReason, toolCalls: streamToolCalls, toolResults: streamToolResults, analytics: streamAnalytics, metadata: providerStreamMetadata, } = mcpStreamOutcome;
|
|
7571
7584
|
let streamedTTSResult;
|
|
7572
7585
|
const { stream: incrementalStream, ttsMetadata: streamTtsMetadata } = await this.createIncrementalTTSStream({
|
|
7573
7586
|
stream: mcpStream,
|
|
@@ -7934,6 +7947,7 @@ Current user's request: ${currentInput}`;
|
|
|
7934
7947
|
error: metadata.error,
|
|
7935
7948
|
events: eventSequence,
|
|
7936
7949
|
providerMetadata: providerStreamMetadata,
|
|
7950
|
+
toolTelemetrySource: mcpStreamOutcome,
|
|
7937
7951
|
});
|
|
7938
7952
|
}
|
|
7939
7953
|
catch (error) {
|
|
@@ -8731,7 +8745,11 @@ Current user's request: ${currentInput}`;
|
|
|
8731
8745
|
throw streamConsumeErr;
|
|
8732
8746
|
}
|
|
8733
8747
|
})();
|
|
8734
|
-
|
|
8748
|
+
// toolsUsed/toolExecutions are attached via defineProperties (not
|
|
8749
|
+
// listed as plain fields above) so a getter-based provider result
|
|
8750
|
+
// keeps resolving lazily through this boundary instead of being
|
|
8751
|
+
// read — and frozen — once, right here, before any chunk is drained.
|
|
8752
|
+
return Object.defineProperties({
|
|
8735
8753
|
stream: wrappedStream,
|
|
8736
8754
|
provider: poolStreamProviderName,
|
|
8737
8755
|
usage: poolStreamResult.usage,
|
|
@@ -8741,7 +8759,10 @@ Current user's request: ${currentInput}`;
|
|
|
8741
8759
|
toolResults: poolStreamResult.toolResults ?? [],
|
|
8742
8760
|
analytics: poolStreamResult.analytics,
|
|
8743
8761
|
metadata: poolStreamResult.metadata,
|
|
8744
|
-
}
|
|
8762
|
+
}, pickLiveStreamDescriptors(poolStreamResult, [
|
|
8763
|
+
"toolsUsed",
|
|
8764
|
+
"toolExecutions",
|
|
8765
|
+
]));
|
|
8745
8766
|
}
|
|
8746
8767
|
catch (poolStreamError) {
|
|
8747
8768
|
if (isAbortError(poolStreamError)) {
|
|
@@ -8785,7 +8806,11 @@ Current user's request: ${currentInput}`;
|
|
|
8785
8806
|
provider: providerName,
|
|
8786
8807
|
systemPromptPassedLength: enhancedSystemPrompt.length,
|
|
8787
8808
|
});
|
|
8788
|
-
|
|
8809
|
+
// toolsUsed/toolExecutions are attached via defineProperties, not listed
|
|
8810
|
+
// as plain fields: see the identical comment on the ModelPool branch
|
|
8811
|
+
// above — a plain `toolsUsed: streamResult.toolsUsed` here would invoke
|
|
8812
|
+
// and freeze a getter-based provider's value before any chunk is drained.
|
|
8813
|
+
return Object.defineProperties({
|
|
8789
8814
|
stream: streamResult.stream,
|
|
8790
8815
|
provider: providerName,
|
|
8791
8816
|
usage: streamResult.usage,
|
|
@@ -8800,7 +8825,7 @@ Current user's request: ${currentInput}`;
|
|
|
8800
8825
|
// the loop finishes — snapshotting fields here would freeze them as
|
|
8801
8826
|
// undefined before the stream is drained.
|
|
8802
8827
|
metadata: streamResult.metadata,
|
|
8803
|
-
};
|
|
8828
|
+
}, pickLiveStreamDescriptors(streamResult, ["toolsUsed", "toolExecutions"]));
|
|
8804
8829
|
}
|
|
8805
8830
|
/**
|
|
8806
8831
|
* Process stream result
|
|
@@ -8831,7 +8856,7 @@ Current user's request: ${currentInput}`;
|
|
|
8831
8856
|
* Create stream response
|
|
8832
8857
|
*/
|
|
8833
8858
|
createStreamResponse(streamResult, stream, config) {
|
|
8834
|
-
return {
|
|
8859
|
+
return Object.defineProperties({
|
|
8835
8860
|
stream,
|
|
8836
8861
|
provider: config.providerName,
|
|
8837
8862
|
model: config.options.model,
|
|
@@ -8850,7 +8875,12 @@ Current user's request: ${currentInput}`;
|
|
|
8850
8875
|
guardrailsBlocked: config.guardrailsBlocked,
|
|
8851
8876
|
error: config.error,
|
|
8852
8877
|
}),
|
|
8853
|
-
}
|
|
8878
|
+
}, config.toolTelemetrySource
|
|
8879
|
+
? pickLiveStreamDescriptors(config.toolTelemetrySource, [
|
|
8880
|
+
"toolsUsed",
|
|
8881
|
+
"toolExecutions",
|
|
8882
|
+
])
|
|
8883
|
+
: {});
|
|
8854
8884
|
}
|
|
8855
8885
|
/**
|
|
8856
8886
|
* Handle stream error with fallback
|
|
@@ -77,6 +77,11 @@ async function readAnthropicStep({ params, client, channel, stepSignal, requestT
|
|
|
77
77
|
let cacheWrite5mTokens = 0;
|
|
78
78
|
let cacheWrite1hTokens = 0;
|
|
79
79
|
let stepOutputTokens = 0;
|
|
80
|
+
// Thinking tokens are a SUBSET of output_tokens (Anthropic bills them as
|
|
81
|
+
// part of the same total), so this is tracked separately for
|
|
82
|
+
// observability and never added into outputTokens above.
|
|
83
|
+
let reasoningTokens = 0;
|
|
84
|
+
let stepReasoningTokens = 0;
|
|
80
85
|
// Anthropic closes every complete message with `message_stop`. Its
|
|
81
86
|
// absence is the only signal that the response ended early, because the
|
|
82
87
|
// content blocks that DID arrive are syntactically complete.
|
|
@@ -96,6 +101,9 @@ async function readAnthropicStep({ params, client, channel, stepSignal, requestT
|
|
|
96
101
|
const startOutput = usage?.output_tokens ?? 0;
|
|
97
102
|
outputTokens += startOutput - stepOutputTokens;
|
|
98
103
|
stepOutputTokens = startOutput;
|
|
104
|
+
const startReasoning = usage?.output_tokens_details?.thinking_tokens ?? 0;
|
|
105
|
+
reasoningTokens += startReasoning - stepReasoningTokens;
|
|
106
|
+
stepReasoningTokens = startReasoning;
|
|
99
107
|
// Anthropic reports cache reads/writes separately from input_tokens
|
|
100
108
|
// on this same event; without these the stream drops all cache
|
|
101
109
|
// accounting.
|
|
@@ -186,6 +194,10 @@ async function readAnthropicStep({ params, client, channel, stepSignal, requestT
|
|
|
186
194
|
const cumulative = event.usage?.output_tokens ?? stepOutputTokens;
|
|
187
195
|
outputTokens += cumulative - stepOutputTokens;
|
|
188
196
|
stepOutputTokens = cumulative;
|
|
197
|
+
const cumulativeReasoning = event.usage?.output_tokens_details?.thinking_tokens ??
|
|
198
|
+
stepReasoningTokens;
|
|
199
|
+
reasoningTokens += cumulativeReasoning - stepReasoningTokens;
|
|
200
|
+
stepReasoningTokens = cumulativeReasoning;
|
|
189
201
|
continue;
|
|
190
202
|
}
|
|
191
203
|
if (event.type === "message_stop") {
|
|
@@ -327,6 +339,7 @@ async function readAnthropicStep({ params, client, channel, stepSignal, requestT
|
|
|
327
339
|
// in that tier".
|
|
328
340
|
...(cacheWrite5mTokens ? { cacheWrite5mTokens } : {}),
|
|
329
341
|
...(cacheWrite1hTokens ? { cacheWrite1hTokens } : {}),
|
|
342
|
+
...(reasoningTokens ? { reasoningTokens } : {}),
|
|
330
343
|
},
|
|
331
344
|
rawStopReason,
|
|
332
345
|
raw: blocks,
|
|
@@ -68,7 +68,11 @@ export declare function buildNativeConfig(options: {
|
|
|
68
68
|
temperature?: number;
|
|
69
69
|
maxTokens?: number;
|
|
70
70
|
systemPrompt?: string;
|
|
71
|
-
/**
|
|
71
|
+
/**
|
|
72
|
+
* Model id, used for the registry-driven sampling-param strip and to
|
|
73
|
+
* pick the right thinkingConfig wire shape (thinkingLevel for Gemini 3,
|
|
74
|
+
* a translated numeric thinkingBudget for Gemini 2.5).
|
|
75
|
+
*/
|
|
72
76
|
model?: string;
|
|
73
77
|
thinkingConfig?: ThinkingConfig;
|
|
74
78
|
/**
|
|
@@ -435,8 +435,15 @@ export function buildNativeConfig(options, toolsConfig) {
|
|
|
435
435
|
if (options.systemPrompt) {
|
|
436
436
|
config.systemInstruction = options.systemPrompt;
|
|
437
437
|
}
|
|
438
|
-
// Add thinking config
|
|
439
|
-
|
|
438
|
+
// Add thinking config. `options.model` is the resolved model id (both
|
|
439
|
+
// call sites in googleAiStudio/client.ts pass their effective `modelName`
|
|
440
|
+
// in) — createNativeThinkingConfig picks the wire shape from it: Gemini 3
|
|
441
|
+
// gets thinkingLevel passthrough, Gemini 2.5 gets a translated numeric
|
|
442
|
+
// thinkingBudget (see thinkingConfig.ts). Mirrors the Vertex call sites
|
|
443
|
+
// in googleVertex/client.ts, which this native path was previously
|
|
444
|
+
// missing — Google AI Studio's identical native SDK rejects
|
|
445
|
+
// thinkingLevel on Gemini 2.5 exactly like Vertex does.
|
|
446
|
+
const nativeThinkingConfig = createNativeThinkingConfig(options.thinkingConfig, options.model);
|
|
440
447
|
if (nativeThinkingConfig) {
|
|
441
448
|
config.thinkingConfig = nativeThinkingConfig;
|
|
442
449
|
}
|
|
@@ -202,6 +202,43 @@ export declare class GoogleVertexProvider extends BaseProvider {
|
|
|
202
202
|
* Execute stream using native @anthropic-ai/vertex-sdk for Claude models on Vertex AI
|
|
203
203
|
* This bypasses @ai-sdk/google-vertex completely and uses Anthropic's native SDK
|
|
204
204
|
*/
|
|
205
|
+
/**
|
|
206
|
+
* Extended thinking for Claude-on-Vertex.
|
|
207
|
+
*
|
|
208
|
+
* The direct Anthropic provider has always translated `thinkingConfig` into
|
|
209
|
+
* the Messages API's `thinking` field (anthropic/client.ts). This path never
|
|
210
|
+
* did — it built the request without one — so `thinkingConfig` was accepted
|
|
211
|
+
* and silently ignored here: no error, `usage.reasoning` 0, no reasoning
|
|
212
|
+
* content. Measured against the raw @anthropic-ai/vertex-sdk with the same
|
|
213
|
+
* project, region, credentials and model, `thinking` is supported and
|
|
214
|
+
* returns a real thinking block, so the capability was ours to send.
|
|
215
|
+
*
|
|
216
|
+
* `thinkingLevel` is deliberately not mapped to a budget: the option's
|
|
217
|
+
* contract reserves `budgetTokens` for Anthropic models and `thinkingLevel`
|
|
218
|
+
* for Gemini 3, and inventing a conversion here would be guessing at the
|
|
219
|
+
* caller's intent.
|
|
220
|
+
*
|
|
221
|
+
* The budget must leave room inside `max_tokens` for an answer, so it is
|
|
222
|
+
* clamped below the ceiling rather than passed through — an over-large
|
|
223
|
+
* budget is a 400 from the API.
|
|
224
|
+
*
|
|
225
|
+
* `useFinalResultTool` (schema / structured-output mode) always pairs with
|
|
226
|
+
* a forced `tool_choice:{type:"any"}` in the request built right after this
|
|
227
|
+
* call — Anthropic hard-rejects `thinking` combined with a `tool_choice`
|
|
228
|
+
* that forces tool use: a live 400, "Thinking may not be enabled when
|
|
229
|
+
* tool_choice forces tool use." So `thinking` is omitted entirely in that
|
|
230
|
+
* mode, preserving the prior (pre-thinking-fix) behaviour of silently
|
|
231
|
+
* ignoring `thinkingConfig` for schema calls instead of hard-failing them —
|
|
232
|
+
* mirrors the same guard already applied to the OAuth proxy path in
|
|
233
|
+
* `src/lib/proxy/oauthFetch.ts` (`delete parsed.thinking` when
|
|
234
|
+
* `tool_choice.type` is `"any"` or `"tool"`). The step/context-cap
|
|
235
|
+
* finalization backstop reuses this same omission for free since it spreads
|
|
236
|
+
* `...requestParams`. `tool_choice:{type:"none"}` (the separate
|
|
237
|
+
* tools-disabled backstop, used only outside schema mode) does not force
|
|
238
|
+
* tool use — it forces the opposite — so it is not gated here, consistent
|
|
239
|
+
* with oauthFetch.ts leaving `"none"` alone too.
|
|
240
|
+
*/
|
|
241
|
+
private buildClaudeThinkingParam;
|
|
205
242
|
private executeNativeAnthropicStream;
|
|
206
243
|
/**
|
|
207
244
|
* Execute generate using native @anthropic-ai/vertex-sdk for Claude models on Vertex AI
|
|
@@ -366,6 +403,17 @@ export declare class GoogleVertexProvider extends BaseProvider {
|
|
|
366
403
|
/**
|
|
367
404
|
* Get model suggestions when a model is not found
|
|
368
405
|
*/
|
|
406
|
+
/**
|
|
407
|
+
* Candidate model ids for a "model not available" error.
|
|
408
|
+
*
|
|
409
|
+
* This list is static. It cannot know what the caller's project and region
|
|
410
|
+
* actually serve, so it must not claim to: it previously announced
|
|
411
|
+
* "always available" and included the requested model itself, which
|
|
412
|
+
* produced errors that recommended the very id that had just failed —
|
|
413
|
+
* `gemini-3-pro-preview-11-2025` suggesting `gemini-3-pro-preview-11-2025`.
|
|
414
|
+
* The requested model is now filtered out, and the wording says these are
|
|
415
|
+
* ids to try rather than ids known to work.
|
|
416
|
+
*/
|
|
369
417
|
private getModelSuggestions;
|
|
370
418
|
/**
|
|
371
419
|
* Generate an embedding for `text` using Vertex via @google/genai.
|