@juspay/neurolink 12.41.7 → 12.41.8
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 +2 -2
- package/dist/browser/neurolink.min.js +1 -1
- package/dist/cli/commands/models.js +16 -1
- package/dist/providers/catalog/fireworks.json +4 -3
- package/dist/utils/modelChoices.d.ts +20 -0
- package/dist/utils/modelChoices.js +37 -4
- package/docs-site/static/search-index.json +3 -3
- package/package.json +2 -1
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { ModelResolver, formatSearchResults, formatRecommendation, formatComparison, } from "../../models/modelResolver.js";
|
|
7
7
|
import { getAllModels, getModelsByProvider, getAvailableProviders, formatModelForDisplay, } from "../../models/modelRegistry.js";
|
|
8
|
+
import { getCatalogJsonEntries } from "../../providers/catalog/loader.js";
|
|
8
9
|
import chalk from "chalk";
|
|
9
10
|
import ora from "ora";
|
|
10
11
|
import { logger } from "../../utils/logger.js";
|
|
@@ -334,9 +335,23 @@ export class ModelsCommandFactory {
|
|
|
334
335
|
try {
|
|
335
336
|
const { AIProviderFactory } = await import("../../core/factory.js");
|
|
336
337
|
const provider = (await AIProviderFactory.createProvider(providerName));
|
|
337
|
-
const
|
|
338
|
+
const rawLiveIds = typeof provider.getAvailableModels === "function"
|
|
338
339
|
? await provider.getAvailableModels()
|
|
339
340
|
: [];
|
|
341
|
+
// Project against the JSON catalog's non-retired ids, mirroring
|
|
342
|
+
// getAllModels()'s listing filter: a catalog-backed provider's
|
|
343
|
+
// vendor `/models` endpoint often keeps listing an id long after
|
|
344
|
+
// it 404s on chat completions (see e.g. fireworks.json's
|
|
345
|
+
// `evidence.liveMatrix`), so an unfiltered live listing would
|
|
346
|
+
// print a retired id as a usable "live" result. Providers with no
|
|
347
|
+
// catalog entry (litellm, ollama, openai-compatible gateways,
|
|
348
|
+
// lm-studio, llamacpp) have nothing to project against, so their
|
|
349
|
+
// live discovery stays unrestricted — that is the whole point of
|
|
350
|
+
// this fallback for them.
|
|
351
|
+
const catalogEntry = getCatalogJsonEntries().find((entry) => entry.id === providerName);
|
|
352
|
+
const liveIds = catalogEntry
|
|
353
|
+
? rawLiveIds.filter((id) => catalogEntry.models.catalog[id]?.status !== "retired")
|
|
354
|
+
: rawLiveIds;
|
|
340
355
|
if (liveIds.length > 0) {
|
|
341
356
|
if (spinner) {
|
|
342
357
|
spinner.succeed(`Found ${liveIds.length} models (live from ${providerName})`);
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"enumMember": "KIMI_K2P6",
|
|
24
24
|
"vision": false,
|
|
25
25
|
"status": "retired",
|
|
26
|
-
"description": "Retired 2026-09 — still on the Fireworks roster, but
|
|
26
|
+
"description": "Retired 2026-09 — still listed on the Fireworks /models roster, but the chat endpoint 404s 'Model not found, inaccessible, and/or not deployed' (since the 2026-09-26 nightly); superseded by kimi-k3, same Moonshot family"
|
|
27
27
|
},
|
|
28
28
|
"accounts/fireworks/models/gpt-oss-120b": {
|
|
29
29
|
"enumMember": "GPT_OSS_120B",
|
|
@@ -107,7 +107,8 @@
|
|
|
107
107
|
"topModels": [
|
|
108
108
|
"accounts/fireworks/models/kimi-k3",
|
|
109
109
|
"accounts/fireworks/models/gpt-oss-120b",
|
|
110
|
-
"accounts/fireworks/models/qwen3p8-max"
|
|
110
|
+
"accounts/fireworks/models/qwen3p8-max",
|
|
111
|
+
"accounts/fireworks/models/glm-5p3"
|
|
111
112
|
]
|
|
112
113
|
},
|
|
113
114
|
"capabilities": {
|
|
@@ -146,7 +147,7 @@
|
|
|
146
147
|
},
|
|
147
148
|
"liveMatrix": {
|
|
148
149
|
"date": "2026-09-28",
|
|
149
|
-
"result": "kimi-k2p6
|
|
150
|
+
"result": "Issue #1796: the 2026-09-26 nightly model-liveness gate reported the default, kimi-k2p6, as dead, sending the matrix vision test down the text-only fallback. Confirmed live — GET /models still lists kimi-k2p6, but POST /chat/completions 404s 'Model not found, inaccessible, and/or not deployed', the same still-listed-but-unservable pattern deepseek-v4-pro hit in 2026-08 (hung past 120s rather than 404ing). Moved the default to kimi-k3, the same Moonshot family's newest generation: 200 OK on both a text-only call and a call carrying a PNG, and a full-length call returns a proper OpenAI-shaped tool_calls entry with finish_reason=tool_calls, confirming vision and tool support both survive the swap. kimi-k2p6 marked retired rather than deleted, per the frozen-enum rule. gpt-oss-120b, qwen3p8-max and glm-5p3 (the rest of fallbacks/topModels) were re-probed alive at the same time; glm-5p3 still only answers text calls, not image ones, as found 2026-08-30."
|
|
150
151
|
},
|
|
151
152
|
"addedInPR": "https://github.com/juspay/neurolink/pull/1587"
|
|
152
153
|
}
|
|
@@ -30,6 +30,12 @@ export declare function getTopModelChoices(provider: AIProviderName, limit?: num
|
|
|
30
30
|
* Get all available models for a provider
|
|
31
31
|
* Returns all values from the provider's model enum
|
|
32
32
|
*
|
|
33
|
+
* For a JSON-catalog provider, excludes retired ids. The `catalog` map keeps
|
|
34
|
+
* retired entries as raw table keys (they still resolve for a caller who
|
|
35
|
+
* pins that id explicitly — see `isValidModel`'s dedicated retired-id
|
|
36
|
+
* allowance below), but a listing/selection surface should not offer them.
|
|
37
|
+
* Mirrors the `selectableModels` filter in catalog/schema.ts.
|
|
38
|
+
*
|
|
33
39
|
* @param provider - The AI provider to get models for
|
|
34
40
|
* @returns Array of model identifier strings
|
|
35
41
|
*/
|
|
@@ -57,6 +63,20 @@ export declare function getDefaultModel(provider: AIProviderName): string | unde
|
|
|
57
63
|
/**
|
|
58
64
|
* Check if a model is valid for a given provider
|
|
59
65
|
*
|
|
66
|
+
* `getAllModels` excludes retired catalog ids (it is a listing/selection
|
|
67
|
+
* surface), but a caller who pins a retired id explicitly must not have
|
|
68
|
+
* that pin start failing validation just because it dropped out of the
|
|
69
|
+
* listing — so this falls back to the full catalog (all statuses) before
|
|
70
|
+
* rejecting a JSON-catalog provider's model.
|
|
71
|
+
*
|
|
72
|
+
* The empty-listing case is checked against catalog membership, not
|
|
73
|
+
* accepted outright: a catalog provider whose every entry happens to be
|
|
74
|
+
* retired still has a real catalog to validate against, and a fabricated
|
|
75
|
+
* id must not slip through just because the *selectable* listing is empty.
|
|
76
|
+
* Only a provider with no catalog entry at all (openai-compatible,
|
|
77
|
+
* lm-studio, llamacpp — providers without a strict model list) keeps the
|
|
78
|
+
* permissive "allow any model" behavior.
|
|
79
|
+
*
|
|
60
80
|
* @param provider - The AI provider
|
|
61
81
|
* @param model - The model identifier to check
|
|
62
82
|
* @returns true if the model exists in the provider's model enum
|
|
@@ -510,13 +510,21 @@ export function getTopModelChoices(provider, limit = 5) {
|
|
|
510
510
|
* Get all available models for a provider
|
|
511
511
|
* Returns all values from the provider's model enum
|
|
512
512
|
*
|
|
513
|
+
* For a JSON-catalog provider, excludes retired ids. The `catalog` map keeps
|
|
514
|
+
* retired entries as raw table keys (they still resolve for a caller who
|
|
515
|
+
* pins that id explicitly — see `isValidModel`'s dedicated retired-id
|
|
516
|
+
* allowance below), but a listing/selection surface should not offer them.
|
|
517
|
+
* Mirrors the `selectableModels` filter in catalog/schema.ts.
|
|
518
|
+
*
|
|
513
519
|
* @param provider - The AI provider to get models for
|
|
514
520
|
* @returns Array of model identifier strings
|
|
515
521
|
*/
|
|
516
522
|
export function getAllModels(provider) {
|
|
517
523
|
const catalogEntry = catalogEntryFor(provider);
|
|
518
524
|
if (catalogEntry) {
|
|
519
|
-
return Object.
|
|
525
|
+
return Object.entries(catalogEntry.models.catalog)
|
|
526
|
+
.filter(([, spec]) => spec.status !== "retired")
|
|
527
|
+
.map(([model]) => model);
|
|
520
528
|
}
|
|
521
529
|
const modelEnum = MODEL_ENUMS[provider];
|
|
522
530
|
if (!modelEnum) {
|
|
@@ -557,17 +565,42 @@ export function getDefaultModel(provider) {
|
|
|
557
565
|
/**
|
|
558
566
|
* Check if a model is valid for a given provider
|
|
559
567
|
*
|
|
568
|
+
* `getAllModels` excludes retired catalog ids (it is a listing/selection
|
|
569
|
+
* surface), but a caller who pins a retired id explicitly must not have
|
|
570
|
+
* that pin start failing validation just because it dropped out of the
|
|
571
|
+
* listing — so this falls back to the full catalog (all statuses) before
|
|
572
|
+
* rejecting a JSON-catalog provider's model.
|
|
573
|
+
*
|
|
574
|
+
* The empty-listing case is checked against catalog membership, not
|
|
575
|
+
* accepted outright: a catalog provider whose every entry happens to be
|
|
576
|
+
* retired still has a real catalog to validate against, and a fabricated
|
|
577
|
+
* id must not slip through just because the *selectable* listing is empty.
|
|
578
|
+
* Only a provider with no catalog entry at all (openai-compatible,
|
|
579
|
+
* lm-studio, llamacpp — providers without a strict model list) keeps the
|
|
580
|
+
* permissive "allow any model" behavior.
|
|
581
|
+
*
|
|
560
582
|
* @param provider - The AI provider
|
|
561
583
|
* @param model - The model identifier to check
|
|
562
584
|
* @returns true if the model exists in the provider's model enum
|
|
563
585
|
*/
|
|
564
586
|
export function isValidModel(provider, model) {
|
|
565
587
|
const models = getAllModels(provider);
|
|
566
|
-
if (models.
|
|
567
|
-
// For providers without strict model lists (like openai-compatible), allow any model
|
|
588
|
+
if (models.includes(model)) {
|
|
568
589
|
return true;
|
|
569
590
|
}
|
|
570
|
-
|
|
591
|
+
const catalogEntry = catalogEntryFor(provider);
|
|
592
|
+
if (catalogEntry) {
|
|
593
|
+
// Falls back to the FULL catalog (all statuses) so an explicitly pinned
|
|
594
|
+
// retired id still validates, and — critically — so an all-retired
|
|
595
|
+
// catalog (getAllModels() === []) is checked against real membership
|
|
596
|
+
// instead of accepting any string. Object.hasOwn (not `in`) so an
|
|
597
|
+
// inherited Object.prototype member name (e.g. "toString") is never
|
|
598
|
+
// mistaken for a real catalog key.
|
|
599
|
+
return Object.hasOwn(catalogEntry.models.catalog, model);
|
|
600
|
+
}
|
|
601
|
+
// No JSON catalog and no strict MODEL_ENUMS entry (openai-compatible,
|
|
602
|
+
// lm-studio, llamacpp): keep the permissive "allow any model" behavior.
|
|
603
|
+
return models.length === 0;
|
|
571
604
|
}
|
|
572
605
|
/**
|
|
573
606
|
* Get model choices formatted for inquirer prompts with a specific default
|
|
@@ -8905,9 +8905,9 @@
|
|
|
8905
8905
|
{"objectID":"2957ad3d500250301428a12b2e3e4c2be4dc09a0433c376e38fdebb122bc49ce","title":"Middleware: a narrow, real consequence","url":"/docs/plans/2026-09-03-remove-remaining-ai-sdk-plan#middleware-a-narrow-real-consequence","content":"Model middleware is applied by wrapping the model in\nprepareGenerationContext, which a native generate() override bypasses.\nGoogle AI Studio, Vertex and Bedrock already bypass it for exactly this reason,\nso stage 3 extends an existing gap rather than inventing one.\n\nThe blast radius is small and was measured, not assumed. Wrapping is opt-in:\ngetAISDKModelWithMiddleware returns the model untouched unless the caller\npasses middleware options, and the factory returns it untouched again when the\nresulting chain is empty. A default generate() call is therefore unaffected.\nLifecycle callbacks such as onFinish are handled above the model layer and\nwere confirmed to fire on every provider including the already-native ones.\n\nThe repo's own middleware suite cannot guard this. It targets Vertex, which\nalready bypasses model middleware, and it is flaky here regardless: two\nconsecutive runs failed different tests, both with an empty response from the\nprovider.","hierarchy":{"lvl0":"Plans","lvl1":"Removing the remaining Vercel AI SDK dependencies","lvl2":"Middleware: a narrow, real consequence","lvl3":""}},
|
|
8906
8906
|
{"objectID":"9f8c37cc0b2630c198a3fcf383e60aa8cc17797e031cf981f512cb84dbff8f3d","title":"What the first stage-3 attempt taught","url":"/docs/plans/2026-09-03-remove-remaining-ai-sdk-plan#what-the-first-stage-3-attempt-taught","content":"The generate-loop migration was written, tested against every provider\nreachable from this machine, found green, and reverted. It is worth being\nprecise about why, because the next attempt will hit the same walls.\n\nThe wire format changed, and only the mocked gate saw it. Both native paths\ndrove the turn through the streaming machinery, so generate() began sending\nstream: true where the ai loop sent a plain JSON request. That is exactly the\ndistinction useStreamingWireForGenerate() encodes, and it defaults to false\nbecause some OpenAI-compatible backends mishandle stream_options or omit\nusage on streams. Every provider with working credentials here supports\nstreaming, so a live matrix of 40 cells could not see it.\ntest:providers-mocked serves a canned non-streaming body and went from 0\nfailures to 17.\n\nThe fix direction is known. Loop over the delegating model's existing\ndoGenerate rather than over the streaming loop. It already picks the JSON or\nSSE wire, and already carries the 400 retry, the context-overflow correction\nand the invalid-model fallback the gate checks. What remains is the multi-step\ntool iteration around it and appending tool results in the shape its own\nmessage conversion expects. Anthropic needs a non-streaming messages.create\nfor the same reason: its loop adapter sets stream on every step.\n\nTwo regressions will recur. Structured output dropped to null whenever a\nschema arrived with no tools, because appendFinalResultTool declines an empty\ntool list and the ai path did not need tools at all. And onFinish stopped\nfiring, because NeuroLink turns it into lifecycle middleware and middleware is\napplied by wrapping the model, which a native override bypasses. Vertex already\nsolved the second one with fireGenerateOnFinish.","hierarchy":{"lvl0":"Plans","lvl1":"Removing the remaining Vercel AI SDK dependencies","lvl2":"What the first stage-3 attempt taught","lvl3":""}},
|
|
8907
8907
|
{"objectID":"154ece25f3804f5ea83b5688488d2659c020cfbb37a79346104f16c81ba62983","title":"Two bugs the stricter harness surfaced","url":"/docs/plans/2026-09-03-remove-remaining-ai-sdk-plan#two-bugs-the-stricter-harness-surfaced","content":"Neither is caused by this work; both were hidden by assertions that were too\nlenient.\nDeepSeek produces no structured output on the ai path. It fails with \"No\n object generated: response did not match schema\". The baseline recorded\n hasStructured: false and still passed, because the harness exempted it. The\n reverted native path fixed this by putting response_format on the wire, so\n a correct reimplementation should recover it.\nGroq had silently decommissioned llama-3.3-70b-versatile. The old\n harness reported generate as passing while something else answered. The\n harness now records which provider actually answered and fails when it is not\n the one requested.","hierarchy":{"lvl0":"Plans","lvl1":"Removing the remaining Vercel AI SDK dependencies","lvl2":"Two bugs the stricter harness surfaced","lvl3":""}},
|
|
8908
|
-
{"objectID":"a299f1d5f0dd8214982e3acedcb736d0c4f8bbfeddc57e43f0f2ce1ca4edaf6f","title":"Model middleware on Vertex, AI Studio and Bedrock","url":"/docs/plans/2026-09-07-middleware-on-native-providers","content":"Model middleware on Vertex, AI Studio and Bedrock\n\nStatus:
|
|
8909
|
-
{"objectID":"c3c569ca370972e51b7e2bdccdc752874bab48300c2894b817a93d029066986f","title":"Model middleware on Vertex, AI Studio and Bedrock","url":"/docs/plans/2026-09-07-middleware-on-native-providers#model-middleware-on-vertex-ai-studio-and-bedrock","content":"Status:
|
|
8910
|
-
{"objectID":"8619e3cf755518dcb8233a8c978e53c37d21817d13cb1b627391b6eb8e1109c9","title":"The gap, stated exactly","url":"/docs/plans/2026-09-07-middleware-on-native-providers#the-gap-stated-exactly","content":"middleware is a public option on generate() and stream(). It is applied\nby wrapping the model handle, in exactly one place:\n\nFive call sites reach it. That is the whole list:\n\n| call site | mode |\n| -------------------------------------------------------------- | -------------------------------------------- |\n| openaiChatCompletionsBase.ts:1132 | generate |\n| openaiChatCompletionsBase.ts:1534 (applyMiddlewareToModel) | stream |\n| anthropic/client.ts:1766 | generate |\n| amazonSagemaker.ts:206 | generate |\n| baseProvider.ts:1515 | inside prepareGenerationContext — live |\n\nThe fifth entry matters, and an earlier draft of this spec got it wrong by\ncalling it deleted. prepareGenerationContext is live; it is the seam a\nprovider reaches by going through BaseProvider.runGenerateInActiveContext.\n\
|
|
8908
|
+
{"objectID":"a299f1d5f0dd8214982e3acedcb736d0c4f8bbfeddc57e43f0f2ce1ca4edaf6f","title":"Model middleware on Vertex, AI Studio and Bedrock","url":"/docs/plans/2026-09-07-middleware-on-native-providers","content":"Model middleware on Vertex, AI Studio and Bedrock\n\nStatus: done. AI Studio (301e4e18a), Vertex and Bedrock are all\nimplemented — each via its own synthetic V3 model bridge (generate() and\nstream()), so transformParams / wrapGenerate / wrapStream now run on\nevery provider this plan covers. The rest of this document, including the\n\"still reach none of the five\" language below, describes the gap as it\nstood before any of the three landed; it is kept for the record, not as a\ncurrent description.\nGoal: make transformParams / wrapGenerate / wrapStream run on the\nthree providers that bypass them entirely, on both generate() and\nstream().\n\nThe gap, stated exactly\n\nmiddleware is a public option on generate() and stream(). It is applied\nby wrapping the model handle, in exactly one place:\n\nFive call sites reach it. That is the whole list:\n\n| call site | mode |\n| -------------------------------------------------------------- | -------------------------------------------- |\n| openaiChatCompletionsBase.ts:1132 | generate |\n| openaiChatCompletionsBase.ts:1534 (applyMiddlewareToModel) | stream |\n| anthropic/client.ts:1766 | generate |\n| amazonSagemaker.ts:206 | generate |\n| baseProvider.ts:1515 | inside prepareGenerationContext — live |\n\nThe fifth entry matters, and an earlier draft of this spec got it wrong by\ncalling it deleted. prepareGenerationContext is live; it is the seam a\nprovider reaches by going through BaseProvider.runGenerateInActiveContext.\n\nAt the time this plan was written, googleVertex, googleAiStudio and\namazonBedrock reached none of the five: each overrode generate() and\nexecuteStream() with a native path that never wrapped its model. All three\nhave since closed that gap, each through its own synthetic V3 model bridge\nrather than through one of the five call sites above — the bridge builds a\nLanguageModelV3 whose doGenerate/doStream drives the native loop, wraps\nit with applyMiddlewareToModel, and reads the middleware-transformed params\nback onto the native request. The symptoms below describe the gap as it\nstood before any of the three landed:\ntransformParams never fired — a middleware that rewrote the prompt,\n maxOutputTokens, temperature or topP was silently ignored\nwrapGenerate and wrapStream never fired — guardrails did not filter,\n and a guardrail that blocked a prompt did not block it\non Vertex onFinish still fired, special-cased separately via\n fireGenerateOnFinish — which was invoked from googleVertex/client.ts\n and nowhere else\non AI Studio and Bedrock, not even that: both files contained zero\n references to onFinish, so a caller's onFinish was dropped on the\n generate path\n\nThat last point was about generate only. stream() lifecycle callbacks were\nunaffected on all three: BaseProvider.wrapStreamWithLifecycleCallbacks\nreads onChunk / onFinish / onError and is applied on the generic stream\npath, so a streaming caller still got them. What no provider here got was\nmodel middleware.\n\nThe last point was the sharp one: a caller who configured blocking\nguardrails and pointed at any of these three providers got no error and no\nfiltering. It looked configured and did nothing.\n\nEntry points to change\n\n| provider | generate | stream |\n| -------------------------- | -------- | ----------------------------------------- |\n| googleVertex/client.ts | :6635 | :1175 executeStream, :6575 stream |\n| googleAiStudio/client.ts | :1746 | :772 executeStream |\n| amazonBedrock/client.ts | :233 | :895 executeStream |\n\nWhy it was left\n\nAcknowledged twice and deliberately: docs/plans/2026-09-03-remove-remaining-ai-sdk-plan.md\nrecords that these three \"already bypass it for exactly this reason, so stage 3\nextends an existing gap rather than inventing one\", and PR #1636 scoped itself\nto the OpenAI-compatible family and said so under \"Not in this PR\".\n\nSo this is a pre-existing gap widened by the native migration, not a\nregression it introduced. Wording in any PR should say that.\n\nThe pattern to copy\n\nPR #1636 solved the same problem for the OpenAI-compatible stream path. Its shape\nis the template, and its four hard-won corrections are the specification for\nwhat \"done\" means here:\nBuild a V3 base model whose doStream starts the real native loop,\n wrap it with the middleware chain, then drive the wrapped model. Convert\n the prompt to the wire format after transformParams, or a rewrite\n never reaches the wire.\nEmit a terminal finish part carrying usage and finish reason, from\n the loop's deferred promises. Without it a middleware observing the st","hierarchy":{"lvl0":"Plans","lvl1":"Model middleware on Vertex, AI Studio and Bedrock","lvl2":"","lvl3":""}},
|
|
8909
|
+
{"objectID":"c3c569ca370972e51b7e2bdccdc752874bab48300c2894b817a93d029066986f","title":"Model middleware on Vertex, AI Studio and Bedrock","url":"/docs/plans/2026-09-07-middleware-on-native-providers#model-middleware-on-vertex-ai-studio-and-bedrock","content":"Status: done. AI Studio (301e4e18a), Vertex and Bedrock are all\nimplemented — each via its own synthetic V3 model bridge (generate() and\nstream()), so transformParams / wrapGenerate / wrapStream now run on\nevery provider this plan covers. The rest of this document, including the\n\"still reach none of the five\" language below, describes the gap as it\nstood before any of the three landed; it is kept for the record, not as a\ncurrent description.\nGoal: make transformParams / wrapGenerate / wrapStream run on the\nthree providers that bypass them entirely, on both generate() and\nstream().","hierarchy":{"lvl0":"Plans","lvl1":"Model middleware on Vertex, AI Studio and Bedrock","lvl2":"Model middleware on Vertex, AI Studio and Bedrock","lvl3":""}},
|
|
8910
|
+
{"objectID":"8619e3cf755518dcb8233a8c978e53c37d21817d13cb1b627391b6eb8e1109c9","title":"The gap, stated exactly","url":"/docs/plans/2026-09-07-middleware-on-native-providers#the-gap-stated-exactly","content":"middleware is a public option on generate() and stream(). It is applied\nby wrapping the model handle, in exactly one place:\n\nFive call sites reach it. That is the whole list:\n\n| call site | mode |\n| -------------------------------------------------------------- | -------------------------------------------- |\n| openaiChatCompletionsBase.ts:1132 | generate |\n| openaiChatCompletionsBase.ts:1534 (applyMiddlewareToModel) | stream |\n| anthropic/client.ts:1766 | generate |\n| amazonSagemaker.ts:206 | generate |\n| baseProvider.ts:1515 | inside prepareGenerationContext — live |\n\nThe fifth entry matters, and an earlier draft of this spec got it wrong by\ncalling it deleted. prepareGenerationContext is live; it is the seam a\nprovider reaches by going through BaseProvider.runGenerateInActiveContext.\n\nAt the time this plan was written, googleVertex, googleAiStudio and\namazonBedrock reached none of the five: each overrode generate() and\nexecuteStream() with a native path that never wrapped its model. All three\nhave since closed that gap, each through its own synthetic V3 model bridge\nrather than through one of the five call sites above — the bridge builds a\nLanguageModelV3 whose doGenerate/doStream drives the native loop, wraps\nit with applyMiddlewareToModel, and reads the middleware-transformed params\nback onto the native request. The symptoms below describe the gap as it\nstood before any of the three landed:\ntransformParams never fired — a middleware that rewrote the prompt,\n maxOutputTokens, temperature or topP was silently ignored\nwrapGenerate and wrapStream never fired — guardrails did not filter,\n an","hierarchy":{"lvl0":"Plans","lvl1":"Model middleware on Vertex, AI Studio and Bedrock","lvl2":"The gap, stated exactly","lvl3":""}},
|
|
8911
8911
|
{"objectID":"46f9060fd36e2a33467541a050598523ead1cf1f31809c71ced840e112c2bd91","title":"Entry points to change","url":"/docs/plans/2026-09-07-middleware-on-native-providers#entry-points-to-change","content":"| provider | generate | stream |\n| -------------------------- | -------- | ----------------------------------------- |\n| googleVertex/client.ts | :6635 | :1175 executeStream, :6575 stream |\n| googleAiStudio/client.ts | :1746 | :772 executeStream |\n| amazonBedrock/client.ts | :233 | :895 executeStream |","hierarchy":{"lvl0":"Plans","lvl1":"Model middleware on Vertex, AI Studio and Bedrock","lvl2":"Entry points to change","lvl3":""}},
|
|
8912
8912
|
{"objectID":"2ffdb223dac8263f80806fa56949891f5b7009470175bbf85e48e879ec43740f","title":"Why it was left","url":"/docs/plans/2026-09-07-middleware-on-native-providers#why-it-was-left","content":"Acknowledged twice and deliberately: docs/plans/2026-09-03-remove-remaining-ai-sdk-plan.md\nrecords that these three \"already bypass it for exactly this reason, so stage 3\nextends an existing gap rather than inventing one\", and PR #1636 scoped itself\nto the OpenAI-compatible family and said so under \"Not in this PR\".\n\nSo this is a pre-existing gap widened by the native migration, not a\nregression it introduced. Wording in any PR should say that.","hierarchy":{"lvl0":"Plans","lvl1":"Model middleware on Vertex, AI Studio and Bedrock","lvl2":"Why it was left","lvl3":""}},
|
|
8913
8913
|
{"objectID":"65376f7d1279f4258909a230331317c89cb720126c497682f23c502c9a8181c0","title":"The pattern to copy","url":"/docs/plans/2026-09-07-middleware-on-native-providers#the-pattern-to-copy","content":"PR #1636 solved the same problem for the OpenAI-compatible stream path. Its shape\nis the template, and its four hard-won corrections are the specification for\nwhat \"done\" means here:\nBuild a V3 base model whose doStream starts the real native loop,\n wrap it with the middleware chain, then drive the wrapped model. Convert\n the prompt to the wire format after transformParams, or a rewrite\n never reaches the wire.\nEmit a terminal finish part carrying usage and finish reason, from\n the loop's deferred promises. Without it a middleware observing the stream\n sees neither.\nTolerate a middleware that never calls doStream. Guardrails' precall\n path returns its own stream; the loop never starts, so every reader of the\n loop promise must survive its absence or analytics hang forever.\nForward cancellation. Breaking out of a wrapped stream must abort the\n upstream request, or the HTTP connection leaks.\n\nHonour on the way back in: prompt, maxOutputTokens, temperature, topP.\ntools is read-only — a rewrite gets a WARN, never a silent drop.","hierarchy":{"lvl0":"Plans","lvl1":"Model middleware on Vertex, AI Studio and Bedrock","lvl2":"The pattern to copy","lvl3":""}},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.41.
|
|
3
|
+
"version": "12.41.8",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|
|
@@ -140,6 +140,7 @@
|
|
|
140
140
|
"test:provider-descriptors": "pnpm exec tsx test/continuous-test-suite-provider-descriptors.ts",
|
|
141
141
|
"test:provider-structure": "pnpm exec tsx test/continuous-test-suite-provider-structure.ts",
|
|
142
142
|
"test:model-manifests": "pnpm exec tsx test/continuous-test-suite-model-manifests.ts",
|
|
143
|
+
"test:cli-models-list": "pnpm exec tsx test/continuous-test-suite-cli-models-list.ts",
|
|
143
144
|
"test:provider-fallback": "pnpm exec tsx test/continuous-test-suite-provider-fallback.ts",
|
|
144
145
|
"test:provider-fallback-latency": "pnpm exec tsx test/continuous-test-suite-provider-fallback-latency.ts",
|
|
145
146
|
"test:provider-wiring": "pnpm exec tsx test/continuous-test-suite-provider-wiring.ts",
|