@juspay/neurolink 12.49.10 → 12.49.12
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 +66 -66
- package/dist/providers/catalog/loader.js +6 -0
- package/dist/providers/catalog/provider-catalog.schema.json +3 -0
- package/dist/providers/catalog/reka.json +4 -1
- package/dist/providers/catalog/schema.d.ts +1 -0
- package/dist/providers/catalog/schema.js +1 -0
- package/dist/providers/configuredOpenAICompat.d.ts +7 -0
- package/dist/providers/configuredOpenAICompat.js +11 -0
- package/dist/types/providerCatalog.d.ts +22 -6
- package/dist/types/providers.d.ts +11 -0
- package/docs-site/static/search-index.json +4 -4
- package/package.json +2 -2
|
@@ -113,6 +113,9 @@ export function getCatalogJsonEntries() {
|
|
|
113
113
|
}
|
|
114
114
|
export function buildCatalogEntries() {
|
|
115
115
|
return CATALOG_JSON_ENTRIES.map((entry) => {
|
|
116
|
+
// Only models whose entry sets `tools` explicitly contribute a row —
|
|
117
|
+
// see CatalogModelSpec.tools and OpenAICompatCatalogEntry.modelToolOverrides.
|
|
118
|
+
const modelToolOverrides = Object.fromEntries(Object.entries(entry.models.catalog).flatMap(([modelId, spec]) => spec.tools !== undefined ? [[modelId, spec.tools]] : []));
|
|
116
119
|
const base = {
|
|
117
120
|
providerName: entry.id,
|
|
118
121
|
aliases: [entry.id, ...entry.aliases],
|
|
@@ -135,6 +138,9 @@ export function buildCatalogEntries() {
|
|
|
135
138
|
...(typeof entry.capabilities.tools === "boolean"
|
|
136
139
|
? { supportsTools: entry.capabilities.tools }
|
|
137
140
|
: {}),
|
|
141
|
+
...(Object.keys(modelToolOverrides).length > 0
|
|
142
|
+
? { modelToolOverrides }
|
|
143
|
+
: {}),
|
|
138
144
|
// Unlike `tools`, `capabilities.structuredOutputWithTools` is a plain
|
|
139
145
|
// required boolean in the schema (no "model-dependent" member), so this
|
|
140
146
|
// is a direct passthrough — `false` and `true` both carry meaning to
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"output": 2
|
|
20
20
|
},
|
|
21
21
|
"vision": true,
|
|
22
|
+
"tools": true,
|
|
22
23
|
"status": "production",
|
|
23
24
|
"description": "NeuroLink default. Listed as reka-flash in the baseline model table on https://docs.reka.ai/chat/models.md (intro: \"Our baseline models always available for public access are:\") and named as the model in the code examples on https://docs.reka.ai/chat/overview.md, https://docs.reka.ai/chat/function-calling.md and https://docs.reka.ai/chat/api-reference/create.md (retrieved 2026-09-29). https://docs.reka.ai/pricing.md has a row named \"Reka Flash\" described as \"Fast and cost-efficient model for most tasks\" with $0.80 under \"Input Tokens (per 1M)\" and $2.00 under \"Output Tokens (per 1M)\"; https://docs.reka.ai/chat/models.md ends with \"For full listing of models and pricing, see the Reka API Pricing page\". https://docs.reka.ai/chat/function-calling.md says \"Currently, only Reka Flash supports function calling.\" Vision is true: the first curl example on https://docs.reka.ai/overview.md sends an image_url content part to model \"reka-flash\", and the Quickstart's \"First request\" example (https://docs.reka.ai/quickstart.md) carries the comment '# or \"reka-flash\"' beside an image_url request. No context window or maximum output figure is set for this model; models.defaultContextWindow and models.defaultMaxOutputTokens apply."
|
|
24
25
|
},
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
"output": 0.1
|
|
29
30
|
},
|
|
30
31
|
"vision": true,
|
|
32
|
+
"tools": false,
|
|
31
33
|
"status": "production",
|
|
32
34
|
"description": "Listed as \"reka-edge (or reka-edge-2603)\" in the baseline model table on https://docs.reka.ai/chat/models.md and on https://docs.reka.ai/quickstart.md (retrieved 2026-09-29). The Quickstart's \"First request\" example sends an image_url content part to model \"reka-edge\", and the example response on https://docs.reka.ai/chat/api-reference/get.md lists the id \"reka-edge\". https://docs.reka.ai/pricing.md has a row named \"Reka Edge\" described as \"Compact model ideal for on-device execution\" with $0.10 under \"Input Tokens (per 1M)\" and $0.10 under \"Output Tokens (per 1M)\". https://docs.reka.ai/chat/function-calling.md says \"Currently, only Reka Flash supports function calling.\" No context window or maximum output figure is set for this model; models.defaultContextWindow and models.defaultMaxOutputTokens apply."
|
|
33
35
|
},
|
|
@@ -37,6 +39,7 @@
|
|
|
37
39
|
"output": 0.1
|
|
38
40
|
},
|
|
39
41
|
"vision": true,
|
|
42
|
+
"tools": false,
|
|
40
43
|
"status": "production",
|
|
41
44
|
"description": "Named in the same table row as reka-edge, \"reka-edge (or reka-edge-2603)\", on https://docs.reka.ai/chat/models.md and https://docs.reka.ai/quickstart.md, and shown as {\"id\": \"reka-edge-2603\"} in the example output of GET https://api.reka.ai/v1/models on https://docs.reka.ai/chat/models.md, which says \"All of these model IDs can be used as values for the Chat API's model parameter\" (retrieved 2026-09-29). Vision and prices are those of the row's reka-edge example and its \"Reka Edge\" pricing row (https://docs.reka.ai/quickstart.md, https://docs.reka.ai/pricing.md). No context window or maximum output figure is set for this model; models.defaultContextWindow and models.defaultMaxOutputTokens apply."
|
|
42
45
|
}
|
|
@@ -88,7 +91,7 @@
|
|
|
88
91
|
"3. Authentication: the vendor's REST examples send the header X-Api-Key (https://docs.reka.ai/chat/overview.md) and the OpenAPI file https://docs.reka.ai/openapi/api-reference.yaml declares one security scheme, an apiKey in the header X-Api-Key; the OpenAI Python SDK examples pass api_key=\"YOUR_API_KEY\" to the client (https://docs.reka.ai/quickstart.md)",
|
|
89
92
|
"4. Set {apiKeyEnvVar} in your .env file"
|
|
90
93
|
],
|
|
91
|
-
"description": "Docs-verified only: the vendor's GET https://api.reka.ai/v1/models needs a key (it answers HTTP 401 without one), so the three model ids come from https://docs.reka.ai/chat/models.md and the roster has not been checked; the entry is not yet live-verified. Endpoint https://api.reka.ai/v1: the Quickstart (https://docs.reka.ai/quickstart.md) says \"our API is fully OpenAI-compatible\" and shows the OpenAI Python SDK with base_url \"https://api.reka.ai/v1\"; https://docs.reka.ai/chat/overview.md shows POST https://api.reka.ai/v1/chat/completions with a messages array and reads the reply from response.choices[0].message.content. Unauthenticated GETs made 2026-09-29: /models answered HTTP 401 with the JSON body {\"error\":{\"message\":\"Unauthorized\",\"type\":\"authentication_error\",\"code\":null,\"param\":null}}; /chat/completions answered HTTP 405 with header allow: POST and the body {\"detail\":\"Method Not Allowed\"}. No POST request was sent. errorRules carry the statuses https://docs.reka.ai/errors.md lists (401 authentication_error, 429 rate_limit_error, 500 server_error) plus a pattern rule on the FAQ's \"P001: Insufficient Balance\" text. capabilities.streaming is true because https://docs.reka.ai/chat/overview.md says \"The Chat API supports streaming\". capabilities.tools is model-dependent because https://docs.reka.ai/chat/function-calling.md documents the tools parameter and tool_calls and says \"Currently, only Reka Flash supports function calling.\" capabilities.structuredOutput is false: the ChatRequest on https://docs.reka.ai/chat/api-reference/create.md lists messages, model, frequency_penalty, max_tokens, presence_penalty, seed, stop, stream, temperature, tool_choice, tools, top_k and top_p. capabilities.toolsWithStreaming and capabilities.structuredOutputWithTools are false because no request combining them was sent. capabilities.embeddings and capabilities.thinking are false. models.defaultContextWindow (16384) and models.defaultMaxOutputTokens (4096) are placeholders the vendor does not publish; the Chat API reference describes max_tokens as \"limited by the model's context length. Defaults to 1024.\" Each model's status field holds production, a placeholder for a value the catalog schema requires; it is not a vendor statement. billingPolicy holds free-tier, one of the three values the catalog schema allows (free-tier, free-with-card, no-free-tier). The vendor wording behind it: on https://platform.reka.ai/pricing the Pay as you go tile has a \"Start for free\" link to /sign-up and the page carries the text \"Free credits used\"; https://docs.reka.ai/pricing.md says \"Get started with no upfront costs.\"; https://docs.reka.ai/resources/faqs.md answers \"Do I need to pre-pay?\" with \"Yes. Add credits to your account before making requests.\" apiKeyFormat is null, so NeuroLink's key-format check is not applied."
|
|
94
|
+
"description": "Docs-verified only: the vendor's GET https://api.reka.ai/v1/models needs a key (it answers HTTP 401 without one), so the three model ids come from https://docs.reka.ai/chat/models.md and the roster has not been checked; the entry is not yet live-verified. Endpoint https://api.reka.ai/v1: the Quickstart (https://docs.reka.ai/quickstart.md) says \"our API is fully OpenAI-compatible\" and shows the OpenAI Python SDK with base_url \"https://api.reka.ai/v1\"; https://docs.reka.ai/chat/overview.md shows POST https://api.reka.ai/v1/chat/completions with a messages array and reads the reply from response.choices[0].message.content. Unauthenticated GETs made 2026-09-29: /models answered HTTP 401 with the JSON body {\"error\":{\"message\":\"Unauthorized\",\"type\":\"authentication_error\",\"code\":null,\"param\":null}}; /chat/completions answered HTTP 405 with header allow: POST and the body {\"detail\":\"Method Not Allowed\"}. No POST request was sent. errorRules carry the statuses https://docs.reka.ai/errors.md lists (401 authentication_error, 429 rate_limit_error, 500 server_error) plus a pattern rule on the FAQ's \"P001: Insufficient Balance\" text. capabilities.streaming is true because https://docs.reka.ai/chat/overview.md says \"The Chat API supports streaming\". capabilities.tools is model-dependent because https://docs.reka.ai/chat/function-calling.md documents the tools parameter and tool_calls and says \"Currently, only Reka Flash supports function calling.\" That sentence is why reka-flash's models.catalog entry sets tools: true and reka-edge/reka-edge-2603 set tools: false (see CatalogModelSpec.tools) instead of leaving every model to the provider-level model-dependent default. capabilities.structuredOutput is false: the ChatRequest on https://docs.reka.ai/chat/api-reference/create.md lists messages, model, frequency_penalty, max_tokens, presence_penalty, seed, stop, stream, temperature, tool_choice, tools, top_k and top_p. capabilities.toolsWithStreaming and capabilities.structuredOutputWithTools are false because no request combining them was sent. capabilities.embeddings and capabilities.thinking are false. models.defaultContextWindow (16384) and models.defaultMaxOutputTokens (4096) are placeholders the vendor does not publish; the Chat API reference describes max_tokens as \"limited by the model's context length. Defaults to 1024.\" Each model's status field holds production, a placeholder for a value the catalog schema requires; it is not a vendor statement. billingPolicy holds free-tier, one of the three values the catalog schema allows (free-tier, free-with-card, no-free-tier). The vendor wording behind it: on https://platform.reka.ai/pricing the Pay as you go tile has a \"Start for free\" link to /sign-up and the page carries the text \"Free credits used\"; https://docs.reka.ai/pricing.md says \"Get started with no upfront costs.\"; https://docs.reka.ai/resources/faqs.md answers \"Do I need to pre-pay?\" with \"Yes. Add credits to your account before making requests.\" apiKeyFormat is null, so NeuroLink's key-format check is not applied."
|
|
92
95
|
},
|
|
93
96
|
"evidence": {
|
|
94
97
|
"rosterVerified": {
|
|
@@ -46,6 +46,7 @@ export declare const providerCatalogJsonSchema: z.ZodObject<{
|
|
|
46
46
|
cachedInput: z.ZodOptional<z.ZodNumber>;
|
|
47
47
|
}, z.core.$strict>>;
|
|
48
48
|
vision: z.ZodBoolean;
|
|
49
|
+
tools: z.ZodOptional<z.ZodBoolean>;
|
|
49
50
|
status: z.ZodEnum<{
|
|
50
51
|
production: "production";
|
|
51
52
|
preview: "preview";
|
|
@@ -23,6 +23,7 @@ const catalogModelSpecSchema = z.strictObject({
|
|
|
23
23
|
maxOutputTokens: z.number().optional(),
|
|
24
24
|
pricingPerMTok: catalogPricingPerMTokSchema.optional(),
|
|
25
25
|
vision: z.boolean(),
|
|
26
|
+
tools: z.boolean().optional(),
|
|
26
27
|
status: catalogModelStatusSchema,
|
|
27
28
|
description: z.string(),
|
|
28
29
|
enumMember: z
|
|
@@ -62,6 +62,13 @@ export declare class ConfiguredOpenAICompatProvider extends OpenAIChatCompletion
|
|
|
62
62
|
* every unknown id. A vendor that declares tools: false must never receive
|
|
63
63
|
* a `tools` array — Mancer's free model rejects one with 400 — so the
|
|
64
64
|
* declaration wins here and the registry is only consulted otherwise.
|
|
65
|
+
* A per-model entry in `modelToolOverrides` (from a "model-dependent"
|
|
66
|
+
* provider whose catalog names which specific models accept tools — see
|
|
67
|
+
* CatalogModelSpec.tools) wins over all of this: it is the same kind of
|
|
68
|
+
* wire-probed fact as `supportsTools`, just scoped to one model instead of
|
|
69
|
+
* the whole provider, so it is checked first and can both grant and
|
|
70
|
+
* withhold tools regardless of what the provider-level flag says.
|
|
71
|
+
*
|
|
65
72
|
* Like the other entry-reading overrides above, this runs only after
|
|
66
73
|
* construction: BaseProvider merely closes over it.
|
|
67
74
|
*/
|
|
@@ -125,10 +125,21 @@ export class ConfiguredOpenAICompatProvider extends OpenAIChatCompletionsProvide
|
|
|
125
125
|
* every unknown id. A vendor that declares tools: false must never receive
|
|
126
126
|
* a `tools` array — Mancer's free model rejects one with 400 — so the
|
|
127
127
|
* declaration wins here and the registry is only consulted otherwise.
|
|
128
|
+
* A per-model entry in `modelToolOverrides` (from a "model-dependent"
|
|
129
|
+
* provider whose catalog names which specific models accept tools — see
|
|
130
|
+
* CatalogModelSpec.tools) wins over all of this: it is the same kind of
|
|
131
|
+
* wire-probed fact as `supportsTools`, just scoped to one model instead of
|
|
132
|
+
* the whole provider, so it is checked first and can both grant and
|
|
133
|
+
* withhold tools regardless of what the provider-level flag says.
|
|
134
|
+
*
|
|
128
135
|
* Like the other entry-reading overrides above, this runs only after
|
|
129
136
|
* construction: BaseProvider merely closes over it.
|
|
130
137
|
*/
|
|
131
138
|
supportsTools() {
|
|
139
|
+
const override = this.entry.modelToolOverrides?.[this.modelName];
|
|
140
|
+
if (override !== undefined) {
|
|
141
|
+
return override;
|
|
142
|
+
}
|
|
132
143
|
if (this.entry.supportsTools === false) {
|
|
133
144
|
return false;
|
|
134
145
|
}
|
|
@@ -27,6 +27,17 @@ export type CatalogModelSpec = {
|
|
|
27
27
|
maxOutputTokens?: number;
|
|
28
28
|
pricingPerMTok?: CatalogPricingPerMTok;
|
|
29
29
|
vision: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Per-model override of the provider-level `capabilities.tools`, for a
|
|
32
|
+
* "model-dependent" provider whose vendor docs name which specific models
|
|
33
|
+
* accept tool definitions (e.g. Reka: "Currently, only Reka Flash
|
|
34
|
+
* supports function calling"). Absent means "inherit the provider-level
|
|
35
|
+
* answer", same as every model before this field existed. Only meaningful
|
|
36
|
+
* when `capabilities.tools` is `"model-dependent"` — a provider that
|
|
37
|
+
* already declares a plain `true`/`false` has no need for it, since that
|
|
38
|
+
* single value already applies to every model it serves.
|
|
39
|
+
*/
|
|
40
|
+
tools?: boolean;
|
|
30
41
|
status: CatalogModelStatus;
|
|
31
42
|
description: string;
|
|
32
43
|
/**
|
|
@@ -123,13 +134,18 @@ export type CatalogEvidence = {
|
|
|
123
134
|
export type CatalogCapabilities = {
|
|
124
135
|
text: boolean;
|
|
125
136
|
streaming: boolean;
|
|
126
|
-
/** "model-dependent" when tool support varies per served model
|
|
127
|
-
* vendor doesn't reject `tools` for unsupported ones (the model just
|
|
128
|
-
* never emits tool_calls) — e.g. HuggingFace's router. Maps to
|
|
137
|
+
/** "model-dependent" when tool support varies per served model. Maps to
|
|
129
138
|
* ProviderDescriptor.toolSupport's own "model-dependent" member and
|
|
130
|
-
* leaves OpenAICompatCatalogEntry.supportsTools unset so
|
|
131
|
-
* ConfiguredOpenAICompatProvider falls
|
|
132
|
-
*
|
|
139
|
+
* leaves OpenAICompatCatalogEntry.supportsTools unset, so
|
|
140
|
+
* ConfiguredOpenAICompatProvider.supportsTools() falls back to whichever
|
|
141
|
+
* of its two remaining sources applies: a model whose own
|
|
142
|
+
* models.catalog[id].tools is set (see CatalogModelSpec.tools) answers
|
|
143
|
+
* from that; any other model falls through further, to the
|
|
144
|
+
* model-registry default (true for an unregistered id) — the same
|
|
145
|
+
* behavior every model had before CatalogModelSpec.tools existed, and
|
|
146
|
+
* still correct for a vendor that doesn't reject `tools` for an
|
|
147
|
+
* unsupported model (the model just never emits tool_calls), e.g.
|
|
148
|
+
* HuggingFace's router. */
|
|
133
149
|
tools: boolean | "model-dependent";
|
|
134
150
|
toolsWithStreaming: boolean;
|
|
135
151
|
structuredOutput: boolean;
|
|
@@ -1043,6 +1043,17 @@ export type OpenAICompatCatalogEntry = {
|
|
|
1043
1043
|
* same default every hand-written provider uses.
|
|
1044
1044
|
*/
|
|
1045
1045
|
supportsTools?: boolean;
|
|
1046
|
+
/**
|
|
1047
|
+
* Per-model override of `supportsTools`, from catalog models whose entry
|
|
1048
|
+
* sets `tools` explicitly (CatalogModelSpec.tools) — keyed by the model id
|
|
1049
|
+
* exactly as it appears in `models.catalog`. Checked first by
|
|
1050
|
+
* ConfiguredOpenAICompatProvider.supportsTools(), so it can both grant and
|
|
1051
|
+
* withhold tools regardless of what `supportsTools` says; a model id
|
|
1052
|
+
* absent from this map falls through to `supportsTools` unchanged. Built
|
|
1053
|
+
* only from models that declare `tools`, so a provider with no per-model
|
|
1054
|
+
* overrides gets no field here at all (not an empty object).
|
|
1055
|
+
*/
|
|
1056
|
+
modelToolOverrides?: Record<string, boolean>;
|
|
1046
1057
|
/**
|
|
1047
1058
|
* Whether the vendor accepts native tool definitions and `response_format`
|
|
1048
1059
|
* in the SAME request, from the catalog's
|
|
@@ -3506,7 +3506,7 @@
|
|
|
3506
3506
|
{"objectID":"062ba86ed5fa937d989ef36219f6bc4d2673654750f6c4fbfee623527282bc03","title":"From Previous Implementations","url":"/docs/features/guardrails-implementation#from-previous-implementations","content":"If upgrading from older guardrail implementations:\nUpdate configuration format to new interfaces\nReplace deprecated methods with new utility functions\nTest evaluation thresholds and adjust as needed\nUpdate error handling to use new patterns","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Implementation Guide","lvl2":"From Previous Implementations","lvl3":""}},
|
|
3507
3507
|
{"objectID":"1d4cfe18f157b91540119afedbf464d626c2c320e56551b69d5b3f853541e3c4","title":"Breaking Changes","url":"/docs/features/guardrails-implementation#breaking-changes","content":"Configuration structure has been updated for better organization\nSome utility function signatures have changed\nError handling patterns have been improved","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Implementation Guide","lvl2":"Breaking Changes","lvl3":""}},
|
|
3508
3508
|
{"objectID":"214fe14d9f320f468b5ed10d5b5cf315a7aa2a0fcb1a32598f42a622570e177d","title":"Conclusion","url":"/docs/features/guardrails-implementation#conclusion","content":"The NeuroLink guardrails implementation provides comprehensive content safety and filtering capabilities with:\n✅ AI-powered pre-call evaluation\n✅ Flexible content filtering options\n✅ Configurable response actions\n✅ Visual proof and demonstrations\n✅ High performance and scalability\n✅ Comprehensive error handling\n✅ TypeScript support throughout\n\nFor additional support or questions, refer to the main NeuroLink documentation or create an issue in the repository.","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Implementation Guide","lvl2":"Conclusion","lvl3":""}},
|
|
3509
|
-
{"objectID":"540c47bd7c6e059a9673d6acb056728c913d14a87db9e96c85e9ad17847af52d","title":"Guardrails Middleware","url":"/docs/features/guardrails","content":"Guardrails Middleware\n\nSince: v7.42.0 | Status: Stable | Availability: SDK (CLI + SDK)\n\nOverview\n\nWhat it does: Guardrails middleware provides real-time content filtering and policy enforcement for AI model outputs, blocking profanity, PII, unsafe content, and custom-defined terms.\n\nWhy use it: Protect your application from generating harmful, inappropriate, or non-compliant content. Ensures AI responses meet safety standards and regulatory requirements.\n\nCommon use cases:\nContent moderation for user-facing applications\nPII (Personally Identifiable Information) redaction\nProfanity filtering for family-friendly apps\nCompliance with industry regulations (COPPA, GDPR, etc.)\nBrand safety and reputation management\n\nQuick Start\n\nGuardrails work out of the box with the security preset. No custom configuration required for basic content filtering.\n\nSDK Example with Security Preset\nEnables guardrails middleware with default configuration\nPass middleware on every call that should be filtered; the NeuroLink constructor does not take this option\nContent is already filtered - safe to display to users\n\nCustom Guardrails Configuration\nMaster switch for guardrails middleware\nEnable keyword-based filtering (fast, regex-based)\nCustom terms to filter/redact from outputs\nEnable AI-powered content safety check (slower, more accurate)\nUse fast, cheap model for safety evaluation\n\nCLI Usage\n\nConfiguration\n\n| Option | Type | Default | Required | Description |\n| ------------------------- | ---------- | ------- | -------- | ------------------------------------ |\n| enabled | boolean | true | No | Enable/disable guardrails middleware |\n| badWords.enabled | boolean | false | No | Enable keyword-based filtering |\n| badWords.list | string[] | [] | No | List of terms to filter/redact |\n| modelFilter.enabled | boolean | false | No | Enable AI-based content safety check |\n| modelFilter.filterModel | string | - | No | Model to use for safety evaluation |\n\nEnvironment Variables\n\nConfig File\n\nHow It Works\n\nFiltering Pipeline\nUser prompt → Sent to AI model\nAI generates response → Initial content created\nGuardrails middleware intercepts:\nBad word filtering: Regex-based term replacement\nModel-based filtering: AI evaluates content safety\nFiltered response → Delivered to user\n\nBad Word Filtering\n\nSimple regex-based replacement:\nCase-insensitive matching\nReplaces with
|
|
3509
|
+
{"objectID":"540c47bd7c6e059a9673d6acb056728c913d14a87db9e96c85e9ad17847af52d","title":"Guardrails Middleware","url":"/docs/features/guardrails","content":"Guardrails Middleware\n\nSince: v7.42.0 | Status: Stable | Availability: SDK (CLI + SDK)\n\nOverview\n\nWhat it does: Guardrails middleware provides real-time content filtering and policy enforcement for AI model outputs, blocking profanity, PII, unsafe content, and custom-defined terms.\n\nWhy use it: Protect your application from generating harmful, inappropriate, or non-compliant content. Ensures AI responses meet safety standards and regulatory requirements.\n\nCommon use cases:\nContent moderation for user-facing applications\nPII (Personally Identifiable Information) redaction\nProfanity filtering for family-friendly apps\nCompliance with industry regulations (COPPA, GDPR, etc.)\nBrand safety and reputation management\n\nQuick Start\n\nGuardrails work out of the box with the security preset. No custom configuration required for basic content filtering.\n\nSDK Example with Security Preset\nEnables guardrails middleware with default configuration\nPass middleware on every call that should be filtered; the NeuroLink constructor does not take this option\nContent is already filtered - safe to display to users\n\nCustom Guardrails Configuration\nMaster switch for guardrails middleware\nEnable keyword-based filtering (fast, regex-based)\nCustom terms to filter/redact from outputs\nEnable AI-powered content safety check (slower, more accurate)\nUse fast, cheap model for safety evaluation\n\nCLI Usage\n\nConfiguration\n\n| Option | Type | Default | Required | Description |\n| ------------------------- | ---------- | ------- | -------- | ------------------------------------ |\n| enabled | boolean | true | No | Enable/disable guardrails middleware |\n| badWords.enabled | boolean | false | No | Enable keyword-based filtering |\n| badWords.list | string[] | [] | No | List of terms to filter/redact |\n| modelFilter.enabled | boolean | false | No | Enable AI-based content safety check |\n| modelFilter.filterModel | string | - | No | Model to use for safety evaluation |\n\nEnvironment Variables\n\nConfig File\n\nHow It Works\n\nFiltering Pipeline\nUser prompt → Sent to AI model\nAI generates response → Initial content created\nGuardrails middleware intercepts:\nBad word filtering: Regex-based term replacement\nModel-based filtering: AI evaluates content safety\nFiltered response → Delivered to user\n\nBad Word Filtering\n\nSimple regex-based replacement:\nCase-insensitive matching\nReplaces each match with a fixed string, [REDACTED] by default (not length-preserving asterisks) — override it with badWords.replacementText\nWorks in both generate and stream modes\n\nModel-Based Filtering\n\nWhile guardrails filter common PII patterns, always review critical outputs manually. False negatives can occur with obfuscated data or uncommon PII formats. For high-stakes compliance, combine with dedicated PII detection services.\n\nAI-powered safety check:\nUses separate, lightweight model (e.g., gpt-4o-mini)\nBinary safe/unsafe classification\nFull redaction on unsafe detection\n\nAdvanced Usage\n\nCombining with Other Middleware\n\nStreaming with Guardrails\n\nDynamic Guardrails\n\nAPI Reference\n\nMiddleware Configuration\npreset: \"security\" → Enables guardrails with defaults\npreset: \"all\" → Enables guardrails + all other middleware\nmiddlewareConfig.guardrails → Custom guardrails configuration\n\nSee guardrails-ai-integration.md for complete integration guide.\n\nTroubleshooting\n\nProblem: Guardrails not filtering content\n\nCause: Middleware not enabled or preset not configured\nSolution:\n\nProblem: Too many false positives (legitimate content filtered)\n\nCause: Overly aggressive bad word list\nSolution:\n\nProblem: Model-based filter is slow\n\nCause: Using large/expensive model for filtering\nSolution:\n\nProblem: Guardrails not working in streaming mode\n\nCause: Streaming guardrails only support bad word filtering (not model-based)\nSolution:\n\nBest Practices\n\nContent Filtering Strategy\nStart with presets - Use preset: \"security\" as baseline\nLayer protections - Combine bad words + model filtering\nUse lightweight filter models - gpt-4o-mini for speed\nTest thoroughly - Verify filtering doesn't break legitimate content\nMonitor and iterate - Track false positives/negatives\n\nBad Word List Curation\n\n✅ Do:\nInclude specific harmful terms\nUse exact phrases, not single characters\nRegularly update based on user reports\nConsider context-specific terms for your domain\n\n❌ Don't:\nAdd common English words (high false positive rate)\nInclude single letters or short words\nRely solely on bad words (use model filter too)\n\nPerformance Optimization\n\nCompliance Use Cases\n\nCOPPA (Children's Online Privacy)\n\nGDPR Data Protection\n\nRelated Features\nHITL Workflows - User approval for risky actions\nMiddleware Architecture - Custom middleware development\nAnalytics Integration - Track filtered content metrics\n\nMigration Notes\n\nIf upgrading from versions before v7.42.0:\nGuardrails are now enabled via middleware pres","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"","lvl3":""}},
|
|
3510
3510
|
{"objectID":"ad4c8c0e011c259d8f444afec90c94a3c939d9f14e65491e8044a8417430b54c","title":"Guardrails Middleware","url":"/docs/features/guardrails#guardrails-middleware","content":"Since: v7.42.0 | Status: Stable | Availability: SDK (CLI + SDK)","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Guardrails Middleware","lvl3":""}},
|
|
3511
3511
|
{"objectID":"1ecba9f0cdb3586cf8ad53bba31fb80cabab7aed2aba88050b4f98078dd2bec9","title":"Overview","url":"/docs/features/guardrails#overview","content":"What it does: Guardrails middleware provides real-time content filtering and policy enforcement for AI model outputs, blocking profanity, PII, unsafe content, and custom-defined terms.\n\nWhy use it: Protect your application from generating harmful, inappropriate, or non-compliant content. Ensures AI responses meet safety standards and regulatory requirements.\n\nCommon use cases:\nContent moderation for user-facing applications\nPII (Personally Identifiable Information) redaction\nProfanity filtering for family-friendly apps\nCompliance with industry regulations (COPPA, GDPR, etc.)\nBrand safety and reputation management","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Overview","lvl3":""}},
|
|
3512
3512
|
{"objectID":"064824951ceeb2f827852673ce43e1d5b0a4776cda59dec766413ea3ea1a41ae","title":"Quick Start","url":"/docs/features/guardrails#quick-start","content":"Guardrails work out of the box with the security preset. No custom configuration required for basic content filtering.","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Quick Start","lvl3":""}},
|
|
@@ -3519,7 +3519,7 @@
|
|
|
3519
3519
|
{"objectID":"2406e4412d40d6ab610c334f551ae73529304f50a559b6fdf180d616d7536174","title":"Environment Variables","url":"/docs/features/guardrails#environment-variables","content":"`bash","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Environment Variables","lvl3":""}},
|
|
3520
3520
|
{"objectID":"946b41af2f888ce1a40149ea8123d2c4584292d7a22fe88549f0b7c23671f951","title":"Or enable all middleware (includes guardrails + analytics)","url":"/docs/features/guardrails#or-enable-all-middleware-includes-guardrails-analytics","content":"`","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Or enable all middleware (includes guardrails + analytics)","lvl3":""}},
|
|
3521
3521
|
{"objectID":"70cbcd4ca56befe769c6ddb6128a5ab280c75a48edc8e9b4141dfce607bc2c1e","title":"Filtering Pipeline","url":"/docs/features/guardrails#filtering-pipeline","content":"User prompt → Sent to AI model\nAI generates response → Initial content created\nGuardrails middleware intercepts:\nBad word filtering: Regex-based term replacement\nModel-based filtering: AI evaluates content safety\nFiltered response → Delivered to user","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Filtering Pipeline","lvl3":""}},
|
|
3522
|
-
{"objectID":"3af7a22581a93723a5045560d7c0026a6fc3f1bca903dd47c28e0dfa5707e350","title":"Bad Word Filtering","url":"/docs/features/guardrails#bad-word-filtering","content":"Simple regex-based replacement:\nCase-insensitive matching\nReplaces with
|
|
3522
|
+
{"objectID":"3af7a22581a93723a5045560d7c0026a6fc3f1bca903dd47c28e0dfa5707e350","title":"Bad Word Filtering","url":"/docs/features/guardrails#bad-word-filtering","content":"Simple regex-based replacement:\nCase-insensitive matching\nReplaces each match with a fixed string, [REDACTED] by default (not length-preserving asterisks) — override it with badWords.replacementText\nWorks in both generate and stream modes","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Bad Word Filtering","lvl3":""}},
|
|
3523
3523
|
{"objectID":"5c5b50314493905262b204dbb73bacc7c6ab8a60fa3124469df9e6c1706e47a5","title":"Model-Based Filtering","url":"/docs/features/guardrails#model-based-filtering","content":"While guardrails filter common PII patterns, always review critical outputs manually. False negatives can occur with obfuscated data or uncommon PII formats. For high-stakes compliance, combine with dedicated PII detection services.\n\nAI-powered safety check:\nUses separate, lightweight model (e.g., gpt-4o-mini)\nBinary safe/unsafe classification\nFull redaction on unsafe detection","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Model-Based Filtering","lvl3":""}},
|
|
3524
3524
|
{"objectID":"dbfe7ff9f27039591c8f98fc3b03c705f22f7b36b689e5f0de95241ae3fb71ee","title":"Middleware Configuration","url":"/docs/features/guardrails#middleware-configuration","content":"preset: \"security\" → Enables guardrails with defaults\npreset: \"all\" → Enables guardrails + all other middleware\nmiddlewareConfig.guardrails → Custom guardrails configuration\n\nSee guardrails-ai-integration.md for complete integration guide.","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Middleware Configuration","lvl3":""}},
|
|
3525
3525
|
{"objectID":"85995a92035eb64e3e92878f16c818aa6b02432dfcdf8a2c1b7d0ec93efb0ceb","title":"Problem: Guardrails not filtering content","url":"/docs/features/guardrails#problem-guardrails-not-filtering-content","content":"Cause: Middleware not enabled or preset not configured\nSolution:","hierarchy":{"lvl0":"Features","lvl1":"Guardrails Middleware","lvl2":"Problem: Guardrails not filtering content","lvl3":""}},
|
|
@@ -9771,11 +9771,11 @@
|
|
|
9771
9771
|
{"objectID":"205e4e44d27692634aa5454565d9f060ceb88cdac97e7d37622bc5b9a1eefeb6","title":"Verification commands","url":"/docs/provider-integration/tiers/tier-1-aggregator-passthrough#verification-commands","content":"`bash","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 1 — Aggregator Passthrough","lvl2":"Verification commands","lvl3":""}},
|
|
9772
9772
|
{"objectID":"09ead22698863d776e82e2f0f3dfdd9a596f39cc106302a02c51a6ef37b436de","title":"LiteLLM example","url":"/docs/provider-integration/tiers/tier-1-aggregator-passthrough#litellm-example","content":"pnpm run cli generate \"hello\" --provider litellm --model","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 1 — Aggregator Passthrough","lvl2":"LiteLLM example","lvl3":""}},
|
|
9773
9773
|
{"objectID":"f46ff1668fbf30431a2b6578654212feb2043845eb7a28281e47075703948472","title":"OpenRouter example","url":"/docs/provider-integration/tiers/tier-1-aggregator-passthrough#openrouter-example","content":"pnpm run cli generate \"hello\" --provider openrouter --model /\n\n\nBoth should return a normal GenerateResult with non-empty content`. If\neither 400s with an \"unknown model\" style error, the aggregator doesn't\nactually serve that model yet — fix the aggregator-side config, not\nNeuroLink.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 1 — Aggregator Passthrough","lvl2":"OpenRouter example","lvl3":""}},
|
|
9774
|
-
{"objectID":"0c443abf0cfa1b31edc3337559bddbf37453d87732cfd17b08d461f55c77b195","title":"Tier 2 — Catalog Entry","url":"/docs/provider-integration/tiers/tier-2-catalog-entry","content":"Tier 2 — Catalog Entry\n\nWhen this applies: the vendor speaks the OpenAI /v1/chat/completions\nwire format (Bearer auth, standard SSE, standard JSON body) and needs\nzero behavioral overrides — no custom adjustRequestBody, no\nadjustResponseFormat, no nonstandard auth header, no adjustBodyAfter400.\nThis is the Groq/xAI/Together AI/Fireworks/Perplexity/Cloudflare/Mistral\nshape from before the redesign — now expressed as one JSON file instead of\na hand-written subclass (see ../adr/0002-catalog-over-subclass-default.md\nand the single-JSON spec at\ndocs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md).\n\nIf you're not sure whether your provider is quirk-free, start writing the\nJSON anyway — if it turns out you need a hook, migrate to Tier 3 instead of\nforcing the quirk into the catalog shape.\n\nFiles touched (end state)\n\n| # | File | Change |\n| --- | ------------------------------------- | ------------------------------- |\n| 1 | src/lib/providers/catalog/<id>.json | The entire integration, as data |\n\nThat is the whole list. Everything else is generated or derived:\npnpm run codegen:catalog writes the AIProviderName member, the\n <Name>Models enum and the NeurolinkCredentials key into marked\n regions, plus the generated catalog index. Pre-commit and CI fail on\n stale output, so it can't drift.\nThe runtime loader builds the registry entry, descriptor, config options,\n context windows, pricing, vision map and model choices from the JSON.\nThe test suites derive their spec rows, matrix rows and counts from the\n built catalog.\n\nScaffold it with:\n\nTier 2 emits exactly two files: a pre-filled <id>.json (with TODO markers\nwhere only a live probe can supply the truth) and a short checklist. The\nJSON deliberately fails schema validation until every TODO is replaced.\n\nCount pins — nothing to bump\n\nThere are none left. The wiring and descriptor suites compute their\nexpected totals from CATALOG_PROVIDER_IDS, and the matrix rows spread\nfrom the catalog with a completeness guard that throws if any catalog\nprovider is missing. Adding a provider changes no test file.\n\nsrc/lib/factories/providerRegistry.ts isn't in the table either:\n_doRegister() loops over the catalog and registers every entry\ngenerically.\n\nOne historical exception worth re-checking: commandFactory.ts's separate\nsetup [provider] subcommand hand-hardcoded its own provider-choices array.\nThat was migrated to derive from the enum (PR #1583) — confirm it still\ndoes before assuming you need a manual edit.\n\nThe JSON, field by field\n\nid, displayName, aliases, tier, then:\n\nwire — baseURL for the normal case. Env var names derive by\nconvention (<CONSTANT_CASE(id)>_API_KEY / _BASE_URL / _MODEL); set\nenvOverrides only for a vendor that breaks it. For a URL computed from\nanother credential (Cloudflare's account id) use baseURLTemplate plus\nexactly one extraCredentials entry.\n\nmodels — default, fallbacks, defaultContextWindow,\ndefaultMaxOutputTokens, and a catalog map of model id → {contextWindow?,\nmaxOutputTokens?, pricingPerMTok?, vision, status, description, enumMember?}.\nOmit a number rather than invent one. Optional refinements:\n\n| Field | Use it when
|
|
9774
|
+
{"objectID":"0c443abf0cfa1b31edc3337559bddbf37453d87732cfd17b08d461f55c77b195","title":"Tier 2 — Catalog Entry","url":"/docs/provider-integration/tiers/tier-2-catalog-entry","content":"Tier 2 — Catalog Entry\n\nWhen this applies: the vendor speaks the OpenAI /v1/chat/completions\nwire format (Bearer auth, standard SSE, standard JSON body) and needs\nzero behavioral overrides — no custom adjustRequestBody, no\nadjustResponseFormat, no nonstandard auth header, no adjustBodyAfter400.\nThis is the Groq/xAI/Together AI/Fireworks/Perplexity/Cloudflare/Mistral\nshape from before the redesign — now expressed as one JSON file instead of\na hand-written subclass (see ../adr/0002-catalog-over-subclass-default.md\nand the single-JSON spec at\ndocs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md).\n\nIf you're not sure whether your provider is quirk-free, start writing the\nJSON anyway — if it turns out you need a hook, migrate to Tier 3 instead of\nforcing the quirk into the catalog shape.\n\nFiles touched (end state)\n\n| # | File | Change |\n| --- | ------------------------------------- | ------------------------------- |\n| 1 | src/lib/providers/catalog/<id>.json | The entire integration, as data |\n\nThat is the whole list. Everything else is generated or derived:\npnpm run codegen:catalog writes the AIProviderName member, the\n <Name>Models enum and the NeurolinkCredentials key into marked\n regions, plus the generated catalog index. Pre-commit and CI fail on\n stale output, so it can't drift.\nThe runtime loader builds the registry entry, descriptor, config options,\n context windows, pricing, vision map and model choices from the JSON.\nThe test suites derive their spec rows, matrix rows and counts from the\n built catalog.\n\nScaffold it with:\n\nTier 2 emits exactly two files: a pre-filled <id>.json (with TODO markers\nwhere only a live probe can supply the truth) and a short checklist. The\nJSON deliberately fails schema validation until every TODO is replaced.\n\nCount pins — nothing to bump\n\nThere are none left. The wiring and descriptor suites compute their\nexpected totals from CATALOG_PROVIDER_IDS, and the matrix rows spread\nfrom the catalog with a completeness guard that throws if any catalog\nprovider is missing. Adding a provider changes no test file.\n\nsrc/lib/factories/providerRegistry.ts isn't in the table either:\n_doRegister() loops over the catalog and registers every entry\ngenerically.\n\nOne historical exception worth re-checking: commandFactory.ts's separate\nsetup [provider] subcommand hand-hardcoded its own provider-choices array.\nThat was migrated to derive from the enum (PR #1583) — confirm it still\ndoes before assuming you need a manual edit.\n\nThe JSON, field by field\n\nid, displayName, aliases, tier, then:\n\nwire — baseURL for the normal case. Env var names derive by\nconvention (<CONSTANT_CASE(id)>_API_KEY / _BASE_URL / _MODEL); set\nenvOverrides only for a vendor that breaks it. For a URL computed from\nanother credential (Cloudflare's account id) use baseURLTemplate plus\nexactly one extraCredentials entry.\n\nmodels — default, fallbacks, defaultContextWindow,\ndefaultMaxOutputTokens, and a catalog map of model id → {contextWindow?,\nmaxOutputTokens?, pricingPerMTok?, vision, tools?, status, description, enumMember?}.\nOmit a number rather than invent one. Optional refinements:\n\n| Field | Use it when |\n| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| enumMember | The derived constant-case name would break an existing export |\n| enumTypeName | The <Name>Models enum name must differ from the derived one |\n| fallbackModelName | The legacy fallback differs from fallbacks[1] ?? fallbacks[0] |\n| registryDefaultModel | The registry default differs from default |\n| topModels | The CLI picker should show a curated ordered subset |\n| visionModel | Vision tests need a specific model (the default is text-only) |\n| testModel | The catalog default is retired/gated on the testing account |\n| tools (per model) | capabilities.tools is \"model-dependent\" and the vendor's own docs say which served models actually accept tool definitions (Reka: only reka-flash) |\n\ntestModel is matrix-only","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 2 — Catalog Entry","lvl2":"","lvl3":""}},
|
|
9775
9775
|
{"objectID":"4b278bfa53040dfc60deaffd7c0042488d914cc4eff89ded532f5582eceadce6","title":"Tier 2 — Catalog Entry","url":"/docs/provider-integration/tiers/tier-2-catalog-entry#tier-2-catalog-entry","content":"When this applies: the vendor speaks the OpenAI /v1/chat/completions\nwire format (Bearer auth, standard SSE, standard JSON body) and needs\nzero behavioral overrides — no custom adjustRequestBody, no\nadjustResponseFormat, no nonstandard auth header, no adjustBodyAfter400.\nThis is the Groq/xAI/Together AI/Fireworks/Perplexity/Cloudflare/Mistral\nshape from before the redesign — now expressed as one JSON file instead of\na hand-written subclass (see ../adr/0002-catalog-over-subclass-default.md\nand the single-JSON spec at\ndocs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md).\n\nIf you're not sure whether your provider is quirk-free, start writing the\nJSON anyway — if it turns out you need a hook, migrate to Tier 3 instead of\nforcing the quirk into the catalog shape.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 2 — Catalog Entry","lvl2":"Tier 2 — Catalog Entry","lvl3":""}},
|
|
9776
9776
|
{"objectID":"1bb614eb5848cace52afb691aa99aeab78366a84a216f758ef9df6c86e49c0cc","title":"Files touched (end state)","url":"/docs/provider-integration/tiers/tier-2-catalog-entry#files-touched-end-state","content":"| # | File | Change |\n| --- | ------------------------------------- | ------------------------------- |\n| 1 | src/lib/providers/catalog/<id>.json | The entire integration, as data |\n\nThat is the whole list. Everything else is generated or derived:\npnpm run codegen:catalog writes the AIProviderName member, the\n <Name>Models enum and the NeurolinkCredentials key into marked\n regions, plus the generated catalog index. Pre-commit and CI fail on\n stale output, so it can't drift.\nThe runtime loader builds the registry entry, descriptor, config options,\n context windows, pricing, vision map and model choices from the JSON.\nThe test suites derive their spec rows, matrix rows and counts from the\n built catalog.\n\nScaffold it with:\n\nTier 2 emits exactly two files: a pre-filled <id>.json (with TODO markers\nwhere only a live probe can supply the truth) and a short checklist. The\nJSON deliberately fails schema validation until every TODO is replaced.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 2 — Catalog Entry","lvl2":"Files touched (end state)","lvl3":""}},
|
|
9777
9777
|
{"objectID":"9627a6b63ab505017fbc3edd7f9ec312f548b35aef74edd6e2be5eac8e1ade0f","title":"Count pins — nothing to bump","url":"/docs/provider-integration/tiers/tier-2-catalog-entry#count-pins-nothing-to-bump","content":"There are none left. The wiring and descriptor suites compute their\nexpected totals from CATALOG_PROVIDER_IDS, and the matrix rows spread\nfrom the catalog with a completeness guard that throws if any catalog\nprovider is missing. Adding a provider changes no test file.\n\nsrc/lib/factories/providerRegistry.ts isn't in the table either:\n_doRegister() loops over the catalog and registers every entry\ngenerically.\n\nOne historical exception worth re-checking: commandFactory.ts's separate\nsetup [provider] subcommand hand-hardcoded its own provider-choices array.\nThat was migrated to derive from the enum (PR #1583) — confirm it still\ndoes before assuming you need a manual edit.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 2 — Catalog Entry","lvl2":"Count pins — nothing to bump","lvl3":""}},
|
|
9778
|
-
{"objectID":"672b4a181677219d0db0d64d290a3f1a268691c336f02fe776a01d94d0684ae5","title":"The JSON, field by field","url":"/docs/provider-integration/tiers/tier-2-catalog-entry#the-json-field-by-field","content":"id, displayName, aliases, tier, then:\n\nwire — baseURL for the normal case. Env var names derive by\nconvention (<CONSTANT_CASE(id)>_API_KEY / _BASE_URL / _MODEL); set\nenvOverrides only for a vendor that breaks it. For a URL computed from\nanother credential (Cloudflare's account id) use baseURLTemplate plus\nexactly one extraCredentials entry.\n\nmodels — default, fallbacks, defaultContextWindow,\ndefaultMaxOutputTokens, and a catalog map of model id → {contextWindow?,\nmaxOutputTokens?, pricingPerMTok?, vision, status, description, enumMember?}.\nOmit a number rather than invent one. Optional refinements:\n\n| Field | Use it when
|
|
9778
|
+
{"objectID":"672b4a181677219d0db0d64d290a3f1a268691c336f02fe776a01d94d0684ae5","title":"The JSON, field by field","url":"/docs/provider-integration/tiers/tier-2-catalog-entry#the-json-field-by-field","content":"id, displayName, aliases, tier, then:\n\nwire — baseURL for the normal case. Env var names derive by\nconvention (<CONSTANT_CASE(id)>_API_KEY / _BASE_URL / _MODEL); set\nenvOverrides only for a vendor that breaks it. For a URL computed from\nanother credential (Cloudflare's account id) use baseURLTemplate plus\nexactly one extraCredentials entry.\n\nmodels — default, fallbacks, defaultContextWindow,\ndefaultMaxOutputTokens, and a catalog map of model id → {contextWindow?,\nmaxOutputTokens?, pricingPerMTok?, vision, tools?, status, description, enumMember?}.\nOmit a number rather than invent one. Optional refinements:\n\n| Field | Use it when |\n| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| enumMember | The derived constant-case name would break an existing export |\n| enumTypeName | The <Name>Models enum name must differ from the derived one |\n| fallbackModelName | The legacy fallback differs from fallbacks[1] ??","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 2 — Catalog Entry","lvl2":"The JSON, field by field","lvl3":""}},
|
|
9779
9779
|
{"objectID":"5f38f36d8546533723645d1643ea69418d7e5cbe47cde5d18b5ad998d053e476","title":"Live verification","url":"/docs/provider-integration/tiers/tier-2-catalog-entry#live-verification","content":"The mocked gates prove the wire contract, not the commercial reality.\nEach of these caught a real defect on the cerebras pilot:\nRoster probe first — authenticated GET <baseURL>/models. Pick\n default, fallbacks and catalog keys from what the API serves TODAY.\n Vendor docs listed four cerebras models; the live roster had two, and\n the documented default 404'd (finding #7). This ages: both Groq's and\n Fireworks' catalog defaults went dead within weeks.\nBilling policy — confirm how a working key is obtained. Cerebras has\n no keyless free tier: even the \"$5 free credits\" require saving a payment\n card (finding #8); SambaNova requires payment outright (finding #11).\nCapability probes — probe tools + response_format in one request\n before setting structuredOutputWithTools; strict backends 400. Don't\n copy another provider's flags on vibes.\nLive matrix — with a working key:\n npx tsx test/continuous-test-suite-provider-matrix.ts --provider=<id>\n must pass generate, stream, tool calling and structured output, and a\n bare node dist/cli/index.js generate \"...\" --provider <id> must resolve\n the default model. The pilot's first live run was 2/4 and surfaced an\n SDK-wide bug (tool_choice emitted on tools-less requests — fixed in\n #1564, now pinned by the mocked suite), which is why this step exists.\n\nRecord the outcome in evidence.liveMatrix.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 2 — Catalog Entry","lvl2":"Live verification","lvl3":""}},
|
|
9780
9780
|
{"objectID":"bea00545b1053aa393e34f487097636d2ee23cfdc652c6724dc6029192017ffd","title":"Verification commands","url":"/docs/provider-integration/tiers/tier-2-catalog-entry#verification-commands","content":"All must exit 0 before opening the PR. The first three test commands run in\nthe provider-safety-net CI job (.github/workflows/ci.yml) — zero-API,\nzero-credential checks, so there's no reason to skip them locally. Add a\ncase to test:error-classifier-contract first if your entry sets\ntimeoutErrorClass or vendor-specific errorRules.\n\nBecause the suites derive from data, a new provider needs no new assertions\n— but if you ever do add one, run the break-one-assertion ritual: flip it,\nconfirm the suite reports ✗ and exits non-zero (not ⊘ skip — see the\nassertion-message hazard in CLAUDE.md), then restore it.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 2 — Catalog Entry","lvl2":"Verification commands","lvl3":""}},
|
|
9781
9781
|
{"objectID":"3f8e5102409b953258a82548fec14a7726774f6e1e5c3c7d826400ef24ebf105","title":"Tier 3 — Adapter-Based Native","url":"/docs/provider-integration/tiers/tier-3-adapter-native","content":"Tier 3 — Adapter-Based Native\n\nWhen this applies: the vendor has its own SDK or wire format that\nisn't OpenAI-compatible, but it's still a normal request/response (or\nrequest/SSE-stream) HTTP+JSON lifecycle you can drive from a provider\nclass. This is the Anthropic/Google AI Studio shape — a dedicated\nsrc/lib/providers/<name>.ts extending BaseProvider directly, not the\nOpenAIChatCompletionsProvider family.\n\nCorrected from the original plan text (2026-08-18): the plan's\ndraft cited \"the Mistral/Cohere/Ollama shape\" as the Tier 3 example.\nThat's stale — mistral.ts, cohere.ts, and ollama/client.ts all\nextend OpenAIChatCompletionsProvider, the Tier 2 family, not\nBaseProvider directly. (Mistral is separately already named in\n../adr/0002-catalog-over-subclass-default.md as a Tier 2\ncatalog-migration candidate — the original draft was internally\ninconsistent about which tier Mistral belongs to.) The verified,\ncurrently-shipping examples of a chat/text provider extending\nBaseProvider directly are Anthropic\n(src/lib/providers/anthropic/client.ts) and Google AI Studio\n(src/lib/providers/googleAiStudio/client.ts) — used below.\nWhy these two, specifically: they implement the request/response and\nstreaming lifecycle against their vendor's own wire format directly,\ninside the provider class itself — they don't inherit that lifecycle\nfrom OpenAIChatCompletionsProvider's shared chat-completions\nimplementation the way Mistral/Cohere/Ollama do. That's the actual line\nbetween Tier 2 and Tier 3: not \"does the vendor have a custom SDK\" but\n\"does this class implement the provider surface itself, or inherit it.\"\nWhen you compare your new provider's shape against Anthropic/Google AI\nStudio, that's the property you're matching — not their specific\nrequest/response format, which is vendor-idiosyncratic and won't look\nlike yours.\n\nAs of 2026-08-18 there is no shared streaming-loop adapter beyond\nBaseProvider and OpenAIChatCompletionsProvider (checked\nsrc/lib/providers/ for a nativeAdapter*.ts or similar — none exists).\nIf one lands later, extend it instead of hand-rolling the SSE parser and\nmulti-step tool loop; the steps below describe the always-true minimum\nregardless of whether that shared adapter exists yet.\n\nFiles touched (end state)\n\n| # | File | Change |\n| --- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 1 | src/lib/constants/enums.ts | New AIProviderName member + a <Name>Models enum (default + fallback model ids — Tier 3 providers keep an explicit model catalog since there's no OPENAI_COMPAT_CATALOG row to hold defaultModel/fallbackModels) |\n| 2 | src/lib/providers/<name>.ts | NEW provider class extending BaseProvider (or a shared adapter, if one has landed by the time you read this) |\n| 3 | src/lib/factories/providerDescriptors.ts | One ProviderDescriptor entry |\n| 4 | src/lib/factories/providerRegistry.ts | One ProviderFactory.registerProvider() block, dynamic import, 5-argument call including the descriptor argument from PROVIDER_DESCRIPTORS_BY_NAME |\n| 5 | src/lib/types/providers.ts | New NeurolinkCredentials[\"<key>\"] slice |\n| 6 | src/lib/adapters/providerImageAdapter.ts | VISION_CAPABILITIES entry — only if the provider/model is multimodal |\n| 7 | test/continuous-test-suite-providers-mocked.ts | Mocked-contract section ","hierarchy":{"lvl0":"Provider Integration","lvl1":"Tier 3 — Adapter-Based Native","lvl2":"","lvl3":""}},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.49.
|
|
3
|
+
"version": "12.49.12",
|
|
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": {
|
|
@@ -537,7 +537,7 @@
|
|
|
537
537
|
"livekit-server-sdk": "^2.15.4",
|
|
538
538
|
"mammoth": "1.12.0",
|
|
539
539
|
"mediabunny": "^1.40.1",
|
|
540
|
-
"music-metadata": "^11.
|
|
540
|
+
"music-metadata": "^11.16.1",
|
|
541
541
|
"pdf-parse": "^2.4.5",
|
|
542
542
|
"pptxgenjs": "^4.0.1",
|
|
543
543
|
"sharp": "^0.35.3"
|